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
sign_key * new_sign_key() {
63
64
2
  sign_key * ret;
65
66
2
  ret = (sign_key*)m_malloc(sizeof(sign_key));
67
2
  ret->type = DROPBEAR_SIGNKEY_NONE;
68
2
  ret->source = SIGNKEY_SOURCE_INVALID;
69
2
  return ret;
70
2
}
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
8
enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) {
87
8
  int i;
88
26
  for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) {
89
26
    const char *fixed_name = signkey_names[i];
90
26
    if (namelen == strlen(fixed_name)
91
26
      && memcmp(fixed_name, name, namelen) == 0) {
92
93
8
#if DROPBEAR_ECDSA
94
      /* Some of the ECDSA key sizes are defined even if they're not compiled in */
95
8
      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
8
        ) {
106
0
        TRACE(("attempt to use ecdsa type %d not compiled in", i))
107
0
        return DROPBEAR_SIGNKEY_NONE;
108
0
      }
109
8
#endif
110
111
8
      return (enum signkey_type)i;
112
8
    }
113
26
  }
114
115
0
  TRACE(("signkey_type_from_name unexpected key type."))
116
117
0
  return DROPBEAR_SIGNKEY_NONE;
118
8
}
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
0
enum signature_type signature_type_from_name(const char* name, unsigned int namelen) {
146
0
#if DROPBEAR_RSA
147
0
#if DROPBEAR_RSA_SHA256
148
0
  if (namelen == strlen(SSH_SIGNATURE_RSA_SHA256) 
149
0
    && memcmp(name, SSH_SIGNATURE_RSA_SHA256, namelen) == 0) {
150
0
    return DROPBEAR_SIGNATURE_RSA_SHA256;
151
0
  }
152
0
#endif
153
0
#if DROPBEAR_RSA_SHA1
154
0
  if (namelen == strlen(SSH_SIGNKEY_RSA) 
155
0
    && memcmp(name, SSH_SIGNKEY_RSA, namelen) == 0) {
156
0
    return DROPBEAR_SIGNATURE_RSA_SHA1;
157
0
  }
158
0
#endif
159
0
#endif /* DROPBEAR_RSA */
160
0
  return (enum signature_type)signkey_type_from_name(name, namelen);
161
0
}
162
163
/* Returns the signature type from a key type. Must not be called
164
   with RSA keytype */
165
0
enum signature_type signature_type_from_signkey(enum signkey_type keytype) {
166
0
#if DROPBEAR_RSA
167
0
  assert(keytype != DROPBEAR_SIGNKEY_RSA);
168
0
#endif
169
0
  assert(keytype < DROPBEAR_SIGNKEY_NUM_NAMED);
170
0
  return (enum signature_type)keytype;
171
0
}
172
173
0
enum signkey_type signkey_type_from_signature(enum signature_type sigtype) {
174
0
#if DROPBEAR_RSA
175
0
#if DROPBEAR_RSA_SHA256
176
0
  if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
177
0
    return DROPBEAR_SIGNKEY_RSA;
178
0
  }
179
0
#endif
180
0
#if DROPBEAR_RSA_SHA1
181
0
  if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA1) {
182
0
    return DROPBEAR_SIGNKEY_RSA;
183
0
  }
184
0
#endif
185
0
#endif /* DROPBEAR_RSA */
186
0
  assert((int)sigtype < (int)DROPBEAR_SIGNKEY_NUM_NAMED);
187
0
  return (enum signkey_type)sigtype;
188
0
}
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
180
signkey_key_ptr(sign_key *key, enum signkey_type type) {
194
180
  switch (type) {
195
0
#if DROPBEAR_ED25519
196
0
    case DROPBEAR_SIGNKEY_ED25519:
197
0
#if DROPBEAR_SK_ED25519
198
0
    case DROPBEAR_SIGNKEY_SK_ED25519:
199
0
#endif
200
0
      return (void**)&key->ed25519key;
201
0
#endif
202
0
#if DROPBEAR_ECDSA
203
0
#if DROPBEAR_ECC_256
204
180
    case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
205
180
#if DROPBEAR_SK_ECDSA
206
180
    case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256:
207
180
#endif
208
180
      return (void**)&key->ecckey256;
209
0
#endif
210
0
#if DROPBEAR_ECC_384
211
0
    case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
212
0
      return (void**)&key->ecckey384;
213
0
#endif
214
0
#if DROPBEAR_ECC_521
215
0
    case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
216
0
      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
180
  }
230
180
}
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
0
int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
236
237
0
  char *ident;
