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