Coverage Report

Created: 2023-09-25 06:08

/src/dropbear/src/signkey.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Dropbear - a SSH2 server
3
 * 
4
 * Copyright (c) 2002,2003 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
#include "includes.h"
26
#include "dbutil.h"
27
#include "signkey.h"
28
#include "buffer.h"
29
#include "ssh.h"
30
#include "ecdsa.h"
31
#include "sk-ecdsa.h"
32
#include "sk-ed25519.h"
33
#include "rsa.h"
34
#include "dss.h"
35
#include "ed25519.h"
36
37
static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
38
#if DROPBEAR_RSA
39
  "ssh-rsa",
40
#endif
41
#if DROPBEAR_DSS
42
  "ssh-dss",
43
#endif
44
#if DROPBEAR_ECDSA
45
  "ecdsa-sha2-nistp256",
46
  "ecdsa-sha2-nistp384",
47
  "ecdsa-sha2-nistp521",
48
#if DROPBEAR_SK_ECDSA
49
  "sk-ecdsa-sha2-nistp256@openssh.com",
50
#endif /* DROPBEAR_SK_ECDSA */
51
#endif /* DROPBEAR_ECDSA */
52
#if DROPBEAR_ED25519
53
  "ssh-ed25519",
54
#if DROPBEAR_SK_ED25519
55
  "sk-ssh-ed25519@openssh.com",
56
#endif /* DROPBEAR_SK_ED25519 */
57
#endif /* DROPBEAR_ED25519 */
58
  /* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
59
};
60
61
/* malloc a new sign_key and set the dss and rsa keys to NULL */
62
2.85k
sign_key * new_sign_key() {
63
64
2.85k
  sign_key * ret;
65
66
2.85k
  ret = (sign_key*)m_malloc(sizeof(sign_key));
67
2.85k
  ret->type = DROPBEAR_SIGNKEY_NONE;
68
2.85k
  ret->source = SIGNKEY_SOURCE_INVALID;
69
2.85k
  return ret;
70
2.85k
}
71
72
/* Returns key name corresponding to the type. Exits fatally
73
 * if the type is invalid */
74
0
const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen) {
75
0
  if (type >= DROPBEAR_SIGNKEY_NUM_NAMED) {
76
0
    dropbear_exit("Bad key type %d", type);
77
0
  }
78
79
0
  if (namelen) {
80
0
    *namelen = strlen(signkey_names[type]);
81
0
  }
82
0
  return signkey_names[type];
83
0
}
84
85
/* Returns DROPBEAR_SIGNKEY_NONE if none match */
86
3.92k
enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) {
87
3.92k
  int i;
88
14.8k
  for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) {
89
14.6k
    const char *fixed_name = signkey_names[i];
90
14.6k
    if (namelen == strlen(fixed_name)
91
14.6k
      && memcmp(fixed_name, name, namelen) == 0) {
92
93
3.69k
#if DROPBEAR_ECDSA
94
      /* Some of the ECDSA key sizes are defined even if they're not compiled in */
95
3.69k
      if (0
96
#if !DROPBEAR_ECC_256
97
        || i == DROPBEAR_SIGNKEY_ECDSA_NISTP256
98
#endif
99
#if !DROPBEAR_ECC_384
100
        || i == DROPBEAR_SIGNKEY_ECDSA_NISTP384
101
#endif
102
#if !DROPBEAR_ECC_521
103
        || i == DROPBEAR_SIGNKEY_ECDSA_NISTP521
104
#endif
105
3.69k
        ) {
106
0
        TRACE(("attempt to use ecdsa type %d not compiled in", i))
107
0
        return DROPBEAR_SIGNKEY_NONE;
108
0
      }
109
3.69k
#endif
110
111
3.69k
      return (enum signkey_type)i;
112
3.69k
    }
113
14.6k
  }
114
115
233
  TRACE(("signkey_type_from_name unexpected key type."))
116
117
233
  return DROPBEAR_SIGNKEY_NONE;
