Coverage Report

Created: 2026-08-13 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssh/ssh-ecdsa.c
Line
Count
Source
1
/* $OpenBSD: ssh-ecdsa.c,v 1.29 2026/02/14 00:18:34 jsg Exp $ */
2
/*
3
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4
 * Copyright (c) 2010 Damien Miller.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include "includes.h"
28
29
#if defined(WITH_OPENSSL)
30
#include "openbsd-compat/openssl-compat.h"
31
32
#include <sys/types.h>
33
34
#include <openssl/bn.h>
35
#include <openssl/ec.h>
36
#include <openssl/ecdsa.h>
37
#include <openssl/evp.h>
38
39
#include <string.h>
40
41
#include "sshbuf.h"
42
#include "ssherr.h"
43
#define SSHKEY_INTERNAL
44
#include "sshkey.h"
45
46
int
47
sshkey_ecdsa_fixup_group(EVP_PKEY *k)
48
0
{
49
0
  int nids[] = {
50
0
    NID_X9_62_prime256v1,
51
0
    NID_secp384r1,
52
0
    NID_secp521r1,
53
0
    -1
54
0
  };
55
0
  int nid = -1;
56
0
  u_int i;
57
0
  const EC_GROUP *g;
58
0
  EC_KEY *ec = NULL;
59
0
  EC_GROUP *eg = NULL;
60
61
0
  if ((ec = EVP_PKEY_get1_EC_KEY(k)) == NULL ||
62
0
      (g = EC_KEY_get0_group(ec)) == NULL)
63
0
    goto out;
64
  /*
65
   * The group may be stored in a ASN.1 encoded private key in one of two
66
   * ways: as a "named group", which is reconstituted by ASN.1 object ID
67
   * or explicit group parameters encoded into the key blob. Only the
68
   * "named group" case sets the group NID for us, but we can figure
69
   * it out for the other case by comparing against all the groups that
70
   * are supported.
71
   */
72
0
  if ((nid = EC_GROUP_get_curve_name(g)) > 0)
73
0
    goto out;
74
0
  nid = -1;
75
0
  for (i = 0; nids[i] != -1; i++) {
76
0
    if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
77
0
      goto out;
78
0
    if (EC_GROUP_cmp(g, eg, NULL) == 0)
79
0
      break;
80
0
    EC_GROUP_free(eg);
81
0
    eg = NULL;
82
0
  }
83
0
  if (nids[i] == -1)
84
0
    goto out;
85
86
  /* Use the group with the NID attached */
87
0
  EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
88
0
  if (EC_KEY_set_group(ec, eg) != 1 ||
89
0
      EVP_PKEY_set1_EC_KEY(k, ec) != 1)
90
0
    goto out;
91
  /* success */
92
0
  nid = nids[i];
93
0
 out:
94
0
  EC_KEY_free(ec);
95
0
  EC_GROUP_free(eg);
96
0
  return nid;
97
0
}
98
99
static u_int
100
ssh_ecdsa_size(const struct sshkey *key)
101
0
{
102
0
  switch (key->ecdsa_nid) {
103
0
  case NID_X9_62_prime256v1:
104
0
    return 256;
105
0
  case NID_secp384r1:
106
0
    return 384;
107
0
  case NID_secp521r1:
108
0
    return 521;
109
0
  default:
110
0
    return 0;
111
0
  }
112
0
}
113
114
static void
115
ssh_ecdsa_cleanup(struct sshkey *k)
116
932
{
117
932
  EVP_PKEY_free(k->pkey);
118
932
  k->pkey = NULL;
119
932
}
120
121
static int
122
ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
123
0
{
124
0
  if (a->pkey == NULL || b->pkey == NULL)
125
0
    return 0;
126
0
  return EVP_PKEY_cmp(a->pkey, b->pkey) == 1;
127
0
}
128
129
static int
130
ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
131
    enum sshkey_serialize_rep opts)
