X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_ext.c;h=396ad7e171ce6633e49d866b9ec751a7589f6125;hp=8b6c170ef6e4c90f21f36a97013a140414956ab6;hb=fa4629b6a2518d202fd051f228c3d8770682b3be;hpb=de2a9e38f39eacc2e052d694f5b5fa5b7e734abc diff --git a/ssl/t1_ext.c b/ssl/t1_ext.c index 8b6c170ef6..396ad7e171 100644 --- a/ssl/t1_ext.c +++ b/ssl/t1_ext.c @@ -57,229 +57,236 @@ #include "ssl_locl.h" -#ifndef OPENSSL_NO_TLSEXT - -/* Find a custom extension from the list */ +/* Find a custom extension from the list. */ static custom_ext_method *custom_ext_find(custom_ext_methods *exts, - unsigned short ext_type) - { - size_t i; - custom_ext_method *meth = exts->meths; - for (i = 0; i < exts->meths_count; i++, meth++) - { - if (ext_type == meth->ext_type) - return meth; - } - return NULL; - } -/* Initialise custom extensions flags to indicate neither sent nor - * received. + unsigned int ext_type) +{ + size_t i; + custom_ext_method *meth = exts->meths; + for (i = 0; i < exts->meths_count; i++, meth++) { + if (ext_type == meth->ext_type) + return meth; + } + return NULL; +} + +/* + * Initialise custom extensions flags to indicate neither sent nor received. */ void custom_ext_init(custom_ext_methods *exts) - { - size_t i; - custom_ext_method *meth = exts->meths; - for (i = 0; i < exts->meths_count; i++, meth++) - meth->ext_flags = 0; - } - -/* pass received custom extension data to the application for parsing */ +{ + size_t i; + custom_ext_method *meth = exts->meths; + for (i = 0; i < exts->meths_count; i++, meth++) + meth->ext_flags = 0; +} +/* Pass received custom extension data to the application for parsing. */ int custom_ext_parse(SSL *s, int server, - unsigned int ext_type, - const unsigned char *ext_data, - size_t ext_size, - int *al) - { - custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; - custom_ext_method *meth; - meth = custom_ext_find(exts, ext_type); - /* If not found or no parse function set, return success */ - /* If not found return success */ - if (!meth) - return 1; - if (!server) - { - /* If it's ServerHello we can't have any extensions not - * sent in ClientHello. - */ - if (!(meth->ext_flags & SSL_EXT_FLAG_SENT)) - { - *al = TLS1_AD_UNSUPPORTED_EXTENSION; - return 0; - } - } - /* If already present it's a duplicate */ - if (meth->ext_flags & SSL_EXT_FLAG_RECEIVED) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } - meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; - if (!meth->parse_cb) - return 1; + unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, int *al) +{ + custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; + custom_ext_method *meth; + meth = custom_ext_find(exts, ext_type); + /* If not found return success */ + if (!meth) + return 1; + if (!server) { + /* + * If it's ServerHello we can't have any extensions not sent in + * ClientHello. + */ + if (!(meth->ext_flags & SSL_EXT_FLAG_SENT)) { + *al = TLS1_AD_UNSUPPORTED_EXTENSION; + return 0; + } + } + /* If already present it's a duplicate */ + if (meth->ext_flags & SSL_EXT_FLAG_RECEIVED) { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; + /* If no parse function set return success */ + if (!meth->parse_cb) + return 1; - return meth->parse_cb(s, ext_type, ext_data, ext_size, al, meth->arg); - } + return meth->parse_cb(s, ext_type, ext_data, ext_size, al, + meth->parse_arg); +} -/* request custom extension data from the application and add to the - * return buffer +/* + * Request custom extension data from the application and add to the return + * buffer. */ - int custom_ext_add(SSL *s, int server, - unsigned char **pret, - unsigned char *limit, - int *al) - { - custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; - custom_ext_method *meth; - unsigned char *ret = *pret; - size_t i; + unsigned char **pret, unsigned char *limit, int *al) +{ + custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; + custom_ext_method *meth; + unsigned char *ret = *pret; + size_t i; - for (i = 0; i < exts->meths_count; i++) - { - const unsigned char *out = NULL; - size_t outlen = 0; - meth = exts->meths + i; + for (i = 0; i < exts->meths_count; i++) { + const unsigned char *out = NULL; + size_t outlen = 0; + meth = exts->meths + i; - if (server) - { - /* For ServerHello only send extensions present - * in ClientHello. - */ - if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) - continue; - /* If callback absent for server skip it */ - if (!meth->add_cb) - continue; - } - if (meth->add_cb) - { - int cb_retval = 0; - cb_retval = meth->add_cb(s, meth->ext_type, - &out, &outlen, al, - meth->arg); - if (cb_retval == 0) - return 0; /* error */ - if (cb_retval == -1) - continue; /* skip this extension */ - } - if (4 > limit - ret || outlen > (size_t)(limit - ret - 4)) - return 0; - s2n(meth->ext_type, ret); - s2n(outlen, ret); - if (outlen) - { - memcpy(ret, out, outlen); - ret += outlen; - } - /* We can't send duplicates: code logic should prevent this */ - OPENSSL_assert(!(meth->ext_flags & SSL_EXT_FLAG_SENT)); - /* Indicate extension has been sent: this is both a sanity - * check to ensure we don't send duplicate extensions - * and indicates to servers that an extension can be - * sent in ServerHello. - */ - meth->ext_flags |= SSL_EXT_FLAG_SENT; - } - *pret = ret; - return 1; - } + if (server) { + /* + * For ServerHello only send extensions present in ClientHello. + */ + if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) + continue; + /* If callback absent for server skip it */ + if (!meth->add_cb) + continue; + } + if (meth->add_cb) { + int cb_retval = 0; + cb_retval = meth->add_cb(s, meth->ext_type, + &out, &outlen, al, meth->add_arg); + if (cb_retval < 0) + return 0; /* error */ + if (cb_retval == 0) + continue; /* skip this extension */ + } + if (4 > limit - ret || outlen > (size_t)(limit - ret - 4)) + return 0; + s2n(meth->ext_type, ret); + s2n(outlen, ret); + if (outlen) { + memcpy(ret, out, outlen); + ret += outlen; + } + /* + * We can't send duplicates: code logic should prevent this. + */ + OPENSSL_assert(!(meth->ext_flags & SSL_EXT_FLAG_SENT)); + /* + * Indicate extension has been sent: this is both a sanity check to + * ensure we don't send duplicate extensions and indicates that it is + * not an error if the extension is present in ServerHello. + */ + meth->ext_flags |= SSL_EXT_FLAG_SENT; + if (meth->free_cb) + meth->free_cb(s, meth->ext_type, out, meth->add_arg); + } + *pret = ret; + return 1; +} /* Copy table of custom extensions */ - int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) - { - if (src->meths_count) - { - dst->meths = BUF_memdup(src->meths, sizeof(custom_ext_method) * src->meths_count); - if (dst->meths == NULL) - return 0; - dst->meths_count = src->meths_count; - } - return 1; - } +{ + if (src->meths_count) { + dst->meths = + BUF_memdup(src->meths, + sizeof(custom_ext_method) * src->meths_count); + if (dst->meths == NULL) + return 0; + dst->meths_count = src->meths_count; + } + return 1; +} void custom_exts_free(custom_ext_methods *exts) - { - if (exts->meths) - OPENSSL_free(exts->meths); - } +{ + OPENSSL_free(exts->meths); +} -/* Set callbacks for a custom extension */ -static int custom_ext_set(custom_ext_methods *exts, - unsigned int ext_type, - custom_ext_parse_cb parse_cb, - custom_ext_add_cb add_cb, - void *arg) - { - custom_ext_method *meth; - /* See if it is a supported internally */ - switch(ext_type) - { - case TLSEXT_TYPE_application_layer_protocol_negotiation: - case TLSEXT_TYPE_ec_point_formats: - case TLSEXT_TYPE_elliptic_curves: - case TLSEXT_TYPE_heartbeat: - case TLSEXT_TYPE_next_proto_neg: - case TLSEXT_TYPE_padding: - case TLSEXT_TYPE_renegotiate: - case TLSEXT_TYPE_server_name: - case TLSEXT_TYPE_session_ticket: - case TLSEXT_TYPE_signature_algorithms: - case TLSEXT_TYPE_srp: - case TLSEXT_TYPE_status_request: - case TLSEXT_TYPE_use_srtp: -#ifdef TLSEXT_TYPE_opaque_prf_input - case TLSEXT_TYPE_opaque_prf_input: -#endif -#ifdef TLSEXT_TYPE_encrypt_then_mac - case TLSEXT_TYPE_encrypt_then_mac: -#endif - return 0; - } - /* Extension type must fit in 16 bits */ - if (ext_type > 0xffff) - return 0; - /* Search for duplicate */ - if (custom_ext_find(exts, ext_type)) - return 0; - exts->meths = OPENSSL_realloc(exts->meths, - (exts->meths_count + 1) * sizeof(custom_ext_method)); +/* Set callbacks for a custom extension. */ +static int custom_ext_meth_add(custom_ext_methods *exts, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + custom_ext_method *meth; + /* + * Check application error: if add_cb is not set free_cb will never be + * called. + */ + if (!add_cb && free_cb) + return 0; + /* Don't add if extension supported internally. */ + if (SSL_extension_supported(ext_type)) + return 0; + /* Extension type must fit in 16 bits */ + if (ext_type > 0xffff) + return 0; + /* Search for duplicate */ + if (custom_ext_find(exts, ext_type)) + return 0; + exts->meths = OPENSSL_realloc(exts->meths, + (exts->meths_count + + 1) * sizeof(custom_ext_method)); - if (!exts->meths) - { - exts->meths_count = 0; - return 0; - } + if (!exts->meths) { + exts->meths_count = 0; + return 0; + } - meth = exts->meths + exts->meths_count; - memset(meth, 0, sizeof(custom_ext_method)); - meth->parse_cb = parse_cb; - meth->add_cb = add_cb; - meth->ext_type = ext_type; - meth->arg = arg; - exts->meths_count++; - return 1; - } + meth = exts->meths + exts->meths_count; + memset(meth, 0, sizeof(*meth)); + meth->parse_cb = parse_cb; + meth->add_cb = add_cb; + meth->free_cb = free_cb; + meth->ext_type = ext_type; + meth->add_arg = add_arg; + meth->parse_arg = parse_arg; + exts->meths_count++; + return 1; +} /* Application level functions to add custom extension callbacks */ +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg) +{ + return custom_ext_meth_add(&ctx->cert->cli_ext, ext_type, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} -int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned int ext_type, - custom_ext_add_cb add_cb, - custom_ext_parse_cb parse_cb, void *arg) +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg) +{ + return custom_ext_meth_add(&ctx->cert->srv_ext, ext_type, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} - { - return custom_ext_set(&ctx->cert->cli_ext, ext_type, parse_cb, add_cb, - arg); - } - -int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned int ext_type, - custom_ext_parse_cb parse_cb, - custom_ext_add_cb add_cb, void *arg) - { - return custom_ext_set(&ctx->cert->srv_ext, ext_type, parse_cb, add_cb, - arg); - } +int SSL_extension_supported(unsigned int ext_type) +{ + switch (ext_type) { + /* Internally supported extensions. */ + case TLSEXT_TYPE_application_layer_protocol_negotiation: + case TLSEXT_TYPE_ec_point_formats: + case TLSEXT_TYPE_elliptic_curves: + case TLSEXT_TYPE_heartbeat: + case TLSEXT_TYPE_next_proto_neg: + case TLSEXT_TYPE_padding: + case TLSEXT_TYPE_renegotiate: + case TLSEXT_TYPE_server_name: + case TLSEXT_TYPE_session_ticket: + case TLSEXT_TYPE_signature_algorithms: + case TLSEXT_TYPE_srp: + case TLSEXT_TYPE_status_request: + case TLSEXT_TYPE_use_srtp: +#ifdef TLSEXT_TYPE_encrypt_then_mac + case TLSEXT_TYPE_encrypt_then_mac: #endif + return 1; + default: + return 0; + } +}