LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - prf.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 54 73 74.0 %
Date: 2020-10-30 04:50:48 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2002-2015 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2014-2015 Nikos Mavrogiannopoulos
       4             :  * Copyright (C) 2016-2017 Red Hat, Inc.
       5             :  *
       6             :  * Author: Nikos Mavrogiannopoulos
       7             :  *
       8             :  * This file is part of GnuTLS.
       9             :  *
      10             :  * The GnuTLS is free software; you can redistribute it and/or
      11             :  * modify it under the terms of the GNU Lesser General Public License
      12             :  * as published by the Free Software Foundation; either version 2.1 of
      13             :  * the License, or (at your option) any later version.
      14             :  *
      15             :  * This library is distributed in the hope that it will be useful, but
      16             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :  * Lesser General Public License for more details.
      19             :  *
      20             :  * You should have received a copy of the GNU Lesser General Public License
      21             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      22             :  *
      23             :  */
      24             : 
      25             : /* Functions for the TLS PRF handling.
      26             :  */
      27             : 
      28             : #include "gnutls_int.h"
      29             : #include "errors.h"
      30             : #include "handshake.h"
      31             : #include "secrets.h"
      32             : #include <num.h>
      33             : #include <state.h>
      34             : #include <algorithms.h>
      35             : 
      36             : /**
      37             :  * gnutls_prf_raw:
      38             :  * @session: is a #gnutls_session_t type.
      39             :  * @label_size: length of the @label variable.
      40             :  * @label: label used in PRF computation, typically a short string.
      41             :  * @seed_size: length of the @seed variable.
      42             :  * @seed: optional extra data to seed the PRF with.
      43             :  * @outsize: size of pre-allocated output buffer to hold the output.
      44             :  * @out: pre-allocated buffer to hold the generated data.
      45             :  *
      46             :  * Apply the TLS Pseudo-Random-Function (PRF) on the master secret
      47             :  * and the provided data.
      48             :  *
      49             :  * The @label variable usually contains a string denoting the purpose
      50             :  * for the generated data.  The @seed usually contains data such as the
      51             :  * client and server random, perhaps together with some additional
      52             :  * data that is added to guarantee uniqueness of the output for a
      53             :  * particular purpose.
      54             :  *
      55             :  * Because the output is not guaranteed to be unique for a particular
      56             :  * session unless @seed includes the client random and server random
      57             :  * fields (the PRF would output the same data on another connection
      58             :  * resumed from the first one), it is not recommended to use this
      59             :  * function directly.  The gnutls_prf() function seeds the PRF with the
      60             :  * client and server random fields directly, and is recommended if you
      61             :  * want to generate pseudo random data unique for each session.
      62             :  *
      63             :  * Note: This function will only operate under TLS versions prior to 1.3.
      64             :  * In TLS1.3 the use of PRF is replaced with HKDF and the generic
      65             :  * exporters like gnutls_prf_rfc5705() should be used instead. Under
      66             :  * TLS1.3 this function returns %GNUTLS_E_INVALID_REQUEST.
      67             :  *
      68             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
      69             :  **/
      70             : int
      71           0 : gnutls_prf_raw(gnutls_session_t session,
      72             :                size_t label_size,
      73             :                const char *label,
      74             :                size_t seed_size, const char *seed, size_t outsize,
      75             :                char *out)
      76             : {
      77           0 :         int ret;
      78           0 :         const version_entry_st *vers = get_version(session);
      79             : 
      80           0 :         if (vers && vers->tls13_sem)
      81           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
      82             : 
      83           0 :         if (session->security_parameters.prf == NULL)
      84           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
      85             : 
      86           0 :         ret = _gnutls_prf_raw(session->security_parameters.prf->id,
      87           0 :                           GNUTLS_MASTER_SIZE, session->security_parameters.master_secret,
      88             :                           label_size, label,
      89             :                           seed_size, (uint8_t *) seed,
      90             :                           outsize, out);
      91             : 
      92           0 :         return ret;
      93             : }
      94             : 
      95             : static int
      96          20 : _tls13_derive_exporter(const mac_entry_st *prf,
      97             :                        gnutls_session_t session,
      98             :                        size_t label_size, const char *label,
      99             :                        size_t context_size, const char *context,
     100             :                        size_t outsize, char *out,
     101             :                        bool early)
     102             : {
     103          20 :         uint8_t secret[MAX_HASH_SIZE];
     104          20 :         uint8_t digest[MAX_HASH_SIZE];
     105          20 :         unsigned digest_size = prf->output_size;
     106          20 :         int ret;
     107             : 
     108          40 :         ret = _tls13_derive_secret2(prf, label, label_size, NULL, 0,
     109          20 :                                     session->key.proto.tls13.ap_expkey,
     110             :                                     secret);
     111          20 :         if (ret < 0)
     112           0 :                 return gnutls_assert_val(ret);
     113             : 
     114          20 :         ret = gnutls_hash_fast((gnutls_digest_algorithm_t)prf->id,
     115             :                                context, context_size, digest);
     116          20 :         if (ret < 0)
     117           0 :                 return gnutls_assert_val(ret);
     118             : 
     119          20 :         return _tls13_expand_secret2(prf,
     120             :                                      EXPORTER_LABEL, sizeof(EXPORTER_LABEL)-1,
     121             :                                      digest, digest_size,
     122             :                                      secret, outsize, out);
     123             : }
     124             : 
     125             : /**
     126             :  * gnutls_prf_rfc5705:
     127             :  * @session: is a #gnutls_session_t type.
     128             :  * @label_size: length of the @label variable.
     129             :  * @label: label used in PRF computation, typically a short string.
     130             :  * @context_size: length of the @extra variable.
     131             :  * @context: optional extra data to seed the PRF with.
     132             :  * @outsize: size of pre-allocated output buffer to hold the output.
     133             :  * @out: pre-allocated buffer to hold the generated data.
     134             :  *
     135             :  * Exports keying material from TLS/DTLS session to an application, as
     136             :  * specified in RFC5705.
     137             :  *
     138             :  * In the TLS versions prior to 1.3, it applies the TLS
     139             :  * Pseudo-Random-Function (PRF) on the master secret and the provided
     140             :  * data, seeded with the client and server random fields.
     141             :  *
     142             :  * In TLS 1.3, it applies HKDF on the exporter master secret derived
     143             :  * from the master secret.
     144             :  *
     145             :  * The @label variable usually contains a string denoting the purpose
     146             :  * for the generated data.
     147             :  *
     148             :  * The @context variable can be used to add more data to the seed, after
     149             :  * the random variables.  It can be used to make sure the
     150             :  * generated output is strongly connected to some additional data
     151             :  * (e.g., a string used in user authentication). 
     152             :  *
     153             :  * The output is placed in @out, which must be pre-allocated.
     154             :  *
     155             :  * Note that, to provide the RFC5705 context, the @context variable
     156             :  * must be non-null.
     157             :  *
     158             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
     159             :  *
     160             :  * Since: 3.4.4
     161             :  **/
     162             : int
     163          18 : gnutls_prf_rfc5705(gnutls_session_t session,
     164             :                    size_t label_size, const char *label,
     165             :                    size_t context_size, const char *context,
     166             :                    size_t outsize, char *out)
     167             : {
     168          18 :         const version_entry_st *vers = get_version(session);
     169          18 :         int ret;
     170             : 
     171          18 :         if (session->security_parameters.prf == NULL)
     172           1 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     173             : 
     174          17 :         if (vers && vers->tls13_sem) {
     175          12 :                 ret = _tls13_derive_exporter(session->security_parameters.prf,
     176             :                                              session,
     177             :                                              label_size, label,
     178             :                                              context_size, context,
     179             :                                              outsize, out,
     180             :                                              0);
     181             :         } else {
     182           5 :                 char *pctx = NULL;
     183             : 
     184           5 :                 if (context != NULL && context_size > 65535)  {
     185           0 :                         gnutls_assert();
     186           0 :                         return GNUTLS_E_INVALID_REQUEST;
     187             :                 }
     188             : 
     189           5 :                 if (context != NULL) {
     190           2 :                         pctx = gnutls_malloc(context_size+2);
     191           2 :                         if (!pctx) {
     192           0 :                                 gnutls_assert();
     193           0 :                                 return GNUTLS_E_MEMORY_ERROR;
     194             :                         }
     195             : 
     196           2 :                         memcpy(pctx+2, context, context_size);
     197           2 :                         _gnutls_write_uint16(context_size, (void*)pctx);
     198           2 :                         context_size += 2;
     199             :                 }
     200             : 
     201           5 :                 ret = gnutls_prf(session, label_size, label, 0,
     202             :                                  context_size, pctx, outsize, out);
     203             : 
     204           5 :                 gnutls_free(pctx);
     205             :         }
     206             : 
     207             :         return ret;
     208             : }
     209             : 
     210             : /**
     211             :  * gnutls_prf_early:
     212             :  * @session: is a #gnutls_session_t type.
     213             :  * @label_size: length of the @label variable.
     214             :  * @label: label used in PRF computation, typically a short string.
     215             :  * @context_size: length of the @extra variable.
     216             :  * @context: optional extra data to seed the PRF with.
     217             :  * @outsize: size of pre-allocated output buffer to hold the output.
     218             :  * @out: pre-allocated buffer to hold the generated data.
     219             :  *
     220             :  * This function is similar to gnutls_prf_rfc5705(), but only works in
     221             :  * TLS 1.3 or later to export early keying material.
     222             :  *
     223             :  * Note that the keying material is only available after the
     224             :  * ClientHello message is processed and before the application traffic
     225             :  * keys are established.  Therefore this function shall be called in a
     226             :  * handshake hook function for %GNUTLS_HANDSHAKE_CLIENT_HELLO.
     227             :  *
     228             :  * The @label variable usually contains a string denoting the purpose
     229             :  * for the generated data.
     230             :  *
     231             :  * The @context variable can be used to add more data to the seed, after
     232             :  * the random variables.  It can be used to make sure the
     233             :  * generated output is strongly connected to some additional data
     234             :  * (e.g., a string used in user authentication).
     235             :  *
     236             :  * The output is placed in @out, which must be pre-allocated.
     237             :  *
     238             :  * Note that, to provide the RFC5705 context, the @context variable
     239             :  * must be non-null.
     240             :  *
     241             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
     242             :  *
     243             :  * Since: 3.6.8
     244             :  **/
     245             : int
     246           8 : gnutls_prf_early(gnutls_session_t session,
     247             :                  size_t label_size, const char *label,
     248             :                  size_t context_size, const char *context,
     249             :                  size_t outsize, char *out)
     250             : {
     251           8 :         if (session->internals.initial_negotiation_completed ||
     252           8 :             session->key.binders[0].prf == NULL)
     253           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     254             : 
     255           8 :         return _tls13_derive_exporter(session->key.binders[0].prf, session,
     256             :                                       label_size, label,
     257             :                                       context_size, context,
     258             :                                       outsize, out,
     259             :                                       1);
     260             : }
     261             : 
     262             : /**
     263             :  * gnutls_prf:
     264             :  * @session: is a #gnutls_session_t type.
     265             :  * @label_size: length of the @label variable.
     266             :  * @label: label used in PRF computation, typically a short string.
     267             :  * @server_random_first: non-zero if server random field should be first in seed
     268             :  * @extra_size: length of the @extra variable.
     269             :  * @extra: optional extra data to seed the PRF with.
     270             :  * @outsize: size of pre-allocated output buffer to hold the output.
     271             :  * @out: pre-allocated buffer to hold the generated data.
     272             :  *
     273             :  * Applies the TLS Pseudo-Random-Function (PRF) on the master secret
     274             :  * and the provided data, seeded with the client and server random fields.
     275             :  * For the key expansion specified in RFC5705 see gnutls_prf_rfc5705().
     276             :  *
     277             :  * The @label variable usually contains a string denoting the purpose
     278             :  * for the generated data.  The @server_random_first indicates whether
     279             :  * the client random field or the server random field should be first
     280             :  * in the seed.  Non-zero indicates that the server random field is first,
     281             :  * 0 that the client random field is first.
     282             :  *
     283             :  * The @extra variable can be used to add more data to the seed, after
     284             :  * the random variables.  It can be used to make sure the
     285             :  * generated output is strongly connected to some additional data
     286             :  * (e.g., a string used in user authentication).
     287             :  *
     288             :  * The output is placed in @out, which must be pre-allocated.
     289             :  *
     290             :  * Note: This function produces identical output with gnutls_prf_rfc5705()
     291             :  * when @server_random_first is set to 0 and @extra is %NULL. Under TLS1.3
     292             :  * this function will only operate when these conditions are true, or otherwise
     293             :  * return %GNUTLS_E_INVALID_REQUEST.
     294             :  *
     295             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
     296             :  **/
     297             : int
     298          24 : gnutls_prf(gnutls_session_t session,
     299             :            size_t label_size,
     300             :            const char *label,
     301             :            int server_random_first,
     302             :            size_t extra_size, const char *extra,
     303             :            size_t outsize, char *out)
     304             : {
     305          24 :         int ret;
     306          24 :         uint8_t *seed;
     307          24 :         const version_entry_st *vers = get_version(session);
     308          24 :         size_t seedsize = 2 * GNUTLS_RANDOM_SIZE + extra_size;
     309             : 
     310          24 :         if (vers && vers->tls13_sem) {
     311           8 :                 if (extra == NULL && server_random_first == 0)
     312           4 :                         return gnutls_prf_rfc5705(session, label_size, label,
     313             :                                                   extra_size, extra, outsize, out);
     314             :                 else
     315           4 :                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     316             :         }
     317             : 
     318          16 :         if (session->security_parameters.prf == NULL)
     319           1 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     320             : 
     321          15 :         seed = gnutls_malloc(seedsize);
     322          15 :         if (!seed) {
     323           0 :                 gnutls_assert();
     324           0 :                 return GNUTLS_E_MEMORY_ERROR;
     325             :         }
     326             : 
     327          15 :         memcpy(seed, server_random_first ?
     328             :                session->security_parameters.server_random :
     329             :                session->security_parameters.client_random,
     330             :                GNUTLS_RANDOM_SIZE);
     331          15 :         memcpy(seed + GNUTLS_RANDOM_SIZE,
     332             :                server_random_first ? session->security_parameters.
     333             :                client_random : session->security_parameters.server_random,
     334             :                GNUTLS_RANDOM_SIZE);
     335             : 
     336          15 :         if (extra && extra_size) {
     337           3 :                 memcpy(seed + 2 * GNUTLS_RANDOM_SIZE, extra, extra_size);
     338             :         }
     339             : 
     340          15 :         ret =
     341          30 :             _gnutls_prf_raw(session->security_parameters.prf->id,
     342          15 :                         GNUTLS_MASTER_SIZE, session->security_parameters.master_secret,
     343             :                         label_size, label,
     344             :                         seedsize, seed,
     345             :                         outsize, out);
     346             : 
     347          15 :         gnutls_free(seed);
     348             : 
     349          15 :         return ret;
     350             : }
     351             : 

Generated by: LCOV version 1.14