238
0
  unsigned int len;
239
0
  enum signkey_type keytype;
240
0
  int ret = DROPBEAR_FAILURE;
241
242
0
  TRACE2(("enter buf_get_pub_key"))
243
244
0
  ident = buf_getstring(buf, &len);
245
0
  keytype = signkey_type_from_name(ident, len);
246
0
  m_free(ident);
247
248
0
  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
0
  TRACE2(("buf_get_pub_key keytype is %d", keytype))
254
255
0
  *type = keytype;
256
257
  /* Rewind the buffer back before "ssh-rsa" etc */
258
0
  buf_decrpos(buf, len + 4);
259
260
0
#if DROPBEAR_DSS
261
0
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
262
0
    dss_key_free(key->dsskey);
263
0
    key->dsskey = m_malloc(sizeof(*key->dsskey));
264
0
    ret = buf_get_dss_pub_key(buf, key->dsskey);
265
0
    if (ret == DROPBEAR_FAILURE) {
266
0
      dss_key_free(key->dsskey);
267
0
      key->dsskey = NULL;
268
0
    }
269
0
  }
270
0
#endif
271
0
#if DROPBEAR_RSA
272
0
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
273
0
    rsa_key_free(key->rsakey);
274
0
    key->rsakey = m_malloc(sizeof(*key->rsakey));
275
0
    ret = buf_get_rsa_pub_key(buf, key->rsakey);
276
0
    if (ret == DROPBEAR_FAILURE) {
277
0
      rsa_key_free(key->rsakey);
278
0
      key->rsakey = NULL;
279
0
    }
280
0
  }
281
0
#endif
282
0
#if DROPBEAR_ECDSA
283
0
  if (signkey_is_ecdsa(keytype)
284
0
#if DROPBEAR_SK_ECDSA
285
0
    || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
286
0
#endif
287
0
  ) {
288
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
289
0
    if (eck) {
290
0
      if (*eck) {
291
0
        ecc_free(*eck);
292
0
        m_free(*eck);
293
0
        *eck = NULL;
294
0
      }
295
0
      *eck = buf_get_ecdsa_pub_key(buf);
296
0
      if (*eck) {
297
0
        ret = DROPBEAR_SUCCESS;
298
0
      }
299
0
    }
300
0
  }
301
0
#endif
302
0
#if DROPBEAR_ED25519
303
0
  if (keytype == DROPBEAR_SIGNKEY_ED25519
304
0
#if DROPBEAR_SK_ED25519
305
0
    || keytype == DROPBEAR_SIGNKEY_SK_ED25519
306
0
#endif
307
0
    ) {
308
0
    ed25519_key_free(key->ed25519key);
309
0
    key->ed25519key = m_malloc(sizeof(*key->ed25519key));
310
0
    ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype);
311
0
    if (ret == DROPBEAR_FAILURE) {
312
0
      m_free(key->ed25519key);
313
0
      key->ed25519key = NULL;
314
0
    }
315
0
  }
316
0
#endif
317
318
0
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
319
0
  if (0
320
0
#if DROPBEAR_SK_ED25519
321
0
    || keytype == DROPBEAR_SIGNKEY_SK_ED25519
322
0
#endif
323
0
#if DROPBEAR_SK_ECDSA
324
0
    || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
325
0
#endif
326
0
  ) {
327
0
    key->sk_app = buf_getstring(buf, &key->sk_applen);
328
0
  }
329
0
#endif
330
331
0
  TRACE2(("leave buf_get_pub_key"))
332
333
0
  return ret;
