Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/nettle/int/tls1-prf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2017 Red Hat, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* Functions for the TLS PRF handling.
24
 */
25
26
#if HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
30
#include "gnutls_int.h"
31
#include "fips.h"
32
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include <nettle/hmac.h>
37
#include <nettle/memxor.h>
38
#include "int/tls1-prf.h"
39
#include <nettle/sha1.h>
40
#include <nettle/md5.h>
41
42
/* The RFC2246 P_hash() function. The mac_ctx is expected to
43
 * be initialized and key set to be the secret key.
44
 */
45
static void P_hash(void *mac_ctx, nettle_hash_update_func *update,
46
       nettle_hash_digest_func *digest, size_t digest_size,
47
       size_t seed_size, const uint8_t *seed, size_t label_size,
48
       const char *label, size_t dst_length, uint8_t *dst)
49
0
{
50
0
  uint8_t Atmp[MAX_HASH_SIZE];
51
0
  ssize_t left;
52
0
  unsigned started = 0;
53
54
  /* round up */
55
0
  left = dst_length;
56
57
0
  while (left > 0) {
58
0
    if (started == 0) { /* A(0) */
59
0
      update(mac_ctx, label_size,
60
0
             (const uint8_t *)label); /* hash label */
61
0
      update(mac_ctx, seed_size, seed);
62
0
      started = 1;
63
0
    } else {
64
0
      update(mac_ctx, digest_size, Atmp);
65
0
    }
66
0
    digest(mac_ctx, digest_size, Atmp); /* store A(i) */
67
68
0
    update(mac_ctx, digest_size, Atmp); /* hash A(i) */
69
0
    update(mac_ctx, label_size,
70
0
           (const uint8_t *)label); /* hash label */
71
0
    update(mac_ctx, seed_size, seed); /* hash seed */
72
73
0
    if (left < (ssize_t)digest_size)
74
0
      digest_size = left;
75
76
0
    digest(mac_ctx, digest_size, dst);
77
78
0
    left -= digest_size;
79
0
    dst += digest_size;
80
0
  }
81
82
0
  return;
83
0
}
84
85
int tls10_prf(size_t secret_size, const uint8_t *secret, size_t label_size,
86
        const char *label, size_t seed_size, const uint8_t *seed,
87
        size_t length, uint8_t *dst)
88
0
{
89
0
  int l_s;
90
0
  const uint8_t *s1, *s2;
91
0
  struct hmac_md5_ctx md5_ctx;
92
0
  struct hmac_sha1_ctx sha1_ctx;
93
0
  uint8_t o1[MAX_PRF_BYTES];
94
95
0
  if (length > MAX_PRF_BYTES)
96
0
    return 0;
97
98
0
  l_s = secret_size / 2;
99
0
  s1 = &secret[0];
100
0
  s2 = &secret[l_s];
101
0
  if (secret_size % 2 != 0) {
102
0
    l_s++;
103
0
  }
104
105
0
  hmac_md5_set_key(&md5_ctx, l_s, s1);
106
107
0
  P_hash(&md5_ctx, (nettle_hash_update_func *)hmac_md5_update,
108
0
         (nettle_hash_digest_func *)hmac_md5_digest, MD5_DIGEST_SIZE,
109
0
         seed_size, seed, label_size, label, length, o1);
110
111
0
  hmac_sha1_set_key(&sha1_ctx, l_s, s2);
112
113
0
  P_hash(&sha1_ctx, (nettle_hash_update_func *)hmac_sha1_update,
114
0
         (nettle_hash_digest_func *)hmac_sha1_digest, SHA1_DIGEST_SIZE,
115
0
         seed_size, seed, label_size, label, length, dst);
116
117
0
  memxor(dst, o1, length);
118
119
0
  return 1;
120
0
}
121
122
/*-
123
 * tls12_prf:
124
 * @mac_ctx: a MAC context initialized with key being the secret
125
 * @update: a MAC update function
126
 * @digest: a MAC digest function
127
 * @digest_size: the MAC output size
128
 * @label_size: the size of the label
129
 * @label: the label to apply
130
 * @seed_size: the seed size
131
 * @seed: the seed
132
 * @length: size of desired PRF output
133
 * @dst: the location to store output
134
 *
135
 * The TLS 1.2 Pseudo-Random-Function (PRF).
136
 *
137
 * Returns: zero on failure, non zero on success.
138
 -*/
139
int tls12_prf(void *mac_ctx, nettle_hash_update_func *update,
140
        nettle_hash_digest_func *digest, size_t digest_size,
141
        size_t label_size, const char *label, size_t seed_size,
142
        const uint8_t *seed, size_t length, uint8_t *dst)
143
0
{
144
0
#define MASTER_SECRET "master secret"
145
0
#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET) - 1)
146
147
0
  P_hash(mac_ctx, update, digest, digest_size, seed_size, seed,
148
0
         label_size, label, length, dst);
149
150
  /* Since May 16, 2023, the use of extended master secret is
151
   * mandatory according to FIPS 140-3 IG D.Q.  Instead of
152
   * allowing the "extended master secret" label specifically,
153
   * we mark the use of non-EMS label, i.e., "master secret" as
154
   * non-approved, because it is still useful to call the
155
   * gnutls_prf_raw function with arbitrary label, e.g., in
156
   * self-tests.
157
   */
158
0
  if (label_size == MASTER_SECRET_SIZE &&
159
0
      memcmp(label, MASTER_SECRET, MASTER_SECRET_SIZE) == 0) {
160
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
161
0
  } else {
162
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
163
0
  }
164
165
0
  return 1;
166
0
}