Coverage Report

Created: 2023-03-20 06:28

/src/dropbear/src/ecdsa.c
Line
Count
Source (jump to first uncovered line)
1
#include "includes.h"
2
#include "dbutil.h"
3
#include "crypto_desc.h"
4
#include "ecc.h"
5
#include "ecdsa.h"
6
#include "signkey.h"
7
8
#if DROPBEAR_ECDSA
9
10
int signkey_is_ecdsa(enum signkey_type type)
11
196
{
12
196
  return type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
13
196
    || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
14
196
    || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
15
196
}
16
17
0
enum signkey_type ecdsa_signkey_type(const ecc_key * key) {
18
0
#if DROPBEAR_ECC_256
19
0
  if (key->dp == ecc_curve_nistp256.dp) {
20
0
    return DROPBEAR_SIGNKEY_ECDSA_NISTP256;
21
0
  }
22
0
#endif
23
0
#if DROPBEAR_ECC_384
24
0
  if (key->dp == ecc_curve_nistp384.dp) {
25
0
    return DROPBEAR_SIGNKEY_ECDSA_NISTP384;
26
0
  }
27
0
#endif
28
0
#if DROPBEAR_ECC_521
29
0
  if (key->dp == ecc_curve_nistp521.dp) {
30
0
    return DROPBEAR_SIGNKEY_ECDSA_NISTP521;
31
0
  }
32
0
#endif
33
0
  return DROPBEAR_SIGNKEY_NONE;
34
0
}
35
36
0
ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) {
37
0
  const ltc_ecc_set_type *dp = NULL; /* curve domain parameters */
38
0
  ecc_key *new_key = NULL;
39
0
  switch (bit_size) {
40
0
#if DROPBEAR_ECC_256
41
0
    case 256:
42
0
      dp = ecc_curve_nistp256.dp;
43
0
      break;
44
0
#endif
45
0
#if DROPBEAR_ECC_384
46
0
    case 384:
47
0
      dp = ecc_curve_nistp384.dp;
48
0
      break;
49
0
#endif
50
0
#if DROPBEAR_ECC_521
51
0
    case 521:
52
0
      dp = ecc_curve_nistp521.dp;
53
0
      break;
54
0
#endif
55
0
  }
56
0
  if (!dp) {
57
0
    dropbear_exit("Key size %d isn't valid. Try "
58
0
#if DROPBEAR_ECC_256
59
0
      "256 "
60
0
#endif
61
0
#if DROPBEAR_ECC_384
62
0
      "384 "
63
0
#endif
64
0
#if DROPBEAR_ECC_521
65
0
      "521 "
66
0
#endif
67
0
      , bit_size);
68
0
  }
69
70
0
  new_key = m_malloc(sizeof(*new_key));
71
0
  if (ecc_make_key_ex(NULL, dropbear_ltc_prng, new_key, dp) != CRYPT_OK) {
72
0
    dropbear_exit("ECC error");
73
0
  }
74
0
  return new_key;
75
0
}
76
77
2
ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
78
2
  unsigned char *key_ident = NULL, *identifier = NULL;
79
2
  unsigned int key_ident_len, identifier_len;
80
2
  buffer *q_buf = NULL;
81
2
  struct dropbear_ecc_curve **curve;
82
2
  ecc_key *new_key = NULL;
83
84
  /* string   "ecdsa-sha2-[identifier]" or "sk-ecdsa-sha2-nistp256@openssh.com" */
85
2
  key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
86
  /* string   "[identifier]" */
87
2
  identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
88
89
2
  if (strcmp (key_ident, "sk-ecdsa-sha2-nistp256@openssh.com") == 0) {
90
0
    if (strcmp (identifier, "nistp256") != 0) {
91
0
      TRACE(("mismatching identifiers"))
92
0
      goto out;
93
0
    }
94
2
  } else {
95
2
    if (key_ident_len != identifier_len + strlen ("ecdsa-sha2-")) {
96
0
      TRACE(("Bad identifier lengths"))
97
0
      goto out;
98
0
    }
99
2
    if (memcmp(&key_ident[strlen ("ecdsa-sha2-")], identifier, identifier_len) != 0) {
100
0
      TRACE(("mismatching identifiers"))
101
0
      goto out;
102
0
    }
103
2
  }