118
3.92k
}
119
120
/* Special case for rsa-sha2-256. This could be generalised if more 
121
   signature names are added that aren't 1-1 with public key names */
122
0
const char* signature_name_from_type(enum signature_type type, unsigned int *namelen) {
123
0
#if DROPBEAR_RSA
124
0
#if DROPBEAR_RSA_SHA256
125
0
  if (type == DROPBEAR_SIGNATURE_RSA_SHA256) {
126
0
    if (namelen) {
127
0
      *namelen = strlen(SSH_SIGNATURE_RSA_SHA256);
128
0
    }
129
0
    return SSH_SIGNATURE_RSA_SHA256;
130
0
  }
131
0
#endif
132
0
#if DROPBEAR_RSA_SHA1
133
0
  if (type == DROPBEAR_SIGNATURE_RSA_SHA1) {
134
0
    if (namelen) {
135
0
      *namelen = strlen(SSH_SIGNKEY_RSA);
136
0
    }
137
0
    return SSH_SIGNKEY_RSA;
138
0
  }
139
0
#endif
140
0
#endif /* DROPBEAR_RSA */
141
0
  return signkey_name_from_type((enum signkey_type)type, namelen);
142
0
}
143
144
/* Returns DROPBEAR_SIGNATURE_NONE if none match */
145
1.67k
enum signature_type signature_type_from_name(const char* name, unsigned int namelen) {
146
1.67k
#if DROPBEAR_RSA
147
1.67k
#if DROPBEAR_RSA_SHA256
148
1.67k
  if (namelen == strlen(SSH_SIGNATURE_RSA_SHA256) 
149
1.67k
    && memcmp(name, SSH_SIGNATURE_RSA_SHA256, namelen) == 0) {
150
8
    return DROPBEAR_SIGNATURE_RSA_SHA256;
151
8
  }
152
1.66k
#endif
153
1.66k
#if DROPBEAR_RSA_SHA1
154
1.66k
  if (namelen == strlen(SSH_SIGNKEY_RSA) 
155
1.66k
    && memcmp(name, SSH_SIGNKEY_RSA, namelen) == 0) {
156
871
    return DROPBEAR_SIGNATURE_RSA_SHA1;
157
871
  }
158
791
#endif
159
791
#endif /* DROPBEAR_RSA */
160
791
  return (enum signature_type)signkey_type_from_name(name, namelen);
161
1.66k
}
162
163
/* Returns the signature type from a key type. Must not be called
164
   with RSA keytype */
165
804
enum signature_type signature_type_from_signkey(enum signkey_type keytype) {
166
804
#if DROPBEAR_RSA
167
804
  assert(keytype != DROPBEAR_SIGNKEY_RSA);
168
804
#endif
169
804
  assert(keytype < DROPBEAR_SIGNKEY_NUM_NAMED);
170
804
  return (enum signature_type)keytype;
171
804
}
172
173
1.58k
enum signkey_type signkey_type_from_signature(enum signature_type sigtype) {
174
1.58k
#if DROPBEAR_RSA
175
1.58k
#if DROPBEAR_RSA_SHA256
176
1.58k
  if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
177
7
    return DROPBEAR_SIGNKEY_RSA;
178
7
  }
179
1.57k
#endif
180
1.57k
#if DROPBEAR_RSA_SHA1
181
1.57k
  if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA1) {
182
869
    return DROPBEAR_SIGNKEY_RSA;
183
869
  }
184
707
#endif
185
707
#endif /* DROPBEAR_RSA */
186
707
  assert((int)sigtype < (int)DROPBEAR_SIGNKEY_NUM_NAMED);
187
707
  return (enum signkey_type)sigtype;
