Mercurial > dropbear
comparison keyimport.c @ 640:76097ec1a29a dropbear-tfm
- Bring in original tomsfastmath patch against 0.52 from Peter Turczak
in 2008
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 21 Nov 2011 19:19:57 +0800 |
parents | 9dbc0c443497 |
children |
comparison
equal
deleted
inserted
replaced
518:ce104c8b0be1 | 640:76097ec1a29a |
---|---|
341 return len; | 341 return len; |
342 } | 342 } |
343 | 343 |
344 | 344 |
345 /* Simple structure to point to an mp-int within a blob. */ | 345 /* Simple structure to point to an mp-int within a blob. */ |
346 struct mpint_pos { void *start; int bytes; }; | 346 struct fpint_pos { void *start; int bytes; }; |
347 | 347 |
348 /* ---------------------------------------------------------------------- | 348 /* ---------------------------------------------------------------------- |
349 * Code to read and write OpenSSH private keys. | 349 * Code to read and write OpenSSH private keys. |
350 */ | 350 */ |
351 | 351 |
695 { | 695 { |
696 buffer * keyblob = NULL; | 696 buffer * keyblob = NULL; |
697 buffer * extrablob = NULL; /* used for calculated values to write */ | 697 buffer * extrablob = NULL; /* used for calculated values to write */ |
698 unsigned char *outblob = NULL; | 698 unsigned char *outblob = NULL; |
699 int outlen = -9999; | 699 int outlen = -9999; |
700 struct mpint_pos numbers[9]; | 700 struct fpint_pos numbers[9]; |
701 int nnumbers = -1, pos, len, seqlen, i; | 701 int nnumbers = -1, pos, len, seqlen, i; |
702 char *header = NULL, *footer = NULL; | 702 char *header = NULL, *footer = NULL; |
703 char zero[1]; | 703 char zero[1]; |
704 int ret = 0; | 704 int ret = 0; |
705 FILE *fp; | 705 FILE *fp; |
706 int keytype = -1; | 706 int keytype = -1; |
707 | 707 |
708 #ifdef DROPBEAR_RSA | 708 #ifdef DROPBEAR_RSA |
709 mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ | 709 fp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ |
710 | 710 |
711 if (key->rsakey != NULL) { | 711 if (key->rsakey != NULL) { |
712 keytype = DROPBEAR_SIGNKEY_RSA; | 712 keytype = DROPBEAR_SIGNKEY_RSA; |
713 } | 713 } |
714 #endif | 714 #endif |
768 numbers[5].bytes = buf_getint(keyblob); | 768 numbers[5].bytes = buf_getint(keyblob); |
769 numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); | 769 numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); |
770 buf_incrpos(keyblob, numbers[5].bytes); | 770 buf_incrpos(keyblob, numbers[5].bytes); |
771 | 771 |
772 /* now calculate some extra parameters: */ | 772 /* now calculate some extra parameters: */ |
773 m_mp_init(&tmpval); | 773 m_fp_init(&tmpval); |
774 m_mp_init(&dmp1); | 774 m_fp_init(&dmp1); |
775 m_mp_init(&dmq1); | 775 m_fp_init(&dmq1); |
776 m_mp_init(&iqmp); | 776 m_fp_init(&iqmp); |
777 | 777 |
778 /* dmp1 = d mod (p-1) */ | 778 /* dmp1 = d mod (p-1) */ |
779 if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) { | 779 fp_sub_d(key->rsakey->p, 1, &tmpval); |
780 fprintf(stderr, "Bignum error for p-1\n"); | 780 |
781 goto error; | 781 if (fp_mod(key->rsakey->d, &tmpval, &dmp1) != FP_OKAY) { |
782 } | |
783 if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) { | |
784 fprintf(stderr, "Bignum error for dmp1\n"); | 782 fprintf(stderr, "Bignum error for dmp1\n"); |
785 goto error; | 783 goto error; |
786 } | 784 } |
787 | 785 |
788 /* dmq1 = d mod (q-1) */ | 786 /* dmq1 = d mod (q-1) */ |
789 if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) { | 787 fp_sub_d(key->rsakey->q, 1, &tmpval); |
790 fprintf(stderr, "Bignum error for q-1\n"); | 788 |
791 goto error; | 789 if (fp_mod(key->rsakey->d, &tmpval, &dmq1) != FP_OKAY) { |
792 } | |
793 if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) { | |
794 fprintf(stderr, "Bignum error for dmq1\n"); | 790 fprintf(stderr, "Bignum error for dmq1\n"); |
795 goto error; | 791 goto error; |
796 } | 792 } |
797 | 793 |
798 /* iqmp = (q^-1) mod p */ | 794 /* iqmp = (q^-1) mod p */ |
799 if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) { | 795 if (fp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != FP_OKAY) { |
800 fprintf(stderr, "Bignum error for iqmp\n"); | 796 fprintf(stderr, "Bignum error for iqmp\n"); |
801 goto error; | 797 goto error; |
802 } | 798 } |
803 | 799 |
804 extrablob = buf_new(2000); | 800 extrablob = buf_new(2000); |
805 buf_putmpint(extrablob, &dmp1); | 801 buf_putfpint(extrablob, &dmp1); |
806 buf_putmpint(extrablob, &dmq1); | 802 buf_putfpint(extrablob, &dmq1); |
807 buf_putmpint(extrablob, &iqmp); | 803 buf_putfpint(extrablob, &iqmp); |
808 buf_setpos(extrablob, 0); | 804 buf_setpos(extrablob, 0); |
809 mp_clear(&dmp1); | 805 fp_zero(&dmp1); |
810 mp_clear(&dmq1); | 806 fp_zero(&dmq1); |
811 mp_clear(&iqmp); | 807 fp_zero(&iqmp); |
812 mp_clear(&tmpval); | 808 fp_zero(&tmpval); |
813 | 809 |
814 /* dmp1 */ | 810 /* dmp1 */ |
815 numbers[6].bytes = buf_getint(extrablob); | 811 numbers[6].bytes = buf_getint(extrablob); |
816 numbers[6].start = buf_getptr(extrablob, numbers[6].bytes); | 812 numbers[6].start = buf_getptr(extrablob, numbers[6].bytes); |
817 buf_incrpos(extrablob, numbers[6].bytes); | 813 buf_incrpos(extrablob, numbers[6].bytes); |
972 * Code to read ssh.com private keys. | 968 * Code to read ssh.com private keys. |
973 */ | 969 */ |
974 | 970 |
975 /* | 971 /* |
976 * The format of the base64 blob is largely ssh2-packet-formatted, | 972 * The format of the base64 blob is largely ssh2-packet-formatted, |
977 * except that mpints are a bit different: they're more like the | 973 * except that fpints are a bit different: they're more like the |
978 * old ssh1 mpint. You have a 32-bit bit count N, followed by | 974 * old ssh1 fpint. You have a 32-bit bit count N, followed by |
979 * (N+7)/8 bytes of data. | 975 * (N+7)/8 bytes of data. |
980 * | 976 * |
981 * So. The blob contains: | 977 * So. The blob contains: |
982 * | 978 * |
983 * - uint32 0x3f6ff9eb (magic number) | 979 * - uint32 0x3f6ff9eb (magic number) |
996 * added after that string while still making it clear where the | 992 * added after that string while still making it clear where the |
997 * real payload ends. Also it probably makes for a reasonable | 993 * real payload ends. Also it probably makes for a reasonable |
998 * decryption check.) | 994 * decryption check.) |
999 * | 995 * |
1000 * The payload blob, for an RSA key, contains: | 996 * The payload blob, for an RSA key, contains: |
1001 * - mpint e | 997 * - fpint e |
1002 * - mpint d | 998 * - fpint d |
1003 * - mpint n (yes, the public and private stuff is intermixed) | 999 * - fpint n (yes, the public and private stuff is intermixed) |
1004 * - mpint u (presumably inverse of p mod q) | 1000 * - fpint u (presumably inverse of p mod q) |
1005 * - mpint p (p is the smaller prime) | 1001 * - fpint p (p is the smaller prime) |
1006 * - mpint q (q is the larger) | 1002 * - fpint q (q is the larger) |
1007 * | 1003 * |
1008 * For a DSA key, the payload blob contains: | 1004 * For a DSA key, the payload blob contains: |
1009 * - uint32 0 | 1005 * - uint32 0 |
1010 * - mpint p | 1006 * - fpint p |
1011 * - mpint g | 1007 * - fpint g |
1012 * - mpint q | 1008 * - fpint q |
1013 * - mpint y | 1009 * - fpint y |
1014 * - mpint x | 1010 * - fpint x |
1015 * | 1011 * |
1016 * Alternatively, if the parameters are `predefined', that | 1012 * Alternatively, if the parameters are `predefined', that |
1017 * (0,p,g,q) sequence can be replaced by a uint32 1 and a string | 1013 * (0,p,g,q) sequence can be replaced by a uint32 1 and a string |
1018 * containing some predefined parameter specification. *shudder*, | 1014 * containing some predefined parameter specification. *shudder*, |
1019 * but I doubt we'll encounter this in real life. | 1015 * but I doubt we'll encounter this in real life. |
1207 memset(&key, 0, sizeof(key)); | 1203 memset(&key, 0, sizeof(key)); |
1208 m_free(key); | 1204 m_free(key); |
1209 return answer; | 1205 return answer; |
1210 } | 1206 } |
1211 | 1207 |
1212 static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) | 1208 static int sshcom_read_fpint(void *data, int len, struct fpint_pos *ret) |
1213 { | 1209 { |
1214 int bits; | 1210 int bits; |
1215 int bytes; | 1211 int bytes; |
1216 unsigned char *d = (unsigned char *) data; | 1212 unsigned char *d = (unsigned char *) data; |
1217 | 1213 |
1231 ret->start = NULL; | 1227 ret->start = NULL; |
1232 ret->bytes = -1; | 1228 ret->bytes = -1; |
1233 return len; /* ensure further calls fail as well */ | 1229 return len; /* ensure further calls fail as well */ |
1234 } | 1230 } |
1235 | 1231 |
1236 static int sshcom_put_mpint(void *target, void *data, int len) | 1232 static int sshcom_put_fpint(void *target, void *data, int len) |
1237 { | 1233 { |
1238 unsigned char *d = (unsigned char *)target; | 1234 unsigned char *d = (unsigned char *)target; |
1239 unsigned char *i = (unsigned char *)data; | 1235 unsigned char *i = (unsigned char *)data; |
1240 int bits = len * 8 - 1; | 1236 int bits = len * 8 - 1; |
1241 | 1237 |
1400 */ | 1396 */ |
1401 blobsize = cipherlen + 256; | 1397 blobsize = cipherlen + 256; |
1402 blob = snewn(blobsize, unsigned char); | 1398 blob = snewn(blobsize, unsigned char); |
1403 privlen = 0; | 1399 privlen = 0; |
1404 if (type == RSA) { | 1400 if (type == RSA) { |
1405 struct mpint_pos n, e, d, u, p, q; | 1401 struct fpint_pos n, e, d, u, p, q; |
1406 int pos = 0; | 1402 int pos = 0; |
1407 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &e); | 1403 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &e); |
1408 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &d); | 1404 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &d); |
1409 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &n); | 1405 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &n); |
1410 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &u); | 1406 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &u); |
1411 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p); | 1407 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &p); |
1412 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q); | 1408 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &q); |
1413 if (!q.start) { | 1409 if (!q.start) { |
1414 errmsg = "key data did not contain six integers"; | 1410 errmsg = "key data did not contain six integers"; |
1415 goto error; | 1411 goto error; |
1416 } | 1412 } |
1417 | 1413 |
1425 pos += put_mp(blob+pos, q.start, q.bytes); | 1421 pos += put_mp(blob+pos, q.start, q.bytes); |
1426 pos += put_mp(blob+pos, p.start, p.bytes); | 1422 pos += put_mp(blob+pos, p.start, p.bytes); |
1427 pos += put_mp(blob+pos, u.start, u.bytes); | 1423 pos += put_mp(blob+pos, u.start, u.bytes); |
1428 privlen = pos - publen; | 1424 privlen = pos - publen; |
1429 } else if (type == DSA) { | 1425 } else if (type == DSA) { |
1430 struct mpint_pos p, q, g, x, y; | 1426 struct fpint_pos p, q, g, x, y; |
1431 int pos = 4; | 1427 int pos = 4; |
1432 if (GET_32BIT(ciphertext) != 0) { | 1428 if (GET_32BIT(ciphertext) != 0) { |
1433 errmsg = "predefined DSA parameters not supported"; | 1429 errmsg = "predefined DSA parameters not supported"; |
1434 goto error; | 1430 goto error; |
1435 } | 1431 } |
1436 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &p); | 1432 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &p); |
1437 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &g); | 1433 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &g); |
1438 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &q); | 1434 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &q); |
1439 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &y); | 1435 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &y); |
1440 pos += sshcom_read_mpint(ciphertext+pos, cipherlen-pos, &x); | 1436 pos += sshcom_read_fpint(ciphertext+pos, cipherlen-pos, &x); |
1441 if (!x.start) { | 1437 if (!x.start) { |
1442 errmsg = "key data did not contain five integers"; | 1438 errmsg = "key data did not contain five integers"; |
1443 goto error; | 1439 goto error; |
1444 } | 1440 } |
1445 | 1441 |
1487 { | 1483 { |
1488 unsigned char *pubblob, *privblob; | 1484 unsigned char *pubblob, *privblob; |
1489 int publen, privlen; | 1485 int publen, privlen; |
1490 unsigned char *outblob; | 1486 unsigned char *outblob; |
1491 int outlen; | 1487 int outlen; |
1492 struct mpint_pos numbers[6]; | 1488 struct fpint_pos numbers[6]; |
1493 int nnumbers, initial_zero, pos, lenpos, i; | 1489 int nnumbers, initial_zero, pos, lenpos, i; |
1494 char *type; | 1490 char *type; |
1495 char *ciphertext; | 1491 char *ciphertext; |
1496 int cipherlen; | 1492 int cipherlen; |
1497 int ret = 0; | 1493 int ret = 0; |
1508 * Find the sequence of integers to be encoded into the OpenSSH | 1504 * Find the sequence of integers to be encoded into the OpenSSH |
1509 * key blob, and also decide on the header line. | 1505 * key blob, and also decide on the header line. |
1510 */ | 1506 */ |
1511 if (key->alg == &ssh_rsa) { | 1507 if (key->alg == &ssh_rsa) { |
1512 int pos; | 1508 int pos; |
1513 struct mpint_pos n, e, d, p, q, iqmp; | 1509 struct fpint_pos n, e, d, p, q, iqmp; |
1514 | 1510 |
1515 pos = 4 + GET_32BIT(pubblob); | 1511 pos = 4 + GET_32BIT(pubblob); |
1516 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e); | 1512 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &e); |
1517 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n); | 1513 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &n); |
1518 pos = 0; | 1514 pos = 0; |
1519 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d); | 1515 pos += ssh2_read_fpint(privblob+pos, privlen-pos, &d); |
1520 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p); | 1516 pos += ssh2_read_fpint(privblob+pos, privlen-pos, &p); |
1521 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q); | 1517 pos += ssh2_read_fpint(privblob+pos, privlen-pos, &q); |
1522 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp); | 1518 pos += ssh2_read_fpint(privblob+pos, privlen-pos, &iqmp); |
1523 | 1519 |
1524 dropbear_assert(e.start && iqmp.start); /* can't go wrong */ | 1520 dropbear_assert(e.start && iqmp.start); /* can't go wrong */ |
1525 | 1521 |
1526 numbers[0] = e; | 1522 numbers[0] = e; |
1527 numbers[1] = d; | 1523 numbers[1] = d; |
1533 nnumbers = 6; | 1529 nnumbers = 6; |
1534 initial_zero = 0; | 1530 initial_zero = 0; |
1535 type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}"; | 1531 type = "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}"; |
1536 } else if (key->alg == &ssh_dss) { | 1532 } else if (key->alg == &ssh_dss) { |
1537 int pos; | 1533 int pos; |
1538 struct mpint_pos p, q, g, y, x; | 1534 struct fpint_pos p, q, g, y, x; |
1539 | 1535 |
1540 pos = 4 + GET_32BIT(pubblob); | 1536 pos = 4 + GET_32BIT(pubblob); |
1541 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p); | 1537 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &p); |
1542 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q); | 1538 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &q); |
1543 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g); | 1539 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &g); |
1544 pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y); | 1540 pos += ssh2_read_fpint(pubblob+pos, publen-pos, &y); |
1545 pos = 0; | 1541 pos = 0; |
1546 pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x); | 1542 pos += ssh2_read_fpint(privblob+pos, privlen-pos, &x); |
1547 | 1543 |
1548 dropbear_assert(y.start && x.start); /* can't go wrong */ | 1544 dropbear_assert(y.start && x.start); /* can't go wrong */ |
1549 | 1545 |
1550 numbers[0] = p; | 1546 numbers[0] = p; |
1551 numbers[1] = g; | 1547 numbers[1] = g; |
1587 if (initial_zero) { | 1583 if (initial_zero) { |
1588 PUT_32BIT(outblob+pos, 0); | 1584 PUT_32BIT(outblob+pos, 0); |
1589 pos += 4; | 1585 pos += 4; |
1590 } | 1586 } |
1591 for (i = 0; i < nnumbers; i++) | 1587 for (i = 0; i < nnumbers; i++) |
1592 pos += sshcom_put_mpint(outblob+pos, | 1588 pos += sshcom_put_fpint(outblob+pos, |
1593 numbers[i].start, numbers[i].bytes); | 1589 numbers[i].start, numbers[i].bytes); |
1594 /* Now wrap up the encrypted payload. */ | 1590 /* Now wrap up the encrypted payload. */ |
1595 PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8)); | 1591 PUT_32BIT(outblob+lenpos+4, pos - (lenpos+8)); |
1596 /* Pad encrypted blob to a multiple of cipher block size. */ | 1592 /* Pad encrypted blob to a multiple of cipher block size. */ |
1597 if (passphrase) { | 1593 if (passphrase) { |