From: Dr. Stephen Henson Date: Tue, 5 Aug 2014 14:21:36 +0000 (+0100) Subject: Revision of custom extension code. X-Git-Tag: master-post-reformat~516^2 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=b83294fe3022b9d5d525ccdcfeb53d39c25b05bd;p=oweals%2Fopenssl.git Revision of custom extension code. Move custom extension structures from SSL_CTX to CERT structure. This change means the form can be revised in future without binary compatibility issues. Also since CERT is part of SSL structures so per-SSL custom extensions could be supported in future as well as per SSL_CTX. Reviewed-by: Rich Salz Reviewed-by: Emilia Käsper --- diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 0865485bcf..903f1282dd 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -368,7 +368,7 @@ static int ssl23_client_hello(SSL *s) if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL) ssl2_compat = 0; #endif - if (s->ctx->custom_cli_ext_records_count != 0) + if (s->cert->custom_cli_ext_records_count != 0) ssl2_compat = 0; } #endif diff --git a/ssl/ssl.h b/ssl/ssl.h index 376dd69818..dc18255c1f 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -425,20 +425,6 @@ typedef int (*custom_srv_ext_second_cb_fn)(SSL *s, unsigned short ext_type, const unsigned char **out, unsigned short *outlen, int *al, void *arg); -typedef struct { - unsigned short ext_type; - custom_cli_ext_first_cb_fn fn1; - custom_cli_ext_second_cb_fn fn2; - void *arg; -} custom_cli_ext_record; - -typedef struct { - unsigned short ext_type; - custom_srv_ext_first_cb_fn fn1; - custom_srv_ext_second_cb_fn fn2; - void *arg; -} custom_srv_ext_record; - #endif #ifndef OPENSSL_NO_SSL_INTERN @@ -1160,11 +1146,6 @@ struct ssl_ctx_st size_t tlsext_ellipticcurvelist_length; unsigned char *tlsext_ellipticcurvelist; # endif /* OPENSSL_NO_EC */ - /* Arrays containing the callbacks for custom TLS Extensions. */ - custom_cli_ext_record *custom_cli_ext_records; - size_t custom_cli_ext_records_count; - custom_srv_ext_record *custom_srv_ext_records; - size_t custom_srv_ext_records_count; }; #endif diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 4e75a96283..45049587b9 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -423,6 +423,27 @@ CERT *ssl_cert_dup(CERT *cert) ret->sec_level = cert->sec_level; ret->sec_ex = cert->sec_ex; +#ifndef OPENSSL_NO_TLSEXT + if (cert->custom_cli_ext_records_count) + { + ret->custom_cli_ext_records = BUF_memdup(cert->custom_cli_ext_records, sizeof(custom_cli_ext_record) * cert->custom_cli_ext_records_count); + if (ret->custom_cli_ext_records == NULL) + goto err; + ret->custom_cli_ext_records_count = + cert->custom_cli_ext_records_count; + } + + if (cert->custom_srv_ext_records_count) + { + ret->custom_srv_ext_records = BUF_memdup(cert->custom_srv_ext_records, sizeof(custom_srv_ext_record) * cert->custom_srv_ext_records_count); + if (ret->custom_srv_ext_records == NULL) + goto err; + ret->custom_srv_ext_records_count = + cert->custom_srv_ext_records_count; + } + +#endif + return(ret); #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH) @@ -441,6 +462,13 @@ err: EC_KEY_free(ret->ecdh_tmp); #endif +#ifndef OPENSSL_NO_TLSEXT + if (ret->custom_cli_ext_records) + OPENSSL_free(ret->custom_cli_ext_records); + if (ret->custom_srv_ext_records) + OPENSSL_free(ret->custom_srv_ext_records); +#endif + ssl_cert_clear_certs(ret); return NULL; @@ -531,6 +559,12 @@ void ssl_cert_free(CERT *c) X509_STORE_free(c->chain_store); if (c->ciphers_raw) OPENSSL_free(c->ciphers_raw); +#ifndef OPENSSL_NO_TLSEXT + if (c->custom_cli_ext_records) + OPENSSL_free(c->custom_cli_ext_records); + if (c->custom_srv_ext_records) + OPENSSL_free(c->custom_srv_ext_records); +#endif OPENSSL_free(c); } diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 9f4040d701..98f4018014 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1751,7 +1751,7 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned } # endif -int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, +static int cert_set_custom_cli_ext(CERT *cert, unsigned short ext_type, custom_cli_ext_first_cb_fn fn1, custom_cli_ext_second_cb_fn fn2, void* arg) { @@ -1759,19 +1759,19 @@ int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, custom_cli_ext_record* record; /* Check for duplicates */ - for (i=0; i < ctx->custom_cli_ext_records_count; i++) - if (ext_type == ctx->custom_cli_ext_records[i].ext_type) + for (i=0; i < cert->custom_cli_ext_records_count; i++) + if (ext_type == cert->custom_cli_ext_records[i].ext_type) return 0; - ctx->custom_cli_ext_records = OPENSSL_realloc(ctx->custom_cli_ext_records, - (ctx->custom_cli_ext_records_count + 1) * + cert->custom_cli_ext_records = OPENSSL_realloc(cert->custom_cli_ext_records, + (cert->custom_cli_ext_records_count + 1) * sizeof(custom_cli_ext_record)); - if (!ctx->custom_cli_ext_records) { - ctx->custom_cli_ext_records_count = 0; + if (!cert->custom_cli_ext_records) { + cert->custom_cli_ext_records_count = 0; return 0; } - ctx->custom_cli_ext_records_count++; - record = &ctx->custom_cli_ext_records[ctx->custom_cli_ext_records_count - 1]; + cert->custom_cli_ext_records_count++; + record = &cert->custom_cli_ext_records[cert->custom_cli_ext_records_count - 1]; record->ext_type = ext_type; record->fn1 = fn1; record->fn2 = fn2; @@ -1779,7 +1779,7 @@ int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, return 1; } -int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, +static int cert_set_custom_srv_ext(CERT *cert, unsigned short ext_type, custom_srv_ext_first_cb_fn fn1, custom_srv_ext_second_cb_fn fn2, void* arg) { @@ -1787,25 +1787,39 @@ int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, custom_srv_ext_record* record; /* Check for duplicates */ - for (i=0; i < ctx->custom_srv_ext_records_count; i++) - if (ext_type == ctx->custom_srv_ext_records[i].ext_type) + for (i=0; i < cert->custom_srv_ext_records_count; i++) + if (ext_type == cert->custom_srv_ext_records[i].ext_type) return 0; - ctx->custom_srv_ext_records = OPENSSL_realloc(ctx->custom_srv_ext_records, - (ctx->custom_srv_ext_records_count + 1) * + cert->custom_srv_ext_records = OPENSSL_realloc(cert->custom_srv_ext_records, + (cert->custom_srv_ext_records_count + 1) * sizeof(custom_srv_ext_record)); - if (!ctx->custom_srv_ext_records) { - ctx->custom_srv_ext_records_count = 0; + if (!cert->custom_srv_ext_records) { + cert->custom_srv_ext_records_count = 0; return 0; } - ctx->custom_srv_ext_records_count++; - record = &ctx->custom_srv_ext_records[ctx->custom_srv_ext_records_count - 1]; + cert->custom_srv_ext_records_count++; + record = &cert->custom_srv_ext_records[cert->custom_srv_ext_records_count - 1]; record->ext_type = ext_type; record->fn1 = fn1; record->fn2 = fn2; record->arg = arg; return 1; } + +int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, + custom_cli_ext_first_cb_fn fn1, + custom_cli_ext_second_cb_fn fn2, void *arg) + { + return cert_set_custom_cli_ext(ctx->cert, ext_type, fn1, fn2,arg); + } + +int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, + custom_srv_ext_first_cb_fn fn1, + custom_srv_ext_second_cb_fn fn2, void *arg) + { + return cert_set_custom_srv_ext(ctx->cert, ext_type, fn1, fn2,arg); + } /* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit @@ -2078,10 +2092,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) #ifndef OPENSSL_NO_SRP SSL_CTX_SRP_CTX_init(ret); #endif - ret->custom_cli_ext_records = NULL; - ret->custom_cli_ext_records_count = 0; - ret->custom_srv_ext_records = NULL; - ret->custom_srv_ext_records_count = 0; #ifndef OPENSSL_NO_BUF_FREELISTS ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); @@ -2220,10 +2230,6 @@ void SSL_CTX_free(SSL_CTX *a) #ifndef OPENSSL_NO_SRP SSL_CTX_SRP_CTX_free(a); #endif -#ifndef OPENSSL_NO_TLSEXT - OPENSSL_free(a->custom_cli_ext_records); - OPENSSL_free(a->custom_srv_ext_records); -#endif #ifndef OPENSSL_NO_ENGINE if (a->client_cert_engine) ENGINE_finish(a->client_cert_engine); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 7b28886e6b..4a12aec5fc 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -532,6 +532,20 @@ typedef struct cert_pkey_st #define SSL_CERT_FLAGS_CHECK_TLS_STRICT \ (SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT) +typedef struct { + unsigned short ext_type; + custom_cli_ext_first_cb_fn fn1; + custom_cli_ext_second_cb_fn fn2; + void *arg; +} custom_cli_ext_record; + +typedef struct { + unsigned short ext_type; + custom_srv_ext_first_cb_fn fn1; + custom_srv_ext_second_cb_fn fn2; + void *arg; +} custom_srv_ext_record; + typedef struct cert_st { /* Current active set */ @@ -628,6 +642,12 @@ typedef struct cert_st unsigned char *ciphers_raw; size_t ciphers_rawlen; + /* Arrays containing the callbacks for custom TLS Extensions. */ + custom_cli_ext_record *custom_cli_ext_records; + size_t custom_cli_ext_records_count; + custom_srv_ext_record *custom_srv_ext_records; + size_t custom_srv_ext_records_count; + /* Security callback */ int (*sec_cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex); /* Security level */ diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 3616c0a11e..ac00a2ac4c 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1482,17 +1482,17 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c } /* Add custom TLS Extensions to ClientHello */ - if (s->ctx->custom_cli_ext_records_count) + if (s->cert->custom_cli_ext_records_count) { size_t i; custom_cli_ext_record* record; - for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) + for (i = 0; i < s->cert->custom_cli_ext_records_count; i++) { const unsigned char* out = NULL; unsigned short outlen = 0; - record = &s->ctx->custom_cli_ext_records[i]; + record = &s->cert->custom_cli_ext_records[i]; /* NULL callback sends empty extension */ /* -1 from callback omits extension */ if (record->fn1) @@ -1747,13 +1747,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c } #endif - for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++) + for (i = 0; i < s->cert->custom_srv_ext_records_count; i++) { const unsigned char *out = NULL; unsigned short outlen = 0; int cb_retval = 0; - record = &s->ctx->custom_srv_ext_records[i]; + record = &s->cert->custom_srv_ext_records[i]; /* NULL callback or -1 omits extension */ if (!record->fn2) @@ -2503,13 +2503,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char * so call the callback and record the extension number so that * an appropriate ServerHello may be later returned. */ - else if (!s->hit && s->ctx->custom_srv_ext_records_count) + else if (!s->hit && s->cert->custom_srv_ext_records_count) { custom_srv_ext_record *record; - for (i=0; i < s->ctx->custom_srv_ext_records_count; i++) + for (i=0; i < s->cert->custom_srv_ext_records_count; i++) { - record = &s->ctx->custom_srv_ext_records[i]; + record = &s->cert->custom_srv_ext_records[i]; if (type == record->ext_type) { if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg)) @@ -2848,14 +2848,14 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char /* If this extension type was not otherwise handled, but * matches a custom_cli_ext_record, then send it to the c * callback */ - else if (s->ctx->custom_cli_ext_records_count) + else if (s->cert->custom_cli_ext_records_count) { size_t i; custom_cli_ext_record* record; - for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) + for (i = 0; i < s->cert->custom_cli_ext_records_count; i++) { - record = &s->ctx->custom_cli_ext_records[i]; + record = &s->cert->custom_cli_ext_records[i]; if (record->ext_type == type) { if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))