Coverage Report

Created: 2026-10-17 06:40

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