keyimport.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. /*
  2. * Based on PuTTY's import.c for importing/exporting OpenSSH and SSH.com
  3. * keyfiles.
  4. *
  5. * Modifications copyright 2003-2022 Matt Johnston
  6. *
  7. * PuTTY is copyright 1997-2003 Simon Tatham.
  8. *
  9. * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
  10. * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
  11. * Justin Bradford, and CORE SDI S.A.
  12. *
  13. * Permission is hereby granted, free of charge, to any person
  14. * obtaining a copy of this software and associated documentation files
  15. * (the "Software"), to deal in the Software without restriction,
  16. * including without limitation the rights to use, copy, modify, merge,
  17. * publish, distribute, sublicense, and/or sell copies of the Software,
  18. * and to permit persons to whom the Software is furnished to do so,
  19. * subject to the following conditions:
  20. *
  21. * The above copyright notice and this permission notice shall be
  22. * included in all copies or substantial portions of the Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
  28. * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  29. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. */
  32. #include "keyimport.h"
  33. #include "bignum.h"
  34. #include "buffer.h"
  35. #include "dbutil.h"
  36. #include "ecc.h"
  37. #include "ssh.h"
  38. #include "rsa.h"
  39. #include "dss.h"
  40. #include "ed25519.h"
  41. #include "ecdsa.h"
  42. #include "signkey_ossh.h"
  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)
  50. #if DROPBEAR_ECDSA
  51. static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
  52. static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
  53. static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
  54. #endif
  55. #define PUT_32BIT(cp, value) do { \
  56. (cp)[3] = (unsigned char)(value); \
  57. (cp)[2] = (unsigned char)((value) >> 8); \
  58. (cp)[1] = (unsigned char)((value) >> 16); \
  59. (cp)[0] = (unsigned char)((value) >> 24); } while (0)
  60. #define GET_32BIT(cp) \
  61. (((unsigned long)(unsigned char)(cp)[0] << 24) | \
  62. ((unsigned long)(unsigned char)(cp)[1] << 16) | \
  63. ((unsigned long)(unsigned char)(cp)[2] << 8) | \
  64. ((unsigned long)(unsigned char)(cp)[3]))
  65. static int openssh_encrypted(const char *filename);
  66. static sign_key *openssh_read(const char *filename, const char *passphrase);
  67. static int openssh_write(const char *filename, sign_key *key,
  68. const char *passphrase);
  69. static int dropbear_write(const char*filename, sign_key * key);
  70. static sign_key *dropbear_read(const char* filename);
  71. static int toint(unsigned u);
  72. #if 0
  73. static int sshcom_encrypted(const char *filename, char **comment);
  74. static struct ssh2_userkey *sshcom_read(const char *filename, char *passphrase);
  75. static int sshcom_write(const char *filename, struct ssh2_userkey *key,
  76. char *passphrase);
  77. #endif
  78. int import_encrypted(const char* filename, int filetype) {
  79. if (filetype == KEYFILE_OPENSSH) {
  80. return openssh_encrypted(filename);
  81. #if 0
  82. } else if (filetype == KEYFILE_SSHCOM) {
  83. return sshcom_encrypted(filename, NULL);
  84. #endif
  85. }
  86. return 0;
  87. }
  88. sign_key *import_read(const char *filename, const char *passphrase, int filetype) {
  89. if (filetype == KEYFILE_OPENSSH) {
  90. return openssh_read(filename, passphrase);
  91. } else if (filetype == KEYFILE_DROPBEAR) {
  92. return dropbear_read(filename);
  93. #if 0
  94. } else if (filetype == KEYFILE_SSHCOM) {
  95. return sshcom_read(filename, passphrase);
  96. #endif
  97. }
  98. return NULL;
  99. }
  100. int import_write(const char *filename, sign_key *key, const char *passphrase,
  101. int filetype) {
  102. if (filetype == KEYFILE_OPENSSH) {
  103. return openssh_write(filename, key, passphrase);
  104. } else if (filetype == KEYFILE_DROPBEAR) {
  105. return dropbear_write(filename, key);
  106. #if 0
  107. } else if (filetype == KEYFILE_SSHCOM) {
  108. return sshcom_write(filename, key, passphrase);
  109. #endif
  110. }
  111. return 0;
  112. }
  113. static sign_key *dropbear_read(const char* filename) {
  114. buffer * buf = NULL;
  115. sign_key *ret = NULL;
  116. enum signkey_type type;
  117. buf = buf_new(MAX_PRIVKEY_SIZE);
  118. if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
  119. goto error;
  120. }
  121. buf_setpos(buf, 0);
  122. ret = new_sign_key();
  123. type = DROPBEAR_SIGNKEY_ANY;
  124. if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){
  125. goto error;
  126. }
  127. buf_free(buf);
  128. ret->type = type;
  129. return ret;
  130. error:
  131. if (buf) {
  132. buf_free(buf);
  133. }
  134. if (ret) {
  135. sign_key_free(ret);
  136. }
  137. return NULL;
  138. }
  139. /* returns 0 on fail, 1 on success */
  140. static int dropbear_write(const char*filename, sign_key * key) {
  141. buffer * buf;
  142. FILE*fp;
  143. int len;
  144. int ret;
  145. buf = buf_new(MAX_PRIVKEY_SIZE);
  146. buf_put_priv_key(buf, key, key->type);
  147. fp = fopen(filename, "w");
  148. if (!fp) {
  149. ret = 0;
  150. goto out;
  151. }
  152. buf_setpos(buf, 0);
  153. do {
  154. len = fwrite(buf_getptr(buf, buf->len - buf->pos),
  155. 1, buf->len - buf->pos, fp);
  156. buf_incrpos(buf, len);
  157. } while (len > 0 && buf->len != buf->pos);
  158. fclose(fp);
  159. if (buf->pos != buf->len) {
  160. ret = 0;
  161. } else {
  162. ret = 1;
  163. }
  164. out:
  165. buf_free(buf);
  166. return ret;
  167. }
  168. /* ----------------------------------------------------------------------
  169. * Helper routines. (The base64 ones are defined in sshpubk.c.)
  170. */
  171. #define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
  172. ((c) >= 'a' && (c) <= 'z') || \
  173. ((c) >= '0' && (c) <= '9') || \
  174. (c) == '+' || (c) == '/' || (c) == '=' \
  175. )
  176. /* cpl has to be less than 100 */
  177. static void base64_encode_fp(FILE * fp, const unsigned char *data,
  178. int datalen, int cpl)
  179. {
  180. unsigned char out[100];
  181. int n;
  182. unsigned long outlen;
  183. int rawcpl;
  184. rawcpl = cpl * 3 / 4;
  185. dropbear_assert((unsigned int)cpl < sizeof(out));
  186. while (datalen > 0) {
  187. n = (datalen < rawcpl ? datalen : rawcpl);
  188. outlen = sizeof(out);
  189. base64_encode(data, n, out, &outlen);
  190. data += n;
  191. datalen -= n;
  192. fwrite(out, 1, outlen, fp);
  193. fputc('\n', fp);
  194. }
  195. }
  196. /*
  197. * Read an ASN.1/BER identifier and length pair.
  198. *
  199. * Flags are a combination of the #defines listed below.
  200. *
  201. * Returns -1 if unsuccessful; otherwise returns the number of
  202. * bytes used out of the source data.
  203. */
  204. /* ASN.1 tag classes. */
  205. #define ASN1_CLASS_UNIVERSAL (0 << 6)
  206. #define ASN1_CLASS_APPLICATION (1 << 6)
  207. #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
  208. #define ASN1_CLASS_PRIVATE (3 << 6)
  209. #define ASN1_CLASS_MASK (3 << 6)
  210. /* Primitive versus constructed bit. */
  211. #define ASN1_CONSTRUCTED (1 << 5)
  212. static int ber_read_id_len(void *source, int sourcelen,
  213. int *id, int *length, int *flags)
  214. {
  215. unsigned char *p = (unsigned char *) source;
  216. if (sourcelen == 0)
  217. return -1;
  218. *flags = (*p & 0xE0);
  219. if ((*p & 0x1F) == 0x1F) {
  220. *id = 0;
  221. while (*p & 0x80) {
  222. p++, sourcelen--;
  223. if (sourcelen == 0)
  224. return -1;
  225. *id = (*id << 7) | (*p & 0x7F);
  226. }
  227. p++, sourcelen--;
  228. } else {
  229. *id = *p & 0x1F;
  230. p++, sourcelen--;
  231. }
  232. if (sourcelen == 0)
  233. return -1;
  234. if (*p & 0x80) {
  235. unsigned len;
  236. int n = *p & 0x7F;
  237. p++, sourcelen--;
  238. if (sourcelen < n)
  239. return -1;
  240. len = 0;
  241. while (n--)
  242. len = (len << 8) | (*p++);
  243. sourcelen -= n;
  244. *length = toint(len);
  245. } else {
  246. *length = *p;
  247. p++, sourcelen--;
  248. }
  249. if (*length < 0) {
  250. printf("Negative ASN.1 length\n");
  251. return -1;
  252. }
  253. return p - (unsigned char *) source;
  254. }
  255. /*
  256. * Write an ASN.1/BER identifier and length pair. Returns the
  257. * number of bytes consumed. Assumes dest contains enough space.
  258. * Will avoid writing anything if dest is NULL, but still return
  259. * amount of space required.
  260. */
  261. static int ber_write_id_len(void *dest, int id, int length, int flags)
  262. {
  263. unsigned char *d = (unsigned char *)dest;
  264. int len = 0;
  265. if (id <= 30) {
  266. /*
  267. * Identifier is one byte.
  268. */
  269. len++;
  270. if (d) *d++ = id | flags;
  271. } else {
  272. int n;
  273. /*
  274. * Identifier is multiple bytes: the first byte is 11111
  275. * plus the flags, and subsequent bytes encode the value of
  276. * the identifier, 7 bits at a time, with the top bit of
  277. * each byte 1 except the last one which is 0.
  278. */
  279. len++;
  280. if (d) *d++ = 0x1F | flags;
  281. for (n = 1; (id >> (7*n)) > 0; n++)
  282. continue; /* count the bytes */
  283. while (n--) {
  284. len++;
  285. if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F);
  286. }
  287. }
  288. if (length < 128) {
  289. /*
  290. * Length is one byte.
  291. */
  292. len++;
  293. if (d) *d++ = length;
  294. } else {
  295. int n;
  296. /*
  297. * Length is multiple bytes. The first is 0x80 plus the
  298. * number of subsequent bytes, and the subsequent bytes
  299. * encode the actual length.
  300. */
  301. for (n = 1; (length >> (8*n)) > 0; n++)
  302. continue; /* count the bytes */
  303. len++;
  304. if (d) *d++ = 0x80 | n;
  305. while (n--) {
  306. len++;
  307. if (d) *d++ = (length >> (8*n)) & 0xFF;
  308. }
  309. }
  310. return len;
  311. }
  312. /* Simple structure to point to an mp-int within a blob. */
  313. struct mpint_pos { void *start; int bytes; };
  314. /* ----------------------------------------------------------------------
  315. * Code to read and write OpenSSH private keys.
  316. */
  317. enum { OSSH_DSA, OSSH_RSA, OSSH_EC, OSSH_PKEY };
  318. struct openssh_key {
  319. int type;
  320. int encrypted;
  321. char iv[32];
  322. /* keyblob is publickey1 onwards (ref OpenSSH PROTOCOL.key) */
  323. unsigned char *keyblob;
  324. unsigned int keyblob_len, keyblob_size;
  325. };
  326. static struct openssh_key *load_openssh_key(const char *filename)
  327. {
  328. struct openssh_key *ret;
  329. buffer *buf = NULL;
  330. FILE *fp = NULL;
  331. char buffer[256];
  332. char *errmsg = NULL, *p = NULL;
  333. int headers_done;
  334. unsigned long len;
  335. ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key));
  336. ret->keyblob = NULL;
  337. ret->keyblob_len = ret->keyblob_size = 0;
  338. ret->encrypted = 0;
  339. memset(ret->iv, 0, sizeof(ret->iv));
  340. if (strlen(filename) == 1 && filename[0] == '-') {
  341. fp = stdin;
  342. } else {
  343. fp = fopen(filename, "r");
  344. }
  345. if (!fp) {
  346. errmsg = "Unable to open key file";
  347. goto error;
  348. }
  349. if (!fgets(buffer, sizeof(buffer), fp) ||
  350. 0 != strncmp(buffer, "-----BEGIN ", 11) ||
  351. 0 != strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) {
  352. errmsg = "File does not begin with OpenSSH key header";
  353. goto error;
  354. }
  355. if (!strcmp(buffer, "-----BEGIN RSA PRIVATE KEY-----\n"))
  356. ret->type = OSSH_RSA;
  357. else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
  358. ret->type = OSSH_DSA;
  359. else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n"))
  360. ret->type = OSSH_EC;
  361. else if (!strcmp(buffer, "-----BEGIN OPENSSH PRIVATE KEY-----\n"))
  362. ret->type = OSSH_PKEY;
  363. else {
  364. errmsg = "Unrecognised key type";
  365. goto error;
  366. }
  367. headers_done = 0;
  368. buf = buf_new(0);
  369. while (1) {
  370. if (!fgets(buffer, sizeof(buffer), fp)) {
  371. errmsg = "Unexpected end of file";
  372. goto error;
  373. }
  374. if (0 == strncmp(buffer, "-----END ", 9) &&
  375. 0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
  376. break; /* done */
  377. if ((p = strchr(buffer, ':')) != NULL) {
  378. if (headers_done) {
  379. errmsg = "Header found in body of key data";
  380. goto error;
  381. }
  382. *p++ = '\0';
  383. while (*p && isspace((unsigned char)*p)) p++;
  384. if (!strcmp(buffer, "Proc-Type")) {
  385. if (p[0] != '4' || p[1] != ',') {
  386. errmsg = "Proc-Type is not 4 (only 4 is supported)";
  387. goto error;
  388. }
  389. p += 2;
  390. if (!strcmp(p, "ENCRYPTED\n"))
  391. ret->encrypted = 1;
  392. } else if (!strcmp(buffer, "DEK-Info")) {
  393. int i, j;
  394. if (strncmp(p, "DES-EDE3-CBC,", 13)) {
  395. errmsg = "Ciphers other than DES-EDE3-CBC not supported";
  396. goto error;
  397. }
  398. p += 13;
  399. for (i = 0; i < 8; i++) {
  400. if (1 != sscanf(p, "%2x", &j))
  401. break;
  402. ret->iv[i] = j;
  403. p += 2;
  404. }
  405. if (i < 8) {
  406. errmsg = "Expected 16-digit iv in DEK-Info";
  407. goto error;
  408. }
  409. }
  410. } else {
  411. headers_done = 1;
  412. len = strlen(buffer);
  413. buf = buf_resize(buf, buf->size + len);
  414. buf_putbytes(buf, buffer, len);
  415. }
  416. }
  417. if (buf && buf->len) {
  418. ret->keyblob_size = ret->keyblob_len + buf->len*4/3 + 256;
  419. ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, ret->keyblob_size);
  420. len = ret->keyblob_size;
  421. if (base64_decode((const unsigned char *)buf->data, buf->len,
  422. ret->keyblob, &len) != CRYPT_OK){
  423. errmsg = "Error decoding base64";
  424. goto error;
  425. }
  426. ret->keyblob_len = len;
  427. }
  428. if (ret->type == OSSH_PKEY) {
  429. if (ret->keyblob_len < OSSH_PKEY_BLOBLEN ||
  430. memcmp(ret->keyblob, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN)) {
  431. errmsg = "Error decoding OpenSSH key";
  432. goto error;
  433. }
  434. ret->keyblob_len -= OSSH_PKEY_BLOBLEN;
  435. memmove(ret->keyblob, ret->keyblob + OSSH_PKEY_BLOBLEN, ret->keyblob_len);
  436. }
  437. if (ret->keyblob_len == 0 || !ret->keyblob) {
  438. errmsg = "Key body not present";
  439. goto error;
  440. }
  441. if (ret->encrypted && ret->keyblob_len % 8 != 0) {
  442. errmsg = "Encrypted key blob is not a multiple of cipher block size";
  443. goto error;
  444. }
  445. if (buf) {
  446. buf_burn_free(buf);
  447. }
  448. m_burn(buffer, sizeof(buffer));
  449. return ret;
  450. error:
  451. if (buf) {
  452. buf_burn_free(buf);
  453. }
  454. m_burn(buffer, sizeof(buffer));
  455. if (ret) {
  456. if (ret->keyblob) {
  457. m_burn(ret->keyblob, ret->keyblob_size);
  458. m_free(ret->keyblob);
  459. }
  460. m_free(ret);
  461. }
  462. if (fp) {
  463. fclose(fp);
  464. }
  465. if (errmsg) {
  466. fprintf(stderr, "Error: %s\n", errmsg);
  467. }
  468. return NULL;
  469. }
  470. static int openssh_encrypted(const char *filename)
  471. {
  472. struct openssh_key *key = load_openssh_key(filename);
  473. int ret;
  474. if (!key)
  475. return 0;
  476. ret = key->encrypted;
  477. m_burn(key->keyblob, key->keyblob_size);
  478. m_free(key->keyblob);
  479. m_free(key);
  480. return ret;
  481. }
  482. static sign_key *openssh_read(const char *filename, const char * UNUSED(passphrase))
  483. {
  484. struct openssh_key *key;
  485. unsigned char *p;
  486. int ret, id, len, flags;
  487. int i, num_integers = 0;
  488. sign_key *retval = NULL;
  489. char *errmsg;
  490. unsigned char *modptr = NULL;
  491. int modlen = -9999;
  492. enum signkey_type type;
  493. sign_key *retkey;
  494. buffer * blobbuf = NULL;
  495. retkey = new_sign_key();
  496. key = load_openssh_key(filename);
  497. if (!key)
  498. return NULL;
  499. if (key->encrypted) {
  500. errmsg = "Encrypted keys are not supported. Please convert with ssh-keygen first";
  501. goto error;
  502. }
  503. /*
  504. * Now we have a decrypted key blob, which contains OpenSSH
  505. * encoded private key. We must now untangle the OpenSSH format.
  506. */
  507. if (key->type == OSSH_PKEY) {
  508. blobbuf = buf_new(key->keyblob_len);
  509. buf_putbytes(blobbuf, key->keyblob, key->keyblob_len);
  510. buf_setpos(blobbuf, 0);
  511. /* limit length of public key blob */
  512. len = buf_getint(blobbuf);
  513. type = DROPBEAR_SIGNKEY_ANY;
  514. if (buf_get_pub_key(blobbuf, retkey, &type)
  515. != DROPBEAR_SUCCESS) {
  516. errmsg = "Error parsing OpenSSH key";
  517. goto ossh_error;
  518. }
  519. /* restore full length */
  520. buf_setlen(blobbuf, key->keyblob_len);
  521. /* length of private key part. we can discard it */
  522. buf_getint(blobbuf);
  523. /* discard checkkey1 */
  524. buf_getint(blobbuf);
  525. /* discard checkkey2 */
  526. buf_getint(blobbuf);
  527. errmsg = "Unsupported OpenSSH key type";
  528. retkey->type = type;
  529. ret = DROPBEAR_FAILURE;
  530. /* Parse private key part */
  531. #if DROPBEAR_RSA
  532. if (type == DROPBEAR_SIGNKEY_RSA) {
  533. errmsg = "Error parsing OpenSSH RSA key";
  534. ret = buf_get_rsa_priv_ossh(blobbuf, retkey);
  535. }
  536. #endif
  537. #if DROPBEAR_ED25519
  538. if (type == DROPBEAR_SIGNKEY_ED25519) {
  539. errmsg = "Error parsing OpenSSH ed25519 key";
  540. ret = buf_get_ed25519_priv_ossh(blobbuf, retkey);
  541. }
  542. #endif
  543. #if DROPBEAR_ECDSA
  544. if (signkey_is_ecdsa(type)) {
  545. errmsg = "Error parsing OpenSSH ecdsa key";
  546. ret = buf_get_ecdsa_priv_ossh(blobbuf, retkey);
  547. }
  548. #endif
  549. if (ret == DROPBEAR_SUCCESS) {
  550. errmsg = NULL;
  551. retval = retkey;
  552. goto error;
  553. }
  554. ossh_error:
  555. sign_key_free(retkey);
  556. retkey = NULL;
  557. goto error;
  558. }
  559. /*
  560. * Now we have a decrypted key blob, which contains an ASN.1
  561. * encoded private key. We must now untangle the ASN.1.
  562. *
  563. * We expect the whole key blob to be formatted as a SEQUENCE
  564. * (0x30 followed by a length code indicating that the rest of
  565. * the blob is part of the sequence). Within that SEQUENCE we
  566. * expect to see a bunch of INTEGERs. What those integers mean
  567. * depends on the key type:
  568. *
  569. * - For RSA, we expect the integers to be 0, n, e, d, p, q,
  570. * dmp1, dmq1, iqmp in that order. (The last three are d mod
  571. * (p-1), d mod (q-1), inverse of q mod p respectively.)
  572. *
  573. * - For DSA, we expect them to be 0, p, q, g, y, x in that
  574. * order.
  575. */
  576. p = key->keyblob;
  577. /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
  578. ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
  579. p += ret;
  580. if (ret < 0 || id != 16 || len < 0 ||
  581. key->keyblob+key->keyblob_len-p < len) {
  582. errmsg = "ASN.1 decoding failure";
  583. goto error;
  584. }
  585. /* Expect a load of INTEGERs. */
  586. if (key->type == OSSH_RSA)
  587. num_integers = 9;
  588. else if (key->type == OSSH_DSA)
  589. num_integers = 6;
  590. else if (key->type == OSSH_EC)
  591. num_integers = 1;
  592. /*
  593. * Space to create key blob in.
  594. */
  595. blobbuf = buf_new(3000);
  596. #if DROPBEAR_DSS
  597. if (key->type == OSSH_DSA) {
  598. buf_putstring(blobbuf, "ssh-dss", 7);
  599. retkey->type = DROPBEAR_SIGNKEY_DSS;
  600. }
  601. #endif
  602. #if DROPBEAR_RSA
  603. if (key->type == OSSH_RSA) {
  604. buf_putstring(blobbuf, "ssh-rsa", 7);
  605. retkey->type = DROPBEAR_SIGNKEY_RSA;
  606. }
  607. #endif
  608. for (i = 0; i < num_integers; i++) {
  609. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  610. &id, &len, &flags);
  611. p += ret;
  612. if (ret < 0 || id != 2 || len < 0 ||
  613. key->keyblob+key->keyblob_len-p < len) {
  614. errmsg = "ASN.1 decoding failure";
  615. goto error;
  616. }
  617. if (i == 0) {
  618. /* First integer is a version indicator */
  619. int expected = -1;
  620. switch (key->type) {
  621. case OSSH_RSA:
  622. case OSSH_DSA:
  623. expected = 0;
  624. break;
  625. case OSSH_EC:
  626. expected = 1;
  627. break;
  628. }
  629. if (len != 1 || p[0] != expected) {
  630. errmsg = "Version number mismatch";
  631. goto error;
  632. }
  633. } else if (key->type == OSSH_RSA) {
  634. /*
  635. * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp
  636. * but we want e, n, d, p, q
  637. */
  638. if (i == 1) {
  639. /* Save the details for after we deal with number 2. */
  640. modptr = p;
  641. modlen = len;
  642. } else if (i >= 2 && i <= 5) {
  643. buf_putstring(blobbuf, (const char*)p, len);
  644. if (i == 2) {
  645. buf_putstring(blobbuf, (const char*)modptr, modlen);
  646. }
  647. }
  648. } else if (key->type == OSSH_DSA) {
  649. /*
  650. * OpenSSH key order is p, q, g, y, x,
  651. * we want the same.
  652. */
  653. buf_putstring(blobbuf, (const char*)p, len);
  654. }
  655. /* Skip past the number. */
  656. p += len;
  657. }
  658. #if DROPBEAR_ECDSA
  659. if (key->type == OSSH_EC) {
  660. unsigned char* private_key_bytes = NULL;
  661. int private_key_len = 0;
  662. unsigned char* public_key_bytes = NULL;
  663. int public_key_len = 0;
  664. ecc_key *ecc = NULL;
  665. const struct dropbear_ecc_curve *curve = NULL;
  666. /* See SEC1 v2, Appendix C.4 */
  667. /* OpenSSL (so OpenSSH) seems to include the optional parts. */
  668. /* privateKey OCTET STRING, */
  669. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  670. &id, &len, &flags);
  671. p += ret;
  672. /* id==4 for octet string */
  673. if (ret < 0 || id != 4 || len < 0 ||
  674. key->keyblob+key->keyblob_len-p < len) {
  675. errmsg = "ASN.1 decoding failure";
  676. goto error;
  677. }
  678. private_key_bytes = p;
  679. private_key_len = len;
  680. p += len;
  681. /* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */
  682. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  683. &id, &len, &flags);
  684. p += ret;
  685. /* id==0 */
  686. if (ret < 0 || id != 0 || len < 0) {
  687. errmsg = "ASN.1 decoding failure";
  688. goto error;
  689. }
  690. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  691. &id, &len, &flags);
  692. p += ret;
  693. /* id==6 for object */
  694. if (ret < 0 || id != 6 || len < 0 ||
  695. key->keyblob+key->keyblob_len-p < len) {
  696. errmsg = "ASN.1 decoding failure";
  697. goto error;
  698. }
  699. if (0) {}
  700. #if DROPBEAR_ECC_256
  701. else if (len == sizeof(OID_SEC256R1_BLOB)
  702. && memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
  703. retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
  704. curve = &ecc_curve_nistp256;
  705. }
  706. #endif
  707. #if DROPBEAR_ECC_384
  708. else if (len == sizeof(OID_SEC384R1_BLOB)
  709. && memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
  710. retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
  711. curve = &ecc_curve_nistp384;
  712. }
  713. #endif
  714. #if DROPBEAR_ECC_521
  715. else if (len == sizeof(OID_SEC521R1_BLOB)
  716. && memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
  717. retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
  718. curve = &ecc_curve_nistp521;
  719. }
  720. #endif
  721. else {
  722. errmsg = "Unknown ECC key type";
  723. goto error;
  724. }
  725. p += len;
  726. /* publicKey [1] BIT STRING OPTIONAL */
  727. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  728. &id, &len, &flags);
  729. p += ret;
  730. /* id==1 */
  731. if (ret < 0 || id != 1 || len < 0) {
  732. errmsg = "ASN.1 decoding failure";
  733. goto error;
  734. }
  735. ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
  736. &id, &len, &flags);
  737. p += ret;
  738. /* id==3 for bit string */
  739. if (ret < 0 || id != 3 || len < 0 ||
  740. key->keyblob+key->keyblob_len-p < len) {
  741. errmsg = "ASN.1 decoding failure";
  742. goto error;
  743. }
  744. public_key_bytes = p+1;
  745. public_key_len = len-1;
  746. p += len;
  747. buf_putbytes(blobbuf, public_key_bytes, public_key_len);
  748. ecc = buf_get_ecc_raw_pubkey(blobbuf, curve);
  749. if (!ecc) {
  750. errmsg = "Error parsing ECC key";
  751. goto error;
  752. }
  753. m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL);
  754. if (mp_from_ubin(ecc->k, private_key_bytes, private_key_len)
  755. != MP_OKAY) {
  756. errmsg = "Error parsing ECC key";
  757. goto error;
  758. }
  759. *signkey_key_ptr(retkey, retkey->type) = ecc;
  760. }
  761. #endif /* DROPBEAR_ECDSA */
  762. /*
  763. * Now put together the actual key. Simplest way to do this is
  764. * to assemble our own key blobs and feed them to the createkey
  765. * functions; this is a bit faffy but it does mean we get all
  766. * the sanity checks for free.
  767. */
  768. if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
  769. buf_setpos(blobbuf, 0);
  770. type = DROPBEAR_SIGNKEY_ANY;
  771. if (buf_get_priv_key(blobbuf, retkey, &type)
  772. != DROPBEAR_SUCCESS) {
  773. errmsg = "unable to create key structure";
  774. sign_key_free(retkey);
  775. retkey = NULL;
  776. goto error;
  777. }
  778. }
  779. errmsg = NULL; /* no error */
  780. retval = retkey;
  781. error:
  782. if (blobbuf) {
  783. buf_burn_free(blobbuf);
  784. }
  785. m_burn(key->keyblob, key->keyblob_size);
  786. m_free(key->keyblob);
  787. m_burn(key, sizeof(*key));
  788. m_free(key);
  789. if (errmsg) {
  790. fprintf(stderr, "Error: %s\n", errmsg);
  791. }
  792. return retval;
  793. }
  794. static int openssh_write(const char *filename, sign_key *key,
  795. const char *passphrase)
  796. {
  797. buffer * keyblob = NULL;
  798. buffer * extrablob = NULL; /* used for calculated values to write */
  799. unsigned char *outblob = NULL;
  800. int outlen = -9999;
  801. struct mpint_pos numbers[9];
  802. int nnumbers = -1, pos = 0, len = 0, seqlen, i;
  803. char *header = NULL, *footer = NULL;
  804. char zero[1];
  805. int ret = 0;
  806. FILE *fp;
  807. #if DROPBEAR_DSS
  808. if (key->type == DROPBEAR_SIGNKEY_DSS) {
  809. /*
  810. * Fetch the key blobs.
  811. */
  812. keyblob = buf_new(3000);
  813. buf_put_priv_key(keyblob, key, key->type);
  814. buf_setpos(keyblob, 0);
  815. /* skip the "ssh-rsa" or "ssh-dss" header */
  816. buf_incrpos(keyblob, buf_getint(keyblob));
  817. /*
  818. * Find the sequence of integers to be encoded into the OpenSSH
  819. * key blob, and also decide on the header line.
  820. */
  821. numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
  822. #if DROPBEAR_DSS
  823. if (key->type == DROPBEAR_SIGNKEY_DSS) {
  824. /* p */
  825. numbers[1].bytes = buf_getint(keyblob);
  826. numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
  827. buf_incrpos(keyblob, numbers[1].bytes);
  828. /* q */
  829. numbers[2].bytes = buf_getint(keyblob);
  830. numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
  831. buf_incrpos(keyblob, numbers[2].bytes);
  832. /* g */
  833. numbers[3].bytes = buf_getint(keyblob);
  834. numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
  835. buf_incrpos(keyblob, numbers[3].bytes);
  836. /* y */
  837. numbers[4].bytes = buf_getint(keyblob);
  838. numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
  839. buf_incrpos(keyblob, numbers[4].bytes);
  840. /* x */
  841. numbers[5].bytes = buf_getint(keyblob);
  842. numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
  843. buf_incrpos(keyblob, numbers[5].bytes);
  844. nnumbers = 6;
  845. header = "-----BEGIN DSA PRIVATE KEY-----\n";
  846. footer = "-----END DSA PRIVATE KEY-----\n";
  847. }
  848. #endif /* DROPBEAR_DSS */
  849. /*
  850. * Now count up the total size of the ASN.1 encoded integers,
  851. * so as to determine the length of the containing SEQUENCE.
  852. */
  853. len = 0;
  854. for (i = 0; i < nnumbers; i++) {
  855. len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
  856. len += numbers[i].bytes;
  857. }
  858. seqlen = len;
  859. /* Now add on the SEQUENCE header. */
  860. len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
  861. /* Round up to the cipher block size, ensuring we have at least one
  862. * byte of padding (see below). */
  863. outlen = len;
  864. if (passphrase)
  865. outlen = (outlen+8) &~ 7;
  866. /*
  867. * Now we know how big outblob needs to be. Allocate it.
  868. */
  869. outblob = (unsigned char*)m_malloc(outlen);
  870. /*
  871. * And write the data into it.
  872. */
  873. pos = 0;
  874. pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
  875. for (i = 0; i < nnumbers; i++) {
  876. pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
  877. memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
  878. pos += numbers[i].bytes;
  879. }
  880. } /* end DSS handling */
  881. #endif /* DROPBEAR_DSS */
  882. if (0
  883. #if DROPBEAR_RSA
  884. || key->type == DROPBEAR_SIGNKEY_RSA
  885. #endif
  886. #if DROPBEAR_ED25519
  887. || key->type == DROPBEAR_SIGNKEY_ED25519
  888. #endif
  889. #if DROPBEAR_ECDSA
  890. || signkey_is_ecdsa(key->type)
  891. #endif
  892. ) {
  893. buffer *buf = buf_new(3200);
  894. keyblob = buf_new(3000);
  895. extrablob = buf_new(3100);
  896. /* private key blob w/o header */
  897. #if DROPBEAR_RSA
  898. if (key->type == DROPBEAR_SIGNKEY_RSA) {
  899. buf_put_rsa_priv_ossh(keyblob, key);
  900. }
  901. #endif
  902. #if DROPBEAR_ED25519
  903. if (key->type == DROPBEAR_SIGNKEY_ED25519) {
  904. buf_put_ed25519_priv_ossh(keyblob, key);
  905. }
  906. #endif
  907. #if DROPBEAR_ECDSA
  908. if (signkey_is_ecdsa(key->type)) {
  909. buf_put_ecdsa_priv_ossh(keyblob, key);
  910. }
  911. #endif
  912. /* header */
  913. buf_putbytes(buf, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN);
  914. /* public key */
  915. buf_put_pub_key(buf, key, key->type);
  916. /* private key */
  917. buf_putint(extrablob, 0); /* checkint 1 */
  918. buf_putint(extrablob, 0); /* checkint 2 */
  919. /* raw openssh private key */
  920. buf_putbytes(extrablob, keyblob->data, keyblob->len);
  921. /* comment */
  922. buf_putstring(extrablob, "", 0);
  923. /* padding to cipher block length */
  924. len = (extrablob->len+8) & ~7;
  925. for (i = 1; len - extrablob->len > 0; i++)
  926. buf_putbyte(extrablob, i);
  927. buf_setpos(extrablob, 0);
  928. buf_putbytes(extrablob, "\0\0\0\0\0\0\0\0", 8);
  929. buf_putbufstring(buf, extrablob);
  930. outlen = len = pos = buf->len;
  931. outblob = (unsigned char*)m_malloc(outlen);
  932. memcpy(outblob, buf->data, buf->len);
  933. buf_burn_free(buf);
  934. buf = NULL;
  935. header = "-----BEGIN OPENSSH PRIVATE KEY-----\n";
  936. footer = "-----END OPENSSH PRIVATE KEY-----\n";
  937. }
  938. /*
  939. * Padding on OpenSSH keys is deterministic. The number of
  940. * padding bytes is always more than zero, and always at most
  941. * the cipher block length. The value of each padding byte is
  942. * equal to the number of padding bytes. So a plaintext that's
  943. * an exact multiple of the block size will be padded with 08
  944. * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a
  945. * plaintext one byte less than a multiple of the block size
  946. * will be padded with just 01.
  947. *
  948. * This enables the OpenSSL key decryption function to strip
  949. * off the padding algorithmically and return the unpadded
  950. * plaintext to the next layer: it looks at the final byte, and
  951. * then expects to find that many bytes at the end of the data
  952. * with the same value. Those are all removed and the rest is
  953. * returned.
  954. */
  955. dropbear_assert(pos == len);
  956. while (pos < outlen) {
  957. outblob[pos++] = outlen - len;
  958. }
  959. /*
  960. * Encrypt the key.
  961. */
  962. if (passphrase) {
  963. fprintf(stderr, "Encrypted keys aren't supported currently\n");
  964. goto error;
  965. }
  966. /*
  967. * And save it. We'll use Unix line endings just in case it's
  968. * subsequently transferred in binary mode.
  969. */
  970. if (strlen(filename) == 1 && filename[0] == '-') {
  971. fp = stdout;
  972. } else {
  973. fp = fopen(filename, "wb"); /* ensure Unix line endings */
  974. }
  975. if (!fp) {
  976. fprintf(stderr, "Failed opening output file\n");
  977. goto error;
  978. }
  979. fputs(header, fp);
  980. base64_encode_fp(fp, outblob, outlen, 64);
  981. fputs(footer, fp);
  982. fclose(fp);
  983. ret = 1;
  984. error:
  985. if (outblob) {
  986. memset(outblob, 0, outlen);
  987. m_free(outblob);
  988. }
  989. if (keyblob) {
  990. buf_burn_free(keyblob);
  991. }
  992. if (extrablob) {
  993. buf_burn_free(extrablob);
  994. }
  995. return ret;
  996. }
  997. /* From PuTTY misc.c */
  998. static int toint(unsigned u)
  999. {
  1000. /*
  1001. * Convert an unsigned to an int, without running into the
  1002. * undefined behaviour which happens by the strict C standard if
  1003. * the value overflows. You'd hope that sensible compilers would
  1004. * do the sensible thing in response to a cast, but actually I
  1005. * don't trust modern compilers not to do silly things like
  1006. * assuming that _obviously_ you wouldn't have caused an overflow
  1007. * and so they can elide an 'if (i < 0)' test immediately after
  1008. * the cast.
  1009. *
  1010. * Sensible compilers ought of course to optimise this entire
  1011. * function into 'just return the input value'!
  1012. */
  1013. if (u <= (unsigned)INT_MAX)
  1014. return (int)u;
  1015. else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
  1016. return INT_MIN + (int)(u - (unsigned)INT_MIN);
  1017. else
  1018. return INT_MIN; /* fallback; should never occur on binary machines */
  1019. }