diff --git a/crypto/err/pkcs7.errordata b/crypto/err/pkcs7.errordata index 7080bd948c..8469c8ef52 100644 --- a/crypto/err/pkcs7.errordata +++ b/crypto/err/pkcs7.errordata @@ -1,4 +1,35 @@ PKCS7,100,BAD_PKCS7_VERSION +PKCS7,113,CERTIFICATE_VERIFY_ERROR +PKCS7,134,CERT_MUST_BE_RSA +PKCS7,123,CIPHER_HAS_NO_OBJECT_IDENTIFIER +PKCS7,106,CIPHER_NOT_INITIALIZED +PKCS7,111,CONTENT_AND_DATA_PRESENT +PKCS7,121,DECRYPT_ERROR +PKCS7,129,DIGEST_FAILURE +PKCS7,119,ERROR_ADDING_RECIPIENT +PKCS7,118,ERROR_SETTING_CIPHER +PKCS7,104,INVALID_NULL_POINTER +PKCS7,126,INVALID_SIGNED_DATA_TYPE PKCS7,101,NOT_PKCS7_SIGNED_DATA PKCS7,102,NO_CERTIFICATES_INCLUDED +PKCS7,105,NO_CONTENT PKCS7,103,NO_CRLS_INCLUDED +PKCS7,133,NO_DEFAULT_DIGEST +PKCS7,128,NO_RECIPIENT_MATCHES_CERTIFICATE +PKCS7,112,NO_SIGNATURES_ON_DATA +PKCS7,116,NO_SIGNERS +PKCS7,132,PKCS7_ADD_SIGNATURE_ERROR +PKCS7,131,PKCS7_ADD_SIGNER_ERROR +PKCS7,122,PKCS7_DATASIGN +PKCS7,120,PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE +PKCS7,115,SIGNATURE_FAILURE +PKCS7,117,SIGNER_CERTIFICATE_NOT_FOUND +PKCS7,124,SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE +PKCS7,114,SMIME_TEXT_ERROR +PKCS7,109,UNABLE_TO_FIND_MEM_BIO +PKCS7,108,UNABLE_TO_FIND_MESSAGE_DIGEST +PKCS7,125,UNKNOWN_DIGEST_TYPE +PKCS7,127,UNSUPPORTED_CIPHER_TYPE +PKCS7,107,UNSUPPORTED_CONTENT_TYPE +PKCS7,110,WRONG_CONTENT_TYPE +PKCS7,130,WRONG_PKCS7_TYPE diff --git a/crypto/pkcs7/bio/bio_cipher_test.cc b/crypto/pkcs7/bio/bio_cipher_test.cc index c05ffcf04c..3cb91b3a2e 100644 --- a/crypto/pkcs7/bio/bio_cipher_test.cc +++ b/crypto/pkcs7/bio/bio_cipher_test.cc @@ -26,6 +26,7 @@ static const struct CipherParams Ciphers[] = { {"AES_256_CTR", EVP_aes_256_ctr}, {"AES_256_OFB", EVP_aes_256_ofb}, {"ChaCha20Poly1305", EVP_chacha20_poly1305}, + {"DES_EDE3_CBC", EVP_des_ede3_cbc}, }; class BIOCipherTest : public testing::TestWithParam {}; @@ -65,6 +66,7 @@ TEST_P(BIOCipherTest, Basic) { EXPECT_FALSE(BIO_ctrl(bio_cipher.get(), BIO_C_GET_CIPHER_CTX, 0, NULL)); EXPECT_FALSE(BIO_ctrl(bio_cipher.get(), BIO_C_SSL_MODE, 0, NULL)); EXPECT_FALSE(BIO_set_cipher(bio_cipher.get(), EVP_rc4(), key, iv, /*enc*/ 1)); + ASSERT_TRUE(BIO_set_cipher(bio_cipher.get(), cipher, key, iv, /*enc*/ 1)); // Round-trip using |BIO_write| for encryption with same BIOs, reset between // encryption/decryption using |BIO_reset|. Fixed size IO. diff --git a/crypto/pkcs7/bio/cipher.c b/crypto/pkcs7/bio/cipher.c index ee5c95e7eb..6a7eb61cfb 100644 --- a/crypto/pkcs7/bio/cipher.c +++ b/crypto/pkcs7/bio/cipher.c @@ -283,7 +283,7 @@ int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *key, const EVP_CIPHER *kSupportedCiphers[] = { EVP_aes_128_cbc(), EVP_aes_128_ctr(), EVP_aes_128_ofb(), EVP_aes_256_cbc(), EVP_aes_256_ctr(), EVP_aes_256_ofb(), - EVP_chacha20_poly1305(), + EVP_chacha20_poly1305(), EVP_des_ede3_cbc(), }; const size_t kSupportedCiphersCount = sizeof(kSupportedCiphers) / sizeof(EVP_CIPHER *); diff --git a/crypto/pkcs7/internal.h b/crypto/pkcs7/internal.h index a3b5bc433e..b57e81749d 100644 --- a/crypto/pkcs7/internal.h +++ b/crypto/pkcs7/internal.h @@ -22,8 +22,6 @@ extern "C" { #endif -typedef struct pkcs7_issuer_and_serial_st PKCS7_ISSUER_AND_SERIAL; -typedef struct pkcs7_enc_content_st PKCS7_ENC_CONTENT; DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED) @@ -35,84 +33,6 @@ DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) DEFINE_STACK_OF(PKCS7) -// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-11.1 -// -// SignedAndEnvelopedData ::= SEQUENCE { -// version Version, -// recipientInfos RecipientInfos, -// digestAlgorithms DigestAlgorithmIdentifiers, -// encryptedContentInfo EncryptedContentInfo, -// certificates -// [0] IMPLICIT ExtendedCertificatesAndCertificates -// OPTIONAL, -// crls -// [1] IMPLICIT CertificateRevocationLists OPTIONAL, -// signerInfos SignerInfos } -struct pkcs7_sign_envelope_st { - ASN1_INTEGER *version; - STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; - STACK_OF(X509_ALGOR) *md_algs; - PKCS7_ENC_CONTENT *enc_data; - STACK_OF(X509) *cert; - STACK_OF(X509_CRL) *crl; - STACK_OF(PKCS7_SIGNER_INFO) *signer_info; -}; - -// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-6.7 -// -// IssuerAndSerialNumber ::= SEQUENCE { -// issuer Name, -// serialNumber CertificateSerialNumber } -struct pkcs7_issuer_and_serial_st { - X509_NAME *issuer; - ASN1_INTEGER *serial; -}; - -// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-9.2 -// -// SignerInfo ::= SEQUENCE { -// version Version, -// issuerAndSerialNumber IssuerAndSerialNumber, -// digestAlgorithm DigestAlgorithmIdentifier, -// authenticatedAttributes -// [0] IMPLICIT Attributes OPTIONAL, -// digestEncryptionAlgorithm -// DigestEncryptionAlgorithmIdentifier, -// encryptedDigest EncryptedDigest, -// unauthenticatedAttributes -// [1] IMPLICIT Attributes OPTIONAL } -// -// EncryptedDigest ::= OCTET STRING -struct pkcs7_signer_info_st { - ASN1_INTEGER *version; - PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; - X509_ALGOR *digest_alg; - STACK_OF(X509_ATTRIBUTE) *auth_attr; - X509_ALGOR *digest_enc_alg; - ASN1_OCTET_STRING *enc_digest; - STACK_OF(X509_ATTRIBUTE) *unauth_attr; - EVP_PKEY *pkey; // NOTE: |pkey| is not seriliazed. -}; - -// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-10.2 -// -// RecipientInfo ::= SEQUENCE { -// version Version, -// issuerAndSerialNumber IssuerAndSerialNumber, -// keyEncryptionAlgorithm -// -// KeyEncryptionAlgorithmIdentifier, -// encryptedKey EncryptedKey } -// -// EncryptedKey ::= OCTET STRING -struct pkcs7_recip_info_st { - ASN1_INTEGER *version; - PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; - X509_ALGOR *key_enc_algor; - ASN1_OCTET_STRING *enc_key; - X509 *cert; // NOTE: |cert| is not serialized -}; - // ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-10.1 // // EncryptedContentInfo ::= SEQUENCE { @@ -130,20 +50,6 @@ struct pkcs7_enc_content_st { const EVP_CIPHER *cipher; // NOTE: |cipher| is not serialized }; -// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-10.1 -// -// EnvelopedData ::= SEQUENCE { -// version Version, -// recipientInfos RecipientInfos, -// encryptedContentInfo EncryptedContentInfo } -// -// RecipientInfos ::= SET OF RecipientInfo -struct pkcs7_envelope_st { - ASN1_INTEGER *version; - PKCS7_ENC_CONTENT *enc_data; - STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; -}; - // ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-12 // // DigestedData ::= SEQUENCE { @@ -229,6 +135,10 @@ OPENSSL_EXPORT int BIO_set_cipher(BIO *b, const EVP_CIPHER *cipher, // authentic. OPENSSL_EXPORT int BIO_get_cipher_status(BIO *b); +// pkcs7_final initializes a data BIO using |p7|, copies all of |data| into it, +// before final finalizing |p7|. It returns 1 on success and 0 on failure. +OPENSSL_EXPORT int pkcs7_final(PKCS7 *p7, BIO *data); + #if defined(__cplusplus) } // extern C #endif diff --git a/crypto/pkcs7/pkcs7.c b/crypto/pkcs7/pkcs7.c index 4ff90e8280..699e571af7 100644 --- a/crypto/pkcs7/pkcs7.c +++ b/crypto/pkcs7/pkcs7.c @@ -22,11 +22,15 @@ #include #include #include +#include #include "../bytestring/internal.h" +#include "../fipsmodule/digest/internal.h" #include "../internal.h" #include "internal.h" +// TODO remove all other usages of OPENSSL_BEGIN_ALLOW_DEPRECATED in this file +OPENSSL_BEGIN_ALLOW_DEPRECATED // 1.2.840.113549.1.7.1 static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, @@ -996,7 +1000,7 @@ OPENSSL_END_ALLOW_DEPRECATED continue; } int sign_nid = OBJ_obj2nid(si->digest_alg->algorithm); - bio_tmp = pkcs7_find_digest(&md_ctx, bio_tmp, sign_nid); + bio_tmp = pkcs7_find_digest(&md_ctx, bio, sign_nid); if (bio_tmp == NULL) { goto err; } @@ -1065,13 +1069,13 @@ OPENSSL_END_ALLOW_DEPRECATED // copies are considered successful. It returns 1 on success and 0 on failure. static int pkcs7_bio_copy_content(BIO *src, BIO *dst) { uint8_t buf[1024]; - int bytes_processed, ret = 0; + int bytes_processed = 0, ret = 0; while ((bytes_processed = BIO_read(src, buf, sizeof(buf))) > 0) { if (!BIO_write_all(dst, buf, bytes_processed)) { goto err; } } - if (bytes_processed < 0) { + if (bytes_processed < 0 || !BIO_flush(dst)) { goto err; } ret = 1; @@ -1081,7 +1085,7 @@ static int pkcs7_bio_copy_content(BIO *src, BIO *dst) { } // PKCS7_final copies the contents of |data| into |p7| before finalizing |p7|. -static int pkcs7_final(PKCS7 *p7, BIO *data) { +int pkcs7_final(PKCS7 *p7, BIO *data) { BIO *p7bio; int ret = 0; @@ -1089,14 +1093,13 @@ static int pkcs7_final(PKCS7 *p7, BIO *data) { if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) { OPENSSL_END_ALLOW_DEPRECATED OPENSSL_PUT_ERROR(PKCS7, ERR_R_PKCS7_LIB); - return 0; + goto err; } if (!pkcs7_bio_copy_content(data, p7bio)) { goto err; } - BIO_flush(p7bio); OPENSSL_BEGIN_ALLOW_DEPRECATED if (!PKCS7_dataFinal(p7, p7bio)) { OPENSSL_END_ALLOW_DEPRECATED @@ -1230,11 +1233,28 @@ static BIO *pkcs7_data_decode(PKCS7 *p7, EVP_PKEY *pkey, X509 *pcert) { goto err; } break; + case NID_pkcs7_signedAndEnveloped: + rsk = p7->d.signed_and_enveloped->recipientinfo; + enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; + // |data_body| is NULL if the optional EncryptedContent is missing. + data_body = p7->d.signed_and_enveloped->enc_data->enc_data; + cipher = EVP_get_cipherbynid(OBJ_obj2nid(enc_alg->algorithm)); + if (cipher == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + goto err; + } + break; default: OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } + // Detached content must be supplied via in_bio instead + if (data_body == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_CONTENT); + goto err; + } + if ((cipher_bio = BIO_new(BIO_f_cipher())) == NULL) { OPENSSL_PUT_ERROR(PKCS7, ERR_R_BIO_LIB); goto err; @@ -1409,3 +1429,265 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) { BIO_free_all(bio); return ret; } + +static STACK_OF(X509) *pkcs7_get0_certificates(const PKCS7 *p7) { + GUARD_PTR(p7); + GUARD_PTR(p7->d.ptr); + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + return p7->d.sign->cert; + case NID_pkcs7_signedAndEnveloped: + return p7->d.signed_and_enveloped->cert; + default: + return NULL; + } +} + +static STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, + int flags) { + GUARD_PTR(p7); + STACK_OF(X509) *signers = NULL; + X509 *signer = NULL; + + if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); + return NULL; + } + STACK_OF(X509) *included_certs = pkcs7_get0_certificates(p7); + STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7); + + if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_SIGNERS); + return NULL; + } + + if ((signers = sk_X509_new_null()) == NULL) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_CRYPTO_LIB); + return NULL; + } + + for (size_t i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + PKCS7_ISSUER_AND_SERIAL *ias = si->issuer_and_serial; + // Prioritize |certs| passed by caller + signer = X509_find_by_issuer_and_serial(certs, ias->issuer, ias->serial); + if (!signer) { + signer = X509_find_by_issuer_and_serial(included_certs, ias->issuer, + ias->serial); + } + if (!signer) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); + sk_X509_free(signers); + return NULL; + } + if (!sk_X509_push(signers, signer)) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PKCS7_LIB); + sk_X509_free(signers); + return NULL; + } + } + + return signers; +} + +static int pkcs7_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert) { + GUARD_PTR(p_sk); + if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) { + goto err; + } + if (!sk_X509_push(*p_sk, cert)) { + goto err; + } + return 1; +err: + OPENSSL_PUT_ERROR(X509, ERR_R_CRYPTO_LIB); + return 0; +} + +static int pkcs7_x509_add_certs_new(STACK_OF(X509) **p_sk, + STACK_OF(X509) *certs) { + GUARD_PTR(p_sk); + if (!certs) { // |certs| can be null in the caller + return 1; + } + for (size_t i = 0; i < sk_X509_num(certs); i++) { + if (!pkcs7_x509_add_cert_new(p_sk, sk_X509_value(certs, i))) + return 0; + } + return 1; +} + +static int pkcs7_signature_verify(BIO *in_bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *signer) { + GUARD_PTR(in_bio); + GUARD_PTR(p7); + GUARD_PTR(si); + GUARD_PTR(signer); + EVP_MD_CTX *mdc_copy = NULL; + int ret = 0; + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + case NID_pkcs7_signedAndEnveloped: + break; + default: + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_WRONG_PKCS7_TYPE); + goto err; + } + + const int md_type = OBJ_obj2nid(si->digest_alg->algorithm); + EVP_MD_CTX *mdc = NULL; + BIO *bio = in_bio; + // There may be multiple MD-type BIOs in the chain, so iterate until we find + // the BIO with MD type we're looking for. + while (bio) { + if ((bio = BIO_find_type(bio, BIO_TYPE_MD)) == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + goto err; + } + if (!BIO_get_md_ctx(bio, &mdc) || !mdc) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PKCS7_LIB); + goto err; + } + if (EVP_MD_CTX_type(mdc) == md_type) { // found it! + break; + } + bio = BIO_next(bio); + } + + // Make a copy of |mdc| so we don't finalize the MD_CTX owned by |bio| + if ((mdc_copy = EVP_MD_CTX_new()) == NULL || + !EVP_MD_CTX_copy_ex(mdc_copy, mdc)) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_EVP_LIB); + goto err; + } + + // We don't currently support signed attributes + if (si->auth_attr && sk_X509_ATTRIBUTE_num(si->auth_attr) != 0) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_INVALID_SIGNED_DATA_TYPE); + goto err; + } + + EVP_PKEY *pkey; + if ((pkey = X509_get0_pubkey(signer)) == NULL) { + goto err; + } + + ASN1_OCTET_STRING *data_body = si->enc_digest; + if (!EVP_VerifyFinal(mdc_copy, data_body->data, data_body->length, pkey)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_SIGNATURE_FAILURE); + goto err; + } + + ret = 1; + +err: + EVP_MD_CTX_free(mdc_copy); + return ret; +} + +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags) { + GUARD_PTR(p7); + GUARD_PTR(store); + STACK_OF(X509) *signers = NULL, *untrusted = NULL; + X509_STORE_CTX *cert_ctx = NULL; + BIO *p7bio = NULL; + int ret = 0; + + if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); + goto out; + } + + // If |p7| is detached, caller must supply data via |indata| + if (PKCS7_is_detached(p7) && indata == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_CONTENT); + goto out; + } + + // We enforce OpenSSL's PKCS7_NO_DUAL_CONTENT flag in all cases for signed + if (PKCS7_type_is_signed(p7) && (!PKCS7_is_detached(p7) && indata)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT); + goto out; + } + + STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7); + if (sinfos == NULL || sk_PKCS7_SIGNER_INFO_num(sinfos) == 0UL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA); + goto out; + } + + if ((signers = PKCS7_get0_signers(p7, certs, flags)) == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_SIGNERS); + goto out; + } + + if (!(flags & PKCS7_NOVERIFY)) { + STACK_OF(X509) *included_certs = pkcs7_get0_certificates(p7); + if ((cert_ctx = X509_STORE_CTX_new()) == NULL || + !pkcs7_x509_add_certs_new(&untrusted, certs) || + !pkcs7_x509_add_certs_new(&untrusted, included_certs)) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PKCS7_LIB); + goto out; + } + + for (size_t k = 0; k < sk_X509_num(signers); k++) { + X509 *signer = sk_X509_value(signers, k); + if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_X509_LIB); + goto out; + } + if (!X509_STORE_CTX_set_default(cert_ctx, "smime_sign")) { + goto out; + } + X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl); + } + // NOTE: unlike most of our functions, |X509_verify_cert| can return <= 0 + if (X509_verify_cert(cert_ctx) <= 0) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR); + goto out; + } + } + + // In copying data into out, we also read it through digest filters on |p7| to + // calculate digest for verification. + if ((p7bio = PKCS7_dataInit(p7, indata)) == NULL || + (out && !pkcs7_bio_copy_content(p7bio, out))) { + goto out; + } + + // Verify signatures against signers + for (size_t ii = 0; ii < sk_PKCS7_SIGNER_INFO_num(sinfos); ii++) { + PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, ii); + X509 *signer = sk_X509_value(signers, ii); + if (!pkcs7_signature_verify(p7bio, p7, si, signer)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_SIGNATURE_FAILURE); + goto out; + } + } + + ret = 1; + +out: + X509_STORE_CTX_free(cert_ctx); + // If |indata| was passed for detached signature, |PKCS7_dataInit| has pushed + // it onto |p7bio|. Pop the reference so caller retains ownership of |indata|. + if (indata) { + BIO_pop(p7bio); + } + BIO_free_all(p7bio); + if (signers) { + sk_X509_free(signers); + } + if (untrusted) { + sk_X509_free(untrusted); + } + return ret; +} + +PKCS7 *SMIME_read_PKCS7(BIO *in, BIO **bcont) { return NULL; } + +int SMIME_write_PKCS7(BIO *out, PKCS7 *p7, BIO *data, int flags) { return 0; } + +OPENSSL_END_ALLOW_DEPRECATED diff --git a/crypto/pkcs7/pkcs7_test.cc b/crypto/pkcs7/pkcs7_test.cc index b75408a1a3..1ae76dfa86 100644 --- a/crypto/pkcs7/pkcs7_test.cc +++ b/crypto/pkcs7/pkcs7_test.cc @@ -26,7 +26,6 @@ #include "../internal.h" #include "../test/test_util.h" - // kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS // using the Chrome UI. static const uint8_t kPKCS7NSS[] = { @@ -1320,20 +1319,6 @@ hJTbHtjEDJ7BHLC/CNUhXbpyyu1y EXPECT_EQ(Bytes(pkcs7_bytes, pkcs7_len), Bytes(kExpectedOutput, sizeof(kExpectedOutput))); - // Other option combinations should fail. - EXPECT_FALSE(PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, - data_bio.get(), - PKCS7_NOATTR | PKCS7_BINARY | PKCS7_NOCERTS)); - EXPECT_FALSE(PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, - data_bio.get(), - PKCS7_BINARY | PKCS7_NOCERTS | PKCS7_DETACHED)); - EXPECT_FALSE( - PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, data_bio.get(), - PKCS7_NOATTR | PKCS7_TEXT | PKCS7_NOCERTS | PKCS7_DETACHED)); - EXPECT_FALSE(PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, - data_bio.get(), - PKCS7_NOATTR | PKCS7_BINARY | PKCS7_DETACHED)); - ERR_clear_error(); } @@ -1440,10 +1425,8 @@ TEST(PKCS7Test, GettersSetters) { EXPECT_TRUE(PKCS7_type_is_signed(p7_dup.get())); p7_der = kPKCS7SignedWithSignerInfo; - PKCS7 *p7_ptr = nullptr; bssl::UniquePtr bio(BIO_new_mem_buf(p7_der, p7_der_len)); - ASSERT_FALSE(d2i_PKCS7_bio(bio.get(), nullptr)); - p7.reset(d2i_PKCS7_bio(bio.get(), &p7_ptr)); + p7.reset(d2i_PKCS7_bio(bio.get(), nullptr)); ASSERT_TRUE(p7); ASSERT_TRUE(PKCS7_type_is_signed(p7.get())); bio.reset(BIO_new(BIO_s_mem())); @@ -1637,7 +1620,7 @@ TEST(PKCS7Test, DataInitFinal) { ASSERT_TRUE(p7); ASSERT_TRUE(PKCS7_set_type(p7.get(), NID_pkcs7_digest)); ASSERT_TRUE(PKCS7_set_digest(p7.get(), EVP_sha256())); - EXPECT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data)); + ASSERT_TRUE(PKCS7_content_new(p7.get(), NID_pkcs7_data)); bio.reset(PKCS7_dataInit(p7.get(), nullptr)); EXPECT_TRUE(bio); EXPECT_TRUE(PKCS7_dataFinal(p7.get(), bio.get())); @@ -1879,3 +1862,91 @@ TEST(PKCS7Test, TestEnveloped) { /*flags*/ 0)); EXPECT_EQ(X509_R_KEY_VALUES_MISMATCH, ERR_GET_REASON(ERR_peek_error())); } + +TEST(PKCS7Test, TestSigned) { + bssl::UniquePtr p7; + bssl::UniquePtr p7si; + bssl::UniquePtr bio_in, bio_out; + bssl::UniquePtr certs; + bssl::UniquePtr store; + bssl::UniquePtr store_ctx; + bssl::UniquePtr not_before, not_after; + bssl::UniquePtr root_rsa, leaf_rsa; + bssl::UniquePtr root_pkey, leaf_pkey; + uint8_t buf[64], out_buf[sizeof(buf)]; + + OPENSSL_memset(buf, 'A', sizeof(buf)); + OPENSSL_memset(out_buf, '\0', sizeof(out_buf)); + + root_rsa.reset(RSA_new()); + ASSERT_TRUE(RSA_generate_key_fips(root_rsa.get(), 2048, nullptr)); + root_pkey.reset(EVP_PKEY_new()); + ASSERT_TRUE(EVP_PKEY_set1_RSA(root_pkey.get(), root_rsa.get())); + leaf_rsa.reset(RSA_new()); + ASSERT_TRUE(RSA_generate_key_fips(leaf_rsa.get(), 2048, nullptr)); + leaf_pkey.reset(EVP_PKEY_new()); + ASSERT_TRUE(EVP_PKEY_set1_RSA(leaf_pkey.get(), leaf_rsa.get())); + + // |PKCS7_verify| creates its own X509_STORE_CTX internally, so we can't set + // relative validity time on the store it uses from here (by default + // X509_STORE_CTX uses std's |time|). So, we set a wide validity gap here. + // |not_after| won't need to be updated until December 9999 and |not_before| + // would only need to be reconsidered in the advent of a time machine. + not_before.reset(ASN1_TIME_set_posix(nullptr, 0L)); + not_after.reset(ASN1_TIME_set_posix(nullptr, INT64_C(253402300799))); + + bssl::UniquePtr root = + MakeTestCert("Root", "Root", root_pkey.get(), /*is_ca=*/true); + ASSERT_TRUE(root); + ASSERT_TRUE(X509_set_notBefore(root.get(), not_before.get())); + ASSERT_TRUE(X509_set_notAfter(root.get(), not_after.get())); + // Root signs itself + ASSERT_TRUE(X509_sign(root.get(), root_pkey.get(), EVP_sha256())); + + bssl::UniquePtr leaf = + MakeTestCert("Root", "Leaf", leaf_pkey.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + ASSERT_TRUE(X509_set_notBefore(leaf.get(), not_before.get())); + ASSERT_TRUE(X509_set_notAfter(leaf.get(), not_after.get())); + // Root signs leaf + ASSERT_TRUE(X509_sign(leaf.get(), root_pkey.get(), EVP_sha256())); + X509_up_ref(leaf.get()); + X509_up_ref(leaf.get()); + + store.reset(X509_STORE_new()); + ASSERT_TRUE(X509_STORE_add_cert(store.get(), root.get())); + + bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf))); + p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(), + /*flags*/ 0)); + ASSERT_TRUE(p7); + EXPECT_TRUE(PKCS7_type_is_signed(p7.get())); + EXPECT_FALSE(PKCS7_is_detached(p7.get())); + + // attached + certs.reset(sk_X509_new_null()); + ASSERT_TRUE(sk_X509_push(certs.get(), leaf.get())); + bio_out.reset(BIO_new(BIO_s_mem())); + EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(), nullptr, + bio_out.get(), /*flags*/ 0)); + ASSERT_EQ((int)sizeof(out_buf), + BIO_read(bio_out.get(), out_buf, sizeof(out_buf))); + EXPECT_EQ(Bytes(buf, sizeof(buf)), Bytes(out_buf, sizeof(out_buf))); + + + // detached + bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf))); + p7.reset(PKCS7_sign(leaf.get(), leaf_pkey.get(), nullptr, bio_in.get(), + PKCS7_DETACHED)); + EXPECT_TRUE(PKCS7_is_detached(p7.get())); + certs.reset(sk_X509_new_null()); + ASSERT_TRUE(sk_X509_push(certs.get(), leaf.get())); + bio_in.reset(BIO_new_mem_buf(buf, sizeof(buf))); + bio_out.reset(BIO_new(BIO_s_mem())); + EXPECT_TRUE(PKCS7_verify(p7.get(), certs.get(), store.get(), bio_in.get(), + bio_out.get(), /*flags*/ 0)); + OPENSSL_memset(out_buf, '\0', sizeof(out_buf)); + ASSERT_EQ((int)sizeof(out_buf), + BIO_read(bio_out.get(), out_buf, sizeof(out_buf))); + EXPECT_EQ(Bytes(buf, sizeof(buf)), Bytes(out_buf, sizeof(out_buf))); +} diff --git a/crypto/pkcs7/pkcs7_x509.c b/crypto/pkcs7/pkcs7_x509.c index 10183efc21..23e9e47fd1 100644 --- a/crypto/pkcs7/pkcs7_x509.c +++ b/crypto/pkcs7/pkcs7_x509.c @@ -233,12 +233,19 @@ int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) { } PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) { - if (out == NULL) { - OPENSSL_PUT_ERROR(PKCS7, ERR_R_PASSED_NULL_PARAMETER); + GUARD_PTR(bio); + uint8_t *data; + size_t len; + // Read BIO contents into newly allocated buffer + if (!BIO_read_asn1(bio, &data, &len, INT_MAX)) { return NULL; } - - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bio, *out); + const uint8_t *ptr = data; + // d2i_PKCS7 handles indefinite-length BER properly, so use it instead of + // ASN1_item_d2i_bio + void *ret = d2i_PKCS7(out, &ptr, len); + OPENSSL_free(data); + return ret; } int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) { @@ -370,6 +377,107 @@ static int write_signer_info(CBB *out, const void *arg) { return ret; } +static PKCS7_SIGNER_INFO *pkcs7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey) { + PKCS7_SIGNER_INFO *si = NULL; + const EVP_MD *digest = NULL; + + EVP_PKEY_CTX *pkey_ctx = EVP_PKEY_CTX_new(pkey, /*engine*/ NULL); + if (!pkey_ctx) { + goto err; + } + int ok = EVP_PKEY_CTX_get_signature_md(pkey_ctx, &digest); + EVP_PKEY_CTX_free(pkey_ctx); + if (!ok && (EVP_PKEY_id(pkey) == EVP_PKEY_RSA || + EVP_PKEY_id(pkey) == EVP_PKEY_DSA)) { + // OpenSSL's docs say that this defaults to SHA1, but appears to actually + // default to SHA256 in 1.1.x and 3.x + // https://linux.die.net/man/3/pkcs7_sign + // https://github.com/openssl/openssl/blob/79c98fc6ccab49f02528e06cc046ac61f841a753/crypto/rsa/rsa_ameth.c#L438 + digest = EVP_sha256(); + } else if (!ok) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_DEFAULT_DIGEST); + goto err; + } + + if ((si = PKCS7_SIGNER_INFO_new()) == NULL || + !PKCS7_SIGNER_INFO_set(si, x509, pkey, digest) || + !PKCS7_add_signer(p7, si)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_PKCS7_DATASIGN); + goto err; + } + return si; +err: + PKCS7_SIGNER_INFO_free(si); + return NULL; +} + +static PKCS7_SIGNER_INFO *pkcs7_sign_add_signer(PKCS7 *p7, X509 *signcert, + EVP_PKEY *pkey, int flags) { + PKCS7_SIGNER_INFO *si = NULL; + STACK_OF(X509_ALGOR) *smcap = NULL; + + if (!X509_check_private_key(signcert, pkey)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + + if ((si = pkcs7_add_signature(p7, signcert, pkey)) == NULL) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); + return NULL; + } + + if (!(flags & PKCS7_NOCERTS)) { + if (!PKCS7_add_certificate(p7, signcert)) + goto err; + } + + return si; +err: + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + return NULL; +} + +static int pkcs7_do_general_sign(X509 *sign_cert, EVP_PKEY *pkey, + struct stack_st_X509 *certs, BIO *data, + int flags, PKCS7 **ret) { + if ((*ret = PKCS7_new()) == NULL || !PKCS7_set_type(*ret, NID_pkcs7_signed) || + !PKCS7_content_new(*ret, NID_pkcs7_data)) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_PKCS7_LIB); + goto err; + } + + if (!pkcs7_sign_add_signer(*ret, sign_cert, pkey, flags)) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); + goto err; + } + + for (size_t i = 0; i < sk_X509_num(certs); i++) { + if (!PKCS7_add_certificate(*ret, sk_X509_value(certs, i))) { + OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); + goto err; + } + } + + if ((flags & PKCS7_DETACHED) && + PKCS7_type_is_data((*ret)->d.sign->contents)) { + ASN1_OCTET_STRING_free((*ret)->d.sign->contents->d.data); + (*ret)->d.sign->contents->d.data = NULL; + } + + if (!pkcs7_final(*ret, data)) { + goto err; + } + + return 1; +err: + if (*ret) { + PKCS7_free(*ret); + } + *ret = NULL; + return 0; +} + PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { CBB cbb; @@ -407,6 +515,11 @@ PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs, goto out; } OPENSSL_free(si_data.signature); + } else if (sign_cert != NULL && pkey != NULL && data != NULL) { + // pkcs7_do_general_sign will either populate |*ret| on success or set it to + // NULL on failure. goto out label regardless to skip CBB/d2i stuff below. + pkcs7_do_general_sign(sign_cert, pkey, certs, data, flags, &ret); + goto out; } else { OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); goto out; diff --git a/crypto/test/test_util.cc b/crypto/test/test_util.cc index 4d3853f295..9c010c5d50 100644 --- a/crypto/test/test_util.cc +++ b/crypto/test/test_util.cc @@ -111,6 +111,35 @@ bssl::UniquePtr RSAFromPEM(const char *pem) { PEM_read_bio_RSAPrivateKey(bio.get(), nullptr, nullptr, nullptr)); } +bssl::UniquePtr MakeTestCert(const char *issuer, + const char *subject, EVP_PKEY *key, + bool is_ca) { + bssl::UniquePtr cert(X509_new()); + if (!cert || // + !X509_set_version(cert.get(), X509_VERSION_3) || + !X509_NAME_add_entry_by_txt( + X509_get_issuer_name(cert.get()), "CN", MBSTRING_UTF8, + reinterpret_cast(issuer), -1, -1, 0) || + !X509_NAME_add_entry_by_txt( + X509_get_subject_name(cert.get()), "CN", MBSTRING_UTF8, + reinterpret_cast(subject), -1, -1, 0) || + !X509_set_pubkey(cert.get(), key) || + !ASN1_TIME_adj(X509_getm_notBefore(cert.get()), kReferenceTime, -1, 0) || + !ASN1_TIME_adj(X509_getm_notAfter(cert.get()), kReferenceTime, 1, 0)) { + return nullptr; + } + bssl::UniquePtr bc(BASIC_CONSTRAINTS_new()); + if (!bc) { + return nullptr; + } + bc->ca = is_ca ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; + if (!X509_add1_ext_i2d(cert.get(), NID_basic_constraints, bc.get(), + /*crit=*/1, /*flags=*/0)) { + return nullptr; + } + return cert; +} + bssl::UniquePtr CertsToStack( const std::vector &certs) { bssl::UniquePtr stack(sk_X509_new_null()); diff --git a/crypto/test/test_util.h b/crypto/test/test_util.h index 98458b84c9..4adb192638 100644 --- a/crypto/test/test_util.h +++ b/crypto/test/test_util.h @@ -83,6 +83,17 @@ bssl::UniquePtr CertsToStack(const std::vector &certs); // |RSA*|. bssl::UniquePtr RSAFromPEM(const char *pem); +// kReferenceTime is the reference time used by certs created by |MakeTestCert|. +// It is the unix timestamp for Sep 27th, 2016. +static const int64_t kReferenceTime = 1474934400; + +// MakeTestCert creates an X509 certificate for use in testing. It is configured +// to be valid from 1 day prior |kReferenceTime| until 1 day after +// |kReferenceTime|. +bssl::UniquePtr MakeTestCert(const char *issuer, + const char *subject, EVP_PKEY *key, + bool is_ca); + // unique_ptr will automatically call fclose on the file descriptior when the // variable goes out of scope, so we need to specify BIO_NOCLOSE close flags // to avoid a double-free condition. diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 99e8a155f4..ec64e8aeea 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -1514,8 +1514,6 @@ static bssl::UniquePtr CRLsToStack( return stack; } -static const int64_t kReferenceTime = 1474934400 /* Sep 27th, 2016 */; - static int Verify( X509 *leaf, const std::vector &roots, const std::vector &intermediates, @@ -2234,35 +2232,6 @@ static bssl::UniquePtr MakeGeneralName(int type, return name; } -static bssl::UniquePtr MakeTestCert(const char *issuer, - const char *subject, EVP_PKEY *key, - bool is_ca) { - bssl::UniquePtr cert(X509_new()); - if (!cert || // - !X509_set_version(cert.get(), X509_VERSION_3) || - !X509_NAME_add_entry_by_txt( - X509_get_issuer_name(cert.get()), "CN", MBSTRING_UTF8, - reinterpret_cast(issuer), -1, -1, 0) || - !X509_NAME_add_entry_by_txt( - X509_get_subject_name(cert.get()), "CN", MBSTRING_UTF8, - reinterpret_cast(subject), -1, -1, 0) || - !X509_set_pubkey(cert.get(), key) || - !ASN1_TIME_adj(X509_getm_notBefore(cert.get()), kReferenceTime, -1, 0) || - !ASN1_TIME_adj(X509_getm_notAfter(cert.get()), kReferenceTime, 1, 0)) { - return nullptr; - } - bssl::UniquePtr bc(BASIC_CONSTRAINTS_new()); - if (!bc) { - return nullptr; - } - bc->ca = is_ca ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; - if (!X509_add1_ext_i2d(cert.get(), NID_basic_constraints, bc.get(), - /*crit=*/1, /*flags=*/0)) { - return nullptr; - } - return cert; -} - static bool AddExtendedKeyUsage(X509 *x509, const std::vector &eku_nids) { bssl::UniquePtr objs(sk_ASN1_OBJECT_new_null()); if (objs == nullptr) { diff --git a/generated-src/err_data.c b/generated-src/err_data.c index 96bca7dba6..e7998a89b1 100644 --- a/generated-src/err_data.c +++ b/generated-src/err_data.c @@ -76,54 +76,54 @@ const uint32_t kOpenSSLReasonValues[] = { 0xc3b00f7, 0xc3b8921, 0x10320892, - 0x10329a2b, - 0x10331a37, - 0x10339a50, - 0x10341a63, + 0x10329c47, + 0x10331c53, + 0x10339c6c, + 0x10341c7f, 0x10349064, 0x10350db0, - 0x10359a76, - 0x10361aa0, - 0x10369ab3, - 0x10371ad2, - 0x10379aeb, - 0x10381b00, - 0x10389b1e, - 0x10391b2d, - 0x10399b49, - 0x103a1b64, - 0x103a9b73, - 0x103b1b8f, - 0x103b9baa, - 0x103c1bd0, + 0x10359c92, + 0x10361cbc, + 0x10369ccf, + 0x10371cee, + 0x10379d07, + 0x10381d1c, + 0x10389d3a, + 0x10391d49, + 0x10399d65, + 0x103a1d80, + 0x103a9d8f, + 0x103b1dab, + 0x103b9dc6, + 0x103c1dec, 0x103c80f7, - 0x103d1be1, - 0x103d9bf5, - 0x103e1c14, - 0x103e9c23, - 0x103f1c3a, - 0x103f9c4d, + 0x103d1dfd, + 0x103d9e11, + 0x103e1e30, + 0x103e9e3f, + 0x103f1e56, + 0x103f9e69, 0x10400d74, - 0x10409c60, - 0x10411c7e, - 0x10419c91, - 0x10421cab, - 0x10429cbb, - 0x10431ccf, - 0x10439ce5, - 0x10441cfd, - 0x10449d12, - 0x10451d26, - 0x10459d38, + 0x10409e7c, + 0x10411e9a, + 0x10419ead, + 0x10421ec7, + 0x10429ed7, + 0x10431eeb, + 0x10439f01, + 0x10441f19, + 0x10449f2e, + 0x10451f42, + 0x10459f54, 0x10460635, 0x1046899a, - 0x10471d4d, - 0x10479d64, - 0x10481d79, - 0x10489d87, + 0x10471f69, + 0x10479f80, + 0x10481f95, + 0x10489fa3, 0x10490fb0, - 0x10499bc1, - 0x104a1a8b, + 0x10499ddd, + 0x104a1ca7, 0x107c1072, 0x14320d38, 0x14328d65, @@ -203,52 +203,52 @@ const uint32_t kOpenSSLReasonValues[] = { 0x283500f7, 0x28358d52, 0x2836099a, - 0x2c3237b6, + 0x2c3239d2, 0x2c32975c, - 0x2c3337c4, - 0x2c33b7d6, - 0x2c3437ea, - 0x2c34b7fc, - 0x2c353817, - 0x2c35b829, - 0x2c363859, + 0x2c3339e0, + 0x2c33b9f2, + 0x2c343a06, + 0x2c34ba18, + 0x2c353a33, + 0x2c35ba45, + 0x2c363a75, 0x2c36833a, - 0x2c373866, - 0x2c37b892, - 0x2c3838d0, - 0x2c38b8e7, - 0x2c393905, - 0x2c39b915, - 0x2c3a3927, - 0x2c3ab93b, - 0x2c3b394c, - 0x2c3bb96b, - 0x2c3c176e, - 0x2c3c9784, - 0x2c3d39b0, - 0x2c3d979d, - 0x2c3e39da, - 0x2c3eb9e8, - 0x2c3f3a00, - 0x2c3fba18, - 0x2c403a42, + 0x2c373a82, + 0x2c37baae, + 0x2c383aec, + 0x2c38bb03, + 0x2c393b21, + 0x2c39bb31, + 0x2c3a3b43, + 0x2c3abb57, + 0x2c3b3b68, + 0x2c3bbb87, + 0x2c3c1846, + 0x2c3c985c, + 0x2c3d3bcc, + 0x2c3d9880, + 0x2c3e3bf6, + 0x2c3ebc04, + 0x2c3f3c1c, + 0x2c3fbc34, + 0x2c403c5e, 0x2c4093fd, - 0x2c413a53, - 0x2c41ba79, + 0x2c413c6f, + 0x2c41bc95, 0x2c421382, - 0x2c42ba8a, + 0x2c42bca6, 0x2c43076d, - 0x2c43b95d, - 0x2c4438a5, - 0x2c44ba25, - 0x2c45383c, - 0x2c45b878, - 0x2c4638f5, - 0x2c46b97f, - 0x2c473994, - 0x2c47b9cd, - 0x2c4838b7, - 0x2c48ba66, + 0x2c43bb79, + 0x2c443ac1, + 0x2c44bc41, + 0x2c453a58, + 0x2c45ba94, + 0x2c463b11, + 0x2c46bb9b, + 0x2c473bb0, + 0x2c47bbe9, + 0x2c483ad3, + 0x2c48bc82, 0x30320000, 0x30328015, 0x3033001f, @@ -388,269 +388,269 @@ const uint32_t kOpenSSLReasonValues[] = { 0x3c418ea4, 0x3c420fb0, 0x3c428f3a, - 0x40321e19, - 0x40329e2f, - 0x40331e5d, - 0x40339e67, - 0x40341e7e, - 0x40349e9c, - 0x40351eac, - 0x40359ebe, - 0x40361ecb, - 0x40369ed7, - 0x40371eec, - 0x40379f25, - 0x40381f30, - 0x40389f42, + 0x40322035, + 0x4032a04b, + 0x40332079, + 0x4033a083, + 0x4034209a, + 0x4034a0b8, + 0x403520c8, + 0x4035a0da, + 0x403620e7, + 0x4036a0f3, + 0x40372108, + 0x4037a141, + 0x4038214c, + 0x4038a15e, 0x40391064, - 0x40399f52, - 0x403a1f65, - 0x403a9f86, - 0x403b1f97, - 0x403b9fa7, + 0x4039a16e, + 0x403a2181, + 0x403aa1a2, + 0x403b21b3, + 0x403ba1c3, 0x403c0071, 0x403c8090, - 0x403d2008, - 0x403da01e, - 0x403e202d, - 0x403ea065, - 0x403f207f, - 0x403fa0a7, - 0x404020bc, - 0x4040a0d0, - 0x4041210b, - 0x4041a126, - 0x4042213f, - 0x4042a152, - 0x40432166, - 0x4043a194, - 0x404421ab, + 0x403d2224, + 0x403da23a, + 0x403e2249, + 0x403ea281, + 0x403f229b, + 0x403fa2c3, + 0x404022d8, + 0x4040a2ec, + 0x40412327, + 0x4041a342, + 0x4042235b, + 0x4042a36e, + 0x40432382, + 0x4043a3b0, + 0x404423c7, 0x404480b9, - 0x404521c0, - 0x4045a1d2, - 0x404621f6, - 0x4046a216, - 0x40472224, - 0x4047a24b, - 0x404822bc, - 0x4048a376, - 0x4049238d, - 0x4049a3a7, - 0x404a23be, - 0x404aa3dc, - 0x404b23f4, - 0x404ba421, - 0x404c2437, - 0x404ca449, - 0x404d246a, - 0x404da4a3, - 0x404e24b7, - 0x404ea4c4, - 0x404f2575, - 0x404fa5eb, - 0x4050265a, - 0x4050a66e, - 0x405126a1, - 0x405226b1, - 0x4052a6d5, - 0x405326ed, - 0x4053a700, - 0x40542715, - 0x4054a738, - 0x40552763, - 0x4055a7a0, - 0x405627c5, - 0x4056a7de, - 0x405727f6, - 0x4057a809, - 0x4058281e, - 0x4058a845, - 0x40592874, - 0x4059a8a1, - 0x405aa8b5, - 0x405b28cd, - 0x405ba8de, - 0x405c28f1, - 0x405ca930, - 0x405d293d, - 0x405da962, - 0x405e29a0, + 0x404523dc, + 0x4045a3ee, + 0x40462412, + 0x4046a432, + 0x40472440, + 0x4047a467, + 0x404824d8, + 0x4048a592, + 0x404925a9, + 0x4049a5c3, + 0x404a25da, + 0x404aa5f8, + 0x404b2610, + 0x404ba63d, + 0x404c2653, + 0x404ca665, + 0x404d2686, + 0x404da6bf, + 0x404e26d3, + 0x404ea6e0, + 0x404f2791, + 0x404fa807, + 0x40502876, + 0x4050a88a, + 0x405128bd, + 0x405228cd, + 0x4052a8f1, + 0x40532909, + 0x4053a91c, + 0x40542931, + 0x4054a954, + 0x4055297f, + 0x4055a9bc, + 0x405629e1, + 0x4056a9fa, + 0x40572a12, + 0x4057aa25, + 0x40582a3a, + 0x4058aa61, + 0x40592a90, + 0x4059aabd, + 0x405aaad1, + 0x405b2ae9, + 0x405baafa, + 0x405c2b0d, + 0x405cab4c, + 0x405d2b59, + 0x405dab7e, + 0x405e2bbc, 0x405e8b2d, - 0x405f29c1, - 0x405fa9ce, - 0x406029dc, - 0x4060a9fe, - 0x40612a5f, - 0x4061aa97, - 0x40622aae, - 0x4062aabf, - 0x40632b0c, - 0x4063ab21, - 0x40642b38, - 0x4064ab64, - 0x40652b7f, - 0x4065ab96, - 0x40662bae, - 0x4066abd8, - 0x40672c03, - 0x4067ad06, - 0x40682d4e, - 0x4068ad6f, - 0x40692da1, - 0x4069adcf, - 0x406a2df0, - 0x406aae10, - 0x406b2f98, - 0x406bafbb, - 0x406c2fd1, - 0x406cb2db, - 0x406d330a, - 0x406db332, - 0x406e3360, - 0x406eb3ad, - 0x406f3406, - 0x406fb43e, - 0x40703451, - 0x4070b46e, + 0x405f2bdd, + 0x405fabea, + 0x40602bf8, + 0x4060ac1a, + 0x40612c7b, + 0x4061acb3, + 0x40622cca, + 0x4062acdb, + 0x40632d28, + 0x4063ad3d, + 0x40642d54, + 0x4064ad80, + 0x40652d9b, + 0x4065adb2, + 0x40662dca, + 0x4066adf4, + 0x40672e1f, + 0x4067af22, + 0x40682f6a, + 0x4068af8b, + 0x40692fbd, + 0x4069afeb, + 0x406a300c, + 0x406ab02c, + 0x406b31b4, + 0x406bb1d7, + 0x406c31ed, + 0x406cb4f7, + 0x406d3526, + 0x406db54e, + 0x406e357c, + 0x406eb5c9, + 0x406f3622, + 0x406fb65a, + 0x4070366d, + 0x4070b68a, 0x4071084d, - 0x4071b480, - 0x40723493, - 0x4072b4c9, - 0x407334e1, - 0x40739986, - 0x407434f5, - 0x4074b50f, - 0x40753520, - 0x4075b534, - 0x40763542, + 0x4071b69c, + 0x407236af, + 0x4072b6e5, + 0x407336fd, + 0x40739ba2, + 0x40743711, + 0x4074b72b, + 0x4075373c, + 0x4075b750, + 0x4076375e, 0x40769732, - 0x40773567, - 0x4077b5a7, - 0x407835c2, - 0x4078b5fb, - 0x40793612, - 0x4079b628, - 0x407a3654, - 0x407ab667, - 0x407b367c, - 0x407bb68e, - 0x407c36bf, - 0x407cb6c8, - 0x407d2d8a, - 0x407da613, - 0x407e35d7, - 0x407ea855, - 0x407f2238, - 0x407fa40b, - 0x40802585, - 0x4080a260, - 0x408126c3, - 0x4081a512, - 0x4082334b, - 0x40829fb3, - 0x40832830, - 0x4083ab49, - 0x40842274, - 0x4084a88d, - 0x40852902, - 0x4085aa26, - 0x40862982, - 0x4086a62d, - 0x40873391, - 0x4087aa74, - 0x40881ff1, - 0x4088ad19, - 0x40892040, - 0x40899fcd, - 0x408a3009, - 0x408a9d9e, - 0x408b36a3, - 0x408bb41b, - 0x408c2912, - 0x408c9dd6, - 0x408d235c, - 0x408da2a6, - 0x408e248c, - 0x408ea780, - 0x408f2d2d, - 0x408faa42, - 0x40902c24, - 0x4090a954, - 0x40912ff1, - 0x40919dfc, - 0x4092208d, - 0x4092b3cc, - 0x409334ac, - 0x4093a63e, - 0x40942288, - 0x4094b022, - 0x40952ad0, - 0x4095b634, - 0x40963378, - 0x4096a59e, - 0x40972689, - 0x4097a4db, - 0x409820ed, - 0x4098aae4, - 0x409933e8, - 0x4099a7ad, - 0x409a2746, - 0x409a9dba, - 0x409b22e2, - 0x409ba30d, - 0x409c3589, - 0x409ca335, - 0x409d255a, - 0x409da528, - 0x409e217e, - 0x409ea5d3, - 0x409f25bb, - 0x409fa2d5, - 0x40a025fb, - 0x40a0a4f5, - 0x40a12543, - 0x40fa2cec, - 0x40faac48, - 0x40fb2ccb, - 0x40fbac62, - 0x40fcacaa, - 0x40fd2c83, - 0x40fd9efe, - 0x40fe1f12, - 0x41f42ec3, - 0x41f92f55, - 0x41fe2e48, - 0x41feb0fe, - 0x41ff322c, - 0x42032edc, - 0x42082efe, - 0x4208af3a, - 0x42092e2c, - 0x4209af74, - 0x420a2e83, - 0x420aae63, - 0x420b2ea3, - 0x420baf1c, - 0x420c3248, - 0x420cb032, - 0x420d30e5, - 0x420db11c, - 0x4212314f, - 0x4217320f, - 0x4217b191, - 0x421c31b3, - 0x421f316e, - 0x422132c0, - 0x422631f2, - 0x422b329e, - 0x422bb0c0, - 0x422c3280, - 0x422cb073, - 0x422d304c, - 0x422db25f, - 0x422e309f, - 0x423031ce, - 0x4230b136, + 0x40773783, + 0x4077b7c3, + 0x407837de, + 0x4078b817, + 0x4079382e, + 0x4079b844, + 0x407a3870, + 0x407ab883, + 0x407b3898, + 0x407bb8aa, + 0x407c38db, + 0x407cb8e4, + 0x407d2fa6, + 0x407da82f, + 0x407e37f3, + 0x407eaa71, + 0x407f2454, + 0x407fa627, + 0x408027a1, + 0x4080a47c, + 0x408128df, + 0x4081a72e, + 0x40823567, + 0x4082a1cf, + 0x40832a4c, + 0x4083ad65, + 0x40842490, + 0x4084aaa9, + 0x40852b1e, + 0x4085ac42, + 0x40862b9e, + 0x4086a849, + 0x408735ad, + 0x4087ac90, + 0x4088220d, + 0x4088af35, + 0x4089225c, + 0x4089a1e9, + 0x408a3225, + 0x408a9fba, + 0x408b38bf, + 0x408bb637, + 0x408c2b2e, + 0x408c9ff2, + 0x408d2578, + 0x408da4c2, + 0x408e26a8, + 0x408ea99c, + 0x408f2f49, + 0x408fac5e, + 0x40902e40, + 0x4090ab70, + 0x4091320d, + 0x4091a018, + 0x409222a9, + 0x4092b5e8, + 0x409336c8, + 0x4093a85a, + 0x409424a4, + 0x4094b23e, + 0x40952cec, + 0x4095b850, + 0x40963594, + 0x4096a7ba, + 0x409728a5, + 0x4097a6f7, + 0x40982309, + 0x4098ad00, + 0x40993604, + 0x4099a9c9, + 0x409a2962, + 0x409a9fd6, + 0x409b24fe, + 0x409ba529, + 0x409c37a5, + 0x409ca551, + 0x409d2776, + 0x409da744, + 0x409e239a, + 0x409ea7ef, + 0x409f27d7, + 0x409fa4f1, + 0x40a02817, + 0x40a0a711, + 0x40a1275f, + 0x40fa2f08, + 0x40faae64, + 0x40fb2ee7, + 0x40fbae7e, + 0x40fcaec6, + 0x40fd2e9f, + 0x40fda11a, + 0x40fe212e, + 0x41f430df, + 0x41f93171, + 0x41fe3064, + 0x41feb31a, + 0x41ff3448, + 0x420330f8, + 0x4208311a, + 0x4208b156, + 0x42093048, + 0x4209b190, + 0x420a309f, + 0x420ab07f, + 0x420b30bf, + 0x420bb138, + 0x420c3464, + 0x420cb24e, + 0x420d3301, + 0x420db338, + 0x4212336b, + 0x4217342b, + 0x4217b3ad, + 0x421c33cf, + 0x421f338a, + 0x422134dc, + 0x4226340e, + 0x422b34ba, + 0x422bb2dc, + 0x422c349c, + 0x422cb28f, + 0x422d3268, + 0x422db47b, + 0x422e32bb, + 0x423033ea, + 0x4230b352, 0x42310b85, 0x44320778, 0x44328787, @@ -670,108 +670,139 @@ const uint32_t kOpenSSLReasonValues[] = { 0x4439885b, 0x443a086e, 0x4832175c, - 0x4832976e, - 0x48331784, - 0x4833979d, - 0x4c3217da, - 0x4c3297ea, - 0x4c3317fd, - 0x4c33981d, + 0x48329846, + 0x4833185c, + 0x48339880, + 0x48341818, + 0x48349875, + 0x4835179f, + 0x483599ad, + 0x48361963, + 0x4836994c, + 0x483719c6, + 0x483797b6, + 0x483818b2, + 0x48389409, + 0x4839193b, + 0x483995b5, + 0x483a18c8, + 0x483a95c7, + 0x483b1803, + 0x483b97ec, + 0x483c1526, + 0x483c97cf, + 0x483d1904, + 0x483d977f, + 0x483e1913, + 0x483e9981, + 0x483f182d, + 0x483f9995, + 0x48401891, + 0x484097dd, + 0x484119d9, + 0x484198ed, + 0x484218d3, + 0x484292c7, + 0x4843176e, + 0x4c321a16, + 0x4c329a26, + 0x4c33177f, + 0x4c339a39, 0x4c3400b9, 0x4c3480f7, - 0x4c351829, - 0x4c359837, - 0x4c361853, - 0x4c369879, - 0x4c371888, - 0x4c379896, - 0x4c3818ab, - 0x4c3898b7, - 0x4c3918d7, - 0x4c399901, - 0x4c3a191a, - 0x4c3a9933, + 0x4c351a45, + 0x4c359a53, + 0x4c361a6f, + 0x4c369a95, + 0x4c371aa4, + 0x4c379ab2, + 0x4c381ac7, + 0x4c389ad3, + 0x4c391af3, + 0x4c399b1d, + 0x4c3a1b36, + 0x4c3a9b4f, 0x4c3b0635, - 0x4c3b994c, - 0x4c3c195e, - 0x4c3c996d, - 0x4c3d1986, + 0x4c3b9b68, + 0x4c3c1b7a, + 0x4c3c9b89, + 0x4c3d1ba2, 0x4c3d8d97, - 0x4c3e19f3, - 0x4c3e9995, - 0x4c3f1a15, + 0x4c3e1c0f, + 0x4c3e9bb1, + 0x4c3f1c31, 0x4c3f9732, - 0x4c4019ab, - 0x4c4097c6, - 0x4c4119e3, - 0x4c419866, - 0x4c4219cf, - 0x4c4297ae, - 0x50323a9c, - 0x5032baab, - 0x50333ab6, - 0x5033bac6, - 0x50343adf, - 0x5034baf9, - 0x50353b07, - 0x5035bb1d, - 0x50363b2f, - 0x5036bb45, - 0x50373b5e, - 0x5037bb71, - 0x50383b89, - 0x5038bb9a, - 0x50393baf, - 0x5039bbc3, - 0x503a3be3, - 0x503abbf9, - 0x503b3c11, - 0x503bbc23, - 0x503c3c3f, - 0x503cbc56, - 0x503d3c6f, - 0x503dbc85, - 0x503e3c92, - 0x503ebca8, - 0x503f3cba, + 0x4c401bc7, + 0x4c409a02, + 0x4c411bff, + 0x4c419a82, + 0x4c421beb, + 0x4c4299ea, + 0x50323cb8, + 0x5032bcc7, + 0x50333cd2, + 0x5033bce2, + 0x50343cfb, + 0x5034bd15, + 0x50353d23, + 0x5035bd39, + 0x50363d4b, + 0x5036bd61, + 0x50373d7a, + 0x5037bd8d, + 0x50383da5, + 0x5038bdb6, + 0x50393dcb, + 0x5039bddf, + 0x503a3dff, + 0x503abe15, + 0x503b3e2d, + 0x503bbe3f, + 0x503c3e5b, + 0x503cbe72, + 0x503d3e8b, + 0x503dbea1, + 0x503e3eae, + 0x503ebec4, + 0x503f3ed6, 0x503f83b3, - 0x50403ccd, - 0x5040bcdd, - 0x50413cf7, - 0x5041bd06, - 0x50423d20, - 0x5042bd3d, - 0x50433d4d, - 0x5043bd5d, - 0x50443d7a, + 0x50403ee9, + 0x5040bef9, + 0x50413f13, + 0x5041bf22, + 0x50423f3c, + 0x5042bf59, + 0x50433f69, + 0x5043bf79, + 0x50443f96, 0x50448469, - 0x50453d8e, - 0x5045bdac, - 0x50463dbf, - 0x5046bdd5, - 0x50473de7, - 0x5047bdfc, - 0x50483e22, - 0x5048be30, - 0x50493e43, - 0x5049be58, - 0x504a3e6e, - 0x504abe7e, - 0x504b3e9e, - 0x504bbeb1, - 0x504c3ed4, - 0x504cbf02, - 0x504d3f2f, - 0x504dbf4c, - 0x504e3f67, - 0x504ebf83, - 0x504f3f95, - 0x504fbfac, - 0x50503fbb, + 0x50453faa, + 0x5045bfc8, + 0x50463fdb, + 0x5046bff1, + 0x50474003, + 0x5047c018, + 0x5048403e, + 0x5048c04c, + 0x5049405f, + 0x5049c074, + 0x504a408a, + 0x504ac09a, + 0x504b40ba, + 0x504bc0cd, + 0x504c40f0, + 0x504cc11e, + 0x504d414b, + 0x504dc168, + 0x504e4183, + 0x504ec19f, + 0x504f41b1, + 0x504fc1c8, + 0x505041d7, 0x50508729, - 0x50513fce, - 0x5051bd6c, - 0x50523f14, + 0x505141ea, + 0x5051bf88, + 0x50524130, 0x583210b7, 0x5c329409, 0x5c331422, @@ -853,21 +884,21 @@ const uint32_t kOpenSSLReasonValues[] = { 0x78478b85, 0x78480b42, 0x7c321398, - 0x80321879, + 0x80321a95, 0x80328090, - 0x80333785, + 0x803339a1, 0x803380b9, - 0x80343794, - 0x8034b6fc, - 0x8035371a, - 0x8035b7a8, - 0x8036375c, - 0x8036b70b, - 0x8037374e, - 0x8037b6e9, - 0x8038376f, - 0x8038b72b, - 0x80393740, + 0x803439b0, + 0x8034b918, + 0x80353936, + 0x8035b9c4, + 0x80363978, + 0x8036b927, + 0x8037396a, + 0x8037b905, + 0x8038398b, + 0x8038b947, + 0x8039395c, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -1176,14 +1207,39 @@ const char kOpenSSLReasonStringData[] = "UNSUPPORTED_CIPHER\0" "UNSUPPORTED_ENCRYPTION\0" "BAD_PKCS7_VERSION\0" + "CERT_MUST_BE_RSA\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" + "CIPHER_NOT_INITIALIZED\0" + "CONTENT_AND_DATA_PRESENT\0" + "DECRYPT_ERROR\0" + "DIGEST_FAILURE\0" + "ERROR_ADDING_RECIPIENT\0" + "ERROR_SETTING_CIPHER\0" + "INVALID_NULL_POINTER\0" + "INVALID_SIGNED_DATA_TYPE\0" "NOT_PKCS7_SIGNED_DATA\0" "NO_CERTIFICATES_INCLUDED\0" + "NO_CONTENT\0" "NO_CRLS_INCLUDED\0" + "NO_RECIPIENT_MATCHES_CERTIFICATE\0" + "NO_SIGNATURES_ON_DATA\0" + "NO_SIGNERS\0" + "PKCS7_ADD_SIGNATURE_ERROR\0" + "PKCS7_ADD_SIGNER_ERROR\0" + "PKCS7_DATASIGN\0" + "SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE\0" + "SMIME_TEXT_ERROR\0" + "UNABLE_TO_FIND_MEM_BIO\0" + "UNABLE_TO_FIND_MESSAGE_DIGEST\0" + "UNKNOWN_DIGEST_TYPE\0" + "UNSUPPORTED_CIPHER_TYPE\0" + "UNSUPPORTED_CONTENT_TYPE\0" + "WRONG_CONTENT_TYPE\0" + "WRONG_PKCS7_TYPE\0" "AMBIGUOUS_FRIENDLY_NAME\0" "BAD_ITERATION_COUNT\0" "BAD_PKCS12_DATA\0" "BAD_PKCS12_VERSION\0" - "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" "CRYPT_ERROR\0" "ENCRYPT_ERROR\0" "ERROR_SETTING_CIPHER_PARAMS\0" diff --git a/include/openssl/base.h b/include/openssl/base.h index 76da3809e2..68e12912ab 100644 --- a/include/openssl/base.h +++ b/include/openssl/base.h @@ -359,6 +359,8 @@ typedef struct pkcs7_digest_st PKCS7_DIGEST; typedef struct pkcs7_encrypt_st PKCS7_ENCRYPT; typedef struct pkcs7_recip_info_st PKCS7_RECIP_INFO; typedef struct pkcs7_signer_info_st PKCS7_SIGNER_INFO; +typedef struct pkcs7_issuer_and_serial_st PKCS7_ISSUER_AND_SERIAL; +typedef struct pkcs7_enc_content_st PKCS7_ENC_CONTENT; typedef struct pkcs12_st PKCS12; typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; typedef struct private_key_st X509_PKEY; diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h index 3562c22820..9afa70b592 100644 --- a/include/openssl/pkcs7.h +++ b/include/openssl/pkcs7.h @@ -158,6 +158,98 @@ struct pkcs7_signed_st { STACK_OF(PKCS7_SIGNER_INFO) *signer_info; }; +// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-9.2 +// +// SignerInfo ::= SEQUENCE { +// version Version, +// issuerAndSerialNumber IssuerAndSerialNumber, +// digestAlgorithm DigestAlgorithmIdentifier, +// authenticatedAttributes +// [0] IMPLICIT Attributes OPTIONAL, +// digestEncryptionAlgorithm +// DigestEncryptionAlgorithmIdentifier, +// encryptedDigest EncryptedDigest, +// unauthenticatedAttributes +// [1] IMPLICIT Attributes OPTIONAL } +// +// EncryptedDigest ::= OCTET STRING +struct pkcs7_signer_info_st { + ASN1_INTEGER *version; + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; + EVP_PKEY *pkey; // NOTE: |pkey| is not seriliazed. +}; + +// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-11.1 +// +// SignedAndEnvelopedData ::= SEQUENCE { +// version Version, +// recipientInfos RecipientInfos, +// digestAlgorithms DigestAlgorithmIdentifiers, +// encryptedContentInfo EncryptedContentInfo, +// certificates +// [0] IMPLICIT ExtendedCertificatesAndCertificates +// OPTIONAL, +// crls +// [1] IMPLICIT CertificateRevocationLists OPTIONAL, +// signerInfos SignerInfos } +struct pkcs7_sign_envelope_st { + ASN1_INTEGER *version; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + STACK_OF(X509_ALGOR) *md_algs; + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(X509) *cert; + STACK_OF(X509_CRL) *crl; + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; +}; + +// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-10.1 +// +// EnvelopedData ::= SEQUENCE { +// version Version, +// recipientInfos RecipientInfos, +// encryptedContentInfo EncryptedContentInfo } +// +// RecipientInfos ::= SET OF RecipientInfo +struct pkcs7_envelope_st { + ASN1_INTEGER *version; + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; +}; + +// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-10.2 +// +// RecipientInfo ::= SEQUENCE { +// version Version, +// issuerAndSerialNumber IssuerAndSerialNumber, +// keyEncryptionAlgorithm +// +// KeyEncryptionAlgorithmIdentifier, +// encryptedKey EncryptedKey } +// +// EncryptedKey ::= OCTET STRING +struct pkcs7_recip_info_st { + ASN1_INTEGER *version; + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; // NOTE: |cert| is not serialized +}; + +// ASN.1 defined here https://datatracker.ietf.org/doc/html/rfc2315#section-6.7 +// +// IssuerAndSerialNumber ::= SEQUENCE { +// issuer Name, +// serialNumber CertificateSerialNumber } +struct pkcs7_issuer_and_serial_st { + X509_NAME *issuer; + ASN1_INTEGER *serial; +}; + // Only declare ASN1 functions or define stacks publibly if needed by supported // projects that depend on them. DECLARE_ASN1_FUNCTIONS(PKCS7) @@ -169,7 +261,7 @@ DEFINE_STACK_OF(PKCS7_SIGNER_INFO) // PKCS7_dup returns a newly allocated copy of |p7| without deep-copying // internal references. -OPENSSL_EXPORT PKCS7 *PKCS7_dup(PKCS7 * p7); +OPENSSL_EXPORT PKCS7 *PKCS7_dup(PKCS7 *p7); // d2i_PKCS7_bio behaves like |d2i_PKCS7| but reads the input from |bio|. If // the length of the object is indefinite the full contents of |bio| are read. @@ -184,8 +276,8 @@ OPENSSL_EXPORT int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7); // PKCS7_get_signed_attribute returns a pointer to the first signed attribute // from |si| with NID |nid| if one is present, else NULL. -OPENSSL_EXPORT ASN1_TYPE *PKCS7_get_signed_attribute(const PKCS7_SIGNER_INFO *si, - int nid); +OPENSSL_EXPORT ASN1_TYPE *PKCS7_get_signed_attribute( + const PKCS7_SIGNER_INFO *si, int nid); // PKCS7_get_signer_info returns |p7|'s attached PKCS7_SIGNER_INFO if present // and |p7| is of a relevant type, else NULL. This function only pertains to @@ -199,20 +291,20 @@ OPENSSL_EXPORT int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); // PKCS7_SIGNER_INFO_set attaches the other parameters to |p7i|, returning 1 on // success and 0 on error or if specified parameters are inapplicable to -// signing. Only EC, DH, and RSA |pkey|s are supported. |pkey| is assigned to -// |p7i| and its reference count is incremented. +// signing. Only EC, DH, and RSA |pkey|s are supported. |pkey|'s reference +// count is incremented, but neither |x509|'s nor |dgst|'s is. OPENSSL_EXPORT int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst); // PKCS7_add_certificate adds |x509| to |p7|'s certificate stack, incrementing // |x509|'s reference count. It returns 1 on success and 0 on failure or if // |p7| isn't of an applicable type: signedData and signedAndEnvelopedData. -OPENSSL_EXPORT int PKCS7_add_certificate(PKCS7 *p7, X509 * x509); +OPENSSL_EXPORT int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); // PKCS7_add_crl adds |x509| to |p7|'s CRL stack, incrementing |x509|'s // reference count. It returns 1 on success and 0 on failure or if |p7| isn't // of an applicable type: signedData and signedAndEnvelopedData. -OPENSSL_EXPORT int PKCS7_add_crl(PKCS7 *p7, X509_CRL * x509); +OPENSSL_EXPORT int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); // PKCS7_add_recipient_info adds |ri| to |p7|, returning 1 on succes or 0 if // |p7| is of an inapplicable type: envelopedData and signedAndEnvelopedData. @@ -226,15 +318,15 @@ OPENSSL_EXPORT int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); // returns 1 on success and 0 on failure. OPENSSL_EXPORT int PKCS7_content_new(PKCS7 *p7, int nid); -// PKCS7_set_cipher sets |cipher| on |p7| for applicable types of |p7|. It -// returns 1 on success and 0 on failure or if |p7| is not an applicable type: -// envelopedData and signedAndEnvelopedData. -OPENSSL_EXPORT int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); +// PKCS7_set_content sets |p7_data| as content on |p7| for applicaple types of +// |p7|. It frees any existing content on |p7|, returning 1 on success and 0 on +// failure. +OPENSSL_EXPORT int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); // PKCS7_set_content sets |p7_data| as content on |p7| for applicable types of // |p7|: signedData and digestData. |p7_data| may be NULL. It frees any // existing content on |p7|, returning 1 on success and 0 on failure. -OPENSSL_EXPORT int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +OPENSSL_EXPORT int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); // PKCS7_set_type instantiates |p7| as type |type|. It returns 1 on success and // 0 on failure or if |type| is not a valid PKCS7 content type. @@ -272,9 +364,10 @@ OPENSSL_EXPORT int PKCS7_type_is_signed(const PKCS7 *p7); // signedAndEnveloped OPENSSL_EXPORT int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7); - // PKCS7_sign [Deprecated] // +// TODO [childw] update this +// // Only |PKCS7_DETACHED| and a combination of // "PKCS7_DETACHED|PKCS7_BINARY|PKCS7_NOATTR|PKCS7_PARTIAL" is supported. // See |PKCS7_sign| for more details. @@ -312,7 +405,8 @@ OPENSSL_EXPORT int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7); // |PKCS7_sign|. #define PKCS7_STREAM 0x1000 -// The following flags are used with |PKCS7_verify| (not implemented). +// The following flags are used with |PKCS7_verify| (not implemented) in +// OpenSSL, but are not implemented by AWS-LC. #define PKCS7_NOSIGS 0x4 #define PKCS7_NOCHAIN 0x8 #define PKCS7_NOINTERN 0x10 @@ -320,6 +414,8 @@ OPENSSL_EXPORT int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7); // PKCS7_sign can operate in two modes to provide some backwards compatibility: // +// TODO [childw] update this +// // The first mode assembles |certs| into a PKCS#7 signed data ContentInfo with // external data and no signatures. It returns a newly-allocated |PKCS7| on // success or NULL on error. |sign_cert| and |pkey| must be NULL. |data| is @@ -339,6 +435,22 @@ OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7 *PKCS7_sign(X509 *sign_cert, STACK_OF(X509) *certs, BIO *data, int flags); +// TODO [childw] +// - tacitly enforce PKCS7_NOATTR +// - support NOVERIFY +OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_verify(PKCS7 *p7, + STACK_OF(X509) *certs, + X509_STORE *store, + BIO *indata, BIO *out, + int flags); + +// SMIME_read_PKCS7 is a no-op and returns NULL +OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7 *SMIME_read_PKCS7(BIO *in, BIO **bcont); + +// SMIME_write_PKCS7 is a no-op and returns 0 +OPENSSL_EXPORT OPENSSL_DEPRECATED int SMIME_write_PKCS7(BIO *out, PKCS7 *p7, + BIO *data, int flags); + // PKCS7_is_detached returns 0 if |p7| has attached content and 1 otherwise. OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_is_detached(PKCS7 *p7); @@ -353,21 +465,27 @@ OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); // PKCS7_set_digest sets |p7|'s digest to |md|. It returns 1 on success and 0 if // |p7| is of the wrong content type. -OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); +OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_set_digest(PKCS7 *p7, + const EVP_MD *md); // PKCS7_get_recipient_info returns a pointer to a stack containing |p7|'s // |PKCS7_RECIP_INFO| or NULL if none are present. -OPENSSL_EXPORT OPENSSL_DEPRECATED STACK_OF(PKCS7_RECIP_INFO) *PKCS7_get_recipient_info(PKCS7 *p7); +OPENSSL_EXPORT OPENSSL_DEPRECATED STACK_OF(PKCS7_RECIP_INFO) * +PKCS7_get_recipient_info(PKCS7 *p7); // PKCS7_add_recipient allocates a new |PCKS7_RECEPIENT_INFO|, adds |x509| to it // and returns that |PCKS7_RECEPIENT_INFO|. -OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7_RECIP_INFO *PKCS7_add_recipient( + PKCS7 *p7, X509 *x509); // PKCS7_encrypt encrypts the contents of |in| with |cipher| and adds |certs| as // recipient infos and returns an encrypted |PKCS7| or NULL on failed // encryption. |flags| is ignored. We only perform key encryption using RSA, so // |certs| must use RSA public keys. -OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, int flags); +OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, + BIO *in, + const EVP_CIPHER *cipher, + int flags); // PKCS7_decrypt decrypts |p7| with |pkey| and writes the plaintext to |data|. // If |cert| is present, it's public key is checked against |pkey| and |p7|'s @@ -377,7 +495,9 @@ OPENSSL_EXPORT OPENSSL_DEPRECATED PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BI // NOTE: If |p7| was encrypted with a stream cipher, this operation may return 1 // even on decryption failure. The reason for this is detailed in RFC 3218 and // comments in the |PKCS7_decrypt| source. -OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags); +OPENSSL_EXPORT OPENSSL_DEPRECATED int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, + X509 *cert, BIO *data, + int flags); #if defined(__cplusplus) } // extern C @@ -386,6 +506,7 @@ extern "C++" { BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(PKCS7, PKCS7_free) +BORINGSSL_MAKE_DELETER(PKCS7_SIGNER_INFO, PKCS7_SIGNER_INFO_free) BSSL_NAMESPACE_END } // extern C++