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