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