188
707
}
189
190
/* Returns a pointer to the key part specific to "type".
191
Be sure to check both (ret != NULL) and (*ret != NULL) */
192
void **
193
1.14k
signkey_key_ptr(sign_key *key, enum signkey_type type) {
194
1.14k
  switch (type) {
195
0
#if DROPBEAR_ED25519
196
0
    case DROPBEAR_SIGNKEY_ED25519:
197
0
#if DROPBEAR_SK_ED25519
198
117
    case DROPBEAR_SIGNKEY_SK_ED25519:
199
117
#endif
200
117
      return (void**)&key->ed25519key;
201
0
#endif
202
0
#if DROPBEAR_ECDSA
203
0
#if DROPBEAR_ECC_256
204
614
    case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
205
614
#if DROPBEAR_SK_ECDSA
206
709
    case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256:
207
709
#endif
208
709
      return (void**)&key->ecckey256;
209
0
#endif
210
0
#if DROPBEAR_ECC_384
211
147
    case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
212
147
      return (void**)&key->ecckey384;
213
0
#endif
214
0
#if DROPBEAR_ECC_521
215
169
    case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
216
169
      return (void**)&key->ecckey521;
217
0
#endif
218
0
#endif /* DROPBEAR_ECDSA */
219
0
#if DROPBEAR_RSA
220
0
    case DROPBEAR_SIGNKEY_RSA:
221
0
      return (void**)&key->rsakey;
222
0
#endif
223
0
#if DROPBEAR_DSS
224
0
    case DROPBEAR_SIGNKEY_DSS:
225
0
      return (void**)&key->dsskey;
226
0
#endif
227
0
    default:
228
0
      return NULL;
229
1.14k
  }
230
1.14k
}
231
232
/* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail.
233
 * type should be set by the caller to specify the type to read, and
234
 * on return is set to the type read (useful when type = _ANY) */
235
2.85k
int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
236
237
2.85k
  char *ident;
238
2.85k
  unsigned int len;
239
2.85k
  enum signkey_type keytype;
240
2.85k
  int ret = DROPBEAR_FAILURE;
241
242
2.85k
  TRACE2(("enter buf_get_pub_key"))
243
244
2.85k
  ident = buf_getstring(buf, &len);
245
2.85k
  keytype = signkey_type_from_name(ident, len);
246
2.85k
  m_free(ident);
247
248
2.85k
  if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
249
0
    TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, *type))
250
0
    return DROPBEAR_FAILURE;
251
0
  }
252
  
253
2.85k
  TRACE2(("buf_get_pub_key keytype is %d", keytype))
254
255
2.85k
  *type = keytype;
256
257
  /* Rewind the buffer back before "ssh-rsa" etc */
258
2.85k
  buf_decrpos(buf, len + 4);
259
260
2.85k
#if DROPBEAR_DSS
261
2.85k
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
262
351
    dss_key_free(key->dsskey);
263
351
    key->dsskey = m_malloc(sizeof(*key->dsskey));
264
351
    ret = buf_get_dss_pub_key(buf, key->dsskey);
265
351
    if (ret == DROPBEAR_FAILURE) {
266
75
      dss_key_free(key->dsskey);
267
75
      key->dsskey = NULL;
268
75
    }
269
351
  }
270
2.85k
#endif
271
2.85k
#if DROPBEAR_RSA
272
2.85k
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
273
1.18k
    rsa_key_free(key->rsakey);
274
1.18k
    key->rsakey = m_malloc(sizeof(*key->rsakey));
275
1.18k
    ret = buf_get_rsa_pub_key(buf, key->rsakey);
276
1.18k
    if (ret == DROPBEAR_FAILURE) {
277
132
      rsa_key_free(key->rsakey);
278
132
      key->rsakey = NULL;
279
132
    }
280
1.18k
  }
281
2.85k
#endif
282
2.85k
#if DROPBEAR_ECDSA
283
2.85k
  if (signkey_is_ecdsa(keytype)
284
2.85k
#if DROPBEAR_SK_ECDSA
285
2.85k
    || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
286
2.85k
#endif
287
2.85k
  ) {
288
746
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
289
746
    if (eck) {
290
746
      if (*eck) {
291
0
        ecc_free(*eck);
292
0
        m_free(*eck);
293
0
        *eck = NULL;
294
0
      }
295
746
      *eck = buf_get_ecdsa_pub_key(buf);
296
746
      if (*eck) {
297
282
        ret = DROPBEAR_SUCCESS;
298
282
      }
299
746
    }
300
746
  }
