Coverage Report

Created: 2026-09-14 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/src/tls/rsa.c
Line
Count
Source
1
/*
2
 * RSA
3
 * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "includes.h"
10
11
#include "common.h"
12
#include "asn1.h"
13
#include "bignum.h"
14
#include "rsa.h"
15
16
17
struct crypto_rsa_key {
18
  int private_key; /* whether private key is set */
19
  struct bignum *n; /* modulus (p * q) */
20
  struct bignum *e; /* public exponent */
21
  /* The following parameters are available only if private_key is set */
22
  struct bignum *d; /* private exponent */
23
  struct bignum *p; /* prime p (factor of n) */
24
  struct bignum *q; /* prime q (factor of n) */
25
  struct bignum *dmp1; /* d mod (p - 1); CRT exponent */
26
  struct bignum *dmq1; /* d mod (q - 1); CRT exponent */
27
  struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */
28
};
29
30
31
static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end,
32
             struct bignum *num)
33
18
{
34
18
  struct asn1_hdr hdr;
35
36
18
  if (pos == NULL)
37
0
    return NULL;
38
39
18
  if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
40
18
      !asn1_is_integer(&hdr)) {
41
0
    asn1_unexpected(&hdr, "RSA: Expected INTEGER");
42
0
    return NULL;
43
0
  }
44
45
18
  if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) {
46
0
    wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER");
47
0
    return NULL;
48
0
  }
49
50
18
  return hdr.payload + hdr.length;
51
18
}
52
53
54
/**
55
 * crypto_rsa_import_public_key - Import an RSA public key
56
 * @buf: Key buffer (DER encoded RSA public key)
57
 * @len: Key buffer length in bytes
58
 * Returns: Pointer to the public key or %NULL on failure
59
 */
60
struct crypto_rsa_key *
61
crypto_rsa_import_public_key(const u8 *buf, size_t len)
62
0
{
63
0
  struct crypto_rsa_key *key;
64
0
  struct asn1_hdr hdr;
65
0
  const u8 *pos, *end;
66
67
0
  key = os_zalloc(sizeof(*key));
68
0
  if (key == NULL)
69
0
    return NULL;
70
71
0
  key->n = bignum_init();
72
0
  key->e = bignum_init();
73
0
  if (key->n == NULL || key->e == NULL) {
74
0
    crypto_rsa_free(key);
75
0
    return NULL;
76
0
  }
77
78
  /*
79
   * PKCS #1, 7.1:
80
   * RSAPublicKey ::= SEQUENCE {
81
   *     modulus INTEGER, -- n
82
   *     publicExponent INTEGER -- e
83
   * }
84
   */
85
86
0
  if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
87
0
    asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)");
88
0
    goto error;
89
0
  }
90
0
  pos = hdr.payload;
91
0
  end = pos + hdr.length;
92
93
0
  pos = crypto_rsa_parse_integer(pos, end, key->n);
94
0
  pos = crypto_rsa_parse_integer(pos, end, key->e);
95
96
0
  if (pos == NULL)
97
0
    goto error;
98
99
0
  if (pos != end) {
100
0
    wpa_hexdump(MSG_DEBUG,
101
0
          "RSA: Extra data in public key SEQUENCE",
102
0
          pos, end - pos);
103
0
    goto error;
104
0
  }
105
106
0
  return key;
107
108
0
error:
109
0
  crypto_rsa_free(key);
110
0
  return NULL;
111
0
}
112
113
114
struct crypto_rsa_key *
115
crypto_rsa_import_public_key_parts(const u8 *n, size_t n_len,
116
           const u8 *e, size_t e_len)
117
0
{
118
0
  struct crypto_rsa_key *key;
119
120
0
  key = os_zalloc(sizeof(*key));
121
0
  if (key == NULL)
122
0
    return NULL;
123
124
0
  key->n = bignum_init();
125
0
  key->e = bignum_init();
126
0
  if (key->n == NULL || key->e == NULL ||
127
0
      bignum_set_unsigned_bin(key->n, n, n_len) < 0 ||
128
0
      bignum_set_unsigned_bin(key->e, e, e_len) < 0) {
129
0
    crypto_rsa_free(key);
130
0
    return NULL;
131
0
  }
132
133
0
  return key;
134
0
}
135
136
137
/**
138
 * crypto_rsa_import_private_key - Import an RSA private key
139
 * @buf: Key buffer (DER encoded RSA private key)
140
 * @len: Key buffer length in bytes
141
 * Returns: Pointer to the private key or %NULL on failure
142
 */
