LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - hello_ext.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 365 402 90.8 %
Date: 2020-10-30 04:50:48 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2001-2018 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2015-2018 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos, Simon Josefsson
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : /* Functions that relate to the TLS hello extension parsing.
      25             :  * Hello extensions are packets appended in the TLS hello packet, and
      26             :  * allow for extra functionality.
      27             :  */
      28             : 
      29             : #include "gnutls_int.h"
      30             : #include "hello_ext.h"
      31             : #include "errors.h"
      32             : #include "ext/max_record.h"
      33             : #include <ext/server_name.h>
      34             : #include <ext/srp.h>
      35             : #include <ext/heartbeat.h>
      36             : #include <ext/session_ticket.h>
      37             : #include <ext/safe_renegotiation.h>
      38             : #include <ext/signature.h>
      39             : #include <ext/safe_renegotiation.h>
      40             : #include "ext/supported_groups.h"
      41             : #include "ext/ec_point_formats.h"
      42             : #include <ext/status_request.h>
      43             : #include <ext/ext_master_secret.h>
      44             : #include <ext/supported_versions.h>
      45             : #include <ext/post_handshake.h>
      46             : #include <ext/srtp.h>
      47             : #include <ext/alpn.h>
      48             : #include <ext/dumbfw.h>
      49             : #include <ext/key_share.h>
      50             : #include <ext/pre_shared_key.h>
      51             : #include <ext/psk_ke_modes.h>
      52             : #include <ext/etm.h>
      53             : #include <ext/cookie.h>
      54             : #include <ext/early_data.h>
      55             : #include <ext/record_size_limit.h>
      56             : #include "extv.h"
      57             : #include <num.h>
      58             : #include <ext/client_cert_type.h>
      59             : #include <ext/server_cert_type.h>
      60             : 
      61             : static void
      62             : unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
      63             : 
      64             : static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
      65             : 
      66             : static hello_ext_entry_st const *extfunc[MAX_EXT_TYPES+1] = {
      67             :         [GNUTLS_EXTENSION_EXT_MASTER_SECRET] = &ext_mod_ext_master_secret,
      68             :         [GNUTLS_EXTENSION_SUPPORTED_VERSIONS] = &ext_mod_supported_versions,
      69             :         [GNUTLS_EXTENSION_POST_HANDSHAKE] = &ext_mod_post_handshake,
      70             :         [GNUTLS_EXTENSION_ETM] = &ext_mod_etm,
      71             : #ifdef ENABLE_OCSP
      72             :         [GNUTLS_EXTENSION_STATUS_REQUEST] = &ext_mod_status_request,
      73             : #endif
      74             :         [GNUTLS_EXTENSION_SERVER_NAME] = &ext_mod_server_name,
      75             :         [GNUTLS_EXTENSION_SAFE_RENEGOTIATION] = &ext_mod_sr,
      76             : #ifdef ENABLE_SRP
      77             :         [GNUTLS_EXTENSION_SRP] = &ext_mod_srp,
      78             : #endif
      79             : #ifdef ENABLE_HEARTBEAT
      80             :         [GNUTLS_EXTENSION_HEARTBEAT] = &ext_mod_heartbeat,
      81             : #endif
      82             :         [GNUTLS_EXTENSION_SESSION_TICKET] = &ext_mod_session_ticket,
      83             :         [GNUTLS_EXTENSION_CLIENT_CERT_TYPE] = &ext_mod_client_cert_type,
      84             :         [GNUTLS_EXTENSION_SERVER_CERT_TYPE] = &ext_mod_server_cert_type,
      85             :         [GNUTLS_EXTENSION_SUPPORTED_GROUPS] = &ext_mod_supported_groups,
      86             :         [GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS] = &ext_mod_supported_ec_point_formats,
      87             :         [GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS] = &ext_mod_sig,
      88             :         [GNUTLS_EXTENSION_KEY_SHARE] = &ext_mod_key_share,
      89             :         [GNUTLS_EXTENSION_COOKIE] = &ext_mod_cookie,
      90             :         [GNUTLS_EXTENSION_EARLY_DATA] = &ext_mod_early_data,
      91             : #ifdef ENABLE_DTLS_SRTP
      92             :         [GNUTLS_EXTENSION_SRTP] = &ext_mod_srtp,
      93             : #endif
      94             : #ifdef ENABLE_ALPN
      95             :         [GNUTLS_EXTENSION_ALPN] = &ext_mod_alpn,
      96             : #endif
      97             :         [GNUTLS_EXTENSION_RECORD_SIZE_LIMIT] = &ext_mod_record_size_limit,
      98             :         [GNUTLS_EXTENSION_MAX_RECORD_SIZE] = &ext_mod_max_record_size,
      99             :         [GNUTLS_EXTENSION_PSK_KE_MODES] = &ext_mod_psk_ke_modes,
     100             :         [GNUTLS_EXTENSION_PRE_SHARED_KEY] = &ext_mod_pre_shared_key,
     101             :         /* This must be the last extension registered.
     102             :          */
     103             :         [GNUTLS_EXTENSION_DUMBFW] = &ext_mod_dumbfw,
     104             : };
     105             : 
     106             : static const hello_ext_entry_st *
     107      156769 : gid_to_ext_entry(gnutls_session_t session, extensions_t id)
     108             : {
     109      156769 :         unsigned i;
     110             : 
     111      156769 :         assert(id < MAX_EXT_TYPES);
     112             : 
     113      157283 :         for (i=0;i<session->internals.rexts_size;i++) {
     114         532 :                 if (session->internals.rexts[i].gid == id) {
     115             :                         return &session->internals.rexts[i];
     116             :                 }
     117             :         }
     118             : 
     119      156751 :         return extfunc[id];
     120             : }
     121             : 
     122             : static const hello_ext_entry_st *
     123     1392050 : tls_id_to_ext_entry(gnutls_session_t session, uint16_t tls_id, gnutls_ext_parse_type_t parse_point)
     124             : {
     125     1392050 :         unsigned i;
     126     1392050 :         const hello_ext_entry_st *e;
     127             : 
     128     1395230 :         for (i=0;i<session->internals.rexts_size;i++) {
     129        3526 :                 if (session->internals.rexts[i].tls_id == tls_id) {
     130         341 :                         e = &session->internals.rexts[i];
     131         341 :                         goto done;
     132             :                 }
     133             :         }
     134             : 
     135    64549900 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     136    63655900 :                 if (!extfunc[i])
     137    35343500 :                         continue;
     138             : 
     139    28312400 :                 if (extfunc[i]->tls_id == tls_id) {
     140      497768 :                         e = extfunc[i];
     141      497768 :                         goto done;
     142             :                 }
     143             :         }
     144             : 
     145             :         return NULL;
     146      498109 : done:
     147      498109 :         if (parse_point == GNUTLS_EXT_ANY || (IS_SERVER(session) && e->server_parse_point == parse_point) ||
     148       49378 :             (!IS_SERVER(session) && e->client_parse_point == parse_point)) {
     149             :                 return e;
     150             :         } else {
     151      395819 :                 return NULL;
     152             :         }
     153             : }
     154             : 
     155             : 
     156             : /**
     157             :  * gnutls_ext_get_name:
     158             :  * @ext: is a TLS extension numeric ID
     159             :  *
     160             :  * Convert a TLS extension numeric ID to a printable string.
     161             :  *
     162             :  * Returns: a pointer to a string that contains the name of the
     163             :  *   specified cipher, or %NULL.
     164             :  **/
     165          15 : const char *gnutls_ext_get_name(unsigned int ext)
     166             : {
     167          15 :         size_t i;
     168             : 
     169         463 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     170         456 :                 if (!extfunc[i])
     171         273 :                         continue;
     172             : 
     173         183 :                 if (extfunc[i]->tls_id == ext)
     174           8 :                         return extfunc[i]->name;
     175             :         }
     176             : 
     177             :         return NULL;
     178             : }
     179             : 
     180             : /* Returns %GNUTLS_EXTENSION_INVALID on error
     181             :  */
     182          10 : static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
     183             : {
     184          10 :         unsigned i;
     185             : 
     186          10 :         for (i=0; i < session->internals.rexts_size; i++) {
     187           4 :                 if (session->internals.rexts[i].tls_id == tls_id)
     188           4 :                         return session->internals.rexts[i].gid;
     189             :         }
     190             : 
     191         168 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     192         168 :                 if (!extfunc[i])
     193          12 :                         continue;
     194             : 
     195         156 :                 if (extfunc[i]->tls_id == tls_id)
     196           6 :                         return extfunc[i]->gid;
     197             :         }
     198             : 
     199             :         return GNUTLS_EXTENSION_INVALID;
     200             : }
     201             : 
     202             : typedef struct hello_ext_ctx_st {
     203             :         gnutls_session_t session;
     204             :         gnutls_ext_flags_t msg;
     205             :         gnutls_ext_parse_type_t parse_point;
     206             :         const hello_ext_entry_st *ext; /* used during send */
     207             :         unsigned seen_pre_shared_key;
     208             : } hello_ext_ctx_st;
     209             : 
     210             : static
     211     1392050 : int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned data_size)
     212             : {
     213     1392050 :         hello_ext_ctx_st *ctx = _ctx;
     214     1392050 :         gnutls_session_t session = ctx->session;
     215     1392050 :         const hello_ext_entry_st *ext;
     216     1392050 :         int ret;
     217             : 
     218     1392050 :         if (tls_id == PRE_SHARED_KEY_TLS_ID) {
     219       10838 :                 ctx->seen_pre_shared_key = 1;
     220     1381220 :         } else if (ctx->seen_pre_shared_key && session->security_parameters.entity == GNUTLS_SERVER) {
     221             :                 /* the pre-shared key extension must always be the last one,
     222             :                  * draft-ietf-tls-tls13-28: 4.2.11 */
     223           4 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     224             :         }
     225             : 
     226     1392050 :         ext = tls_id_to_ext_entry(session, tls_id, ctx->parse_point);
     227     1392050 :         if (ext == NULL || ext->recv_func == NULL) {
     228     1289850 :                 goto ignore;
     229             :         }
     230             : 
     231             :         /* we do not hard fail when extensions defined for TLS are used for
     232             :          * DTLS and vice-versa. They may extend their role in the future. */
     233      102198 :         if (IS_DTLS(session)) {
     234        3282 :                 if (!(ext->validity & GNUTLS_EXT_FLAG_DTLS)) {
     235           0 :                         gnutls_assert();
     236           0 :                         goto ignore;
     237             :                 }
     238             :         } else {
     239       98916 :                 if (!(ext->validity & GNUTLS_EXT_FLAG_TLS)) {
     240           0 :                         gnutls_assert();
     241           0 :                         goto ignore;
     242             :                 }
     243             :         }
     244             : 
     245      102198 :         if (session->security_parameters.entity == GNUTLS_CLIENT) {
     246       10717 :                 if (!(ext->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) &&
     247       10716 :                     !_gnutls_hello_ext_is_present(session, ext->gid)) {
     248           6 :                         _gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session,
     249             :                                         ext->name, (int)tls_id);
     250           6 :                         return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
     251             :                 }
     252             :         }
     253             : 
     254      102192 :         if ((ext->validity & ctx->msg) == 0) {
     255           4 :                 _gnutls_debug_log("EXT[%p]: Received unexpected extension (%s/%d) for '%s'\n", session,
     256             :                                   ext->name, (int)tls_id,
     257             :                                   ext_msg_validity_to_str(ctx->msg));
     258           4 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
     259             :         }
     260             : 
     261      102188 :         if (session->security_parameters.entity == GNUTLS_SERVER) {
     262       91480 :                 ret = _gnutls_hello_ext_save(session, ext->gid, 1);
     263       91421 :                 if (ret == 0)
     264          59 :                         return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
     265             :         }
     266             : 
     267      102129 :         _gnutls_handshake_log
     268             :             ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
     269             :              session, ext->name, (int)tls_id,
     270             :              data_size);
     271             : 
     272      102129 :         _gnutls_ext_set_msg(session, ctx->msg);
     273      102129 :         if ((ret = ext->recv_func(session, data, data_size)) < 0) {
     274        1826 :                 gnutls_assert();
     275        1826 :                 return ret;
     276             :         }
     277             : 
     278             :         return 0;
     279             : 
     280     1289850 :  ignore:
     281     1289850 :         if (ext) {
     282          92 :                 _gnutls_handshake_log
     283             :                     ("EXT[%p]: Ignoring extension '%s/%d'\n", session,
     284             :                      ext->name, (int)tls_id);
     285             :         }
     286             :         return 0;
     287             : }
     288             : 
     289             : int
     290      100214 : _gnutls_parse_hello_extensions(gnutls_session_t session,
     291             :                                gnutls_ext_flags_t msg,
     292             :                                gnutls_ext_parse_type_t parse_point,
     293             :                                const uint8_t * data, int data_size)
     294             : {
     295      100214 :         int ret;
     296      100214 :         hello_ext_ctx_st ctx;
     297             : 
     298      100214 :         msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
     299             : 
     300      100214 :         ctx.session = session;
     301      100214 :         ctx.msg = msg;
     302      100214 :         ctx.parse_point = parse_point;
     303      100214 :         ctx.seen_pre_shared_key = 0;
     304             : 
     305      100214 :         ret = _gnutls_extv_parse(&ctx, hello_ext_parse, data, data_size);
     306      100214 :         if (ret < 0)
     307        3144 :                 return gnutls_assert_val(ret);
     308             : 
     309             :         return 0;
     310             : }
     311             : 
     312             : static
     313      622589 : int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
     314             : {
     315      622589 :         hello_ext_ctx_st *ctx = _ctx;
     316      622589 :         int ret;
     317      622589 :         const hello_ext_entry_st *p = ctx->ext;
     318      622589 :         gnutls_session_t session = ctx->session;
     319      622589 :         int appended;
     320      622589 :         size_t size_prev;
     321             : 
     322      622589 :         if (unlikely(p->send_func == NULL))
     323             :                 return 0;
     324             : 
     325      622589 :         if (ctx->parse_point != GNUTLS_EXT_ANY &&
     326       19550 :             ((IS_SERVER(session) && p->server_parse_point != ctx->parse_point) ||
     327           0 :              (!IS_SERVER(session) && p->client_parse_point != ctx->parse_point))) {
     328             :                 return 0;
     329             :         }
     330             : 
     331      609295 :         if (IS_DTLS(session)) {
     332       15073 :                 if (!(p->validity & GNUTLS_EXT_FLAG_DTLS)) {
     333        4806 :                         gnutls_assert();
     334        4806 :                         goto skip;
     335             :                 }
     336             :         } else {
     337      594222 :                 if (!(p->validity & GNUTLS_EXT_FLAG_TLS)) {
     338           0 :                         gnutls_assert();
     339           0 :                         goto skip;
     340             :                 }
     341             :         }
     342             : 
     343      604489 :         if ((ctx->msg & p->validity) == 0) {
     344      276903 :                 goto skip;
     345             :         } else {
     346      454018 :                 _gnutls_handshake_log("EXT[%p]: Preparing extension (%s/%d) for '%s'\n", session,
     347             :                                   p->name, (int)p->tls_id,
     348             :                                   ext_msg_validity_to_str(ctx->msg));
     349             :         }
     350             : 
     351             :         /* ensure we don't send something twice (i.e, overridden extensions in
     352             :          * client), and ensure we are sending only what we received in server. */
     353      327586 :         ret = _gnutls_hello_ext_is_present(session, p->gid);
     354             : 
     355      327586 :         if (session->security_parameters.entity == GNUTLS_SERVER) {
     356             :                 /* if client didn't advertise and the override flag is not present */
     357      236541 :                 if (!(p->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) && ret == 0)
     358             :                         return 0;
     359             :         } else {
     360       91045 :                 if (ret != 0) /* already sent */
     361             :                         return 0;
     362             :         }
     363             : 
     364             : 
     365      150224 :         size_prev = buf->length;
     366             : 
     367      150224 :         _gnutls_ext_set_msg(session, ctx->msg);
     368      150224 :         ret = p->send_func(session, buf);
     369      150224 :         if (ret < 0 && ret != GNUTLS_E_INT_RET_0) {
     370         162 :                 return gnutls_assert_val(ret);
     371             :         }
     372             : 
     373      150068 :         appended = buf->length - size_prev;
     374             : 
     375             :         /* add this extension to the extension list, to know which extensions
     376             :          * to expect.
     377             :          */
     378      150068 :         if ((appended > 0 || ret == GNUTLS_E_INT_RET_0) &&
     379       74269 :             session->security_parameters.entity == GNUTLS_CLIENT) {
     380             : 
     381       37511 :                 _gnutls_hello_ext_save(session, p->gid, 0);
     382             :         }
     383             : 
     384             :         return ret;
     385             : 
     386      281709 :  skip:
     387      439451 :         _gnutls_handshake_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session,
     388             :                           p->name, (int)p->tls_id,
     389             :                           ext_msg_validity_to_str(ctx->msg));
     390             :         return 0;
     391             : }
     392             : 
     393             : int
     394       24968 : _gnutls_gen_hello_extensions(gnutls_session_t session,
     395             :                              gnutls_buffer_st * buf,
     396             :                              gnutls_ext_flags_t msg,
     397             :                              gnutls_ext_parse_type_t parse_point)
     398             : {
     399       24968 :         int pos, ret;
     400       24968 :         size_t i;
     401       24968 :         hello_ext_ctx_st ctx;
     402             : 
     403       24968 :         msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
     404             : 
     405       24968 :         ctx.session = session;
     406       24968 :         ctx.msg = msg;
     407       24968 :         ctx.parse_point = parse_point;
     408             : 
     409       24968 :         ret = _gnutls_extv_append_init(buf);
     410       24968 :         if (ret < 0)
     411           0 :                 return gnutls_assert_val(ret);
     412             : 
     413       24968 :         pos = ret;
     414       24968 :         _gnutls_ext_set_extensions_offset(session, pos);
     415             : 
     416       25065 :         for (i=0; i < session->internals.rexts_size; i++) {
     417          97 :                 ctx.ext = &session->internals.rexts[i];
     418          97 :                 ret = _gnutls_extv_append(buf, session->internals.rexts[i].tls_id,
     419             :                                           &ctx, hello_ext_send);
     420          97 :                 if (ret < 0)
     421           0 :                         return gnutls_assert_val(ret);
     422             : 
     423          97 :                 if (ret > 0)
     424          97 :                         _gnutls_handshake_log
     425             :                                     ("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
     426             :                                      session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
     427             :         }
     428             : 
     429             :         /* hello_ext_send() ensures we don't send duplicates, in case
     430             :          * of overridden extensions */
     431     1615120 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     432     1590310 :                 if (!extfunc[i])
     433      967816 :                         continue;
     434             : 
     435      622492 :                 ctx.ext = extfunc[i];
     436      622492 :                 ret = _gnutls_extv_append(buf, extfunc[i]->tls_id,
     437             :                                           &ctx, hello_ext_send);
     438      622492 :                 if (ret < 0)
     439         162 :                         return gnutls_assert_val(ret);
     440             : 
     441      622336 :                 if (ret > 0)
     442     1590150 :                         _gnutls_handshake_log
     443             :                                     ("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
     444             :                                      session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
     445             :         }
     446             : 
     447       24812 :         ret = _gnutls_extv_append_final(buf, pos, !(msg & GNUTLS_EXT_FLAG_EE));
     448       24812 :         if (ret < 0)
     449           0 :                 return gnutls_assert_val(ret);
     450             : 
     451             :         return 0;
     452             : }
     453             : 
     454             : /* Global deinit and init of global extensions */
     455        3384 : int _gnutls_hello_ext_init(void)
     456             : {
     457        3384 :         return GNUTLS_E_SUCCESS;
     458             : }
     459             : 
     460        2185 : void _gnutls_hello_ext_deinit(void)
     461             : {
     462        2185 :         unsigned i;
     463             : 
     464      142025 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     465      139840 :                 if (!extfunc[i])
     466       85135 :                         continue;
     467             : 
     468       54705 :                 if (extfunc[i]->free_struct != 0) {
     469          80 :                         gnutls_free(((hello_ext_entry_st *)extfunc[i])->name);
     470          80 :                         gnutls_free(extfunc[i]);
     471             :                 }
     472             :         }
     473        2185 : }
     474             : 
     475             : /* Packing of extension data (for use in resumption) */
     476       34612 : static int pack_extension(gnutls_session_t session, const hello_ext_entry_st *extp,
     477             :                           gnutls_buffer_st *packed)
     478             : {
     479       34612 :         int ret;
     480       34612 :         int size_offset;
     481       34612 :         int cur_size;
     482       34612 :         gnutls_ext_priv_data_t data;
     483       34612 :         int rval = 0;
     484             : 
     485       34612 :         ret =
     486       34612 :             _gnutls_hello_ext_get_priv(session, extp->gid,
     487             :                                          &data);
     488       34612 :         if (ret >= 0 && extp->pack_func != NULL) {
     489        5125 :                 BUFFER_APPEND_NUM(packed, extp->gid);
     490             : 
     491        5125 :                 size_offset = packed->length;
     492        5125 :                 BUFFER_APPEND_NUM(packed, 0);
     493             : 
     494        5125 :                 cur_size = packed->length;
     495             : 
     496        5125 :                 ret = extp->pack_func(data, packed);
     497        5125 :                 if (ret < 0) {
     498           0 :                         gnutls_assert();
     499           0 :                         return ret;
     500             :                 }
     501             : 
     502        5125 :                 rval = 1;
     503             :                 /* write the actual size */
     504       39737 :                 _gnutls_write_uint32(packed->length - cur_size,
     505        5125 :                                      packed->data + size_offset);
     506             :         }
     507             : 
     508             :         return rval;
     509             : }
     510             : 
     511        6564 : int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
     512             : {
     513        6564 :         unsigned int i;
     514        6564 :         int ret;
     515        6564 :         int total_exts_pos;
     516        6564 :         int n_exts = 0;
     517        6564 :         const struct hello_ext_entry_st *ext;
     518             : 
     519        6564 :         total_exts_pos = packed->length;
     520        6564 :         BUFFER_APPEND_NUM(packed, 0);
     521             : 
     522      426660 :         for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
     523      420096 :                 if (session->internals.used_exts & ((ext_track_t)1 << i)) {
     524             : 
     525       34612 :                         ext = gid_to_ext_entry(session, i);
     526       34612 :                         if (ext == NULL)
     527           0 :                                 continue;
     528             : 
     529       34612 :                         ret = pack_extension(session, ext, packed);
     530       34612 :                         if (ret < 0)
     531           0 :                                 return gnutls_assert_val(ret);
     532             : 
     533       34612 :                         if (ret > 0)
     534        5125 :                                 n_exts++;
     535             :                 }
     536             :         }
     537             : 
     538        6564 :         _gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
     539             : 
     540        6564 :         return 0;
     541             : }
     542             : 
     543       18660 : int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
     544             :                                       handshake_buffer_st *recv_buf)
     545             : {
     546       18660 :         int ret;
     547       18660 :         gnutls_buffer_st *buf = &session->internals.full_client_hello;
     548             : 
     549       18660 :         _gnutls_buffer_clear(buf);
     550             : 
     551       18660 :         if ((ret = _gnutls_buffer_append_prefix(buf, 8, recv_buf->htype)) < 0)
     552           0 :                 return gnutls_assert_val(ret);
     553       18660 :         if ((ret = _gnutls_buffer_append_prefix(buf, 24, recv_buf->data.length)) < 0)
     554           0 :                 return gnutls_assert_val(ret);
     555       18660 :         if ((ret = _gnutls_buffer_append_data(buf, recv_buf->data.data, recv_buf->data.length)) < 0)
     556           0 :                 return gnutls_assert_val(ret);
     557             : 
     558             :         return 0;
     559             : }
     560             : 
     561        2077 : unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
     562             :                                            gnutls_datum_t *d)
     563             : {
     564        2077 :         gnutls_buffer_st *buf = &session->internals.full_client_hello;
     565             : 
     566        2077 :         if (!buf->length)
     567             :                 return 0;
     568             : 
     569        2077 :         d->data = buf->data;
     570        2077 :         d->size = buf->length;
     571             : 
     572        2077 :         return 1;
     573             : }
     574             : 
     575             : static void
     576        1340 : _gnutls_ext_set_resumed_session_data(gnutls_session_t session,
     577             :                                      extensions_t id,
     578             :                                      gnutls_ext_priv_data_t data)
     579             : {
     580        1340 :         const struct hello_ext_entry_st *ext;
     581             : 
     582             :         /* If this happens we need to increase the max */
     583        1340 :         assert(id < MAX_EXT_TYPES);
     584             : 
     585        1340 :         ext = gid_to_ext_entry(session, id);
     586        1340 :         assert(ext != NULL);
     587             : 
     588        1340 :         if (session->internals.ext_data[id].resumed_set != 0)
     589           0 :                 unset_resumed_ext_data(session, ext, id);
     590             : 
     591        1340 :         session->internals.ext_data[id].resumed_priv = data;
     592        1340 :         session->internals.ext_data[id].resumed_set = 1;
     593        1340 :         return;
     594             : }
     595             : 
     596        1322 : int _gnutls_hello_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
     597             : {
     598        1322 :         int i, ret;
     599        1322 :         gnutls_ext_priv_data_t data;
     600        1322 :         int max_exts = 0;
     601        1322 :         extensions_t id;
     602        1322 :         int size_for_id, cur_pos;
     603        1322 :         const struct hello_ext_entry_st *ext;
     604             : 
     605        1322 :         BUFFER_POP_NUM(packed, max_exts);
     606        2662 :         for (i = 0; i < max_exts; i++) {
     607        1340 :                 BUFFER_POP_NUM(packed, id);
     608        1340 :                 BUFFER_POP_NUM(packed, size_for_id);
     609             : 
     610        1340 :                 cur_pos = packed->length;
     611             : 
     612        1340 :                 ext = gid_to_ext_entry(session, id);
     613        1340 :                 if (ext == NULL || ext->unpack_func == NULL) {
     614           0 :                         gnutls_assert();
     615           0 :                         return GNUTLS_E_PARSING_ERROR;
     616             :                 }
     617             : 
     618        1340 :                 ret = ext->unpack_func(packed, &data);
     619        1340 :                 if (ret < 0) {
     620           0 :                         gnutls_assert();
     621           0 :                         return ret;
     622             :                 }
     623             : 
     624             :                 /* verify that unpack read the correct bytes */
     625        1340 :                 cur_pos = cur_pos - packed->length;
     626        1340 :                 if (cur_pos /* read length */  != size_for_id) {
     627           0 :                         gnutls_assert();
     628           0 :                         return GNUTLS_E_PARSING_ERROR;
     629             :                 }
     630             : 
     631        1340 :                 _gnutls_ext_set_resumed_session_data(session, id, data);
     632             :         }
     633             : 
     634             :         return 0;
     635             : 
     636             :       error:
     637             :         return ret;
     638             : }
     639             : 
     640             : static void
     641       61047 : unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
     642             : {
     643       61047 :         if (session->internals.ext_data[idx].set == 0)
     644             :                 return;
     645             : 
     646       58604 :         if (ext && ext->deinit_func && session->internals.ext_data[idx].priv != NULL)
     647       52678 :                 ext->deinit_func(session->internals.ext_data[idx].priv);
     648       58604 :         session->internals.ext_data[idx].set = 0;
     649             : }
     650             : 
     651             : void
     652        1918 : _gnutls_hello_ext_unset_priv(gnutls_session_t session,
     653             :                               extensions_t id)
     654             : {
     655        1918 :         const struct hello_ext_entry_st *ext;
     656             : 
     657        1918 :         ext = gid_to_ext_entry(session, id);
     658        1918 :         if (ext)
     659        1918 :                 unset_ext_data(session, ext, id);
     660        1918 : }
     661             : 
     662       58715 : static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
     663             : {
     664       58715 :         if (session->internals.ext_data[idx].resumed_set == 0)
     665             :                 return;
     666             : 
     667        1329 :         if (ext && ext->deinit_func && session->internals.ext_data[idx].resumed_priv) {
     668        1329 :                 ext->deinit_func(session->internals.ext_data[idx].resumed_priv);
     669             :         }
     670        1329 :         session->internals.ext_data[idx].resumed_set = 0;
     671             : }
     672             : 
     673             : /* Deinitializes all data that are associated with TLS extensions.
     674             :  */
     675       23001 : void _gnutls_hello_ext_priv_deinit(gnutls_session_t session)
     676             : {
     677       23001 :         unsigned int i;
     678       23001 :         const struct hello_ext_entry_st *ext;
     679             : 
     680     1495060 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     681     1472060 :                 if (!session->internals.ext_data[i].set && !session->internals.ext_data[i].resumed_set)
     682     1413350 :                         continue;
     683             : 
     684       58715 :                 ext = gid_to_ext_entry(session, i);
     685       58715 :                 if (ext) {
     686       58715 :                         unset_ext_data(session, ext, i);
     687       58715 :                         unset_resumed_ext_data(session, ext, i);
     688             :                 }
     689             :         }
     690       23001 : }
     691             : 
     692             : /* This function allows an extension to store data in the current session
     693             :  * and retrieve them later on. We use functions instead of a pointer to a
     694             :  * private pointer, to allow API additions by individual extensions.
     695             :  */
     696             : void
     697       58844 : _gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t id,
     698             :                              gnutls_ext_priv_data_t data)
     699             : {
     700       58844 :         const struct hello_ext_entry_st *ext;
     701             : 
     702       58844 :         assert(id < MAX_EXT_TYPES);
     703             : 
     704       58844 :         ext = gid_to_ext_entry(session, id);
     705       58844 :         assert(ext != NULL);
     706             : 
     707       58844 :         if (session->internals.ext_data[id].set != 0) {
     708         414 :                 unset_ext_data(session, ext, id);
     709             :         }
     710       58844 :         session->internals.ext_data[id].priv = data;
     711       58844 :         session->internals.ext_data[id].set = 1;
     712             : 
     713       58844 :         return;
     714             : }
     715             : 
     716             : int
     717      216761 : _gnutls_hello_ext_get_priv(gnutls_session_t session,
     718             :                             extensions_t id, gnutls_ext_priv_data_t * data)
     719             : {
     720      216761 :         if (session->internals.ext_data[id].set != 0) {
     721      105880 :                 *data =
     722      105880 :                     session->internals.ext_data[id].priv;
     723      105880 :                 return 0;
     724             :         }
     725             : 
     726             :         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     727             : }
     728             : 
     729             : int
     730        4443 : _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
     731             :                                     extensions_t id,
     732             :                                     gnutls_ext_priv_data_t * data)
     733             : {
     734        4443 :         if (session->internals.ext_data[id].resumed_set != 0) {
     735         143 :                 *data =
     736         143 :                     session->internals.ext_data[id].resumed_priv;
     737         143 :                 return 0;
     738             :         }
     739             : 
     740             :         return GNUTLS_E_INVALID_REQUEST;
     741             : }
     742             : 
     743             : /**
     744             :  * gnutls_ext_register:
     745             :  * @name: the name of the extension to register
     746             :  * @id: the numeric TLS id of the extension
     747             :  * @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
     748             :  * @recv_func: a function to receive the data
     749             :  * @send_func: a function to send the data
     750             :  * @deinit_func: a function deinitialize any private data
     751             :  * @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
     752             :  * @unpack_func: a function which will deserialize the extension's private data
     753             :  *
     754             :  * This function will register a new extension type. The extension will remain
     755             :  * registered until gnutls_global_deinit() is called. If the extension type
     756             :  * is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned.
     757             :  *
     758             :  * Each registered extension can store temporary data into the gnutls_session_t
     759             :  * structure using gnutls_ext_set_data(), and they can be retrieved using
     760             :  * gnutls_ext_get_data().
     761             :  *
     762             :  * Any extensions registered with this function are valid for the client
     763             :  * and TLS1.2 server hello (or encrypted extensions for TLS1.3).
     764             :  *
     765             :  * This function is not thread safe.
     766             :  *
     767             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     768             :  *
     769             :  * Since: 3.4.0
     770             :  **/
     771             : int
     772          82 : gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_point,
     773             :                     gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
     774             :                     gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
     775             :                     gnutls_ext_unpack_func unpack_func)
     776             : {
     777          82 :         hello_ext_entry_st *tmp_mod;
     778          82 :         unsigned i;
     779          82 :         unsigned gid = GNUTLS_EXTENSION_MAX+1;
     780             : 
     781        5330 :         for (i = 0; i < MAX_EXT_TYPES; i++) {
     782        5248 :                 if (!extfunc[i])
     783        1792 :                         continue;
     784             : 
     785        3456 :                 if (extfunc[i]->tls_id == id)
     786           0 :                         return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
     787             : 
     788        3456 :                 if (extfunc[i]->gid >= gid)
     789        1406 :                         gid = extfunc[i]->gid + 1;
     790             :         }
     791             : 
     792          82 :         if (gid > GNUTLS_EXTENSION_MAX_VALUE || gid >= sizeof(extfunc)/sizeof(extfunc[0]))
     793           2 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     794             : 
     795          80 :         tmp_mod = gnutls_calloc(1, sizeof(*tmp_mod));
     796          80 :         if (tmp_mod == NULL)
     797           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     798             : 
     799          80 :         tmp_mod->name = gnutls_strdup(name);
     800          80 :         tmp_mod->free_struct = 1;
     801          80 :         tmp_mod->tls_id = id;
     802          80 :         tmp_mod->gid = gid;
     803          80 :         tmp_mod->client_parse_point = parse_point;
     804          80 :         tmp_mod->server_parse_point = parse_point;
     805          80 :         tmp_mod->recv_func = recv_func;
     806          80 :         tmp_mod->send_func = send_func;
     807          80 :         tmp_mod->deinit_func = deinit_func;
     808          80 :         tmp_mod->pack_func = pack_func;
     809          80 :         tmp_mod->unpack_func = unpack_func;
     810          80 :         tmp_mod->validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
     811             :                             GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS;
     812             : 
     813          80 :         assert(extfunc[gid] == NULL);
     814          80 :         extfunc[gid] = tmp_mod;
     815             : 
     816          80 :         return 0;
     817             : }
     818             : 
     819             : #define VALIDITY_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | \
     820             :                         GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | \
     821             :                         GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
     822             : 
     823             : /**
     824             :  * gnutls_session_ext_register:
     825             :  * @session: the session for which this extension will be set
     826             :  * @name: the name of the extension to register
     827             :  * @id: the numeric id of the extension
     828             :  * @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
     829             :  * @recv_func: a function to receive the data
     830             :  * @send_func: a function to send the data
     831             :  * @deinit_func: a function deinitialize any private data
     832             :  * @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
     833             :  * @unpack_func: a function which will deserialize the extension's private data
     834             :  * @flags: must be zero or flags from %gnutls_ext_flags_t
     835             :  *
     836             :  * This function will register a new extension type. The extension will be
     837             :  * only usable within the registered session. If the extension type
     838             :  * is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned,
     839             :  * unless the flag %GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL is specified. The latter
     840             :  * flag when specified can be used to override certain extensions introduced
     841             :  * after 3.6.0. It is expected to be used by applications which handle
     842             :  * custom extensions that are not currently supported in GnuTLS, but direct
     843             :  * support for them may be added in the future.
     844             :  *
     845             :  * Each registered extension can store temporary data into the gnutls_session_t
     846             :  * structure using gnutls_ext_set_data(), and they can be retrieved using
     847             :  * gnutls_ext_get_data().
     848             :  *
     849             :  * The validity of the extension registered can be given by the appropriate flags
     850             :  * of %gnutls_ext_flags_t. If no validity is given, then the registered extension
     851             :  * will be valid for client and TLS1.2 server hello (or encrypted extensions for TLS1.3).
     852             :  *
     853             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     854             :  *
     855             :  * Since: 3.5.5
     856             :  **/
     857             : int
     858          90 : gnutls_session_ext_register(gnutls_session_t session,
     859             :                             const char *name, int id, gnutls_ext_parse_type_t parse_point,
     860             :                             gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
     861             :                             gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
     862             :                             gnutls_ext_unpack_func unpack_func, unsigned flags)
     863             : {
     864          90 :         hello_ext_entry_st tmp_mod;
     865          90 :         hello_ext_entry_st *exts;
     866          90 :         unsigned i;
     867          90 :         unsigned gid = GNUTLS_EXTENSION_MAX+1;
     868             : 
     869             :         /* reject handling any extensions which modify the TLS handshake
     870             :          * in any way, or are mapped to an exported API. */
     871        2381 :         for (i = 0; i < GNUTLS_EXTENSION_MAX; i++) {
     872        2304 :                 if (!extfunc[i])
     873          90 :                         continue;
     874             : 
     875        2214 :                 if (extfunc[i]->tls_id == id) {
     876          13 :                         if (!(flags & GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL)) {
     877           5 :                                 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
     878           8 :                         } else if (extfunc[i]->cannot_be_overriden) {
     879           2 :                                 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
     880             :                         }
     881             :                         break;
     882             :                 }
     883             : 
     884        2201 :                 if (extfunc[i]->gid >= gid)
     885           0 :                         gid = extfunc[i]->gid + 1;
     886             :         }
     887             : 
     888         223 :         for (i=0;i<session->internals.rexts_size;i++) {
     889         140 :                 if (session->internals.rexts[i].tls_id == id) {
     890           0 :                         return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
     891             :                 }
     892             : 
     893         140 :                 if (session->internals.rexts[i].gid >= gid)
     894         140 :                         gid = session->internals.rexts[i].gid + 1;
     895             :         }
     896             : 
     897          83 :         if (gid > GNUTLS_EXTENSION_MAX_VALUE)
     898           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     899             : 
     900          83 :         memset(&tmp_mod, 0, sizeof(hello_ext_entry_st));
     901          83 :         tmp_mod.name = gnutls_strdup(name);
     902          83 :         tmp_mod.free_struct = 1;
     903          83 :         tmp_mod.tls_id = id;
     904          83 :         tmp_mod.gid = gid;
     905          83 :         tmp_mod.client_parse_point = parse_point;
     906          83 :         tmp_mod.server_parse_point = parse_point;
     907          83 :         tmp_mod.recv_func = recv_func;
     908          83 :         tmp_mod.send_func = send_func;
     909          83 :         tmp_mod.deinit_func = deinit_func;
     910          83 :         tmp_mod.pack_func = pack_func;
     911          83 :         tmp_mod.unpack_func = unpack_func;
     912          83 :         tmp_mod.validity = flags;
     913             : 
     914          83 :         if ((tmp_mod.validity & VALIDITY_MASK) == 0) {
     915          76 :                 tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
     916             :                                    GNUTLS_EXT_FLAG_EE;
     917             :         }
     918             : 
     919          83 :         if ((tmp_mod.validity & (GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)) == 0) {
     920          83 :                 if (IS_DTLS(session))
     921           0 :                         tmp_mod.validity |= GNUTLS_EXT_FLAG_DTLS;
     922             :                 else
     923          83 :                         tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS;
     924             :         }
     925             : 
     926          83 :         exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts));
     927          83 :         if (exts == NULL) {
     928           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     929             :         }
     930             : 
     931          83 :         session->internals.rexts = exts;
     932             : 
     933          83 :         memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(hello_ext_entry_st));
     934          83 :         session->internals.rexts_size++;
     935             : 
     936          83 :         return 0;
     937             : }
     938             : 
     939             : /**
     940             :  * gnutls_ext_set_data:
     941             :  * @session: a #gnutls_session_t opaque pointer
     942             :  * @tls_id: the numeric id of the extension
     943             :  * @data: the private data to set
     944             :  *
     945             :  * This function allows an extension handler to store data in the current session
     946             :  * and retrieve them later on. The set data will be deallocated using
     947             :  * the gnutls_ext_deinit_data_func.
     948             :  *
     949             :  * Since: 3.4.0
     950             :  **/
     951             : void
     952           5 : gnutls_ext_set_data(gnutls_session_t session, unsigned tls_id,
     953             :                     gnutls_ext_priv_data_t data)
     954             : {
     955           5 :         unsigned id = tls_id_to_gid(session, tls_id);
     956           5 :         if (id == GNUTLS_EXTENSION_INVALID)
     957             :                 return;
     958             : 
     959           5 :         _gnutls_hello_ext_set_priv(session, id, data);
     960             : }
     961             : 
     962             : /**
     963             :  * gnutls_ext_get_data:
     964             :  * @session: a #gnutls_session_t opaque pointer
     965             :  * @tls_id: the numeric id of the extension
     966             :  * @data: a pointer to the private data to retrieve
     967             :  *
     968             :  * This function retrieves any data previously stored with gnutls_ext_set_data().
     969             :  *
     970             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     971             :  *
     972             :  * Since: 3.4.0
     973             :  **/
     974             : int
     975           5 : gnutls_ext_get_data(gnutls_session_t session,
     976             :                     unsigned tls_id, gnutls_ext_priv_data_t *data)
     977             : {
     978           5 :         unsigned id = tls_id_to_gid(session, tls_id);
     979           5 :         if (id == GNUTLS_EXTENSION_INVALID)
     980           0 :                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     981             : 
     982           5 :         return _gnutls_hello_ext_get_priv(session, id, data);
     983             : }
     984             : 
     985             : /**
     986             :  * gnutls_ext_get_current_msg:
     987             :  * @session: a #gnutls_session_t opaque pointer
     988             :  *
     989             :  * This function allows an extension handler to obtain the message
     990             :  * this extension is being called from. The returned value is a single
     991             :  * entry of the %gnutls_ext_flags_t enumeration. That is, if an
     992             :  * extension was registered with the %GNUTLS_EXT_FLAG_HRR and
     993             :  * %GNUTLS_EXT_FLAG_EE flags, the value when called during parsing of the
     994             :  * encrypted extensions message will be %GNUTLS_EXT_FLAG_EE.
     995             :  *
     996             :  * If not called under an extension handler, its value is undefined.
     997             :  *
     998             :  * Since: 3.6.3
     999             :  **/
    1000           1 : unsigned gnutls_ext_get_current_msg(gnutls_session_t session)
    1001             : {
    1002           1 :         return _gnutls_ext_get_msg(session);
    1003             : }
    1004             : 
    1005             : /**
    1006             :  * gnutls_ext_get_name2:
    1007             :  * @session: a #gnutls_session_t opaque pointer
    1008             :  * @tls_id: is a TLS extension numeric ID
    1009             :  * @parse_point: the parse type of the extension
    1010             :  *
    1011             :  * Convert a TLS extension numeric ID to a printable string.
    1012             :  *
    1013             :  * Returns: a pointer to a string that contains the name of the
    1014             :  *   specified cipher, or %NULL.
    1015             :  **/
    1016           0 : const char *gnutls_ext_get_name2(gnutls_session_t session, unsigned int tls_id,
    1017             :                                  gnutls_ext_parse_type_t parse_point)
    1018             : {
    1019           0 :         const struct hello_ext_entry_st *ext;
    1020             : 
    1021           0 :         ext = tls_id_to_ext_entry(session, tls_id, parse_point);
    1022           0 :         if (ext)
    1023           0 :                 return ext->name;
    1024             : 
    1025             :         return NULL;
    1026             : }
    1027             : 

Generated by: LCOV version 1.14