Skip to content

Commit

Permalink
Implement PKCS7_verify, update PKCS7_sign (#1993)
Browse files Browse the repository at this point in the history
This PR implements `PKCS7_verify` for verifying signedData-type PKCS7 messages.
It also adds another mode of operation to `PKCS7_sign` for compatibility with
Ruby. Flags for these functions are documented in header comments.

We also remove most support for signedAndEnveloped-type PKCS7 messges, as
they're not required by Ruby's tests beyond a few getters/setters.  OpenSSL
supports this type in [`PKCS7_decrypt`][1] but not [`PKCS7_verify`][2],
[`PKCS7_sign`][3], nor [`PKCS7_encrypt`][4], so it's unclear what (if any) role
signedAndEnveloped types have with respect to these functions. If we wish to
revisit support for this type in the future, I have a branch [here][5]
implementing encrypt/decrypt/sign/verify support and [a test][6].

Lastly, we externalize some of the previously internal PKCS7 ASN.1/struct
definitions as ruby's source accesses some of their members directly.


[1]: https://github.com/openssl/openssl/blob/f7c4d4519cd5daad5335b39ba7a3c864c65bf6ee/crypto/pkcs7/pk7_smime.c#L490
[2]: https://github.com/openssl/openssl/blob/f7c4d4519cd5daad5335b39ba7a3c864c65bf6ee/crypto/pkcs7/pk7_smime.c#L236
[3]: https://github.com/openssl/openssl/blob/f7c4d4519cd5daad5335b39ba7a3c864c65bf6ee/crypto/pkcs7/pk7_smime.c#L36
[4]: https://github.com/openssl/openssl/blob/f7c4d4519cd5daad5335b39ba7a3c864c65bf6ee/crypto/pkcs7/pk7_smime.c#L442
[5]: https://github.com/WillChilds-Klein/aws-lc/tree/pkcs7-signed-and-enveloped/
[6]: https://github.com/WillChilds-Klein/aws-lc/blob/pkcs7-signed-and-enveloped/crypto/pkcs7/pkcs7_test.cc#L1953-L1984
  • Loading branch information
WillChilds-Klein authored Dec 9, 2024
1 parent d681431 commit 96de127
Show file tree
Hide file tree
Showing 13 changed files with 1,307 additions and 665 deletions.
31 changes: 31 additions & 0 deletions crypto/err/pkcs7.errordata
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions crypto/pkcs7/bio/bio_cipher_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<CipherParams> {};
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion crypto/pkcs7/bio/cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
98 changes: 4 additions & 94 deletions crypto/pkcs7/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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.
int pkcs7_final(PKCS7 *p7, BIO *data);

#if defined(__cplusplus)
} // extern C
#endif
Expand Down
Loading

0 comments on commit 96de127

Please sign in to comment.