104
105
2
  for (curve = dropbear_ecc_curves; *curve; curve++) {
106
2
    if (memcmp(identifier, (char*)(*curve)->name, strlen((char*)(*curve)->name)) == 0) {
107
2
      break;
108
2
    }
109
2
  }
110
2
  if (!*curve) {
111
0
    TRACE(("couldn't match ecc curve"))
112
0
    goto out;
113
0
  }
114
115
  /* string Q */
116
2
  q_buf = buf_getstringbuf(buf);
117
2
  new_key = buf_get_ecc_raw_pubkey(q_buf, *curve);
118
119
2
out:
120
2
  m_free(key_ident);
121
2
  m_free(identifier);
122
2
  if (q_buf) {
123
2
    buf_free(q_buf);
124
2
    q_buf = NULL;
125
2
  }
126
2
  TRACE(("leave buf_get_ecdsa_pub_key"))  
127
2
  return new_key;
128
2
}
129
130
2
ecc_key *buf_get_ecdsa_priv_key(buffer *buf) {
131
2
  ecc_key *new_key = NULL;
132
2
  TRACE(("enter buf_get_ecdsa_priv_key"))
133
2
  new_key = buf_get_ecdsa_pub_key(buf);
134
2
  if (!new_key) {
135
0
    return NULL;
136
0
  }
137
138
2
  if (buf_getmpint(buf, new_key->k) != DROPBEAR_SUCCESS) {
139
0
    ecc_free(new_key);
140
0
    m_free(new_key);
141
0
    return NULL;
142
0
  }
143
144
2
  return new_key;
145
2
}
146
147
188
void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key) {
148
188
  struct dropbear_ecc_curve *curve = NULL;
149
188
  char key_ident[30];
150
151
188
  curve = curve_for_dp(key->dp);
152
188
  snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
153
188
  buf_putstring(buf, key_ident, strlen(key_ident));
154
188
  buf_putstring(buf, curve->name, strlen(curve->name));
155
188
  buf_put_ecc_raw_pubkey_string(buf, key);
156
188
}
157
158
0
void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
159
0
  buf_put_ecdsa_pub_key(buf, key);
160
0
  buf_putmpint(buf, key->k);
161
0
}
162
163
0
void buf_put_ecdsa_sign(buffer *buf, const ecc_key *key, const buffer *data_buf) {
164
  /* Based on libtomcrypt's ecc_sign_hash but without the asn1 */
165
0
  int err = DROPBEAR_FAILURE;
166
0
  struct dropbear_ecc_curve *curve = NULL;
167
0
  hash_state hs;
168
0
  unsigned char hash[64];
169
0
  void *e = NULL, *p = NULL, *s = NULL, *r;
170
0
  char key_ident[30];
171
0
  buffer *sigbuf = NULL;
172
173
0
  TRACE(("buf_put_ecdsa_sign"))
174
0
  curve = curve_for_dp(key->dp);
175
176
0
  if (ltc_init_multi(&r, &s, &p, &e, NULL) != CRYPT_OK) { 
177
0
    goto out;
178
0
  }
179
180
0
  curve->hash_desc->init(&hs);
181
0
  curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
182
0
  curve->hash_desc->done(&hs, hash);
183
184
0
  if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
185
0
    goto out;
186
0
  }
187
188
0
  if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) { 
189
0
    goto out; 
190
0
  }
191
192
0
  for (;;) {
193
0
    ecc_key R_key; /* ephemeral key */
194
0
    if (ecc_make_key_ex(NULL, dropbear_ltc_prng, &R_key, key->dp) != CRYPT_OK) {
195
0
      goto out;
196
0
    }
197
0
    if (ltc_mp.mpdiv(R_key.pubkey.x, p, NULL, r) != CRYPT_OK) {
198
0
      goto out;
199
0
    }
200
0
    if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ) {
201
      /* try again */
202
0
      ecc_free(&R_key);
203
0
      continue;
204
0
    }
205
    /* k = 1/k */
206
0
    if (ltc_mp.invmod(R_key.k, p, R_key.k) != CRYPT_OK) {
207
0
      goto out;
208
0
    }
209
    /* s = xr */
