11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* Custom extension utility functions */ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include <openssl/ct.h> 131cb0ef41Sopenharmony_ci#include "../ssl_local.h" 141cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 151cb0ef41Sopenharmony_ci#include "statem_local.h" 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_citypedef struct { 181cb0ef41Sopenharmony_ci void *add_arg; 191cb0ef41Sopenharmony_ci custom_ext_add_cb add_cb; 201cb0ef41Sopenharmony_ci custom_ext_free_cb free_cb; 211cb0ef41Sopenharmony_ci} custom_ext_add_cb_wrap; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_citypedef struct { 241cb0ef41Sopenharmony_ci void *parse_arg; 251cb0ef41Sopenharmony_ci custom_ext_parse_cb parse_cb; 261cb0ef41Sopenharmony_ci} custom_ext_parse_cb_wrap; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci/* 291cb0ef41Sopenharmony_ci * Provide thin wrapper callbacks which convert new style arguments to old style 301cb0ef41Sopenharmony_ci */ 311cb0ef41Sopenharmony_cistatic int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type, 321cb0ef41Sopenharmony_ci unsigned int context, 331cb0ef41Sopenharmony_ci const unsigned char **out, 341cb0ef41Sopenharmony_ci size_t *outlen, X509 *x, size_t chainidx, 351cb0ef41Sopenharmony_ci int *al, void *add_arg) 361cb0ef41Sopenharmony_ci{ 371cb0ef41Sopenharmony_ci custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci if (add_cb_wrap->add_cb == NULL) 401cb0ef41Sopenharmony_ci return 1; 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci return add_cb_wrap->add_cb(s, ext_type, out, outlen, al, 431cb0ef41Sopenharmony_ci add_cb_wrap->add_arg); 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_cistatic void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type, 471cb0ef41Sopenharmony_ci unsigned int context, 481cb0ef41Sopenharmony_ci const unsigned char *out, void *add_arg) 491cb0ef41Sopenharmony_ci{ 501cb0ef41Sopenharmony_ci custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci if (add_cb_wrap->free_cb == NULL) 531cb0ef41Sopenharmony_ci return; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg); 561cb0ef41Sopenharmony_ci} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_cistatic int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type, 591cb0ef41Sopenharmony_ci unsigned int context, 601cb0ef41Sopenharmony_ci const unsigned char *in, 611cb0ef41Sopenharmony_ci size_t inlen, X509 *x, size_t chainidx, 621cb0ef41Sopenharmony_ci int *al, void *parse_arg) 631cb0ef41Sopenharmony_ci{ 641cb0ef41Sopenharmony_ci custom_ext_parse_cb_wrap *parse_cb_wrap = 651cb0ef41Sopenharmony_ci (custom_ext_parse_cb_wrap *)parse_arg; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci if (parse_cb_wrap->parse_cb == NULL) 681cb0ef41Sopenharmony_ci return 1; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al, 711cb0ef41Sopenharmony_ci parse_cb_wrap->parse_arg); 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci/* 751cb0ef41Sopenharmony_ci * Find a custom extension from the list. The |role| param is there to 761cb0ef41Sopenharmony_ci * support the legacy API where custom extensions for client and server could 771cb0ef41Sopenharmony_ci * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we 781cb0ef41Sopenharmony_ci * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the 791cb0ef41Sopenharmony_ci * client, or ENDPOINT_BOTH for either 801cb0ef41Sopenharmony_ci */ 811cb0ef41Sopenharmony_cicustom_ext_method *custom_ext_find(const custom_ext_methods *exts, 821cb0ef41Sopenharmony_ci ENDPOINT role, unsigned int ext_type, 831cb0ef41Sopenharmony_ci size_t *idx) 841cb0ef41Sopenharmony_ci{ 851cb0ef41Sopenharmony_ci size_t i; 861cb0ef41Sopenharmony_ci custom_ext_method *meth = exts->meths; 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci for (i = 0; i < exts->meths_count; i++, meth++) { 891cb0ef41Sopenharmony_ci if (ext_type == meth->ext_type 901cb0ef41Sopenharmony_ci && (role == ENDPOINT_BOTH || role == meth->role 911cb0ef41Sopenharmony_ci || meth->role == ENDPOINT_BOTH)) { 921cb0ef41Sopenharmony_ci if (idx != NULL) 931cb0ef41Sopenharmony_ci *idx = i; 941cb0ef41Sopenharmony_ci return meth; 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci return NULL; 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci/* 1011cb0ef41Sopenharmony_ci * Initialise custom extensions flags to indicate neither sent nor received. 1021cb0ef41Sopenharmony_ci */ 1031cb0ef41Sopenharmony_civoid custom_ext_init(custom_ext_methods *exts) 1041cb0ef41Sopenharmony_ci{ 1051cb0ef41Sopenharmony_ci size_t i; 1061cb0ef41Sopenharmony_ci custom_ext_method *meth = exts->meths; 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci for (i = 0; i < exts->meths_count; i++, meth++) 1091cb0ef41Sopenharmony_ci meth->ext_flags = 0; 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci/* Pass received custom extension data to the application for parsing. */ 1131cb0ef41Sopenharmony_ciint custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type, 1141cb0ef41Sopenharmony_ci const unsigned char *ext_data, size_t ext_size, X509 *x, 1151cb0ef41Sopenharmony_ci size_t chainidx) 1161cb0ef41Sopenharmony_ci{ 1171cb0ef41Sopenharmony_ci int al; 1181cb0ef41Sopenharmony_ci custom_ext_methods *exts = &s->cert->custext; 1191cb0ef41Sopenharmony_ci custom_ext_method *meth; 1201cb0ef41Sopenharmony_ci ENDPOINT role = ENDPOINT_BOTH; 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0) 1231cb0ef41Sopenharmony_ci role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT; 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci meth = custom_ext_find(exts, role, ext_type, NULL); 1261cb0ef41Sopenharmony_ci /* If not found return success */ 1271cb0ef41Sopenharmony_ci if (!meth) 1281cb0ef41Sopenharmony_ci return 1; 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci /* Check if extension is defined for our protocol. If not, skip */ 1311cb0ef41Sopenharmony_ci if (!extension_is_relevant(s, meth->context, context)) 1321cb0ef41Sopenharmony_ci return 1; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO 1351cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_SERVER_HELLO 1361cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) { 1371cb0ef41Sopenharmony_ci /* 1381cb0ef41Sopenharmony_ci * If it's ServerHello or EncryptedExtensions we can't have any 1391cb0ef41Sopenharmony_ci * extensions not sent in ClientHello. 1401cb0ef41Sopenharmony_ci */ 1411cb0ef41Sopenharmony_ci if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) { 1421cb0ef41Sopenharmony_ci SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION); 1431cb0ef41Sopenharmony_ci return 0; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci /* 1481cb0ef41Sopenharmony_ci * Extensions received in the ClientHello or CertificateRequest are marked 1491cb0ef41Sopenharmony_ci * with the SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent 1501cb0ef41Sopenharmony_ci * extensions in the response messages 1511cb0ef41Sopenharmony_ci */ 1521cb0ef41Sopenharmony_ci if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST)) 1531cb0ef41Sopenharmony_ci != 0) 1541cb0ef41Sopenharmony_ci meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci /* If no parse function set return success */ 1571cb0ef41Sopenharmony_ci if (!meth->parse_cb) 1581cb0ef41Sopenharmony_ci return 1; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx, 1611cb0ef41Sopenharmony_ci &al, meth->parse_arg) <= 0) { 1621cb0ef41Sopenharmony_ci SSLfatal(s, al, SSL_R_BAD_EXTENSION); 1631cb0ef41Sopenharmony_ci return 0; 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci return 1; 1671cb0ef41Sopenharmony_ci} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci/* 1701cb0ef41Sopenharmony_ci * Request custom extension data from the application and add to the return 1711cb0ef41Sopenharmony_ci * buffer. 1721cb0ef41Sopenharmony_ci */ 1731cb0ef41Sopenharmony_ciint custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx, 1741cb0ef41Sopenharmony_ci int maxversion) 1751cb0ef41Sopenharmony_ci{ 1761cb0ef41Sopenharmony_ci custom_ext_methods *exts = &s->cert->custext; 1771cb0ef41Sopenharmony_ci custom_ext_method *meth; 1781cb0ef41Sopenharmony_ci size_t i; 1791cb0ef41Sopenharmony_ci int al; 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci for (i = 0; i < exts->meths_count; i++) { 1821cb0ef41Sopenharmony_ci const unsigned char *out = NULL; 1831cb0ef41Sopenharmony_ci size_t outlen = 0; 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci meth = exts->meths + i; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci if (!should_add_extension(s, meth->context, context, maxversion)) 1881cb0ef41Sopenharmony_ci continue; 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO 1911cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_SERVER_HELLO 1921cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 1931cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_CERTIFICATE 1941cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) { 1951cb0ef41Sopenharmony_ci /* Only send extensions present in ClientHello/CertificateRequest */ 1961cb0ef41Sopenharmony_ci if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) 1971cb0ef41Sopenharmony_ci continue; 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci /* 2001cb0ef41Sopenharmony_ci * We skip it if the callback is absent - except for a ClientHello where 2011cb0ef41Sopenharmony_ci * we add an empty extension. 2021cb0ef41Sopenharmony_ci */ 2031cb0ef41Sopenharmony_ci if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL) 2041cb0ef41Sopenharmony_ci continue; 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci if (meth->add_cb != NULL) { 2071cb0ef41Sopenharmony_ci int cb_retval = meth->add_cb(s, meth->ext_type, context, &out, 2081cb0ef41Sopenharmony_ci &outlen, x, chainidx, &al, 2091cb0ef41Sopenharmony_ci meth->add_arg); 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci if (cb_retval < 0) { 2121cb0ef41Sopenharmony_ci SSLfatal(s, al, SSL_R_CALLBACK_FAILED); 2131cb0ef41Sopenharmony_ci return 0; /* error */ 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci if (cb_retval == 0) 2161cb0ef41Sopenharmony_ci continue; /* skip this extension */ 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci if (!WPACKET_put_bytes_u16(pkt, meth->ext_type) 2201cb0ef41Sopenharmony_ci || !WPACKET_start_sub_packet_u16(pkt) 2211cb0ef41Sopenharmony_ci || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen)) 2221cb0ef41Sopenharmony_ci || !WPACKET_close(pkt)) { 2231cb0ef41Sopenharmony_ci if (meth->free_cb != NULL) 2241cb0ef41Sopenharmony_ci meth->free_cb(s, meth->ext_type, context, out, meth->add_arg); 2251cb0ef41Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); 2261cb0ef41Sopenharmony_ci return 0; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci if ((context & SSL_EXT_CLIENT_HELLO) != 0) { 2291cb0ef41Sopenharmony_ci /* 2301cb0ef41Sopenharmony_ci * We can't send duplicates: code logic should prevent this. 2311cb0ef41Sopenharmony_ci */ 2321cb0ef41Sopenharmony_ci if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) { 2331cb0ef41Sopenharmony_ci if (meth->free_cb != NULL) 2341cb0ef41Sopenharmony_ci meth->free_cb(s, meth->ext_type, context, out, 2351cb0ef41Sopenharmony_ci meth->add_arg); 2361cb0ef41Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); 2371cb0ef41Sopenharmony_ci return 0; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci /* 2401cb0ef41Sopenharmony_ci * Indicate extension has been sent: this is both a sanity check to 2411cb0ef41Sopenharmony_ci * ensure we don't send duplicate extensions and indicates that it 2421cb0ef41Sopenharmony_ci * is not an error if the extension is present in ServerHello. 2431cb0ef41Sopenharmony_ci */ 2441cb0ef41Sopenharmony_ci meth->ext_flags |= SSL_EXT_FLAG_SENT; 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci if (meth->free_cb != NULL) 2471cb0ef41Sopenharmony_ci meth->free_cb(s, meth->ext_type, context, out, meth->add_arg); 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci return 1; 2501cb0ef41Sopenharmony_ci} 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci/* Copy the flags from src to dst for any extensions that exist in both */ 2531cb0ef41Sopenharmony_ciint custom_exts_copy_flags(custom_ext_methods *dst, 2541cb0ef41Sopenharmony_ci const custom_ext_methods *src) 2551cb0ef41Sopenharmony_ci{ 2561cb0ef41Sopenharmony_ci size_t i; 2571cb0ef41Sopenharmony_ci custom_ext_method *methsrc = src->meths; 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci for (i = 0; i < src->meths_count; i++, methsrc++) { 2601cb0ef41Sopenharmony_ci custom_ext_method *methdst = custom_ext_find(dst, methsrc->role, 2611cb0ef41Sopenharmony_ci methsrc->ext_type, NULL); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci if (methdst == NULL) 2641cb0ef41Sopenharmony_ci continue; 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci methdst->ext_flags = methsrc->ext_flags; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci return 1; 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci/* Copy table of custom extensions */ 2731cb0ef41Sopenharmony_ciint custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) 2741cb0ef41Sopenharmony_ci{ 2751cb0ef41Sopenharmony_ci size_t i; 2761cb0ef41Sopenharmony_ci int err = 0; 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci if (src->meths_count > 0) { 2791cb0ef41Sopenharmony_ci dst->meths = 2801cb0ef41Sopenharmony_ci OPENSSL_memdup(src->meths, 2811cb0ef41Sopenharmony_ci sizeof(*src->meths) * src->meths_count); 2821cb0ef41Sopenharmony_ci if (dst->meths == NULL) 2831cb0ef41Sopenharmony_ci return 0; 2841cb0ef41Sopenharmony_ci dst->meths_count = src->meths_count; 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci for (i = 0; i < src->meths_count; i++) { 2871cb0ef41Sopenharmony_ci custom_ext_method *methsrc = src->meths + i; 2881cb0ef41Sopenharmony_ci custom_ext_method *methdst = dst->meths + i; 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci if (methsrc->add_cb != custom_ext_add_old_cb_wrap) 2911cb0ef41Sopenharmony_ci continue; 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci /* 2941cb0ef41Sopenharmony_ci * We have found an old style API wrapper. We need to copy the 2951cb0ef41Sopenharmony_ci * arguments too. 2961cb0ef41Sopenharmony_ci */ 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci if (err) { 2991cb0ef41Sopenharmony_ci methdst->add_arg = NULL; 3001cb0ef41Sopenharmony_ci methdst->parse_arg = NULL; 3011cb0ef41Sopenharmony_ci continue; 3021cb0ef41Sopenharmony_ci } 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci methdst->add_arg = OPENSSL_memdup(methsrc->add_arg, 3051cb0ef41Sopenharmony_ci sizeof(custom_ext_add_cb_wrap)); 3061cb0ef41Sopenharmony_ci methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg, 3071cb0ef41Sopenharmony_ci sizeof(custom_ext_parse_cb_wrap)); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci if (methdst->add_arg == NULL || methdst->parse_arg == NULL) 3101cb0ef41Sopenharmony_ci err = 1; 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci if (err) { 3151cb0ef41Sopenharmony_ci custom_exts_free(dst); 3161cb0ef41Sopenharmony_ci return 0; 3171cb0ef41Sopenharmony_ci } 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci return 1; 3201cb0ef41Sopenharmony_ci} 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_civoid custom_exts_free(custom_ext_methods *exts) 3231cb0ef41Sopenharmony_ci{ 3241cb0ef41Sopenharmony_ci size_t i; 3251cb0ef41Sopenharmony_ci custom_ext_method *meth; 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ci for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) { 3281cb0ef41Sopenharmony_ci if (meth->add_cb != custom_ext_add_old_cb_wrap) 3291cb0ef41Sopenharmony_ci continue; 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci /* Old style API wrapper. Need to free the arguments too */ 3321cb0ef41Sopenharmony_ci OPENSSL_free(meth->add_arg); 3331cb0ef41Sopenharmony_ci OPENSSL_free(meth->parse_arg); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci OPENSSL_free(exts->meths); 3361cb0ef41Sopenharmony_ci exts->meths = NULL; 3371cb0ef41Sopenharmony_ci exts->meths_count = 0; 3381cb0ef41Sopenharmony_ci} 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci/* Return true if a client custom extension exists, false otherwise */ 3411cb0ef41Sopenharmony_ciint SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type) 3421cb0ef41Sopenharmony_ci{ 3431cb0ef41Sopenharmony_ci return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type, 3441cb0ef41Sopenharmony_ci NULL) != NULL; 3451cb0ef41Sopenharmony_ci} 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_cistatic int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role, 3481cb0ef41Sopenharmony_ci unsigned int ext_type, 3491cb0ef41Sopenharmony_ci unsigned int context, 3501cb0ef41Sopenharmony_ci SSL_custom_ext_add_cb_ex add_cb, 3511cb0ef41Sopenharmony_ci SSL_custom_ext_free_cb_ex free_cb, 3521cb0ef41Sopenharmony_ci void *add_arg, 3531cb0ef41Sopenharmony_ci SSL_custom_ext_parse_cb_ex parse_cb, 3541cb0ef41Sopenharmony_ci void *parse_arg) 3551cb0ef41Sopenharmony_ci{ 3561cb0ef41Sopenharmony_ci custom_ext_methods *exts = &ctx->cert->custext; 3571cb0ef41Sopenharmony_ci custom_ext_method *meth, *tmp; 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci /* 3601cb0ef41Sopenharmony_ci * Check application error: if add_cb is not set free_cb will never be 3611cb0ef41Sopenharmony_ci * called. 3621cb0ef41Sopenharmony_ci */ 3631cb0ef41Sopenharmony_ci if (add_cb == NULL && free_cb != NULL) 3641cb0ef41Sopenharmony_ci return 0; 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_CT 3671cb0ef41Sopenharmony_ci /* 3681cb0ef41Sopenharmony_ci * We don't want applications registering callbacks for SCT extensions 3691cb0ef41Sopenharmony_ci * whilst simultaneously using the built-in SCT validation features, as 3701cb0ef41Sopenharmony_ci * these two things may not play well together. 3711cb0ef41Sopenharmony_ci */ 3721cb0ef41Sopenharmony_ci if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp 3731cb0ef41Sopenharmony_ci && (context & SSL_EXT_CLIENT_HELLO) != 0 3741cb0ef41Sopenharmony_ci && SSL_CTX_ct_is_enabled(ctx)) 3751cb0ef41Sopenharmony_ci return 0; 3761cb0ef41Sopenharmony_ci#endif 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci /* 3791cb0ef41Sopenharmony_ci * Don't add if extension supported internally, but make exception 3801cb0ef41Sopenharmony_ci * for extension types that previously were not supported, but now are. 3811cb0ef41Sopenharmony_ci */ 3821cb0ef41Sopenharmony_ci if (SSL_extension_supported(ext_type) 3831cb0ef41Sopenharmony_ci && ext_type != TLSEXT_TYPE_signed_certificate_timestamp) 3841cb0ef41Sopenharmony_ci return 0; 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci /* Extension type must fit in 16 bits */ 3871cb0ef41Sopenharmony_ci if (ext_type > 0xffff) 3881cb0ef41Sopenharmony_ci return 0; 3891cb0ef41Sopenharmony_ci /* Search for duplicate */ 3901cb0ef41Sopenharmony_ci if (custom_ext_find(exts, role, ext_type, NULL)) 3911cb0ef41Sopenharmony_ci return 0; 3921cb0ef41Sopenharmony_ci tmp = OPENSSL_realloc(exts->meths, 3931cb0ef41Sopenharmony_ci (exts->meths_count + 1) * sizeof(custom_ext_method)); 3941cb0ef41Sopenharmony_ci if (tmp == NULL) 3951cb0ef41Sopenharmony_ci return 0; 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci exts->meths = tmp; 3981cb0ef41Sopenharmony_ci meth = exts->meths + exts->meths_count; 3991cb0ef41Sopenharmony_ci memset(meth, 0, sizeof(*meth)); 4001cb0ef41Sopenharmony_ci meth->role = role; 4011cb0ef41Sopenharmony_ci meth->context = context; 4021cb0ef41Sopenharmony_ci meth->parse_cb = parse_cb; 4031cb0ef41Sopenharmony_ci meth->add_cb = add_cb; 4041cb0ef41Sopenharmony_ci meth->free_cb = free_cb; 4051cb0ef41Sopenharmony_ci meth->ext_type = ext_type; 4061cb0ef41Sopenharmony_ci meth->add_arg = add_arg; 4071cb0ef41Sopenharmony_ci meth->parse_arg = parse_arg; 4081cb0ef41Sopenharmony_ci exts->meths_count++; 4091cb0ef41Sopenharmony_ci return 1; 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_cistatic int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role, 4131cb0ef41Sopenharmony_ci unsigned int ext_type, 4141cb0ef41Sopenharmony_ci unsigned int context, 4151cb0ef41Sopenharmony_ci custom_ext_add_cb add_cb, 4161cb0ef41Sopenharmony_ci custom_ext_free_cb free_cb, 4171cb0ef41Sopenharmony_ci void *add_arg, 4181cb0ef41Sopenharmony_ci custom_ext_parse_cb parse_cb, void *parse_arg) 4191cb0ef41Sopenharmony_ci{ 4201cb0ef41Sopenharmony_ci custom_ext_add_cb_wrap *add_cb_wrap 4211cb0ef41Sopenharmony_ci = OPENSSL_malloc(sizeof(*add_cb_wrap)); 4221cb0ef41Sopenharmony_ci custom_ext_parse_cb_wrap *parse_cb_wrap 4231cb0ef41Sopenharmony_ci = OPENSSL_malloc(sizeof(*parse_cb_wrap)); 4241cb0ef41Sopenharmony_ci int ret; 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci if (add_cb_wrap == NULL || parse_cb_wrap == NULL) { 4271cb0ef41Sopenharmony_ci OPENSSL_free(add_cb_wrap); 4281cb0ef41Sopenharmony_ci OPENSSL_free(parse_cb_wrap); 4291cb0ef41Sopenharmony_ci return 0; 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci add_cb_wrap->add_arg = add_arg; 4331cb0ef41Sopenharmony_ci add_cb_wrap->add_cb = add_cb; 4341cb0ef41Sopenharmony_ci add_cb_wrap->free_cb = free_cb; 4351cb0ef41Sopenharmony_ci parse_cb_wrap->parse_arg = parse_arg; 4361cb0ef41Sopenharmony_ci parse_cb_wrap->parse_cb = parse_cb; 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci ret = add_custom_ext_intern(ctx, role, ext_type, 4391cb0ef41Sopenharmony_ci context, 4401cb0ef41Sopenharmony_ci custom_ext_add_old_cb_wrap, 4411cb0ef41Sopenharmony_ci custom_ext_free_old_cb_wrap, 4421cb0ef41Sopenharmony_ci add_cb_wrap, 4431cb0ef41Sopenharmony_ci custom_ext_parse_old_cb_wrap, 4441cb0ef41Sopenharmony_ci parse_cb_wrap); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci if (!ret) { 4471cb0ef41Sopenharmony_ci OPENSSL_free(add_cb_wrap); 4481cb0ef41Sopenharmony_ci OPENSSL_free(parse_cb_wrap); 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci return ret; 4521cb0ef41Sopenharmony_ci} 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci/* Application level functions to add the old custom extension callbacks */ 4551cb0ef41Sopenharmony_ciint SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 4561cb0ef41Sopenharmony_ci custom_ext_add_cb add_cb, 4571cb0ef41Sopenharmony_ci custom_ext_free_cb free_cb, 4581cb0ef41Sopenharmony_ci void *add_arg, 4591cb0ef41Sopenharmony_ci custom_ext_parse_cb parse_cb, void *parse_arg) 4601cb0ef41Sopenharmony_ci{ 4611cb0ef41Sopenharmony_ci return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type, 4621cb0ef41Sopenharmony_ci SSL_EXT_TLS1_2_AND_BELOW_ONLY 4631cb0ef41Sopenharmony_ci | SSL_EXT_CLIENT_HELLO 4641cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_2_SERVER_HELLO 4651cb0ef41Sopenharmony_ci | SSL_EXT_IGNORE_ON_RESUMPTION, 4661cb0ef41Sopenharmony_ci add_cb, free_cb, add_arg, parse_cb, parse_arg); 4671cb0ef41Sopenharmony_ci} 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ciint SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 4701cb0ef41Sopenharmony_ci custom_ext_add_cb add_cb, 4711cb0ef41Sopenharmony_ci custom_ext_free_cb free_cb, 4721cb0ef41Sopenharmony_ci void *add_arg, 4731cb0ef41Sopenharmony_ci custom_ext_parse_cb parse_cb, void *parse_arg) 4741cb0ef41Sopenharmony_ci{ 4751cb0ef41Sopenharmony_ci return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type, 4761cb0ef41Sopenharmony_ci SSL_EXT_TLS1_2_AND_BELOW_ONLY 4771cb0ef41Sopenharmony_ci | SSL_EXT_CLIENT_HELLO 4781cb0ef41Sopenharmony_ci | SSL_EXT_TLS1_2_SERVER_HELLO 4791cb0ef41Sopenharmony_ci | SSL_EXT_IGNORE_ON_RESUMPTION, 4801cb0ef41Sopenharmony_ci add_cb, free_cb, add_arg, parse_cb, parse_arg); 4811cb0ef41Sopenharmony_ci} 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ciint SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 4841cb0ef41Sopenharmony_ci unsigned int context, 4851cb0ef41Sopenharmony_ci SSL_custom_ext_add_cb_ex add_cb, 4861cb0ef41Sopenharmony_ci SSL_custom_ext_free_cb_ex free_cb, 4871cb0ef41Sopenharmony_ci void *add_arg, 4881cb0ef41Sopenharmony_ci SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg) 4891cb0ef41Sopenharmony_ci{ 4901cb0ef41Sopenharmony_ci return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb, 4911cb0ef41Sopenharmony_ci free_cb, add_arg, parse_cb, parse_arg); 4921cb0ef41Sopenharmony_ci} 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ciint SSL_extension_supported(unsigned int ext_type) 4951cb0ef41Sopenharmony_ci{ 4961cb0ef41Sopenharmony_ci switch (ext_type) { 4971cb0ef41Sopenharmony_ci /* Internally supported extensions. */ 4981cb0ef41Sopenharmony_ci case TLSEXT_TYPE_application_layer_protocol_negotiation: 4991cb0ef41Sopenharmony_ci case TLSEXT_TYPE_ec_point_formats: 5001cb0ef41Sopenharmony_ci case TLSEXT_TYPE_supported_groups: 5011cb0ef41Sopenharmony_ci case TLSEXT_TYPE_key_share: 5021cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG 5031cb0ef41Sopenharmony_ci case TLSEXT_TYPE_next_proto_neg: 5041cb0ef41Sopenharmony_ci#endif 5051cb0ef41Sopenharmony_ci case TLSEXT_TYPE_padding: 5061cb0ef41Sopenharmony_ci case TLSEXT_TYPE_renegotiate: 5071cb0ef41Sopenharmony_ci case TLSEXT_TYPE_max_fragment_length: 5081cb0ef41Sopenharmony_ci case TLSEXT_TYPE_server_name: 5091cb0ef41Sopenharmony_ci case TLSEXT_TYPE_session_ticket: 5101cb0ef41Sopenharmony_ci case TLSEXT_TYPE_signature_algorithms: 5111cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_SRP 5121cb0ef41Sopenharmony_ci case TLSEXT_TYPE_srp: 5131cb0ef41Sopenharmony_ci#endif 5141cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_OCSP 5151cb0ef41Sopenharmony_ci case TLSEXT_TYPE_status_request: 5161cb0ef41Sopenharmony_ci#endif 5171cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_CT 5181cb0ef41Sopenharmony_ci case TLSEXT_TYPE_signed_certificate_timestamp: 5191cb0ef41Sopenharmony_ci#endif 5201cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_SRTP 5211cb0ef41Sopenharmony_ci case TLSEXT_TYPE_use_srtp: 5221cb0ef41Sopenharmony_ci#endif 5231cb0ef41Sopenharmony_ci case TLSEXT_TYPE_encrypt_then_mac: 5241cb0ef41Sopenharmony_ci case TLSEXT_TYPE_supported_versions: 5251cb0ef41Sopenharmony_ci case TLSEXT_TYPE_extended_master_secret: 5261cb0ef41Sopenharmony_ci case TLSEXT_TYPE_psk_kex_modes: 5271cb0ef41Sopenharmony_ci case TLSEXT_TYPE_cookie: 5281cb0ef41Sopenharmony_ci case TLSEXT_TYPE_early_data: 5291cb0ef41Sopenharmony_ci case TLSEXT_TYPE_certificate_authorities: 5301cb0ef41Sopenharmony_ci case TLSEXT_TYPE_psk: 5311cb0ef41Sopenharmony_ci case TLSEXT_TYPE_post_handshake_auth: 5321cb0ef41Sopenharmony_ci return 1; 5331cb0ef41Sopenharmony_ci default: 5341cb0ef41Sopenharmony_ci return 0; 5351cb0ef41Sopenharmony_ci } 5361cb0ef41Sopenharmony_ci} 537