From fa7c263747cb73f03b321399a1452cc40516d9a4 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 13 Mar 2017 15:00:36 +0000 Subject: [PATCH] New certificate_authorities functions Add functions to add/retrieve the certificate_authorities. The older client_CA functions mainly just call the new versions now. Rename fields sice new extension can be generated by client and server. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/3015) --- include/openssl/ssl.h | 8 +++++ ssl/s3_lib.c | 4 +-- ssl/ssl_cert.c | 79 +++++++++++++++++++++++++++-------------- ssl/ssl_lib.c | 12 +++---- ssl/ssl_locl.h | 15 +++++--- ssl/statem/extensions.c | 4 +-- ssl/statem/statem_lib.c | 4 +-- ssl/t1_lib.c | 2 +- 8 files changed, 84 insertions(+), 44 deletions(-) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index b1a8c696fb..9a98d87d21 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1718,6 +1718,14 @@ __owur const char *SSL_alert_type_string(int value); __owur const char *SSL_alert_desc_string_long(int value); __owur const char *SSL_alert_desc_string(int value); +void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s); +__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx); +__owur int SSL_add1_CA_list(SSL *ssl, const X509 *x); +__owur int SSL_CTX_add1_CA_list(SSL_CTX *ctx, const X509 *x); +__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s); + void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); __owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index d8cce5e63c..54c49ab762 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -2935,7 +2935,7 @@ void ssl3_free(SSL *s) #endif OPENSSL_free(s->s3->tmp.ctype); - sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); OPENSSL_free(s->s3->tmp.ciphers_raw); OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); OPENSSL_free(s->s3->tmp.peer_sigalgs); @@ -2954,7 +2954,7 @@ void ssl3_clear(SSL *s) { ssl3_cleanup_key_block(s); OPENSSL_free(s->s3->tmp.ctype); - sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); OPENSSL_free(s->s3->tmp.ciphers_raw); OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); OPENSSL_free(s->s3->tmp.peer_sigalgs); diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 50b2e645a9..95dde8517d 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -459,8 +459,8 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) return i; } -static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list, - STACK_OF(X509_NAME) *name_list) +static void set0_CA_list(STACK_OF(X509_NAME) **ca_list, + STACK_OF(X509_NAME) *name_list) { sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); *ca_list = name_list; @@ -488,63 +488,90 @@ STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) return (ret); } -void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) +void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) { - set_client_CA_list(&(s->client_CA), name_list); + set0_CA_list(&s->ca_names, name_list); +} + +void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) +{ + set0_CA_list(&ctx->ca_names, name_list); +} + +const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx) +{ + return ctx->ca_names; +} + +const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s) +{ + return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names; } void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) { - set_client_CA_list(&(ctx->client_CA), name_list); + SSL_CTX_set0_CA_list(ctx, name_list); } STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { - return (ctx->client_CA); + return ctx->ca_names; +} + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) +{ + SSL_set0_CA_list(s, name_list); +} + +const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s) +{ + return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL; } STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) { - if (!s->server) { /* we are in the client */ - if (s->s3 != NULL) - return s->s3->tmp.ca_names; - else - return NULL; - } else { - if (s->client_CA != NULL) - return s->client_CA; - else - return s->ctx->client_CA; - } + if (!s->server) + return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL; + return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names; } -static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) +static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x) { X509_NAME *name; if (x == NULL) - return (0); - if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL)) - return (0); + return 0; + if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL)) + return 0; if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) - return (0); + return 0; if (!sk_X509_NAME_push(*sk, name)) { X509_NAME_free(name); - return (0); + return 0; } - return (1); + return 1; +} + +int SSL_add1_CA_list(SSL *ssl, const X509 *x) +{ + return add_ca_name(&ssl->ca_names, x); +} + +int SSL_CTX_add1_CA_list(SSL_CTX *ctx, const X509 *x) +{ + return add_ca_name(&ctx->ca_names, x); } int SSL_add_client_CA(SSL *ssl, X509 *x) { - return (add_client_CA(&(ssl->client_CA), x)); + return add_ca_name(&ssl->ca_names, x); } int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) { - return (add_client_CA(&(ctx->client_CA), x)); + return add_ca_name(&ctx->ca_names, x); } static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 24fc994d1f..4f4eba104a 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1018,7 +1018,7 @@ void SSL_free(SSL *s) OPENSSL_free(s->ext.tls13_cookie); OPENSSL_free(s->clienthello); - sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free); + sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free); sk_X509_pop_free(s->verified_chain, X509_free); @@ -2692,7 +2692,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) goto err2; } - if ((ret->client_CA = sk_X509_NAME_new_null()) == NULL) + if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL) goto err; if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data)) @@ -2814,7 +2814,7 @@ void SSL_CTX_free(SSL_CTX *a) sk_SSL_CIPHER_free(a->cipher_list); sk_SSL_CIPHER_free(a->cipher_list_by_id); ssl_cert_free(a->cert); - sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free); + sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free); sk_X509_pop_free(a->extra_certs, X509_free); a->comp_methods = NULL; #ifndef OPENSSL_NO_SRTP @@ -3410,10 +3410,10 @@ SSL *SSL_dup(SSL *s) goto err; /* Dup the client_CA list */ - if (s->client_CA != NULL) { - if ((sk = sk_X509_NAME_dup(s->client_CA)) == NULL) + if (s->ca_names != NULL) { + if ((sk = sk_X509_NAME_dup(s->ca_names)) == NULL) goto err; - ret->client_CA = sk; + ret->ca_names = sk; for (i = 0; i < sk_X509_NAME_num(sk); i++) { xn = sk_X509_NAME_value(sk, i); if (sk_X509_NAME_set(sk, i, X509_NAME_dup(xn)) == NULL) { diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 4378b7177d..f53293109b 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -542,7 +542,7 @@ struct ssl_session_st { /* This is the cert and type for the other end. */ X509 *peer; int peer_type; - /* Certificate chain peer sent */ + /* Certificate chain peer sent. */ STACK_OF(X509) *peer_chain; /* * when app_verify_callback accepts a session where the peer's @@ -790,8 +790,12 @@ struct ssl_ctx_st { /* used if SSL's info_callback is NULL */ void (*info_callback) (const SSL *ssl, int type, int val); - /* what we put in client cert requests */ - STACK_OF(X509_NAME) *client_CA; + /* + * What we put in certificate_authorities extension for TLS 1.3 + * (ClientHello and CertificateRequest) or just client cert requests for + * earlier versions. + */ + STACK_OF(X509_NAME) *ca_names; /* * Default values to use in SSL structures follow (these are copied by @@ -1115,7 +1119,7 @@ struct ssl_st { /* extra application data */ CRYPTO_EX_DATA ex_data; /* for server side, keep the list of CA_dn we can use */ - STACK_OF(X509_NAME) *client_CA; + STACK_OF(X509_NAME) *ca_names; CRYPTO_REF_COUNT references; /* protocol behaviour */ uint32_t options; @@ -1371,7 +1375,8 @@ typedef struct ssl3_state_st { /* Certificate types in certificate request message. */ uint8_t *ctype; size_t ctype_len; - STACK_OF(X509_NAME) *ca_names; + /* Certificate authorities list peer sent */ + STACK_OF(X509_NAME) *peer_ca_names; size_t key_block_length; unsigned char *key_block; const EVP_CIPHER *new_sym_enc; diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 043b8304eb..22669dd565 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -983,8 +983,8 @@ static int final_ems(SSL *s, unsigned int context, int sent, int *al) static int init_certificate_authorities(SSL *s, unsigned int context) { - sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); - s->s3->tmp.ca_names = NULL; + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = NULL; return 1; } diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 860b8141bd..e3fc7e8b1e 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -2023,8 +2023,8 @@ int parse_ca_names(SSL *s, PACKET *pkt, int *al) xn = NULL; } - sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free); - s->s3->tmp.ca_names = ca_sk; + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = ca_sk; return 1; diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 1c98b53e96..698c25b46f 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -2041,7 +2041,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, rv |= CERT_PKEY_CERT_TYPE; } - ca_dn = s->s3->tmp.ca_names; + ca_dn = s->s3->tmp.peer_ca_names; if (!sk_X509_NAME_num(ca_dn)) rv |= CERT_PKEY_ISSUER_NAME; -- 2.34.1