-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove custom PKCS7 ASN1 functions, add new structs (#1726)
### Issues: Resolves #CryptoAlg-2493 ### Description of changes: This PR is the first in a series implementing Ruby's supported subset of the PKCS7 standard. To do this, we remove AWS-LC's customized ASN.1 serialization logic and delegate to `asn1.h` and `asn1t.h`. We also update the various `PKCS_type_is_*` no-op functions to actually check the input's type. The PKCS7 tests currently contain a test signedData structure that is encoded using BER. Because our `ASN1_get_object` currently [disallows](https://github.com/aws/aws-lc/blob/8080ce32b118746475c718d14a609bd1325166e1/crypto/asn1/asn1_lib.c#L136) indefinite-length BER, we need to modify `d2i_PKCS7` to detect and convert BER (if present) into DER before parsing. This allows us to retain backwards compatibility with BER-encoded PKCS7 objects. Please see the PR description on GitHub for more discussion on this topic. The next PR in this series will implement the various getters, setters, and allocation functions needed to support CRruby with testing for each. Please see PR #1780 for an idea of what that will look like.
- Loading branch information
1 parent
f3344b8
commit 621bceb
Showing
7 changed files
with
449 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <openssl/pkcs7.h> | ||
|
||
#include <openssl/asn1t.h> | ||
#include <openssl/pem.h> | ||
|
||
#include "internal.h" | ||
#include "../internal.h" | ||
#include "../bytestring/internal.h" | ||
|
||
ASN1_ADB_TEMPLATE(p7default) = ASN1_EXP_OPT(PKCS7, d.other, ASN1_ANY, 0); | ||
|
||
ASN1_ADB(PKCS7) = { | ||
ADB_ENTRY(NID_pkcs7_data, ASN1_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING, 0)), | ||
ADB_ENTRY(NID_pkcs7_signed, ASN1_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)), | ||
ADB_ENTRY(NID_pkcs7_enveloped, ASN1_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)), | ||
ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)), | ||
ADB_ENTRY(NID_pkcs7_digest, ASN1_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)), | ||
ADB_ENTRY(NID_pkcs7_encrypted, ASN1_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0)) | ||
} ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL); | ||
|
||
ASN1_SEQUENCE(PKCS7) = { | ||
ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT), | ||
ASN1_ADB_OBJECT(PKCS7) | ||
} ASN1_SEQUENCE_END(PKCS7) | ||
|
||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(PKCS7) | ||
|
||
PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len) { | ||
uint8_t *der_bytes = NULL; | ||
PKCS7 *ret = NULL; | ||
CBS cbs, cbs_der; | ||
|
||
if (!in) { | ||
return NULL; | ||
} | ||
|
||
CBS_init(&cbs, *in, len); | ||
// |CBS_asn1_ber_to_der| will allocate memory and point |der_bytes| to it. | ||
// we're responsible for freeing this below. | ||
if (!CBS_asn1_ber_to_der(&cbs, &cbs_der, &der_bytes)) { | ||
goto err; | ||
} | ||
|
||
// |CBS_asn1_ber_to_der| will set |der_bytes| to NULL if it doesn't detect | ||
// any convertible BER elements in |in|. | ||
if (der_bytes == NULL) { | ||
ret = (PKCS7 *) ASN1_item_d2i( | ||
(ASN1_VALUE **) a, in, len, | ||
ASN1_ITEM_rptr(PKCS7) | ||
); | ||
} else { | ||
// |ASN1_item_d2i| will increment the input pointer by |der_len| length, so | ||
// save off another pointer so we can free |der_bytes| at the end of this | ||
// function. | ||
uint8_t *der_bytes_ptr = der_bytes; | ||
size_t der_len = CBS_len(&cbs_der); | ||
ret = (PKCS7 *) ASN1_item_d2i( | ||
(ASN1_VALUE **) a, (const uint8_t**) &der_bytes_ptr, | ||
der_len, ASN1_ITEM_rptr(PKCS7) | ||
); | ||
// Advance |*in| by however many bytes |ASN1_item_d2i| advanced | ||
// |der_bytes_ptr| | ||
*in += der_bytes_ptr - der_bytes; | ||
} | ||
|
||
err: | ||
OPENSSL_free(der_bytes); | ||
der_bytes = NULL; | ||
return ret; | ||
} | ||
|
||
int i2d_PKCS7(PKCS7 *a, unsigned char **out) { | ||
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(PKCS7)); | ||
} | ||
|
||
IMPLEMENT_ASN1_DUP_FUNCTION(PKCS7) | ||
|
||
ASN1_SEQUENCE(PKCS7_SIGNED) = { | ||
ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER), | ||
ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR), | ||
ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7), | ||
ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0), | ||
ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1), | ||
ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO) | ||
} ASN1_SEQUENCE_END(PKCS7_SIGNED) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED) | ||
|
||
ASN1_SEQUENCE(PKCS7_ISSUER_AND_SERIAL) = { | ||
ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, issuer, X509_NAME), | ||
ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, serial, ASN1_INTEGER) | ||
} ASN1_SEQUENCE_END(PKCS7_ISSUER_AND_SERIAL) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) | ||
|
||
// Minor tweak to operation: free up X509. | ||
static int recip_info_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | ||
void *exarg) | ||
{ | ||
if (operation == ASN1_OP_FREE_POST) { | ||
PKCS7_RECIP_INFO *ri = (PKCS7_RECIP_INFO *)*pval; | ||
X509_free(ri->cert); | ||
} | ||
return 1; | ||
} | ||
|
||
ASN1_SEQUENCE_cb(PKCS7_RECIP_INFO, recip_info_cb) = { | ||
ASN1_SIMPLE(PKCS7_RECIP_INFO, version, ASN1_INTEGER), | ||
ASN1_SIMPLE(PKCS7_RECIP_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), | ||
ASN1_SIMPLE(PKCS7_RECIP_INFO, key_enc_algor, X509_ALGOR), | ||
ASN1_SIMPLE(PKCS7_RECIP_INFO, enc_key, ASN1_OCTET_STRING) | ||
} ASN1_SEQUENCE_END_cb(PKCS7_RECIP_INFO, PKCS7_RECIP_INFO) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) | ||
|
||
// Minor tweak to operation: free up EVP_PKEY. | ||
static int signer_info_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | ||
void *exarg) | ||
{ | ||
PKCS7_SIGNER_INFO *si = (PKCS7_SIGNER_INFO *)*pval; | ||
if (operation == ASN1_OP_FREE_POST) { | ||
EVP_PKEY_free(si->pkey); | ||
} | ||
return 1; | ||
} | ||
|
||
ASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, signer_info_cb) = { | ||
ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER), | ||
ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), | ||
ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR), | ||
/* NB this should be a SET OF but we use a SEQUENCE OF so the | ||
* original order * is retained when the structure is reencoded. | ||
* Since the attributes are implicitly tagged this will not affect | ||
* the encoding. | ||
*/ | ||
ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0), | ||
ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR), | ||
ASN1_SIMPLE(PKCS7_SIGNER_INFO, enc_digest, ASN1_OCTET_STRING), | ||
ASN1_IMP_SET_OF_OPT(PKCS7_SIGNER_INFO, unauth_attr, X509_ATTRIBUTE, 1) | ||
} ASN1_SEQUENCE_END_cb(PKCS7_SIGNER_INFO, PKCS7_SIGNER_INFO) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) | ||
|
||
ASN1_SEQUENCE(PKCS7_ENC_CONTENT) = { | ||
ASN1_SIMPLE(PKCS7_ENC_CONTENT, content_type, ASN1_OBJECT), | ||
ASN1_SIMPLE(PKCS7_ENC_CONTENT, algorithm, X509_ALGOR), | ||
ASN1_IMP_OPT(PKCS7_ENC_CONTENT, enc_data, ASN1_OCTET_STRING, 0) | ||
} ASN1_SEQUENCE_END(PKCS7_ENC_CONTENT) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) | ||
|
||
ASN1_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { | ||
ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, version, ASN1_INTEGER), | ||
ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), | ||
ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, md_algs, X509_ALGOR), | ||
ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, enc_data, PKCS7_ENC_CONTENT), | ||
ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, cert, X509, 0), | ||
ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, crl, X509_CRL, 1), | ||
ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, signer_info, PKCS7_SIGNER_INFO) | ||
} ASN1_SEQUENCE_END(PKCS7_SIGN_ENVELOPE) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) | ||
|
||
ASN1_SEQUENCE(PKCS7_ENCRYPT) = { | ||
ASN1_SIMPLE(PKCS7_ENCRYPT, version, ASN1_INTEGER), | ||
ASN1_SIMPLE(PKCS7_ENCRYPT, enc_data, PKCS7_ENC_CONTENT) | ||
} ASN1_SEQUENCE_END(PKCS7_ENCRYPT) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENCRYPT) | ||
|
||
ASN1_SEQUENCE(PKCS7_DIGEST) = { | ||
ASN1_SIMPLE(PKCS7_DIGEST, version, ASN1_INTEGER), | ||
ASN1_SIMPLE(PKCS7_DIGEST, md, X509_ALGOR), | ||
ASN1_SIMPLE(PKCS7_DIGEST, contents, PKCS7), | ||
ASN1_SIMPLE(PKCS7_DIGEST, digest, ASN1_OCTET_STRING) | ||
} ASN1_SEQUENCE_END(PKCS7_DIGEST) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) | ||
|
||
ASN1_SEQUENCE(PKCS7_ENVELOPE) = { | ||
ASN1_SIMPLE(PKCS7_ENVELOPE, version, ASN1_INTEGER), | ||
ASN1_SET_OF(PKCS7_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), | ||
ASN1_SIMPLE(PKCS7_ENVELOPE, enc_data, PKCS7_ENC_CONTENT) | ||
} ASN1_SEQUENCE_END(PKCS7_ENVELOPE) | ||
|
||
IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENVELOPE) |
Oops, something went wrong.