2 * Copyright (C) 2018 Opengear
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #if defined(HAVE_CONFIG_H)
29 #include <sys/types.h>
32 #include <file/file.h>
33 #include <talloc/talloc.h>
35 #include <util/util.h>
36 #include <i18n/i18n.h>
38 #include <openssl/conf.h>
39 #include <openssl/bio.h>
40 #include <openssl/pem.h>
41 #include <openssl/rsa.h>
42 #include <openssl/evp.h>
43 #include <openssl/err.h>
44 #include <openssl/cms.h>
45 #include <openssl/pkcs12.h>
49 static const EVP_MD *s_verify_md = NULL;
51 static __attribute__((constructor)) void crypto_init(void)
53 #if OPENSSL_VERSION_NUMBER < 0x10100000L
55 OpenSSL_add_all_algorithms();
56 ERR_load_crypto_strings();
57 ERR_load_CMS_strings();
60 s_verify_md = EVP_get_digestbyname(VERIFY_DIGEST);
62 pb_log("Specified OpenSSL digest '%s' not found\n", VERIFY_DIGEST);
66 #if OPENSSL_VERSION_NUMBER < 0x10100000L
67 static __attribute__((destructor)) void crypto_fini(void)
74 static int pb_log_print_errors_cb(const char *str,
75 size_t len __attribute__((unused)),
76 void *u __attribute__((unused)))
82 static int get_pkcs12(FILE *keyfile, X509 **cert, EVP_PKEY **priv)
89 p12 = d2i_PKCS12_fp(keyfile, NULL);
92 * annoying but NULL and "" are two valid but different
95 if (!PKCS12_parse(p12, NULL, priv, cert, NULL) &&
96 !PKCS12_parse(p12, "", priv, cert, NULL)) {
97 pb_log("%s: Error parsing OpenSSL PKCS12:\n", __func__);
98 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
108 static X509 *get_cert(FILE *keyfile)
110 EVP_PKEY *priv = NULL;
113 if (get_pkcs12(keyfile, &cert, &priv)) {
118 cert = PEM_read_X509(keyfile, NULL, NULL, NULL);
124 static STACK_OF(X509) *get_cert_stack(FILE *keyfile)
126 STACK_OF(X509) *certs = sk_X509_new_null();
130 cert = get_cert(keyfile);
132 sk_X509_push(certs, get_cert(keyfile));
134 pb_log("%s: Error allocating OpenSSL X509 stack:\n", __func__);
135 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
142 static EVP_PKEY *get_public_key(FILE *keyfile)
144 EVP_PKEY *pkey = NULL;
148 * walk through supported file types looking for a public key:
151 * 2. PEM encoded X509
152 * 3. PEM encoded raw public key
154 * someday in the future maybe utilize the keyring_path
155 * as an input for X509_STORE_load_locations for certificate
159 cert = get_cert(keyfile);
161 pkey = X509_get_pubkey(cert);
166 pkey = PEM_read_PUBKEY(keyfile, NULL, NULL, NULL);
169 /* handles both cases */
171 pb_log("%s: Error loading OpenSSL public key:\n", __func__);
172 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
178 int decrypt_file(const char *filename,
179 FILE *authorized_signatures_handle,
180 const char *keyring_path __attribute__((unused)))
182 BIO *content_bio = NULL, *file_bio = NULL, *out_bio = NULL;
183 STACK_OF(X509) *certs = NULL;
184 CMS_ContentInfo *cms = NULL;
185 EVP_PKEY *priv = NULL;
192 if (!get_pkcs12(authorized_signatures_handle, &cert, &priv)) {
193 pb_log("%s: Error opening OpenSSL decrypt authorization file:\n",
195 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
199 file_bio = BIO_new_file(filename, "r");
201 pb_log("%s: Error opening OpenSSL decrypt cipher file '%s':\n",
203 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
207 out_bio = BIO_new(BIO_s_mem());
209 pb_log("%s: Error allocating OpenSSL decrypt output buffer:\n",
211 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
215 /* right now only support signed-envelope CMS */
217 cms = SMIME_read_CMS(file_bio, &content_bio);
219 pb_log("%s: Error parsing OpenSSL CMS decrypt '%s'\n",
221 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
225 BIO_free(content_bio);
226 content_bio = BIO_new(BIO_s_mem());
228 pb_log("%s: Error allocating OpenSSL decrypt content buffer:\n",
230 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
234 if (!CMS_decrypt(cms, priv, cert, NULL, out_bio, 0)) {
235 pb_log("%s: Error in OpenSSL CMS decrypt '%s'\n",
237 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
241 certs = sk_X509_new_null();
243 pb_log("%s: Error allocating OpenSSL X509 stack:\n", __func__);
244 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
248 sk_X509_push(certs, cert);
250 CMS_ContentInfo_free(cms);
252 cms = SMIME_read_CMS(out_bio, &content_bio);
254 pb_log("%s: Error parsing OpenSSL CMS decrypt verify:\n",
256 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
260 /* this is a mem BIO so failure is 0 or -1 */
261 if (BIO_reset(out_bio) < 1) {
262 pb_log("%s: Error resetting OpenSSL decrypt output buffer:\n",
264 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
268 /* in this mode its attached content */
269 if (!CMS_verify(cms, certs, NULL, content_bio, out_bio,
270 CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY)) {
271 pb_log("%s: Failed OpenSSL CMS decrypt verify:\n", __func__);
272 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
276 /* reopen the file so we force a truncation */
278 file_bio = BIO_new_file(filename, "w");
280 pb_log("%s: Error opening OpenSSL decrypt output file '%s'\n",
282 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
286 outl = BIO_get_mem_data(out_bio, &outptr);
289 bytes = BIO_write(file_bio, outptr, outl);
294 } else if (bytes < 0) {
295 pb_log("%s: OpenSSL decrypt output write failure on file '%s':\n",
297 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
307 CMS_ContentInfo_free(cms);
309 BIO_free(content_bio);
317 int verify_file_signature(const char *plaintext_filename,
318 const char *signature_filename,
319 FILE *authorized_signatures_handle,
320 const char *keyring_path __attribute__((unused)))
322 BIO *signature_bio = NULL, *plaintext_bio = NULL, *content_bio = NULL;
323 STACK_OF(X509) *certs = NULL;
324 CMS_ContentInfo *cms = NULL;
325 ssize_t bytes_read = -1;
326 EVP_MD_CTX *ctx = NULL;
327 EVP_PKEY *pkey = NULL;
333 plaintext_bio = BIO_new_file(plaintext_filename, "r");
334 if (!plaintext_bio) {
335 pb_log("%s: Error opening OpenSSL verify plaintext file '%s'\n",
336 __func__, plaintext_filename);
337 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
341 signature_bio = BIO_new_file(signature_filename, "r");
342 if (!signature_bio) {
343 pb_log("%s: Error opening OpenSSL verify signature file '%s'\n",
344 __func__, signature_filename);
345 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
349 /* first check CMS */
350 cms = SMIME_read_CMS(signature_bio, &content_bio);
352 certs = get_cert_stack(authorized_signatures_handle);
355 * this has to always be detached, which means we always
356 * ignore content_bio and we have to set the NO_SIGNER_CERT_VERIFY
357 * until such time we implement the keyring_path as a X509_STORE
360 if (!CMS_verify(cms, certs, NULL, plaintext_bio, NULL,
361 CMS_DETACHED | CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY)) {
362 pb_log("%s: Failed OpenSSL CMS verify:\n", __func__);
363 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
371 /* for explicit dgst mode we need an explicit md defined */
375 ctx = EVP_MD_CTX_create();
378 pb_log("%s: Error allocating OpenSSL MD ctx:\n", __func__);
379 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
383 pkey = get_public_key(authorized_signatures_handle);
387 if (EVP_DigestVerifyInit(ctx, NULL, s_verify_md, NULL, pkey) < 1) {
388 pb_log("%s: Error initializing OpenSSL verify:\n", __func__);
389 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
394 bytes_read = BIO_read(plaintext_bio, rdbuf, 8192);
395 if (bytes_read > 0) {
396 if (EVP_DigestVerifyUpdate(ctx, rdbuf, (size_t)(bytes_read)) < 1) {
397 pb_log("%s: OpenSSL digest update failure on file '%s':\n",
398 __func__, plaintext_filename);
399 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
402 } else if (bytes_read < 0) {
403 pb_log("%s: OpenSSL read failure on file '%s':\n",
404 __func__, plaintext_filename);
405 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
411 * can't do signature buffer as an update so have to read in whole file
412 * would be handy if there was some sort of BIO_read_all but there
413 * doesn't seem to be so rather than reinvent the wheel close it and
414 * use the existing support
416 BIO_free(signature_bio);
417 signature_bio = NULL;
419 if (read_file(NULL, signature_filename, &sigbuf, &siglen)) {
420 pb_log("%s: Error reading OpenSSL signature file '%s'\n",
421 __func__, signature_filename);
425 if (EVP_DigestVerifyFinal(ctx, (unsigned char*)sigbuf, siglen))
428 pb_log("%s: Error finalizing OpenSSL verify:\n", __func__);
429 ERR_print_errors_cb(&pb_log_print_errors_cb, NULL);
435 CMS_ContentInfo_free(cms);
438 BIO_free(plaintext_bio);
439 BIO_free(signature_bio);
440 BIO_free(content_bio);
442 EVP_MD_CTX_destroy(ctx);
446 int lockdown_status(void)
449 * if it's a PKCS12 then we're in decrypt mode since we have the
450 * private key, otherwise it's sign mode
452 * someday add in support for runtime determination based on what
453 * files come back in the async sig file load?
455 FILE *authorized_signatures_handle = NULL;
456 int ret = PB_LOCKDOWN_SIGN;
459 #if !defined(HARD_LOCKDOWN)
460 if (access(LOCKDOWN_FILE, F_OK) == -1)
461 return PB_LOCKDOWN_NONE;
464 /* determine lockdown type */
466 authorized_signatures_handle = fopen(LOCKDOWN_FILE, "r");
467 if (authorized_signatures_handle) {
468 p12 = d2i_PKCS12_fp(authorized_signatures_handle, NULL);
470 ret = PB_LOCKDOWN_DECRYPT;
473 fclose(authorized_signatures_handle);