diff options
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c')
| -rw-r--r-- | Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c | 236 |
1 files changed, 148 insertions, 88 deletions
diff --git a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c index cd22c851..71afa212 100644 --- a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c +++ b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_smime.c @@ -64,21 +64,14 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); + PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { - PKCS7 *p7 = NULL; - PKCS7_SIGNER_INFO *si; - BIO *p7bio = NULL; - STACK_OF(X509_ALGOR) *smcap = NULL; + PKCS7 *p7; int i; - if (!X509_check_private_key(signcert, pkey)) { - PKCS7err(PKCS7_F_PKCS7_SIGN, - PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); - return NULL; - } - if (!(p7 = PKCS7_new())) { PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE); return NULL; @@ -90,88 +83,167 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, if (!PKCS7_content_new(p7, NID_pkcs7_data)) goto err; -#if defined(OPENSSL_SYS_UEFI) - /* - * NOTE: Update to SHA-256 digest algorithm for UEFI version. - */ - if (!(si = PKCS7_add_signature(p7, signcert, pkey, EVP_sha256()))) { -#else - if (!(si = PKCS7_add_signature(p7, signcert, pkey, EVP_sha1()))) { -#endif - PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); + if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) { + PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); goto err; } if (!(flags & PKCS7_NOCERTS)) { + for (i = 0; i < sk_X509_num(certs); i++) { + if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i))) + goto err; + } + } + + if (flags & PKCS7_DETACHED) + PKCS7_set_detached(p7, 1); + + if (flags & (PKCS7_STREAM | PKCS7_PARTIAL)) + return p7; + + if (PKCS7_final(p7, data, flags)) + return p7; + + err: + PKCS7_free(p7); + return NULL; +} + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags) +{ + BIO *p7bio; + int ret = 0; + if (!(p7bio = PKCS7_dataInit(p7, NULL))) { + PKCS7err(PKCS7_F_PKCS7_FINAL, ERR_R_MALLOC_FAILURE); + return 0; + } + + SMIME_crlf_copy(data, p7bio, flags); + + (void)BIO_flush(p7bio); + + if (!PKCS7_dataFinal(p7, p7bio)) { + PKCS7err(PKCS7_F_PKCS7_FINAL, PKCS7_R_PKCS7_DATASIGN); + goto err; + } + + ret = 1; + + err: + BIO_free_all(p7bio); + + return ret; + +} + +/* Check to see if a cipher exists and if so add S/MIME capabilities */ + +static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) +{ + if (EVP_get_cipherbynid(nid)) + return PKCS7_simple_smimecap(sk, nid, arg); + return 1; +} + +static int add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) +{ + if (EVP_get_digestbynid(nid)) + return PKCS7_simple_smimecap(sk, nid, arg); + return 1; +} + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, + EVP_PKEY *pkey, const EVP_MD *md, + int flags) +{ + PKCS7_SIGNER_INFO *si = NULL; + STACK_OF(X509_ALGOR) *smcap = NULL; + if (!X509_check_private_key(signcert, pkey)) { + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, + PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + + if (!(si = PKCS7_add_signature(p7, signcert, pkey, md))) { + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, + PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); + return NULL; + } + + if (!(flags & PKCS7_NOCERTS)) { if (!PKCS7_add_certificate(p7, signcert)) goto err; - if (certs) - for (i = 0; i < sk_X509_num(certs); i++) - if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i))) - goto err; } if (!(flags & PKCS7_NOATTR)) { - if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, - V_ASN1_OBJECT, - OBJ_nid2obj(NID_pkcs7_data))) + if (!PKCS7_add_attrib_content_type(si, NULL)) goto err; /* Add SMIMECapabilities */ if (!(flags & PKCS7_NOSMIMECAP)) { if (!(smcap = sk_X509_ALGOR_new_null())) { - PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE); + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, ERR_R_MALLOC_FAILURE); goto err; } -#ifndef OPENSSL_NO_DES - if (!PKCS7_simple_smimecap(smcap, NID_des_ede3_cbc, -1)) - goto err; -#endif -#ifndef OPENSSL_NO_RC2 - if (!PKCS7_simple_smimecap(smcap, NID_rc2_cbc, 128)) - goto err; - if (!PKCS7_simple_smimecap(smcap, NID_rc2_cbc, 64)) - goto err; -#endif -#ifndef OPENSSL_NO_DES - if (!PKCS7_simple_smimecap(smcap, NID_des_cbc, -1)) - goto err; -#endif -#ifndef OPENSSL_NO_RC2 - if (!PKCS7_simple_smimecap(smcap, NID_rc2_cbc, 40)) - goto err; -#endif - if (!PKCS7_add_attrib_smimecap(si, smcap)) + if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1) + || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1) + || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) + || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1) + || !add_cipher_smcap(smcap, NID_aes_128_cbc, -1) + || !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 128) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 64) + || !add_cipher_smcap(smcap, NID_des_cbc, -1) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 40) + || !PKCS7_add_attrib_smimecap(si, smcap)) goto err; sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); smcap = NULL; } + if (flags & PKCS7_REUSE_DIGEST) { + if (!pkcs7_copy_existing_digest(p7, si)) + goto err; + if (!(flags & PKCS7_PARTIAL) && !PKCS7_SIGNER_INFO_sign(si)) + goto err; + } } + return si; + err: + if (smcap) + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + return NULL; +} - if (flags & PKCS7_DETACHED) - PKCS7_set_detached(p7, 1); +/* + * Search for a digest matching SignerInfo digest type and if found copy + * across. + */ - if (flags & PKCS7_STREAM) - return p7; +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) +{ + int i; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *sitmp; + ASN1_OCTET_STRING *osdig = NULL; + sinfos = PKCS7_get_signer_info(p7); + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + if (si == sitmp) + break; + if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0) + continue; + if (!OBJ_cmp(si->digest_alg->algorithm, sitmp->digest_alg->algorithm)) { + osdig = PKCS7_digest_from_attributes(sitmp->auth_attr); + break; + } - if (!(p7bio = PKCS7_dataInit(p7, NULL))) { - PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE); - goto err; } - SMIME_crlf_copy(data, p7bio, flags); + if (osdig) + return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); - if (!PKCS7_dataFinal(p7, p7bio)) { - PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_DATASIGN); - goto err; - } - - BIO_free_all(p7bio); - return p7; - err: - sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); - BIO_free_all(p7bio); - PKCS7_free(p7); - return NULL; + PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, + PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); + return 0; } int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, @@ -295,14 +367,13 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, tmpout = out; bufsiz = 4096; - buf = OPENSSL_malloc (bufsiz); + buf = OPENSSL_malloc(bufsiz); if (buf == NULL) { - goto err; + goto err; } - /* We now have to 'read' from p7bio to calculate digests etc. */ for (;;) { - i = BIO_read(p7bio, buf, sizeof(buf)); + i = BIO_read(p7bio, buf, bufsiz); if (i <= 0) break; if (tmpout) @@ -343,7 +414,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, sk_X509_free(signers); if (buf != NULL) { - OPENSSL_free (buf); + OPENSSL_free(buf); } return ret; @@ -375,7 +446,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) { PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_NO_SIGNERS); - return NULL; + return 0; } if (!(signers = sk_X509_new_null())) { @@ -400,7 +471,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); sk_X509_free(signers); - return NULL; + return 0; } if (!sk_X509_push(signers, signer)) { @@ -440,22 +511,11 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, } } - if (!(p7bio = PKCS7_dataInit(p7, NULL))) { - PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE); - goto err; - } - - SMIME_crlf_copy(in, p7bio, flags); - - (void)BIO_flush(p7bio); - - if (!PKCS7_dataFinal(p7, p7bio)) { - PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_PKCS7_DATAFINAL_ERROR); - goto err; - } - BIO_free_all(p7bio); + if (flags & PKCS7_STREAM) + return p7; - return p7; + if (PKCS7_final(p7, in, flags)) + return p7; err: |