132
0
{
133
0
  int r;
134
135
0
  if (key->pkey == NULL)
136
0
    return SSH_ERR_INVALID_ARGUMENT;
137
0
  if ((r = sshbuf_put_cstring(b,
138
0
      sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
139
0
      (r = sshbuf_put_ec_pkey(b, key->pkey)) != 0)
140
0
    return r;
141
142
0
  return 0;
143
0
}
144
145
static int
146
ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
147
    enum sshkey_serialize_rep opts)
148
0
{
149
0
  int r;
150
151
0
  if (!sshkey_is_cert(key)) {
152
0
    if ((r = ssh_ecdsa_serialize_public(key, b, opts)) != 0)
153
0
      return r;
154
0
  }
155
0
  if ((r = sshbuf_put_bignum2(b,
156
0
      EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(key->pkey)))) != 0)
157
0
    return r;
158
0
  return 0;
159
0
}
160
161
static int
162
ssh_ecdsa_generate(struct sshkey *k, int bits)
163
0
{
164
0
  EVP_PKEY *res = NULL;
165
0
  EVP_PKEY_CTX *ctx = NULL;
166
0
  int ret = SSH_ERR_INTERNAL_ERROR;
167
168
0
  if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
169
0
    return SSH_ERR_KEY_LENGTH;
170
171
0
  if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL)
172
0
    return SSH_ERR_ALLOC_FAIL;
173
174
0
  if (EVP_PKEY_keygen_init(ctx) <= 0 ||
175
0
      EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, k->ecdsa_nid) <= 0 ||
176
0
      EVP_PKEY_keygen(ctx, &res) <= 0) {
177
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
178
0
    goto out;
179
0
  }
180
  /* success */
181
0
  k->pkey = res;
182
0
  res = NULL;
183
0
  ret = 0;
184
0
 out:
185
0
  EVP_PKEY_free(res);
186
0
  EVP_PKEY_CTX_free(ctx);
187
0
  return ret;
188
0
}
189
190
static int
191
ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to)
192
0
{
193
0
  const EC_KEY *ec_from;
194
0
  EC_KEY *ec_to = NULL;
195
0
  int ret = SSH_ERR_INTERNAL_ERROR;
196
197
0
  ec_from = EVP_PKEY_get0_EC_KEY(from->pkey);
198
0
  if (ec_from == NULL)
199
0
    return SSH_ERR_LIBCRYPTO_ERROR;
200
201
0
  to->ecdsa_nid = from->ecdsa_nid;
202
0
  if ((ec_to = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL)
203
0
    return SSH_ERR_ALLOC_FAIL;
204
0
  if (EC_KEY_set_public_key(ec_to,
205
0
      EC_KEY_get0_public_key(ec_from)) != 1) {
206
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
207
0
    goto out;
208
0
  }
209
0
  EVP_PKEY_free(to->pkey);
210
0
  if ((to->pkey = EVP_PKEY_new()) == NULL) {
211
0
    ret = SSH_ERR_ALLOC_FAIL;
212
0
    goto out;
213
0
  }
214
0
  if (EVP_PKEY_set1_EC_KEY(to->pkey, ec_to) != 1) {
215
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
216
0
    goto out;
217
0
  }
218
0
  ret = 0;
219
0
 out:
220
0
  EC_KEY_free(ec_to);
221
0
  return ret;
222
0
}
223
224
static int
225
ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
226
    struct sshkey *key)
227
932
{
228
932
  int r;
229
932
  char *curve = NULL;
230
932
  EVP_PKEY *pkey = NULL;
231
932
  EC_KEY *ec = NULL;
232
233
932
  if ((key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype)) == -1)
234
0
    return SSH_ERR_INVALID_ARGUMENT;
235
932
  if ((r = sshbuf_get_cstring(b, &curve, NULL)) != 0)
236
19
    goto out;
237
913
  if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
238
123
    r = SSH_ERR_EC_CURVE_MISMATCH;
239
123
    goto out;
240
123
  }
241
790
  if ((ec = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
242
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
243
0
    goto out;
244
0
  }
245
790
  if ((r = sshbuf_get_eckey(b, ec)) != 0)
246
146
    goto out;
247
644
  if (sshkey_ec_validate_public(EC_KEY_get0_group(ec),
248
644
      EC_KEY_get0_public_key(ec)) != 0) {
249
0
    r = SSH_ERR_KEY_INVALID_EC_VALUE;
250
0
    goto out;
251
0
  }
252
644
  if ((pkey = EVP_PKEY_new()) == NULL) {
253
0
    r = SSH_ERR_ALLOC_FAIL;
254
0
    goto out;
255
0
  }
256
644
  if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) {
257
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
258
0
    goto out;
259
0
  }