210
0
    if (ltc_mp.mulmod(key->k, r, p, s) != CRYPT_OK) {
211
0
      goto out;
212
0
    }
213
    /* s = e +  xr */
214
0
    if (ltc_mp.add(e, s, s) != CRYPT_OK) {
215
0
      goto out;
216
0
    }
217
0
    if (ltc_mp.mpdiv(s, p, NULL, s) != CRYPT_OK) {
218
0
      goto out;
219
0
    }
220
    /* s = (e + xr)/k */
221
0
    if (ltc_mp.mulmod(s, R_key.k, p, s) != CRYPT_OK) {
222
0
      goto out;
223
0
    }
224
0
    ecc_free(&R_key);
225
226
0
    if (ltc_mp.compare_d(s, 0) != LTC_MP_EQ) {
227
0
      break;
228
0
    }
229
0
  }
230
231
0
  snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
232
0
  buf_putstring(buf, key_ident, strlen(key_ident));
233
  /* enough for nistp521 */
234
0
  sigbuf = buf_new(200);
235
0
  buf_putmpint(sigbuf, (mp_int*)r);
236
0
  buf_putmpint(sigbuf, (mp_int*)s);
237
0
  buf_putbufstring(buf, sigbuf);
238
239
0
  err = DROPBEAR_SUCCESS;
240
241
0
out:
242
0
  if (r && s && p && e) {
243
0
    ltc_deinit_multi(r, s, p, e, NULL);
244
0
  }
245
246
0
  if (sigbuf) {
247
0
    buf_free(sigbuf);
248
0
  }
249
250
0
  if (err == DROPBEAR_FAILURE) {
251
0
    dropbear_exit("ECC error");
252
0
  }
253
0
}
254
255
/* returns values in s and r
256
   returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
257
static int buf_get_ecdsa_verify_params(buffer *buf,
258
0
      void *r, void* s) {
259
0
  int ret = DROPBEAR_FAILURE;
260
0
  unsigned int sig_len;
261
0
  unsigned int sig_pos;
262
263
0
  sig_len = buf_getint(buf);
264
0
  sig_pos = buf->pos;
265
0
  if (buf_getmpint(buf, r) != DROPBEAR_SUCCESS) {
266
0
    goto out;
267
0
  }
268
0
  if (buf_getmpint(buf, s) != DROPBEAR_SUCCESS) {
269
0
    goto out;
270
0
  }
271
0
  if (buf->pos - sig_pos != sig_len) {
272
0
    goto out;
273
0
  }
274
0
  ret = DROPBEAR_SUCCESS;
275
276
0
out:
277
0
  return ret;
278
0
}
279
280
281
0
int buf_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf) {
282
  /* Based on libtomcrypt's ecc_verify_hash but without the asn1 */
283
0
  int ret = DROPBEAR_FAILURE;
284
0
  hash_state hs;
285
0
  struct dropbear_ecc_curve *curve = NULL;
286
0
  unsigned char hash[64];
287
0
  ecc_point *mG = NULL, *mQ = NULL;
288
0
  void *r = NULL, *s = NULL, *v = NULL, *w = NULL, *u1 = NULL, *u2 = NULL, 
289
0
    *e = NULL, *p = NULL, *m = NULL;
290
0
  void *mp = NULL;
291
292
  /* verify 
293
   *
294
   * w  = s^-1 mod n
295
   * u1 = xw 
296
   * u2 = rw
297
   * X = u1*G + u2*Q
298
   * v = X_x1 mod n
299
   * accept if v == r
300
   */
301
302
0
  TRACE(("buf_ecdsa_verify"))
303
0
  curve = curve_for_dp(key->dp);
304
305
0
  mG = ltc_ecc_new_point();
306
0
  mQ = ltc_ecc_new_point();
307
0
  if (ltc_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL) != CRYPT_OK
308
0
    || !mG
309
0
    || !mQ) {
310
0
    dropbear_exit("ECC error");
311
0
  }
312
313
0
  if (buf_get_ecdsa_verify_params(buf, r, s) != DROPBEAR_SUCCESS) {
314
0
    goto out;
315
0
  }
316
317
0
  curve->hash_desc->init(&hs);
318
0
  curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