334
0
}
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
8
int buf_get_priv_key(buffer *buf, sign_key *key, enum signkey_type *type) {
340
341
8
  char *ident;
342
8
  unsigned int len;
343
8
  enum signkey_type keytype;
344
8
  int ret = DROPBEAR_FAILURE;
345
346
8
  TRACE2(("enter buf_get_priv_key"))
347
348
8
  ident = buf_getstring(buf, &len);
349
8
  keytype = signkey_type_from_name(ident, len);
350
8
  m_free(ident);
351
352
8
  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
8
  *type = keytype;
358
359
  /* Rewind the buffer back before "ssh-rsa" etc */
360
8
  buf_decrpos(buf, len + 4);
361
362
8
#if DROPBEAR_DSS
363
8
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
364
2
    dss_key_free(key->dsskey);
365
2
    key->dsskey = m_malloc(sizeof(*key->dsskey));
366
2
    ret = buf_get_dss_priv_key(buf, key->dsskey);
367
2
    if (ret == DROPBEAR_FAILURE) {
368
0
      dss_key_free(key->dsskey);
369
0
      key->dsskey = NULL;
370
0
    }
371
2
  }
372
8
#endif
373
8
#if DROPBEAR_RSA
374
8
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
375
2
    rsa_key_free(key->rsakey);
376
2
    key->rsakey = m_malloc(sizeof(*key->rsakey));
377
2
    ret = buf_get_rsa_priv_key(buf, key->rsakey);
378
2
    if (ret == DROPBEAR_FAILURE) {
379
0
      rsa_key_free(key->rsakey);
380
0
      key->rsakey = NULL;
381
0
    }
382
2
  }
383
8
#endif
384
8
#if DROPBEAR_ECDSA
385
8
  if (signkey_is_ecdsa(keytype)) {
386
2
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
387
2
    if (eck) {
388
2
      if (*eck) {
389
0
        ecc_free(*eck);
390
0
        m_free(*eck);
391
0
        *eck = NULL;
392
0
      }
393
2
      *eck = buf_get_ecdsa_priv_key(buf);
394
2
      if (*eck) {
395
2
        ret = DROPBEAR_SUCCESS;
396
2
      }
397
2
    }
398
2
  }
399
8
#endif
400
8
#if DROPBEAR_ED25519
401
8
  if (keytype == DROPBEAR_SIGNKEY_ED25519) {
402
2
    ed25519_key_free(key->ed25519key);
403
2
    key->ed25519key = m_malloc(sizeof(*key->ed25519key));
404
2
    ret = buf_get_ed25519_priv_key(buf, key->ed25519key);
405
2
    if (ret == DROPBEAR_FAILURE) {
406
0
      m_free(key->ed25519key);
407
0
      key->ed25519key = NULL;
408
0
    }
409
2
  }
410
8
#endif
411
412
8
  TRACE2(("leave buf_get_priv_key"))
413
414
8
  return ret;
415
  
416
8
}
417
418
/* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */
419
178
void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
420
421
178
  buffer *pubkeys;
422
423
178
  TRACE2(("enter buf_put_pub_key"))
424
178
  pubkeys = buf_new(MAX_PUBKEY_SIZE);
425
  
426
178
#if DROPBEAR_DSS
427
178
  if (type == DROPBEAR_SIGNKEY_DSS) {
428
0
    buf_put_dss_pub_key(pubkeys, key->dsskey);
429
0
  }
430
178
#endif
431
178
#if DROPBEAR_RSA
432
178
  if (type == DROPBEAR_SIGNKEY_RSA) {
433
0
    buf_put_rsa_pub_key(pubkeys, key->rsakey);
434
0
  }
435
178
#endif
436
178
#if DROPBEAR_ECDSA
437
178
  if (signkey_is_ecdsa(type)) {
438
178
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
439
178
    if (eck && *eck) {
440
178
      buf_put_ecdsa_pub_key(pubkeys, *eck);
441
178
    }
442
178
  }
443
178
#endif
444
178
#if DROPBEAR_ED25519
445
178
  if (type == DROPBEAR_SIGNKEY_ED25519
446
178
#if DROPBEAR_SK_ED25519
447
178
    || type == DROPBEAR_SIGNKEY_SK_ED25519
448
178
#endif
449
178
  ) {
450
0
    buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
451
0
  }
452
178
#endif
453
178
  if (pubkeys->len == 0) {
454
0
    dropbear_exit("Bad key types in buf_put_pub_key");
455
0
  }
456
457
178
  buf_putbufstring(buf, pubkeys);
458
178
  buf_free(pubkeys);
459
178
  TRACE2(("leave buf_put_pub_key"))