260
644
  EVP_PKEY_free(key->pkey);
261
644
  key->pkey = pkey;
262
644
  pkey = NULL;
263
  /* success */
264
644
  r = 0;
265
#ifdef DEBUG_PK
266
  sshkey_dump_ec_point(
267
      EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key->pkey)),
268
      EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(key->pkey)));
269
#endif
270
932
 out:
271
932
  EC_KEY_free(ec);
272
932
  EVP_PKEY_free(pkey);
273
932
  free(curve);
274
932
  return r;
275
644
}
276
277
static int
278
ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b,
279
    struct sshkey *key)
280
307
{
281
307
  int r;
282
307
  BIGNUM *exponent = NULL;
283
307
  EC_KEY *ec = NULL;
284
285
307
  if (!sshkey_is_cert(key)) {
286
307
    if ((r = ssh_ecdsa_deserialize_public(ktype, b, key)) != 0)
287
263
      return r;
288
307
  }
289
44
  if ((r = sshbuf_get_bignum2(b, &exponent)) != 0)
290
4
    goto out;
291
40
  if ((ec = EVP_PKEY_get1_EC_KEY(key->pkey)) == NULL) {
292
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
293
0
    goto out;
294
0
  }
295
40
  if (EC_KEY_set_private_key(ec, exponent) != 1) {
296
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
297
0
    goto out;
298
0
  }
299
40
  if ((r = sshkey_ec_validate_private(ec)) != 0)
300
33
    goto out;
301
7
  if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) {
302
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
303
0
    goto out;
304
0
  }
305
  /* success */
306
7
  r = 0;
307
44
 out:
308
44
  BN_clear_free(exponent);
309
44
  EC_KEY_free(ec);
310
44
  return r;
311
7
}
312
313
static int
314
ssh_ecdsa_sign(struct sshkey *key,
315
    u_char **sigp, size_t *lenp,
316
    const u_char *data, size_t dlen,
317
    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
318
0
{
319
0
  ECDSA_SIG *esig = NULL;
320
0
  unsigned char *sigb = NULL;
321
0
  const unsigned char *psig;
322
0
  const BIGNUM *sig_r, *sig_s;
323
0
  int hash_alg;
324
0
  size_t slen = 0;
325
0
  int ret = SSH_ERR_INTERNAL_ERROR;
326
327
0
  if (lenp != NULL)
328
0
    *lenp = 0;
329
0
  if (sigp != NULL)
330
0
    *sigp = NULL;
331
332
0
  if (key == NULL || key->pkey == NULL ||
333
0
      sshkey_type_plain(key->type) != KEY_ECDSA)
334
0
    return SSH_ERR_INVALID_ARGUMENT;
335
336
0
  if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
337
0
    return SSH_ERR_INTERNAL_ERROR;
338
339
0
  if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sigb, &slen,
340
0
      data, dlen)) != 0)
341
0
    goto out;
342
343
0
  psig = sigb;
344
0
  if ((esig = d2i_ECDSA_SIG(NULL, &psig, slen)) == NULL) {
345
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
346
0
    goto out;
347
0
  }
348
0
  ECDSA_SIG_get0(esig, &sig_r, &sig_s);
349
350
0
  if ((ret = ssh_ecdsa_encode_store_sig(key, sig_r, sig_s,
351
0
      sigp, lenp)) != 0)
352
0
    goto out;
353
  /* success */
354
0
  ret = 0;
355
0
 out:
356
0
  freezero(sigb, slen);
357
0
  ECDSA_SIG_free(esig);
358
0
  return ret;
359
0
}
360
361
int
362
ssh_ecdsa_encode_store_sig(const struct sshkey *key,
363
    const BIGNUM *sig_r, const BIGNUM *sig_s,
364
    u_char **sigp, size_t *lenp)
365
0
{
366
0
  struct sshbuf *b = NULL, *bb = NULL;
367
0
  int ret;
368
0
  size_t len;
369
370
0
  if (lenp != NULL)
371
0
    *lenp = 0;
372
0
  if (sigp != NULL)
373
0
    *sigp = NULL;
374
375
0
  if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
376
0
    ret = SSH_ERR_ALLOC_FAIL;
377
0
    goto out;
378
0
  }
