comparison keyimport.c @ 1733:d529a52b2f7c coverity coverity

merge coverity from main
author Matt Johnston <matt@ucc.asn.au>
date Fri, 26 Jun 2020 21:07:34 +0800
parents 1051e4eea25a
children 064f5be2fc45
comparison
equal deleted inserted replaced
1643:b59623a64678 1733:d529a52b2f7c
33 #include "keyimport.h" 33 #include "keyimport.h"
34 #include "bignum.h" 34 #include "bignum.h"
35 #include "buffer.h" 35 #include "buffer.h"
36 #include "dbutil.h" 36 #include "dbutil.h"
37 #include "ecc.h" 37 #include "ecc.h"
38 #include "ssh.h"
39 #include "rsa.h"
40 #include "dss.h"
41 #include "ed25519.h"
42
43 static const unsigned char OSSH_PKEY_BLOB[] =
44 "openssh-key-v1\0" /* AUTH_MAGIC */
45 "\0\0\0\4none" /* cipher name*/
46 "\0\0\0\4none" /* kdf name */
47 "\0\0\0\0" /* kdf */
48 "\0\0\0\1"; /* key num */
49 #define OSSH_PKEY_BLOBLEN (sizeof(OSSH_PKEY_BLOB) - 1)
38 50
39 #if DROPBEAR_ECDSA 51 #if DROPBEAR_ECDSA
40 static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; 52 static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
41 static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22}; 53 static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
42 static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23}; 54 static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
350 362
351 /* ---------------------------------------------------------------------- 363 /* ----------------------------------------------------------------------
352 * Code to read and write OpenSSH private keys. 364 * Code to read and write OpenSSH private keys.
353 */ 365 */
354 366
355 enum { OSSH_DSA, OSSH_RSA, OSSH_EC }; 367 enum { OSSH_DSA, OSSH_RSA, OSSH_EC, OSSH_PKEY };
356 struct openssh_key { 368 struct openssh_key {
357 int type; 369 int type;
358 int encrypted; 370 int encrypted;
359 char iv[32]; 371 char iv[32];
360 unsigned char *keyblob; 372 unsigned char *keyblob;
362 }; 374 };
363 375
364 static struct openssh_key *load_openssh_key(const char *filename) 376 static struct openssh_key *load_openssh_key(const char *filename)
365 { 377 {
366 struct openssh_key *ret; 378 struct openssh_key *ret;
379 buffer *buf = NULL;
367 FILE *fp = NULL; 380 FILE *fp = NULL;
368 char buffer[256]; 381 char buffer[256];
369 char *errmsg = NULL, *p = NULL; 382 char *errmsg = NULL, *p = NULL;
370 int headers_done; 383 int headers_done;
371 unsigned long len, outlen; 384 unsigned long len;
372 385
373 ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); 386 ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key));
374 ret->keyblob = NULL; 387 ret->keyblob = NULL;
375 ret->keyblob_len = ret->keyblob_size = 0; 388 ret->keyblob_len = ret->keyblob_size = 0;
376 ret->encrypted = 0; 389 ret->encrypted = 0;
395 ret->type = OSSH_RSA; 408 ret->type = OSSH_RSA;
396 else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n")) 409 else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
397 ret->type = OSSH_DSA; 410 ret->type = OSSH_DSA;
398 else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) 411 else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n"))
399 ret->type = OSSH_EC; 412 ret->type = OSSH_EC;
413 else if (!strcmp(buffer, "-----BEGIN OPENSSH PRIVATE KEY-----\n"))
414 ret->type = OSSH_PKEY;
400 else { 415 else {
401 errmsg = "Unrecognised key type"; 416 errmsg = "Unrecognised key type";
402 goto error; 417 goto error;
403 } 418 }
404 419
405 headers_done = 0; 420 headers_done = 0;
421 buf = buf_new(0);
406 while (1) { 422 while (1) {
407 if (!fgets(buffer, sizeof(buffer), fp)) { 423 if (!fgets(buffer, sizeof(buffer), fp)) {
408 errmsg = "Unexpected end of file"; 424 errmsg = "Unexpected end of file";
409 goto error; 425 goto error;
410 } 426 }
446 } 462 }
447 } 463 }
448 } else { 464 } else {
449 headers_done = 1; 465 headers_done = 1;
450 len = strlen(buffer); 466 len = strlen(buffer);
451 outlen = len*4/3; 467 buf = buf_resize(buf, buf->size + len);
452 if (ret->keyblob_len + outlen > ret->keyblob_size) { 468 buf_putbytes(buf, buffer, len);
453 ret->keyblob_size = ret->keyblob_len + outlen + 256; 469 }
454 ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, 470 }
455 ret->keyblob_size); 471
456 } 472 if (buf && buf->len) {
457 outlen = ret->keyblob_size - ret->keyblob_len; 473 ret->keyblob_size = ret->keyblob_len + buf->len*4/3 + 256;
458 if (base64_decode((const unsigned char *)buffer, len, 474 ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, ret->keyblob_size);
459 ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ 475 len = ret->keyblob_size;
460 errmsg = "Error decoding base64"; 476 if (base64_decode((const unsigned char *)buf->data, buf->len,
461 goto error; 477 ret->keyblob, &len) != CRYPT_OK){
462 } 478 errmsg = "Error decoding base64";
463 ret->keyblob_len += outlen; 479 goto error;
464 } 480 }
481 ret->keyblob_len = len;
482 }
483
484 if (ret->type == OSSH_PKEY) {
485 if (ret->keyblob_len < OSSH_PKEY_BLOBLEN ||
486 memcmp(ret->keyblob, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN)) {
487 errmsg = "Error decoding OpenSSH key";
488 goto error;
489 }
490 ret->keyblob_len -= OSSH_PKEY_BLOBLEN;
491 memmove(ret->keyblob, ret->keyblob + OSSH_PKEY_BLOBLEN, ret->keyblob_len);
465 } 492 }
466 493
467 if (ret->keyblob_len == 0 || !ret->keyblob) { 494 if (ret->keyblob_len == 0 || !ret->keyblob) {
468 errmsg = "Key body not present"; 495 errmsg = "Key body not present";
469 goto error; 496 goto error;
472 if (ret->encrypted && ret->keyblob_len % 8 != 0) { 499 if (ret->encrypted && ret->keyblob_len % 8 != 0) {
473 errmsg = "Encrypted key blob is not a multiple of cipher block size"; 500 errmsg = "Encrypted key blob is not a multiple of cipher block size";
474 goto error; 501 goto error;
475 } 502 }
476 503
504 if (buf) {
505 buf_burn(buf);
506 buf_free(buf);
507 }
477 m_burn(buffer, sizeof(buffer)); 508 m_burn(buffer, sizeof(buffer));
478 return ret; 509 return ret;
479 510
480 error: 511 error:
512 if (buf) {
513 buf_burn(buf);
514 buf_free(buf);
515 }
481 m_burn(buffer, sizeof(buffer)); 516 m_burn(buffer, sizeof(buffer));
482 if (ret) { 517 if (ret) {
483 if (ret->keyblob) { 518 if (ret->keyblob) {
484 m_burn(ret->keyblob, ret->keyblob_size); 519 m_burn(ret->keyblob, ret->keyblob_size);
485 m_free(ret->keyblob); 520 m_free(ret->keyblob);
565 key->keyblob, key->keyblob_len); 600 key->keyblob, key->keyblob_len);
566 601
567 memset(&md5c, 0, sizeof(md5c)); 602 memset(&md5c, 0, sizeof(md5c));
568 memset(keybuf, 0, sizeof(keybuf)); 603 memset(keybuf, 0, sizeof(keybuf));
569 #endif 604 #endif
605 }
606
607 /*
608 * Now we have a decrypted key blob, which contains OpenSSH
609 * encoded private key. We must now untangle the OpenSSH format.
610 */
611 if (key->type == OSSH_PKEY) {
612 blobbuf = buf_new(key->keyblob_len);
613 buf_putbytes(blobbuf, key->keyblob, key->keyblob_len);
614 buf_setpos(blobbuf, 0);
615
616 /* limit length of private key blob */
617 len = buf_getint(blobbuf);
618 buf_setlen(blobbuf, blobbuf->pos + len);
619
620 type = DROPBEAR_SIGNKEY_ANY;
621 if (buf_get_pub_key(blobbuf, retkey, &type)
622 != DROPBEAR_SUCCESS) {
623 errmsg = "Error parsing OpenSSH key";
624 goto ossh_error;
625 }
626
627 /* restore full length */
628 buf_setlen(blobbuf, key->keyblob_len);
629
630 if (type != DROPBEAR_SIGNKEY_NONE) {
631 retkey->type = type;
632 /* limit length of private key blob */
633 len = buf_getint(blobbuf);
634 buf_setlen(blobbuf, blobbuf->pos + len);
635 #if DROPBEAR_ED25519
636 if (type == DROPBEAR_SIGNKEY_ED25519) {
637 buf_incrpos(blobbuf, 8);
638 buf_eatstring(blobbuf);
639 buf_eatstring(blobbuf);
640 buf_incrpos(blobbuf, -SSH_SIGNKEY_ED25519_LEN-4);
641 if (buf_get_ed25519_priv_key(blobbuf, retkey->ed25519key)
642 == DROPBEAR_SUCCESS) {
643 errmsg = NULL;
644 retval = retkey;
645 goto error;
646 }
647 }
648 #endif
649 }
650
651 errmsg = "Unsupported OpenSSH key type";
652 ossh_error:
653 sign_key_free(retkey);
654 retkey = NULL;
655 goto error;
570 } 656 }
571 657
572 /* 658 /*
573 * Now we have a decrypted key blob, which contains an ASN.1 659 * Now we have a decrypted key blob, which contains an ASN.1
574 * encoded private key. We must now untangle the ASN.1. 660 * encoded private key. We must now untangle the ASN.1.
779 if (!ecc) { 865 if (!ecc) {
780 errmsg = "Error parsing ECC key"; 866 errmsg = "Error parsing ECC key";
781 goto error; 867 goto error;
782 } 868 }
783 m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL); 869 m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL);
784 if (mp_read_unsigned_bin(ecc->k, private_key_bytes, private_key_len) 870 if (mp_from_ubin(ecc->k, private_key_bytes, private_key_len)
785 != MP_OKAY) { 871 != MP_OKAY) {
786 errmsg = "Error parsing ECC key"; 872 errmsg = "Error parsing ECC key";
787 goto error; 873 goto error;
788 } 874 }
789 875
1054 int curve_oid_len = 0; 1140 int curve_oid_len = 0;
1055 const void* curve_oid = NULL; 1141 const void* curve_oid = NULL;
1056 unsigned long pubkey_size = 2*curve_size+1; 1142 unsigned long pubkey_size = 2*curve_size+1;
1057 int k_size; 1143 int k_size;
1058 int err = 0; 1144 int err = 0;
1145 size_t written;
1059 1146
1060 /* version. less than 10 bytes */ 1147 /* version. less than 10 bytes */
1061 buf_incrwritepos(seq_buf, 1148 buf_incrwritepos(seq_buf,
1062 ber_write_id_len(buf_getwriteptr(seq_buf, 10), 2, 1, 0)); 1149 ber_write_id_len(buf_getwriteptr(seq_buf, 10), 2, 1, 0));
1063 buf_putbyte(seq_buf, 1); 1150 buf_putbyte(seq_buf, 1);
1064 1151
1065 /* privateKey */ 1152 /* privateKey */
1066 k_size = mp_unsigned_bin_size((*eck)->k); 1153 k_size = mp_ubin_size((*eck)->k);
1067 dropbear_assert(k_size <= curve_size); 1154 dropbear_assert(k_size <= curve_size);
1068 buf_incrwritepos(seq_buf, 1155 buf_incrwritepos(seq_buf,
1069 ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, k_size, 0)); 1156 ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, k_size, 0));
1070 mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, k_size)); 1157 if (mp_to_ubin((*eck)->k, buf_getwriteptr(seq_buf, k_size), k_size, &written) != MP_OKAY) {
1071 buf_incrwritepos(seq_buf, k_size); 1158 dropbear_exit("ECC error");
1159 }
1160 buf_incrwritepos(seq_buf, written);
1072 1161
1073 /* SECGCurveNames */ 1162 /* SECGCurveNames */
1074 switch (key->type) 1163 switch (key->type)
1075 { 1164 {
1076 case DROPBEAR_SIGNKEY_ECDSA_NISTP256: 1165 case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
1124 buf_free(seq_buf); 1213 buf_free(seq_buf);
1125 seq_buf = NULL; 1214 seq_buf = NULL;
1126 1215
1127 header = "-----BEGIN EC PRIVATE KEY-----\n"; 1216 header = "-----BEGIN EC PRIVATE KEY-----\n";
1128 footer = "-----END EC PRIVATE KEY-----\n"; 1217 footer = "-----END EC PRIVATE KEY-----\n";
1218 }
1219 #endif
1220
1221 #if DROPBEAR_ED25519
1222 if (key->type == DROPBEAR_SIGNKEY_ED25519) {
1223 buffer *buf = buf_new(300);
1224 keyblob = buf_new(100);
1225 extrablob = buf_new(200);
1226
1227 /* private key blob w/o header */
1228 buf_put_priv_key(keyblob, key, key->type);
1229 buf_setpos(keyblob, 0);
1230 buf_incrpos(keyblob, buf_getint(keyblob));
1231 len = buf_getint(keyblob);
1232
1233 /* header */
1234 buf_putbytes(buf, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN);
1235
1236 /* public key */
1237 buf_put_pub_key(buf, key, key->type);
1238
1239 /* private key */
1240 buf_incrwritepos(extrablob, 4);
1241 buf_put_pub_key(extrablob, key, key->type);
1242 buf_putstring(extrablob, buf_getptr(keyblob, len), len);
1243 /* comment */
1244 buf_putstring(extrablob, "", 0);
1245 /* padding to cipher block length */
1246 len = (extrablob->len+8) & ~7;
1247 for (i = 1; len - extrablob->len > 0; i++)
1248 buf_putbyte(extrablob, i);
1249 buf_setpos(extrablob, 0);
1250 buf_putbytes(extrablob, "\0\0\0\0\0\0\0\0", 8);
1251 buf_putbufstring(buf, extrablob);
1252
1253 outlen = len = pos = buf->len;
1254 outblob = (unsigned char*)m_malloc(outlen);
1255 memcpy(outblob, buf->data, buf->len);
1256
1257 buf_burn(buf);
1258 buf_free(buf);
1259 buf = NULL;
1260
1261 header = "-----BEGIN OPENSSH PRIVATE KEY-----\n";
1262 footer = "-----END OPENSSH PRIVATE KEY-----\n";
1129 } 1263 }
1130 #endif 1264 #endif
1131 1265
1132 /* 1266 /*
1133 * Padding on OpenSSH keys is deterministic. The number of 1267 * Padding on OpenSSH keys is deterministic. The number of