Annotation of src/usr.bin/ssh/sshkey.c, Revision 1.85
1.85 ! djm 1: /* $OpenBSD: sshkey.c,v 1.84 2019/10/09 00:04:42 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4: * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5: * Copyright (c) 2010,2011 Damien Miller. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
1.7 djm 29: #include <netinet/in.h>
1.1 djm 30:
1.12 djm 31: #ifdef WITH_OPENSSL
1.1 djm 32: #include <openssl/evp.h>
33: #include <openssl/err.h>
34: #include <openssl/pem.h>
1.12 djm 35: #endif
1.1 djm 36:
37: #include "crypto_api.h"
38:
39: #include <errno.h>
40: #include <stdio.h>
41: #include <string.h>
42: #include <util.h>
1.13 deraadt 43: #include <limits.h>
1.7 djm 44: #include <resolv.h>
1.1 djm 45:
46: #include "ssh2.h"
47: #include "ssherr.h"
48: #include "misc.h"
49: #include "sshbuf.h"
50: #include "cipher.h"
51: #include "digest.h"
52: #define SSHKEY_INTERNAL
53: #include "sshkey.h"
1.11 djm 54: #include "match.h"
1.1 djm 55:
1.74 dtucker 56: #ifdef WITH_XMSS
57: #include "sshkey-xmss.h"
1.62 markus 58: #include "xmss_fast.h"
1.74 dtucker 59: #endif
1.62 markus 60:
1.1 djm 61: /* openssh private key file format */
62: #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
63: #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
64: #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
65: #define MARK_END_LEN (sizeof(MARK_END) - 1)
66: #define KDFNAME "bcrypt"
67: #define AUTH_MAGIC "openssh-key-v1"
68: #define SALT_LEN 16
1.56 djm 69: #define DEFAULT_CIPHERNAME "aes256-ctr"
1.1 djm 70: #define DEFAULT_ROUNDS 16
71:
72: /* Version identification string for SSH v1 identity files. */
73: #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
74:
1.76 djm 75: /*
76: * Constants relating to "shielding" support; protection of keys expected
77: * to remain in memory for long durations
78: */
79: #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
80: #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
81: #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
82:
83: int sshkey_private_serialize_opt(struct sshkey *key,
1.62 markus 84: struct sshbuf *buf, enum sshkey_serialize_rep);
1.14 djm 85: static int sshkey_from_blob_internal(struct sshbuf *buf,
1.1 djm 86: struct sshkey **keyp, int allow_cert);
87:
88: /* Supported key types */
89: struct keytype {
90: const char *name;
91: const char *shortname;
1.65 djm 92: const char *sigalg;
1.1 djm 93: int type;
94: int nid;
95: int cert;
1.28 markus 96: int sigonly;
1.1 djm 97: };
98: static const struct keytype keytypes[] = {
1.65 djm 99: { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
100: { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
1.28 markus 101: KEY_ED25519_CERT, 0, 1, 0 },
1.62 markus 102: #ifdef WITH_XMSS
1.65 djm 103: { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
104: { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
1.62 markus 105: KEY_XMSS_CERT, 0, 1, 0 },
106: #endif /* WITH_XMSS */
1.1 djm 107: #ifdef WITH_OPENSSL
1.65 djm 108: { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
109: { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
110: { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
111: { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
112: { "ecdsa-sha2-nistp256", "ECDSA", NULL,
113: KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
114: { "ecdsa-sha2-nistp384", "ECDSA", NULL,
115: KEY_ECDSA, NID_secp384r1, 0, 0 },
116: { "ecdsa-sha2-nistp521", "ECDSA", NULL,
117: KEY_ECDSA, NID_secp521r1, 0, 0 },
1.85 ! djm 118: { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
! 119: KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 },
1.65 djm 120: { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
121: KEY_RSA_CERT, 0, 1, 0 },
122: { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
1.72 djm 123: "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
1.65 djm 124: { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
1.72 djm 125: "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
1.65 djm 126: { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
127: KEY_DSA_CERT, 0, 1, 0 },
128: { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 129: KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
1.65 djm 130: { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
1.28 markus 131: KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
1.65 djm 132: { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
133: KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
1.85 ! djm 134: { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL,
! 135: KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 },
1.1 djm 136: #endif /* WITH_OPENSSL */
1.65 djm 137: { NULL, NULL, NULL, -1, -1, 0, 0 }
1.1 djm 138: };
139:
140: const char *
141: sshkey_type(const struct sshkey *k)
142: {
143: const struct keytype *kt;
144:
145: for (kt = keytypes; kt->type != -1; kt++) {
146: if (kt->type == k->type)
147: return kt->shortname;
148: }
149: return "unknown";
150: }
151:
152: static const char *
153: sshkey_ssh_name_from_type_nid(int type, int nid)
154: {
155: const struct keytype *kt;
156:
157: for (kt = keytypes; kt->type != -1; kt++) {
158: if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
159: return kt->name;
160: }
161: return "ssh-unknown";
162: }
163:
164: int
165: sshkey_type_is_cert(int type)
166: {
167: const struct keytype *kt;
168:
169: for (kt = keytypes; kt->type != -1; kt++) {
170: if (kt->type == type)
171: return kt->cert;
172: }
173: return 0;
174: }
175:
176: const char *
177: sshkey_ssh_name(const struct sshkey *k)
178: {
179: return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
180: }
181:
182: const char *
183: sshkey_ssh_name_plain(const struct sshkey *k)
184: {
185: return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
186: k->ecdsa_nid);
187: }
188:
189: int
190: sshkey_type_from_name(const char *name)
191: {
192: const struct keytype *kt;
193:
194: for (kt = keytypes; kt->type != -1; kt++) {
195: /* Only allow shortname matches for plain key types */
196: if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
197: (!kt->cert && strcasecmp(kt->shortname, name) == 0))
198: return kt->type;
199: }
200: return KEY_UNSPEC;
201: }
202:
1.85 ! djm 203: static int
! 204: key_type_is_ecdsa_variant(int type)
! 205: {
! 206: switch (type) {
! 207: case KEY_ECDSA:
! 208: case KEY_ECDSA_CERT:
! 209: case KEY_ECDSA_SK:
! 210: case KEY_ECDSA_SK_CERT:
! 211: return 1;
! 212: }
! 213: return 0;
! 214: }
! 215:
1.1 djm 216: int
217: sshkey_ecdsa_nid_from_name(const char *name)
218: {
219: const struct keytype *kt;
220:
1.4 djm 221: for (kt = keytypes; kt->type != -1; kt++) {
1.85 ! djm 222: if (!key_type_is_ecdsa_variant(kt->type))
1.4 djm 223: continue;
224: if (kt->name != NULL && strcmp(name, kt->name) == 0)
225: return kt->nid;
226: }
1.1 djm 227: return -1;
228: }
229:
230: char *
1.45 djm 231: sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
1.1 djm 232: {
233: char *tmp, *ret = NULL;
234: size_t nlen, rlen = 0;
235: const struct keytype *kt;
236:
237: for (kt = keytypes; kt->type != -1; kt++) {
1.45 djm 238: if (kt->name == NULL)
239: continue;
240: if (!include_sigonly && kt->sigonly)
1.1 djm 241: continue;
242: if ((certs_only && !kt->cert) || (plain_only && kt->cert))
243: continue;
244: if (ret != NULL)
1.38 djm 245: ret[rlen++] = sep;
1.1 djm 246: nlen = strlen(kt->name);
247: if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
248: free(ret);
249: return NULL;
250: }
251: ret = tmp;
252: memcpy(ret + rlen, kt->name, nlen + 1);
253: rlen += nlen;
254: }
255: return ret;
256: }
257:
258: int
1.11 djm 259: sshkey_names_valid2(const char *names, int allow_wildcard)
1.1 djm 260: {
261: char *s, *cp, *p;
1.11 djm 262: const struct keytype *kt;
263: int type;
1.1 djm 264:
265: if (names == NULL || strcmp(names, "") == 0)
266: return 0;
267: if ((s = cp = strdup(names)) == NULL)
268: return 0;
269: for ((p = strsep(&cp, ",")); p && *p != '\0';
270: (p = strsep(&cp, ","))) {
1.11 djm 271: type = sshkey_type_from_name(p);
272: if (type == KEY_UNSPEC) {
273: if (allow_wildcard) {
274: /*
275: * Try matching key types against the string.
276: * If any has a positive or negative match then
277: * the component is accepted.
278: */
279: for (kt = keytypes; kt->type != -1; kt++) {
280: if (match_pattern_list(kt->name,
1.17 djm 281: p, 0) != 0)
1.11 djm 282: break;
283: }
284: if (kt->type != -1)
285: continue;
286: }
1.1 djm 287: free(s);
288: return 0;
289: }
290: }
291: free(s);
292: return 1;
293: }
294:
295: u_int
296: sshkey_size(const struct sshkey *k)
297: {
1.69 djm 298: #ifdef WITH_OPENSSL
299: const BIGNUM *rsa_n, *dsa_p;
300: #endif /* WITH_OPENSSL */
301:
1.1 djm 302: switch (k->type) {
303: #ifdef WITH_OPENSSL
304: case KEY_RSA:
305: case KEY_RSA_CERT:
1.69 djm 306: if (k->rsa == NULL)
307: return 0;
308: RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
309: return BN_num_bits(rsa_n);
1.1 djm 310: case KEY_DSA:
311: case KEY_DSA_CERT:
1.69 djm 312: if (k->dsa == NULL)
313: return 0;
314: DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL);
315: return BN_num_bits(dsa_p);
1.1 djm 316: case KEY_ECDSA:
317: case KEY_ECDSA_CERT:
1.85 ! djm 318: case KEY_ECDSA_SK:
! 319: case KEY_ECDSA_SK_CERT:
1.1 djm 320: return sshkey_curve_nid_to_bits(k->ecdsa_nid);
321: #endif /* WITH_OPENSSL */
322: case KEY_ED25519:
323: case KEY_ED25519_CERT:
1.62 markus 324: case KEY_XMSS:
325: case KEY_XMSS_CERT:
1.1 djm 326: return 256; /* XXX */
327: }
328: return 0;
329: }
330:
331: static int
332: sshkey_type_is_valid_ca(int type)
333: {
334: switch (type) {
335: case KEY_RSA:
336: case KEY_DSA:
337: case KEY_ECDSA:
1.85 ! djm 338: case KEY_ECDSA_SK:
1.1 djm 339: case KEY_ED25519:
1.62 markus 340: case KEY_XMSS:
1.1 djm 341: return 1;
342: default:
343: return 0;
344: }
345: }
346:
347: int
348: sshkey_is_cert(const struct sshkey *k)
349: {
350: if (k == NULL)
351: return 0;
352: return sshkey_type_is_cert(k->type);
353: }
354:
355: /* Return the cert-less equivalent to a certified key type */
356: int
357: sshkey_type_plain(int type)
358: {
359: switch (type) {
360: case KEY_RSA_CERT:
361: return KEY_RSA;
362: case KEY_DSA_CERT:
363: return KEY_DSA;
364: case KEY_ECDSA_CERT:
365: return KEY_ECDSA;
1.85 ! djm 366: case KEY_ECDSA_SK_CERT:
! 367: return KEY_ECDSA_SK;
1.1 djm 368: case KEY_ED25519_CERT:
369: return KEY_ED25519;
1.62 markus 370: case KEY_XMSS_CERT:
371: return KEY_XMSS;
1.1 djm 372: default:
373: return type;
374: }
375: }
376:
377: #ifdef WITH_OPENSSL
378: /* XXX: these are really begging for a table-driven approach */
379: int
380: sshkey_curve_name_to_nid(const char *name)
381: {
382: if (strcmp(name, "nistp256") == 0)
383: return NID_X9_62_prime256v1;
384: else if (strcmp(name, "nistp384") == 0)
385: return NID_secp384r1;
386: else if (strcmp(name, "nistp521") == 0)
387: return NID_secp521r1;
388: else
389: return -1;
390: }
391:
392: u_int
393: sshkey_curve_nid_to_bits(int nid)
394: {
395: switch (nid) {
396: case NID_X9_62_prime256v1:
397: return 256;
398: case NID_secp384r1:
399: return 384;
400: case NID_secp521r1:
401: return 521;
402: default:
403: return 0;
404: }
405: }
406:
407: int
408: sshkey_ecdsa_bits_to_nid(int bits)
409: {
410: switch (bits) {
411: case 256:
412: return NID_X9_62_prime256v1;
413: case 384:
414: return NID_secp384r1;
415: case 521:
416: return NID_secp521r1;
417: default:
418: return -1;
419: }
420: }
421:
422: const char *
423: sshkey_curve_nid_to_name(int nid)
424: {
425: switch (nid) {
426: case NID_X9_62_prime256v1:
427: return "nistp256";
428: case NID_secp384r1:
429: return "nistp384";
430: case NID_secp521r1:
431: return "nistp521";
432: default:
433: return NULL;
434: }
435: }
436:
437: int
438: sshkey_ec_nid_to_hash_alg(int nid)
439: {
440: int kbits = sshkey_curve_nid_to_bits(nid);
441:
442: if (kbits <= 0)
443: return -1;
444:
445: /* RFC5656 section 6.2.1 */
446: if (kbits <= 256)
447: return SSH_DIGEST_SHA256;
448: else if (kbits <= 384)
449: return SSH_DIGEST_SHA384;
450: else
451: return SSH_DIGEST_SHA512;
452: }
453: #endif /* WITH_OPENSSL */
454:
455: static void
456: cert_free(struct sshkey_cert *cert)
457: {
458: u_int i;
459:
460: if (cert == NULL)
461: return;
1.31 mmcc 462: sshbuf_free(cert->certblob);
463: sshbuf_free(cert->critical);
464: sshbuf_free(cert->extensions);
1.29 mmcc 465: free(cert->key_id);
1.1 djm 466: for (i = 0; i < cert->nprincipals; i++)
467: free(cert->principals[i]);
1.29 mmcc 468: free(cert->principals);
1.30 mmcc 469: sshkey_free(cert->signature_key);
1.67 djm 470: free(cert->signature_type);
1.61 jsing 471: freezero(cert, sizeof(*cert));
1.1 djm 472: }
473:
474: static struct sshkey_cert *
475: cert_new(void)
476: {
477: struct sshkey_cert *cert;
478:
479: if ((cert = calloc(1, sizeof(*cert))) == NULL)
480: return NULL;
481: if ((cert->certblob = sshbuf_new()) == NULL ||
482: (cert->critical = sshbuf_new()) == NULL ||
483: (cert->extensions = sshbuf_new()) == NULL) {
484: cert_free(cert);
485: return NULL;
486: }
487: cert->key_id = NULL;
488: cert->principals = NULL;
489: cert->signature_key = NULL;
1.67 djm 490: cert->signature_type = NULL;
1.1 djm 491: return cert;
492: }
493:
494: struct sshkey *
495: sshkey_new(int type)
496: {
497: struct sshkey *k;
498: #ifdef WITH_OPENSSL
499: RSA *rsa;
500: DSA *dsa;
501: #endif /* WITH_OPENSSL */
502:
503: if ((k = calloc(1, sizeof(*k))) == NULL)
504: return NULL;
505: k->type = type;
506: k->ecdsa = NULL;
507: k->ecdsa_nid = -1;
508: k->dsa = NULL;
509: k->rsa = NULL;
510: k->cert = NULL;
511: k->ed25519_sk = NULL;
512: k->ed25519_pk = NULL;
1.62 markus 513: k->xmss_sk = NULL;
514: k->xmss_pk = NULL;
1.1 djm 515: switch (k->type) {
516: #ifdef WITH_OPENSSL
517: case KEY_RSA:
518: case KEY_RSA_CERT:
1.69 djm 519: if ((rsa = RSA_new()) == NULL) {
1.1 djm 520: free(k);
521: return NULL;
522: }
523: k->rsa = rsa;
524: break;
525: case KEY_DSA:
526: case KEY_DSA_CERT:
1.69 djm 527: if ((dsa = DSA_new()) == NULL) {
1.1 djm 528: free(k);
529: return NULL;
530: }
531: k->dsa = dsa;
532: break;
533: case KEY_ECDSA:
534: case KEY_ECDSA_CERT:
1.85 ! djm 535: case KEY_ECDSA_SK:
! 536: case KEY_ECDSA_SK_CERT:
1.1 djm 537: /* Cannot do anything until we know the group */
538: break;
539: #endif /* WITH_OPENSSL */
540: case KEY_ED25519:
541: case KEY_ED25519_CERT:
1.62 markus 542: case KEY_XMSS:
543: case KEY_XMSS_CERT:
1.1 djm 544: /* no need to prealloc */
545: break;
546: case KEY_UNSPEC:
547: break;
548: default:
549: free(k);
550: return NULL;
551: }
552:
553: if (sshkey_is_cert(k)) {
554: if ((k->cert = cert_new()) == NULL) {
555: sshkey_free(k);
556: return NULL;
557: }
558: }
559:
560: return k;
561: }
562:
563: void
564: sshkey_free(struct sshkey *k)
565: {
566: if (k == NULL)
567: return;
568: switch (k->type) {
569: #ifdef WITH_OPENSSL
570: case KEY_RSA:
571: case KEY_RSA_CERT:
1.60 jsing 572: RSA_free(k->rsa);
1.1 djm 573: k->rsa = NULL;
574: break;
575: case KEY_DSA:
576: case KEY_DSA_CERT:
1.60 jsing 577: DSA_free(k->dsa);
1.1 djm 578: k->dsa = NULL;
579: break;
1.85 ! djm 580: case KEY_ECDSA_SK:
! 581: case KEY_ECDSA_SK_CERT:
! 582: free(k->sk_application);
! 583: sshbuf_free(k->sk_key_handle);
! 584: sshbuf_free(k->sk_reserved);
! 585: /* FALLTHROUGH */
1.1 djm 586: case KEY_ECDSA:
587: case KEY_ECDSA_CERT:
1.60 jsing 588: EC_KEY_free(k->ecdsa);
1.1 djm 589: k->ecdsa = NULL;
590: break;
591: #endif /* WITH_OPENSSL */
592: case KEY_ED25519:
593: case KEY_ED25519_CERT:
1.61 jsing 594: freezero(k->ed25519_pk, ED25519_PK_SZ);
595: k->ed25519_pk = NULL;
596: freezero(k->ed25519_sk, ED25519_SK_SZ);
597: k->ed25519_sk = NULL;
1.1 djm 598: break;
1.62 markus 599: #ifdef WITH_XMSS
600: case KEY_XMSS:
601: case KEY_XMSS_CERT:
602: freezero(k->xmss_pk, sshkey_xmss_pklen(k));
603: k->xmss_pk = NULL;
604: freezero(k->xmss_sk, sshkey_xmss_sklen(k));
605: k->xmss_sk = NULL;
606: sshkey_xmss_free_state(k);
607: free(k->xmss_name);
608: k->xmss_name = NULL;
609: free(k->xmss_filename);
610: k->xmss_filename = NULL;
611: break;
612: #endif /* WITH_XMSS */
1.1 djm 613: case KEY_UNSPEC:
614: break;
615: default:
616: break;
617: }
618: if (sshkey_is_cert(k))
619: cert_free(k->cert);
1.76 djm 620: freezero(k->shielded_private, k->shielded_len);
621: freezero(k->shield_prekey, k->shield_prekey_len);
1.61 jsing 622: freezero(k, sizeof(*k));
1.1 djm 623: }
624:
625: static int
626: cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
627: {
628: if (a == NULL && b == NULL)
629: return 1;
630: if (a == NULL || b == NULL)
631: return 0;
632: if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
633: return 0;
634: if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
635: sshbuf_len(a->certblob)) != 0)
636: return 0;
637: return 1;
638: }
639:
640: /*
641: * Compare public portions of key only, allowing comparisons between
642: * certificates and plain keys too.
643: */
644: int
645: sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
646: {
647: #ifdef WITH_OPENSSL
648: BN_CTX *bnctx;
1.69 djm 649: const BIGNUM *rsa_e_a, *rsa_n_a;
650: const BIGNUM *rsa_e_b, *rsa_n_b;
651: const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
652: const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
1.1 djm 653: #endif /* WITH_OPENSSL */
654:
655: if (a == NULL || b == NULL ||
656: sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
657: return 0;
658:
659: switch (a->type) {
660: #ifdef WITH_OPENSSL
661: case KEY_RSA_CERT:
662: case KEY_RSA:
1.69 djm 663: if (a->rsa == NULL || b->rsa == NULL)
664: return 0;
665: RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
666: RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
667: return BN_cmp(rsa_e_a, rsa_e_b) == 0 &&
668: BN_cmp(rsa_n_a, rsa_n_b) == 0;
1.1 djm 669: case KEY_DSA_CERT:
670: case KEY_DSA:
1.69 djm 671: if (a->dsa == NULL || b->dsa == NULL)
672: return 0;
673: DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
674: DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
675: DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
676: DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
677: return BN_cmp(dsa_p_a, dsa_p_b) == 0 &&
678: BN_cmp(dsa_q_a, dsa_q_b) == 0 &&
679: BN_cmp(dsa_g_a, dsa_g_b) == 0 &&
680: BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0;
1.85 ! djm 681: case KEY_ECDSA_SK:
! 682: case KEY_ECDSA_SK_CERT:
! 683: if (a->sk_application == NULL || b->sk_application == NULL)
! 684: return 0;
! 685: if (strcmp(a->sk_application, b->sk_application) != 0)
! 686: return 0;
! 687: /* FALLTHROUGH */
1.1 djm 688: case KEY_ECDSA_CERT:
689: case KEY_ECDSA:
690: if (a->ecdsa == NULL || b->ecdsa == NULL ||
691: EC_KEY_get0_public_key(a->ecdsa) == NULL ||
692: EC_KEY_get0_public_key(b->ecdsa) == NULL)
693: return 0;
694: if ((bnctx = BN_CTX_new()) == NULL)
695: return 0;
696: if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
697: EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
698: EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
699: EC_KEY_get0_public_key(a->ecdsa),
700: EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
701: BN_CTX_free(bnctx);
702: return 0;
703: }
704: BN_CTX_free(bnctx);
705: return 1;
706: #endif /* WITH_OPENSSL */
707: case KEY_ED25519:
708: case KEY_ED25519_CERT:
709: return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
710: memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
1.62 markus 711: #ifdef WITH_XMSS
712: case KEY_XMSS:
713: case KEY_XMSS_CERT:
714: return a->xmss_pk != NULL && b->xmss_pk != NULL &&
715: sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
716: memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
717: #endif /* WITH_XMSS */
1.1 djm 718: default:
719: return 0;
720: }
721: /* NOTREACHED */
722: }
723:
724: int
725: sshkey_equal(const struct sshkey *a, const struct sshkey *b)
726: {
727: if (a == NULL || b == NULL || a->type != b->type)
728: return 0;
729: if (sshkey_is_cert(a)) {
730: if (!cert_compare(a->cert, b->cert))
731: return 0;
732: }
733: return sshkey_equal_public(a, b);
734: }
735:
736: static int
1.62 markus 737: to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
738: enum sshkey_serialize_rep opts)
1.1 djm 739: {
740: int type, ret = SSH_ERR_INTERNAL_ERROR;
741: const char *typename;
1.69 djm 742: #ifdef WITH_OPENSSL
743: const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
744: #endif /* WITH_OPENSSL */
1.1 djm 745:
746: if (key == NULL)
747: return SSH_ERR_INVALID_ARGUMENT;
748:
1.19 djm 749: if (sshkey_is_cert(key)) {
750: if (key->cert == NULL)
751: return SSH_ERR_EXPECTED_CERT;
752: if (sshbuf_len(key->cert->certblob) == 0)
753: return SSH_ERR_KEY_LACKS_CERTBLOB;
754: }
1.1 djm 755: type = force_plain ? sshkey_type_plain(key->type) : key->type;
756: typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
757:
758: switch (type) {
759: #ifdef WITH_OPENSSL
760: case KEY_DSA_CERT:
761: case KEY_ECDSA_CERT:
1.85 ! djm 762: case KEY_ECDSA_SK_CERT:
1.1 djm 763: case KEY_RSA_CERT:
764: #endif /* WITH_OPENSSL */
765: case KEY_ED25519_CERT:
1.62 markus 766: #ifdef WITH_XMSS
767: case KEY_XMSS_CERT:
768: #endif /* WITH_XMSS */
1.1 djm 769: /* Use the existing blob */
770: /* XXX modified flag? */
771: if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
772: return ret;
773: break;
774: #ifdef WITH_OPENSSL
775: case KEY_DSA:
776: if (key->dsa == NULL)
777: return SSH_ERR_INVALID_ARGUMENT;
1.69 djm 778: DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
779: DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
1.1 djm 780: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
1.69 djm 781: (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
782: (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
783: (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
784: (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
1.1 djm 785: return ret;
786: break;
787: case KEY_ECDSA:
1.85 ! djm 788: case KEY_ECDSA_SK:
1.1 djm 789: if (key->ecdsa == NULL)
790: return SSH_ERR_INVALID_ARGUMENT;
791: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
792: (ret = sshbuf_put_cstring(b,
793: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
794: (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
795: return ret;
1.85 ! djm 796: if (type == KEY_ECDSA_SK) {
! 797: if ((ret = sshbuf_put_cstring(b,
! 798: key->sk_application)) != 0)
! 799: return ret;
! 800: }
1.1 djm 801: break;
802: case KEY_RSA:
803: if (key->rsa == NULL)
804: return SSH_ERR_INVALID_ARGUMENT;
1.69 djm 805: RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
1.1 djm 806: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
1.69 djm 807: (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
808: (ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
1.1 djm 809: return ret;
810: break;
811: #endif /* WITH_OPENSSL */
812: case KEY_ED25519:
813: if (key->ed25519_pk == NULL)
814: return SSH_ERR_INVALID_ARGUMENT;
815: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
816: (ret = sshbuf_put_string(b,
817: key->ed25519_pk, ED25519_PK_SZ)) != 0)
818: return ret;
819: break;
1.62 markus 820: #ifdef WITH_XMSS
821: case KEY_XMSS:
822: if (key->xmss_name == NULL || key->xmss_pk == NULL ||
823: sshkey_xmss_pklen(key) == 0)
824: return SSH_ERR_INVALID_ARGUMENT;
825: if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
826: (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
827: (ret = sshbuf_put_string(b,
828: key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
829: (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
830: return ret;
831: break;
832: #endif /* WITH_XMSS */
1.1 djm 833: default:
834: return SSH_ERR_KEY_TYPE_UNKNOWN;
835: }
836: return 0;
837: }
838:
839: int
1.14 djm 840: sshkey_putb(const struct sshkey *key, struct sshbuf *b)
1.1 djm 841: {
1.62 markus 842: return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 843: }
844:
845: int
1.62 markus 846: sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
847: enum sshkey_serialize_rep opts)
1.14 djm 848: {
849: struct sshbuf *tmp;
850: int r;
851:
852: if ((tmp = sshbuf_new()) == NULL)
853: return SSH_ERR_ALLOC_FAIL;
1.62 markus 854: r = to_blob_buf(key, tmp, 0, opts);
1.14 djm 855: if (r == 0)
856: r = sshbuf_put_stringb(b, tmp);
857: sshbuf_free(tmp);
858: return r;
859: }
860:
861: int
1.62 markus 862: sshkey_puts(const struct sshkey *key, struct sshbuf *b)
863: {
864: return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
865: }
866:
867: int
1.14 djm 868: sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
1.1 djm 869: {
1.62 markus 870: return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 871: }
872:
873: static int
1.62 markus 874: to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
875: enum sshkey_serialize_rep opts)
1.1 djm 876: {
877: int ret = SSH_ERR_INTERNAL_ERROR;
878: size_t len;
879: struct sshbuf *b = NULL;
880:
881: if (lenp != NULL)
882: *lenp = 0;
883: if (blobp != NULL)
884: *blobp = NULL;
885: if ((b = sshbuf_new()) == NULL)
886: return SSH_ERR_ALLOC_FAIL;
1.62 markus 887: if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
1.1 djm 888: goto out;
889: len = sshbuf_len(b);
890: if (lenp != NULL)
891: *lenp = len;
892: if (blobp != NULL) {
893: if ((*blobp = malloc(len)) == NULL) {
894: ret = SSH_ERR_ALLOC_FAIL;
895: goto out;
896: }
897: memcpy(*blobp, sshbuf_ptr(b), len);
898: }
899: ret = 0;
900: out:
901: sshbuf_free(b);
902: return ret;
903: }
904:
905: int
906: sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
907: {
1.62 markus 908: return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 909: }
910:
911: int
912: sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
913: {
1.62 markus 914: return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
1.1 djm 915: }
916:
917: int
1.7 djm 918: sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1.1 djm 919: u_char **retp, size_t *lenp)
920: {
921: u_char *blob = NULL, *ret = NULL;
922: size_t blob_len = 0;
1.7 djm 923: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 924:
925: if (retp != NULL)
926: *retp = NULL;
927: if (lenp != NULL)
928: *lenp = 0;
1.7 djm 929: if (ssh_digest_bytes(dgst_alg) == 0) {
1.1 djm 930: r = SSH_ERR_INVALID_ARGUMENT;
931: goto out;
932: }
1.62 markus 933: if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
934: != 0)
1.1 djm 935: goto out;
936: if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
937: r = SSH_ERR_ALLOC_FAIL;
938: goto out;
939: }
1.7 djm 940: if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
1.1 djm 941: ret, SSH_DIGEST_MAX_LENGTH)) != 0)
942: goto out;
943: /* success */
944: if (retp != NULL) {
945: *retp = ret;
946: ret = NULL;
947: }
948: if (lenp != NULL)
1.7 djm 949: *lenp = ssh_digest_bytes(dgst_alg);
1.1 djm 950: r = 0;
951: out:
952: free(ret);
953: if (blob != NULL) {
954: explicit_bzero(blob, blob_len);
955: free(blob);
956: }
957: return r;
958: }
959:
960: static char *
1.7 djm 961: fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
962: {
963: char *ret;
964: size_t plen = strlen(alg) + 1;
965: size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
966:
967: if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
968: return NULL;
969: strlcpy(ret, alg, rlen);
970: strlcat(ret, ":", rlen);
971: if (dgst_raw_len == 0)
972: return ret;
1.79 dtucker 973: if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) {
1.61 jsing 974: freezero(ret, rlen);
1.7 djm 975: return NULL;
976: }
977: /* Trim padding characters from end */
978: ret[strcspn(ret, "=")] = '\0';
979: return ret;
980: }
981:
982: static char *
983: fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
1.1 djm 984: {
1.7 djm 985: char *retval, hex[5];
986: size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
1.1 djm 987:
1.7 djm 988: if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
1.1 djm 989: return NULL;
1.7 djm 990: strlcpy(retval, alg, rlen);
991: strlcat(retval, ":", rlen);
1.1 djm 992: for (i = 0; i < dgst_raw_len; i++) {
1.7 djm 993: snprintf(hex, sizeof(hex), "%s%02x",
994: i > 0 ? ":" : "", dgst_raw[i]);
995: strlcat(retval, hex, rlen);
1.1 djm 996: }
997: return retval;
998: }
999:
1000: static char *
1001: fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
1002: {
1003: char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
1004: char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
1005: 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
1006: u_int i, j = 0, rounds, seed = 1;
1007: char *retval;
1008:
1009: rounds = (dgst_raw_len / 2) + 1;
1010: if ((retval = calloc(rounds, 6)) == NULL)
1011: return NULL;
1012: retval[j++] = 'x';
1013: for (i = 0; i < rounds; i++) {
1014: u_int idx0, idx1, idx2, idx3, idx4;
1015: if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
1016: idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
1017: seed) % 6;
1018: idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
1019: idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
1020: (seed / 6)) % 6;
1021: retval[j++] = vowels[idx0];
1022: retval[j++] = consonants[idx1];
1023: retval[j++] = vowels[idx2];
1024: if ((i + 1) < rounds) {
1025: idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
1026: idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
1027: retval[j++] = consonants[idx3];
1028: retval[j++] = '-';
1029: retval[j++] = consonants[idx4];
1030: seed = ((seed * 5) +
1031: ((((u_int)(dgst_raw[2 * i])) * 7) +
1032: ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
1033: }
1034: } else {
1035: idx0 = seed % 6;
1036: idx1 = 16;
1037: idx2 = seed / 6;
1038: retval[j++] = vowels[idx0];
1039: retval[j++] = consonants[idx1];
1040: retval[j++] = vowels[idx2];
1041: }
1042: }
1043: retval[j++] = 'x';
1044: retval[j++] = '\0';
1045: return retval;
1046: }
1047:
1048: /*
1049: * Draw an ASCII-Art representing the fingerprint so human brain can
1050: * profit from its built-in pattern recognition ability.
1051: * This technique is called "random art" and can be found in some
1052: * scientific publications like this original paper:
1053: *
1054: * "Hash Visualization: a New Technique to improve Real-World Security",
1055: * Perrig A. and Song D., 1999, International Workshop on Cryptographic
1056: * Techniques and E-Commerce (CrypTEC '99)
1057: * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1058: *
1059: * The subject came up in a talk by Dan Kaminsky, too.
1060: *
1061: * If you see the picture is different, the key is different.
1062: * If the picture looks the same, you still know nothing.
1063: *
1064: * The algorithm used here is a worm crawling over a discrete plane,
1065: * leaving a trace (augmenting the field) everywhere it goes.
1066: * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1067: * makes the respective movement vector be ignored for this turn.
1068: * Graphs are not unambiguous, because circles in graphs can be
1069: * walked in either direction.
1070: */
1071:
1072: /*
1073: * Field sizes for the random art. Have to be odd, so the starting point
1074: * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1075: * Else pictures would be too dense, and drawing the frame would
1076: * fail, too, because the key type would not fit in anymore.
1077: */
1078: #define FLDBASE 8
1079: #define FLDSIZE_Y (FLDBASE + 1)
1080: #define FLDSIZE_X (FLDBASE * 2 + 1)
1081: static char *
1.7 djm 1082: fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
1.1 djm 1083: const struct sshkey *k)
1084: {
1085: /*
1086: * Chars to be used after each other every time the worm
1087: * intersects with itself. Matter of taste.
1088: */
1089: char *augmentation_string = " .o+=*BOX@%&#/^SE";
1.7 djm 1090: char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
1.1 djm 1091: u_char field[FLDSIZE_X][FLDSIZE_Y];
1.7 djm 1092: size_t i, tlen, hlen;
1.1 djm 1093: u_int b;
1.3 djm 1094: int x, y, r;
1.1 djm 1095: size_t len = strlen(augmentation_string) - 1;
1096:
1097: if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1098: return NULL;
1099:
1100: /* initialize field */
1101: memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1102: x = FLDSIZE_X / 2;
1103: y = FLDSIZE_Y / 2;
1104:
1105: /* process raw key */
1106: for (i = 0; i < dgst_raw_len; i++) {
1107: int input;
1108: /* each byte conveys four 2-bit move commands */
1109: input = dgst_raw[i];
1110: for (b = 0; b < 4; b++) {
1111: /* evaluate 2 bit, rest is shifted later */
1112: x += (input & 0x1) ? 1 : -1;
1113: y += (input & 0x2) ? 1 : -1;
1114:
1115: /* assure we are still in bounds */
1.37 deraadt 1116: x = MAXIMUM(x, 0);
1117: y = MAXIMUM(y, 0);
1118: x = MINIMUM(x, FLDSIZE_X - 1);
1119: y = MINIMUM(y, FLDSIZE_Y - 1);
1.1 djm 1120:
1121: /* augment the field */
1122: if (field[x][y] < len - 2)
1123: field[x][y]++;
1124: input = input >> 2;
1125: }
1126: }
1127:
1128: /* mark starting point and end point*/
1129: field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1130: field[x][y] = len;
1131:
1.3 djm 1132: /* assemble title */
1133: r = snprintf(title, sizeof(title), "[%s %u]",
1134: sshkey_type(k), sshkey_size(k));
1135: /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1136: if (r < 0 || r > (int)sizeof(title))
1.7 djm 1137: r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1138: tlen = (r <= 0) ? 0 : strlen(title);
1139:
1140: /* assemble hash ID. */
1141: r = snprintf(hash, sizeof(hash), "[%s]", alg);
1142: hlen = (r <= 0) ? 0 : strlen(hash);
1.1 djm 1143:
1144: /* output upper border */
1.3 djm 1145: p = retval;
1146: *p++ = '+';
1147: for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1148: *p++ = '-';
1149: memcpy(p, title, tlen);
1150: p += tlen;
1.7 djm 1151: for (i += tlen; i < FLDSIZE_X; i++)
1.1 djm 1152: *p++ = '-';
1153: *p++ = '+';
1154: *p++ = '\n';
1155:
1156: /* output content */
1157: for (y = 0; y < FLDSIZE_Y; y++) {
1158: *p++ = '|';
1159: for (x = 0; x < FLDSIZE_X; x++)
1.37 deraadt 1160: *p++ = augmentation_string[MINIMUM(field[x][y], len)];
1.1 djm 1161: *p++ = '|';
1162: *p++ = '\n';
1163: }
1164:
1165: /* output lower border */
1166: *p++ = '+';
1.7 djm 1167: for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
1168: *p++ = '-';
1169: memcpy(p, hash, hlen);
1170: p += hlen;
1171: for (i += hlen; i < FLDSIZE_X; i++)
1.1 djm 1172: *p++ = '-';
1173: *p++ = '+';
1174:
1175: return retval;
1176: }
1177:
1178: char *
1.7 djm 1179: sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1.1 djm 1180: enum sshkey_fp_rep dgst_rep)
1181: {
1182: char *retval = NULL;
1183: u_char *dgst_raw;
1184: size_t dgst_raw_len;
1185:
1.7 djm 1186: if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
1.1 djm 1187: return NULL;
1188: switch (dgst_rep) {
1.7 djm 1189: case SSH_FP_DEFAULT:
1190: if (dgst_alg == SSH_DIGEST_MD5) {
1191: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1192: dgst_raw, dgst_raw_len);
1193: } else {
1194: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1195: dgst_raw, dgst_raw_len);
1196: }
1197: break;
1.1 djm 1198: case SSH_FP_HEX:
1.7 djm 1199: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
1200: dgst_raw, dgst_raw_len);
1201: break;
1202: case SSH_FP_BASE64:
1203: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
1204: dgst_raw, dgst_raw_len);
1.1 djm 1205: break;
1206: case SSH_FP_BUBBLEBABBLE:
1207: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1208: break;
1209: case SSH_FP_RANDOMART:
1.7 djm 1210: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
1211: dgst_raw, dgst_raw_len, k);
1.1 djm 1212: break;
1213: default:
1214: explicit_bzero(dgst_raw, dgst_raw_len);
1215: free(dgst_raw);
1216: return NULL;
1217: }
1218: explicit_bzero(dgst_raw, dgst_raw_len);
1219: free(dgst_raw);
1220: return retval;
1221: }
1222:
1.63 djm 1223: static int
1224: peek_type_nid(const char *s, size_t l, int *nid)
1225: {
1226: const struct keytype *kt;
1227:
1228: for (kt = keytypes; kt->type != -1; kt++) {
1229: if (kt->name == NULL || strlen(kt->name) != l)
1230: continue;
1231: if (memcmp(s, kt->name, l) == 0) {
1232: *nid = -1;
1.85 ! djm 1233: if (key_type_is_ecdsa_variant(kt->type))
1.63 djm 1234: *nid = kt->nid;
1235: return kt->type;
1236: }
1237: }
1238: return KEY_UNSPEC;
1239: }
1240:
1.1 djm 1241:
1.63 djm 1242: /* XXX this can now be made const char * */
1.1 djm 1243: int
1244: sshkey_read(struct sshkey *ret, char **cpp)
1245: {
1246: struct sshkey *k;
1.63 djm 1247: char *cp, *blobcopy;
1248: size_t space;
1.1 djm 1249: int r, type, curve_nid = -1;
1250: struct sshbuf *blob;
1.44 dtucker 1251:
1252: if (ret == NULL)
1253: return SSH_ERR_INVALID_ARGUMENT;
1.1 djm 1254:
1255: switch (ret->type) {
1256: case KEY_UNSPEC:
1257: case KEY_RSA:
1258: case KEY_DSA:
1259: case KEY_ECDSA:
1.85 ! djm 1260: case KEY_ECDSA_SK:
1.1 djm 1261: case KEY_ED25519:
1262: case KEY_DSA_CERT:
1263: case KEY_ECDSA_CERT:
1.85 ! djm 1264: case KEY_ECDSA_SK_CERT:
1.1 djm 1265: case KEY_RSA_CERT:
1266: case KEY_ED25519_CERT:
1.62 markus 1267: #ifdef WITH_XMSS
1268: case KEY_XMSS:
1269: case KEY_XMSS_CERT:
1270: #endif /* WITH_XMSS */
1.63 djm 1271: break; /* ok */
1272: default:
1273: return SSH_ERR_INVALID_ARGUMENT;
1274: }
1275:
1276: /* Decode type */
1277: cp = *cpp;
1278: space = strcspn(cp, " \t");
1279: if (space == strlen(cp))
1280: return SSH_ERR_INVALID_FORMAT;
1281: if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1282: return SSH_ERR_INVALID_FORMAT;
1283:
1284: /* skip whitespace */
1285: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1286: ;
1287: if (*cp == '\0')
1288: return SSH_ERR_INVALID_FORMAT;
1289: if (ret->type != KEY_UNSPEC && ret->type != type)
1290: return SSH_ERR_KEY_TYPE_MISMATCH;
1291: if ((blob = sshbuf_new()) == NULL)
1292: return SSH_ERR_ALLOC_FAIL;
1293:
1294: /* find end of keyblob and decode */
1295: space = strcspn(cp, " \t");
1296: if ((blobcopy = strndup(cp, space)) == NULL) {
1297: sshbuf_free(blob);
1298: return SSH_ERR_ALLOC_FAIL;
1299: }
1300: if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1301: free(blobcopy);
1302: sshbuf_free(blob);
1303: return r;
1304: }
1305: free(blobcopy);
1306: if ((r = sshkey_fromb(blob, &k)) != 0) {
1.1 djm 1307: sshbuf_free(blob);
1.63 djm 1308: return r;
1309: }
1310: sshbuf_free(blob);
1311:
1312: /* skip whitespace and leave cp at start of comment */
1313: for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1314: ;
1315:
1316: /* ensure type of blob matches type at start of line */
1317: if (k->type != type) {
1318: sshkey_free(k);
1319: return SSH_ERR_KEY_TYPE_MISMATCH;
1320: }
1.85 ! djm 1321: if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) {
1.63 djm 1322: sshkey_free(k);
1323: return SSH_ERR_EC_CURVE_MISMATCH;
1324: }
1325:
1326: /* Fill in ret from parsed key */
1327: ret->type = type;
1328: if (sshkey_is_cert(ret)) {
1329: if (!sshkey_is_cert(k)) {
1.1 djm 1330: sshkey_free(k);
1.63 djm 1331: return SSH_ERR_EXPECTED_CERT;
1.1 djm 1332: }
1.63 djm 1333: if (ret->cert != NULL)
1334: cert_free(ret->cert);
1335: ret->cert = k->cert;
1336: k->cert = NULL;
1337: }
1338: switch (sshkey_type_plain(ret->type)) {
1.1 djm 1339: #ifdef WITH_OPENSSL
1.63 djm 1340: case KEY_RSA:
1341: RSA_free(ret->rsa);
1342: ret->rsa = k->rsa;
1343: k->rsa = NULL;
1.1 djm 1344: #ifdef DEBUG_PK
1.63 djm 1345: RSA_print_fp(stderr, ret->rsa, 8);
1.1 djm 1346: #endif
1.63 djm 1347: break;
1348: case KEY_DSA:
1349: DSA_free(ret->dsa);
1350: ret->dsa = k->dsa;
1351: k->dsa = NULL;
1.1 djm 1352: #ifdef DEBUG_PK
1.63 djm 1353: DSA_print_fp(stderr, ret->dsa, 8);
1.1 djm 1354: #endif
1.63 djm 1355: break;
1356: case KEY_ECDSA:
1357: EC_KEY_free(ret->ecdsa);
1358: ret->ecdsa = k->ecdsa;
1359: ret->ecdsa_nid = k->ecdsa_nid;
1360: k->ecdsa = NULL;
1361: k->ecdsa_nid = -1;
1.1 djm 1362: #ifdef DEBUG_PK
1.63 djm 1363: sshkey_dump_ec_key(ret->ecdsa);
1.1 djm 1364: #endif
1.63 djm 1365: break;
1.85 ! djm 1366: case KEY_ECDSA_SK:
! 1367: EC_KEY_free(ret->ecdsa);
! 1368: ret->ecdsa = k->ecdsa;
! 1369: ret->ecdsa_nid = k->ecdsa_nid;
! 1370: ret->sk_application = k->sk_application;
! 1371: k->ecdsa = NULL;
! 1372: k->ecdsa_nid = -1;
! 1373: k->sk_application = NULL;
! 1374: #ifdef DEBUG_PK
! 1375: sshkey_dump_ec_key(ret->ecdsa);
! 1376: fprintf(stderr, "App: %s\n", ret->sk_application);
! 1377: #endif
! 1378: break;
1.1 djm 1379: #endif /* WITH_OPENSSL */
1.63 djm 1380: case KEY_ED25519:
1381: freezero(ret->ed25519_pk, ED25519_PK_SZ);
1382: ret->ed25519_pk = k->ed25519_pk;
1383: k->ed25519_pk = NULL;
1.1 djm 1384: #ifdef DEBUG_PK
1.63 djm 1385: /* XXX */
1.1 djm 1386: #endif
1.63 djm 1387: break;
1.62 markus 1388: #ifdef WITH_XMSS
1.63 djm 1389: case KEY_XMSS:
1390: free(ret->xmss_pk);
1391: ret->xmss_pk = k->xmss_pk;
1392: k->xmss_pk = NULL;
1393: free(ret->xmss_state);
1394: ret->xmss_state = k->xmss_state;
1395: k->xmss_state = NULL;
1396: free(ret->xmss_name);
1397: ret->xmss_name = k->xmss_name;
1398: k->xmss_name = NULL;
1399: free(ret->xmss_filename);
1400: ret->xmss_filename = k->xmss_filename;
1401: k->xmss_filename = NULL;
1.62 markus 1402: #ifdef DEBUG_PK
1.63 djm 1403: /* XXX */
1.62 markus 1404: #endif
1.63 djm 1405: break;
1.62 markus 1406: #endif /* WITH_XMSS */
1.63 djm 1407: default:
1.1 djm 1408: sshkey_free(k);
1.63 djm 1409: return SSH_ERR_INTERNAL_ERROR;
1.1 djm 1410: }
1.63 djm 1411: sshkey_free(k);
1412:
1413: /* success */
1414: *cpp = cp;
1415: return 0;
1.1 djm 1416: }
1417:
1418: int
1.19 djm 1419: sshkey_to_base64(const struct sshkey *key, char **b64p)
1.1 djm 1420: {
1.19 djm 1421: int r = SSH_ERR_INTERNAL_ERROR;
1422: struct sshbuf *b = NULL;
1.1 djm 1423: char *uu = NULL;
1.19 djm 1424:
1425: if (b64p != NULL)
1426: *b64p = NULL;
1427: if ((b = sshbuf_new()) == NULL)
1428: return SSH_ERR_ALLOC_FAIL;
1429: if ((r = sshkey_putb(key, b)) != 0)
1430: goto out;
1.81 djm 1431: if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) {
1.19 djm 1432: r = SSH_ERR_ALLOC_FAIL;
1433: goto out;
1434: }
1435: /* Success */
1436: if (b64p != NULL) {
1437: *b64p = uu;
1438: uu = NULL;
1439: }
1440: r = 0;
1441: out:
1442: sshbuf_free(b);
1443: free(uu);
1444: return r;
1445: }
1446:
1.52 djm 1447: int
1.19 djm 1448: sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1449: {
1450: int r = SSH_ERR_INTERNAL_ERROR;
1451: char *uu = NULL;
1452:
1.48 djm 1453: if ((r = sshkey_to_base64(key, &uu)) != 0)
1454: goto out;
1455: if ((r = sshbuf_putf(b, "%s %s",
1456: sshkey_ssh_name(key), uu)) != 0)
1457: goto out;
1.19 djm 1458: r = 0;
1459: out:
1460: free(uu);
1461: return r;
1462: }
1463:
1464: int
1465: sshkey_write(const struct sshkey *key, FILE *f)
1466: {
1467: struct sshbuf *b = NULL;
1468: int r = SSH_ERR_INTERNAL_ERROR;
1469:
1470: if ((b = sshbuf_new()) == NULL)
1471: return SSH_ERR_ALLOC_FAIL;
1472: if ((r = sshkey_format_text(key, b)) != 0)
1.1 djm 1473: goto out;
1474: if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1475: if (feof(f))
1476: errno = EPIPE;
1.19 djm 1477: r = SSH_ERR_SYSTEM_ERROR;
1.1 djm 1478: goto out;
1479: }
1.19 djm 1480: /* Success */
1481: r = 0;
1.1 djm 1482: out:
1.19 djm 1483: sshbuf_free(b);
1484: return r;
1.1 djm 1485: }
1486:
1487: const char *
1488: sshkey_cert_type(const struct sshkey *k)
1489: {
1490: switch (k->cert->type) {
1491: case SSH2_CERT_TYPE_USER:
1492: return "user";
1493: case SSH2_CERT_TYPE_HOST:
1494: return "host";
1495: default:
1496: return "unknown";
1497: }
1498: }
1499:
1500: #ifdef WITH_OPENSSL
1501: static int
1502: rsa_generate_private_key(u_int bits, RSA **rsap)
1503: {
1504: RSA *private = NULL;
1505: BIGNUM *f4 = NULL;
1506: int ret = SSH_ERR_INTERNAL_ERROR;
1507:
1.49 djm 1508: if (rsap == NULL)
1509: return SSH_ERR_INVALID_ARGUMENT;
1510: if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1.1 djm 1511: bits > SSHBUF_MAX_BIGNUM * 8)
1.49 djm 1512: return SSH_ERR_KEY_LENGTH;
1.1 djm 1513: *rsap = NULL;
1514: if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1515: ret = SSH_ERR_ALLOC_FAIL;
1516: goto out;
1517: }
1518: if (!BN_set_word(f4, RSA_F4) ||
1519: !RSA_generate_key_ex(private, bits, f4, NULL)) {
1520: ret = SSH_ERR_LIBCRYPTO_ERROR;
1521: goto out;
1522: }
1523: *rsap = private;
1524: private = NULL;
1525: ret = 0;
1526: out:
1.60 jsing 1527: RSA_free(private);
1528: BN_free(f4);
1.1 djm 1529: return ret;
1530: }
1531:
1532: static int
1533: dsa_generate_private_key(u_int bits, DSA **dsap)
1534: {
1535: DSA *private;
1536: int ret = SSH_ERR_INTERNAL_ERROR;
1537:
1.49 djm 1538: if (dsap == NULL)
1.1 djm 1539: return SSH_ERR_INVALID_ARGUMENT;
1.49 djm 1540: if (bits != 1024)
1541: return SSH_ERR_KEY_LENGTH;
1.1 djm 1542: if ((private = DSA_new()) == NULL) {
1543: ret = SSH_ERR_ALLOC_FAIL;
1544: goto out;
1545: }
1546: *dsap = NULL;
1547: if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1548: NULL, NULL) || !DSA_generate_key(private)) {
1549: ret = SSH_ERR_LIBCRYPTO_ERROR;
1550: goto out;
1551: }
1552: *dsap = private;
1553: private = NULL;
1554: ret = 0;
1555: out:
1.60 jsing 1556: DSA_free(private);
1.1 djm 1557: return ret;
1558: }
1559:
1560: int
1561: sshkey_ecdsa_key_to_nid(EC_KEY *k)
1562: {
1563: EC_GROUP *eg;
1564: int nids[] = {
1565: NID_X9_62_prime256v1,
1566: NID_secp384r1,
1567: NID_secp521r1,
1568: -1
1569: };
1570: int nid;
1571: u_int i;
1572: BN_CTX *bnctx;
1573: const EC_GROUP *g = EC_KEY_get0_group(k);
1574:
1575: /*
1576: * The group may be stored in a ASN.1 encoded private key in one of two
1577: * ways: as a "named group", which is reconstituted by ASN.1 object ID
1578: * or explicit group parameters encoded into the key blob. Only the
1579: * "named group" case sets the group NID for us, but we can figure
1580: * it out for the other case by comparing against all the groups that
1581: * are supported.
1582: */
1583: if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1584: return nid;
1585: if ((bnctx = BN_CTX_new()) == NULL)
1586: return -1;
1587: for (i = 0; nids[i] != -1; i++) {
1588: if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
1589: BN_CTX_free(bnctx);
1590: return -1;
1591: }
1592: if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1593: break;
1594: EC_GROUP_free(eg);
1595: }
1596: BN_CTX_free(bnctx);
1597: if (nids[i] != -1) {
1598: /* Use the group with the NID attached */
1599: EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1600: if (EC_KEY_set_group(k, eg) != 1) {
1601: EC_GROUP_free(eg);
1602: return -1;
1603: }
1604: }
1605: return nids[i];
1606: }
1607:
1608: static int
1609: ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1610: {
1611: EC_KEY *private;
1612: int ret = SSH_ERR_INTERNAL_ERROR;
1613:
1.50 djm 1614: if (nid == NULL || ecdsap == NULL)
1.1 djm 1615: return SSH_ERR_INVALID_ARGUMENT;
1.50 djm 1616: if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1617: return SSH_ERR_KEY_LENGTH;
1.1 djm 1618: *ecdsap = NULL;
1619: if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1620: ret = SSH_ERR_ALLOC_FAIL;
1621: goto out;
1622: }
1623: if (EC_KEY_generate_key(private) != 1) {
1624: ret = SSH_ERR_LIBCRYPTO_ERROR;
1625: goto out;
1626: }
1627: EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1628: *ecdsap = private;
1629: private = NULL;
1630: ret = 0;
1631: out:
1.60 jsing 1632: EC_KEY_free(private);
1.1 djm 1633: return ret;
1634: }
1635: #endif /* WITH_OPENSSL */
1636:
1637: int
1638: sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1639: {
1640: struct sshkey *k;
1641: int ret = SSH_ERR_INTERNAL_ERROR;
1642:
1643: if (keyp == NULL)
1644: return SSH_ERR_INVALID_ARGUMENT;
1645: *keyp = NULL;
1646: if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1647: return SSH_ERR_ALLOC_FAIL;
1648: switch (type) {
1649: case KEY_ED25519:
1650: if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1651: (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1652: ret = SSH_ERR_ALLOC_FAIL;
1653: break;
1654: }
1655: crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1656: ret = 0;
1657: break;
1.62 markus 1658: #ifdef WITH_XMSS
1659: case KEY_XMSS:
1660: ret = sshkey_xmss_generate_private_key(k, bits);
1661: break;
1662: #endif /* WITH_XMSS */
1.1 djm 1663: #ifdef WITH_OPENSSL
1664: case KEY_DSA:
1665: ret = dsa_generate_private_key(bits, &k->dsa);
1666: break;
1667: case KEY_ECDSA:
1668: ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1669: &k->ecdsa);
1670: break;
1671: case KEY_RSA:
1672: ret = rsa_generate_private_key(bits, &k->rsa);
1673: break;
1674: #endif /* WITH_OPENSSL */
1675: default:
1676: ret = SSH_ERR_INVALID_ARGUMENT;
1677: }
1678: if (ret == 0) {
1679: k->type = type;
1680: *keyp = k;
1681: } else
1682: sshkey_free(k);
1683: return ret;
1684: }
1685:
1686: int
1687: sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1688: {
1689: u_int i;
1690: const struct sshkey_cert *from;
1691: struct sshkey_cert *to;
1.67 djm 1692: int r = SSH_ERR_INTERNAL_ERROR;
1.1 djm 1693:
1.67 djm 1694: if (to_key == NULL || (from = from_key->cert) == NULL)
1.1 djm 1695: return SSH_ERR_INVALID_ARGUMENT;
1696:
1.67 djm 1697: if ((to = cert_new()) == NULL)
1.1 djm 1698: return SSH_ERR_ALLOC_FAIL;
1699:
1.67 djm 1700: if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1701: (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
1702: (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
1703: goto out;
1.1 djm 1704:
1705: to->serial = from->serial;
1706: to->type = from->type;
1707: if (from->key_id == NULL)
1708: to->key_id = NULL;
1.67 djm 1709: else if ((to->key_id = strdup(from->key_id)) == NULL) {
1710: r = SSH_ERR_ALLOC_FAIL;
1711: goto out;
1712: }
1.1 djm 1713: to->valid_after = from->valid_after;
1714: to->valid_before = from->valid_before;
1715: if (from->signature_key == NULL)
1716: to->signature_key = NULL;
1.67 djm 1717: else if ((r = sshkey_from_private(from->signature_key,
1.1 djm 1718: &to->signature_key)) != 0)
1.67 djm 1719: goto out;
1720: if (from->signature_type != NULL &&
1721: (to->signature_type = strdup(from->signature_type)) == NULL) {
1722: r = SSH_ERR_ALLOC_FAIL;
1723: goto out;
1724: }
1725: if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
1726: r = SSH_ERR_INVALID_ARGUMENT;
1727: goto out;
1728: }
1.1 djm 1729: if (from->nprincipals > 0) {
1730: if ((to->principals = calloc(from->nprincipals,
1.67 djm 1731: sizeof(*to->principals))) == NULL) {
1732: r = SSH_ERR_ALLOC_FAIL;
1733: goto out;
1734: }
1.1 djm 1735: for (i = 0; i < from->nprincipals; i++) {
1736: to->principals[i] = strdup(from->principals[i]);
1737: if (to->principals[i] == NULL) {
1738: to->nprincipals = i;
1.67 djm 1739: r = SSH_ERR_ALLOC_FAIL;
1740: goto out;
1.1 djm 1741: }
1742: }
1743: }
1744: to->nprincipals = from->nprincipals;
1.67 djm 1745:
1746: /* success */
1747: cert_free(to_key->cert);
1748: to_key->cert = to;
1749: to = NULL;
1750: r = 0;
1751: out:
1752: cert_free(to);
1753: return r;
1.1 djm 1754: }
1755:
1756: int
1757: sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1758: {
1759: struct sshkey *n = NULL;
1.69 djm 1760: int r = SSH_ERR_INTERNAL_ERROR;
1761: #ifdef WITH_OPENSSL
1762: const BIGNUM *rsa_n, *rsa_e;
1763: BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
1764: const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
1765: BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL;
1766: BIGNUM *dsa_pub_key_dup = NULL;
1767: #endif /* WITH_OPENSSL */
1.1 djm 1768:
1.24 djm 1769: *pkp = NULL;
1.85 ! djm 1770: if ((n = sshkey_new(k->type)) == NULL) {
! 1771: r = SSH_ERR_ALLOC_FAIL;
! 1772: goto out;
! 1773: }
1.1 djm 1774: switch (k->type) {
1775: #ifdef WITH_OPENSSL
1776: case KEY_DSA:
1777: case KEY_DSA_CERT:
1.69 djm 1778: DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
1779: DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
1780: if ((dsa_p_dup = BN_dup(dsa_p)) == NULL ||
1781: (dsa_q_dup = BN_dup(dsa_q)) == NULL ||
1782: (dsa_g_dup = BN_dup(dsa_g)) == NULL ||
1783: (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) {
1784: r = SSH_ERR_ALLOC_FAIL;
1785: goto out;
1786: }
1787: if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) {
1788: r = SSH_ERR_LIBCRYPTO_ERROR;
1789: goto out;
1.1 djm 1790: }
1.69 djm 1791: dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */
1792: if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) {
1793: r = SSH_ERR_LIBCRYPTO_ERROR;
1794: goto out;
1795: }
1796: dsa_pub_key_dup = NULL; /* transferred */
1797:
1.1 djm 1798: break;
1799: case KEY_ECDSA:
1800: case KEY_ECDSA_CERT:
1.85 ! djm 1801: case KEY_ECDSA_SK:
! 1802: case KEY_ECDSA_SK_CERT:
1.1 djm 1803: n->ecdsa_nid = k->ecdsa_nid;
1804: n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1805: if (n->ecdsa == NULL) {
1.69 djm 1806: r = SSH_ERR_ALLOC_FAIL;
1807: goto out;
1.1 djm 1808: }
1809: if (EC_KEY_set_public_key(n->ecdsa,
1810: EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1.69 djm 1811: r = SSH_ERR_LIBCRYPTO_ERROR;
1812: goto out;
1.1 djm 1813: }
1.85 ! djm 1814: if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT)
! 1815: break;
! 1816: /* Append security-key application string */
! 1817: if ((n->sk_application = strdup(k->sk_application)) == NULL)
! 1818: goto out;
1.1 djm 1819: break;
1820: case KEY_RSA:
1821: case KEY_RSA_CERT:
1.69 djm 1822: RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
1823: if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
1824: (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
1825: r = SSH_ERR_ALLOC_FAIL;
1826: goto out;
1827: }
1828: if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
1829: r = SSH_ERR_LIBCRYPTO_ERROR;
1830: goto out;
1831: }
1832: rsa_n_dup = rsa_e_dup = NULL; /* transferred */
1.1 djm 1833: break;
1834: #endif /* WITH_OPENSSL */
1835: case KEY_ED25519:
1836: case KEY_ED25519_CERT:
1837: if (k->ed25519_pk != NULL) {
1838: if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1.69 djm 1839: r = SSH_ERR_ALLOC_FAIL;
1840: goto out;
1.1 djm 1841: }
1842: memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1843: }
1844: break;
1.62 markus 1845: #ifdef WITH_XMSS
1846: case KEY_XMSS:
1847: case KEY_XMSS_CERT:
1.69 djm 1848: if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
1849: goto out;
1.62 markus 1850: if (k->xmss_pk != NULL) {
1851: size_t pklen = sshkey_xmss_pklen(k);
1852: if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1.69 djm 1853: r = SSH_ERR_INTERNAL_ERROR;
1854: goto out;
1.62 markus 1855: }
1856: if ((n->xmss_pk = malloc(pklen)) == NULL) {
1.69 djm 1857: r = SSH_ERR_ALLOC_FAIL;
1858: goto out;
1.62 markus 1859: }
1860: memcpy(n->xmss_pk, k->xmss_pk, pklen);
1861: }
1862: break;
1863: #endif /* WITH_XMSS */
1.1 djm 1864: default:
1.69 djm 1865: r = SSH_ERR_KEY_TYPE_UNKNOWN;
1866: goto out;
1.1 djm 1867: }
1.69 djm 1868: if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
1869: goto out;
1870: /* success */
1.1 djm 1871: *pkp = n;
1.69 djm 1872: n = NULL;
1873: r = 0;
1874: out:
1875: sshkey_free(n);
1.83 djm 1876: #ifdef WITH_OPENSSL
1.69 djm 1877: BN_clear_free(rsa_n_dup);
1878: BN_clear_free(rsa_e_dup);
1879: BN_clear_free(dsa_p_dup);
1880: BN_clear_free(dsa_q_dup);
1881: BN_clear_free(dsa_g_dup);
1882: BN_clear_free(dsa_pub_key_dup);
1.83 djm 1883: #endif /* WITH_OPENSSL */
1.69 djm 1884:
1885: return r;
1.1 djm 1886: }
1887:
1.76 djm 1888: int
1889: sshkey_is_shielded(struct sshkey *k)
1890: {
1891: return k != NULL && k->shielded_private != NULL;
1892: }
1893:
1894: int
1895: sshkey_shield_private(struct sshkey *k)
1896: {
1897: struct sshbuf *prvbuf = NULL;
1898: u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
1899: struct sshcipher_ctx *cctx = NULL;
1900: const struct sshcipher *cipher;
1901: size_t i, enclen = 0;
1902: struct sshkey *kswap = NULL, tmp;
1903: int r = SSH_ERR_INTERNAL_ERROR;
1904:
1905: #ifdef DEBUG_PK
1906: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1907: #endif
1908: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1909: r = SSH_ERR_INVALID_ARGUMENT;
1910: goto out;
1911: }
1912: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1913: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1914: r = SSH_ERR_INTERNAL_ERROR;
1915: goto out;
1916: }
1917:
1918: /* Prepare a random pre-key, and from it an ephemeral key */
1919: if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
1920: r = SSH_ERR_ALLOC_FAIL;
1921: goto out;
1922: }
1923: arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1924: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1925: prekey, SSHKEY_SHIELD_PREKEY_LEN,
1926: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1927: goto out;
1928: #ifdef DEBUG_PK
1929: fprintf(stderr, "%s: key+iv\n", __func__);
1930: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1931: stderr);
1932: #endif
1933: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1934: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
1935: goto out;
1936:
1937: /* Serialise and encrypt the private key using the ephemeral key */
1938: if ((prvbuf = sshbuf_new()) == NULL) {
1939: r = SSH_ERR_ALLOC_FAIL;
1940: goto out;
1941: }
1942: if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
1943: goto out;
1944: if ((r = sshkey_private_serialize_opt(k, prvbuf,
1945: SSHKEY_SERIALIZE_FULL)) != 0)
1946: goto out;
1947: /* pad to cipher blocksize */
1948: i = 0;
1949: while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
1950: if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
1951: goto out;
1952: }
1953: #ifdef DEBUG_PK
1954: fprintf(stderr, "%s: serialised\n", __func__);
1955: sshbuf_dump(prvbuf, stderr);
1956: #endif
1957: /* encrypt */
1958: enclen = sshbuf_len(prvbuf);
1959: if ((enc = malloc(enclen)) == NULL) {
1960: r = SSH_ERR_ALLOC_FAIL;
1961: goto out;
1962: }
1963: if ((r = cipher_crypt(cctx, 0, enc,
1964: sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
1965: goto out;
1966: #ifdef DEBUG_PK
1967: fprintf(stderr, "%s: encrypted\n", __func__);
1968: sshbuf_dump_data(enc, enclen, stderr);
1969: #endif
1970:
1971: /* Make a scrubbed, public-only copy of our private key argument */
1972: if ((r = sshkey_from_private(k, &kswap)) != 0)
1973: goto out;
1974:
1975: /* Swap the private key out (it will be destroyed below) */
1976: tmp = *kswap;
1977: *kswap = *k;
1978: *k = tmp;
1979:
1980: /* Insert the shielded key into our argument */
1981: k->shielded_private = enc;
1982: k->shielded_len = enclen;
1983: k->shield_prekey = prekey;
1984: k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
1985: enc = prekey = NULL; /* transferred */
1986: enclen = 0;
1987:
1988: /* success */
1989: r = 0;
1990:
1991: out:
1992: /* XXX behaviour on error - invalidate original private key? */
1993: cipher_free(cctx);
1994: explicit_bzero(keyiv, sizeof(keyiv));
1995: explicit_bzero(&tmp, sizeof(tmp));
1.78 djm 1996: freezero(enc, enclen);
1.76 djm 1997: freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1998: sshkey_free(kswap);
1999: sshbuf_free(prvbuf);
2000: return r;
2001: }
2002:
2003: int
2004: sshkey_unshield_private(struct sshkey *k)
2005: {
2006: struct sshbuf *prvbuf = NULL;
2007: u_char pad, *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
2008: struct sshcipher_ctx *cctx = NULL;
2009: const struct sshcipher *cipher;
2010: size_t i;
2011: struct sshkey *kswap = NULL, tmp;
2012: int r = SSH_ERR_INTERNAL_ERROR;
2013:
2014: #ifdef DEBUG_PK
2015: fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
2016: #endif
2017: if (!sshkey_is_shielded(k))
2018: return 0; /* nothing to do */
2019:
2020: if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
2021: r = SSH_ERR_INVALID_ARGUMENT;
2022: goto out;
2023: }
2024: if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
2025: ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
2026: r = SSH_ERR_INTERNAL_ERROR;
2027: goto out;
2028: }
2029: /* check size of shielded key blob */
2030: if (k->shielded_len < cipher_blocksize(cipher) ||
2031: (k->shielded_len % cipher_blocksize(cipher)) != 0) {
2032: r = SSH_ERR_INVALID_FORMAT;
2033: goto out;
2034: }
2035:
2036: /* Calculate the ephemeral key from the prekey */
2037: if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
2038: k->shield_prekey, k->shield_prekey_len,
2039: keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
2040: goto out;
2041: if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
2042: keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
2043: goto out;
2044: #ifdef DEBUG_PK
2045: fprintf(stderr, "%s: key+iv\n", __func__);
2046: sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
2047: stderr);
2048: #endif
2049:
2050: /* Decrypt and parse the shielded private key using the ephemeral key */
2051: if ((prvbuf = sshbuf_new()) == NULL) {
2052: r = SSH_ERR_ALLOC_FAIL;
2053: goto out;
2054: }
2055: if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
2056: goto out;
2057: /* decrypt */
2058: #ifdef DEBUG_PK
2059: fprintf(stderr, "%s: encrypted\n", __func__);
2060: sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
2061: #endif
2062: if ((r = cipher_crypt(cctx, 0, cp,
2063: k->shielded_private, k->shielded_len, 0, 0)) != 0)
2064: goto out;
2065: #ifdef DEBUG_PK
2066: fprintf(stderr, "%s: serialised\n", __func__);
2067: sshbuf_dump(prvbuf, stderr);
2068: #endif
2069: /* Parse private key */
2070: if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
2071: goto out;
2072: /* Check deterministic padding */
2073: i = 0;
2074: while (sshbuf_len(prvbuf)) {
2075: if ((r = sshbuf_get_u8(prvbuf, &pad)) != 0)
2076: goto out;
2077: if (pad != (++i & 0xff)) {
2078: r = SSH_ERR_INVALID_FORMAT;
2079: goto out;
2080: }
2081: }
2082:
2083: /* Swap the parsed key back into place */
2084: tmp = *kswap;
2085: *kswap = *k;
2086: *k = tmp;
2087:
2088: /* success */
2089: r = 0;
2090:
2091: out:
2092: cipher_free(cctx);
2093: explicit_bzero(keyiv, sizeof(keyiv));
2094: explicit_bzero(&tmp, sizeof(tmp));
2095: sshkey_free(kswap);
2096: sshbuf_free(prvbuf);
2097: return r;
2098: }
2099:
1.1 djm 2100: static int
1.14 djm 2101: cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1.1 djm 2102: {
1.14 djm 2103: struct sshbuf *principals = NULL, *crit = NULL;
2104: struct sshbuf *exts = NULL, *ca = NULL;
2105: u_char *sig = NULL;
2106: size_t signed_len = 0, slen = 0, kidlen = 0;
1.1 djm 2107: int ret = SSH_ERR_INTERNAL_ERROR;
2108:
2109: /* Copy the entire key blob for verification and later serialisation */
1.14 djm 2110: if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
1.1 djm 2111: return ret;
2112:
1.20 djm 2113: /* Parse body of certificate up to signature */
2114: if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
1.1 djm 2115: (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
2116: (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1.4 djm 2117: (ret = sshbuf_froms(b, &principals)) != 0 ||
1.1 djm 2118: (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
2119: (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1.4 djm 2120: (ret = sshbuf_froms(b, &crit)) != 0 ||
1.20 djm 2121: (ret = sshbuf_froms(b, &exts)) != 0 ||
1.1 djm 2122: (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1.14 djm 2123: (ret = sshbuf_froms(b, &ca)) != 0) {
1.1 djm 2124: /* XXX debug print error for ret */
2125: ret = SSH_ERR_INVALID_FORMAT;
2126: goto out;
2127: }
2128:
2129: /* Signature is left in the buffer so we can calculate this length */
2130: signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
2131:
2132: if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
2133: ret = SSH_ERR_INVALID_FORMAT;
2134: goto out;
2135: }
2136:
2137: if (key->cert->type != SSH2_CERT_TYPE_USER &&
2138: key->cert->type != SSH2_CERT_TYPE_HOST) {
2139: ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
2140: goto out;
2141: }
2142:
1.4 djm 2143: /* Parse principals section */
2144: while (sshbuf_len(principals) > 0) {
2145: char *principal = NULL;
2146: char **oprincipals = NULL;
2147:
1.1 djm 2148: if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
2149: ret = SSH_ERR_INVALID_FORMAT;
2150: goto out;
2151: }
1.4 djm 2152: if ((ret = sshbuf_get_cstring(principals, &principal,
2153: NULL)) != 0) {
1.1 djm 2154: ret = SSH_ERR_INVALID_FORMAT;
2155: goto out;
2156: }
2157: oprincipals = key->cert->principals;
1.51 deraadt 2158: key->cert->principals = recallocarray(key->cert->principals,
2159: key->cert->nprincipals, key->cert->nprincipals + 1,
2160: sizeof(*key->cert->principals));
1.1 djm 2161: if (key->cert->principals == NULL) {
2162: free(principal);
2163: key->cert->principals = oprincipals;
2164: ret = SSH_ERR_ALLOC_FAIL;
2165: goto out;
2166: }
2167: key->cert->principals[key->cert->nprincipals++] = principal;
2168: }
2169:
1.4 djm 2170: /*
2171: * Stash a copies of the critical options and extensions sections
2172: * for later use.
2173: */
2174: if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
2175: (exts != NULL &&
2176: (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1.1 djm 2177: goto out;
2178:
1.4 djm 2179: /*
2180: * Validate critical options and extensions sections format.
2181: */
2182: while (sshbuf_len(crit) != 0) {
2183: if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
2184: (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
2185: sshbuf_reset(key->cert->critical);
1.1 djm 2186: ret = SSH_ERR_INVALID_FORMAT;
2187: goto out;
2188: }
2189: }
1.4 djm 2190: while (exts != NULL && sshbuf_len(exts) != 0) {
2191: if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
2192: (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
2193: sshbuf_reset(key->cert->extensions);
1.1 djm 2194: ret = SSH_ERR_INVALID_FORMAT;
2195: goto out;
2196: }
2197: }
2198:
1.4 djm 2199: /* Parse CA key and check signature */
1.14 djm 2200: if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
1.1 djm 2201: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2202: goto out;
2203: }
2204: if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
2205: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2206: goto out;
2207: }
2208: if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1.59 djm 2209: sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1.1 djm 2210: goto out;
1.82 djm 2211: if ((ret = sshkey_get_sigtype(sig, slen,
2212: &key->cert->signature_type)) != 0)
1.67 djm 2213: goto out;
1.4 djm 2214:
2215: /* Success */
1.1 djm 2216: ret = 0;
2217: out:
1.14 djm 2218: sshbuf_free(ca);
1.4 djm 2219: sshbuf_free(crit);
2220: sshbuf_free(exts);
2221: sshbuf_free(principals);
1.1 djm 2222: free(sig);
2223: return ret;
2224: }
2225:
1.83 djm 2226: #ifdef WITH_OPENSSL
1.1 djm 2227: static int
1.69 djm 2228: check_rsa_length(const RSA *rsa)
2229: {
2230: const BIGNUM *rsa_n;
2231:
2232: RSA_get0_key(rsa, &rsa_n, NULL, NULL);
2233: if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
2234: return SSH_ERR_KEY_LENGTH;
2235: return 0;
2236: }
1.83 djm 2237: #endif /* WITH_OPENSSL */
1.69 djm 2238:
2239: static int
1.14 djm 2240: sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
2241: int allow_cert)
1.1 djm 2242: {
1.12 djm 2243: int type, ret = SSH_ERR_INTERNAL_ERROR;
1.62 markus 2244: char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 2245: struct sshkey *key = NULL;
2246: size_t len;
2247: u_char *pk = NULL;
1.14 djm 2248: struct sshbuf *copy;
1.1 djm 2249: #ifdef WITH_OPENSSL
2250: EC_POINT *q = NULL;
1.69 djm 2251: BIGNUM *rsa_n = NULL, *rsa_e = NULL;
2252: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
1.1 djm 2253: #endif /* WITH_OPENSSL */
2254:
2255: #ifdef DEBUG_PK /* XXX */
1.14 djm 2256: sshbuf_dump(b, stderr);
1.1 djm 2257: #endif
1.32 djm 2258: if (keyp != NULL)
2259: *keyp = NULL;
1.14 djm 2260: if ((copy = sshbuf_fromb(b)) == NULL) {
2261: ret = SSH_ERR_ALLOC_FAIL;
2262: goto out;
2263: }
1.1 djm 2264: if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
2265: ret = SSH_ERR_INVALID_FORMAT;
2266: goto out;
2267: }
2268:
2269: type = sshkey_type_from_name(ktype);
2270: if (!allow_cert && sshkey_type_is_cert(type)) {
2271: ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2272: goto out;
2273: }
2274: switch (type) {
2275: #ifdef WITH_OPENSSL
2276: case KEY_RSA_CERT:
1.14 djm 2277: /* Skip nonce */
1.1 djm 2278: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2279: ret = SSH_ERR_INVALID_FORMAT;
2280: goto out;
2281: }
2282: /* FALLTHROUGH */
2283: case KEY_RSA:
2284: if ((key = sshkey_new(type)) == NULL) {
2285: ret = SSH_ERR_ALLOC_FAIL;
2286: goto out;
2287: }
1.73 djm 2288: if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
2289: sshbuf_get_bignum2(b, &rsa_n) != 0) {
1.1 djm 2290: ret = SSH_ERR_INVALID_FORMAT;
2291: goto out;
2292: }
1.69 djm 2293: if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
2294: ret = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 2295: goto out;
2296: }
1.69 djm 2297: rsa_n = rsa_e = NULL; /* transferred */
2298: if ((ret = check_rsa_length(key->rsa)) != 0)
2299: goto out;
1.1 djm 2300: #ifdef DEBUG_PK
2301: RSA_print_fp(stderr, key->rsa, 8);
2302: #endif
2303: break;
2304: case KEY_DSA_CERT:
1.14 djm 2305: /* Skip nonce */
1.1 djm 2306: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2307: ret = SSH_ERR_INVALID_FORMAT;
2308: goto out;
2309: }
2310: /* FALLTHROUGH */
2311: case KEY_DSA:
2312: if ((key = sshkey_new(type)) == NULL) {
2313: ret = SSH_ERR_ALLOC_FAIL;
2314: goto out;
2315: }
1.73 djm 2316: if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
2317: sshbuf_get_bignum2(b, &dsa_q) != 0 ||
2318: sshbuf_get_bignum2(b, &dsa_g) != 0 ||
2319: sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
1.1 djm 2320: ret = SSH_ERR_INVALID_FORMAT;
2321: goto out;
2322: }
1.69 djm 2323: if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
2324: ret = SSH_ERR_LIBCRYPTO_ERROR;
2325: goto out;
2326: }
2327: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
2328: if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
2329: ret = SSH_ERR_LIBCRYPTO_ERROR;
2330: goto out;
2331: }
2332: dsa_pub_key = NULL; /* transferred */
1.1 djm 2333: #ifdef DEBUG_PK
2334: DSA_print_fp(stderr, key->dsa, 8);
2335: #endif
2336: break;
2337: case KEY_ECDSA_CERT:
1.85 ! djm 2338: case KEY_ECDSA_SK_CERT:
1.14 djm 2339: /* Skip nonce */
1.1 djm 2340: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2341: ret = SSH_ERR_INVALID_FORMAT;
2342: goto out;
2343: }
2344: /* FALLTHROUGH */
2345: case KEY_ECDSA:
1.85 ! djm 2346: case KEY_ECDSA_SK:
1.1 djm 2347: if ((key = sshkey_new(type)) == NULL) {
2348: ret = SSH_ERR_ALLOC_FAIL;
2349: goto out;
2350: }
1.12 djm 2351: key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
1.1 djm 2352: if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
2353: ret = SSH_ERR_INVALID_FORMAT;
2354: goto out;
2355: }
2356: if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2357: ret = SSH_ERR_EC_CURVE_MISMATCH;
2358: goto out;
2359: }
1.60 jsing 2360: EC_KEY_free(key->ecdsa);
1.1 djm 2361: if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2362: == NULL) {
2363: ret = SSH_ERR_EC_CURVE_INVALID;
2364: goto out;
2365: }
2366: if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2367: ret = SSH_ERR_ALLOC_FAIL;
2368: goto out;
2369: }
2370: if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2371: ret = SSH_ERR_INVALID_FORMAT;
2372: goto out;
2373: }
2374: if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2375: q) != 0) {
2376: ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2377: goto out;
2378: }
2379: if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2380: /* XXX assume it is a allocation error */
2381: ret = SSH_ERR_ALLOC_FAIL;
2382: goto out;
2383: }
2384: #ifdef DEBUG_PK
2385: sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2386: #endif
1.85 ! djm 2387: if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
! 2388: /* Parse additional security-key application string */
! 2389: if (sshbuf_get_cstring(b, &key->sk_application,
! 2390: NULL) != 0) {
! 2391: ret = SSH_ERR_INVALID_FORMAT;
! 2392: goto out;
! 2393: }
! 2394: #ifdef DEBUG_PK
! 2395: fprintf(stderr, "App: %s\n", key->sk_application);
! 2396: #endif
! 2397: }
1.1 djm 2398: break;
2399: #endif /* WITH_OPENSSL */
2400: case KEY_ED25519_CERT:
1.14 djm 2401: /* Skip nonce */
1.1 djm 2402: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2403: ret = SSH_ERR_INVALID_FORMAT;
2404: goto out;
2405: }
2406: /* FALLTHROUGH */
2407: case KEY_ED25519:
2408: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2409: goto out;
2410: if (len != ED25519_PK_SZ) {
2411: ret = SSH_ERR_INVALID_FORMAT;
2412: goto out;
2413: }
2414: if ((key = sshkey_new(type)) == NULL) {
2415: ret = SSH_ERR_ALLOC_FAIL;
2416: goto out;
2417: }
2418: key->ed25519_pk = pk;
2419: pk = NULL;
2420: break;
1.62 markus 2421: #ifdef WITH_XMSS
2422: case KEY_XMSS_CERT:
2423: /* Skip nonce */
2424: if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2425: ret = SSH_ERR_INVALID_FORMAT;
2426: goto out;
2427: }
2428: /* FALLTHROUGH */
2429: case KEY_XMSS:
2430: if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2431: goto out;
2432: if ((key = sshkey_new(type)) == NULL) {
2433: ret = SSH_ERR_ALLOC_FAIL;
2434: goto out;
2435: }
2436: if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2437: goto out;
2438: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2439: goto out;
2440: if (len == 0 || len != sshkey_xmss_pklen(key)) {
2441: ret = SSH_ERR_INVALID_FORMAT;
2442: goto out;
2443: }
2444: key->xmss_pk = pk;
2445: pk = NULL;
2446: if (type != KEY_XMSS_CERT &&
2447: (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2448: goto out;
2449: break;
2450: #endif /* WITH_XMSS */
1.1 djm 2451: case KEY_UNSPEC:
2452: default:
2453: ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2454: goto out;
2455: }
2456:
2457: /* Parse certificate potion */
1.14 djm 2458: if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
1.1 djm 2459: goto out;
2460:
2461: if (key != NULL && sshbuf_len(b) != 0) {
2462: ret = SSH_ERR_INVALID_FORMAT;
2463: goto out;
2464: }
2465: ret = 0;
1.32 djm 2466: if (keyp != NULL) {
2467: *keyp = key;
2468: key = NULL;
2469: }
1.1 djm 2470: out:
1.14 djm 2471: sshbuf_free(copy);
1.1 djm 2472: sshkey_free(key);
1.62 markus 2473: free(xmss_name);
1.1 djm 2474: free(ktype);
2475: free(curve);
2476: free(pk);
2477: #ifdef WITH_OPENSSL
1.60 jsing 2478: EC_POINT_free(q);
1.69 djm 2479: BN_clear_free(rsa_n);
2480: BN_clear_free(rsa_e);
2481: BN_clear_free(dsa_p);
2482: BN_clear_free(dsa_q);
2483: BN_clear_free(dsa_g);
2484: BN_clear_free(dsa_pub_key);
1.1 djm 2485: #endif /* WITH_OPENSSL */
2486: return ret;
2487: }
2488:
2489: int
2490: sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2491: {
1.14 djm 2492: struct sshbuf *b;
2493: int r;
2494:
2495: if ((b = sshbuf_from(blob, blen)) == NULL)
2496: return SSH_ERR_ALLOC_FAIL;
2497: r = sshkey_from_blob_internal(b, keyp, 1);
2498: sshbuf_free(b);
2499: return r;
2500: }
2501:
2502: int
2503: sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
2504: {
2505: return sshkey_from_blob_internal(b, keyp, 1);
2506: }
2507:
2508: int
2509: sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2510: {
2511: struct sshbuf *b;
2512: int r;
2513:
2514: if ((r = sshbuf_froms(buf, &b)) != 0)
2515: return r;
2516: r = sshkey_from_blob_internal(b, keyp, 1);
1.58 djm 2517: sshbuf_free(b);
2518: return r;
2519: }
2520:
1.82 djm 2521: int
2522: sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
1.58 djm 2523: {
2524: int r;
2525: struct sshbuf *b = NULL;
2526: char *sigtype = NULL;
2527:
2528: if (sigtypep != NULL)
2529: *sigtypep = NULL;
2530: if ((b = sshbuf_from(sig, siglen)) == NULL)
2531: return SSH_ERR_ALLOC_FAIL;
2532: if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2533: goto out;
2534: /* success */
2535: if (sigtypep != NULL) {
2536: *sigtypep = sigtype;
2537: sigtype = NULL;
2538: }
2539: r = 0;
2540: out:
2541: free(sigtype);
1.14 djm 2542: sshbuf_free(b);
2543: return r;
1.68 djm 2544: }
2545:
2546: /*
2547: *
2548: * Checks whether a certificate's signature type is allowed.
2549: * Returns 0 (success) if the certificate signature type appears in the
2550: * "allowed" pattern-list, or the key is not a certificate to begin with.
2551: * Otherwise returns a ssherr.h code.
2552: */
2553: int
2554: sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
2555: {
2556: if (key == NULL || allowed == NULL)
2557: return SSH_ERR_INVALID_ARGUMENT;
2558: if (!sshkey_type_is_cert(key->type))
2559: return 0;
2560: if (key->cert == NULL || key->cert->signature_type == NULL)
2561: return SSH_ERR_INVALID_ARGUMENT;
2562: if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
2563: return SSH_ERR_SIGN_ALG_UNSUPPORTED;
2564: return 0;
1.65 djm 2565: }
2566:
2567: /*
2568: * Returns the expected signature algorithm for a given public key algorithm.
2569: */
1.66 djm 2570: const char *
2571: sshkey_sigalg_by_name(const char *name)
1.65 djm 2572: {
2573: const struct keytype *kt;
2574:
2575: for (kt = keytypes; kt->type != -1; kt++) {
2576: if (strcmp(kt->name, name) != 0)
2577: continue;
2578: if (kt->sigalg != NULL)
2579: return kt->sigalg;
2580: if (!kt->cert)
2581: return kt->name;
2582: return sshkey_ssh_name_from_type_nid(
2583: sshkey_type_plain(kt->type), kt->nid);
2584: }
2585: return NULL;
2586: }
2587:
2588: /*
2589: * Verifies that the signature algorithm appearing inside the signature blob
2590: * matches that which was requested.
2591: */
2592: int
2593: sshkey_check_sigtype(const u_char *sig, size_t siglen,
2594: const char *requested_alg)
2595: {
2596: const char *expected_alg;
2597: char *sigtype = NULL;
2598: int r;
2599:
2600: if (requested_alg == NULL)
2601: return 0;
1.66 djm 2602: if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
1.65 djm 2603: return SSH_ERR_INVALID_ARGUMENT;
1.82 djm 2604: if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
1.65 djm 2605: return r;
2606: r = strcmp(expected_alg, sigtype) == 0;
2607: free(sigtype);
2608: return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
1.1 djm 2609: }
2610:
2611: int
1.76 djm 2612: sshkey_sign(struct sshkey *key,
1.1 djm 2613: u_char **sigp, size_t *lenp,
1.28 markus 2614: const u_char *data, size_t datalen, const char *alg, u_int compat)
1.1 djm 2615: {
1.76 djm 2616: int was_shielded = sshkey_is_shielded(key);
2617: int r2, r = SSH_ERR_INTERNAL_ERROR;
2618:
1.1 djm 2619: if (sigp != NULL)
2620: *sigp = NULL;
2621: if (lenp != NULL)
2622: *lenp = 0;
2623: if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2624: return SSH_ERR_INVALID_ARGUMENT;
1.76 djm 2625: if ((r = sshkey_unshield_private(key)) != 0)
2626: return r;
1.1 djm 2627: switch (key->type) {
2628: #ifdef WITH_OPENSSL
2629: case KEY_DSA_CERT:
2630: case KEY_DSA:
1.76 djm 2631: r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2632: break;
1.1 djm 2633: case KEY_ECDSA_CERT:
2634: case KEY_ECDSA:
1.76 djm 2635: r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2636: break;
1.1 djm 2637: case KEY_RSA_CERT:
2638: case KEY_RSA:
1.76 djm 2639: r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2640: break;
1.1 djm 2641: #endif /* WITH_OPENSSL */
2642: case KEY_ED25519:
2643: case KEY_ED25519_CERT:
1.76 djm 2644: r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2645: break;
1.62 markus 2646: #ifdef WITH_XMSS
2647: case KEY_XMSS:
2648: case KEY_XMSS_CERT:
1.76 djm 2649: r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2650: break;
1.62 markus 2651: #endif /* WITH_XMSS */
1.1 djm 2652: default:
1.76 djm 2653: r = SSH_ERR_KEY_TYPE_UNKNOWN;
2654: break;
1.1 djm 2655: }
1.76 djm 2656: if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2657: return r2;
2658: return r;
1.1 djm 2659: }
2660:
2661: /*
2662: * ssh_key_verify returns 0 for a correct signature and < 0 on error.
1.59 djm 2663: * If "alg" specified, then the signature must use that algorithm.
1.1 djm 2664: */
2665: int
2666: sshkey_verify(const struct sshkey *key,
2667: const u_char *sig, size_t siglen,
1.59 djm 2668: const u_char *data, size_t dlen, const char *alg, u_int compat)
1.1 djm 2669: {
1.6 djm 2670: if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
1.1 djm 2671: return SSH_ERR_INVALID_ARGUMENT;
2672: switch (key->type) {
2673: #ifdef WITH_OPENSSL
2674: case KEY_DSA_CERT:
2675: case KEY_DSA:
2676: return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2677: case KEY_ECDSA_CERT:
2678: case KEY_ECDSA:
2679: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
1.85 ! djm 2680: case KEY_ECDSA_SK_CERT:
! 2681: case KEY_ECDSA_SK:
! 2682: return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
! 2683: compat);
1.1 djm 2684: case KEY_RSA_CERT:
2685: case KEY_RSA:
1.59 djm 2686: return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
1.1 djm 2687: #endif /* WITH_OPENSSL */
2688: case KEY_ED25519:
2689: case KEY_ED25519_CERT:
2690: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
1.62 markus 2691: #ifdef WITH_XMSS
2692: case KEY_XMSS:
2693: case KEY_XMSS_CERT:
2694: return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2695: #endif /* WITH_XMSS */
1.1 djm 2696: default:
2697: return SSH_ERR_KEY_TYPE_UNKNOWN;
2698: }
2699: }
2700:
2701: /* Convert a plain key to their _CERT equivalent */
2702: int
1.20 djm 2703: sshkey_to_certified(struct sshkey *k)
1.1 djm 2704: {
2705: int newtype;
2706:
2707: switch (k->type) {
2708: #ifdef WITH_OPENSSL
2709: case KEY_RSA:
1.20 djm 2710: newtype = KEY_RSA_CERT;
1.1 djm 2711: break;
2712: case KEY_DSA:
1.20 djm 2713: newtype = KEY_DSA_CERT;
1.1 djm 2714: break;
2715: case KEY_ECDSA:
2716: newtype = KEY_ECDSA_CERT;
2717: break;
1.85 ! djm 2718: case KEY_ECDSA_SK:
! 2719: newtype = KEY_ECDSA_SK_CERT;
! 2720: break;
1.1 djm 2721: #endif /* WITH_OPENSSL */
2722: case KEY_ED25519:
2723: newtype = KEY_ED25519_CERT;
2724: break;
1.62 markus 2725: #ifdef WITH_XMSS
2726: case KEY_XMSS:
2727: newtype = KEY_XMSS_CERT;
2728: break;
2729: #endif /* WITH_XMSS */
1.1 djm 2730: default:
2731: return SSH_ERR_INVALID_ARGUMENT;
2732: }
2733: if ((k->cert = cert_new()) == NULL)
2734: return SSH_ERR_ALLOC_FAIL;
2735: k->type = newtype;
2736: return 0;
2737: }
2738:
2739: /* Convert a certificate to its raw key equivalent */
2740: int
2741: sshkey_drop_cert(struct sshkey *k)
2742: {
2743: if (!sshkey_type_is_cert(k->type))
2744: return SSH_ERR_KEY_TYPE_UNKNOWN;
2745: cert_free(k->cert);
2746: k->cert = NULL;
2747: k->type = sshkey_type_plain(k->type);
2748: return 0;
2749: }
2750:
2751: /* Sign a certified key, (re-)generating the signed certblob. */
2752: int
1.53 djm 2753: sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2754: sshkey_certify_signer *signer, void *signer_ctx)
1.1 djm 2755: {
2756: struct sshbuf *principals = NULL;
2757: u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2758: size_t i, ca_len, sig_len;
2759: int ret = SSH_ERR_INTERNAL_ERROR;
1.67 djm 2760: struct sshbuf *cert = NULL;
2761: char *sigtype = NULL;
1.69 djm 2762: #ifdef WITH_OPENSSL
2763: const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
2764: #endif /* WITH_OPENSSL */
1.1 djm 2765:
2766: if (k == NULL || k->cert == NULL ||
2767: k->cert->certblob == NULL || ca == NULL)
2768: return SSH_ERR_INVALID_ARGUMENT;
2769: if (!sshkey_is_cert(k))
2770: return SSH_ERR_KEY_TYPE_UNKNOWN;
2771: if (!sshkey_type_is_valid_ca(ca->type))
2772: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2773:
1.67 djm 2774: /*
2775: * If no alg specified as argument but a signature_type was set,
2776: * then prefer that. If both were specified, then they must match.
2777: */
2778: if (alg == NULL)
2779: alg = k->cert->signature_type;
2780: else if (k->cert->signature_type != NULL &&
2781: strcmp(alg, k->cert->signature_type) != 0)
2782: return SSH_ERR_INVALID_ARGUMENT;
1.75 djm 2783:
2784: /*
2785: * If no signing algorithm or signature_type was specified and we're
2786: * using a RSA key, then default to a good signature algorithm.
2787: */
2788: if (alg == NULL && ca->type == KEY_RSA)
2789: alg = "rsa-sha2-512";
1.67 djm 2790:
1.1 djm 2791: if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2792: return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2793:
2794: cert = k->cert->certblob; /* for readability */
2795: sshbuf_reset(cert);
2796: if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2797: goto out;
2798:
2799: /* -v01 certs put nonce first */
2800: arc4random_buf(&nonce, sizeof(nonce));
1.20 djm 2801: if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2802: goto out;
1.1 djm 2803:
2804: /* XXX this substantially duplicates to_blob(); refactor */
2805: switch (k->type) {
2806: #ifdef WITH_OPENSSL
2807: case KEY_DSA_CERT:
1.69 djm 2808: DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
2809: DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
2810: if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
2811: (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
2812: (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
2813: (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
1.1 djm 2814: goto out;
2815: break;
2816: case KEY_ECDSA_CERT:
1.85 ! djm 2817: case KEY_ECDSA_SK_CERT:
1.1 djm 2818: if ((ret = sshbuf_put_cstring(cert,
2819: sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2820: (ret = sshbuf_put_ec(cert,
2821: EC_KEY_get0_public_key(k->ecdsa),
2822: EC_KEY_get0_group(k->ecdsa))) != 0)
2823: goto out;
1.85 ! djm 2824: if (k->type == KEY_ECDSA_SK_CERT) {
! 2825: if ((ret = sshbuf_put_cstring(cert,
! 2826: k->sk_application)) != 0)
! 2827: goto out;
! 2828: }
1.1 djm 2829: break;
2830: case KEY_RSA_CERT:
1.69 djm 2831: RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
2832: if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
2833: (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
1.1 djm 2834: goto out;
2835: break;
2836: #endif /* WITH_OPENSSL */
2837: case KEY_ED25519_CERT:
2838: if ((ret = sshbuf_put_string(cert,
2839: k->ed25519_pk, ED25519_PK_SZ)) != 0)
2840: goto out;
2841: break;
1.62 markus 2842: #ifdef WITH_XMSS
2843: case KEY_XMSS_CERT:
2844: if (k->xmss_name == NULL) {
2845: ret = SSH_ERR_INVALID_ARGUMENT;
2846: goto out;
2847: }
2848: if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2849: (ret = sshbuf_put_string(cert,
2850: k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2851: goto out;
2852: break;
2853: #endif /* WITH_XMSS */
1.1 djm 2854: default:
2855: ret = SSH_ERR_INVALID_ARGUMENT;
1.15 djm 2856: goto out;
1.1 djm 2857: }
2858:
1.20 djm 2859: if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
2860: (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
1.1 djm 2861: (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2862: goto out;
2863:
2864: if ((principals = sshbuf_new()) == NULL) {
2865: ret = SSH_ERR_ALLOC_FAIL;
2866: goto out;
2867: }
2868: for (i = 0; i < k->cert->nprincipals; i++) {
2869: if ((ret = sshbuf_put_cstring(principals,
2870: k->cert->principals[i])) != 0)
2871: goto out;
2872: }
2873: if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2874: (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2875: (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
1.20 djm 2876: (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
2877: (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
2878: (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
1.1 djm 2879: (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2880: goto out;
2881:
2882: /* Sign the whole mess */
1.53 djm 2883: if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2884: sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
1.1 djm 2885: goto out;
1.67 djm 2886: /* Check and update signature_type against what was actually used */
1.82 djm 2887: if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
1.67 djm 2888: goto out;
2889: if (alg != NULL && strcmp(alg, sigtype) != 0) {
2890: ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2891: goto out;
2892: }
2893: if (k->cert->signature_type == NULL) {
2894: k->cert->signature_type = sigtype;
2895: sigtype = NULL;
2896: }
1.1 djm 2897: /* Append signature and we are done */
2898: if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2899: goto out;
2900: ret = 0;
2901: out:
2902: if (ret != 0)
2903: sshbuf_reset(cert);
1.29 mmcc 2904: free(sig_blob);
2905: free(ca_blob);
1.67 djm 2906: free(sigtype);
1.31 mmcc 2907: sshbuf_free(principals);
1.1 djm 2908: return ret;
1.53 djm 2909: }
2910:
2911: static int
1.76 djm 2912: default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
1.53 djm 2913: const u_char *data, size_t datalen,
2914: const char *alg, u_int compat, void *ctx)
2915: {
2916: if (ctx != NULL)
2917: return SSH_ERR_INVALID_ARGUMENT;
2918: return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
2919: }
2920:
2921: int
2922: sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
2923: {
2924: return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
1.1 djm 2925: }
2926:
2927: int
2928: sshkey_cert_check_authority(const struct sshkey *k,
2929: int want_host, int require_principal,
2930: const char *name, const char **reason)
2931: {
2932: u_int i, principal_matches;
2933: time_t now = time(NULL);
2934:
2935: if (reason != NULL)
2936: *reason = NULL;
2937:
2938: if (want_host) {
2939: if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2940: *reason = "Certificate invalid: not a host certificate";
2941: return SSH_ERR_KEY_CERT_INVALID;
2942: }
2943: } else {
2944: if (k->cert->type != SSH2_CERT_TYPE_USER) {
2945: *reason = "Certificate invalid: not a user certificate";
2946: return SSH_ERR_KEY_CERT_INVALID;
2947: }
2948: }
2949: if (now < 0) {
2950: /* yikes - system clock before epoch! */
2951: *reason = "Certificate invalid: not yet valid";
2952: return SSH_ERR_KEY_CERT_INVALID;
2953: }
2954: if ((u_int64_t)now < k->cert->valid_after) {
2955: *reason = "Certificate invalid: not yet valid";
2956: return SSH_ERR_KEY_CERT_INVALID;
2957: }
2958: if ((u_int64_t)now >= k->cert->valid_before) {
2959: *reason = "Certificate invalid: expired";
2960: return SSH_ERR_KEY_CERT_INVALID;
2961: }
2962: if (k->cert->nprincipals == 0) {
2963: if (require_principal) {
2964: *reason = "Certificate lacks principal list";
2965: return SSH_ERR_KEY_CERT_INVALID;
2966: }
2967: } else if (name != NULL) {
2968: principal_matches = 0;
2969: for (i = 0; i < k->cert->nprincipals; i++) {
2970: if (strcmp(name, k->cert->principals[i]) == 0) {
2971: principal_matches = 1;
2972: break;
2973: }
2974: }
2975: if (!principal_matches) {
2976: *reason = "Certificate invalid: name is not a listed "
2977: "principal";
2978: return SSH_ERR_KEY_CERT_INVALID;
2979: }
2980: }
2981: return 0;
1.27 djm 2982: }
2983:
2984: size_t
2985: sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2986: {
2987: char from[32], to[32], ret[64];
2988: time_t tt;
2989: struct tm *tm;
2990:
2991: *from = *to = '\0';
2992: if (cert->valid_after == 0 &&
2993: cert->valid_before == 0xffffffffffffffffULL)
2994: return strlcpy(s, "forever", l);
2995:
2996: if (cert->valid_after != 0) {
2997: /* XXX revisit INT_MAX in 2038 :) */
2998: tt = cert->valid_after > INT_MAX ?
2999: INT_MAX : cert->valid_after;
3000: tm = localtime(&tt);
3001: strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
3002: }
3003: if (cert->valid_before != 0xffffffffffffffffULL) {
3004: /* XXX revisit INT_MAX in 2038 :) */
3005: tt = cert->valid_before > INT_MAX ?
3006: INT_MAX : cert->valid_before;
3007: tm = localtime(&tt);
3008: strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
3009: }
3010:
3011: if (cert->valid_after == 0)
3012: snprintf(ret, sizeof(ret), "before %s", to);
3013: else if (cert->valid_before == 0xffffffffffffffffULL)
3014: snprintf(ret, sizeof(ret), "after %s", from);
3015: else
3016: snprintf(ret, sizeof(ret), "from %s to %s", from, to);
3017:
3018: return strlcpy(s, ret, l);
1.1 djm 3019: }
3020:
3021: int
1.76 djm 3022: sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
1.62 markus 3023: enum sshkey_serialize_rep opts)
1.1 djm 3024: {
3025: int r = SSH_ERR_INTERNAL_ERROR;
1.76 djm 3026: int was_shielded = sshkey_is_shielded(key);
3027: struct sshbuf *b = NULL;
1.69 djm 3028: #ifdef WITH_OPENSSL
3029: const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
3030: const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
3031: #endif /* WITH_OPENSSL */
1.1 djm 3032:
1.76 djm 3033: if ((r = sshkey_unshield_private(key)) != 0)
3034: return r;
3035: if ((b = sshbuf_new()) == NULL)
3036: return SSH_ERR_ALLOC_FAIL;
1.1 djm 3037: if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
3038: goto out;
3039: switch (key->type) {
3040: #ifdef WITH_OPENSSL
3041: case KEY_RSA:
1.69 djm 3042: RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
3043: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3044: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
3045: if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
3046: (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
3047: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3048: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3049: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3050: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3051: goto out;
3052: break;
3053: case KEY_RSA_CERT:
3054: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3055: r = SSH_ERR_INVALID_ARGUMENT;
3056: goto out;
3057: }
1.69 djm 3058: RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
3059: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
3060: RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
1.1 djm 3061: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3062: (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
3063: (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
3064: (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
3065: (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
1.1 djm 3066: goto out;
3067: break;
3068: case KEY_DSA:
1.69 djm 3069: DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
3070: DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
3071: if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
3072: (r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
3073: (r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
3074: (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
3075: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3076: goto out;
3077: break;
3078: case KEY_DSA_CERT:
3079: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3080: r = SSH_ERR_INVALID_ARGUMENT;
3081: goto out;
3082: }
1.69 djm 3083: DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
1.1 djm 3084: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
1.69 djm 3085: (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
1.1 djm 3086: goto out;
3087: break;
3088: case KEY_ECDSA:
3089: if ((r = sshbuf_put_cstring(b,
3090: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
3091: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
3092: (r = sshbuf_put_bignum2(b,
3093: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3094: goto out;
3095: break;
3096: case KEY_ECDSA_CERT:
3097: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3098: r = SSH_ERR_INVALID_ARGUMENT;
3099: goto out;
3100: }
3101: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3102: (r = sshbuf_put_bignum2(b,
3103: EC_KEY_get0_private_key(key->ecdsa))) != 0)
3104: goto out;
3105: break;
1.85 ! djm 3106: case KEY_ECDSA_SK:
! 3107: if ((r = sshbuf_put_cstring(b,
! 3108: sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
! 3109: (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
! 3110: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
! 3111: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
! 3112: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
! 3113: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
! 3114: goto out;
! 3115: break;
! 3116: case KEY_ECDSA_SK_CERT:
! 3117: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
! 3118: r = SSH_ERR_INVALID_ARGUMENT;
! 3119: goto out;
! 3120: }
! 3121: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
! 3122: (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
! 3123: (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
! 3124: (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
! 3125: (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
! 3126: goto out;
! 3127: break;
1.1 djm 3128: #endif /* WITH_OPENSSL */
3129: case KEY_ED25519:
3130: if ((r = sshbuf_put_string(b, key->ed25519_pk,
3131: ED25519_PK_SZ)) != 0 ||
3132: (r = sshbuf_put_string(b, key->ed25519_sk,
3133: ED25519_SK_SZ)) != 0)
3134: goto out;
3135: break;
3136: case KEY_ED25519_CERT:
3137: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
3138: r = SSH_ERR_INVALID_ARGUMENT;
3139: goto out;
3140: }
3141: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3142: (r = sshbuf_put_string(b, key->ed25519_pk,
3143: ED25519_PK_SZ)) != 0 ||
3144: (r = sshbuf_put_string(b, key->ed25519_sk,
3145: ED25519_SK_SZ)) != 0)
3146: goto out;
3147: break;
1.62 markus 3148: #ifdef WITH_XMSS
3149: case KEY_XMSS:
3150: if (key->xmss_name == NULL) {
3151: r = SSH_ERR_INVALID_ARGUMENT;
3152: goto out;
3153: }
3154: if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3155: (r = sshbuf_put_string(b, key->xmss_pk,
3156: sshkey_xmss_pklen(key))) != 0 ||
3157: (r = sshbuf_put_string(b, key->xmss_sk,
3158: sshkey_xmss_sklen(key))) != 0 ||
3159: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3160: goto out;
3161: break;
3162: case KEY_XMSS_CERT:
3163: if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
3164: key->xmss_name == NULL) {
3165: r = SSH_ERR_INVALID_ARGUMENT;
3166: goto out;
3167: }
3168: if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
3169: (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
3170: (r = sshbuf_put_string(b, key->xmss_pk,
3171: sshkey_xmss_pklen(key))) != 0 ||
3172: (r = sshbuf_put_string(b, key->xmss_sk,
3173: sshkey_xmss_sklen(key))) != 0 ||
3174: (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
3175: goto out;
3176: break;
3177: #endif /* WITH_XMSS */
1.1 djm 3178: default:
3179: r = SSH_ERR_INVALID_ARGUMENT;
3180: goto out;
3181: }
1.76 djm 3182: /*
3183: * success (but we still need to append the output to buf after
3184: * possibly re-shielding the private key)
3185: */
1.1 djm 3186: r = 0;
3187: out:
1.76 djm 3188: if (was_shielded)
3189: r = sshkey_shield_private(key);
3190: if (r == 0)
3191: r = sshbuf_putb(buf, b);
3192: sshbuf_free(b);
3193:
1.1 djm 3194: return r;
3195: }
3196:
3197: int
1.76 djm 3198: sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
1.62 markus 3199: {
3200: return sshkey_private_serialize_opt(key, b,
3201: SSHKEY_SERIALIZE_DEFAULT);
3202: }
3203:
3204: int
1.1 djm 3205: sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3206: {
1.62 markus 3207: char *tname = NULL, *curve = NULL, *xmss_name = NULL;
1.1 djm 3208: struct sshkey *k = NULL;
1.14 djm 3209: size_t pklen = 0, sklen = 0;
1.1 djm 3210: int type, r = SSH_ERR_INTERNAL_ERROR;
3211: u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
1.62 markus 3212: u_char *xmss_pk = NULL, *xmss_sk = NULL;
1.1 djm 3213: #ifdef WITH_OPENSSL
3214: BIGNUM *exponent = NULL;
1.69 djm 3215: BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
3216: BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
3217: BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
3218: BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
1.1 djm 3219: #endif /* WITH_OPENSSL */
3220:
3221: if (kp != NULL)
3222: *kp = NULL;
3223: if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
3224: goto out;
3225: type = sshkey_type_from_name(tname);
3226: switch (type) {
3227: #ifdef WITH_OPENSSL
3228: case KEY_DSA:
1.70 djm 3229: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3230: r = SSH_ERR_ALLOC_FAIL;
3231: goto out;
3232: }
1.73 djm 3233: if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
3234: (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
3235: (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
3236: (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 ||
3237: (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
1.69 djm 3238: goto out;
3239: if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
3240: r = SSH_ERR_LIBCRYPTO_ERROR;
3241: goto out;
3242: }
3243: dsa_p = dsa_q = dsa_g = NULL; /* transferred */
3244: if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) {
3245: r = SSH_ERR_LIBCRYPTO_ERROR;
1.1 djm 3246: goto out;
1.69 djm 3247: }
3248: dsa_pub_key = dsa_priv_key = NULL; /* transferred */
1.1 djm 3249: break;
3250: case KEY_DSA_CERT:
1.14 djm 3251: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.73 djm 3252: (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
1.1 djm 3253: goto out;
1.84 djm 3254: if (k->type != type) {
3255: r = SSH_ERR_INVALID_FORMAT;
3256: goto out;
3257: }
1.69 djm 3258: if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
3259: r = SSH_ERR_LIBCRYPTO_ERROR;
3260: goto out;
3261: }
3262: dsa_priv_key = NULL; /* transferred */
1.1 djm 3263: break;
3264: case KEY_ECDSA:
1.70 djm 3265: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3266: r = SSH_ERR_ALLOC_FAIL;
3267: goto out;
3268: }
3269: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3270: r = SSH_ERR_INVALID_ARGUMENT;
3271: goto out;
3272: }
3273: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
3274: goto out;
3275: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
3276: r = SSH_ERR_EC_CURVE_MISMATCH;
3277: goto out;
3278: }
3279: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1.73 djm 3280: if (k->ecdsa == NULL) {
1.1 djm 3281: r = SSH_ERR_LIBCRYPTO_ERROR;
3282: goto out;
3283: }
3284: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
1.73 djm 3285: (r = sshbuf_get_bignum2(buf, &exponent)))
1.1 djm 3286: goto out;
3287: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3288: r = SSH_ERR_LIBCRYPTO_ERROR;
3289: goto out;
3290: }
3291: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 3292: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 3293: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
3294: goto out;
3295: break;
3296: case KEY_ECDSA_CERT:
1.14 djm 3297: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.73 djm 3298: (r = sshbuf_get_bignum2(buf, &exponent)) != 0)
1.1 djm 3299: goto out;
1.84 djm 3300: if (k->type != type ||
3301: k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3302: r = SSH_ERR_INVALID_FORMAT;
3303: goto out;
3304: }
1.1 djm 3305: if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3306: r = SSH_ERR_LIBCRYPTO_ERROR;
3307: goto out;
3308: }
3309: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
1.22 jsg 3310: EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
1.1 djm 3311: (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
3312: goto out;
3313: break;
1.85 ! djm 3314: case KEY_ECDSA_SK:
! 3315: if ((k = sshkey_new(type)) == NULL) {
! 3316: r = SSH_ERR_ALLOC_FAIL;
! 3317: goto out;
! 3318: }
! 3319: if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
! 3320: r = SSH_ERR_INVALID_ARGUMENT;
! 3321: goto out;
! 3322: }
! 3323: if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
! 3324: goto out;
! 3325: if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
! 3326: r = SSH_ERR_EC_CURVE_MISMATCH;
! 3327: goto out;
! 3328: }
! 3329: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
! 3330: (k->sk_reserved = sshbuf_new()) == NULL) {
! 3331: r = SSH_ERR_ALLOC_FAIL;
! 3332: goto out;
! 3333: }
! 3334: k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
! 3335: if (k->ecdsa == NULL) {
! 3336: r = SSH_ERR_LIBCRYPTO_ERROR;
! 3337: goto out;
! 3338: }
! 3339: if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
! 3340: (r = sshbuf_get_cstring(buf, &k->sk_application,
! 3341: NULL)) != 0 ||
! 3342: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
! 3343: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
! 3344: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
! 3345: goto out;
! 3346: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
! 3347: EC_KEY_get0_public_key(k->ecdsa))) != 0)
! 3348: goto out;
! 3349: break;
! 3350: case KEY_ECDSA_SK_CERT:
! 3351: if ((r = sshkey_froms(buf, &k)) != 0)
! 3352: goto out;
! 3353: if ((k->sk_key_handle = sshbuf_new()) == NULL ||
! 3354: (k->sk_reserved = sshbuf_new()) == NULL) {
! 3355: r = SSH_ERR_ALLOC_FAIL;
! 3356: goto out;
! 3357: }
! 3358: if ((r = sshbuf_get_cstring(buf, &k->sk_application,
! 3359: NULL)) != 0 ||
! 3360: (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
! 3361: (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
! 3362: (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
! 3363: goto out;
! 3364: if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
! 3365: EC_KEY_get0_public_key(k->ecdsa))) != 0)
! 3366: goto out;
! 3367: break;
1.1 djm 3368: case KEY_RSA:
1.70 djm 3369: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3370: r = SSH_ERR_ALLOC_FAIL;
3371: goto out;
3372: }
1.73 djm 3373: if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
3374: (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 ||
3375: (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
3376: (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3377: (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3378: (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
1.1 djm 3379: goto out;
1.69 djm 3380: if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) {
3381: r = SSH_ERR_LIBCRYPTO_ERROR;
3382: goto out;
3383: }
3384: rsa_n = rsa_e = rsa_d = NULL; /* transferred */
3385: if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
3386: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3387: goto out;
3388: }
1.69 djm 3389: rsa_p = rsa_q = NULL; /* transferred */
3390: if ((r = check_rsa_length(k->rsa)) != 0)
3391: goto out;
3392: if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
3393: goto out;
1.1 djm 3394: break;
3395: case KEY_RSA_CERT:
1.14 djm 3396: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.73 djm 3397: (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
3398: (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3399: (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3400: (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
1.1 djm 3401: goto out;
1.84 djm 3402: if (k->type != type) {
3403: r = SSH_ERR_INVALID_FORMAT;
3404: goto out;
3405: }
1.69 djm 3406: if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
3407: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 3408: goto out;
3409: }
1.69 djm 3410: rsa_d = NULL; /* transferred */
3411: if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
3412: r = SSH_ERR_LIBCRYPTO_ERROR;
3413: goto out;
3414: }
3415: rsa_p = rsa_q = NULL; /* transferred */
3416: if ((r = check_rsa_length(k->rsa)) != 0)
3417: goto out;
3418: if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
3419: goto out;
1.1 djm 3420: break;
3421: #endif /* WITH_OPENSSL */
3422: case KEY_ED25519:
1.70 djm 3423: if ((k = sshkey_new(type)) == NULL) {
1.1 djm 3424: r = SSH_ERR_ALLOC_FAIL;
3425: goto out;
3426: }
3427: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3428: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3429: goto out;
3430: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3431: r = SSH_ERR_INVALID_FORMAT;
3432: goto out;
3433: }
3434: k->ed25519_pk = ed25519_pk;
3435: k->ed25519_sk = ed25519_sk;
3436: ed25519_pk = ed25519_sk = NULL;
3437: break;
3438: case KEY_ED25519_CERT:
1.14 djm 3439: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.1 djm 3440: (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3441: (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3442: goto out;
1.84 djm 3443: if (k->type != type) {
3444: r = SSH_ERR_INVALID_FORMAT;
3445: goto out;
3446: }
1.1 djm 3447: if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3448: r = SSH_ERR_INVALID_FORMAT;
3449: goto out;
3450: }
3451: k->ed25519_pk = ed25519_pk;
3452: k->ed25519_sk = ed25519_sk;
1.84 djm 3453: ed25519_pk = ed25519_sk = NULL; /* transferred */
1.1 djm 3454: break;
1.62 markus 3455: #ifdef WITH_XMSS
3456: case KEY_XMSS:
1.70 djm 3457: if ((k = sshkey_new(type)) == NULL) {
1.62 markus 3458: r = SSH_ERR_ALLOC_FAIL;
3459: goto out;
3460: }
3461: if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3462: (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
3463: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3464: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3465: goto out;
3466: if (pklen != sshkey_xmss_pklen(k) ||
3467: sklen != sshkey_xmss_sklen(k)) {
3468: r = SSH_ERR_INVALID_FORMAT;
3469: goto out;
3470: }
3471: k->xmss_pk = xmss_pk;
3472: k->xmss_sk = xmss_sk;
3473: xmss_pk = xmss_sk = NULL;
3474: /* optional internal state */
3475: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3476: goto out;
3477: break;
3478: case KEY_XMSS_CERT:
3479: if ((r = sshkey_froms(buf, &k)) != 0 ||
1.64 markus 3480: (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
1.62 markus 3481: (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3482: (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3483: goto out;
1.84 djm 3484: if (k->type != type || strcmp(xmss_name, k->xmss_name) != 0) {
1.64 markus 3485: r = SSH_ERR_INVALID_FORMAT;
3486: goto out;
3487: }
1.62 markus 3488: if (pklen != sshkey_xmss_pklen(k) ||
3489: sklen != sshkey_xmss_sklen(k)) {
3490: r = SSH_ERR_INVALID_FORMAT;
3491: goto out;
3492: }
3493: k->xmss_pk = xmss_pk;
3494: k->xmss_sk = xmss_sk;
3495: xmss_pk = xmss_sk = NULL;
3496: /* optional internal state */
3497: if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3498: goto out;
3499: break;
3500: #endif /* WITH_XMSS */
1.1 djm 3501: default:
3502: r = SSH_ERR_KEY_TYPE_UNKNOWN;
3503: goto out;
3504: }
3505: #ifdef WITH_OPENSSL
3506: /* enable blinding */
3507: switch (k->type) {
3508: case KEY_RSA:
3509: case KEY_RSA_CERT:
3510: if (RSA_blinding_on(k->rsa, NULL) != 1) {
3511: r = SSH_ERR_LIBCRYPTO_ERROR;
3512: goto out;
3513: }
3514: break;
3515: }
3516: #endif /* WITH_OPENSSL */
3517: /* success */
3518: r = 0;
3519: if (kp != NULL) {
3520: *kp = k;
3521: k = NULL;
3522: }
3523: out:
3524: free(tname);
3525: free(curve);
3526: #ifdef WITH_OPENSSL
1.60 jsing 3527: BN_clear_free(exponent);
1.69 djm 3528: BN_clear_free(dsa_p);
3529: BN_clear_free(dsa_q);
3530: BN_clear_free(dsa_g);
3531: BN_clear_free(dsa_pub_key);
3532: BN_clear_free(dsa_priv_key);
3533: BN_clear_free(rsa_n);
3534: BN_clear_free(rsa_e);
3535: BN_clear_free(rsa_d);
3536: BN_clear_free(rsa_p);
3537: BN_clear_free(rsa_q);
3538: BN_clear_free(rsa_iqmp);
1.1 djm 3539: #endif /* WITH_OPENSSL */
3540: sshkey_free(k);
1.61 jsing 3541: freezero(ed25519_pk, pklen);
3542: freezero(ed25519_sk, sklen);
1.62 markus 3543: free(xmss_name);
3544: freezero(xmss_pk, pklen);
3545: freezero(xmss_sk, sklen);
1.1 djm 3546: return r;
3547: }
3548:
3549: #ifdef WITH_OPENSSL
3550: int
3551: sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
3552: {
3553: BN_CTX *bnctx;
3554: EC_POINT *nq = NULL;
3555: BIGNUM *order, *x, *y, *tmp;
3556: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
1.40 djm 3557:
3558: /*
3559: * NB. This assumes OpenSSL has already verified that the public
3560: * point lies on the curve. This is done by EC_POINT_oct2point()
3561: * implicitly calling EC_POINT_is_on_curve(). If this code is ever
3562: * reachable with public points not unmarshalled using
3563: * EC_POINT_oct2point then the caller will need to explicitly check.
3564: */
1.1 djm 3565:
3566: if ((bnctx = BN_CTX_new()) == NULL)
3567: return SSH_ERR_ALLOC_FAIL;
3568: BN_CTX_start(bnctx);
3569:
3570: /*
3571: * We shouldn't ever hit this case because bignum_get_ecpoint()
3572: * refuses to load GF2m points.
3573: */
3574: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3575: NID_X9_62_prime_field)
3576: goto out;
3577:
3578: /* Q != infinity */
3579: if (EC_POINT_is_at_infinity(group, public))
3580: goto out;
3581:
3582: if ((x = BN_CTX_get(bnctx)) == NULL ||
3583: (y = BN_CTX_get(bnctx)) == NULL ||
3584: (order = BN_CTX_get(bnctx)) == NULL ||
3585: (tmp = BN_CTX_get(bnctx)) == NULL) {
3586: ret = SSH_ERR_ALLOC_FAIL;
3587: goto out;
3588: }
3589:
3590: /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
3591: if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
3592: EC_POINT_get_affine_coordinates_GFp(group, public,
3593: x, y, bnctx) != 1) {
3594: ret = SSH_ERR_LIBCRYPTO_ERROR;
3595: goto out;
3596: }
3597: if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
3598: BN_num_bits(y) <= BN_num_bits(order) / 2)
3599: goto out;
3600:
3601: /* nQ == infinity (n == order of subgroup) */
3602: if ((nq = EC_POINT_new(group)) == NULL) {
3603: ret = SSH_ERR_ALLOC_FAIL;
3604: goto out;
3605: }
3606: if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
3607: ret = SSH_ERR_LIBCRYPTO_ERROR;
3608: goto out;
3609: }
3610: if (EC_POINT_is_at_infinity(group, nq) != 1)
3611: goto out;
3612:
3613: /* x < order - 1, y < order - 1 */
3614: if (!BN_sub(tmp, order, BN_value_one())) {
3615: ret = SSH_ERR_LIBCRYPTO_ERROR;
3616: goto out;
3617: }
3618: if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
3619: goto out;
3620: ret = 0;
3621: out:
3622: BN_CTX_free(bnctx);
1.60 jsing 3623: EC_POINT_free(nq);
1.1 djm 3624: return ret;
3625: }
3626:
3627: int
3628: sshkey_ec_validate_private(const EC_KEY *key)
3629: {
3630: BN_CTX *bnctx;
3631: BIGNUM *order, *tmp;
3632: int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
3633:
3634: if ((bnctx = BN_CTX_new()) == NULL)
3635: return SSH_ERR_ALLOC_FAIL;
3636: BN_CTX_start(bnctx);
3637:
3638: if ((order = BN_CTX_get(bnctx)) == NULL ||
3639: (tmp = BN_CTX_get(bnctx)) == NULL) {
3640: ret = SSH_ERR_ALLOC_FAIL;
3641: goto out;
3642: }
3643:
3644: /* log2(private) > log2(order)/2 */
3645: if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
3646: ret = SSH_ERR_LIBCRYPTO_ERROR;
3647: goto out;
3648: }
3649: if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
3650: BN_num_bits(order) / 2)
3651: goto out;
3652:
3653: /* private < order - 1 */
3654: if (!BN_sub(tmp, order, BN_value_one())) {
3655: ret = SSH_ERR_LIBCRYPTO_ERROR;
3656: goto out;
3657: }
3658: if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
3659: goto out;
3660: ret = 0;
3661: out:
3662: BN_CTX_free(bnctx);
3663: return ret;
3664: }
3665:
3666: void
3667: sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
3668: {
3669: BIGNUM *x, *y;
3670: BN_CTX *bnctx;
3671:
3672: if (point == NULL) {
3673: fputs("point=(NULL)\n", stderr);
3674: return;
3675: }
3676: if ((bnctx = BN_CTX_new()) == NULL) {
3677: fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
3678: return;
3679: }
3680: BN_CTX_start(bnctx);
3681: if ((x = BN_CTX_get(bnctx)) == NULL ||
3682: (y = BN_CTX_get(bnctx)) == NULL) {
3683: fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
3684: return;
3685: }
3686: if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
3687: NID_X9_62_prime_field) {
3688: fprintf(stderr, "%s: group is not a prime field\n", __func__);
3689: return;
3690: }
3691: if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
3692: bnctx) != 1) {
3693: fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
3694: __func__);
3695: return;
3696: }
3697: fputs("x=", stderr);
3698: BN_print_fp(stderr, x);
3699: fputs("\ny=", stderr);
3700: BN_print_fp(stderr, y);
3701: fputs("\n", stderr);
3702: BN_CTX_free(bnctx);
3703: }
3704:
3705: void
3706: sshkey_dump_ec_key(const EC_KEY *key)
3707: {
3708: const BIGNUM *exponent;
3709:
3710: sshkey_dump_ec_point(EC_KEY_get0_group(key),
3711: EC_KEY_get0_public_key(key));
3712: fputs("exponent=", stderr);
3713: if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
3714: fputs("(NULL)", stderr);
3715: else
3716: BN_print_fp(stderr, EC_KEY_get0_private_key(key));
3717: fputs("\n", stderr);
3718: }
3719: #endif /* WITH_OPENSSL */
3720:
3721: static int
1.76 djm 3722: sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
1.1 djm 3723: const char *passphrase, const char *comment, const char *ciphername,
3724: int rounds)
3725: {
1.4 djm 3726: u_char *cp, *key = NULL, *pubkeyblob = NULL;
1.1 djm 3727: u_char salt[SALT_LEN];
1.4 djm 3728: char *b64 = NULL;
1.1 djm 3729: size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
3730: u_int check;
3731: int r = SSH_ERR_INTERNAL_ERROR;
1.36 djm 3732: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3733: const struct sshcipher *cipher;
3734: const char *kdfname = KDFNAME;
3735: struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
3736:
3737: if (rounds <= 0)
3738: rounds = DEFAULT_ROUNDS;
3739: if (passphrase == NULL || !strlen(passphrase)) {
3740: ciphername = "none";
3741: kdfname = "none";
3742: } else if (ciphername == NULL)
3743: ciphername = DEFAULT_CIPHERNAME;
1.47 djm 3744: if ((cipher = cipher_by_name(ciphername)) == NULL) {
1.1 djm 3745: r = SSH_ERR_INVALID_ARGUMENT;
3746: goto out;
3747: }
3748:
3749: if ((kdf = sshbuf_new()) == NULL ||
3750: (encoded = sshbuf_new()) == NULL ||
3751: (encrypted = sshbuf_new()) == NULL) {
3752: r = SSH_ERR_ALLOC_FAIL;
3753: goto out;
3754: }
3755: blocksize = cipher_blocksize(cipher);
3756: keylen = cipher_keylen(cipher);
3757: ivlen = cipher_ivlen(cipher);
3758: authlen = cipher_authlen(cipher);
3759: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3760: r = SSH_ERR_ALLOC_FAIL;
3761: goto out;
3762: }
3763: if (strcmp(kdfname, "bcrypt") == 0) {
3764: arc4random_buf(salt, SALT_LEN);
3765: if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3766: salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3767: r = SSH_ERR_INVALID_ARGUMENT;
3768: goto out;
3769: }
3770: if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3771: (r = sshbuf_put_u32(kdf, rounds)) != 0)
3772: goto out;
3773: } else if (strcmp(kdfname, "none") != 0) {
3774: /* Unsupported KDF type */
3775: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3776: goto out;
3777: }
3778: if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3779: key + keylen, ivlen, 1)) != 0)
3780: goto out;
3781:
3782: if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3783: (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3784: (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3785: (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3786: (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3787: (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3788: (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3789: goto out;
3790:
3791: /* set up the buffer that will be encrypted */
3792:
3793: /* Random check bytes */
3794: check = arc4random();
3795: if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3796: (r = sshbuf_put_u32(encrypted, check)) != 0)
3797: goto out;
3798:
3799: /* append private key and comment*/
1.62 markus 3800: if ((r = sshkey_private_serialize_opt(prv, encrypted,
3801: SSHKEY_SERIALIZE_FULL)) != 0 ||
1.1 djm 3802: (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3803: goto out;
3804:
3805: /* padding */
3806: i = 0;
3807: while (sshbuf_len(encrypted) % blocksize) {
3808: if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3809: goto out;
3810: }
3811:
3812: /* length in destination buffer */
3813: if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3814: goto out;
3815:
3816: /* encrypt */
3817: if ((r = sshbuf_reserve(encoded,
3818: sshbuf_len(encrypted) + authlen, &cp)) != 0)
3819: goto out;
1.36 djm 3820: if ((r = cipher_crypt(ciphercontext, 0, cp,
1.1 djm 3821: sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3822: goto out;
3823:
1.81 djm 3824: sshbuf_reset(blob);
1.1 djm 3825:
1.81 djm 3826: /* assemble uuencoded key */
3827: if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
3828: (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
3829: (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
1.1 djm 3830: goto out;
3831:
3832: /* success */
3833: r = 0;
3834:
3835: out:
3836: sshbuf_free(kdf);
3837: sshbuf_free(encoded);
3838: sshbuf_free(encrypted);
1.36 djm 3839: cipher_free(ciphercontext);
1.1 djm 3840: explicit_bzero(salt, sizeof(salt));
3841: if (key != NULL) {
3842: explicit_bzero(key, keylen + ivlen);
3843: free(key);
3844: }
3845: if (pubkeyblob != NULL) {
3846: explicit_bzero(pubkeyblob, pubkeylen);
3847: free(pubkeyblob);
3848: }
3849: if (b64 != NULL) {
3850: explicit_bzero(b64, strlen(b64));
3851: free(b64);
3852: }
3853: return r;
3854: }
3855:
3856: static int
3857: sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3858: struct sshkey **keyp, char **commentp)
3859: {
3860: char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
3861: const struct sshcipher *cipher = NULL;
3862: const u_char *cp;
3863: int r = SSH_ERR_INTERNAL_ERROR;
3864: size_t encoded_len;
1.18 djm 3865: size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
1.1 djm 3866: struct sshbuf *encoded = NULL, *decoded = NULL;
3867: struct sshbuf *kdf = NULL, *decrypted = NULL;
1.36 djm 3868: struct sshcipher_ctx *ciphercontext = NULL;
1.1 djm 3869: struct sshkey *k = NULL;
3870: u_char *key = NULL, *salt = NULL, *dp, pad, last;
3871: u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
3872:
3873: if (keyp != NULL)
3874: *keyp = NULL;
3875: if (commentp != NULL)
3876: *commentp = NULL;
3877:
3878: if ((encoded = sshbuf_new()) == NULL ||
3879: (decoded = sshbuf_new()) == NULL ||
3880: (decrypted = sshbuf_new()) == NULL) {
3881: r = SSH_ERR_ALLOC_FAIL;
3882: goto out;
3883: }
3884:
3885: /* check preamble */
3886: cp = sshbuf_ptr(blob);
3887: encoded_len = sshbuf_len(blob);
3888: if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3889: memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3890: r = SSH_ERR_INVALID_FORMAT;
3891: goto out;
3892: }
3893: cp += MARK_BEGIN_LEN;
3894: encoded_len -= MARK_BEGIN_LEN;
3895:
3896: /* Look for end marker, removing whitespace as we go */
3897: while (encoded_len > 0) {
3898: if (*cp != '\n' && *cp != '\r') {
3899: if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3900: goto out;
3901: }
3902: last = *cp;
3903: encoded_len--;
3904: cp++;
3905: if (last == '\n') {
3906: if (encoded_len >= MARK_END_LEN &&
3907: memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3908: /* \0 terminate */
3909: if ((r = sshbuf_put_u8(encoded, 0)) != 0)
3910: goto out;
3911: break;
3912: }
3913: }
3914: }
3915: if (encoded_len == 0) {
3916: r = SSH_ERR_INVALID_FORMAT;
3917: goto out;
3918: }
3919:
3920: /* decode base64 */
1.4 djm 3921: if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
1.1 djm 3922: goto out;
3923:
3924: /* check magic */
3925: if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
3926: memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
3927: r = SSH_ERR_INVALID_FORMAT;
3928: goto out;
3929: }
3930: /* parse public portion of key */
3931: if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3932: (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
3933: (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
3934: (r = sshbuf_froms(decoded, &kdf)) != 0 ||
3935: (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
3936: (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
3937: (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
3938: goto out;
3939:
3940: if ((cipher = cipher_by_name(ciphername)) == NULL) {
3941: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3942: goto out;
3943: }
3944: if ((passphrase == NULL || strlen(passphrase) == 0) &&
3945: strcmp(ciphername, "none") != 0) {
3946: /* passphrase required */
3947: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3948: goto out;
3949: }
3950: if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
3951: r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3952: goto out;
3953: }
3954: if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
3955: r = SSH_ERR_INVALID_FORMAT;
3956: goto out;
3957: }
3958: if (nkeys != 1) {
3959: /* XXX only one key supported */
3960: r = SSH_ERR_INVALID_FORMAT;
3961: goto out;
3962: }
3963:
3964: /* check size of encrypted key blob */
3965: blocksize = cipher_blocksize(cipher);
3966: if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
3967: r = SSH_ERR_INVALID_FORMAT;
3968: goto out;
3969: }
3970:
3971: /* setup key */
3972: keylen = cipher_keylen(cipher);
3973: ivlen = cipher_ivlen(cipher);
1.18 djm 3974: authlen = cipher_authlen(cipher);
1.1 djm 3975: if ((key = calloc(1, keylen + ivlen)) == NULL) {
3976: r = SSH_ERR_ALLOC_FAIL;
3977: goto out;
3978: }
3979: if (strcmp(kdfname, "bcrypt") == 0) {
3980: if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
3981: (r = sshbuf_get_u32(kdf, &rounds)) != 0)
3982: goto out;
3983: if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
3984: key, keylen + ivlen, rounds) < 0) {
3985: r = SSH_ERR_INVALID_FORMAT;
3986: goto out;
3987: }
3988: }
3989:
1.18 djm 3990: /* check that an appropriate amount of auth data is present */
1.84 djm 3991: if (sshbuf_len(decoded) < authlen ||
3992: sshbuf_len(decoded) - authlen < encrypted_len) {
1.18 djm 3993: r = SSH_ERR_INVALID_FORMAT;
3994: goto out;
3995: }
3996:
1.1 djm 3997: /* decrypt private portion of key */
3998: if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3999: (r = cipher_init(&ciphercontext, cipher, key, keylen,
4000: key + keylen, ivlen, 0)) != 0)
4001: goto out;
1.36 djm 4002: if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
1.18 djm 4003: encrypted_len, 0, authlen)) != 0) {
1.1 djm 4004: /* an integrity error here indicates an incorrect passphrase */
4005: if (r == SSH_ERR_MAC_INVALID)
4006: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4007: goto out;
4008: }
1.18 djm 4009: if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
1.1 djm 4010: goto out;
4011: /* there should be no trailing data */
4012: if (sshbuf_len(decoded) != 0) {
4013: r = SSH_ERR_INVALID_FORMAT;
4014: goto out;
4015: }
4016:
4017: /* check check bytes */
4018: if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
4019: (r = sshbuf_get_u32(decrypted, &check2)) != 0)
4020: goto out;
4021: if (check1 != check2) {
4022: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4023: goto out;
4024: }
4025:
4026: /* Load the private key and comment */
4027: if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
4028: (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
4029: goto out;
4030:
4031: /* Check deterministic padding */
4032: i = 0;
4033: while (sshbuf_len(decrypted)) {
4034: if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
4035: goto out;
4036: if (pad != (++i & 0xff)) {
4037: r = SSH_ERR_INVALID_FORMAT;
4038: goto out;
4039: }
4040: }
4041:
4042: /* XXX decode pubkey and check against private */
4043:
4044: /* success */
4045: r = 0;
4046: if (keyp != NULL) {
4047: *keyp = k;
4048: k = NULL;
4049: }
4050: if (commentp != NULL) {
4051: *commentp = comment;
4052: comment = NULL;
4053: }
4054: out:
4055: pad = 0;
1.36 djm 4056: cipher_free(ciphercontext);
1.1 djm 4057: free(ciphername);
4058: free(kdfname);
4059: free(comment);
4060: if (salt != NULL) {
4061: explicit_bzero(salt, slen);
4062: free(salt);
4063: }
4064: if (key != NULL) {
4065: explicit_bzero(key, keylen + ivlen);
4066: free(key);
4067: }
4068: sshbuf_free(encoded);
4069: sshbuf_free(decoded);
4070: sshbuf_free(kdf);
4071: sshbuf_free(decrypted);
4072: sshkey_free(k);
4073: return r;
4074: }
4075:
4076:
4077: #ifdef WITH_OPENSSL
1.80 djm 4078: /* convert SSH v2 key to PEM or PKCS#8 format */
1.1 djm 4079: static int
1.80 djm 4080: sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
4081: int format, const char *_passphrase, const char *comment)
1.1 djm 4082: {
1.76 djm 4083: int was_shielded = sshkey_is_shielded(key);
1.1 djm 4084: int success, r;
4085: int blen, len = strlen(_passphrase);
4086: u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
4087: const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
1.57 djm 4088: char *bptr;
1.1 djm 4089: BIO *bio = NULL;
1.76 djm 4090: struct sshbuf *blob;
1.80 djm 4091: EVP_PKEY *pkey = NULL;
1.1 djm 4092:
4093: if (len > 0 && len <= 4)
4094: return SSH_ERR_PASSPHRASE_TOO_SHORT;
1.76 djm 4095: if ((blob = sshbuf_new()) == NULL)
1.1 djm 4096: return SSH_ERR_ALLOC_FAIL;
1.76 djm 4097: if ((bio = BIO_new(BIO_s_mem())) == NULL) {
1.80 djm 4098: r = SSH_ERR_ALLOC_FAIL;
4099: goto out;
4100: }
4101: if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
4102: r = SSH_ERR_ALLOC_FAIL;
4103: goto out;
1.76 djm 4104: }
4105: if ((r = sshkey_unshield_private(key)) != 0)
4106: goto out;
1.1 djm 4107:
4108: switch (key->type) {
4109: case KEY_DSA:
1.80 djm 4110: if (format == SSHKEY_PRIVATE_PEM) {
4111: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
4112: cipher, passphrase, len, NULL, NULL);
4113: } else {
4114: success = EVP_PKEY_set1_DSA(pkey, key->dsa);
4115: }
1.1 djm 4116: break;
4117: case KEY_ECDSA:
1.80 djm 4118: if (format == SSHKEY_PRIVATE_PEM) {
4119: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
4120: cipher, passphrase, len, NULL, NULL);
4121: } else {
4122: success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
4123: }
1.1 djm 4124: break;
4125: case KEY_RSA:
1.80 djm 4126: if (format == SSHKEY_PRIVATE_PEM) {
4127: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
4128: cipher, passphrase, len, NULL, NULL);
4129: } else {
4130: success = EVP_PKEY_set1_RSA(pkey, key->rsa);
4131: }
1.1 djm 4132: break;
4133: default:
4134: success = 0;
4135: break;
4136: }
4137: if (success == 0) {
4138: r = SSH_ERR_LIBCRYPTO_ERROR;
4139: goto out;
4140: }
1.80 djm 4141: if (format == SSHKEY_PRIVATE_PKCS8) {
4142: if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
4143: passphrase, len, NULL, NULL)) == 0) {
4144: r = SSH_ERR_LIBCRYPTO_ERROR;
4145: goto out;
4146: }
4147: }
1.1 djm 4148: if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
4149: r = SSH_ERR_INTERNAL_ERROR;
4150: goto out;
4151: }
4152: if ((r = sshbuf_put(blob, bptr, blen)) != 0)
4153: goto out;
4154: r = 0;
4155: out:
1.76 djm 4156: if (was_shielded)
4157: r = sshkey_shield_private(key);
4158: if (r == 0)
4159: r = sshbuf_putb(buf, blob);
1.80 djm 4160:
4161: EVP_PKEY_free(pkey);
1.76 djm 4162: sshbuf_free(blob);
1.1 djm 4163: BIO_free(bio);
4164: return r;
4165: }
4166: #endif /* WITH_OPENSSL */
4167:
4168: /* Serialise "key" to buffer "blob" */
4169: int
4170: sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
4171: const char *passphrase, const char *comment,
1.80 djm 4172: int format, const char *openssh_format_cipher, int openssh_format_rounds)
1.1 djm 4173: {
4174: switch (key->type) {
1.9 markus 4175: #ifdef WITH_OPENSSL
1.1 djm 4176: case KEY_DSA:
4177: case KEY_ECDSA:
4178: case KEY_RSA:
1.80 djm 4179: break; /* see below */
1.1 djm 4180: #endif /* WITH_OPENSSL */
4181: case KEY_ED25519:
1.62 markus 4182: #ifdef WITH_XMSS
4183: case KEY_XMSS:
4184: #endif /* WITH_XMSS */
1.85 ! djm 4185: #ifdef WITH_OPENSSL
! 4186: case KEY_ECDSA_SK:
! 4187: #endif /* WITH_OPENSSL */
1.1 djm 4188: return sshkey_private_to_blob2(key, blob, passphrase,
1.80 djm 4189: comment, openssh_format_cipher, openssh_format_rounds);
1.1 djm 4190: default:
4191: return SSH_ERR_KEY_TYPE_UNKNOWN;
4192: }
1.80 djm 4193:
4194: #ifdef WITH_OPENSSL
4195: switch (format) {
4196: case SSHKEY_PRIVATE_OPENSSH:
4197: return sshkey_private_to_blob2(key, blob, passphrase,
4198: comment, openssh_format_cipher, openssh_format_rounds);
4199: case SSHKEY_PRIVATE_PEM:
4200: case SSHKEY_PRIVATE_PKCS8:
4201: return sshkey_private_to_blob_pem_pkcs8(key, blob,
4202: format, passphrase, comment);
4203: default:
4204: return SSH_ERR_INVALID_ARGUMENT;
4205: }
4206: #endif /* WITH_OPENSSL */
1.1 djm 4207: }
4208:
4209: #ifdef WITH_OPENSSL
1.8 djm 4210: static int
1.52 djm 4211: translate_libcrypto_error(unsigned long pem_err)
4212: {
4213: int pem_reason = ERR_GET_REASON(pem_err);
4214:
4215: switch (ERR_GET_LIB(pem_err)) {
4216: case ERR_LIB_PEM:
4217: switch (pem_reason) {
4218: case PEM_R_BAD_PASSWORD_READ:
4219: case PEM_R_PROBLEMS_GETTING_PASSWORD:
4220: case PEM_R_BAD_DECRYPT:
4221: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4222: default:
4223: return SSH_ERR_INVALID_FORMAT;
4224: }
4225: case ERR_LIB_EVP:
4226: switch (pem_reason) {
4227: case EVP_R_BAD_DECRYPT:
4228: return SSH_ERR_KEY_WRONG_PASSPHRASE;
1.69 djm 4229: #ifdef EVP_R_BN_DECODE_ERROR
1.52 djm 4230: case EVP_R_BN_DECODE_ERROR:
1.69 djm 4231: #endif
1.52 djm 4232: case EVP_R_DECODE_ERROR:
4233: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
4234: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
4235: #endif
4236: return SSH_ERR_INVALID_FORMAT;
4237: default:
4238: return SSH_ERR_LIBCRYPTO_ERROR;
4239: }
4240: case ERR_LIB_ASN1:
4241: return SSH_ERR_INVALID_FORMAT;
4242: }
4243: return SSH_ERR_LIBCRYPTO_ERROR;
4244: }
4245:
4246: static void
4247: clear_libcrypto_errors(void)
4248: {
4249: while (ERR_get_error() != 0)
4250: ;
4251: }
4252:
4253: /*
4254: * Translate OpenSSL error codes to determine whether
4255: * passphrase is required/incorrect.
4256: */
4257: static int
4258: convert_libcrypto_error(void)
4259: {
4260: /*
4261: * Some password errors are reported at the beginning
4262: * of the error queue.
4263: */
4264: if (translate_libcrypto_error(ERR_peek_error()) ==
4265: SSH_ERR_KEY_WRONG_PASSPHRASE)
4266: return SSH_ERR_KEY_WRONG_PASSPHRASE;
4267: return translate_libcrypto_error(ERR_peek_last_error());
4268: }
4269:
4270: static int
1.1 djm 4271: sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
1.8 djm 4272: const char *passphrase, struct sshkey **keyp)
1.1 djm 4273: {
4274: EVP_PKEY *pk = NULL;
4275: struct sshkey *prv = NULL;
4276: BIO *bio = NULL;
4277: int r;
4278:
1.32 djm 4279: if (keyp != NULL)
4280: *keyp = NULL;
1.1 djm 4281:
4282: if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
4283: return SSH_ERR_ALLOC_FAIL;
4284: if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
4285: (int)sshbuf_len(blob)) {
4286: r = SSH_ERR_ALLOC_FAIL;
4287: goto out;
4288: }
4289:
1.52 djm 4290: clear_libcrypto_errors();
1.1 djm 4291: if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
4292: (char *)passphrase)) == NULL) {
1.71 djm 4293: /*
4294: * libcrypto may return various ASN.1 errors when attempting
4295: * to parse a key with an incorrect passphrase.
4296: * Treat all format errors as "incorrect passphrase" if a
4297: * passphrase was supplied.
4298: */
4299: if (passphrase != NULL && *passphrase != '\0')
4300: r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4301: else
4302: r = convert_libcrypto_error();
1.1 djm 4303: goto out;
4304: }
1.69 djm 4305: if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
1.1 djm 4306: (type == KEY_UNSPEC || type == KEY_RSA)) {
4307: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4308: r = SSH_ERR_ALLOC_FAIL;
4309: goto out;
4310: }
4311: prv->rsa = EVP_PKEY_get1_RSA(pk);
4312: prv->type = KEY_RSA;
4313: #ifdef DEBUG_PK
4314: RSA_print_fp(stderr, prv->rsa, 8);
4315: #endif
4316: if (RSA_blinding_on(prv->rsa, NULL) != 1) {
4317: r = SSH_ERR_LIBCRYPTO_ERROR;
1.49 djm 4318: goto out;
4319: }
1.69 djm 4320: if ((r = check_rsa_length(prv->rsa)) != 0)
1.1 djm 4321: goto out;
1.69 djm 4322: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
1.1 djm 4323: (type == KEY_UNSPEC || type == KEY_DSA)) {
4324: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4325: r = SSH_ERR_ALLOC_FAIL;
4326: goto out;
4327: }
4328: prv->dsa = EVP_PKEY_get1_DSA(pk);
4329: prv->type = KEY_DSA;
4330: #ifdef DEBUG_PK
4331: DSA_print_fp(stderr, prv->dsa, 8);
4332: #endif
1.69 djm 4333: } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
1.1 djm 4334: (type == KEY_UNSPEC || type == KEY_ECDSA)) {
4335: if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
4336: r = SSH_ERR_ALLOC_FAIL;
4337: goto out;
4338: }
4339: prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
4340: prv->type = KEY_ECDSA;
4341: prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
4342: if (prv->ecdsa_nid == -1 ||
4343: sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
4344: sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
4345: EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
4346: sshkey_ec_validate_private(prv->ecdsa) != 0) {
4347: r = SSH_ERR_INVALID_FORMAT;
4348: goto out;
4349: }
4350: #ifdef DEBUG_PK
4351: if (prv != NULL && prv->ecdsa != NULL)
4352: sshkey_dump_ec_key(prv->ecdsa);
4353: #endif
4354: } else {
4355: r = SSH_ERR_INVALID_FORMAT;
4356: goto out;
4357: }
4358: r = 0;
1.32 djm 4359: if (keyp != NULL) {
4360: *keyp = prv;
4361: prv = NULL;
4362: }
1.1 djm 4363: out:
4364: BIO_free(bio);
1.60 jsing 4365: EVP_PKEY_free(pk);
1.30 mmcc 4366: sshkey_free(prv);
1.1 djm 4367: return r;
4368: }
4369: #endif /* WITH_OPENSSL */
4370:
4371: int
4372: sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4373: const char *passphrase, struct sshkey **keyp, char **commentp)
4374: {
1.42 djm 4375: int r = SSH_ERR_INTERNAL_ERROR;
4376:
1.32 djm 4377: if (keyp != NULL)
4378: *keyp = NULL;
1.1 djm 4379: if (commentp != NULL)
4380: *commentp = NULL;
4381:
4382: switch (type) {
1.9 markus 4383: #ifdef WITH_OPENSSL
1.1 djm 4384: case KEY_DSA:
4385: case KEY_ECDSA:
4386: case KEY_RSA:
1.8 djm 4387: return sshkey_parse_private_pem_fileblob(blob, type,
4388: passphrase, keyp);
1.1 djm 4389: #endif /* WITH_OPENSSL */
4390: case KEY_ED25519:
1.62 markus 4391: #ifdef WITH_XMSS
4392: case KEY_XMSS:
4393: #endif /* WITH_XMSS */
1.1 djm 4394: return sshkey_parse_private2(blob, type, passphrase,
4395: keyp, commentp);
4396: case KEY_UNSPEC:
1.42 djm 4397: r = sshkey_parse_private2(blob, type, passphrase, keyp,
4398: commentp);
4399: /* Do not fallback to PEM parser if only passphrase is wrong. */
4400: if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
4401: return r;
1.1 djm 4402: #ifdef WITH_OPENSSL
1.8 djm 4403: return sshkey_parse_private_pem_fileblob(blob, type,
4404: passphrase, keyp);
1.1 djm 4405: #else
4406: return SSH_ERR_INVALID_FORMAT;
4407: #endif /* WITH_OPENSSL */
4408: default:
4409: return SSH_ERR_KEY_TYPE_UNKNOWN;
4410: }
4411: }
4412:
4413: int
4414: sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
1.23 tim 4415: struct sshkey **keyp, char **commentp)
1.1 djm 4416: {
4417: if (keyp != NULL)
4418: *keyp = NULL;
4419: if (commentp != NULL)
4420: *commentp = NULL;
4421:
1.23 tim 4422: return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
4423: passphrase, keyp, commentp);
1.1 djm 4424: }
1.62 markus 4425:
4426: #ifdef WITH_XMSS
4427: /*
4428: * serialize the key with the current state and forward the state
4429: * maxsign times.
4430: */
4431: int
1.77 djm 4432: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.62 markus 4433: u_int32_t maxsign, sshkey_printfn *pr)
4434: {
4435: int r, rupdate;
4436:
4437: if (maxsign == 0 ||
4438: sshkey_type_plain(k->type) != KEY_XMSS)
4439: return sshkey_private_serialize_opt(k, b,
4440: SSHKEY_SERIALIZE_DEFAULT);
4441: if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
4442: (r = sshkey_private_serialize_opt(k, b,
4443: SSHKEY_SERIALIZE_STATE)) != 0 ||
4444: (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
4445: goto out;
4446: r = 0;
4447: out:
4448: if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
4449: if (r == 0)
4450: r = rupdate;
4451: }
4452: return r;
4453: }
4454:
4455: u_int32_t
4456: sshkey_signatures_left(const struct sshkey *k)
4457: {
4458: if (sshkey_type_plain(k->type) == KEY_XMSS)
4459: return sshkey_xmss_signatures_left(k);
4460: return 0;
4461: }
4462:
4463: int
4464: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4465: {
4466: if (sshkey_type_plain(k->type) != KEY_XMSS)
4467: return SSH_ERR_INVALID_ARGUMENT;
4468: return sshkey_xmss_enable_maxsign(k, maxsign);
4469: }
4470:
4471: int
4472: sshkey_set_filename(struct sshkey *k, const char *filename)
4473: {
4474: if (k == NULL)
4475: return SSH_ERR_INVALID_ARGUMENT;
4476: if (sshkey_type_plain(k->type) != KEY_XMSS)
4477: return 0;
4478: if (filename == NULL)
4479: return SSH_ERR_INVALID_ARGUMENT;
4480: if ((k->xmss_filename = strdup(filename)) == NULL)
4481: return SSH_ERR_ALLOC_FAIL;
4482: return 0;
4483: }
4484: #else
4485: int
1.76 djm 4486: sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
1.62 markus 4487: u_int32_t maxsign, sshkey_printfn *pr)
4488: {
4489: return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
4490: }
4491:
4492: u_int32_t
4493: sshkey_signatures_left(const struct sshkey *k)
4494: {
4495: return 0;
4496: }
4497:
4498: int
4499: sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
4500: {
4501: return SSH_ERR_INVALID_ARGUMENT;
4502: }
4503:
4504: int
4505: sshkey_set_filename(struct sshkey *k, const char *filename)
4506: {
4507: if (k == NULL)
4508: return SSH_ERR_INVALID_ARGUMENT;
4509: return 0;
4510: }
4511: #endif /* WITH_XMSS */