t1_ext.c revision 325335
1/* ssl/t1_ext.c */ 2/* ==================================================================== 3 * Copyright (c) 2014 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55 56/* Custom extension utility functions */ 57 58#include "ssl_locl.h" 59 60#ifndef OPENSSL_NO_TLSEXT 61 62/* Find a custom extension from the list. */ 63static custom_ext_method *custom_ext_find(custom_ext_methods *exts, 64 unsigned int ext_type) 65{ 66 size_t i; 67 custom_ext_method *meth = exts->meths; 68 for (i = 0; i < exts->meths_count; i++, meth++) { 69 if (ext_type == meth->ext_type) 70 return meth; 71 } 72 return NULL; 73} 74 75/* 76 * Initialise custom extensions flags to indicate neither sent nor received. 77 */ 78void custom_ext_init(custom_ext_methods *exts) 79{ 80 size_t i; 81 custom_ext_method *meth = exts->meths; 82 for (i = 0; i < exts->meths_count; i++, meth++) 83 meth->ext_flags = 0; 84} 85 86/* Pass received custom extension data to the application for parsing. */ 87int custom_ext_parse(SSL *s, int server, 88 unsigned int ext_type, 89 const unsigned char *ext_data, size_t ext_size, int *al) 90{ 91 custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; 92 custom_ext_method *meth; 93 meth = custom_ext_find(exts, ext_type); 94 /* If not found return success */ 95 if (!meth) 96 return 1; 97 if (!server) { 98 /* 99 * If it's ServerHello we can't have any extensions not sent in 100 * ClientHello. 101 */ 102 if (!(meth->ext_flags & SSL_EXT_FLAG_SENT)) { 103 *al = TLS1_AD_UNSUPPORTED_EXTENSION; 104 return 0; 105 } 106 } 107 /* If already present it's a duplicate */ 108 if (meth->ext_flags & SSL_EXT_FLAG_RECEIVED) { 109 *al = TLS1_AD_DECODE_ERROR; 110 return 0; 111 } 112 meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; 113 /* If no parse function set return success */ 114 if (!meth->parse_cb) 115 return 1; 116 117 return meth->parse_cb(s, ext_type, ext_data, ext_size, al, 118 meth->parse_arg); 119} 120 121/* 122 * Request custom extension data from the application and add to the return 123 * buffer. 124 */ 125int custom_ext_add(SSL *s, int server, 126 unsigned char **pret, unsigned char *limit, int *al) 127{ 128 custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; 129 custom_ext_method *meth; 130 unsigned char *ret = *pret; 131 size_t i; 132 133 for (i = 0; i < exts->meths_count; i++) { 134 const unsigned char *out = NULL; 135 size_t outlen = 0; 136 meth = exts->meths + i; 137 138 if (server) { 139 /* 140 * For ServerHello only send extensions present in ClientHello. 141 */ 142 if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) 143 continue; 144 /* If callback absent for server skip it */ 145 if (!meth->add_cb) 146 continue; 147 } 148 if (meth->add_cb) { 149 int cb_retval = 0; 150 cb_retval = meth->add_cb(s, meth->ext_type, 151 &out, &outlen, al, meth->add_arg); 152 if (cb_retval < 0) 153 return 0; /* error */ 154 if (cb_retval == 0) 155 continue; /* skip this extension */ 156 } 157 if (4 > limit - ret || outlen > (size_t)(limit - ret - 4)) 158 return 0; 159 s2n(meth->ext_type, ret); 160 s2n(outlen, ret); 161 if (outlen) { 162 memcpy(ret, out, outlen); 163 ret += outlen; 164 } 165 /* 166 * We can't send duplicates: code logic should prevent this. 167 */ 168 OPENSSL_assert(!(meth->ext_flags & SSL_EXT_FLAG_SENT)); 169 /* 170 * Indicate extension has been sent: this is both a sanity check to 171 * ensure we don't send duplicate extensions and indicates that it is 172 * not an error if the extension is present in ServerHello. 173 */ 174 meth->ext_flags |= SSL_EXT_FLAG_SENT; 175 if (meth->free_cb) 176 meth->free_cb(s, meth->ext_type, out, meth->add_arg); 177 } 178 *pret = ret; 179 return 1; 180} 181 182/* Copy the flags from src to dst for any extensions that exist in both */ 183int custom_exts_copy_flags(custom_ext_methods *dst, 184 const custom_ext_methods *src) 185{ 186 size_t i; 187 custom_ext_method *methsrc = src->meths; 188 189 for (i = 0; i < src->meths_count; i++, methsrc++) { 190 custom_ext_method *methdst = custom_ext_find(dst, methsrc->ext_type); 191 192 if (methdst == NULL) 193 continue; 194 195 methdst->ext_flags = methsrc->ext_flags; 196 } 197 198 return 1; 199} 200 201/* Copy table of custom extensions */ 202int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) 203{ 204 if (src->meths_count) { 205 dst->meths = 206 BUF_memdup(src->meths, 207 sizeof(custom_ext_method) * src->meths_count); 208 if (dst->meths == NULL) 209 return 0; 210 dst->meths_count = src->meths_count; 211 } 212 return 1; 213} 214 215void custom_exts_free(custom_ext_methods *exts) 216{ 217 if (exts->meths) 218 OPENSSL_free(exts->meths); 219} 220 221/* Set callbacks for a custom extension. */ 222static int custom_ext_meth_add(custom_ext_methods *exts, 223 unsigned int ext_type, 224 custom_ext_add_cb add_cb, 225 custom_ext_free_cb free_cb, 226 void *add_arg, 227 custom_ext_parse_cb parse_cb, void *parse_arg) 228{ 229 custom_ext_method *meth; 230 /* 231 * Check application error: if add_cb is not set free_cb will never be 232 * called. 233 */ 234 if (!add_cb && free_cb) 235 return 0; 236 /* Don't add if extension supported internally. */ 237 if (SSL_extension_supported(ext_type)) 238 return 0; 239 /* Extension type must fit in 16 bits */ 240 if (ext_type > 0xffff) 241 return 0; 242 /* Search for duplicate */ 243 if (custom_ext_find(exts, ext_type)) 244 return 0; 245 meth = OPENSSL_realloc(exts->meths, 246 (exts->meths_count + 1) 247 * sizeof(custom_ext_method)); 248 if (meth == NULL) 249 return 0; 250 251 exts->meths = meth; 252 meth += exts->meths_count; 253 memset(meth, 0, sizeof(custom_ext_method)); 254 meth->parse_cb = parse_cb; 255 meth->add_cb = add_cb; 256 meth->free_cb = free_cb; 257 meth->ext_type = ext_type; 258 meth->add_arg = add_arg; 259 meth->parse_arg = parse_arg; 260 exts->meths_count++; 261 return 1; 262} 263 264/* Application level functions to add custom extension callbacks */ 265int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 266 custom_ext_add_cb add_cb, 267 custom_ext_free_cb free_cb, 268 void *add_arg, 269 custom_ext_parse_cb parse_cb, 270 void *parse_arg) 271{ 272 return custom_ext_meth_add(&ctx->cert->cli_ext, ext_type, 273 add_cb, free_cb, add_arg, parse_cb, parse_arg); 274} 275 276int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 277 custom_ext_add_cb add_cb, 278 custom_ext_free_cb free_cb, 279 void *add_arg, 280 custom_ext_parse_cb parse_cb, 281 void *parse_arg) 282{ 283 return custom_ext_meth_add(&ctx->cert->srv_ext, ext_type, 284 add_cb, free_cb, add_arg, parse_cb, parse_arg); 285} 286 287int SSL_extension_supported(unsigned int ext_type) 288{ 289 switch (ext_type) { 290 /* Internally supported extensions. */ 291 case TLSEXT_TYPE_application_layer_protocol_negotiation: 292 case TLSEXT_TYPE_ec_point_formats: 293 case TLSEXT_TYPE_elliptic_curves: 294 case TLSEXT_TYPE_heartbeat: 295# ifndef OPENSSL_NO_NEXTPROTONEG 296 case TLSEXT_TYPE_next_proto_neg: 297# endif 298 case TLSEXT_TYPE_padding: 299 case TLSEXT_TYPE_renegotiate: 300 case TLSEXT_TYPE_server_name: 301 case TLSEXT_TYPE_session_ticket: 302 case TLSEXT_TYPE_signature_algorithms: 303 case TLSEXT_TYPE_srp: 304 case TLSEXT_TYPE_status_request: 305 case TLSEXT_TYPE_use_srtp: 306# ifdef TLSEXT_TYPE_opaque_prf_input 307 case TLSEXT_TYPE_opaque_prf_input: 308# endif 309# ifdef TLSEXT_TYPE_encrypt_then_mac 310 case TLSEXT_TYPE_encrypt_then_mac: 311# endif 312 return 1; 313 default: 314 return 0; 315 } 316} 317#endif 318