t1_ext.c revision 306343
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 table of custom extensions */ 183int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) 184{ 185 if (src->meths_count) { 186 dst->meths = 187 BUF_memdup(src->meths, 188 sizeof(custom_ext_method) * src->meths_count); 189 if (dst->meths == NULL) 190 return 0; 191 dst->meths_count = src->meths_count; 192 } 193 return 1; 194} 195 196void custom_exts_free(custom_ext_methods *exts) 197{ 198 if (exts->meths) 199 OPENSSL_free(exts->meths); 200} 201 202/* Set callbacks for a custom extension. */ 203static int custom_ext_meth_add(custom_ext_methods *exts, 204 unsigned int ext_type, 205 custom_ext_add_cb add_cb, 206 custom_ext_free_cb free_cb, 207 void *add_arg, 208 custom_ext_parse_cb parse_cb, void *parse_arg) 209{ 210 custom_ext_method *meth; 211 /* 212 * Check application error: if add_cb is not set free_cb will never be 213 * called. 214 */ 215 if (!add_cb && free_cb) 216 return 0; 217 /* Don't add if extension supported internally. */ 218 if (SSL_extension_supported(ext_type)) 219 return 0; 220 /* Extension type must fit in 16 bits */ 221 if (ext_type > 0xffff) 222 return 0; 223 /* Search for duplicate */ 224 if (custom_ext_find(exts, ext_type)) 225 return 0; 226 exts->meths = OPENSSL_realloc(exts->meths, 227 (exts->meths_count + 228 1) * sizeof(custom_ext_method)); 229 230 if (!exts->meths) { 231 exts->meths_count = 0; 232 return 0; 233 } 234 235 meth = exts->meths + exts->meths_count; 236 memset(meth, 0, sizeof(custom_ext_method)); 237 meth->parse_cb = parse_cb; 238 meth->add_cb = add_cb; 239 meth->free_cb = free_cb; 240 meth->ext_type = ext_type; 241 meth->add_arg = add_arg; 242 meth->parse_arg = parse_arg; 243 exts->meths_count++; 244 return 1; 245} 246 247/* Application level functions to add custom extension callbacks */ 248int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 249 custom_ext_add_cb add_cb, 250 custom_ext_free_cb free_cb, 251 void *add_arg, 252 custom_ext_parse_cb parse_cb, 253 void *parse_arg) 254{ 255 return custom_ext_meth_add(&ctx->cert->cli_ext, ext_type, 256 add_cb, free_cb, add_arg, parse_cb, parse_arg); 257} 258 259int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, 260 custom_ext_add_cb add_cb, 261 custom_ext_free_cb free_cb, 262 void *add_arg, 263 custom_ext_parse_cb parse_cb, 264 void *parse_arg) 265{ 266 return custom_ext_meth_add(&ctx->cert->srv_ext, ext_type, 267 add_cb, free_cb, add_arg, parse_cb, parse_arg); 268} 269 270int SSL_extension_supported(unsigned int ext_type) 271{ 272 switch (ext_type) { 273 /* Internally supported extensions. */ 274 case TLSEXT_TYPE_application_layer_protocol_negotiation: 275 case TLSEXT_TYPE_ec_point_formats: 276 case TLSEXT_TYPE_elliptic_curves: 277 case TLSEXT_TYPE_heartbeat: 278# ifndef OPENSSL_NO_NEXTPROTONEG 279 case TLSEXT_TYPE_next_proto_neg: 280# endif 281 case TLSEXT_TYPE_padding: 282 case TLSEXT_TYPE_renegotiate: 283 case TLSEXT_TYPE_server_name: 284 case TLSEXT_TYPE_session_ticket: 285 case TLSEXT_TYPE_signature_algorithms: 286 case TLSEXT_TYPE_srp: 287 case TLSEXT_TYPE_status_request: 288 case TLSEXT_TYPE_use_srtp: 289# ifdef TLSEXT_TYPE_opaque_prf_input 290 case TLSEXT_TYPE_opaque_prf_input: 291# endif 292# ifdef TLSEXT_TYPE_encrypt_then_mac 293 case TLSEXT_TYPE_encrypt_then_mac: 294# endif 295 return 1; 296 default: 297 return 0; 298 } 299} 300#endif 301