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