10afa8e06SEd Maste /* 2*f540a430SEd Maste * Copyright (c) 2018-2021 Yubico AB. All rights reserved. 30afa8e06SEd Maste * Use of this source code is governed by a BSD-style 40afa8e06SEd Maste * license that can be found in the LICENSE file. 50afa8e06SEd Maste */ 60afa8e06SEd Maste 70afa8e06SEd Maste #include <openssl/bn.h> 8*f540a430SEd Maste #include <openssl/ecdsa.h> 90afa8e06SEd Maste #include <openssl/obj_mac.h> 100afa8e06SEd Maste 110afa8e06SEd Maste #include "fido.h" 120afa8e06SEd Maste #include "fido/es256.h" 130afa8e06SEd Maste 140afa8e06SEd Maste static int 150afa8e06SEd Maste decode_coord(const cbor_item_t *item, void *xy, size_t xy_len) 160afa8e06SEd Maste { 170afa8e06SEd Maste if (cbor_isa_bytestring(item) == false || 180afa8e06SEd Maste cbor_bytestring_is_definite(item) == false || 190afa8e06SEd Maste cbor_bytestring_length(item) != xy_len) { 200afa8e06SEd Maste fido_log_debug("%s: cbor type", __func__); 210afa8e06SEd Maste return (-1); 220afa8e06SEd Maste } 230afa8e06SEd Maste 240afa8e06SEd Maste memcpy(xy, cbor_bytestring_handle(item), xy_len); 250afa8e06SEd Maste 260afa8e06SEd Maste return (0); 270afa8e06SEd Maste } 280afa8e06SEd Maste 290afa8e06SEd Maste static int 300afa8e06SEd Maste decode_pubkey_point(const cbor_item_t *key, const cbor_item_t *val, void *arg) 310afa8e06SEd Maste { 320afa8e06SEd Maste es256_pk_t *k = arg; 330afa8e06SEd Maste 340afa8e06SEd Maste if (cbor_isa_negint(key) == false || 350afa8e06SEd Maste cbor_int_get_width(key) != CBOR_INT_8) 360afa8e06SEd Maste return (0); /* ignore */ 370afa8e06SEd Maste 380afa8e06SEd Maste switch (cbor_get_uint8(key)) { 390afa8e06SEd Maste case 1: /* x coordinate */ 400afa8e06SEd Maste return (decode_coord(val, &k->x, sizeof(k->x))); 410afa8e06SEd Maste case 2: /* y coordinate */ 420afa8e06SEd Maste return (decode_coord(val, &k->y, sizeof(k->y))); 430afa8e06SEd Maste } 440afa8e06SEd Maste 450afa8e06SEd Maste return (0); /* ignore */ 460afa8e06SEd Maste } 470afa8e06SEd Maste 480afa8e06SEd Maste int 490afa8e06SEd Maste es256_pk_decode(const cbor_item_t *item, es256_pk_t *k) 500afa8e06SEd Maste { 510afa8e06SEd Maste if (cbor_isa_map(item) == false || 520afa8e06SEd Maste cbor_map_is_definite(item) == false || 530afa8e06SEd Maste cbor_map_iter(item, k, decode_pubkey_point) < 0) { 540afa8e06SEd Maste fido_log_debug("%s: cbor type", __func__); 550afa8e06SEd Maste return (-1); 560afa8e06SEd Maste } 570afa8e06SEd Maste 580afa8e06SEd Maste return (0); 590afa8e06SEd Maste } 600afa8e06SEd Maste 610afa8e06SEd Maste cbor_item_t * 620afa8e06SEd Maste es256_pk_encode(const es256_pk_t *pk, int ecdh) 630afa8e06SEd Maste { 640afa8e06SEd Maste cbor_item_t *item = NULL; 650afa8e06SEd Maste struct cbor_pair argv[5]; 660afa8e06SEd Maste int alg; 670afa8e06SEd Maste int ok = -1; 680afa8e06SEd Maste 690afa8e06SEd Maste memset(argv, 0, sizeof(argv)); 700afa8e06SEd Maste 710afa8e06SEd Maste if ((item = cbor_new_definite_map(5)) == NULL) 720afa8e06SEd Maste goto fail; 730afa8e06SEd Maste 740afa8e06SEd Maste /* kty */ 750afa8e06SEd Maste if ((argv[0].key = cbor_build_uint8(1)) == NULL || 760afa8e06SEd Maste (argv[0].value = cbor_build_uint8(2)) == NULL || 770afa8e06SEd Maste !cbor_map_add(item, argv[0])) 780afa8e06SEd Maste goto fail; 790afa8e06SEd Maste 800afa8e06SEd Maste /* 810afa8e06SEd Maste * "The COSEAlgorithmIdentifier used is -25 (ECDH-ES + 820afa8e06SEd Maste * HKDF-256) although this is NOT the algorithm actually 830afa8e06SEd Maste * used. Setting this to a different value may result in 840afa8e06SEd Maste * compatibility issues." 850afa8e06SEd Maste */ 860afa8e06SEd Maste if (ecdh) 870afa8e06SEd Maste alg = COSE_ECDH_ES256; 880afa8e06SEd Maste else 890afa8e06SEd Maste alg = COSE_ES256; 900afa8e06SEd Maste 910afa8e06SEd Maste /* alg */ 920afa8e06SEd Maste if ((argv[1].key = cbor_build_uint8(3)) == NULL || 930afa8e06SEd Maste (argv[1].value = cbor_build_negint8((uint8_t)(-alg - 1))) == NULL || 940afa8e06SEd Maste !cbor_map_add(item, argv[1])) 950afa8e06SEd Maste goto fail; 960afa8e06SEd Maste 970afa8e06SEd Maste /* crv */ 980afa8e06SEd Maste if ((argv[2].key = cbor_build_negint8(0)) == NULL || 990afa8e06SEd Maste (argv[2].value = cbor_build_uint8(1)) == NULL || 1000afa8e06SEd Maste !cbor_map_add(item, argv[2])) 1010afa8e06SEd Maste goto fail; 1020afa8e06SEd Maste 1030afa8e06SEd Maste /* x */ 1040afa8e06SEd Maste if ((argv[3].key = cbor_build_negint8(1)) == NULL || 1050afa8e06SEd Maste (argv[3].value = cbor_build_bytestring(pk->x, 1060afa8e06SEd Maste sizeof(pk->x))) == NULL || !cbor_map_add(item, argv[3])) 1070afa8e06SEd Maste goto fail; 1080afa8e06SEd Maste 1090afa8e06SEd Maste /* y */ 1100afa8e06SEd Maste if ((argv[4].key = cbor_build_negint8(2)) == NULL || 1110afa8e06SEd Maste (argv[4].value = cbor_build_bytestring(pk->y, 1120afa8e06SEd Maste sizeof(pk->y))) == NULL || !cbor_map_add(item, argv[4])) 1130afa8e06SEd Maste goto fail; 1140afa8e06SEd Maste 1150afa8e06SEd Maste ok = 0; 1160afa8e06SEd Maste fail: 1170afa8e06SEd Maste if (ok < 0) { 1180afa8e06SEd Maste if (item != NULL) { 1190afa8e06SEd Maste cbor_decref(&item); 1200afa8e06SEd Maste item = NULL; 1210afa8e06SEd Maste } 1220afa8e06SEd Maste } 1230afa8e06SEd Maste 1240afa8e06SEd Maste for (size_t i = 0; i < 5; i++) { 1250afa8e06SEd Maste if (argv[i].key) 1260afa8e06SEd Maste cbor_decref(&argv[i].key); 1270afa8e06SEd Maste if (argv[i].value) 1280afa8e06SEd Maste cbor_decref(&argv[i].value); 1290afa8e06SEd Maste } 1300afa8e06SEd Maste 1310afa8e06SEd Maste return (item); 1320afa8e06SEd Maste } 1330afa8e06SEd Maste 1340afa8e06SEd Maste es256_sk_t * 1350afa8e06SEd Maste es256_sk_new(void) 1360afa8e06SEd Maste { 1370afa8e06SEd Maste return (calloc(1, sizeof(es256_sk_t))); 1380afa8e06SEd Maste } 1390afa8e06SEd Maste 1400afa8e06SEd Maste void 1410afa8e06SEd Maste es256_sk_free(es256_sk_t **skp) 1420afa8e06SEd Maste { 1430afa8e06SEd Maste es256_sk_t *sk; 1440afa8e06SEd Maste 1450afa8e06SEd Maste if (skp == NULL || (sk = *skp) == NULL) 1460afa8e06SEd Maste return; 1470afa8e06SEd Maste 1480afa8e06SEd Maste freezero(sk, sizeof(*sk)); 1490afa8e06SEd Maste *skp = NULL; 1500afa8e06SEd Maste } 1510afa8e06SEd Maste 1520afa8e06SEd Maste es256_pk_t * 1530afa8e06SEd Maste es256_pk_new(void) 1540afa8e06SEd Maste { 1550afa8e06SEd Maste return (calloc(1, sizeof(es256_pk_t))); 1560afa8e06SEd Maste } 1570afa8e06SEd Maste 1580afa8e06SEd Maste void 1590afa8e06SEd Maste es256_pk_free(es256_pk_t **pkp) 1600afa8e06SEd Maste { 1610afa8e06SEd Maste es256_pk_t *pk; 1620afa8e06SEd Maste 1630afa8e06SEd Maste if (pkp == NULL || (pk = *pkp) == NULL) 1640afa8e06SEd Maste return; 1650afa8e06SEd Maste 1660afa8e06SEd Maste freezero(pk, sizeof(*pk)); 1670afa8e06SEd Maste *pkp = NULL; 1680afa8e06SEd Maste } 1690afa8e06SEd Maste 1700afa8e06SEd Maste int 1710afa8e06SEd Maste es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len) 1720afa8e06SEd Maste { 1730afa8e06SEd Maste const uint8_t *p = ptr; 1740afa8e06SEd Maste 1750afa8e06SEd Maste if (len < sizeof(*pk)) 1760afa8e06SEd Maste return (FIDO_ERR_INVALID_ARGUMENT); 1770afa8e06SEd Maste 1780afa8e06SEd Maste if (len == sizeof(*pk) + 1 && *p == 0x04) 1790afa8e06SEd Maste memcpy(pk, ++p, sizeof(*pk)); /* uncompressed format */ 1800afa8e06SEd Maste else 1810afa8e06SEd Maste memcpy(pk, ptr, sizeof(*pk)); /* libfido2 x||y format */ 1820afa8e06SEd Maste 1830afa8e06SEd Maste return (FIDO_OK); 1840afa8e06SEd Maste } 1850afa8e06SEd Maste 1860afa8e06SEd Maste int 1870afa8e06SEd Maste es256_pk_set_x(es256_pk_t *pk, const unsigned char *x) 1880afa8e06SEd Maste { 1890afa8e06SEd Maste memcpy(pk->x, x, sizeof(pk->x)); 1900afa8e06SEd Maste 1910afa8e06SEd Maste return (0); 1920afa8e06SEd Maste } 1930afa8e06SEd Maste 1940afa8e06SEd Maste int 1950afa8e06SEd Maste es256_pk_set_y(es256_pk_t *pk, const unsigned char *y) 1960afa8e06SEd Maste { 1970afa8e06SEd Maste memcpy(pk->y, y, sizeof(pk->y)); 1980afa8e06SEd Maste 1990afa8e06SEd Maste return (0); 2000afa8e06SEd Maste } 2010afa8e06SEd Maste 2020afa8e06SEd Maste int 2030afa8e06SEd Maste es256_sk_create(es256_sk_t *key) 2040afa8e06SEd Maste { 2050afa8e06SEd Maste EVP_PKEY_CTX *pctx = NULL; 2060afa8e06SEd Maste EVP_PKEY_CTX *kctx = NULL; 2070afa8e06SEd Maste EVP_PKEY *p = NULL; 2080afa8e06SEd Maste EVP_PKEY *k = NULL; 2090afa8e06SEd Maste const EC_KEY *ec; 2100afa8e06SEd Maste const BIGNUM *d; 2110afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 2120afa8e06SEd Maste int n; 2130afa8e06SEd Maste int ok = -1; 2140afa8e06SEd Maste 2150afa8e06SEd Maste if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL || 2160afa8e06SEd Maste EVP_PKEY_paramgen_init(pctx) <= 0 || 2170afa8e06SEd Maste EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0 || 2180afa8e06SEd Maste EVP_PKEY_paramgen(pctx, &p) <= 0) { 2190afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_paramgen", __func__); 2200afa8e06SEd Maste goto fail; 2210afa8e06SEd Maste } 2220afa8e06SEd Maste 2230afa8e06SEd Maste if ((kctx = EVP_PKEY_CTX_new(p, NULL)) == NULL || 2240afa8e06SEd Maste EVP_PKEY_keygen_init(kctx) <= 0 || EVP_PKEY_keygen(kctx, &k) <= 0) { 2250afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_keygen", __func__); 2260afa8e06SEd Maste goto fail; 2270afa8e06SEd Maste } 2280afa8e06SEd Maste 2290afa8e06SEd Maste if ((ec = EVP_PKEY_get0_EC_KEY(k)) == NULL || 2300afa8e06SEd Maste (d = EC_KEY_get0_private_key(ec)) == NULL || 2310afa8e06SEd Maste (n = BN_num_bytes(d)) < 0 || (size_t)n > sizeof(key->d) || 2320afa8e06SEd Maste (n = BN_bn2bin(d, key->d)) < 0 || (size_t)n > sizeof(key->d)) { 2330afa8e06SEd Maste fido_log_debug("%s: EC_KEY_get0_private_key", __func__); 2340afa8e06SEd Maste goto fail; 2350afa8e06SEd Maste } 2360afa8e06SEd Maste 2370afa8e06SEd Maste ok = 0; 2380afa8e06SEd Maste fail: 2390afa8e06SEd Maste if (p != NULL) 2400afa8e06SEd Maste EVP_PKEY_free(p); 2410afa8e06SEd Maste if (k != NULL) 2420afa8e06SEd Maste EVP_PKEY_free(k); 2430afa8e06SEd Maste if (pctx != NULL) 2440afa8e06SEd Maste EVP_PKEY_CTX_free(pctx); 2450afa8e06SEd Maste if (kctx != NULL) 2460afa8e06SEd Maste EVP_PKEY_CTX_free(kctx); 2470afa8e06SEd Maste 2480afa8e06SEd Maste return (ok); 2490afa8e06SEd Maste } 2500afa8e06SEd Maste 2510afa8e06SEd Maste EVP_PKEY * 2520afa8e06SEd Maste es256_pk_to_EVP_PKEY(const es256_pk_t *k) 2530afa8e06SEd Maste { 2540afa8e06SEd Maste BN_CTX *bnctx = NULL; 2550afa8e06SEd Maste EC_KEY *ec = NULL; 2560afa8e06SEd Maste EC_POINT *q = NULL; 2570afa8e06SEd Maste EVP_PKEY *pkey = NULL; 2580afa8e06SEd Maste BIGNUM *x = NULL; 2590afa8e06SEd Maste BIGNUM *y = NULL; 2600afa8e06SEd Maste const EC_GROUP *g = NULL; 2610afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 2620afa8e06SEd Maste int ok = -1; 2630afa8e06SEd Maste 2640afa8e06SEd Maste if ((bnctx = BN_CTX_new()) == NULL) 2650afa8e06SEd Maste goto fail; 2660afa8e06SEd Maste 2670afa8e06SEd Maste BN_CTX_start(bnctx); 2680afa8e06SEd Maste 2690afa8e06SEd Maste if ((x = BN_CTX_get(bnctx)) == NULL || 2700afa8e06SEd Maste (y = BN_CTX_get(bnctx)) == NULL) 2710afa8e06SEd Maste goto fail; 2720afa8e06SEd Maste 2730afa8e06SEd Maste if (BN_bin2bn(k->x, sizeof(k->x), x) == NULL || 2740afa8e06SEd Maste BN_bin2bn(k->y, sizeof(k->y), y) == NULL) { 2750afa8e06SEd Maste fido_log_debug("%s: BN_bin2bn", __func__); 2760afa8e06SEd Maste goto fail; 2770afa8e06SEd Maste } 2780afa8e06SEd Maste 2790afa8e06SEd Maste if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || 2800afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL) { 2810afa8e06SEd Maste fido_log_debug("%s: EC_KEY init", __func__); 2820afa8e06SEd Maste goto fail; 2830afa8e06SEd Maste } 2840afa8e06SEd Maste 2850afa8e06SEd Maste if ((q = EC_POINT_new(g)) == NULL || 2860afa8e06SEd Maste EC_POINT_set_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 || 2870afa8e06SEd Maste EC_KEY_set_public_key(ec, q) == 0) { 2880afa8e06SEd Maste fido_log_debug("%s: EC_KEY_set_public_key", __func__); 2890afa8e06SEd Maste goto fail; 2900afa8e06SEd Maste } 2910afa8e06SEd Maste 2920afa8e06SEd Maste if ((pkey = EVP_PKEY_new()) == NULL || 2930afa8e06SEd Maste EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) { 2940afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__); 2950afa8e06SEd Maste goto fail; 2960afa8e06SEd Maste } 2970afa8e06SEd Maste 2980afa8e06SEd Maste ec = NULL; /* at this point, ec belongs to evp */ 2990afa8e06SEd Maste 3000afa8e06SEd Maste ok = 0; 3010afa8e06SEd Maste fail: 3020afa8e06SEd Maste if (bnctx != NULL) { 3030afa8e06SEd Maste BN_CTX_end(bnctx); 3040afa8e06SEd Maste BN_CTX_free(bnctx); 3050afa8e06SEd Maste } 3060afa8e06SEd Maste 3070afa8e06SEd Maste if (ec != NULL) 3080afa8e06SEd Maste EC_KEY_free(ec); 3090afa8e06SEd Maste if (q != NULL) 3100afa8e06SEd Maste EC_POINT_free(q); 3110afa8e06SEd Maste 3120afa8e06SEd Maste if (ok < 0 && pkey != NULL) { 3130afa8e06SEd Maste EVP_PKEY_free(pkey); 3140afa8e06SEd Maste pkey = NULL; 3150afa8e06SEd Maste } 3160afa8e06SEd Maste 3170afa8e06SEd Maste return (pkey); 3180afa8e06SEd Maste } 3190afa8e06SEd Maste 3200afa8e06SEd Maste int 3210afa8e06SEd Maste es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec) 3220afa8e06SEd Maste { 3230afa8e06SEd Maste BN_CTX *bnctx = NULL; 3240afa8e06SEd Maste BIGNUM *x = NULL; 3250afa8e06SEd Maste BIGNUM *y = NULL; 3260afa8e06SEd Maste const EC_POINT *q = NULL; 3270afa8e06SEd Maste const EC_GROUP *g = NULL; 3280afa8e06SEd Maste int ok = FIDO_ERR_INTERNAL; 3290afa8e06SEd Maste int n; 3300afa8e06SEd Maste 3310afa8e06SEd Maste if ((q = EC_KEY_get0_public_key(ec)) == NULL || 3320afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL || 3330afa8e06SEd Maste (bnctx = BN_CTX_new()) == NULL) 3340afa8e06SEd Maste goto fail; 3350afa8e06SEd Maste 3360afa8e06SEd Maste BN_CTX_start(bnctx); 3370afa8e06SEd Maste 3380afa8e06SEd Maste if ((x = BN_CTX_get(bnctx)) == NULL || 3390afa8e06SEd Maste (y = BN_CTX_get(bnctx)) == NULL) 3400afa8e06SEd Maste goto fail; 3410afa8e06SEd Maste 3420afa8e06SEd Maste if (EC_POINT_get_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 || 3430afa8e06SEd Maste (n = BN_num_bytes(x)) < 0 || (size_t)n > sizeof(pk->x) || 3440afa8e06SEd Maste (n = BN_num_bytes(y)) < 0 || (size_t)n > sizeof(pk->y)) { 3450afa8e06SEd Maste fido_log_debug("%s: EC_POINT_get_affine_coordinates_GFp", 3460afa8e06SEd Maste __func__); 3470afa8e06SEd Maste goto fail; 3480afa8e06SEd Maste } 3490afa8e06SEd Maste 3500afa8e06SEd Maste if ((n = BN_bn2bin(x, pk->x)) < 0 || (size_t)n > sizeof(pk->x) || 3510afa8e06SEd Maste (n = BN_bn2bin(y, pk->y)) < 0 || (size_t)n > sizeof(pk->y)) { 3520afa8e06SEd Maste fido_log_debug("%s: BN_bn2bin", __func__); 3530afa8e06SEd Maste goto fail; 3540afa8e06SEd Maste } 3550afa8e06SEd Maste 3560afa8e06SEd Maste ok = FIDO_OK; 3570afa8e06SEd Maste fail: 3580afa8e06SEd Maste if (bnctx != NULL) { 3590afa8e06SEd Maste BN_CTX_end(bnctx); 3600afa8e06SEd Maste BN_CTX_free(bnctx); 3610afa8e06SEd Maste } 3620afa8e06SEd Maste 3630afa8e06SEd Maste return (ok); 3640afa8e06SEd Maste } 3650afa8e06SEd Maste 366*f540a430SEd Maste int 367*f540a430SEd Maste es256_pk_from_EVP_PKEY(es256_pk_t *pk, const EVP_PKEY *pkey) 368*f540a430SEd Maste { 369*f540a430SEd Maste EC_KEY *ec; 370*f540a430SEd Maste 371*f540a430SEd Maste if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC || 372*f540a430SEd Maste (ec = EVP_PKEY_get0(pkey)) == NULL) 373*f540a430SEd Maste return (FIDO_ERR_INVALID_ARGUMENT); 374*f540a430SEd Maste 375*f540a430SEd Maste return (es256_pk_from_EC_KEY(pk, ec)); 376*f540a430SEd Maste } 377*f540a430SEd Maste 3780afa8e06SEd Maste EVP_PKEY * 3790afa8e06SEd Maste es256_sk_to_EVP_PKEY(const es256_sk_t *k) 3800afa8e06SEd Maste { 3810afa8e06SEd Maste BN_CTX *bnctx = NULL; 3820afa8e06SEd Maste EC_KEY *ec = NULL; 3830afa8e06SEd Maste EVP_PKEY *pkey = NULL; 3840afa8e06SEd Maste BIGNUM *d = NULL; 3850afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 3860afa8e06SEd Maste int ok = -1; 3870afa8e06SEd Maste 3880afa8e06SEd Maste if ((bnctx = BN_CTX_new()) == NULL) 3890afa8e06SEd Maste goto fail; 3900afa8e06SEd Maste 3910afa8e06SEd Maste BN_CTX_start(bnctx); 3920afa8e06SEd Maste 3930afa8e06SEd Maste if ((d = BN_CTX_get(bnctx)) == NULL || 3940afa8e06SEd Maste BN_bin2bn(k->d, sizeof(k->d), d) == NULL) { 3950afa8e06SEd Maste fido_log_debug("%s: BN_bin2bn", __func__); 3960afa8e06SEd Maste goto fail; 3970afa8e06SEd Maste } 3980afa8e06SEd Maste 3990afa8e06SEd Maste if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || 4000afa8e06SEd Maste EC_KEY_set_private_key(ec, d) == 0) { 4010afa8e06SEd Maste fido_log_debug("%s: EC_KEY_set_private_key", __func__); 4020afa8e06SEd Maste goto fail; 4030afa8e06SEd Maste } 4040afa8e06SEd Maste 4050afa8e06SEd Maste if ((pkey = EVP_PKEY_new()) == NULL || 4060afa8e06SEd Maste EVP_PKEY_assign_EC_KEY(pkey, ec) == 0) { 4070afa8e06SEd Maste fido_log_debug("%s: EVP_PKEY_assign_EC_KEY", __func__); 4080afa8e06SEd Maste goto fail; 4090afa8e06SEd Maste } 4100afa8e06SEd Maste 4110afa8e06SEd Maste ec = NULL; /* at this point, ec belongs to evp */ 4120afa8e06SEd Maste 4130afa8e06SEd Maste ok = 0; 4140afa8e06SEd Maste fail: 4150afa8e06SEd Maste if (bnctx != NULL) { 4160afa8e06SEd Maste BN_CTX_end(bnctx); 4170afa8e06SEd Maste BN_CTX_free(bnctx); 4180afa8e06SEd Maste } 4190afa8e06SEd Maste 4200afa8e06SEd Maste if (ec != NULL) 4210afa8e06SEd Maste EC_KEY_free(ec); 4220afa8e06SEd Maste 4230afa8e06SEd Maste if (ok < 0 && pkey != NULL) { 4240afa8e06SEd Maste EVP_PKEY_free(pkey); 4250afa8e06SEd Maste pkey = NULL; 4260afa8e06SEd Maste } 4270afa8e06SEd Maste 4280afa8e06SEd Maste return (pkey); 4290afa8e06SEd Maste } 4300afa8e06SEd Maste 4310afa8e06SEd Maste int 4320afa8e06SEd Maste es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk) 4330afa8e06SEd Maste { 4340afa8e06SEd Maste BIGNUM *d = NULL; 4350afa8e06SEd Maste EC_KEY *ec = NULL; 4360afa8e06SEd Maste EC_POINT *q = NULL; 4370afa8e06SEd Maste const EC_GROUP *g = NULL; 4380afa8e06SEd Maste const int nid = NID_X9_62_prime256v1; 4390afa8e06SEd Maste int ok = -1; 4400afa8e06SEd Maste 4410afa8e06SEd Maste if ((d = BN_bin2bn(sk->d, (int)sizeof(sk->d), NULL)) == NULL || 4420afa8e06SEd Maste (ec = EC_KEY_new_by_curve_name(nid)) == NULL || 4430afa8e06SEd Maste (g = EC_KEY_get0_group(ec)) == NULL || 4440afa8e06SEd Maste (q = EC_POINT_new(g)) == NULL) { 4450afa8e06SEd Maste fido_log_debug("%s: get", __func__); 4460afa8e06SEd Maste goto fail; 4470afa8e06SEd Maste } 4480afa8e06SEd Maste 4490afa8e06SEd Maste if (EC_POINT_mul(g, q, d, NULL, NULL, NULL) == 0 || 4500afa8e06SEd Maste EC_KEY_set_public_key(ec, q) == 0 || 4510afa8e06SEd Maste es256_pk_from_EC_KEY(pk, ec) != FIDO_OK) { 4520afa8e06SEd Maste fido_log_debug("%s: set", __func__); 4530afa8e06SEd Maste goto fail; 4540afa8e06SEd Maste } 4550afa8e06SEd Maste 4560afa8e06SEd Maste ok = 0; 4570afa8e06SEd Maste fail: 4580afa8e06SEd Maste if (d != NULL) 4590afa8e06SEd Maste BN_clear_free(d); 4600afa8e06SEd Maste if (q != NULL) 4610afa8e06SEd Maste EC_POINT_free(q); 4620afa8e06SEd Maste if (ec != NULL) 4630afa8e06SEd Maste EC_KEY_free(ec); 4640afa8e06SEd Maste 4650afa8e06SEd Maste return (ok); 4660afa8e06SEd Maste } 467*f540a430SEd Maste 468*f540a430SEd Maste int 469*f540a430SEd Maste es256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey, 470*f540a430SEd Maste const fido_blob_t *sig) 471*f540a430SEd Maste { 472*f540a430SEd Maste EVP_PKEY_CTX *pctx = NULL; 473*f540a430SEd Maste int ok = -1; 474*f540a430SEd Maste 475*f540a430SEd Maste if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { 476*f540a430SEd Maste fido_log_debug("%s: EVP_PKEY_base_id", __func__); 477*f540a430SEd Maste goto fail; 478*f540a430SEd Maste } 479*f540a430SEd Maste 480*f540a430SEd Maste if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL || 481*f540a430SEd Maste EVP_PKEY_verify_init(pctx) != 1 || 482*f540a430SEd Maste EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr, 483*f540a430SEd Maste dgst->len) != 1) { 484*f540a430SEd Maste fido_log_debug("%s: EVP_PKEY_verify", __func__); 485*f540a430SEd Maste goto fail; 486*f540a430SEd Maste } 487*f540a430SEd Maste 488*f540a430SEd Maste ok = 0; 489*f540a430SEd Maste fail: 490*f540a430SEd Maste EVP_PKEY_CTX_free(pctx); 491*f540a430SEd Maste 492*f540a430SEd Maste return (ok); 493*f540a430SEd Maste } 494*f540a430SEd Maste 495*f540a430SEd Maste int 496*f540a430SEd Maste es256_pk_verify_sig(const fido_blob_t *dgst, const es256_pk_t *pk, 497*f540a430SEd Maste const fido_blob_t *sig) 498*f540a430SEd Maste { 499*f540a430SEd Maste EVP_PKEY *pkey; 500*f540a430SEd Maste int ok = -1; 501*f540a430SEd Maste 502*f540a430SEd Maste if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL || 503*f540a430SEd Maste es256_verify_sig(dgst, pkey, sig) < 0) { 504*f540a430SEd Maste fido_log_debug("%s: es256_verify_sig", __func__); 505*f540a430SEd Maste goto fail; 506*f540a430SEd Maste } 507*f540a430SEd Maste 508*f540a430SEd Maste ok = 0; 509*f540a430SEd Maste fail: 510*f540a430SEd Maste EVP_PKEY_free(pkey); 511*f540a430SEd Maste 512*f540a430SEd Maste return (ok); 513*f540a430SEd Maste } 514