301
2.85k
#endif
302
2.85k
#if DROPBEAR_ED25519
303
2.85k
  if (keytype == DROPBEAR_SIGNKEY_ED25519
304
2.85k
#if DROPBEAR_SK_ED25519
305
2.85k
    || keytype == DROPBEAR_SIGNKEY_SK_ED25519
306
2.85k
#endif
307
2.85k
    ) {
308
346
    ed25519_key_free(key->ed25519key);
309
346
    key->ed25519key = m_malloc(sizeof(*key->ed25519key));
310
346
    ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype);
311
346
    if (ret == DROPBEAR_FAILURE) {
312
58
      m_free(key->ed25519key);
313
58
      key->ed25519key = NULL;
314
58
    }
315
346
  }
316
2.85k
#endif
317
318
2.85k
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
319
2.85k
  if (0
320
2.85k
#if DROPBEAR_SK_ED25519
321
2.85k
    || keytype == DROPBEAR_SIGNKEY_SK_ED25519
322
2.85k
#endif
323
2.85k
#if DROPBEAR_SK_ECDSA
324
2.85k
    || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
325
2.85k
#endif
326
2.85k
  ) {
327
215
    key->sk_app = buf_getstring(buf, &key->sk_applen);
328
215
  }
329
2.85k
#endif
330
331
2.85k
  TRACE2(("leave buf_get_pub_key"))
332
333
2.85k
  return ret;
334
2.85k
}
335
336
/* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail.
337
 * type should be set by the caller to specify the type to read, and
338
 * on return is set to the type read (useful when type = _ANY) */
339
0
int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
340
341
0
  char *ident;
342
0
  unsigned int len;
343
0
  enum signkey_type keytype;
344
0
  int ret = DROPBEAR_FAILURE;
345
346
0
  TRACE2(("enter buf_get_priv_key"))
347
348
0
  ident = buf_getstring(buf, &len);
349
0
  keytype = signkey_type_from_name(ident, len);
350
0
  m_free(ident);
351
352
0
  if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
353
0
    TRACE(("wrong key type: %d %d", *type, keytype))
354
0
    return DROPBEAR_FAILURE;
355
0
  }
356
357
0
  *type = keytype;
358
359
  /* Rewind the buffer back before "ssh-rsa" etc */
360
0
  buf_decrpos(buf, len + 4);
361
362
0
#if DROPBEAR_DSS
363
0
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
364
0
    dss_key_free(key->dsskey);
365
0
    key->dsskey = m_malloc(sizeof(*key->dsskey));
366
0
    ret = buf_get_dss_priv_key(buf, key->dsskey);
367
0
    if (ret == DROPBEAR_FAILURE) {
368
0
      dss_key_free(key->dsskey);
369
0
      key->dsskey = NULL;
370
0
    }
371
0
  }
372
0
#endif
373
0
#if DROPBEAR_RSA
374
0
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
375
0
    rsa_key_free(key->rsakey);
376
0
    key->rsakey = m_malloc(sizeof(*key->rsakey));
377
0
    ret = buf_get_rsa_priv_key(buf, key->rsakey);
378
0
    if (ret == DROPBEAR_FAILURE) {
379
0
      rsa_key_free(key->rsakey);
380
0
      key->rsakey = NULL;
381
0
    }
382
0
  }
383
0
#endif
384
0
#if DROPBEAR_ECDSA
385
0
  if (signkey_is_ecdsa(keytype)) {
386
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
387
0
    if (eck) {
388
0
      if (*eck) {
389
0
        ecc_free(*eck);
390
0
        m_free(*eck);
391
0
        *eck = NULL;
392
0
      }
393
0
      *eck = buf_get_ecdsa_priv_key(buf);
394
0
      if (*eck) {
395
0
        ret = DROPBEAR_SUCCESS;
396
0
      }
397
0
    }
398
0
  }
