1e71b7053SJung-uk Kim /* 2e71b7053SJung-uk Kim * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. 3e71b7053SJung-uk Kim * 4e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8e71b7053SJung-uk Kim */ 9e71b7053SJung-uk Kim 10e71b7053SJung-uk Kim /* Custom extension utility functions */ 11e71b7053SJung-uk Kim 12e71b7053SJung-uk Kim #include <openssl/ct.h> 13*17f01e99SJung-uk Kim #include "../ssl_local.h" 14e71b7053SJung-uk Kim #include "internal/cryptlib.h" 15*17f01e99SJung-uk Kim #include "statem_local.h" 16e71b7053SJung-uk Kim 17e71b7053SJung-uk Kim typedef struct { 18e71b7053SJung-uk Kim void *add_arg; 19e71b7053SJung-uk Kim custom_ext_add_cb add_cb; 20e71b7053SJung-uk Kim custom_ext_free_cb free_cb; 21e71b7053SJung-uk Kim } custom_ext_add_cb_wrap; 22e71b7053SJung-uk Kim 23e71b7053SJung-uk Kim typedef struct { 24e71b7053SJung-uk Kim void *parse_arg; 25e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb; 26e71b7053SJung-uk Kim } custom_ext_parse_cb_wrap; 27e71b7053SJung-uk Kim 28e71b7053SJung-uk Kim /* 29e71b7053SJung-uk Kim * Provide thin wrapper callbacks which convert new style arguments to old style 30e71b7053SJung-uk Kim */ 31e71b7053SJung-uk Kim static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type, 32e71b7053SJung-uk Kim unsigned int context, 33e71b7053SJung-uk Kim const unsigned char **out, 34e71b7053SJung-uk Kim size_t *outlen, X509 *x, size_t chainidx, 35e71b7053SJung-uk Kim int *al, void *add_arg) 36e71b7053SJung-uk Kim { 37e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; 38e71b7053SJung-uk Kim 39e71b7053SJung-uk Kim if (add_cb_wrap->add_cb == NULL) 40e71b7053SJung-uk Kim return 1; 41e71b7053SJung-uk Kim 42e71b7053SJung-uk Kim return add_cb_wrap->add_cb(s, ext_type, out, outlen, al, 43e71b7053SJung-uk Kim add_cb_wrap->add_arg); 44e71b7053SJung-uk Kim } 45e71b7053SJung-uk Kim 46e71b7053SJung-uk Kim static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type, 47e71b7053SJung-uk Kim unsigned int context, 48e71b7053SJung-uk Kim const unsigned char *out, void *add_arg) 49e71b7053SJung-uk Kim { 50e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; 51e71b7053SJung-uk Kim 52e71b7053SJung-uk Kim if (add_cb_wrap->free_cb == NULL) 53e71b7053SJung-uk Kim return; 54e71b7053SJung-uk Kim 55e71b7053SJung-uk Kim add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg); 56e71b7053SJung-uk Kim } 57e71b7053SJung-uk Kim 58e71b7053SJung-uk Kim static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type, 59e71b7053SJung-uk Kim unsigned int context, 60e71b7053SJung-uk Kim const unsigned char *in, 61e71b7053SJung-uk Kim size_t inlen, X509 *x, size_t chainidx, 62e71b7053SJung-uk Kim int *al, void *parse_arg) 63e71b7053SJung-uk Kim { 64e71b7053SJung-uk Kim custom_ext_parse_cb_wrap *parse_cb_wrap = 65e71b7053SJung-uk Kim (custom_ext_parse_cb_wrap *)parse_arg; 66e71b7053SJung-uk Kim 67e71b7053SJung-uk Kim if (parse_cb_wrap->parse_cb == NULL) 68e71b7053SJung-uk Kim return 1; 69e71b7053SJung-uk Kim 70e71b7053SJung-uk Kim return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al, 71e71b7053SJung-uk Kim parse_cb_wrap->parse_arg); 72e71b7053SJung-uk Kim } 73e71b7053SJung-uk Kim 74e71b7053SJung-uk Kim /* 75e71b7053SJung-uk Kim * Find a custom extension from the list. The |role| param is there to 76e71b7053SJung-uk Kim * support the legacy API where custom extensions for client and server could 77e71b7053SJung-uk Kim * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we 78e71b7053SJung-uk Kim * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the 79e71b7053SJung-uk Kim * client, or ENDPOINT_BOTH for either 80e71b7053SJung-uk Kim */ 81e71b7053SJung-uk Kim custom_ext_method *custom_ext_find(const custom_ext_methods *exts, 82e71b7053SJung-uk Kim ENDPOINT role, unsigned int ext_type, 83e71b7053SJung-uk Kim size_t *idx) 84e71b7053SJung-uk Kim { 85e71b7053SJung-uk Kim size_t i; 86e71b7053SJung-uk Kim custom_ext_method *meth = exts->meths; 87e71b7053SJung-uk Kim 88e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++, meth++) { 89e71b7053SJung-uk Kim if (ext_type == meth->ext_type 90e71b7053SJung-uk Kim && (role == ENDPOINT_BOTH || role == meth->role 91e71b7053SJung-uk Kim || meth->role == ENDPOINT_BOTH)) { 92e71b7053SJung-uk Kim if (idx != NULL) 93e71b7053SJung-uk Kim *idx = i; 94e71b7053SJung-uk Kim return meth; 95e71b7053SJung-uk Kim } 96e71b7053SJung-uk Kim } 97e71b7053SJung-uk Kim return NULL; 98e71b7053SJung-uk Kim } 99e71b7053SJung-uk Kim 100e71b7053SJung-uk Kim /* 101e71b7053SJung-uk Kim * Initialise custom extensions flags to indicate neither sent nor received. 102e71b7053SJung-uk Kim */ 103e71b7053SJung-uk Kim void custom_ext_init(custom_ext_methods *exts) 104e71b7053SJung-uk Kim { 105e71b7053SJung-uk Kim size_t i; 106e71b7053SJung-uk Kim custom_ext_method *meth = exts->meths; 107e71b7053SJung-uk Kim 108e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++, meth++) 109e71b7053SJung-uk Kim meth->ext_flags = 0; 110e71b7053SJung-uk Kim } 111e71b7053SJung-uk Kim 112e71b7053SJung-uk Kim /* Pass received custom extension data to the application for parsing. */ 113e71b7053SJung-uk Kim int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type, 114e71b7053SJung-uk Kim const unsigned char *ext_data, size_t ext_size, X509 *x, 115e71b7053SJung-uk Kim size_t chainidx) 116e71b7053SJung-uk Kim { 117e71b7053SJung-uk Kim int al; 118e71b7053SJung-uk Kim custom_ext_methods *exts = &s->cert->custext; 119e71b7053SJung-uk Kim custom_ext_method *meth; 120e71b7053SJung-uk Kim ENDPOINT role = ENDPOINT_BOTH; 121e71b7053SJung-uk Kim 122e71b7053SJung-uk Kim if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0) 123e71b7053SJung-uk Kim role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT; 124e71b7053SJung-uk Kim 125e71b7053SJung-uk Kim meth = custom_ext_find(exts, role, ext_type, NULL); 126e71b7053SJung-uk Kim /* If not found return success */ 127e71b7053SJung-uk Kim if (!meth) 128e71b7053SJung-uk Kim return 1; 129e71b7053SJung-uk Kim 130e71b7053SJung-uk Kim /* Check if extension is defined for our protocol. If not, skip */ 131e71b7053SJung-uk Kim if (!extension_is_relevant(s, meth->context, context)) 132e71b7053SJung-uk Kim return 1; 133e71b7053SJung-uk Kim 134e71b7053SJung-uk Kim if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO 135e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_SERVER_HELLO 136e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) { 137e71b7053SJung-uk Kim /* 138e71b7053SJung-uk Kim * If it's ServerHello or EncryptedExtensions we can't have any 139e71b7053SJung-uk Kim * extensions not sent in ClientHello. 140e71b7053SJung-uk Kim */ 141e71b7053SJung-uk Kim if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) { 142e71b7053SJung-uk Kim SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE, 143e71b7053SJung-uk Kim SSL_R_BAD_EXTENSION); 144e71b7053SJung-uk Kim return 0; 145e71b7053SJung-uk Kim } 146e71b7053SJung-uk Kim } 147e71b7053SJung-uk Kim 148e71b7053SJung-uk Kim /* 149e71b7053SJung-uk Kim * Extensions received in the ClientHello are marked with the 150e71b7053SJung-uk Kim * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent 151e71b7053SJung-uk Kim * extensions in the ServerHello/EncryptedExtensions message 152e71b7053SJung-uk Kim */ 153e71b7053SJung-uk Kim if ((context & SSL_EXT_CLIENT_HELLO) != 0) 154e71b7053SJung-uk Kim meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; 155e71b7053SJung-uk Kim 156e71b7053SJung-uk Kim /* If no parse function set return success */ 157e71b7053SJung-uk Kim if (!meth->parse_cb) 158e71b7053SJung-uk Kim return 1; 159e71b7053SJung-uk Kim 160e71b7053SJung-uk Kim if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx, 161e71b7053SJung-uk Kim &al, meth->parse_arg) <= 0) { 162e71b7053SJung-uk Kim SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION); 163e71b7053SJung-uk Kim return 0; 164e71b7053SJung-uk Kim } 165e71b7053SJung-uk Kim 166e71b7053SJung-uk Kim return 1; 167e71b7053SJung-uk Kim } 168e71b7053SJung-uk Kim 169e71b7053SJung-uk Kim /* 170e71b7053SJung-uk Kim * Request custom extension data from the application and add to the return 171e71b7053SJung-uk Kim * buffer. 172e71b7053SJung-uk Kim */ 173e71b7053SJung-uk Kim int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx, 174e71b7053SJung-uk Kim int maxversion) 175e71b7053SJung-uk Kim { 176e71b7053SJung-uk Kim custom_ext_methods *exts = &s->cert->custext; 177e71b7053SJung-uk Kim custom_ext_method *meth; 178e71b7053SJung-uk Kim size_t i; 179e71b7053SJung-uk Kim int al; 180e71b7053SJung-uk Kim 181e71b7053SJung-uk Kim for (i = 0; i < exts->meths_count; i++) { 182e71b7053SJung-uk Kim const unsigned char *out = NULL; 183e71b7053SJung-uk Kim size_t outlen = 0; 184e71b7053SJung-uk Kim 185e71b7053SJung-uk Kim meth = exts->meths + i; 186e71b7053SJung-uk Kim 187e71b7053SJung-uk Kim if (!should_add_extension(s, meth->context, context, maxversion)) 188e71b7053SJung-uk Kim continue; 189e71b7053SJung-uk Kim 190e71b7053SJung-uk Kim if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO 191e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_SERVER_HELLO 192e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 193e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_CERTIFICATE 194e71b7053SJung-uk Kim | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) { 195e71b7053SJung-uk Kim /* Only send extensions present in ClientHello. */ 196e71b7053SJung-uk Kim if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) 197e71b7053SJung-uk Kim continue; 198e71b7053SJung-uk Kim } 199e71b7053SJung-uk Kim /* 200e71b7053SJung-uk Kim * We skip it if the callback is absent - except for a ClientHello where 201e71b7053SJung-uk Kim * we add an empty extension. 202e71b7053SJung-uk Kim */ 203e71b7053SJung-uk Kim if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL) 204e71b7053SJung-uk Kim continue; 205e71b7053SJung-uk Kim 206e71b7053SJung-uk Kim if (meth->add_cb != NULL) { 207e71b7053SJung-uk Kim int cb_retval = meth->add_cb(s, meth->ext_type, context, &out, 208e71b7053SJung-uk Kim &outlen, x, chainidx, &al, 209e71b7053SJung-uk Kim meth->add_arg); 210e71b7053SJung-uk Kim 211e71b7053SJung-uk Kim if (cb_retval < 0) { 212e71b7053SJung-uk Kim SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED); 213e71b7053SJung-uk Kim return 0; /* error */ 214e71b7053SJung-uk Kim } 215e71b7053SJung-uk Kim if (cb_retval == 0) 216e71b7053SJung-uk Kim continue; /* skip this extension */ 217e71b7053SJung-uk Kim } 218e71b7053SJung-uk Kim 219e71b7053SJung-uk Kim if (!WPACKET_put_bytes_u16(pkt, meth->ext_type) 220e71b7053SJung-uk Kim || !WPACKET_start_sub_packet_u16(pkt) 221e71b7053SJung-uk Kim || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen)) 222e71b7053SJung-uk Kim || !WPACKET_close(pkt)) { 223e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD, 224e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 225e71b7053SJung-uk Kim return 0; 226e71b7053SJung-uk Kim } 227e71b7053SJung-uk Kim if ((context & SSL_EXT_CLIENT_HELLO) != 0) { 228e71b7053SJung-uk Kim /* 229e71b7053SJung-uk Kim * We can't send duplicates: code logic should prevent this. 230e71b7053SJung-uk Kim */ 231e71b7053SJung-uk Kim if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) { 232e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD, 233e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 234e71b7053SJung-uk Kim return 0; 235e71b7053SJung-uk Kim } 236e71b7053SJung-uk Kim /* 237e71b7053SJung-uk Kim * Indicate extension has been sent: this is both a sanity check to 238e71b7053SJung-uk Kim * ensure we don't send duplicate extensions and indicates that it 239e71b7053SJung-uk Kim * is not an error if the extension is present in ServerHello. 240e71b7053SJung-uk Kim */ 241e71b7053SJung-uk Kim meth->ext_flags |= SSL_EXT_FLAG_SENT; 242e71b7053SJung-uk Kim } 243e71b7053SJung-uk Kim if (meth->free_cb != NULL) 244e71b7053SJung-uk Kim meth->free_cb(s, meth->ext_type, context, out, meth->add_arg); 245e71b7053SJung-uk Kim } 246e71b7053SJung-uk Kim return 1; 247e71b7053SJung-uk Kim } 248e71b7053SJung-uk Kim 249e71b7053SJung-uk Kim /* Copy the flags from src to dst for any extensions that exist in both */ 250e71b7053SJung-uk Kim int custom_exts_copy_flags(custom_ext_methods *dst, 251e71b7053SJung-uk Kim const custom_ext_methods *src) 252e71b7053SJung-uk Kim { 253e71b7053SJung-uk Kim size_t i; 254e71b7053SJung-uk Kim custom_ext_method *methsrc = src->meths; 255e71b7053SJung-uk Kim 256e71b7053SJung-uk Kim for (i = 0; i < src->meths_count; i++, methsrc++) { 257e71b7053SJung-uk Kim custom_ext_method *methdst = custom_ext_find(dst, methsrc->role, 258e71b7053SJung-uk Kim methsrc->ext_type, NULL); 259e71b7053SJung-uk Kim 260e71b7053SJung-uk Kim if (methdst == NULL) 261e71b7053SJung-uk Kim continue; 262e71b7053SJung-uk Kim 263e71b7053SJung-uk Kim methdst->ext_flags = methsrc->ext_flags; 264e71b7053SJung-uk Kim } 265e71b7053SJung-uk Kim 266e71b7053SJung-uk Kim return 1; 267e71b7053SJung-uk Kim } 268e71b7053SJung-uk Kim 269e71b7053SJung-uk Kim /* Copy table of custom extensions */ 270e71b7053SJung-uk Kim int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) 271e71b7053SJung-uk Kim { 272e71b7053SJung-uk Kim size_t i; 273e71b7053SJung-uk Kim int err = 0; 274e71b7053SJung-uk Kim 275e71b7053SJung-uk Kim if (src->meths_count > 0) { 276e71b7053SJung-uk Kim dst->meths = 277e71b7053SJung-uk Kim OPENSSL_memdup(src->meths, 278e71b7053SJung-uk Kim sizeof(*src->meths) * src->meths_count); 279e71b7053SJung-uk Kim if (dst->meths == NULL) 280e71b7053SJung-uk Kim return 0; 281e71b7053SJung-uk Kim dst->meths_count = src->meths_count; 282e71b7053SJung-uk Kim 283e71b7053SJung-uk Kim for (i = 0; i < src->meths_count; i++) { 284e71b7053SJung-uk Kim custom_ext_method *methsrc = src->meths + i; 285e71b7053SJung-uk Kim custom_ext_method *methdst = dst->meths + i; 286e71b7053SJung-uk Kim 287e71b7053SJung-uk Kim if (methsrc->add_cb != custom_ext_add_old_cb_wrap) 288e71b7053SJung-uk Kim continue; 289e71b7053SJung-uk Kim 290e71b7053SJung-uk Kim /* 291e71b7053SJung-uk Kim * We have found an old style API wrapper. We need to copy the 292e71b7053SJung-uk Kim * arguments too. 293e71b7053SJung-uk Kim */ 294e71b7053SJung-uk Kim 295e71b7053SJung-uk Kim if (err) { 296e71b7053SJung-uk Kim methdst->add_arg = NULL; 297e71b7053SJung-uk Kim methdst->parse_arg = NULL; 298e71b7053SJung-uk Kim continue; 299e71b7053SJung-uk Kim } 300e71b7053SJung-uk Kim 301e71b7053SJung-uk Kim methdst->add_arg = OPENSSL_memdup(methsrc->add_arg, 302e71b7053SJung-uk Kim sizeof(custom_ext_add_cb_wrap)); 303e71b7053SJung-uk Kim methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg, 304e71b7053SJung-uk Kim sizeof(custom_ext_parse_cb_wrap)); 305e71b7053SJung-uk Kim 306e71b7053SJung-uk Kim if (methdst->add_arg == NULL || methdst->parse_arg == NULL) 307e71b7053SJung-uk Kim err = 1; 308e71b7053SJung-uk Kim } 309e71b7053SJung-uk Kim } 310e71b7053SJung-uk Kim 311e71b7053SJung-uk Kim if (err) { 312e71b7053SJung-uk Kim custom_exts_free(dst); 313e71b7053SJung-uk Kim return 0; 314e71b7053SJung-uk Kim } 315e71b7053SJung-uk Kim 316e71b7053SJung-uk Kim return 1; 317e71b7053SJung-uk Kim } 318e71b7053SJung-uk Kim 319e71b7053SJung-uk Kim void custom_exts_free(custom_ext_methods *exts) 320e71b7053SJung-uk Kim { 321e71b7053SJung-uk Kim size_t i; 322e71b7053SJung-uk Kim custom_ext_method *meth; 323e71b7053SJung-uk Kim 324e71b7053SJung-uk Kim for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) { 325e71b7053SJung-uk Kim if (meth->add_cb != custom_ext_add_old_cb_wrap) 326e71b7053SJung-uk Kim continue; 327e71b7053SJung-uk Kim 328e71b7053SJung-uk Kim /* Old style API wrapper. Need to free the arguments too */ 329e71b7053SJung-uk Kim OPENSSL_free(meth->add_arg); 330e71b7053SJung-uk Kim OPENSSL_free(meth->parse_arg); 331e71b7053SJung-uk Kim } 332e71b7053SJung-uk Kim OPENSSL_free(exts->meths); 333e71b7053SJung-uk Kim } 334e71b7053SJung-uk Kim 335e71b7053SJung-uk Kim /* Return true if a client custom extension exists, false otherwise */ 336e71b7053SJung-uk Kim int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type) 337e71b7053SJung-uk Kim { 338e71b7053SJung-uk Kim return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type, 339e71b7053SJung-uk Kim NULL) != NULL; 340e71b7053SJung-uk Kim } 341e71b7053SJung-uk Kim 342e71b7053SJung-uk Kim static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role, 343e71b7053SJung-uk Kim unsigned int ext_type, 344e71b7053SJung-uk Kim unsigned int context, 345e71b7053SJung-uk Kim SSL_custom_ext_add_cb_ex add_cb, 346e71b7053SJung-uk Kim SSL_custom_ext_free_cb_ex free_cb, 347e71b7053SJung-uk Kim void *add_arg, 348e71b7053SJung-uk Kim SSL_custom_ext_parse_cb_ex parse_cb, 349e71b7053SJung-uk Kim void *parse_arg) 350e71b7053SJung-uk Kim { 351e71b7053SJung-uk Kim custom_ext_methods *exts = &ctx->cert->custext; 352e71b7053SJung-uk Kim custom_ext_method *meth, *tmp; 353e71b7053SJung-uk Kim 354e71b7053SJung-uk Kim /* 355e71b7053SJung-uk Kim * Check application error: if add_cb is not set free_cb will never be 356e71b7053SJung-uk Kim * called. 357e71b7053SJung-uk Kim */ 358e71b7053SJung-uk Kim if (add_cb == NULL && free_cb != NULL) 359e71b7053SJung-uk Kim return 0; 360e71b7053SJung-uk Kim 361e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CT 362e71b7053SJung-uk Kim /* 363e71b7053SJung-uk Kim * We don't want applications registering callbacks for SCT extensions 364e71b7053SJung-uk Kim * whilst simultaneously using the built-in SCT validation features, as 365e71b7053SJung-uk Kim * these two things may not play well together. 366e71b7053SJung-uk Kim */ 367e71b7053SJung-uk Kim if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp 368e71b7053SJung-uk Kim && (context & SSL_EXT_CLIENT_HELLO) != 0 369e71b7053SJung-uk Kim && SSL_CTX_ct_is_enabled(ctx)) 370e71b7053SJung-uk Kim return 0; 371e71b7053SJung-uk Kim #endif 372e71b7053SJung-uk Kim 373e71b7053SJung-uk Kim /* 374e71b7053SJung-uk Kim * Don't add if extension supported internally, but make exception 375e71b7053SJung-uk Kim * for extension types that previously were not supported, but now are. 376e71b7053SJung-uk Kim */ 377e71b7053SJung-uk Kim if (SSL_extension_supported(ext_type) 378e71b7053SJung-uk Kim && ext_type != TLSEXT_TYPE_signed_certificate_timestamp) 379e71b7053SJung-uk Kim return 0; 380e71b7053SJung-uk Kim 381e71b7053SJung-uk Kim /* Extension type must fit in 16 bits */ 382e71b7053SJung-uk Kim if (ext_type > 0xffff) 383e71b7053SJung-uk Kim return 0; 384e71b7053SJung-uk Kim /* Search for duplicate */ 385e71b7053SJung-uk Kim if (custom_ext_find(exts, role, ext_type, NULL)) 386e71b7053SJung-uk Kim return 0; 387e71b7053SJung-uk Kim tmp = OPENSSL_realloc(exts->meths, 388e71b7053SJung-uk Kim (exts->meths_count + 1) * sizeof(custom_ext_method)); 389e71b7053SJung-uk Kim if (tmp == NULL) 390e71b7053SJung-uk Kim return 0; 391e71b7053SJung-uk Kim 392e71b7053SJung-uk Kim exts->meths = tmp; 393e71b7053SJung-uk Kim meth = exts->meths + exts->meths_count; 394e71b7053SJung-uk Kim memset(meth, 0, sizeof(*meth)); 395e71b7053SJung-uk Kim meth->role = role; 396e71b7053SJung-uk Kim meth->context = context; 397e71b7053SJung-uk Kim meth->parse_cb = parse_cb; 398e71b7053SJung-uk Kim meth->add_cb = add_cb; 399e71b7053SJung-uk Kim meth->free_cb = free_cb; 400e71b7053SJung-uk Kim meth->ext_type = ext_type; 401e71b7053SJung-uk Kim meth->add_arg = add_arg; 402e71b7053SJung-uk Kim meth->parse_arg = parse_arg; 403e71b7053SJung-uk Kim exts->meths_count++; 404e71b7053SJung-uk Kim return 1; 405e71b7053SJung-uk Kim } 406e71b7053SJung-uk Kim 407e71b7053SJung-uk Kim static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role, 408e71b7053SJung-uk Kim unsigned int ext_type, 409e71b7053SJung-uk Kim unsigned int context, 410e71b7053SJung-uk Kim custom_ext_add_cb add_cb, 411e71b7053SJung-uk Kim custom_ext_free_cb free_cb, 412e71b7053SJung-uk Kim void *add_arg, 413e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg) 414e71b7053SJung-uk Kim { 415e71b7053SJung-uk Kim custom_ext_add_cb_wrap *add_cb_wrap 416e71b7053SJung-uk Kim = OPENSSL_malloc(sizeof(*add_cb_wrap)); 417e71b7053SJung-uk Kim custom_ext_parse_cb_wrap *parse_cb_wrap 418e71b7053SJung-uk Kim = OPENSSL_malloc(sizeof(*parse_cb_wrap)); 419e71b7053SJung-uk Kim int ret; 420e71b7053SJung-uk Kim 421e71b7053SJung-uk Kim if (add_cb_wrap == NULL || parse_cb_wrap == NULL) { 422e71b7053SJung-uk Kim OPENSSL_free(add_cb_wrap); 423e71b7053SJung-uk Kim OPENSSL_free(parse_cb_wrap); 424e71b7053SJung-uk Kim return 0; 425e71b7053SJung-uk Kim } 426e71b7053SJung-uk Kim 427e71b7053SJung-uk Kim add_cb_wrap->add_arg = add_arg; 428e71b7053SJung-uk Kim add_cb_wrap->add_cb = add_cb; 429e71b7053SJung-uk Kim add_cb_wrap->free_cb = free_cb; 430e71b7053SJung-uk Kim parse_cb_wrap->parse_arg = parse_arg; 431e71b7053SJung-uk Kim parse_cb_wrap->parse_cb = parse_cb; 432e71b7053SJung-uk Kim 433e71b7053SJung-uk Kim ret = add_custom_ext_intern(ctx, role, ext_type, 434e71b7053SJung-uk Kim context, 435e71b7053SJung-uk Kim custom_ext_add_old_cb_wrap, 436e71b7053SJung-uk Kim custom_ext_free_old_cb_wrap, 437e71b7053SJung-uk Kim add_cb_wrap, 438e71b7053SJung-uk Kim custom_ext_parse_old_cb_wrap, 439e71b7053SJung-uk Kim parse_cb_wrap); 440e71b7053SJung-uk Kim 441e71b7053SJung-uk Kim if (!ret) { 442e71b7053SJung-uk Kim OPENSSL_free(add_cb_wrap); 443e71b7053SJung-uk Kim OPENSSL_free(parse_cb_wrap); 444e71b7053SJung-uk Kim } 445e71b7053SJung-uk Kim 446e71b7053SJung-uk Kim return ret; 447e71b7053SJung-uk Kim } 448e71b7053SJung-uk Kim 449e71b7053SJung-uk Kim /* Application level functions to add the old custom extension callbacks */ 450e71b7053SJung-uk Kim int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 451e71b7053SJung-uk Kim custom_ext_add_cb add_cb, 452e71b7053SJung-uk Kim custom_ext_free_cb free_cb, 453e71b7053SJung-uk Kim void *add_arg, 454e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg) 455e71b7053SJung-uk Kim { 456e71b7053SJung-uk Kim return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type, 457e71b7053SJung-uk Kim SSL_EXT_TLS1_2_AND_BELOW_ONLY 458e71b7053SJung-uk Kim | SSL_EXT_CLIENT_HELLO 459e71b7053SJung-uk Kim | SSL_EXT_TLS1_2_SERVER_HELLO 460e71b7053SJung-uk Kim | SSL_EXT_IGNORE_ON_RESUMPTION, 461e71b7053SJung-uk Kim add_cb, free_cb, add_arg, parse_cb, parse_arg); 462e71b7053SJung-uk Kim } 463e71b7053SJung-uk Kim 464e71b7053SJung-uk Kim int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 465e71b7053SJung-uk Kim custom_ext_add_cb add_cb, 466e71b7053SJung-uk Kim custom_ext_free_cb free_cb, 467e71b7053SJung-uk Kim void *add_arg, 468e71b7053SJung-uk Kim custom_ext_parse_cb parse_cb, void *parse_arg) 469e71b7053SJung-uk Kim { 470e71b7053SJung-uk Kim return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type, 471e71b7053SJung-uk Kim SSL_EXT_TLS1_2_AND_BELOW_ONLY 472e71b7053SJung-uk Kim | SSL_EXT_CLIENT_HELLO 473e71b7053SJung-uk Kim | SSL_EXT_TLS1_2_SERVER_HELLO 474e71b7053SJung-uk Kim | SSL_EXT_IGNORE_ON_RESUMPTION, 475e71b7053SJung-uk Kim add_cb, free_cb, add_arg, parse_cb, parse_arg); 476e71b7053SJung-uk Kim } 477e71b7053SJung-uk Kim 478e71b7053SJung-uk Kim int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 479e71b7053SJung-uk Kim unsigned int context, 480e71b7053SJung-uk Kim SSL_custom_ext_add_cb_ex add_cb, 481e71b7053SJung-uk Kim SSL_custom_ext_free_cb_ex free_cb, 482e71b7053SJung-uk Kim void *add_arg, 483e71b7053SJung-uk Kim SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg) 484e71b7053SJung-uk Kim { 485e71b7053SJung-uk Kim return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb, 486e71b7053SJung-uk Kim free_cb, add_arg, parse_cb, parse_arg); 487e71b7053SJung-uk Kim } 488e71b7053SJung-uk Kim 489e71b7053SJung-uk Kim int SSL_extension_supported(unsigned int ext_type) 490e71b7053SJung-uk Kim { 491e71b7053SJung-uk Kim switch (ext_type) { 492e71b7053SJung-uk Kim /* Internally supported extensions. */ 493e71b7053SJung-uk Kim case TLSEXT_TYPE_application_layer_protocol_negotiation: 494e71b7053SJung-uk Kim #ifndef OPENSSL_NO_EC 495e71b7053SJung-uk Kim case TLSEXT_TYPE_ec_point_formats: 496e71b7053SJung-uk Kim case TLSEXT_TYPE_supported_groups: 497e71b7053SJung-uk Kim case TLSEXT_TYPE_key_share: 498e71b7053SJung-uk Kim #endif 499e71b7053SJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 500e71b7053SJung-uk Kim case TLSEXT_TYPE_next_proto_neg: 501e71b7053SJung-uk Kim #endif 502e71b7053SJung-uk Kim case TLSEXT_TYPE_padding: 503e71b7053SJung-uk Kim case TLSEXT_TYPE_renegotiate: 504e71b7053SJung-uk Kim case TLSEXT_TYPE_max_fragment_length: 505e71b7053SJung-uk Kim case TLSEXT_TYPE_server_name: 506e71b7053SJung-uk Kim case TLSEXT_TYPE_session_ticket: 507e71b7053SJung-uk Kim case TLSEXT_TYPE_signature_algorithms: 508e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRP 509e71b7053SJung-uk Kim case TLSEXT_TYPE_srp: 510e71b7053SJung-uk Kim #endif 511e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 512e71b7053SJung-uk Kim case TLSEXT_TYPE_status_request: 513e71b7053SJung-uk Kim #endif 514e71b7053SJung-uk Kim #ifndef OPENSSL_NO_CT 515e71b7053SJung-uk Kim case TLSEXT_TYPE_signed_certificate_timestamp: 516e71b7053SJung-uk Kim #endif 517e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRTP 518e71b7053SJung-uk Kim case TLSEXT_TYPE_use_srtp: 519e71b7053SJung-uk Kim #endif 520e71b7053SJung-uk Kim case TLSEXT_TYPE_encrypt_then_mac: 521e71b7053SJung-uk Kim case TLSEXT_TYPE_supported_versions: 522e71b7053SJung-uk Kim case TLSEXT_TYPE_extended_master_secret: 523e71b7053SJung-uk Kim case TLSEXT_TYPE_psk_kex_modes: 524e71b7053SJung-uk Kim case TLSEXT_TYPE_cookie: 525e71b7053SJung-uk Kim case TLSEXT_TYPE_early_data: 526e71b7053SJung-uk Kim case TLSEXT_TYPE_certificate_authorities: 527e71b7053SJung-uk Kim case TLSEXT_TYPE_psk: 528e71b7053SJung-uk Kim case TLSEXT_TYPE_post_handshake_auth: 529e71b7053SJung-uk Kim return 1; 530e71b7053SJung-uk Kim default: 531e71b7053SJung-uk Kim return 0; 532e71b7053SJung-uk Kim } 533e71b7053SJung-uk Kim } 534