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) {