379
0
  if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 ||
380
0
      (ret = sshbuf_put_bignum2(bb, sig_s)) != 0)
381
0
    goto out;
382
0
  if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
383
0
      (ret = sshbuf_put_stringb(b, bb)) != 0)
384
0
    goto out;
385
0
  len = sshbuf_len(b);
386
0
  if (sigp != NULL) {
387
0
    if ((*sigp = malloc(len)) == NULL) {
388
0
      ret = SSH_ERR_ALLOC_FAIL;
389
0
      goto out;
390
0
    }
391
0
    memcpy(*sigp, sshbuf_ptr(b), len);
392
0
  }
393
0
  if (lenp != NULL)
394
0
    *lenp = len;
395
0
  ret = 0;
396
0
 out:
397
0
  sshbuf_free(b);
398
0
  sshbuf_free(bb);
399
0
  return ret;
400
0
}
401
402
static int
403
ssh_ecdsa_verify(const struct sshkey *key,
404
    const u_char *sig, size_t siglen,
405
    const u_char *data, size_t dlen, const char *alg, u_int compat,
406
    struct sshkey_sig_details **detailsp)
407
140
{
408
140
  ECDSA_SIG *esig = NULL;
409
140
  BIGNUM *sig_r = NULL, *sig_s = NULL;
410
140
  int hash_alg, len = 0;
411
140
  int ret = SSH_ERR_INTERNAL_ERROR;
412
140
  struct sshbuf *b = NULL, *sigbuf = NULL;
413
140
  char *ktype = NULL;
414
140
  unsigned char *sigb = NULL, *cp;
415
416
140
  if (key == NULL || key->pkey == NULL ||
417
140
      sshkey_type_plain(key->type) != KEY_ECDSA ||
418
140
      sig == NULL || siglen == 0)
419
0
    return SSH_ERR_INVALID_ARGUMENT;
420
421
140
  if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
422
0
    return SSH_ERR_INTERNAL_ERROR;
423
424
  /* fetch signature */
425
140
  if ((b = sshbuf_from(sig, siglen)) == NULL)
426
0
    return SSH_ERR_ALLOC_FAIL;
427
140
  if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
428
137
      sshbuf_froms(b, &sigbuf) != 0) {
429
5
    ret = SSH_ERR_INVALID_FORMAT;
430
5
    goto out;
431
5
  }
432
135
  if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
433
107
    ret = SSH_ERR_KEY_TYPE_MISMATCH;
434
107
    goto out;
435
107
  }
436
28
  if (sshbuf_len(b) != 0) {
437
10
    ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
438
10
    goto out;
439
10
  }
440
441
  /* parse signature */
442
18
  if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 ||
443
16
      sshbuf_get_bignum2(sigbuf, &sig_s) != 0) {
444
4
    ret = SSH_ERR_INVALID_FORMAT;
445
4
    goto out;
446
4
  }
447
14
  if (sshbuf_len(sigbuf) != 0) {
448
7
    ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
449
7
    goto out;
450
7
  }
451
452
7
  if ((esig = ECDSA_SIG_new()) == NULL) {
453
0
    ret = SSH_ERR_ALLOC_FAIL;
454
0
    goto out;
455
0
  }
456
7
  if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) {
457
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
458
0
    goto out;
459
0
  }
460
7
  sig_r = sig_s = NULL; /* transferred */
461
462
7
  if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) {
463
0
    len = 0;
464
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
465
0
    goto out;
466
0
  }
467
7
  if ((sigb = calloc(1, len)) == NULL) {
468
0
    ret = SSH_ERR_ALLOC_FAIL;
469
0
    goto out;
470
0
  }
471
7
  cp = sigb; /* ASN1_item_i2d increments the pointer past the object */
472
7
  if (i2d_ECDSA_SIG(esig, &cp) != len) {
473
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
474
0
    goto out;
475
0
  }
476
7
  if ((ret = sshkey_pkey_digest_verify(key->pkey, hash_alg,
477
7
      data, dlen, sigb, len)) != 0)
478
7
    goto out;
479
  /* success */
480
140
 out:
481
140
  freezero(sigb, len);
482
140
  sshbuf_free(sigbuf);
483
140
  sshbuf_free(b);
484
140
  ECDSA_SIG_free(esig);
