1*0afa8e06SEd Maste /* 2*0afa8e06SEd Maste * Copyright (c) 2018 Yubico AB. All rights reserved. 3*0afa8e06SEd Maste * Use of this source code is governed by a BSD-style 4*0afa8e06SEd Maste * license that can be found in the LICENSE file. 5*0afa8e06SEd Maste */ 6*0afa8e06SEd Maste 7*0afa8e06SEd Maste #include <openssl/bn.h> 8*0afa8e06SEd Maste #include <openssl/obj_mac.h> 9*0afa8e06SEd Maste 10*0afa8e06SEd Maste #include "fido.h" 11*0afa8e06SEd Maste #include "fido/es256.h" 12*0afa8e06SEd Maste 13*0afa8e06SEd Maste static int 14*0afa8e06SEd Maste decode_coord(const cbor_item_t *item, void *xy, size_t xy_len) 15*0afa8e06SEd Maste { 16*0afa8e06SEd Maste if (cbor_isa_bytestring(item) == false || 17*0afa8e06SEd Maste cbor_bytestring_is_definite(item) == false || 18*0afa8e06SEd Maste cbor_bytestring_length(item) != xy_len) { 19*0afa8e06SEd Maste fido_log_debug("%s: cbor type", __func__); 20*0afa8e06SEd Maste return (-1); 21*0afa8e06SEd Maste } 22*0afa8e06SEd Maste 23*0afa8e06SEd Maste memcpy(xy, cbor_bytestring_handle(item), xy_len); 24*0afa8e06SEd Maste 25*0afa8e06SEd Maste return (0); 26*0afa8e06SEd Maste } 27*0afa8e06SEd Maste 28*0afa8e06SEd Maste static int 29*0afa8e06SEd Maste decode_pubkey_point(const cbor_item_t *key, const cbor_item_t *val, void *arg) 30*0afa8e06SEd Maste { 31*0afa8e06SEd Maste es256_pk_t *k = arg; 32*0afa8e06SEd Maste 33*0afa8e06SEd Maste if (cbor_isa_negint(key) == false || 34*0afa8e06SEd Maste cbor_int_get_width(key) != CBOR_INT_8) 35*0afa8e06SEd Maste return (0); /* ignore */ 36*0afa8e06SEd Maste 37*0afa8e06SEd Maste switch (cbor_get_uint8(key)) { 38*0afa8e06SEd Maste case 1: /* x coordinate */ 39*0afa8e06SEd Maste return (decode_coord(val, &k->x, sizeof(k->x))); 40*0afa8e06SEd Maste case 2: /* y coordinate */ 41*0afa8e06SEd Maste return (decode_coord(val, &k->y, sizeof(k->y))); 42*0afa8e06SEd Maste } 43*0afa8e06SEd Maste 44*0afa8e06SEd Maste return (0); /* ignore */ 45*0afa8e06SEd Maste } 46*0afa8e06SEd Maste 47*0afa8e06SEd Maste int 48*0afa8e06SEd Maste es256_pk_decode(const cbor_item_t *item, es256_pk_t *k) 49*0afa8e06SEd Maste { 50*0afa8e06SEd Maste if (cbor_isa_map(item) == false || 51*0afa8e06SEd Maste cbor_map_is_definite(item) == false || 52*0afa8e06SEd Maste cbor_map_iter(item, k, decode_pubkey_point) < 0) { 53*0afa8e06SEd Maste fido_log_debug("%s: cbor type", __func__); 54*0afa8e06SEd Maste return (-1); 55*0afa8e06SEd Maste } 56*0afa8e06SEd Maste 57*0afa8e06SEd Maste return (0); 58*0afa8e06SEd Maste } 59*0afa8e06SEd Maste 60*0afa8e06SEd Maste cbor_item_t * 61*0afa8e06SEd Maste es256_pk_encode(const es256_pk_t *pk, int ecdh) 62*0afa8e06SEd Maste { 63*0afa8e06SEd Maste cbor_item_t *item = NULL; 64*0afa8e06SEd Maste struct cbor_pair argv[5]; 65*0afa8e06SEd Maste int alg; 66*0afa8e06SEd Maste int ok = -1; 67*0afa8e06SEd Maste 68*0afa8e06SEd Maste memset(argv, 0, sizeof(argv)); 69*0afa8e06SEd Maste 70*0afa8e06SEd Maste if ((item = cbor_new_definite_map(5)) == NULL) 71*0afa8e06SEd Maste goto fail; 72*0afa8e06SEd Maste 73*0afa8e06SEd Maste /* kty */ 74*0afa8e06SEd Maste if ((argv[0].key = cbor_build_uint8(1)) == NULL || 75*0afa8e06SEd Maste (argv[0].value = cbor_build_uint8(2)) == NULL || 76*0afa8e06SEd Maste !cbor_map_add(item, argv[0])) 77*0afa8e06SEd Maste goto fail; 78*0afa8e06SEd Maste 79*0afa8e06SEd Maste /* 80*0afa8e06SEd Maste * "The COSEAlgorithmIdentifier used is -25 (ECDH-ES + 81*0afa8e06SEd Maste * HKDF-256) although this is NOT the algorithm actually 82*0afa8e06SEd Maste * used. Setting this to a different value may result in 83*0afa8e06SEd Maste * compatibility issues." 84*0afa8e06SEd Maste */ 85*0afa8e06SEd Maste if (ecdh) 86*0afa8e06SEd Maste alg = COSE_ECDH_ES256; 87*0afa8e06SEd Maste else 88*0afa8e06SEd Maste alg = COSE_ES256; 89*0afa8e06SEd Maste 90*0afa8e06SEd Maste /* alg */ 91*0afa8e06SEd Maste if ((argv[1].key = cbor_build_uint8(3)) == NULL || 92*0afa8e06SEd Maste (argv[1].value = cbor_build_negint8((uint8_t)(-alg - 1))) == NULL || 93*0afa8e06SEd Maste !cbor_map_add(item, argv[1])) 94*0afa8e06SEd Maste goto fail; 95*0afa8e06SEd Maste 96*0afa8e06SEd Maste /* crv */ 97*0afa8e06SEd Maste if ((argv[2].key = cbor_build_negint8(0)) == NULL || 98*0afa8e06SEd Maste (argv[2].value = cbor_build_uint8(1)) == NULL || 99*0afa8e06SEd Maste !cbor_map_add(item, argv[2])) 100*0afa8e06SEd Maste goto fail; 101*0afa8e06SEd Maste 102*0afa8e06SEd Maste /* x */ 103*0afa8e06SEd Maste if ((argv[3].key = cbor_build_negint8(1)) == NULL || 104*0afa8e06SEd Maste (argv[3].value = cbor_build_bytestring(pk->x, 105*0afa8e06SEd Maste sizeof(pk->x))) == NULL || !cbor_map_add(item, argv[3])) 106*0afa8e06SEd Maste goto fail; 107*0afa8e06SEd Maste 108*0afa8e06SEd Maste /* y */ 109*0afa8e06SEd Maste if ((argv[4].key = cbor_build_negint8(2)) == NULL || 110*0afa8e06SEd Maste (argv[4].value = cbor_build_bytestring(pk->y, 111*0afa8e06SEd Maste sizeof(pk->y))) == NULL || !cbor_map_add(item, argv[4])) 112*0afa8e06SEd Maste goto fail; 113*0afa8e06SEd Maste 114*0afa8e06SEd Maste ok = 0; 115*0afa8e06SEd Maste fail: 116*0afa8e06SEd Maste if (ok < 0) { 117*0afa8e06SEd Maste if (item != NULL) { 118*0afa8e06SEd Maste cbor_decref(&item); 119*0afa8e06SEd Maste item = NULL; 120*0afa8e06SEd Maste } 121*0afa8e06SEd Maste } 122*0afa8e06SEd Maste 123*0afa8e06SEd Maste for (size_t i = 0; i < 5; i++) { 124*0afa8e06SEd Maste if (argv[i].key) 125*0afa8e06SEd Maste cbor_decref(&argv[i].key); 126*0afa8e06SEd Maste if (argv[i].value) 127*0afa8e06SEd Maste cbor_decref(&argv[i].value); 128*0afa8e06SEd Maste } 129*0afa8e06SEd Maste 130*0afa8e06SEd Maste return (item); 131*0afa8e06SEd Maste } 132*0afa8e06SEd Maste 133*0afa8e06SEd Maste es256_sk_t * 134*0afa8e06SEd Maste es256_sk_new(void) 135*0afa8e06SEd Maste { 136*0afa8e06SEd Maste return (calloc(1, sizeof(es256_sk_t))); 137*0afa8e06SEd Maste } 138*0afa8e06SEd Maste 139*0afa8e06SEd Maste void 140*0afa8e06SEd Maste es256_sk_free(es256_sk_t **skp) 141*0afa8e06SEd Maste { 142*0afa8e06SEd Maste es256_sk_t *sk; 143*0afa8e06SEd Maste 144*0afa8e06SEd Maste if (skp == NULL || (sk = *skp) == NULL) 145*0afa8e06SEd Maste return; 146*0afa8e06SEd Maste 147*0afa8e06SEd Maste freezero(sk, sizeof(*sk)); 148*0afa8e06SEd Maste *skp = NULL; 149*0afa8e06SEd Maste } 150*0afa8e06SEd Maste 151*0afa8e06SEd Maste es256_pk_t * 152*0afa8e06SEd Maste es256_pk_new(void) 153*0afa8e06SEd Maste { 154*0afa8e06SEd Maste return (calloc(1, sizeof(es256_pk_t))); 155*0afa8e06SEd Maste } 156*0afa8e06SEd Maste 157*0afa8e06SEd Maste void 158*0afa8e06SEd Maste es256_pk_free(es256_pk_t **pkp) 159*0afa8e06SEd Maste { 160*0afa8e06SEd Maste es256_pk_t *pk; 161*0afa8e06SEd Maste 162*0afa8e06SEd Maste if (pkp == NULL || (pk = *pkp) == NULL) 163*0afa8e06SEd Maste return; 164*0afa8e06SEd Maste 165*0afa8e06SEd Maste freezero(pk, sizeof(*pk)); 166*0afa8e06SEd Maste *pkp = NULL; 167*0afa8e06SEd Maste } 168*0afa8e06SEd Maste 169*0afa8e06SEd Maste int 170*0afa8e06SEd Maste es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len) 171*0afa8e06SEd Maste { 172*0afa8e06SEd Maste const uint8_t *p = ptr; 173*0afa8e06SEd Maste 174*0afa8e06SEd Maste if (len < sizeof(*pk)) 175*0afa8e06SEd Maste return (FIDO_ERR_INVALID_ARGUMENT); 176*0afa8e06SEd Maste 177*0afa8e06SEd Maste if (len == sizeof(*pk) + 1 && *p == 0x04) 178*0afa8e06SEd Maste memcpy(pk, ++p, sizeof(*pk)); /* uncompressed format */ 179*0afa8e06SEd Maste else 180*0afa8e06SEd Maste memcpy(pk, ptr, sizeof(*pk)); /* libfido2 x||y format */ 181*0afa8e06SEd Maste 182*0afa8e06SEd Maste return (FIDO_OK); 183*0afa8e06SEd Maste } 184*0afa8e06SEd Maste 185*0afa8e06SEd Maste int 186*0afa8e06SEd Maste es256_pk_set_x(es256_pk_t *pk, const unsigned char *x) 187*0afa8e06SEd Maste { 188*0afa8e06SEd Maste memcpy(pk->x, x, sizeof(pk->x)); 189*0afa8e06SEd Maste 190*0afa8e06SEd Maste return (0); 191*0afa8e06SEd Maste } 192*0afa8e06SEd Maste 193*0afa8e06SEd Maste int 194*0afa8e06SEd Maste es256_pk_set_y(es256_pk_t *pk, const unsigned char *y) 195*0afa8e06SEd Maste { 196*0afa8e06SEd Maste memcpy(pk->y, y, sizeof(pk->y)); 197*0afa8e06SEd Maste 198*0afa8e06SEd Maste return (0); 199*0afa8e06SEd Maste } 200*0afa8e06SEd Maste 201*0afa8e06SEd Maste int 202*0afa8e06SEd Maste es256_sk_create(es256_sk_t *key) 203*0afa8e06SEd Maste { 204*0afa8e06SEd Maste EVP_PKEY_CTX *pctx = NULL; 205*0afa8e06SEd Maste EVP_PKEY_CTX *kctx = NULL; 206*0afa8e06SEd Maste EVP_PKEY *p = NULL; 207*0afa8e06SEd Maste EVP_PKEY *k = NULL; 208*0afa8e06SEd Maste const EC_KEY *ec; 209*0afa8e06SEd Maste const BIGNUM *d; 210*0afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 211*0afa8e06SEd Maste int n; 212*0afa8e06SEd Maste int ok = -1; 213*0afa8e06SEd Maste 214*0afa8e06SEd Maste if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL || 215*0afa8e06SEd Maste EVP_PKEY_paramgen_init(pctx) <= 0 || 216*0afa8e06SEd Maste EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0 || 217*0afa8e06SEd Maste EVP_PKEY_paramgen(pctx, &p) <= 0) { 218*0afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_paramgen", __func__); 219*0afa8e06SEd Maste goto fail; 220*0afa8e06SEd Maste } 221*0afa8e06SEd Maste 222*0afa8e06SEd Maste if ((kctx = EVP_PKEY_CTX_new(p, NULL)) == NULL || 223*0afa8e06SEd Maste EVP_PKEY_keygen_init(kctx) <= 0 || EVP_PKEY_keygen(kctx, &k) <= 0) { 224*0afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_keygen", __func__); 225*0afa8e06SEd Maste goto fail; 226*0afa8e06SEd Maste } 227*0afa8e06SEd Maste 228*0afa8e06SEd Maste if ((ec = EVP_PKEY_get0_EC_KEY(k)) == NULL || 229*0afa8e06SEd Maste (d = EC_KEY_get0_private_key(ec)) == NULL || 230*0afa8e06SEd Maste (n = BN_num_bytes(d)) < 0 || (size_t)n > sizeof(key->d) || 231*0afa8e06SEd Maste (n = BN_bn2bin(d, key->d)) < 0 || (size_t)n > sizeof(key->d)) { 232*0afa8e06SEd Maste fido_log_debug("%s: EC_KEY_get0_private_key", __func__); 233*0afa8e06SEd Maste goto fail; 234*0afa8e06SEd Maste } 235*0afa8e06SEd Maste 236*0afa8e06SEd Maste ok = 0; 237*0afa8e06SEd Maste fail: 238*0afa8e06SEd Maste if (p != NULL) 239*0afa8e06SEd Maste EVP_PKEY_free(p); 240*0afa8e06SEd Maste if (k != NULL) 241*0afa8e06SEd Maste EVP_PKEY_free(k); 242*0afa8e06SEd Maste if (pctx != NULL) 243*0afa8e06SEd Maste EVP_PKEY_CTX_free(pctx); 244*0afa8e06SEd Maste if (kctx != NULL) 245*0afa8e06SEd Maste EVP_PKEY_CTX_free(kctx); 246*0afa8e06SEd Maste 247*0afa8e06SEd Maste return (ok); 248*0afa8e06SEd Maste } 249*0afa8e06SEd Maste 250*0afa8e06SEd Maste EVP_PKEY * 251*0afa8e06SEd Maste es256_pk_to_EVP_PKEY(const es256_pk_t *k) 252*0afa8e06SEd Maste { 253*0afa8e06SEd Maste BN_CTX *bnctx = NULL; 254*0afa8e06SEd Maste EC_KEY *ec = NULL; 255*0afa8e06SEd Maste EC_POINT *q = NULL; 256*0afa8e06SEd Maste EVP_PKEY *pkey = NULL; 257*0afa8e06SEd Maste BIGNUM *x = NULL; 258*0afa8e06SEd Maste BIGNUM *y = NULL; 259*0afa8e06SEd Maste const EC_GROUP *g = NULL; 260*0afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 261*0afa8e06SEd Maste int ok = -1; 262*0afa8e06SEd Maste 263*0afa8e06SEd Maste if ((bnctx = BN_CTX_new()) == NULL) 264*0afa8e06SEd Maste goto fail; 265*0afa8e06SEd Maste 266*0afa8e06SEd Maste BN_CTX_start(bnctx); 267*0afa8e06SEd Maste 268*0afa8e06SEd Maste if ((x = BN_CTX_get(bnctx)) == NULL || 269*0afa8e06SEd Maste (y = BN_CTX_get(bnctx)) == NULL) 270*0afa8e06SEd Maste goto fail; 271*0afa8e06SEd Maste 272*0afa8e06SEd Maste if (BN_bin2bn(k->x, sizeof(k->x), x) == NULL || 273*0afa8e06SEd Maste BN_bin2bn(k->y, sizeof(k->y), y) == NULL) { 274*0afa8e06SEd Maste fido_log_debug("%s: BN_bin2bn", __func__); 275*0afa8e06SEd Maste goto fail; 276*0afa8e06SEd Maste } 277*0afa8e06SEd Maste 278*0afa8e06SEd Maste if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || 279*0afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL) { 280*0afa8e06SEd Maste fido_log_debug("%s: EC_KEY init", __func__); 281*0afa8e06SEd Maste goto fail; 282*0afa8e06SEd Maste } 283*0afa8e06SEd Maste 284*0afa8e06SEd Maste if ((q = EC_POINT_new(g)) == NULL || 285*0afa8e06SEd Maste EC_POINT_set_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 || 286*0afa8e06SEd Maste EC_KEY_set_public_key(ec, q) == 0) { 287*0afa8e06SEd Maste fido_log_debug("%s: EC_KEY_set_public_key", __func__); 288*0afa8e06SEd Maste goto fail; 289*0afa8e06SEd Maste } 290*0afa8e06SEd Maste 291*0afa8e06SEd Maste if ((pkey = EVP_PKEY_new()) == NULL || 292*0afa8e06SEd Maste EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) { 293*0afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__); 294*0afa8e06SEd Maste goto fail; 295*0afa8e06SEd Maste } 296*0afa8e06SEd Maste 297*0afa8e06SEd Maste ec = NULL; /* at this point, ec belongs to evp */ 298*0afa8e06SEd Maste 299*0afa8e06SEd Maste ok = 0; 300*0afa8e06SEd Maste fail: 301*0afa8e06SEd Maste if (bnctx != NULL) { 302*0afa8e06SEd Maste BN_CTX_end(bnctx); 303*0afa8e06SEd Maste BN_CTX_free(bnctx); 304*0afa8e06SEd Maste } 305*0afa8e06SEd Maste 306*0afa8e06SEd Maste if (ec != NULL) 307*0afa8e06SEd Maste EC_KEY_free(ec); 308*0afa8e06SEd Maste if (q != NULL) 309*0afa8e06SEd Maste EC_POINT_free(q); 310*0afa8e06SEd Maste 311*0afa8e06SEd Maste if (ok < 0 && pkey != NULL) { 312*0afa8e06SEd Maste EVP_PKEY_free(pkey); 313*0afa8e06SEd Maste pkey = NULL; 314*0afa8e06SEd Maste } 315*0afa8e06SEd Maste 316*0afa8e06SEd Maste return (pkey); 317*0afa8e06SEd Maste } 318*0afa8e06SEd Maste 319*0afa8e06SEd Maste int 320*0afa8e06SEd Maste es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec) 321*0afa8e06SEd Maste { 322*0afa8e06SEd Maste BN_CTX *bnctx = NULL; 323*0afa8e06SEd Maste BIGNUM *x = NULL; 324*0afa8e06SEd Maste BIGNUM *y = NULL; 325*0afa8e06SEd Maste const EC_POINT *q = NULL; 326*0afa8e06SEd Maste const EC_GROUP *g = NULL; 327*0afa8e06SEd Maste int ok = FIDO_ERR_INTERNAL; 328*0afa8e06SEd Maste int n; 329*0afa8e06SEd Maste 330*0afa8e06SEd Maste if ((q = EC_KEY_get0_public_key(ec)) == NULL || 331*0afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL || 332*0afa8e06SEd Maste (bnctx = BN_CTX_new()) == NULL) 333*0afa8e06SEd Maste goto fail; 334*0afa8e06SEd Maste 335*0afa8e06SEd Maste BN_CTX_start(bnctx); 336*0afa8e06SEd Maste 337*0afa8e06SEd Maste if ((x = BN_CTX_get(bnctx)) == NULL || 338*0afa8e06SEd Maste (y = BN_CTX_get(bnctx)) == NULL) 339*0afa8e06SEd Maste goto fail; 340*0afa8e06SEd Maste 341*0afa8e06SEd Maste if (EC_POINT_get_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 || 342*0afa8e06SEd Maste (n = BN_num_bytes(x)) < 0 || (size_t)n > sizeof(pk->x) || 343*0afa8e06SEd Maste (n = BN_num_bytes(y)) < 0 || (size_t)n > sizeof(pk->y)) { 344*0afa8e06SEd Maste fido_log_debug("%s: EC_POINT_get_affine_coordinates_GFp", 345*0afa8e06SEd Maste __func__); 346*0afa8e06SEd Maste goto fail; 347*0afa8e06SEd Maste } 348*0afa8e06SEd Maste 349*0afa8e06SEd Maste if ((n = BN_bn2bin(x, pk->x)) < 0 || (size_t)n > sizeof(pk->x) || 350*0afa8e06SEd Maste (n = BN_bn2bin(y, pk->y)) < 0 || (size_t)n > sizeof(pk->y)) { 351*0afa8e06SEd Maste fido_log_debug("%s: BN_bn2bin", __func__); 352*0afa8e06SEd Maste goto fail; 353*0afa8e06SEd Maste } 354*0afa8e06SEd Maste 355*0afa8e06SEd Maste ok = FIDO_OK; 356*0afa8e06SEd Maste fail: 357*0afa8e06SEd Maste if (bnctx != NULL) { 358*0afa8e06SEd Maste BN_CTX_end(bnctx); 359*0afa8e06SEd Maste BN_CTX_free(bnctx); 360*0afa8e06SEd Maste } 361*0afa8e06SEd Maste 362*0afa8e06SEd Maste return (ok); 363*0afa8e06SEd Maste } 364*0afa8e06SEd Maste 365*0afa8e06SEd Maste EVP_PKEY * 366*0afa8e06SEd Maste es256_sk_to_EVP_PKEY(const es256_sk_t *k) 367*0afa8e06SEd Maste { 368*0afa8e06SEd Maste BN_CTX *bnctx = NULL; 369*0afa8e06SEd Maste EC_KEY *ec = NULL; 370*0afa8e06SEd Maste EVP_PKEY *pkey = NULL; 371*0afa8e06SEd Maste BIGNUM *d = NULL; 372*0afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 373*0afa8e06SEd Maste int ok = -1; 374*0afa8e06SEd Maste 375*0afa8e06SEd Maste if ((bnctx = BN_CTX_new()) == NULL) 376*0afa8e06SEd Maste goto fail; 377*0afa8e06SEd Maste 378*0afa8e06SEd Maste BN_CTX_start(bnctx); 379*0afa8e06SEd Maste 380*0afa8e06SEd Maste if ((d = BN_CTX_get(bnctx)) == NULL || 381*0afa8e06SEd Maste BN_bin2bn(k->d, sizeof(k->d), d) == NULL) { 382*0afa8e06SEd Maste fido_log_debug("%s: BN_bin2bn", __func__); 383*0afa8e06SEd Maste goto fail; 384*0afa8e06SEd Maste } 385*0afa8e06SEd Maste 386*0afa8e06SEd Maste if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || 387*0afa8e06SEd Maste EC_KEY_set_private_key(ec, d) == 0) { 388*0afa8e06SEd Maste fido_log_debug("%s: EC_KEY_set_private_key", __func__); 389*0afa8e06SEd Maste goto fail; 390*0afa8e06SEd Maste } 391*0afa8e06SEd Maste 392*0afa8e06SEd Maste if ((pkey = EVP_PKEY_new()) == NULL || 393*0afa8e06SEd Maste EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) { 394*0afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__); 395*0afa8e06SEd Maste goto fail; 396*0afa8e06SEd Maste } 397*0afa8e06SEd Maste 398*0afa8e06SEd Maste ec = NULL; /* at this point, ec belongs to evp */ 399*0afa8e06SEd Maste 400*0afa8e06SEd Maste ok = 0; 401*0afa8e06SEd Maste fail: 402*0afa8e06SEd Maste if (bnctx != NULL) { 403*0afa8e06SEd Maste BN_CTX_end(bnctx); 404*0afa8e06SEd Maste BN_CTX_free(bnctx); 405*0afa8e06SEd Maste } 406*0afa8e06SEd Maste 407*0afa8e06SEd Maste if (ec != NULL) 408*0afa8e06SEd Maste EC_KEY_free(ec); 409*0afa8e06SEd Maste 410*0afa8e06SEd Maste if (ok < 0 && pkey != NULL) { 411*0afa8e06SEd Maste EVP_PKEY_free(pkey); 412*0afa8e06SEd Maste pkey = NULL; 413*0afa8e06SEd Maste } 414*0afa8e06SEd Maste 415*0afa8e06SEd Maste return (pkey); 416*0afa8e06SEd Maste } 417*0afa8e06SEd Maste 418*0afa8e06SEd Maste int 419*0afa8e06SEd Maste es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk) 420*0afa8e06SEd Maste { 421*0afa8e06SEd Maste BIGNUM *d = NULL; 422*0afa8e06SEd Maste EC_KEY *ec = NULL; 423*0afa8e06SEd Maste EC_POINT *q = NULL; 424*0afa8e06SEd Maste const EC_GROUP *g = NULL; 425*0afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 426*0afa8e06SEd Maste int ok = -1; 427*0afa8e06SEd Maste 428*0afa8e06SEd Maste if ((d = BN_bin2bn(sk->d, (int)sizeof(sk->d), NULL)) == NULL || 429*0afa8e06SEd Maste (ec = EC_KEY_new_by_curve_name(nid)) == NULL || 430*0afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL || 431*0afa8e06SEd Maste (q = EC_POINT_new(g)) == NULL) { 432*0afa8e06SEd Maste fido_log_debug("%s: get", __func__); 433*0afa8e06SEd Maste goto fail; 434*0afa8e06SEd Maste } 435*0afa8e06SEd Maste 436*0afa8e06SEd Maste if (EC_POINT_mul(g, q, d, NULL, NULL, NULL) == 0 || 437*0afa8e06SEd Maste EC_KEY_set_public_key(ec, q) == 0 || 438*0afa8e06SEd Maste es256_pk_from_EC_KEY(pk, ec) != FIDO_OK) { 439*0afa8e06SEd Maste fido_log_debug("%s: set", __func__); 440*0afa8e06SEd Maste goto fail; 441*0afa8e06SEd Maste } 442*0afa8e06SEd Maste 443*0afa8e06SEd Maste ok = 0; 444*0afa8e06SEd Maste fail: 445*0afa8e06SEd Maste if (d != NULL) 446*0afa8e06SEd Maste BN_clear_free(d); 447*0afa8e06SEd Maste if (q != NULL) 448*0afa8e06SEd Maste EC_POINT_free(q); 449*0afa8e06SEd Maste if (ec != NULL) 450*0afa8e06SEd Maste EC_KEY_free(ec); 451*0afa8e06SEd Maste 452*0afa8e06SEd Maste return (ok); 453*0afa8e06SEd Maste } 454