Mercurial > dropbear
comparison keyimport.c @ 1316:2c9dac2d6707
merge 2016.74
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 21 Jul 2016 23:38:42 +0800 |
parents | 750ec4ec4cbe 8678e2cc1e53 |
children | 77c0d57a4410 |
comparison
equal
deleted
inserted
replaced
1298:251c5f7a6e96 | 1316:2c9dac2d6707 |
---|---|
60 char *passphrase); | 60 char *passphrase); |
61 | 61 |
62 static int dropbear_write(const char*filename, sign_key * key); | 62 static int dropbear_write(const char*filename, sign_key * key); |
63 static sign_key *dropbear_read(const char* filename); | 63 static sign_key *dropbear_read(const char* filename); |
64 | 64 |
65 static int toint(unsigned u); | |
66 | |
65 #if 0 | 67 #if 0 |
66 static int sshcom_encrypted(const char *filename, char **comment); | 68 static int sshcom_encrypted(const char *filename, char **comment); |
67 static struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase); | 69 static struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase); |
68 static int sshcom_write(const char *filename, struct ssh2_userkey *key, | 70 static int sshcom_write(const char *filename, struct ssh2_userkey *key, |
69 char *passphrase); | 71 char *passphrase); |
241 | 243 |
242 *flags = (*p & 0xE0); | 244 *flags = (*p & 0xE0); |
243 if ((*p & 0x1F) == 0x1F) { | 245 if ((*p & 0x1F) == 0x1F) { |
244 *id = 0; | 246 *id = 0; |
245 while (*p & 0x80) { | 247 while (*p & 0x80) { |
246 *id = (*id << 7) | (*p & 0x7F); | |
247 p++, sourcelen--; | 248 p++, sourcelen--; |
248 if (sourcelen == 0) | 249 if (sourcelen == 0) |
249 return -1; | 250 return -1; |
250 } | 251 *id = (*id << 7) | (*p & 0x7F); |
251 *id = (*id << 7) | (*p & 0x7F); | 252 } |
252 p++, sourcelen--; | 253 p++, sourcelen--; |
253 } else { | 254 } else { |
254 *id = *p & 0x1F; | 255 *id = *p & 0x1F; |
255 p++, sourcelen--; | 256 p++, sourcelen--; |
256 } | 257 } |
257 | 258 |
258 if (sourcelen == 0) | 259 if (sourcelen == 0) |
259 return -1; | 260 return -1; |
260 | 261 |
261 if (*p & 0x80) { | 262 if (*p & 0x80) { |
263 unsigned len; | |
262 int n = *p & 0x7F; | 264 int n = *p & 0x7F; |
263 p++, sourcelen--; | 265 p++, sourcelen--; |
264 if (sourcelen < n) | 266 if (sourcelen < n) |
265 return -1; | 267 return -1; |
266 *length = 0; | 268 len = 0; |
267 while (n--) | 269 while (n--) |
268 *length = (*length << 8) | (*p++); | 270 len = (len << 8) | (*p++); |
269 sourcelen -= n; | 271 sourcelen -= n; |
272 *length = toint(len); | |
270 } else { | 273 } else { |
271 *length = *p; | 274 *length = *p; |
272 p++, sourcelen--; | 275 p++, sourcelen--; |
276 } | |
277 | |
278 if (*length < 0) { | |
279 printf("Negative ASN.1 length\n"); | |
280 return -1; | |
273 } | 281 } |
274 | 282 |
275 return p - (unsigned char *) source; | 283 return p - (unsigned char *) source; |
276 } | 284 } |
277 | 285 |
467 } | 475 } |
468 | 476 |
469 m_burn(buffer, sizeof(buffer)); | 477 m_burn(buffer, sizeof(buffer)); |
470 return ret; | 478 return ret; |
471 | 479 |
472 error: | 480 error: |
473 m_burn(buffer, sizeof(buffer)); | 481 m_burn(buffer, sizeof(buffer)); |
474 if (ret) { | 482 if (ret) { |
475 if (ret->keyblob) { | 483 if (ret->keyblob) { |
476 m_burn(ret->keyblob, ret->keyblob_size); | 484 m_burn(ret->keyblob, ret->keyblob_size); |
477 m_free(ret->keyblob); | 485 m_free(ret->keyblob); |
582 p = key->keyblob; | 590 p = key->keyblob; |
583 | 591 |
584 /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */ | 592 /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */ |
585 ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags); | 593 ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags); |
586 p += ret; | 594 p += ret; |
587 if (ret < 0 || id != 16) { | 595 if (ret < 0 || id != 16 || len < 0 || |
588 errmsg = "ASN.1 decoding failure - wrong password?"; | 596 key->keyblob+key->keyblob_len-p < len) { |
597 errmsg = "ASN.1 decoding failure"; | |
589 goto error; | 598 goto error; |
590 } | 599 } |
591 | 600 |
592 /* Expect a load of INTEGERs. */ | 601 /* Expect a load of INTEGERs. */ |
593 if (key->type == OSSH_RSA) | 602 if (key->type == OSSH_RSA) |
617 | 626 |
618 for (i = 0; i < num_integers; i++) { | 627 for (i = 0; i < num_integers; i++) { |
619 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 628 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
620 &id, &len, &flags); | 629 &id, &len, &flags); |
621 p += ret; | 630 p += ret; |
622 if (ret < 0 || id != 2 || | 631 if (ret < 0 || id != 2 || len < 0 || |
623 key->keyblob+key->keyblob_len-p < len) { | 632 key->keyblob+key->keyblob_len-p < len) { |
624 errmsg = "ASN.1 decoding failure"; | 633 errmsg = "ASN.1 decoding failure"; |
625 goto error; | 634 goto error; |
626 } | 635 } |
627 | 636 |
683 /* privateKey OCTET STRING, */ | 692 /* privateKey OCTET STRING, */ |
684 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 693 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
685 &id, &len, &flags); | 694 &id, &len, &flags); |
686 p += ret; | 695 p += ret; |
687 /* id==4 for octet string */ | 696 /* id==4 for octet string */ |
688 if (ret < 0 || id != 4 || | 697 if (ret < 0 || id != 4 || len < 0 || |
689 key->keyblob+key->keyblob_len-p < len) { | 698 key->keyblob+key->keyblob_len-p < len) { |
690 errmsg = "ASN.1 decoding failure"; | 699 errmsg = "ASN.1 decoding failure"; |
691 goto error; | 700 goto error; |
692 } | 701 } |
693 private_key_bytes = p; | 702 private_key_bytes = p; |
697 /* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */ | 706 /* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */ |
698 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 707 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
699 &id, &len, &flags); | 708 &id, &len, &flags); |
700 p += ret; | 709 p += ret; |
701 /* id==0 */ | 710 /* id==0 */ |
702 if (ret < 0 || id != 0) { | 711 if (ret < 0 || id != 0 || len < 0) { |
703 errmsg = "ASN.1 decoding failure"; | 712 errmsg = "ASN.1 decoding failure"; |
704 goto error; | 713 goto error; |
705 } | 714 } |
706 | 715 |
707 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 716 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
708 &id, &len, &flags); | 717 &id, &len, &flags); |
709 p += ret; | 718 p += ret; |
710 /* id==6 for object */ | 719 /* id==6 for object */ |
711 if (ret < 0 || id != 6 || | 720 if (ret < 0 || id != 6 || len < 0 || |
712 key->keyblob+key->keyblob_len-p < len) { | 721 key->keyblob+key->keyblob_len-p < len) { |
713 errmsg = "ASN.1 decoding failure"; | 722 errmsg = "ASN.1 decoding failure"; |
714 goto error; | 723 goto error; |
715 } | 724 } |
716 | 725 |
745 /* publicKey [1] BIT STRING OPTIONAL */ | 754 /* publicKey [1] BIT STRING OPTIONAL */ |
746 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 755 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
747 &id, &len, &flags); | 756 &id, &len, &flags); |
748 p += ret; | 757 p += ret; |
749 /* id==1 */ | 758 /* id==1 */ |
750 if (ret < 0 || id != 1) { | 759 if (ret < 0 || id != 1 || len < 0) { |
751 errmsg = "ASN.1 decoding failure"; | 760 errmsg = "ASN.1 decoding failure"; |
752 goto error; | 761 goto error; |
753 } | 762 } |
754 | 763 |
755 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, | 764 ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, |
756 &id, &len, &flags); | 765 &id, &len, &flags); |
757 p += ret; | 766 p += ret; |
758 /* id==3 for bit string */ | 767 /* id==3 for bit string */ |
759 if (ret < 0 || id != 3 || | 768 if (ret < 0 || id != 3 || len < 0 || |
760 key->keyblob+key->keyblob_len-p < len) { | 769 key->keyblob+key->keyblob_len-p < len) { |
761 errmsg = "ASN.1 decoding failure"; | 770 errmsg = "ASN.1 decoding failure"; |
762 goto error; | 771 goto error; |
763 } | 772 } |
764 public_key_bytes = p+1; | 773 public_key_bytes = p+1; |
1379 if (ret) { | 1388 if (ret) { |
1380 if (ret->keyblob) { | 1389 if (ret->keyblob) { |
1381 memset(ret->keyblob, 0, ret->keyblob_size); | 1390 memset(ret->keyblob, 0, ret->keyblob_size); |
1382 m_free(ret->keyblob); | 1391 m_free(ret->keyblob); |
1383 } | 1392 } |
1384 memset(&ret, 0, sizeof(ret)); | 1393 memset(ret, 0, sizeof(*ret)); |
1385 m_free(ret); | 1394 m_free(ret); |
1386 } | 1395 } |
1387 return NULL; | 1396 return NULL; |
1388 } | 1397 } |
1389 | 1398 |
1407 */ | 1416 */ |
1408 answer = 0; | 1417 answer = 0; |
1409 pos = 8; | 1418 pos = 8; |
1410 if (key->keyblob_len < pos+4) | 1419 if (key->keyblob_len < pos+4) |
1411 goto done; /* key is far too short */ | 1420 goto done; /* key is far too short */ |
1412 pos += 4 + GET_32BIT(key->keyblob + pos); /* skip key type */ | 1421 len = toint(GET_32BIT(key->keyblob + pos)); |
1413 if (key->keyblob_len < pos+4) | 1422 if (len < 0 || len > key->keyblob_len - pos - 4) |
1414 goto done; /* key is far too short */ | 1423 goto done; /* key is far too short */ |
1415 len = GET_32BIT(key->keyblob + pos); /* find cipher-type length */ | 1424 pos += 4 + len; /* skip key type */ |
1416 if (key->keyblob_len < pos+4+len) | 1425 len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */ |
1426 if (len < 0 || len > key->keyblob_len - pos - 4) | |
1417 goto done; /* cipher type string is incomplete */ | 1427 goto done; /* cipher type string is incomplete */ |
1418 if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4)) | 1428 if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4)) |
1419 answer = 1; | 1429 answer = 1; |
1420 | 1430 |
1421 done: | 1431 done: |
1422 *comment = dupstr(key->comment); | 1432 *comment = dupstr(key->comment); |
1423 memset(key->keyblob, 0, key->keyblob_size); | 1433 memset(key->keyblob, 0, key->keyblob_size); |
1424 m_free(key->keyblob); | 1434 m_free(key->keyblob); |
1425 memset(&key, 0, sizeof(key)); | 1435 memset(key, 0, sizeof(*key)); |
1426 m_free(key); | 1436 m_free(key); |
1427 return answer; | 1437 return answer; |
1428 } | 1438 } |
1429 | 1439 |
1430 static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) | 1440 static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) |
1431 { | 1441 { |
1432 int bits; | 1442 unsigned bits, bytes; |
1433 int bytes; | |
1434 unsigned char *d = (unsigned char *) data; | 1443 unsigned char *d = (unsigned char *) data; |
1435 | 1444 |
1436 if (len < 4) | 1445 if (len < 4) |
1437 goto error; | 1446 goto error; |
1438 bits = GET_32BIT(d); | 1447 bits = GET_32BIT(d); |
1481 char *ciphertext; | 1490 char *ciphertext; |
1482 int cipherlen; | 1491 int cipherlen; |
1483 struct ssh2_userkey *ret = NULL, *retkey; | 1492 struct ssh2_userkey *ret = NULL, *retkey; |
1484 const struct ssh_signkey *alg; | 1493 const struct ssh_signkey *alg; |
1485 unsigned char *blob = NULL; | 1494 unsigned char *blob = NULL; |
1486 int blobsize, publen, privlen; | 1495 int blobsize = 0, publen, privlen; |
1487 | 1496 |
1488 if (!key) | 1497 if (!key) |
1489 return NULL; | 1498 return NULL; |
1490 | 1499 |
1491 /* | 1500 /* |
1601 } | 1610 } |
1602 | 1611 |
1603 /* | 1612 /* |
1604 * Strip away the containing string to get to the real meat. | 1613 * Strip away the containing string to get to the real meat. |
1605 */ | 1614 */ |
1606 len = GET_32BIT(ciphertext); | 1615 len = toint(GET_32BIT(ciphertext)); |
1607 if (len > cipherlen-4) { | 1616 if (len < 0 || len > cipherlen-4) { |
1608 errmsg = "containing string was ill-formed"; | 1617 errmsg = "containing string was ill-formed"; |
1609 goto error; | 1618 goto error; |
1610 } | 1619 } |
1611 ciphertext += 4; | 1620 ciphertext += 4; |
1612 cipherlen = len; | 1621 cipherlen = len; |
1669 pos += put_mp(blob+pos, g.start, g.bytes); | 1678 pos += put_mp(blob+pos, g.start, g.bytes); |
1670 pos += put_mp(blob+pos, y.start, y.bytes); | 1679 pos += put_mp(blob+pos, y.start, y.bytes); |
1671 publen = pos; | 1680 publen = pos; |
1672 pos += put_mp(blob+pos, x.start, x.bytes); | 1681 pos += put_mp(blob+pos, x.start, x.bytes); |
1673 privlen = pos - publen; | 1682 privlen = pos - publen; |
1674 } | 1683 } else |
1684 return NULL; | |
1675 | 1685 |
1676 dropbear_assert(privlen > 0); /* should have bombed by now if not */ | 1686 dropbear_assert(privlen > 0); /* should have bombed by now if not */ |
1677 | 1687 |
1678 retkey = snew(struct ssh2_userkey); | 1688 retkey = snew(struct ssh2_userkey); |
1679 retkey->alg = alg; | 1689 retkey->alg = alg; |
1693 memset(blob, 0, blobsize); | 1703 memset(blob, 0, blobsize); |
1694 m_free(blob); | 1704 m_free(blob); |
1695 } | 1705 } |
1696 memset(key->keyblob, 0, key->keyblob_size); | 1706 memset(key->keyblob, 0, key->keyblob_size); |
1697 m_free(key->keyblob); | 1707 m_free(key->keyblob); |
1698 memset(&key, 0, sizeof(key)); | 1708 memset(key, 0, sizeof(*key)); |
1699 m_free(key); | 1709 m_free(key); |
1700 return ret; | 1710 return ret; |
1701 } | 1711 } |
1702 | 1712 |
1703 int sshcom_write(const char *filename, sign_key *key, | 1713 int sshcom_write(const char *filename, sign_key *key, |
1906 m_free(pubblob); | 1916 m_free(pubblob); |
1907 } | 1917 } |
1908 return ret; | 1918 return ret; |
1909 } | 1919 } |
1910 #endif /* ssh.com stuff disabled */ | 1920 #endif /* ssh.com stuff disabled */ |
1921 | |
1922 /* From PuTTY misc.c */ | |
1923 static int toint(unsigned u) | |
1924 { | |
1925 /* | |
1926 * Convert an unsigned to an int, without running into the | |
1927 * undefined behaviour which happens by the strict C standard if | |
1928 * the value overflows. You'd hope that sensible compilers would | |
1929 * do the sensible thing in response to a cast, but actually I | |
1930 * don't trust modern compilers not to do silly things like | |
1931 * assuming that _obviously_ you wouldn't have caused an overflow | |
1932 * and so they can elide an 'if (i < 0)' test immediately after | |
1933 * the cast. | |
1934 * | |
1935 * Sensible compilers ought of course to optimise this entire | |
1936 * function into 'just return the input value'! | |
1937 */ | |
1938 if (u <= (unsigned)INT_MAX) | |
1939 return (int)u; | |
1940 else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */ | |
1941 return INT_MIN + (int)(u - (unsigned)INT_MIN); | |
1942 else | |
1943 return INT_MIN; /* fallback; should never occur on binary machines */ | |
1944 } |