void ssl_cert_free(CERT *c) { if (c == NULL) { return; } ssl_cert_clear_certs(c); c->x509_method->cert_free(c); OPENSSL_free(c->sigalgs); CRYPTO_BUFFER_free(c->signed_cert_timestamp_list); CRYPTO_BUFFER_free(c->ocsp_response); OPENSSL_free(c); }
static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) { X509 *ret = (X509 *)*pval; switch (operation) { case ASN1_OP_NEW_POST: ret->name = NULL; ret->ex_flags = 0; ret->ex_pathlen = -1; ret->skid = NULL; ret->akid = NULL; ret->aux = NULL; ret->crldp = NULL; ret->buf = NULL; CRYPTO_new_ex_data(&ret->ex_data); CRYPTO_MUTEX_init(&ret->lock); break; case ASN1_OP_D2I_PRE: CRYPTO_BUFFER_free(ret->buf); ret->buf = NULL; break; case ASN1_OP_D2I_POST: if (ret->name != NULL) OPENSSL_free(ret->name); ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0); break; case ASN1_OP_FREE_POST: CRYPTO_MUTEX_cleanup(&ret->lock); CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); X509_CERT_AUX_free(ret->aux); ASN1_OCTET_STRING_free(ret->skid); AUTHORITY_KEYID_free(ret->akid); CRL_DIST_POINTS_free(ret->crldp); policy_cache_free(ret->policy_cache); GENERAL_NAMES_free(ret->altname); NAME_CONSTRAINTS_free(ret->nc); CRYPTO_BUFFER_free(ret->buf); OPENSSL_free(ret->name); break; } return 1; }
int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL); if (buffer == NULL) { return 0; } const int ok = ssl_set_cert(ssl->cert, buffer); CRYPTO_BUFFER_free(buffer); return ok; }
static int set_signed_cert_timestamp_list(CERT *cert, const uint8_t *list, size_t list_len) { CBS sct_list; CBS_init(&sct_list, list, list_len); if (!ssl_is_sct_list_valid(&sct_list)) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST); return 0; } CRYPTO_BUFFER_free(cert->signed_cert_timestamp_list); cert->signed_cert_timestamp_list = CRYPTO_BUFFER_new(CBS_data(&sct_list), CBS_len(&sct_list), NULL); return cert->signed_cert_timestamp_list != NULL; }
STACK_OF(CRYPTO_BUFFER) * ssl_parse_client_CA_list(SSL *ssl, uint8_t *out_alert, CBS *cbs) { CRYPTO_BUFFER_POOL *const pool = ssl->ctx->pool; STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null(); if (ret == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; } CBS child; if (!CBS_get_u16_length_prefixed(cbs, &child)) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); goto err; } while (CBS_len(&child) > 0) { CBS distinguished_name; if (!CBS_get_u16_length_prefixed(&child, &distinguished_name)) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG); goto err; } CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&distinguished_name, pool); if (buffer == NULL || !sk_CRYPTO_BUFFER_push(ret, buffer)) { CRYPTO_BUFFER_free(buffer); *out_alert = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (!ssl->ctx->x509_method->check_client_CA_list(ret)) { *out_alert = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } return ret; err: sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free); return NULL; }
int SSL_use_certificate(SSL *ssl, X509 *x) { if (x == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } CRYPTO_BUFFER *buffer = x509_to_buffer(x); if (buffer == NULL) { return 0; } const int ok = ssl_set_cert(ssl->cert, buffer); CRYPTO_BUFFER_free(buffer); return ok; }
int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) { switch (check_leaf_cert_and_privkey(buffer, cert->privatekey)) { case leaf_cert_and_privkey_error: return 0; case leaf_cert_and_privkey_mismatch: /* don't fail for a cert/key mismatch, just free current private key * (when switching to a different cert & key, first this function should * be used, then |ssl_set_pkey|. */ EVP_PKEY_free(cert->privatekey); cert->privatekey = NULL; break; case leaf_cert_and_privkey_ok: break; } cert->x509_method->cert_flush_cached_leaf(cert); if (cert->chain != NULL) { CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0)); sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer); CRYPTO_BUFFER_up_ref(buffer); return 1; } cert->chain = sk_CRYPTO_BUFFER_new_null(); if (cert->chain == NULL) { return 0; } if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) { sk_CRYPTO_BUFFER_free(cert->chain); cert->chain = NULL; return 0; } CRYPTO_BUFFER_up_ref(buffer); return 1; }
int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response, size_t response_len) { CRYPTO_BUFFER_free(ssl->cert->ocsp_response); ssl->cert->ocsp_response = CRYPTO_BUFFER_new(response, response_len, NULL); return ssl->cert->ocsp_response != NULL; }
int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response, size_t response_len) { CRYPTO_BUFFER_free(ctx->cert->ocsp_response); ctx->cert->ocsp_response = CRYPTO_BUFFER_new(response, response_len, NULL); return ctx->cert->ocsp_response != NULL; }
STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert, EVP_PKEY **out_pubkey, uint8_t *out_leaf_sha256, CBS *cbs, CRYPTO_BUFFER_POOL *pool) { *out_pubkey = NULL; STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null(); if (ret == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; } CBS certificate_list; if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || CBS_len(&certificate) == 0) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(ret) == 0) { *out_pubkey = ssl_cert_parse_pubkey(&certificate); if (*out_pubkey == NULL) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } /* Retain the hash of the leaf certificate if requested. */ if (out_leaf_sha256 != NULL) { SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, pool); if (buf == NULL) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } if (!sk_CRYPTO_BUFFER_push(ret, buf)) { *out_alert = SSL_AD_INTERNAL_ERROR; CRYPTO_BUFFER_free(buf); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } return ret; err: EVP_PKEY_free(*out_pubkey); *out_pubkey = NULL; sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free); return NULL; }
int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) { SSL *const ssl = hs->ssl; CBS cbs, context, certificate_list; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } const int retain_sha256 = ssl->server && ssl->retain_only_sha256_of_client_certs; int ret = 0; EVP_PKEY *pkey = NULL; STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null(); if (certs == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate, extensions; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || !CBS_get_u16_length_prefixed(&certificate_list, &extensions) || CBS_len(&certificate) == 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 0) { pkey = ssl_cert_parse_pubkey(&certificate); if (pkey == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } /* TLS 1.3 always uses certificate keys for signing thus the correct * keyUsage is enforced. */ if (!ssl_cert_check_digital_signature_key_usage(&certificate)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } if (retain_sha256) { /* Retain the hash of the leaf certificate if requested. */ SHA256(CBS_data(&certificate), CBS_len(&certificate), ssl->s3->new_session->peer_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool); if (buf == NULL || !sk_CRYPTO_BUFFER_push(certs, buf)) { CRYPTO_BUFFER_free(buf); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* Parse out the extensions. */ int have_status_request = 0, have_sct = 0; CBS status_request, sct; const SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_status_request, &have_status_request, &status_request}, {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct}, }; uint8_t alert; if (!ssl_parse_extensions(&extensions, &alert, ext_types, OPENSSL_ARRAY_SIZE(ext_types), 0 /* reject unknown */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } /* All Certificate extensions are parsed, but only the leaf extensions are * stored. */ if (have_status_request) { if (ssl->server || !ssl->ocsp_stapling_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } uint8_t status_type; CBS ocsp_response; if (!CBS_get_u8(&status_request, &status_type) || status_type != TLSEXT_STATUSTYPE_ocsp || !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) || CBS_len(&ocsp_response) == 0 || CBS_len(&status_request) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&ocsp_response, &ssl->s3->new_session->ocsp_response, &ssl->s3->new_session->ocsp_response_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } if (have_sct) { if (ssl->server || !ssl->signed_cert_timestamps_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } if (!ssl_is_sct_list_valid(&sct)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&sct, &ssl->s3->new_session->tlsext_signed_cert_timestamp_list, &ssl->s3->new_session ->tlsext_signed_cert_timestamp_list_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } EVP_PKEY_free(hs->peer_pubkey); hs->peer_pubkey = pkey; pkey = NULL; sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free); ssl->s3->new_session->certs = certs; certs = NULL; if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) { if (!allow_anonymous) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED); goto err; } /* OpenSSL returns X509_V_OK when no certificates are requested. This is * classed by them as a bug, but it's assumed by at least NGINX. */ ssl->s3->new_session->verify_result = X509_V_OK; /* No certificate, so nothing more to do. */ ret = 1; goto err; } ssl->s3->new_session->peer_sha256_valid = retain_sha256; if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result, ssl->s3->new_session->x509_chain)) { goto err; } ret = 1; err: sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free); EVP_PKEY_free(pkey); return ret; }
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; }
static int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) { CBS cert_cbs; CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs); EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs); if (pubkey == NULL) { return 0; } if (!is_key_type_supported(pubkey->type)) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pubkey); return 0; } /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA * certificates, so sanity-check the key usage extension. */ if (pubkey->type == EVP_PKEY_EC && !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pubkey); return 0; } if (cert->privatekey != NULL) { /* Sanity-check that the private key and the certificate match, unless the * key is opaque (in case of, say, a smartcard). */ if (!EVP_PKEY_is_opaque(cert->privatekey) && !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) { /* don't fail for a cert/key mismatch, just free current private key * (when switching to a different cert & key, first this function should * be used, then ssl_set_pkey */ EVP_PKEY_free(cert->privatekey); cert->privatekey = NULL; /* clear error queue */ ERR_clear_error(); } } EVP_PKEY_free(pubkey); ssl_cert_flush_cached_x509_leaf(cert); if (cert->chain != NULL) { CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0)); sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer); CRYPTO_BUFFER_up_ref(buffer); return 1; } cert->chain = sk_CRYPTO_BUFFER_new_null(); if (cert->chain == NULL) { return 0; } if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) { sk_CRYPTO_BUFFER_free(cert->chain); cert->chain = NULL; return 0; } CRYPTO_BUFFER_up_ref(buffer); return 1; }