143
struct crypto_rsa_key *
144
crypto_rsa_import_private_key(const u8 *buf, size_t len)
145
4
{
146
4
  struct crypto_rsa_key *key;
147
4
  struct bignum *zero;
148
4
  struct asn1_hdr hdr;
149
4
  const u8 *pos, *end;
150
151
4
  key = os_zalloc(sizeof(*key));
152
4
  if (key == NULL)
153
0
    return NULL;
154
155
4
  key->private_key = 1;
156
157
4
  key->n = bignum_init();
158
4
  key->e = bignum_init();
159
4
  key->d = bignum_init();
160
4
  key->p = bignum_init();
161
4
  key->q = bignum_init();
162
4
  key->dmp1 = bignum_init();
163
4
  key->dmq1 = bignum_init();
164
4
  key->iqmp = bignum_init();
165
166
4
  if (key->n == NULL || key->e == NULL || key->d == NULL ||
167
4
      key->p == NULL || key->q == NULL || key->dmp1 == NULL ||
168
4
      key->dmq1 == NULL || key->iqmp == NULL) {
169
0
    crypto_rsa_free(key);
170
0
    return NULL;
171
0
  }
172
173
  /*
174
   * PKCS #1, 7.2:
175
   * RSAPrivateKey ::= SEQUENCE {
176
   *    version Version,
177
   *    modulus INTEGER, -- n
178
   *    publicExponent INTEGER, -- e
179
   *    privateExponent INTEGER, -- d
180
   *    prime1 INTEGER, -- p
181
   *    prime2 INTEGER, -- q
182
   *    exponent1 INTEGER, -- d mod (p-1)
183
   *    exponent2 INTEGER, -- d mod (q-1)
184
   *    coefficient INTEGER -- (inverse of q) mod p
185
   * }
186
   *
187
   * Version ::= INTEGER -- shall be 0 for this version of the standard
188
   */
189
4
  if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
190
2
    asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)");
191
2
    goto error;
192
2
  }
193
2
  pos = hdr.payload;
194
2
  end = pos + hdr.length;
195
196
2
  zero = bignum_init();
197
2
  if (zero == NULL)
198
0
    goto error;
199
2
  pos = crypto_rsa_parse_integer(pos, end, zero);
200
2
  if (pos == NULL || bignum_cmp_d(zero, 0) != 0) {
201
0
    wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the "
202
0
         "beginning of private key; not found");
203
0
    bignum_deinit(zero);
204
0
    goto error;
205
0
  }
206
2
  bignum_deinit(zero);
207
208
2
  pos = crypto_rsa_parse_integer(pos, end, key->n);
209
2
  pos = crypto_rsa_parse_integer(pos, end, key->e);
210
2
  pos = crypto_rsa_parse_integer(pos, end, key->d);
211
2
  pos = crypto_rsa_parse_integer(pos, end, key->p);
212
2
  pos = crypto_rsa_parse_integer(pos, end, key->q);
213
2
  pos = crypto_rsa_parse_integer(pos, end, key->dmp1);
214
2
  pos = crypto_rsa_parse_integer(pos, end, key->dmq1);
215
2
  pos = crypto_rsa_parse_integer(pos, end, key->iqmp);
216
217
2
  if (pos == NULL)
218
0
    goto error;
219
220
2
  if (pos != end) {
221
0
    wpa_hexdump(MSG_DEBUG,
222
0
          "RSA: Extra data in public key SEQUENCE",
223
0
          pos, end - pos);
224
0
    goto error;
225
0
  }
226
227
2
  return key;
228
229
2
error:
230
2
  crypto_rsa_free(key);
231
2
  return NULL;
232
2
}
233
234
235
/**
236
 * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key
237
 * @key: RSA key
238
 * Returns: Modulus length of the key
239
 */
