Mercurial > dropbear
comparison signkey.c @ 839:33207ed1174b
Merge in ECC
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 21 Oct 2013 22:57:21 +0800 |
parents | 75509065db53 |
children | d4ce5269a439 |
comparison
equal
deleted
inserted
replaced
834:e378da7eae5d | 839:33207ed1174b |
---|---|
25 #include "includes.h" | 25 #include "includes.h" |
26 #include "dbutil.h" | 26 #include "dbutil.h" |
27 #include "signkey.h" | 27 #include "signkey.h" |
28 #include "buffer.h" | 28 #include "buffer.h" |
29 #include "ssh.h" | 29 #include "ssh.h" |
30 #include "ecdsa.h" | |
31 | |
32 static const char *signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = { | |
33 #ifdef DROPBEAR_RSA | |
34 "ssh-rsa", | |
35 #endif | |
36 #ifdef DROPBEAR_DSS | |
37 "ssh-dss", | |
38 #endif | |
39 #ifdef DROPBEAR_ECDSA | |
40 "ecdsa-sha2-nistp256", | |
41 "ecdsa-sha2-nistp384", | |
42 "ecdsa-sha2-nistp521", | |
43 "ecdsa" // for keygen | |
44 #endif // DROPBEAR_ECDSA | |
45 }; | |
30 | 46 |
31 /* malloc a new sign_key and set the dss and rsa keys to NULL */ | 47 /* malloc a new sign_key and set the dss and rsa keys to NULL */ |
32 sign_key * new_sign_key() { | 48 sign_key * new_sign_key() { |
33 | 49 |
34 sign_key * ret; | 50 sign_key * ret; |
35 | 51 |
36 ret = (sign_key*)m_malloc(sizeof(sign_key)); | 52 ret = (sign_key*)m_malloc(sizeof(sign_key)); |
37 #ifdef DROPBEAR_DSS | |
38 ret->dsskey = NULL; | |
39 #endif | |
40 #ifdef DROPBEAR_RSA | |
41 ret->rsakey = NULL; | |
42 #endif | |
43 ret->filename = NULL; | |
44 ret->type = DROPBEAR_SIGNKEY_NONE; | 53 ret->type = DROPBEAR_SIGNKEY_NONE; |
45 ret->source = SIGNKEY_SOURCE_INVALID; | 54 ret->source = SIGNKEY_SOURCE_INVALID; |
46 return ret; | 55 return ret; |
47 } | 56 } |
48 | 57 |
49 /* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally | 58 /* Returns key name corresponding to the type. Exits fatally |
50 * if the type is invalid */ | 59 * if the type is invalid */ |
51 const char* signkey_name_from_type(int type, int *namelen) { | 60 const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen) { |
52 | 61 if (type >= DROPBEAR_SIGNKEY_NUM_NAMED) { |
53 #ifdef DROPBEAR_RSA | 62 dropbear_exit("Bad key type %d", type); |
54 if (type == DROPBEAR_SIGNKEY_RSA) { | 63 } |
55 *namelen = SSH_SIGNKEY_RSA_LEN; | 64 |
56 return SSH_SIGNKEY_RSA; | 65 if (namelen) { |
57 } | 66 *namelen = strlen(signkey_names[type]); |
58 #endif | 67 } |
59 #ifdef DROPBEAR_DSS | 68 return signkey_names[type]; |
60 if (type == DROPBEAR_SIGNKEY_DSS) { | 69 } |
61 *namelen = SSH_SIGNKEY_DSS_LEN; | 70 |
62 return SSH_SIGNKEY_DSS; | 71 /* Returns DROPBEAR_SIGNKEY_NONE if none match */ |
63 } | 72 enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) { |
64 #endif | 73 int i; |
65 dropbear_exit("Bad key type %d", type); | 74 for (i = 0; i < DROPBEAR_SIGNKEY_NUM_NAMED; i++) { |
66 return NULL; /* notreached */ | 75 const char *fixed_name = signkey_names[i]; |
67 } | 76 if (namelen == strlen(fixed_name) |
68 | 77 && memcmp(fixed_name, name, namelen) == 0) { |
69 /* Returns DROPBEAR_SIGNKEY_RSA, DROPBEAR_SIGNKEY_DSS, | 78 |
70 * or DROPBEAR_SIGNKEY_NONE */ | 79 #ifdef DROPBEAR_ECDSA |
71 int signkey_type_from_name(const char* name, int namelen) { | 80 /* Some of the ECDSA key sizes are defined even if they're not compiled in */ |
72 | 81 if (0 |
73 #ifdef DROPBEAR_RSA | 82 #ifndef DROPBEAR_ECC_256 |
74 if (namelen == SSH_SIGNKEY_RSA_LEN | 83 || i == DROPBEAR_SIGNKEY_ECDSA_NISTP256 |
75 && memcmp(name, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN) == 0) { | 84 #endif |
76 return DROPBEAR_SIGNKEY_RSA; | 85 #ifndef DROPBEAR_ECC_384 |
77 } | 86 || i == DROPBEAR_SIGNKEY_ECDSA_NISTP384 |
78 #endif | 87 #endif |
79 #ifdef DROPBEAR_DSS | 88 #ifndef DROPBEAR_ECC_521 |
80 if (namelen == SSH_SIGNKEY_DSS_LEN | 89 || i == DROPBEAR_SIGNKEY_ECDSA_NISTP521 |
81 && memcmp(name, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN) == 0) { | 90 #endif |
82 return DROPBEAR_SIGNKEY_DSS; | 91 ) { |
83 } | 92 TRACE(("attempt to use ecdsa type %d not compiled in", i)) |
84 #endif | 93 return DROPBEAR_SIGNKEY_NONE; |
94 } | |
95 #endif | |
96 | |
97 return i; | |
98 } | |
99 } | |
85 | 100 |
86 TRACE(("signkey_type_from_name unexpected key type.")) | 101 TRACE(("signkey_type_from_name unexpected key type.")) |
87 | 102 |
88 return DROPBEAR_SIGNKEY_NONE; | 103 return DROPBEAR_SIGNKEY_NONE; |
89 } | 104 } |
105 | |
106 #ifdef DROPBEAR_ECDSA | |
107 ecc_key ** | |
108 signkey_ecc_key_ptr(sign_key *key, enum signkey_type ecc_type) { | |
109 switch (ecc_type) { | |
110 case DROPBEAR_SIGNKEY_ECDSA_NISTP256: | |
111 return &key->ecckey256; | |
112 case DROPBEAR_SIGNKEY_ECDSA_NISTP384: | |
113 return &key->ecckey384; | |
114 case DROPBEAR_SIGNKEY_ECDSA_NISTP521: | |
115 return &key->ecckey521; | |
116 default: | |
117 return NULL; | |
118 } | |
119 } | |
120 #endif | |
90 | 121 |
91 /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail. | 122 /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail. |
92 * type should be set by the caller to specify the type to read, and | 123 * type should be set by the caller to specify the type to read, and |
93 * on return is set to the type read (useful when type = _ANY) */ | 124 * on return is set to the type read (useful when type = _ANY) */ |
94 int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { | 125 int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { |
134 if (ret == DROPBEAR_FAILURE) { | 165 if (ret == DROPBEAR_FAILURE) { |
135 m_free(key->rsakey); | 166 m_free(key->rsakey); |
136 } | 167 } |
137 } | 168 } |
138 #endif | 169 #endif |
170 #ifdef DROPBEAR_ECDSA | |
171 { | |
172 ecc_key **eck = signkey_ecc_key_ptr(key, keytype); | |
173 if (eck) { | |
174 if (*eck) { | |
175 ecc_free(*eck); | |
176 *eck = NULL; | |
177 } | |
178 *eck = buf_get_ecdsa_pub_key(buf); | |
179 if (*eck) { | |
180 ret = DROPBEAR_SUCCESS; | |
181 } | |
182 } | |
183 } | |
184 #endif | |
139 | 185 |
140 TRACE2(("leave buf_get_pub_key")) | 186 TRACE2(("leave buf_get_pub_key")) |
141 | 187 |
142 return ret; | 188 return ret; |
143 | 189 |
187 if (ret == DROPBEAR_FAILURE) { | 233 if (ret == DROPBEAR_FAILURE) { |
188 m_free(key->rsakey); | 234 m_free(key->rsakey); |
189 } | 235 } |
190 } | 236 } |
191 #endif | 237 #endif |
238 #ifdef DROPBEAR_ECDSA | |
239 { | |
240 ecc_key **eck = signkey_ecc_key_ptr(key, keytype); | |
241 if (eck) { | |
242 if (*eck) { | |
243 ecc_free(*eck); | |
244 *eck = NULL; | |
245 } | |
246 *eck = buf_get_ecdsa_priv_key(buf); | |
247 if (*eck) { | |
248 ret = DROPBEAR_SUCCESS; | |
249 } | |
250 } | |
251 } | |
252 #endif | |
192 | 253 |
193 TRACE2(("leave buf_get_priv_key")) | 254 TRACE2(("leave buf_get_priv_key")) |
194 | 255 |
195 return ret; | 256 return ret; |
196 | 257 |
212 #ifdef DROPBEAR_RSA | 273 #ifdef DROPBEAR_RSA |
213 if (type == DROPBEAR_SIGNKEY_RSA) { | 274 if (type == DROPBEAR_SIGNKEY_RSA) { |
214 buf_put_rsa_pub_key(pubkeys, key->rsakey); | 275 buf_put_rsa_pub_key(pubkeys, key->rsakey); |
215 } | 276 } |
216 #endif | 277 #endif |
278 #ifdef DROPBEAR_ECDSA | |
279 { | |
280 ecc_key **eck = signkey_ecc_key_ptr(key, type); | |
281 if (eck) { | |
282 buf_put_ecdsa_pub_key(pubkeys, *eck); | |
283 } | |
284 } | |
285 #endif | |
217 if (pubkeys->len == 0) { | 286 if (pubkeys->len == 0) { |
218 dropbear_exit("Bad key types in buf_put_pub_key"); | 287 dropbear_exit("Bad key types in buf_put_pub_key"); |
219 } | 288 } |
220 | 289 |
221 buf_setpos(pubkeys, 0); | 290 buf_putbufstring(buf, pubkeys); |
222 buf_putstring(buf, buf_getptr(pubkeys, pubkeys->len), | |
223 pubkeys->len); | |
224 | |
225 buf_free(pubkeys); | 291 buf_free(pubkeys); |
226 TRACE2(("leave buf_put_pub_key")) | 292 TRACE2(("leave buf_put_pub_key")) |
227 } | 293 } |
228 | 294 |
229 /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */ | 295 /* type is either DROPBEAR_SIGNKEY_DSS or DROPBEAR_SIGNKEY_RSA */ |
244 buf_put_rsa_priv_key(buf, key->rsakey); | 310 buf_put_rsa_priv_key(buf, key->rsakey); |
245 TRACE(("leave buf_put_priv_key: rsa done")) | 311 TRACE(("leave buf_put_priv_key: rsa done")) |
246 return; | 312 return; |
247 } | 313 } |
248 #endif | 314 #endif |
315 #ifdef DROPBEAR_ECDSA | |
316 { | |
317 ecc_key **eck = signkey_ecc_key_ptr(key, type); | |
318 if (eck) { | |
319 buf_put_ecdsa_priv_key(buf, *eck); | |
320 TRACE(("leave buf_put_priv_key: ecdsa done")) | |
321 return; | |
322 } | |
323 } | |
324 #endif | |
249 dropbear_exit("Bad key types in put pub key"); | 325 dropbear_exit("Bad key types in put pub key"); |
250 } | 326 } |
251 | 327 |
252 void sign_key_free(sign_key *key) { | 328 void sign_key_free(sign_key *key) { |
253 | 329 |
259 #endif | 335 #endif |
260 #ifdef DROPBEAR_RSA | 336 #ifdef DROPBEAR_RSA |
261 rsa_key_free(key->rsakey); | 337 rsa_key_free(key->rsakey); |
262 key->rsakey = NULL; | 338 key->rsakey = NULL; |
263 #endif | 339 #endif |
340 #ifdef DROPBEAR_ECDSA | |
341 if (key->ecckey256) { | |
342 ecc_free(key->ecckey256); | |
343 key->ecckey256 = NULL; | |
344 } | |
345 if (key->ecckey384) { | |
346 ecc_free(key->ecckey384); | |
347 key->ecckey384 = NULL; | |
348 } | |
349 if (key->ecckey521) { | |
350 ecc_free(key->ecckey521); | |
351 key->ecckey521 = NULL; | |
352 } | |
353 #endif | |
264 | 354 |
265 m_free(key->filename); | 355 m_free(key->filename); |
266 | 356 |
267 m_free(key); | 357 m_free(key); |
268 TRACE2(("leave sign_key_free")) | 358 TRACE2(("leave sign_key_free")) |
269 } | 359 } |
270 | 360 |
271 static char hexdig(unsigned char x) { | 361 static char hexdig(unsigned char x) { |
272 | |
273 if (x > 0xf) | 362 if (x > 0xf) |
274 return 'X'; | 363 return 'X'; |
275 | 364 |
276 if (x < 10) | 365 if (x < 10) |
277 return '0' + x; | 366 return '0' + x; |
331 /* skip the size int of the string - this is a bit messy */ | 420 /* skip the size int of the string - this is a bit messy */ |
332 sha1_process(&hs, keyblob, keybloblen); | 421 sha1_process(&hs, keyblob, keybloblen); |
333 | 422 |
334 sha1_done(&hs, hash); | 423 sha1_done(&hs, hash); |
335 | 424 |
336 /* "sha1 hexfingerprinthere\0", each hex digit is "AB:" etc */ | 425 /* "sha1!! hexfingerprinthere\0", each hex digit is "AB:" etc */ |
337 buflen = 5 + 3*SHA1_HASH_SIZE; | 426 buflen = 7 + 3*SHA1_HASH_SIZE; |
338 ret = (char*)m_malloc(buflen); | 427 ret = (char*)m_malloc(buflen); |
339 | 428 |
340 strcpy(ret, "sha1 "); | 429 strcpy(ret, "sha1!! "); |
341 | 430 |
342 for (i = 0; i < SHA1_HASH_SIZE; i++) { | 431 for (i = 0; i < SHA1_HASH_SIZE; i++) { |
343 unsigned int pos = 5 + 3*i; | 432 unsigned int pos = 7 + 3*i; |
344 ret[pos] = hexdig(hash[i] >> 4); | 433 ret[pos] = hexdig(hash[i] >> 4); |
345 ret[pos+1] = hexdig(hash[i] & 0x0f); | 434 ret[pos+1] = hexdig(hash[i] & 0x0f); |
346 ret[pos+2] = ':'; | 435 ret[pos+2] = ':'; |
347 } | 436 } |
348 ret[buflen-1] = 0x0; | 437 ret[buflen-1] = 0x0; |
362 return sign_key_sha1_fingerprint(keyblob, keybloblen); | 451 return sign_key_sha1_fingerprint(keyblob, keybloblen); |
363 #endif | 452 #endif |
364 } | 453 } |
365 | 454 |
366 void buf_put_sign(buffer* buf, sign_key *key, int type, | 455 void buf_put_sign(buffer* buf, sign_key *key, int type, |
367 const unsigned char *data, unsigned int len) { | 456 buffer *data_buf) { |
368 | |
369 buffer *sigblob; | 457 buffer *sigblob; |
370 sigblob = buf_new(MAX_PUBKEY_SIZE); | 458 sigblob = buf_new(MAX_PUBKEY_SIZE); |
371 | 459 |
372 #ifdef DROPBEAR_DSS | 460 #ifdef DROPBEAR_DSS |
373 if (type == DROPBEAR_SIGNKEY_DSS) { | 461 if (type == DROPBEAR_SIGNKEY_DSS) { |
374 buf_put_dss_sign(sigblob, key->dsskey, data, len); | 462 buf_put_dss_sign(sigblob, key->dsskey, data_buf); |
375 } | 463 } |
376 #endif | 464 #endif |
377 #ifdef DROPBEAR_RSA | 465 #ifdef DROPBEAR_RSA |
378 if (type == DROPBEAR_SIGNKEY_RSA) { | 466 if (type == DROPBEAR_SIGNKEY_RSA) { |
379 buf_put_rsa_sign(sigblob, key->rsakey, data, len); | 467 buf_put_rsa_sign(sigblob, key->rsakey, data_buf); |
468 } | |
469 #endif | |
470 #ifdef DROPBEAR_ECDSA | |
471 { | |
472 ecc_key **eck = signkey_ecc_key_ptr(key, type); | |
473 if (eck) { | |
474 buf_put_ecdsa_sign(sigblob, *eck, data_buf); | |
475 } | |
380 } | 476 } |
381 #endif | 477 #endif |
382 if (sigblob->len == 0) { | 478 if (sigblob->len == 0) { |
383 dropbear_exit("Non-matching signing type"); | 479 dropbear_exit("Non-matching signing type"); |
384 } | 480 } |
385 buf_setpos(sigblob, 0); | 481 buf_putbufstring(buf, sigblob); |
386 buf_putstring(buf, buf_getptr(sigblob, sigblob->len), | |
387 sigblob->len); | |
388 | |
389 buf_free(sigblob); | 482 buf_free(sigblob); |
390 | 483 |
391 } | 484 } |
392 | 485 |
393 #ifdef DROPBEAR_SIGNKEY_VERIFY | 486 #ifdef DROPBEAR_SIGNKEY_VERIFY |
394 /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE. | 487 /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE. |
395 * If FAILURE is returned, the position of | 488 * If FAILURE is returned, the position of |
396 * buf is undefined. If SUCCESS is returned, buf will be positioned after the | 489 * buf is undefined. If SUCCESS is returned, buf will be positioned after the |
397 * signature blob */ | 490 * signature blob */ |
398 int buf_verify(buffer * buf, sign_key *key, const unsigned char *data, | 491 int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) { |
399 unsigned int len) { | |
400 | 492 |
401 unsigned int bloblen; | 493 unsigned int bloblen; |
402 unsigned char * ident = NULL; | 494 unsigned char * type_name = NULL; |
403 unsigned int identlen = 0; | 495 unsigned int type_name_len = 0; |
404 | 496 |
405 TRACE(("enter buf_verify")) | 497 TRACE(("enter buf_verify")) |
406 | 498 |
407 bloblen = buf_getint(buf); | 499 bloblen = buf_getint(buf); |
408 ident = buf_getstring(buf, &identlen); | 500 type_name = buf_getstring(buf, &type_name_len); |
409 | 501 enum signkey_type type = signkey_type_from_name(type_name, type_name_len); |
410 #ifdef DROPBEAR_DSS | 502 m_free(type_name); |
411 if (bloblen == DSS_SIGNATURE_SIZE && | 503 |
412 memcmp(ident, SSH_SIGNKEY_DSS, identlen) == 0) { | 504 #ifdef DROPBEAR_DSS |
413 m_free(ident); | 505 if (type == DROPBEAR_SIGNKEY_DSS) { |
414 if (key->dsskey == NULL) { | 506 if (key->dsskey == NULL) { |
415 dropbear_exit("No DSS key to verify signature"); | 507 dropbear_exit("No DSS key to verify signature"); |
416 } | 508 } |
417 return buf_dss_verify(buf, key->dsskey, data, len); | 509 return buf_dss_verify(buf, key->dsskey, data_buf); |
418 } | 510 } |
419 #endif | 511 #endif |
420 | 512 |
421 #ifdef DROPBEAR_RSA | 513 #ifdef DROPBEAR_RSA |
422 if (memcmp(ident, SSH_SIGNKEY_RSA, identlen) == 0) { | 514 if (type == DROPBEAR_SIGNKEY_RSA) { |
423 m_free(ident); | |
424 if (key->rsakey == NULL) { | 515 if (key->rsakey == NULL) { |
425 dropbear_exit("No RSA key to verify signature"); | 516 dropbear_exit("No RSA key to verify signature"); |
426 } | 517 } |
427 return buf_rsa_verify(buf, key->rsakey, data, len); | 518 return buf_rsa_verify(buf, key->rsakey, data_buf); |
428 } | 519 } |
429 #endif | 520 #endif |
430 | 521 #ifdef DROPBEAR_ECDSA |
431 m_free(ident); | 522 { |
523 ecc_key **eck = signkey_ecc_key_ptr(key, type); | |
524 if (eck) { | |
525 return buf_ecdsa_verify(buf, *eck, data_buf); | |
526 } | |
527 } | |
528 #endif | |
529 | |
432 dropbear_exit("Non-matching signing type"); | 530 dropbear_exit("Non-matching signing type"); |
433 return DROPBEAR_FAILURE; | 531 return DROPBEAR_FAILURE; |
434 } | 532 } |
435 #endif /* DROPBEAR_SIGNKEY_VERIFY */ | 533 #endif /* DROPBEAR_SIGNKEY_VERIFY */ |
436 | 534 |