Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/nettle/int/dsa-compute-k.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2019 Red Hat, Inc.
3
 *
4
 * Author: Daiki Ueno
5
 *
6
 * This file is part of GNUTLS.
7
 *
8
 * The GNUTLS library 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
#if HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include "dsa-compute-k.h"
28
29
#include "gnutls_int.h"
30
#include "mem.h"
31
#include "mpn-base256.h"
32
#include <string.h>
33
34
/* For mini-gmp */
35
#ifndef GMP_LIMB_BITS
36
#define GMP_LIMB_BITS GMP_NUMB_BITS
37
#endif
38
39
static inline int is_zero_limb(mp_limb_t x)
40
0
{
41
0
  x |= (x << 1);
42
0
  return ((x >> 1) - 1) >> (GMP_LIMB_BITS - 1);
43
0
}
44
45
static int sec_zero_p(const mp_limb_t *ap, mp_size_t n)
46
0
{
47
0
  volatile mp_limb_t w;
48
0
  mp_size_t i;
49
50
0
  for (i = 0, w = 0; i < n; i++)
51
0
    w |= ap[i];
52
53
0
  return is_zero_limb(w);
54
0
}
55
56
int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x,
57
        mp_size_t qn, mp_bitcnt_t q_bits,
58
        gnutls_mac_algorithm_t mac, const uint8_t *digest,
59
        size_t length)
60
0
{
61
0
  uint8_t V[MAX_HASH_SIZE];
62
0
  uint8_t K[MAX_HASH_SIZE];
63
0
  uint8_t xp[MAX_Q_SIZE];
64
0
  uint8_t tp[MAX_Q_SIZE];
65
0
  mp_bitcnt_t h_bits = length * 8;
66
0
  mp_size_t hn = BITS_TO_LIMBS(h_bits);
67
0
  size_t nbytes = (q_bits + 7) / 8;
68
0
  const uint8_t c0 = 0x00;
69
0
  const uint8_t c1 = 0x01;
70
0
  mp_limb_t cy;
71
0
  gnutls_hmac_hd_t hd;
72
0
  int ret = 0;
73
0
  mp_limb_t scratch[MAX_Q_LIMBS];
74
75
0
  if (unlikely(q_bits > MAX_Q_BITS))
76
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
77
0
  if (unlikely(length > MAX_HASH_SIZE))
78
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
79
80
  /* int2octets(x) */
81
0
  mpn_get_base256(xp, nbytes, x, qn);
82
83
  /* bits2octets(h) */
84
0
  mpn_set_base256(h, hn, digest, length);
85
86
0
  if (hn < qn)
87
    /* qlen > blen: add zero bits to the left */
88
0
    mpn_zero(&h[hn], qn - hn);
89
0
  else if (h_bits > q_bits) {
90
    /* qlen < blen: keep the leftmost qlen bits.  We do this in 2
91
     * steps because mpn_rshift only accepts shift count in the
92
     * range 1 to mp_bits_per_limb-1.
93
     */
94
0
    mp_bitcnt_t shift = h_bits - q_bits;
95
96
0
    if (shift / GMP_NUMB_BITS > 0) {
97
0
      mpn_copyi(h, &h[shift / GMP_NUMB_BITS], qn);
98
0
      hn -= shift / GMP_NUMB_BITS;
99
0
    }
100
101
0
    if (shift % GMP_NUMB_BITS > 0)
102
0
      mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS);
103
0
  }
104
105
0
  cy = mpn_sub_n(h, h, q, qn);
106
  /* Fall back to addmul_1, if nettle is linked with mini-gmp. */
107
0
#if defined(mpn_cnd_add_n) && !NETTLE_USE_MINI_GMP
108
0
  mpn_cnd_add_n(cy, h, h, q, qn);
109
#else
110
  mpn_addmul_1(h, q, qn, cy != 0);
111
#endif
112
0
  mpn_get_base256(tp, nbytes, h, qn);
113
114
  /* Step b */
115
0
  memset(V, c1, length);
116
117
  /* Step c */
118
0
  memset(K, c0, length);
119
120
  /* Step d */
121
0
  ret = gnutls_hmac_init(&hd, mac, K, length);
122
0
  if (ret < 0)