240
size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key)
241
0
{
242
0
  return bignum_get_unsigned_bin_len(key->n);
243
0
}
244
245
246
/**
247
 * crypto_rsa_exptmod - RSA modular exponentiation
248
 * @in: Input data
249
 * @inlen: Input data length
250
 * @out: Buffer for output data
251
 * @outlen: Maximum size of the output buffer and used size on success
252
 * @key: RSA key
253
 * @use_private: 1 = Use RSA private key, 0 = Use RSA public key
254
 * Returns: 0 on success, -1 on failure
255
 */
256
int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen,
257
           struct crypto_rsa_key *key, int use_private)
258
0
{
259
0
  struct bignum *tmp, *a = NULL, *b = NULL;
260
0
  int ret = -1;
261
0
  size_t modlen;
262
263
0
  if (use_private && !key->private_key)
264
0
    return -1;
265
266
0
  tmp = bignum_init();
267
0
  if (tmp == NULL)
268
0
    return -1;
269
270
0
  if (bignum_set_unsigned_bin(tmp, in, inlen) < 0)
271
0
    goto error;
272
0
  if (bignum_cmp(key->n, tmp) < 0) {
273
    /* Too large input value for the RSA key modulus */
274
0
    goto error;
275
0
  }
276
277
0
  if (use_private) {
278
    /*
279
     * Decrypt (or sign) using Chinese remainder theorem to speed
280
     * up calculation. This is equivalent to tmp = tmp^d mod n
281
     * (which would require more CPU to calculate directly).
282
     *
283
     * dmp1 = (1/e) mod (p-1)
284
     * dmq1 = (1/e) mod (q-1)
285
     * iqmp = (1/q) mod p, where p > q
286
     * m1 = c^dmp1 mod p
287
     * m2 = c^dmq1 mod q
288
     * h = q^-1 (m1 - m2) mod p
289
     * m = m2 + hq
290
     */
291
0
    a = bignum_init();
292
0
    b = bignum_init();
293
0
    if (a == NULL || b == NULL)
294
0
      goto error;
295
296
    /* a = tmp^dmp1 mod p */
297
0
    if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0)
298
0
      goto error;
299
300
    /* b = tmp^dmq1 mod q */
301
0
    if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0)
302
0
      goto error;
303
304
    /* tmp = (a - b) * (1/q mod p) (mod p) */
305
0
    if (bignum_sub(a, b, tmp) < 0 ||
306
0
        bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0)
307
0
      goto error;
308
309
    /* tmp = b + q * tmp */
310
0
    if (bignum_mul(tmp, key->q, tmp) < 0 ||
311
0
        bignum_add(tmp, b, tmp) < 0)
312
0
      goto error;
313
0
  } else {
314
    /* Encrypt (or verify signature) */
315
    /* tmp = tmp^e mod N */
316
0
    if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0)
317
0
      goto error;
318
0
  }
319
320
0
  modlen = crypto_rsa_get_modulus_len(key);
321
0
  if (modlen > *outlen) {
322
0
    *outlen = modlen;
323
0
    goto error;
324
0
  }
325
326
0
  if (bignum_get_unsigned_bin_len(tmp) > modlen)
327
0
    goto error; /* should never happen */
328
329
0
  *outlen = modlen;
330
0
  os_memset(out, 0, modlen);
331
0
  if (bignum_get_unsigned_bin(
332
0
        tmp, out +
333
0
        (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0)
334
0
    goto error;
335
336
0
  ret = 0;
337
338
0
error:
339
0
  bignum_deinit(tmp);
340
0
  bignum_deinit(a);
341
0
  bignum_deinit(b);
342
0
  return ret;
343
0
}
344
345
346
/**
347
 * crypto_rsa_free - Free RSA key
348
 * @key: RSA key to be freed
349
 *
350
 * This function frees an RSA key imported with either
351
 * crypto_rsa_import_public_key() or crypto_rsa_import_private_key().
352
 */
353
void crypto_rsa_free(struct crypto_rsa_key *key)
354
8
{
355
8
  if (key) {
356
4
    bignum_deinit(key->n);
357
4
    bignum_deinit(key->e);
358
4
    bignum_deinit(key->d);
359
4
    bignum_deinit(key->p);
360
4
    bignum_deinit(key->q);
361
4
    bignum_deinit(key->dmp1);
362
4
    bignum_deinit(key->dmq1);
363
4
    bignum_deinit(key->iqmp);
364
4
    os_free(key);
365
4
  }
366
8
}