319
0
  curve->hash_desc->done(&hs, hash);
320
321
0
  if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
322
0
    goto out;
323
0
  }
324
325
   /* get the order */
326
0
  if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) { 
327
0
    goto out; 
328
0
  }
329
330
   /* get the modulus */
331
0
  if (ltc_mp.read_radix(m, (char *)key->dp->prime, 16) != CRYPT_OK) { 
332
0
    goto out; 
333
0
  }
334
335
   /* check for zero */
336
0
  if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ 
337
0
    || ltc_mp.compare_d(s, 0) == LTC_MP_EQ 
338
0
    || ltc_mp.compare(r, p) != LTC_MP_LT 
339
0
    || ltc_mp.compare(s, p) != LTC_MP_LT) {
340
0
    goto out;
341
0
  }
342
343
   /*  w  = s^-1 mod n */
344
0
  if (ltc_mp.invmod(s, p, w) != CRYPT_OK) { 
345
0
    goto out; 
346
0
  }
347
348
   /* u1 = ew */
349
0
  if (ltc_mp.mulmod(e, w, p, u1) != CRYPT_OK) { 
350
0
    goto out; 
351
0
  }
352
353
   /* u2 = rw */
354
0
  if (ltc_mp.mulmod(r, w, p, u2) != CRYPT_OK) { 
355
0
    goto out; 
356
0
  }
357
358
   /* find mG and mQ */
359
0
  if (ltc_mp.read_radix(mG->x, (char *)key->dp->Gx, 16) != CRYPT_OK) { 
360
0
    goto out; 
361
0
  }
362
0
  if (ltc_mp.read_radix(mG->y, (char *)key->dp->Gy, 16) != CRYPT_OK) { 
363
0
    goto out; 
364
0
  }
365
0
  if (ltc_mp.set_int(mG->z, 1) != CRYPT_OK) { 
366
0
    goto out; 
367
0
  }
368
369
0
  if (ltc_mp.copy(key->pubkey.x, mQ->x) != CRYPT_OK
370
0
    || ltc_mp.copy(key->pubkey.y, mQ->y) != CRYPT_OK
371
0
    || ltc_mp.copy(key->pubkey.z, mQ->z) != CRYPT_OK) { 
372
0
    goto out; 
373
0
  }
374
375
   /* compute u1*mG + u2*mQ = mG */
376
0
  if (ltc_mp.ecc_mul2add == NULL) {
377
0
    if (ltc_mp.ecc_ptmul(u1, mG, mG, m, 0) != CRYPT_OK) { 
378
0
      goto out; 
379
0
    }
380
0
    if (ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0) != CRYPT_OK) {
381
0
      goto out; 
382
0
    }
383
384
    /* find the montgomery mp */
385
0
    if (ltc_mp.montgomery_setup(m, &mp) != CRYPT_OK) { 
386
0
      goto out; 
387
0
    }
388
389
    /* add them */
390
0
    if (ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp) != CRYPT_OK) { 
391
0
      goto out; 
392
0
    }
393
394
    /* reduce */
395
0
    if (ltc_mp.ecc_map(mG, m, mp) != CRYPT_OK) { 
396
0
      goto out; 
397
0
    }
398
0
  } else {
399
    /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
400
0
    if (ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m) != CRYPT_OK) { 
401
0
      goto out; 
402
0
    }
403
0
  }
404
405
   /* v = X_x1 mod n */
406
0
  if (ltc_mp.mpdiv(mG->x, p, NULL, v) != CRYPT_OK) { 
407
0
    goto out; 
408
0
  }
409
410
   /* does v == r */
411
0
  if (ltc_mp.compare(v, r) == LTC_MP_EQ) {
412
0
    ret = DROPBEAR_SUCCESS;
413
0
  }
414
415
0
out:
416
0
  ltc_ecc_del_point(mG);
417
0
  ltc_ecc_del_point(mQ);
418
0
  ltc_deinit_multi(r, s, v, w, u1, u2, p, e, m, NULL);
419
0
  if (mp != NULL) { 
420
0
    ltc_mp.montgomery_deinit(mp);
421
0
  }
422
0
  return ret;
423
0
}
424
425
426
427
#endif /* DROPBEAR_ECDSA */