460
178
}
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
0
void sign_key_free(sign_key *key) {
503
504
0
  TRACE2(("enter sign_key_free"))
505
506
0
#if DROPBEAR_DSS
507
0
  dss_key_free(key->dsskey);
508
0
  key->dsskey = NULL;
509
0
#endif
510
0
#if DROPBEAR_RSA
511
0
  rsa_key_free(key->rsakey);
512
0
  key->rsakey = NULL;
513
0
#endif
514
0
#if DROPBEAR_ECDSA
515
0
#if DROPBEAR_ECC_256
516
0
  if (key->ecckey256) {
517
0
    ecc_free(key->ecckey256);
518
0
    m_free(key->ecckey256);
519
0
    key->ecckey256 = NULL;
520
0
  }
521
0
#endif
522
0
#if DROPBEAR_ECC_384
523
0
  if (key->ecckey384) {
524
0
    ecc_free(key->ecckey384);
525
0
    m_free(key->ecckey384);
526
0
    key->ecckey384 = NULL;
527
0
  }
528
0
#endif
529
0
#if DROPBEAR_ECC_521
530
0
  if (key->ecckey521) {
531
0
    ecc_free(key->ecckey521);
532
0
    m_free(key->ecckey521);
533
0
    key->ecckey521 = NULL;
534
0
  }
535
0
#endif
536
0
#endif
537
0
#if DROPBEAR_ED25519
538
0
  ed25519_key_free(key->ed25519key);
539
0
  key->ed25519key = NULL;
540
0
#endif
541
542
0
  m_free(key->filename);
543
0
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
544
0
  if (key->sk_app) {
545
0
    m_free(key->sk_app);
546
0
  }
547
0
#endif
548
549
0
  m_free(key);
550
0
  TRACE2(("leave sign_key_free"))
551
0
}
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
0
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) {
642
  
643
0
  char *type_name = NULL;
644
0
  unsigned int type_name_len = 0;
645
0
  enum signature_type sigtype;
646
0
  enum signkey_type keytype;
647
648
0
  TRACE(("enter buf_verify"))
649
650
0
  buf_getint(buf); /* blob length */
651
0
  type_name = buf_getstring(buf, &type_name_len);
652
0
  sigtype = signature_type_from_name(type_name, type_name_len);
653
0
  m_free(type_name);
654
655
0
  if (expect_sigtype != sigtype) {
656
0
      dropbear_exit("Non-matching signing type");
657
0
  }
658
659
0
  keytype = signkey_type_from_signature(sigtype);
660
0
#if DROPBEAR_DSS
661
0
  if (keytype == DROPBEAR_SIGNKEY_DSS) {
662
0
    if (key->dsskey == NULL) {
663
0
      dropbear_exit("No DSS key to verify signature");
664
0
    }
665
0
    return buf_dss_verify(buf, key->dsskey, data_buf);
666
0
  }
667
0
#endif
668
669
0
#if DROPBEAR_RSA
670
0
  if (keytype == DROPBEAR_SIGNKEY_RSA) {
671
0
    if (key->rsakey == NULL) {
672
0
      dropbear_exit("No RSA key to verify signature");
673
0
    }
674
0
    return buf_rsa_verify(buf, key->rsakey, sigtype, data_buf);
675
0
  }
676
0
#endif
677
0
#if DROPBEAR_ECDSA
678
0
  if (signkey_is_ecdsa(keytype)) {
679
0
    ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
680
0
    if (eck && *eck) {
681
0
      return buf_ecdsa_verify(buf, *eck, data_buf);
682
0
    }
683
0
  }
684
0
#endif
685
0
#if DROPBEAR_ED25519
686
0
  if (keytype == DROPBEAR_SIGNKEY_ED25519) {
687
0
    if (key->ed25519key == NULL) {
688
0
      dropbear_exit("No Ed25519 key to verify signature");
689
0
    }
690
0
    return buf_ed25519_verify(buf, key->ed25519key, data_buf);
691
0
  }
692
0
#endif
693
0
#if DROPBEAR_SK_ECDSA
694
0
  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
0
#endif
701
0
#if DROPBEAR_SK_ED25519
702
0
  if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
703
0
    dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
704
0
    if (eck && *eck) {
705
0
      return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen, key->sk_flags_mask);
706
0
    }
707
0
  }
708
0
#endif
709
710
0
  dropbear_exit("Non-matching signing type");
711
0
  return DROPBEAR_FAILURE;
712
0
}
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