123
0
    goto out;
124
0
  ret = gnutls_hmac(hd, V, length);
125
0
  if (ret < 0)
126
0
    goto out;
127
0
  ret = gnutls_hmac(hd, &c0, 1);
128
0
  if (ret < 0)
129
0
    goto out;
130
0
  ret = gnutls_hmac(hd, xp, nbytes);
131
0
  if (ret < 0)
132
0
    goto out;
133
0
  ret = gnutls_hmac(hd, tp, nbytes);
134
0
  if (ret < 0)
135
0
    goto out;
136
0
  gnutls_hmac_deinit(hd, K);
137
138
  /* Step e */
139
0
  ret = gnutls_hmac_fast(mac, K, length, V, length, V);
140
0
  if (ret < 0)
141
0
    goto out;
142
143
  /* Step f */
144
0
  ret = gnutls_hmac_init(&hd, mac, K, length);
145
0
  if (ret < 0)
146
0
    goto out;
147
0
  ret = gnutls_hmac(hd, V, length);
148
0
  if (ret < 0)
149
0
    goto out;
150
0
  ret = gnutls_hmac(hd, &c1, 1);
151
0
  if (ret < 0)
152
0
    goto out;
153
0
  ret = gnutls_hmac(hd, xp, nbytes);
154
0
  if (ret < 0)
155
0
    goto out;
156
0
  ret = gnutls_hmac(hd, tp, nbytes);
157
0
  if (ret < 0)
158
0
    goto out;
159
0
  gnutls_hmac_deinit(hd, K);
160
161
  /* Step g */
162
0
  ret = gnutls_hmac_fast(mac, K, length, V, length, V);
163
0
  if (ret < 0)
164
0
    goto out;
165
166
  /* Step h */
167
0
  for (;;) {
168
    /* Step 1 */
169
0
    size_t tlen = 0;
170
171
    /* Step 2 */
172
0
    while (tlen < nbytes) {
173
0
      size_t remaining = MIN(nbytes - tlen, length);
174
0
      ret = gnutls_hmac_fast(mac, K, length, V, length, V);
175
0
      if (ret < 0)
176
0
        goto out;
177
0
      memcpy(&tp[tlen], V, remaining);
178
0
      tlen += remaining;
179
0
    }
180
181
    /* Step 3 */
182
0
    mpn_set_base256(h, qn, tp, tlen);
183
0
    if (tlen * 8 > q_bits)
184
0
      mpn_rshift(h, h, qn, tlen * 8 - q_bits);
185
    /* Check if k is in [1,q-1] */
186
0
    if (!sec_zero_p(h, qn) && mpn_sub_n(scratch, h, q, qn))
187
0
      break;
188
189
0
    ret = gnutls_hmac_init(&hd, mac, K, length);
190
0
    if (ret < 0)
191
0
      goto out;
192
0
    ret = gnutls_hmac(hd, V, length);
193
0
    if (ret < 0)
194
0
      goto out;
195
0
    ret = gnutls_hmac(hd, &c0, 1);
196
0
    if (ret < 0)
197
0
      goto out;
198
0
    gnutls_hmac_deinit(hd, K);
199
200
0
    ret = gnutls_hmac_fast(mac, K, length, V, length, V);
201
0
    if (ret < 0)
202
0
      goto out;
203
0
  }
204
205
0
out:
206
0
  zeroize_key(xp, sizeof(xp));
207
0
  zeroize_key(tp, sizeof(tp));
208
209
0
  return ret;
210
0
}
211
212
/* cancel-out dsa_sign's addition of 1 to random data */
213
void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
214
          mp_size_t n)
215
0
{
216
  /* Fall back to sub_1, if nettle is linked with mini-gmp. */
217
0
#ifdef mpn_sec_sub_1
218
0
  mp_limb_t t[MAX_Q_LIMBS];
219
220
0
  mpn_sec_sub_1(h, h, n, 1, t);
221
#else
222
  mpn_sub_1(h, h, n, 1);
223
#endif
224
0
  mpn_get_base256(k, nbytes, h, n);
225
0
}
226
227
void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
228
            mp_size_t n)
229
0
{
230
0
  mpn_get_base256(k, nbytes, h, n);
231
0
}