static int test_EVP_DigestVerifyInitFromAlgorithm(void) { int ret = 0; CBS cert, cert_body, tbs_cert, algorithm, signature; uint8_t padding; X509_ALGOR *algor = NULL; const uint8_t *derp; EVP_PKEY *pkey = NULL; EVP_MD_CTX md_ctx; EVP_MD_CTX_init(&md_ctx); CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert)); if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) || CBS_len(&cert) != 0 || !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) || !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) || CBS_len(&cert_body) != 0) { fprintf(stderr, "Failed to parse certificate\n"); goto out; } /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the leading phase byte is just a zero. */ if (!CBS_get_u8(&signature, &padding) || padding != 0) { fprintf(stderr, "Invalid signature padding\n"); goto out; } derp = CBS_data(&algorithm); if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) { fprintf(stderr, "Failed to parse algorithm\n"); } pkey = load_example_rsa_key(); if (pkey == NULL || !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) || !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert), CBS_len(&tbs_cert)) || !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature))) { goto out; } ret = 1; out: if (!ret) { BIO_print_errors_fp(stderr); } EVP_MD_CTX_cleanup(&md_ctx); if (pkey) { EVP_PKEY_free(pkey); } return ret; }
DSA *DSA_parse_private_key(CBS *cbs) { DSA *ret = DSA_new(); if (ret == NULL) { return NULL; } CBS child; uint64_t version; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&child, &version)) { OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); goto err; } if (version != 0) { OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION); goto err; } if (!parse_integer(&child, &ret->p) || !parse_integer(&child, &ret->q) || !parse_integer(&child, &ret->g) || !parse_integer(&child, &ret->pub_key) || !parse_integer(&child, &ret->priv_key) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); goto err; } return ret; err: DSA_free(ret); return NULL; }
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage, unsigned outer_tag, unsigned inner_tag) { assert(!(outer_tag & CBS_ASN1_CONSTRUCTED)); assert(!(inner_tag & CBS_ASN1_CONSTRUCTED)); assert(is_string_type(inner_tag)); if (CBS_peek_asn1_tag(in, outer_tag)) { /* Normal implicitly-tagged string. */ *out_storage = NULL; return CBS_get_asn1(in, out, outer_tag); } /* Otherwise, try to parse an implicitly-tagged constructed string. * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep * of nesting. */ CBB result; CBS child; if (!CBB_init(&result, CBS_len(in)) || !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) { goto err; } while (CBS_len(&child) > 0) { CBS chunk; if (!CBS_get_asn1(&child, &chunk, inner_tag) || !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) { goto err; } } uint8_t *data; size_t len; if (!CBB_finish(&result, &data, &len)) { goto err; } CBS_init(out, data, len); *out_storage = data; return 1; err: CBB_cleanup(&result); return 0; }
EVP_PKEY *EVP_parse_public_key(CBS *cbs) { // Parse the SubjectPublicKeyInfo. CBS spki, algorithm, key; int type; uint8_t padding; if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || !parse_key_type(&algorithm, &type) || !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) || CBS_len(&spki) != 0 || // Every key type defined encodes the key as a byte string with the same // conversion to BIT STRING. !CBS_get_u8(&key, &padding) || padding != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL || !EVP_PKEY_set_type(ret, type)) { goto err; } // Call into the type-specific SPKI decoding function. if (ret->ameth->pub_decode == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); goto err; } if (!ret->ameth->pub_decode(ret, &algorithm, &key)) { goto err; } return ret; err: EVP_PKEY_free(ret); return NULL; }
EVP_PKEY *EVP_parse_private_key(CBS *cbs) { // Parse the PrivateKeyInfo. CBS pkcs8, algorithm, key; uint64_t version; int type; if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&pkcs8, &version) || version != 0 || !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || !parse_key_type(&algorithm, &type) || !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return NULL; } // A PrivateKeyInfo ends with a SET of Attributes which we ignore. // Set up an |EVP_PKEY| of the appropriate type. EVP_PKEY *ret = EVP_PKEY_new(); if (ret == NULL || !EVP_PKEY_set_type(ret, type)) { goto err; } // Call into the type-specific PrivateKeyInfo decoding function. if (ret->ameth->priv_decode == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); goto err; } if (!ret->ameth->priv_decode(ret, &algorithm, &key)) { goto err; } return ret; err: EVP_PKEY_free(ret); return NULL; }
RSA *RSA_parse_public_key(CBS *cbs) { RSA *ret = RSA_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !parse_integer(&child, &ret->n) || !parse_integer(&child, &ret->e) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); RSA_free(ret); return NULL; } return ret; }
DSA_SIG *DSA_SIG_parse(CBS *cbs) { DSA_SIG *ret = DSA_SIG_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !parse_integer(&child, &ret->r) || !parse_integer(&child, &ret->s) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); DSA_SIG_free(ret); return NULL; } return ret; }
/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7 * SignedData blob from |cbs| and sets |*out| to point to the rest of the * input. If the input is in BER format, then |*der_bytes| will be set to a * pointer that needs to be freed by the caller once they have finished * processing |*out| (which will be pointing into |*der_bytes|). * * It returns one on success or zero on error. On error, |*der_bytes| is * NULL. */ static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) { size_t der_len; CBS in, content_info, content_type, wrapped_signed_data, signed_data; uint64_t version; /* The input may be in BER format. */ *der_bytes = NULL; if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) { return 0; } if (*der_bytes != NULL) { CBS_init(&in, *der_bytes, der_len); } else { CBS_init(&in, CBS_data(cbs), CBS_len(cbs)); } /* See https://tools.ietf.org/html/rfc2315#section-7 */ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) { goto err; } if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) { OPENSSL_PUT_ERROR(X509, pkcs7_parse_header, X509_R_NOT_PKCS7_SIGNED_DATA); goto err; } /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ if (!CBS_get_asn1(&content_info, &wrapped_signed_data, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&signed_data, &version) || !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) || !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { goto err; } if (version < 1) { OPENSSL_PUT_ERROR(X509, pkcs7_parse_header, X509_R_BAD_PKCS7_VERSION); goto err; } CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data)); return 1; err: if (*der_bytes) { OPENSSL_free(*der_bytes); *der_bytes = NULL; } return 0; }
ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) { ECDSA_SIG *ret = ECDSA_SIG_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !BN_parse_asn1_unsigned(&child, ret->r) || !BN_parse_asn1_unsigned(&child, ret->s) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); ECDSA_SIG_free(ret); return NULL; } return ret; }
static int parse_key_type(CBS *cbs, int *out_type) { CBS oid; if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { return 0; } for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) { const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; if (CBS_len(&oid) == method->oid_len && OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { *out_type = method->pkey_id; return 1; } } return 0; }
DSA *DSA_parse_public_key(CBS *cbs) { DSA *ret = DSA_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !parse_integer(&child, &ret->pub_key) || !parse_integer(&child, &ret->p) || !parse_integer(&child, &ret->q) || !parse_integer(&child, &ret->g) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR); DSA_free(ret); return NULL; } return ret; }
RSA *RSA_parse_private_key(CBS *cbs) { BN_CTX *ctx = NULL; RSA *ret = RSA_new(); if (ret == NULL) { return NULL; } CBS child; uint64_t version; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&child, &version)) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); goto err; } if (version != kVersionTwoPrime) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION); goto err; } if (!parse_integer(&child, &ret->n) || !parse_integer(&child, &ret->e) || !parse_integer(&child, &ret->d) || !parse_integer(&child, &ret->p) || !parse_integer(&child, &ret->q) || !parse_integer(&child, &ret->dmp1) || !parse_integer(&child, &ret->dmq1) || !parse_integer(&child, &ret->iqmp)) { goto err; } if (CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); goto err; } BN_CTX_free(ctx); return ret; err: BN_CTX_free(ctx); RSA_free(ret); return NULL; }
// num_elements parses one SEQUENCE from |in| and returns the number of elements // in it. On parse error, it returns zero. static size_t num_elements(const uint8_t *in, size_t in_len) { CBS cbs, sequence; CBS_init(&cbs, in, (size_t)in_len); if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) { return 0; } size_t count = 0; while (CBS_len(&sequence) > 0) { if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) { return 0; } count++; } return count; }
static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { // Per RFC 3447, A.1, the parameters have type NULL. CBS null; if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || CBS_len(&null) != 0 || CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } RSA *rsa = RSA_parse_private_key(key); if (rsa == NULL || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); RSA_free(rsa); return 0; } EVP_PKEY_assign_RSA(out, rsa); return 1; }
/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on * success or NULL on error. The |r| and |mont| fields of the result are set to * NULL. */ static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) { RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime)); if (ret == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); return 0; } memset(ret, 0, sizeof(RSA_additional_prime)); CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !parse_integer(&child, &ret->prime) || !parse_integer(&child, &ret->exp) || !parse_integer(&child, &ret->coeff) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); RSA_additional_prime_free(ret); return NULL; } return ret; }
static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { // See RFC 3279, section 2.3.1. // The parameters must be NULL. CBS null; if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || CBS_len(&null) != 0 || CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } RSA *rsa = RSA_parse_public_key(key); if (rsa == NULL || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); RSA_free(rsa); return 0; } EVP_PKEY_assign_RSA(out, rsa); return 1; }
/* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and * positions |*out_tbs_cert| to cover the TBSCertificate, starting at the * subjectPublicKeyInfo. */ static int ssl_cert_skip_to_spki(const CBS *in, CBS *out_tbs_cert) { /* From RFC 5280, section 4.1 * Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } * TBSCertificate ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * serialNumber CertificateSerialNumber, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo, * ... } */ CBS buf = *in; CBS toplevel; if (!CBS_get_asn1(&buf, &toplevel, CBS_ASN1_SEQUENCE) || CBS_len(&buf) != 0 || !CBS_get_asn1(&toplevel, out_tbs_cert, CBS_ASN1_SEQUENCE) || /* version */ !CBS_get_optional_asn1( out_tbs_cert, NULL, NULL, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) || /* serialNumber */ !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_INTEGER) || /* signature algorithm */ !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) || /* issuer */ !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) || /* validity */ !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) || /* subject */ !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE)) { return 0; } return 1; }
int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) { CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) || CBS_len(&child) == 0) { OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); return 0; } if (CBS_data(&child)[0] & 0x80) { OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } /* INTEGERs must be minimal. */ if (CBS_data(&child)[0] == 0x00 && CBS_len(&child) > 1 && !(CBS_data(&child)[1] & 0x80)) { OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); return 0; } return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL; }
static RSA *parse_public_key(CBS *cbs, int buggy) { RSA *ret = RSA_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !parse_integer_buggy(&child, &ret->n, buggy) || !parse_integer(&child, &ret->e) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); RSA_free(ret); return NULL; } if (!BN_is_odd(ret->e) || BN_num_bits(ret->e) < 2) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); RSA_free(ret); return NULL; } return ret; }
int ssl_cert_check_digital_signature_key_usage(const CBS *in) { CBS buf = *in; CBS tbs_cert, outer_extensions; int has_extensions; if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) || /* subjectPublicKeyInfo */ !CBS_get_asn1(&tbs_cert, NULL, CBS_ASN1_SEQUENCE) || /* issuerUniqueID */ !CBS_get_optional_asn1( &tbs_cert, NULL, NULL, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) || /* subjectUniqueID */ !CBS_get_optional_asn1( &tbs_cert, NULL, NULL, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) || !CBS_get_optional_asn1( &tbs_cert, &outer_extensions, &has_extensions, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) { goto parse_err; } if (!has_extensions) { return 1; } CBS extensions; if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) { goto parse_err; } while (CBS_len(&extensions) > 0) { CBS extension, oid, contents; if (!CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) || (CBS_peek_asn1_tag(&extension, CBS_ASN1_BOOLEAN) && !CBS_get_asn1(&extension, NULL, CBS_ASN1_BOOLEAN)) || !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) || CBS_len(&extension) != 0) { goto parse_err; } static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f}; if (CBS_len(&oid) != sizeof(kKeyUsageOID) || OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) != 0) { continue; } CBS bit_string; if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) || CBS_len(&contents) != 0) { goto parse_err; } /* This is the KeyUsage extension. See * https://tools.ietf.org/html/rfc5280#section-4.2.1.3 */ if (!CBS_is_valid_asn1_bitstring(&bit_string)) { goto parse_err; } if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING); return 0; } return 1; } /* No KeyUsage extension found. */ return 1; parse_err: OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); return 0; }
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a * PKCS#12 structure. */ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth, struct pkcs12_context *ctx) { CBS content_type, wrapped_contents, contents, content_infos; int nid, ret = 0; if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) || !CBS_get_asn1(content_info, &wrapped_contents, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); goto err; } nid = OBJ_cbs2nid(&content_type); if (nid == NID_pkcs7_encrypted) { /* See https://tools.ietf.org/html/rfc2315#section-13. * * PKCS#7 encrypted data inside a PKCS#12 structure is generally an * encrypted certificate bag and it's generally encrypted with 40-bit * RC2-CBC. */ CBS version_bytes, eci, contents_type, ai, encrypted_contents; X509_ALGOR *algor = NULL; const uint8_t *inp; uint8_t *out; size_t out_len; if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) || /* EncryptedContentInfo, see * https://tools.ietf.org/html/rfc2315#section-10.1 */ !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) || /* AlgorithmIdentifier, see * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */ !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&eci, &encrypted_contents, CBS_ASN1_CONTEXT_SPECIFIC | 0)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } inp = CBS_data(&ai); algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai)); if (algor == NULL) { goto err; } if (inp != CBS_data(&ai) + CBS_len(&ai)) { X509_ALGOR_free(algor); OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (!pbe_crypt(algor, ctx->password, ctx->password_len, CBS_data(&encrypted_contents), CBS_len(&encrypted_contents), &out, &out_len, 0 /* decrypt */)) { X509_ALGOR_free(algor); goto err; } X509_ALGOR_free(algor); CBS_init(&content_infos, out, out_len); ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx); OPENSSL_free(out); } else if (nid == NID_pkcs7_data) { CBS octet_string_contents; if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx); } else if (nid == NID_pkcs8ShroudedKeyBag) { /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section * 4.2.2. */ const uint8_t *inp = CBS_data(&wrapped_contents); PKCS8_PRIV_KEY_INFO *pki = NULL; X509_SIG *encrypted = NULL; if (*ctx->out_key) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); goto err; } /* encrypted isn't actually an X.509 signature, but it has the same * structure as one and so |X509_SIG| is reused to store it. */ encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents)); if (encrypted == NULL) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); X509_SIG_free(encrypted); goto err; } pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len); X509_SIG_free(encrypted); if (pki == NULL) { goto err; } *ctx->out_key = EVP_PKCS82PKEY(pki); PKCS8_PRIV_KEY_INFO_free(pki); if (ctx->out_key == NULL) { goto err; } ret = 1; } else if (nid == NID_certBag) { CBS cert_bag, cert_type, wrapped_cert, cert; if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) || !CBS_get_asn1(&cert_bag, &wrapped_cert, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { const uint8_t *inp = CBS_data(&cert); X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert)); if (!x509) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (inp != CBS_data(&cert) + CBS_len(&cert)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); X509_free(x509); goto err; } if (0 == sk_X509_push(ctx->out_certs, x509)) { X509_free(x509); goto err; } } ret = 1; } else { /* Unknown element type - ignore it. */ ret = 1; } err: return ret; }
RSA *RSA_parse_private_key(CBS *cbs) { BN_CTX *ctx = NULL; BIGNUM *product_of_primes_so_far = NULL; RSA *ret = RSA_new(); if (ret == NULL) { return NULL; } CBS child; uint64_t version; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&child, &version)) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); goto err; } if (version != kVersionTwoPrime && version != kVersionMulti) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_VERSION); goto err; } if (!parse_integer(&child, &ret->n) || !parse_integer(&child, &ret->e) || !parse_integer(&child, &ret->d) || !parse_integer(&child, &ret->p) || !parse_integer(&child, &ret->q) || !parse_integer(&child, &ret->dmp1) || !parse_integer(&child, &ret->dmq1) || !parse_integer(&child, &ret->iqmp)) { goto err; } if (version == kVersionMulti) { /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later * says "[otherPrimeInfos] shall be omitted if version is 0 and shall * contain at least one instance of OtherPrimeInfo if version is 1." The * OPTIONAL is just so both versions share a single definition. */ CBS other_prime_infos; if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) || CBS_len(&other_prime_infos) == 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); goto err; } ret->additional_primes = sk_RSA_additional_prime_new_null(); if (ret->additional_primes == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } ctx = BN_CTX_new(); product_of_primes_so_far = BN_new(); if (ctx == NULL || product_of_primes_so_far == NULL || !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) { goto err; } while (CBS_len(&other_prime_infos) > 0) { RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos); if (ap == NULL) { goto err; } if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); RSA_additional_prime_free(ap); goto err; } ap->r = BN_dup(product_of_primes_so_far); if (ap->r == NULL || !BN_mul(product_of_primes_so_far, product_of_primes_so_far, ap->prime, ctx)) { goto err; } } } if (CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); goto err; } BN_CTX_free(ctx); BN_free(product_of_primes_so_far); return ret; err: BN_CTX_free(ctx); BN_free(product_of_primes_so_far); RSA_free(ret); return NULL; }
SSL_SESSION * d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length) { CBS cbs, session, cipher_suite, session_id, master_key, peer_cert; CBS hostname, ticket; uint64_t version, tls_version, stime, timeout, verify_result, lifetime; const unsigned char *peer_cert_bytes; uint16_t cipher_value; SSL_SESSION *s = NULL; size_t data_len; int present; if (a != NULL) s = *a; if (s == NULL) { if ((s = SSL_SESSION_new()) == NULL) { SSLerrorx(ERR_R_MALLOC_FAILURE); return (NULL); } } CBS_init(&cbs, *pp, length); if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE)) goto err; /* Session ASN1 version. */ if (!CBS_get_asn1_uint64(&session, &version)) goto err; if (version != SSL_SESSION_ASN1_VERSION) goto err; /* TLS/SSL Protocol Version. */ if (!CBS_get_asn1_uint64(&session, &tls_version)) goto err; if (tls_version > INT_MAX) goto err; s->ssl_version = (int)tls_version; /* Cipher suite. */ if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING)) goto err; if (!CBS_get_u16(&cipher_suite, &cipher_value)) goto err; if (CBS_len(&cipher_suite) != 0) goto err; /* XXX - populate cipher instead? */ s->cipher = NULL; s->cipher_id = SSL3_CK_ID | cipher_value; /* Session ID. */ if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) goto err; if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id), &data_len)) goto err; if (data_len > UINT_MAX) goto err; s->session_id_length = (unsigned int)data_len; /* Master key. */ if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING)) goto err; if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key), &data_len)) goto err; if (data_len > INT_MAX) goto err; s->master_key_length = (int)data_len; /* Time [1]. */ s->time = time(NULL); if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG, 0)) goto err; if (stime > time_max()) goto err; if (stime != 0) s->time = (time_t)stime; /* Timeout [2]. */ s->timeout = 3; if (!CBS_get_optional_asn1_uint64(&session, &timeout, SSLASN1_TIMEOUT_TAG, 0)) goto err; if (timeout > LONG_MAX) goto err; if (timeout != 0) s->timeout = (long)timeout; /* Peer certificate [3]. */ X509_free(s->peer); s->peer = NULL; if (!CBS_get_optional_asn1(&session, &peer_cert, &present, SSLASN1_PEER_CERT_TAG)) goto err; if (present) { data_len = CBS_len(&peer_cert); if (data_len > LONG_MAX) goto err; peer_cert_bytes = CBS_data(&peer_cert); if (d2i_X509(&s->peer, &peer_cert_bytes, (long)data_len) == NULL) goto err; } /* Session ID context [4]. */ s->sid_ctx_length = 0; if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present, SSLASN1_SESSION_ID_CTX_TAG)) goto err; if (present) { if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx, sizeof(s->sid_ctx), &data_len)) goto err; if (data_len > UINT_MAX) goto err; s->sid_ctx_length = (unsigned int)data_len; } /* Verify result [5]. */ s->verify_result = X509_V_OK; if (!CBS_get_optional_asn1_uint64(&session, &verify_result, SSLASN1_VERIFY_RESULT_TAG, X509_V_OK)) goto err; if (verify_result > LONG_MAX) goto err; s->verify_result = (long)verify_result; /* Hostname [6]. */ free(s->tlsext_hostname); s->tlsext_hostname = NULL; if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present, SSLASN1_HOSTNAME_TAG)) goto err; if (present) { if (CBS_contains_zero_byte(&hostname)) goto err; if (!CBS_strdup(&hostname, &s->tlsext_hostname)) goto err; } /* PSK identity hint [7]. */ /* PSK identity [8]. */ /* Ticket lifetime [9]. */ s->tlsext_tick_lifetime_hint = 0; /* XXX - tlsext_ticklen is not yet set... */ if (s->tlsext_ticklen > 0 && s->session_id_length > 0) s->tlsext_tick_lifetime_hint = -1; if (!CBS_get_optional_asn1_uint64(&session, &lifetime, SSLASN1_LIFETIME_TAG, 0)) goto err; if (lifetime > LONG_MAX) goto err; if (lifetime > 0) s->tlsext_tick_lifetime_hint = (long)lifetime; /* Ticket [10]. */ free(s->tlsext_tick); s->tlsext_tick = NULL; if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present, SSLASN1_TICKET_TAG)) goto err; if (present) { if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen)) goto err; } /* Compression method [11]. */ /* SRP username [12]. */ *pp = CBS_data(&cbs); if (a != NULL) *a = s; return (s); err: ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp)); if (s != NULL && (a == NULL || *a != s)) SSL_SESSION_free(s); return (NULL); }
static int test_get_asn1(void) { static const uint8_t kData1[] = {0x30, 2, 1, 2}; static const uint8_t kData2[] = {0x30, 3, 1, 2}; static const uint8_t kData3[] = {0x30, 0x80}; static const uint8_t kData4[] = {0x30, 0x81, 1, 1}; static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1}; static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1}; static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1}; static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1}; static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff}; CBS data, contents; int present; uint64_t value; CBS_init(&data, kData1, sizeof(kData1)); if (CBS_peek_asn1_tag(&data, 0x1) || !CBS_peek_asn1_tag(&data, 0x30)) { return 0; } if (!CBS_get_asn1(&data, &contents, 0x30) || CBS_len(&contents) != 2 || memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) { return 0; } CBS_init(&data, kData2, sizeof(kData2)); /* data is truncated */ if (CBS_get_asn1(&data, &contents, 0x30)) { return 0; } CBS_init(&data, kData3, sizeof(kData3)); /* zero byte length of length */ if (CBS_get_asn1(&data, &contents, 0x30)) { return 0; } CBS_init(&data, kData4, sizeof(kData4)); /* long form mistakenly used. */ if (CBS_get_asn1(&data, &contents, 0x30)) { return 0; } CBS_init(&data, kData5, sizeof(kData5)); /* length takes too many bytes. */ if (CBS_get_asn1(&data, &contents, 0x30)) { return 0; } CBS_init(&data, kData1, sizeof(kData1)); /* wrong tag. */ if (CBS_get_asn1(&data, &contents, 0x31)) { return 0; } CBS_init(&data, NULL, 0); /* peek at empty data. */ if (CBS_peek_asn1_tag(&data, 0x30)) { return 0; } CBS_init(&data, NULL, 0); /* optional elements at empty data. */ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) || present || !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) || present || CBS_len(&contents) != 0 || !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) || CBS_len(&contents) != 0 || !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) || value != 42) { return 0; } CBS_init(&data, kData6, sizeof(kData6)); /* optional element. */ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) || present || !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) || !present || CBS_len(&contents) != 3 || memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) { return 0; } CBS_init(&data, kData6, sizeof(kData6)); /* optional octet string. */ if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) || present || CBS_len(&contents) != 0 || !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) || !present || CBS_len(&contents) != 1 || CBS_data(&contents)[0] != 1) { return 0; } CBS_init(&data, kData7, sizeof(kData7)); /* invalid optional octet string. */ if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) { return 0; } CBS_init(&data, kData8, sizeof(kData8)); /* optional octet string. */ if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) || value != 42 || !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) || value != 1) { return 0; } CBS_init(&data, kData9, sizeof(kData9)); /* invalid optional integer. */ if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) { return 0; } return 1; }
SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method, CRYPTO_BUFFER_POOL *pool) { SSL_SESSION *ret = ssl_session_new(x509_method); if (ret == NULL) { goto err; } CBS session; uint64_t version, ssl_version; if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) || !CBS_get_asn1_uint64(&session, &version) || version != kVersion || !CBS_get_asn1_uint64(&session, &ssl_version)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } ret->ssl_version = ssl_version; CBS cipher; uint16_t cipher_value; if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) || !CBS_get_u16(&cipher, &cipher_value) || CBS_len(&cipher) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } ret->cipher = SSL_get_cipher_by_value(cipher_value); if (ret->cipher == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER); goto err; } CBS session_id, master_key; if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) || CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH || !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) || CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id)); ret->session_id_length = CBS_len(&session_id); OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key)); ret->master_key_length = CBS_len(&master_key); CBS child; uint64_t timeout; if (!CBS_get_asn1(&session, &child, kTimeTag) || !CBS_get_asn1_uint64(&child, &ret->time) || !CBS_get_asn1(&session, &child, kTimeoutTag) || !CBS_get_asn1_uint64(&child, &timeout) || timeout > UINT32_MAX) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } ret->timeout = (uint32_t)timeout; CBS peer; int has_peer; if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) || (has_peer && CBS_len(&peer) == 0)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } /* |peer| is processed with the certificate chain. */ if (!SSL_SESSION_parse_bounded_octet_string( &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx), kSessionIDContextTag) || !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag, X509_V_OK) || !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname, kHostNameTag) || !SSL_SESSION_parse_string(&session, &ret->psk_identity, kPSKIdentityTag) || !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint, kTicketLifetimeHintTag, 0) || !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick, &ret->tlsext_ticklen, kTicketTag)) { goto err; } if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) { CBS peer_sha256; if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) || !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) || CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256)); ret->peer_sha256_valid = 1; } else { ret->peer_sha256_valid = 0; } if (!SSL_SESSION_parse_bounded_octet_string( &session, ret->original_handshake_hash, &ret->original_handshake_hash_len, sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) || !SSL_SESSION_parse_octet_string( &session, &ret->tlsext_signed_cert_timestamp_list, &ret->tlsext_signed_cert_timestamp_list_length, kSignedCertTimestampListTag) || !SSL_SESSION_parse_octet_string( &session, &ret->ocsp_response, &ret->ocsp_response_length, kOCSPResponseTag)) { goto err; } int extended_master_secret; if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret, kExtendedMasterSecretTag, 0 /* default to false */)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } ret->extended_master_secret = !!extended_master_secret; if (!SSL_SESSION_parse_u16(&session, &ret->group_id, kGroupIDTag, 0)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } CBS cert_chain; CBS_init(&cert_chain, NULL, 0); int has_cert_chain; if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain, kCertChainTag) || (has_cert_chain && CBS_len(&cert_chain) == 0)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } if (has_cert_chain && !has_peer) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } if (has_peer || has_cert_chain) { ret->certs = sk_CRYPTO_BUFFER_new_null(); if (ret->certs == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (has_peer) { /* TODO(agl): this should use the |SSL_CTX|'s pool. */ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool); if (buffer == NULL || !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) { CRYPTO_BUFFER_free(buffer); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } while (CBS_len(&cert_chain) > 0) { CBS cert; if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) || CBS_len(&cert) == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } /* TODO(agl): this should use the |SSL_CTX|'s pool. */ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool); if (buffer == NULL || !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) { CRYPTO_BUFFER_free(buffer); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } } if (!x509_method->session_cache_objects(ret)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } CBS age_add; int age_add_present; if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present, kTicketAgeAddTag) || (age_add_present && !CBS_get_u32(&age_add, &ret->ticket_age_add)) || CBS_len(&age_add) != 0) { goto err; } ret->ticket_age_add_valid = age_add_present; int is_server; if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag, 1 /* default to true */)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } /* TODO: in time we can include |is_server| for servers too, then we can enforce that client and server sessions are never mixed up. */ ret->is_server = is_server; if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm, kPeerSignatureAlgorithmTag, 0) || !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data, kTicketMaxEarlyDataTag, 0) || !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag, ret->timeout) || !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn, &ret->early_alpn_len, kEarlyALPNTag) || CBS_len(&session) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); goto err; } return ret; err: SSL_SESSION_free(ret); return NULL; }
/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a * SEQUENCE. */ static int PKCS12_handle_content_infos(CBS *content_infos, unsigned depth, struct pkcs12_context *ctx) { uint8_t *der_bytes = NULL; size_t der_len; CBS in; int ret = 0; /* Generally we only expect depths 0 (the top level, with a * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12 * bags). */ if (depth > 3) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED); return 0; } /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|, * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the * conversion cannot see through those wrappings. So each time we step * through one we need to convert to DER again. */ if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) { return 0; } if (der_bytes != NULL) { CBS_init(&in, der_bytes, der_len); } else { CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos)); } if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, PKCS8_R_BAD_PKCS12_DATA); goto err; } while (CBS_len(&in) > 0) { CBS content_info; if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) { goto err; } } /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped) * copy of the same encrypted private key (with the same IV and * ciphertext)! */ ret = 1; err: if (der_bytes != NULL) { OPENSSL_free(der_bytes); } return ret; }