485
140
  BN_clear_free(sig_r);
486
140
  BN_clear_free(sig_s);
487
140
  free(ktype);
488
140
  return ret;
489
7
}
490
491
/* NB. not static; used by ECDSA-SK */
492
const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
493
  /* .size = */   ssh_ecdsa_size,
494
  /* .alloc = */    NULL,
495
  /* .cleanup = */  ssh_ecdsa_cleanup,
496
  /* .equal = */    ssh_ecdsa_equal,
497
  /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
498
  /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
499
  /* .ssh_serialize_private = */ ssh_ecdsa_serialize_private,
500
  /* .ssh_deserialize_private = */ ssh_ecdsa_deserialize_private,
501
  /* .generate = */ ssh_ecdsa_generate,
502
  /* .copy_public = */  ssh_ecdsa_copy_public,
503
  /* .sign = */   ssh_ecdsa_sign,
504
  /* .verify = */   ssh_ecdsa_verify,
505
};
506
507
const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {
508
  /* .name = */   "ecdsa-sha2-nistp256",
509
  /* .shortname = */  "ECDSA",
510
  /* .sigalg = */   NULL,
511
  /* .type = */   KEY_ECDSA,
512
  /* .nid = */    NID_X9_62_prime256v1,
513
  /* .cert = */   0,
514
  /* .sigonly = */  0,
515
  /* .keybits = */  0,
516
  /* .funcs = */    &sshkey_ecdsa_funcs,
517
};
518
519
const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl = {
520
  /* .name = */   "ecdsa-sha2-nistp256-cert-v01@openssh.com",
521
  /* .shortname = */  "ECDSA-CERT",
522
  /* .sigalg = */   NULL,
523
  /* .type = */   KEY_ECDSA_CERT,
524
  /* .nid = */    NID_X9_62_prime256v1,
525
  /* .cert = */   1,
526
  /* .sigonly = */  0,
527
  /* .keybits = */  0,
528
  /* .funcs = */    &sshkey_ecdsa_funcs,
529
};
530
531
const struct sshkey_impl sshkey_ecdsa_nistp384_impl = {
532
  /* .name = */   "ecdsa-sha2-nistp384",
533
  /* .shortname = */  "ECDSA",
534
  /* .sigalg = */   NULL,
535
  /* .type = */   KEY_ECDSA,
536
  /* .nid = */    NID_secp384r1,
537
  /* .cert = */   0,
538
  /* .sigonly = */  0,
539
  /* .keybits = */  0,
540
  /* .funcs = */    &sshkey_ecdsa_funcs,
541
};
542
543
const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl = {
544
  /* .name = */   "ecdsa-sha2-nistp384-cert-v01@openssh.com",
545
  /* .shortname = */  "ECDSA-CERT",
546
  /* .sigalg = */   NULL,
547
  /* .type = */   KEY_ECDSA_CERT,
548
  /* .nid = */    NID_secp384r1,
549
  /* .cert = */   1,
550
  /* .sigonly = */  0,
551
  /* .keybits = */  0,
552
  /* .funcs = */    &sshkey_ecdsa_funcs,
553
};
554
555
const struct sshkey_impl sshkey_ecdsa_nistp521_impl = {
556
  /* .name = */   "ecdsa-sha2-nistp521",
557
  /* .shortname = */  "ECDSA",
558
  /* .sigalg = */   NULL,
559
  /* .type = */   KEY_ECDSA,
560
  /* .nid = */    NID_secp521r1,
561
  /* .cert = */   0,
562
  /* .sigonly = */  0,
563
  /* .keybits = */  0,
564
  /* .funcs = */    &sshkey_ecdsa_funcs,
565
};
566
567
const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl = {
568
  /* .name = */   "ecdsa-sha2-nistp521-cert-v01@openssh.com",
569
  /* .shortname = */  "ECDSA-CERT",
570
  /* .sigalg = */   NULL,
571
  /* .type = */   KEY_ECDSA_CERT,
572
  /* .nid = */    NID_secp521r1,
573
  /* .cert = */   1,
574
  /* .sigonly = */  0,
575
  /* .keybits = */  0,
576
  /* .funcs = */    &sshkey_ecdsa_funcs,
577
};
578
579
#endif /* WITH_OPENSSL */