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