399
0
#endif
400
0
#if DROPBEAR_ED25519
401
0
  if (keytype == DROPBEAR_SIGNKEY_ED25519) {
402
0
    ed25519_key_free(key->ed25519key);
403
0
    key->ed25519key = m_malloc(sizeof(*key->ed25519key));
404
0
    ret = buf_get_ed25519_priv_key(buf, key->ed25519key);
405
0
    if (ret == DROPBEAR_FAILURE) {
406
0
      m_free(key->ed25519key);
407
0
      key->ed25519key = NULL;
408
0
    }
409
0
  }
410
0
#endif
411
412
0
  TRACE2(("leave buf_get_priv_key"))
413
414
0
  return ret;
415
  
416
0
}
417
418
/* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
419
0
void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
420
421
0
  buffer *pubkeys;
422
423
0
  TRACE2(("enter buf_put_pub_key"))
424
0
  pubkeys = buf_new(MAX_PUBKEY_SIZE);
425
  
426
0
#if DROPBEAR_DSS
427
0
  if (type == DROPBEAR_SIGNKEY_DSS) {
428
0
    buf_put_dss_pub_key(pubkeys, key->dsskey);
429
0
  }
430
0
#endif
431
0
#if DROPBEAR_RSA
432
0
  if (type == DROPBEAR_SIGNKEY_RSA) {
433
0
    buf_put_rsa_pub_key(pubkeys, key->rsakey);
434
0
  }
435
0
#endif
436
0
#if DROPBEAR_ECDSA
437
0
  if (signkey_is_ecdsa(type)) {
438
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
439
0
    if (eck && *eck) {
440
0
      buf_put_ecdsa_pub_key(pubkeys, *eck);
441
0
    }
442
0
  }
443
0
#endif
444
0
#if DROPBEAR_ED25519
445
0
  if (type == DROPBEAR_SIGNKEY_ED25519
446
0
#if DROPBEAR_SK_ED25519
447
0
    || type == DROPBEAR_SIGNKEY_SK_ED25519
448
0
#endif
449
0
  ) {
450
0
    buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
451
0
  }
452
0
#endif
453
0
  if (pubkeys->len == 0) {
454
0
    dropbear_exit("Bad key types in buf_put_pub_key");
455
0
  }
456
457
0
  buf_putbufstring(buf, pubkeys);
458
0
  buf_free(pubkeys);
459
0
  TRACE2(("leave buf_put_pub_key"))
460
0
}
461
462
/* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
463
0
void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type) {
464
465
0
  TRACE(("enter buf_put_priv_key"))
466
0
  TRACE(("type is %d", type))
467
468
0
#if DROPBEAR_DSS
469
0
  if (type == DROPBEAR_SIGNKEY_DSS) {
470
0
    buf_put_dss_priv_key(buf, key->dsskey);
471
0
    TRACE(("leave buf_put_priv_key: dss done"))
472
0
    return;
473
0
  }
474
0
#endif
475
0
#if DROPBEAR_RSA
476
0
  if (type == DROPBEAR_SIGNKEY_RSA) {
477
0
    buf_put_rsa_priv_key(buf, key->rsakey);
478
0
    TRACE(("leave buf_put_priv_key: rsa done"))
479
0
    return;
480
0
  }
481
0
#endif
482
0
#if DROPBEAR_ECDSA
483
0
  if (signkey_is_ecdsa(type)) {
484
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
485
0
    if (eck && *eck) {
486
0
      buf_put_ecdsa_priv_key(buf, *eck);
487
0
      TRACE(("leave buf_put_priv_key: ecdsa done"))
488
0
      return;
489
0
    }
490
0
  }
491
0
#endif
492
0
#if DROPBEAR_ED25519
493
0
  if (type == DROPBEAR_SIGNKEY_ED25519) {
494
0
    buf_put_ed25519_priv_key(buf, key->ed25519key);
495
0
    TRACE(("leave buf_put_priv_key: ed25519 done"))
496
0
    return;
497
0
  }
498
0
#endif
499
0
  dropbear_exit("Bad key types in put pub key");
500
0
}
501
502
2.29k
void sign_key_free(sign_key *key) {
503
504
2.29k
  TRACE2(("enter sign_key_free"))
505
506
2.29k
#if DROPBEAR_DSS
507
2.29k
  dss_key_free(key->dsskey);
508
2.29k
  key->dsskey = NULL;
509
2.29k
#endif
510
2.29k
#if DROPBEAR_RSA
511
2.29k
  rsa_key_free(key->rsakey);
512
2.29k
  key->rsakey = NULL;
513
2.29k
#endif
514
2.29k
#if DROPBEAR_ECDSA
515
2.29k
#if DROPBEAR_ECC_256
516
2.29k
  if (key->ecckey256) {
517
176
    ecc_free(key->ecckey256);
518
176
    m_free(key->ecckey256);
519
176
    key->ecckey256 = NULL;
520
176
  }
521
2.29k
#endif
522
2.29k
#if DROPBEAR_ECC_384
523
2.29k
  if (key->ecckey384) {
524
45
    ecc_free(key->ecckey384);
525
45
    m_free(key->ecckey384);
526
45
    key->ecckey384 = NULL;
527
45
  }
528
2.29k
#endif
529
2.29k
#if DROPBEAR_ECC_521
530
2.29k
  if (key->ecckey521) {
531
54
    ecc_free(key->ecckey521);
532
54
    m_free(key->ecckey521);
533
54
    key->ecckey521 = NULL;
534
54
  }
535
2.29k
#endif
536
2.29k
#endif
537
2.29k
#if DROPBEAR_ED25519
538
2.29k
  ed25519_key_free(key->ed25519key);
539
2.29k
  key->ed25519key = NULL;
540
2.29k
#endif
541
542
2.29k
  m_free(key->filename);
543
2.29k
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
544
2.29k
  if (key->sk_app) {
545
121
    m_free(key->sk_app);
546
121
  }
547
2.29k
#endif
548
549
2.29k
  m_free(key);
550
2.29k
  TRACE2(("leave sign_key_free"))
551
2.29k
}
552
553
static char * sign_key_sha256_fingerprint(const unsigned char* keyblob,
554
0
    unsigned int keybloblen) {
555
556
0
  char * ret;
557
0
  hash_state hs;
558
0
  unsigned char hash[SHA256_HASH_SIZE];
559
0
  unsigned int b64chars, start;
560
0
  unsigned long b64size;
561
0
  const char *prefix = "SHA256:";
562
0
  int err;
563
564
0
  sha256_init(&hs);
565
0
  sha256_process(&hs, keyblob, keybloblen);
566
0
  sha256_done(&hs, hash);
567
568
  /* eg "SHA256:P9szN0L2ls6KxkVv7Bppv3asnZCn03rY7Msm/c8+ZgA"
569
   * 256/6 = 42.66 => 43 base64 chars. OpenSSH discards
570
   * base64 padding output. */
