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