571
0
  start = strlen(prefix);
572
0
  b64chars = 43;
573
  /* space for discarded b64 padding and null terminator */
574
0
  b64size = b64chars + 4;
575
0
  ret = m_malloc(start + b64size);
576
577
0
  memcpy(ret, prefix, start);
578
0
  err = base64_encode(hash, SHA256_HASH_SIZE, &ret[start], &b64size);
579
0
  if (err != CRYPT_OK) {
580
0
    dropbear_exit("base64 failed");
581
0
  }
582
0
  ret[start + b64chars] = '\0';
583
0
  return ret;
584
0
}
585
586
/* This will return a freshly malloced string */
587
0
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen) {
588
0
  return sign_key_sha256_fingerprint(keyblob, keybloblen);
589
0
}
590
591
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, 
592
0
  const buffer *data_buf) {
593
0
  buffer *sigblob = buf_new(MAX_PUBKEY_SIZE);
594
0
  enum signkey_type keytype = signkey_type_from_signature(sigtype);
595
596
#if DEBUG_TRACE > DROPBEAR_VERBOSE_LEVEL
597
  {
598
    const char* signame = signature_name_from_type(sigtype, NULL);
599
    TRACE(("buf_put_sign type %d %s", sigtype, signame));
600
  }
601
#endif
602
603
604
0
#if DROPBEAR_DSS
605
0
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
606
0
    buf_put_dss_sign(sigblob, key->dsskey, data_buf);
607
0
  }
608
0
#endif
609
0
#if DROPBEAR_RSA
610
0
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
611
0
    buf_put_rsa_sign(sigblob, key->rsakey, sigtype, data_buf);
612
0
  }
613
0
#endif
614
0
#if DROPBEAR_ECDSA
615
0
  if (signkey_is_ecdsa(keytype)) {
616
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
617
0
    if (eck && *eck) {
618
0
      buf_put_ecdsa_sign(sigblob, *eck, data_buf);
619
0
    }
620
0
  }
621
0
#endif
622
0
#if DROPBEAR_ED25519
623
0
  if (keytype == DROPBEAR_SIGNKEY_ED25519) {
624
0
    buf_put_ed25519_sign(sigblob, key->ed25519key, data_buf);
625
0
  }
626
0
#endif
627
0
  if (sigblob->len == 0) {
628
0
    dropbear_exit("Non-matching signing type");
629
0
  }
630
0
  buf_putbufstring(buf, sigblob);
631
0
  buf_free(sigblob);
632
633
0
}
634
635
#if DROPBEAR_SIGNKEY_VERIFY
636
637
/* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
638
 * If FAILURE is returned, the position of
639
 * buf is undefined. If SUCCESS is returned, buf will be positioned after the
640
 * signature blob */
641
1.69k
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) {
642
  
643
1.69k
  char *type_name = NULL;
644
1.69k
  unsigned int type_name_len = 0;
645
1.69k
  enum signature_type sigtype;
646
1.69k
  enum signkey_type keytype;
647
648
1.69k
  TRACE(("enter buf_verify"))
649
650
1.69k
  buf_getint(buf); /* blob length */
651
1.69k
  type_name = buf_getstring(buf, &type_name_len);
652
1.69k
  sigtype = signature_type_from_name(type_name, type_name_len);
653
1.69k
  m_free(type_name);
654
655
1.69k
  if (expect_sigtype != sigtype) {
656
87
      dropbear_exit("Non-matching signing type");
657
87
  }
658
659
1.61k
  keytype = signkey_type_from_signature(sigtype);
660
1.61k
#if DROPBEAR_DSS
661
1.61k
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
662
239
    if (key->dsskey == NULL) {
663
0
      dropbear_exit("No DSS key to verify signature");
664
0
    }
665
239
    return buf_dss_verify(buf, key->dsskey, data_buf);
666
239
  }
667
1.37k
#endif
668
669
1.37k
#if DROPBEAR_RSA
670
1.37k
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
671
876
    if (key->rsakey == NULL) {
672
0
      dropbear_exit("No RSA key to verify signature");
673
0
    }
674
876
    return buf_rsa_verify(buf, key->rsakey, sigtype, data_buf);
675
876
  }
676
496
#endif
677
496
#if DROPBEAR_ECDSA
678
496
  if (signkey_is_ecdsa(keytype)) {
679
279
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
680
279
    if (eck && *eck) {
681
279
      return buf_ecdsa_verify(buf, *eck, data_buf);
682
279
    }
683
279
  }
684
217
#endif
685
217
#if DROPBEAR_ED25519
686
217
  if (keytype == DROPBEAR_SIGNKEY_ED25519) {
687
74
    if (key->ed25519key == NULL) {
688
0
      dropbear_exit("No Ed25519 key to verify signature");
689
0
    }
690
74
    return buf_ed25519_verify(buf, key->ed25519key, data_buf);
691
74
  }
692
143
#endif
693
143
#if DROPBEAR_SK_ECDSA
694
143
  if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) {
695
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
696
0
    if (eck && *eck) {
697
0
      return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen, key->sk_flags_mask);
698
0
    }
699
0
  }
700
143
#endif
701
143
#if DROPBEAR_SK_ED25519
702
143
  if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
703
115
    dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
704
115
    if (eck && *eck) {
705
115
      return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen, key->sk_flags_mask);
706
115
    }
707
115
  }
708
28
#endif
709
710
28
  dropbear_exit("Non-matching signing type");
711
0
  return DROPBEAR_FAILURE;
712
143
}
713
#endif /* DROPBEAR_SIGNKEY_VERIFY */
714
715
#if DROPBEAR_KEY_LINES /* ie we're using authorized_keys or known_hosts */
716
717
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE when given a buffer containing
718
 * a key, a key, and a type. The buffer is positioned at the start of the
719
 * base64 data, and contains no trailing data */
720
/* If fingerprint is non-NULL, it will be set to a malloc()ed fingerprint
721
   of the key if it is successfully decoded */
722
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen, 
723
          const unsigned char* algoname, unsigned int algolen, 
724
0
          const buffer * line, char ** fingerprint) {
725
726
0
  buffer * decodekey = NULL;
727
0
  int ret = DROPBEAR_FAILURE;
728
0
  unsigned int len, filealgolen;
729
0
  unsigned long decodekeylen;
730
0
  unsigned char* filealgo = NULL;
731
732
  /* now we have the actual data */
733
0
  len = line->len - line->pos;
734
0
  if (len == 0) {
735
    /* base64_decode doesn't like NULL argument */
736
0
    return DROPBEAR_FAILURE;
737
0
  }
738
0
  decodekeylen = len * 2; /* big to be safe */
739
0
  decodekey = buf_new(decodekeylen);
740
741
0
  if (base64_decode(buf_getptr(line, len), len,
742
0
        buf_getwriteptr(decodekey, decodekey->size),
743
0
        &decodekeylen) != CRYPT_OK) {
744
0
    TRACE(("checkpubkey: base64 decode failed"))
745
0
    goto out;
746
0
  }
747
0
  TRACE(("checkpubkey: base64_decode success"))
748
0
  buf_incrlen(decodekey, decodekeylen);
749
  
750
0
  if (fingerprint) {
751
0
    *fingerprint = sign_key_fingerprint(buf_getptr(decodekey, decodekeylen),
752
0
                      decodekeylen);
753
0
  }
754
  
755
  /* compare the keys */
756
0
  if ( ( decodekeylen != keybloblen )
757
0
      || memcmp( buf_getptr(decodekey, decodekey->len),
758
0
            keyblob, decodekey->len) != 0) {
759
0
    TRACE(("checkpubkey: compare failed"))
760
0
    goto out;
761
0
  }
762
763
  /* ... and also check that the algo specified and the algo in the key
764
   * itself match */
765
0
  filealgolen = buf_getint(decodekey);
766
0
  filealgo = buf_getptr(decodekey, filealgolen);
767
0
  if (filealgolen != algolen || memcmp(filealgo, algoname, algolen) != 0) {
768
0
    TRACE(("checkpubkey: algo match failed")) 
769
0
    goto out;
770
0
  }
771
772
  /* All checks passed */
773
0
  ret = DROPBEAR_SUCCESS;
774
775
0
out:
776
0
  buf_free(decodekey);
777
0
  decodekey = NULL;
778
0
  return ret;
779
0
}
780
#endif
781
782
#if DROPBEAR_FUZZ
783
const char * const * fuzz_signkey_names = signkey_names;
784
785
#endif