1d4afb5ceSopenharmony_ci /* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci * 24d4afb5ceSopenharmony_ci * lws_genec provides an EC abstraction api in lws that works the 25d4afb5ceSopenharmony_ci * same whether you are using openssl or mbedtls crypto functions underneath. 26d4afb5ceSopenharmony_ci */ 27d4afb5ceSopenharmony_ci#include "private-lib-core.h" 28d4afb5ceSopenharmony_ci#include "private-lib-tls-openssl.h" 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \ 31d4afb5ceSopenharmony_ci (OPENSSL_VERSION_NUMBER >= 0x30000000l) && \ 32d4afb5ceSopenharmony_ci !defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS) 33d4afb5ceSopenharmony_ci/* msvc doesn't have #warning... */ 34d4afb5ceSopenharmony_ci#error "You probably need LWS_SUPPRESS_DEPRECATED_API_WARNINGS" 35d4afb5ceSopenharmony_ci#endif 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 38d4afb5ceSopenharmony_ci#include "openssl/ecdh.h" 39d4afb5ceSopenharmony_ci#endif 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci/* 42d4afb5ceSopenharmony_ci * Care: many openssl apis return 1 for success. These are translated to the 43d4afb5ceSopenharmony_ci * lws convention of 0 for success. 44d4afb5ceSopenharmony_ci */ 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 47d4afb5ceSopenharmony_ciEVP_PKEY * EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *p) 48d4afb5ceSopenharmony_ci{ 49d4afb5ceSopenharmony_ci return p->pkey; 50d4afb5ceSopenharmony_ci} 51d4afb5ceSopenharmony_ci#endif 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci#if !defined(LWS_HAVE_ECDSA_SIG_set0) 54d4afb5ceSopenharmony_cistatic void 55d4afb5ceSopenharmony_ciECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) 56d4afb5ceSopenharmony_ci{ 57d4afb5ceSopenharmony_ci if (pr != NULL) 58d4afb5ceSopenharmony_ci *pr = sig->r; 59d4afb5ceSopenharmony_ci if (ps != NULL) 60d4afb5ceSopenharmony_ci *ps = sig->s; 61d4afb5ceSopenharmony_ci} 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_cistatic int 64d4afb5ceSopenharmony_ciECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) 65d4afb5ceSopenharmony_ci{ 66d4afb5ceSopenharmony_ci if (r == NULL || s == NULL) 67d4afb5ceSopenharmony_ci return 0; 68d4afb5ceSopenharmony_ci BN_clear_free(sig->r); 69d4afb5ceSopenharmony_ci BN_clear_free(sig->s); 70d4afb5ceSopenharmony_ci sig->r = r; 71d4afb5ceSopenharmony_ci sig->s = s; 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci return 1; 74d4afb5ceSopenharmony_ci} 75d4afb5ceSopenharmony_ci#endif 76d4afb5ceSopenharmony_ci#if !defined(LWS_HAVE_BN_bn2binpad) 77d4afb5ceSopenharmony_ciint BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) 78d4afb5ceSopenharmony_ci{ 79d4afb5ceSopenharmony_ci int i; 80d4afb5ceSopenharmony_ci#if !defined(USE_WOLFSSL) 81d4afb5ceSopenharmony_ci BN_ULONG l; 82d4afb5ceSopenharmony_ci#endif 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_WOLFSSL) 85d4afb5ceSopenharmony_ci bn_check_top(a); 86d4afb5ceSopenharmony_ci#endif 87d4afb5ceSopenharmony_ci i = BN_num_bytes(a); 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci /* Add leading zeroes if necessary */ 90d4afb5ceSopenharmony_ci if (tolen > i) { 91d4afb5ceSopenharmony_ci memset(to, 0, (size_t)(tolen - i)); 92d4afb5ceSopenharmony_ci to += tolen - i; 93d4afb5ceSopenharmony_ci } 94d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 95d4afb5ceSopenharmony_ci BN_bn2bin(a, to); 96d4afb5ceSopenharmony_ci#else 97d4afb5ceSopenharmony_ci while (i--) { 98d4afb5ceSopenharmony_ci l = a->d[i / BN_BYTES]; 99d4afb5ceSopenharmony_ci *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; 100d4afb5ceSopenharmony_ci } 101d4afb5ceSopenharmony_ci#endif 102d4afb5ceSopenharmony_ci return tolen; 103d4afb5ceSopenharmony_ci} 104d4afb5ceSopenharmony_ci#endif 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_ciconst struct lws_ec_curves lws_ec_curves[4] = { 107d4afb5ceSopenharmony_ci /* 108d4afb5ceSopenharmony_ci * These are the curves we are willing to use by default... 109d4afb5ceSopenharmony_ci * 110d4afb5ceSopenharmony_ci * The 3 recommended+ (P-256) and optional curves in RFC7518 7.6 111d4afb5ceSopenharmony_ci * 112d4afb5ceSopenharmony_ci * Specific keys lengths from RFC8422 p20 113d4afb5ceSopenharmony_ci */ 114d4afb5ceSopenharmony_ci { "P-256", NID_X9_62_prime256v1, 32 }, 115d4afb5ceSopenharmony_ci { "P-384", NID_secp384r1, 48 }, 116d4afb5ceSopenharmony_ci { "P-521", NID_secp521r1, 66 }, 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci { NULL, 0, 0 } 119d4afb5ceSopenharmony_ci}; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_cistatic int 122d4afb5ceSopenharmony_cilws_genec_eckey_import(int nid, EVP_PKEY *pkey, 123d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *el) 124d4afb5ceSopenharmony_ci{ 125d4afb5ceSopenharmony_ci EC_KEY *ec = EC_KEY_new_by_curve_name(nid); 126d4afb5ceSopenharmony_ci BIGNUM *bn_d, *bn_x, *bn_y; 127d4afb5ceSopenharmony_ci int n; 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci if (!ec) 130d4afb5ceSopenharmony_ci return -1; 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci /* 133d4afb5ceSopenharmony_ci * EC_KEY contains 134d4afb5ceSopenharmony_ci * 135d4afb5ceSopenharmony_ci * EC_GROUP * group 136d4afb5ceSopenharmony_ci * EC_POINT * pub_key 137d4afb5ceSopenharmony_ci * BIGNUM * priv_key (ie, d) 138d4afb5ceSopenharmony_ci */ 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci bn_x = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_X].buf, 141d4afb5ceSopenharmony_ci (int)el[LWS_GENCRYPTO_EC_KEYEL_X].len, NULL); 142d4afb5ceSopenharmony_ci if (!bn_x) { 143d4afb5ceSopenharmony_ci lwsl_err("%s: BN_bin2bn (x) fail\n", __func__); 144d4afb5ceSopenharmony_ci goto bail; 145d4afb5ceSopenharmony_ci } 146d4afb5ceSopenharmony_ci bn_y = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_Y].buf, 147d4afb5ceSopenharmony_ci (int)el[LWS_GENCRYPTO_EC_KEYEL_Y].len, NULL); 148d4afb5ceSopenharmony_ci if (!bn_y) { 149d4afb5ceSopenharmony_ci lwsl_err("%s: BN_bin2bn (y) fail\n", __func__); 150d4afb5ceSopenharmony_ci goto bail1; 151d4afb5ceSopenharmony_ci } 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci /* 154d4afb5ceSopenharmony_ci * EC_KEY_set_public_key_affine_coordinates sets the public key for 155d4afb5ceSopenharmony_ci * key based on its affine co-ordinates, i.e. it constructs an 156d4afb5ceSopenharmony_ci * EC_POINT object based on the supplied x and y values and sets 157d4afb5ceSopenharmony_ci * the public key to be this EC_POINT. It will also performs 158d4afb5ceSopenharmony_ci * certain sanity checks on the key to confirm that it is valid. 159d4afb5ceSopenharmony_ci */ 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 162d4afb5ceSopenharmony_ci n = wolfSSL_EC_POINT_set_affine_coordinates_GFp(ec->group, 163d4afb5ceSopenharmony_ci ec->pub_key, 164d4afb5ceSopenharmony_ci bn_x, bn_y, 165d4afb5ceSopenharmony_ci NULL); 166d4afb5ceSopenharmony_ci#else 167d4afb5ceSopenharmony_ci n = EC_KEY_set_public_key_affine_coordinates(ec, bn_x, bn_y); 168d4afb5ceSopenharmony_ci#endif 169d4afb5ceSopenharmony_ci BN_free(bn_x); 170d4afb5ceSopenharmony_ci BN_free(bn_y); 171d4afb5ceSopenharmony_ci if (n != 1) { 172d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_set_public_key_affine_coordinates fail:\n", 173d4afb5ceSopenharmony_ci __func__); 174d4afb5ceSopenharmony_ci lws_tls_err_describe_clear(); 175d4afb5ceSopenharmony_ci goto bail; 176d4afb5ceSopenharmony_ci } 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci if (el[LWS_GENCRYPTO_EC_KEYEL_D].len) { 179d4afb5ceSopenharmony_ci bn_d = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_D].buf, 180d4afb5ceSopenharmony_ci (int)el[LWS_GENCRYPTO_EC_KEYEL_D].len, NULL); 181d4afb5ceSopenharmony_ci if (!bn_d) { 182d4afb5ceSopenharmony_ci lwsl_err("%s: BN_bin2bn (d) fail\n", __func__); 183d4afb5ceSopenharmony_ci goto bail; 184d4afb5ceSopenharmony_ci } 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci n = EC_KEY_set_private_key(ec, bn_d); 187d4afb5ceSopenharmony_ci BN_clear_free(bn_d); 188d4afb5ceSopenharmony_ci if (n != 1) { 189d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__); 190d4afb5ceSopenharmony_ci goto bail; 191d4afb5ceSopenharmony_ci } 192d4afb5ceSopenharmony_ci } 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci /* explicitly confirm the key pieces are consistent */ 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci#if !defined(USE_WOLFSSL) 197d4afb5ceSopenharmony_ci if (EC_KEY_check_key(ec) != 1) { 198d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__); 199d4afb5ceSopenharmony_ci goto bail; 200d4afb5ceSopenharmony_ci } 201d4afb5ceSopenharmony_ci#endif 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci n = EVP_PKEY_assign_EC_KEY(pkey, ec); 204d4afb5ceSopenharmony_ci if (n != 1) { 205d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_PKEY_set1_EC_KEY failed\n", __func__); 206d4afb5ceSopenharmony_ci return -1; 207d4afb5ceSopenharmony_ci } 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci return 0; 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_cibail1: 212d4afb5ceSopenharmony_ci BN_free(bn_x); 213d4afb5ceSopenharmony_cibail: 214d4afb5ceSopenharmony_ci EC_KEY_free(ec); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci return -1; 217d4afb5ceSopenharmony_ci} 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_cistatic int 220d4afb5ceSopenharmony_cilws_genec_keypair_import(struct lws_genec_ctx *ctx, 221d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve_table, 222d4afb5ceSopenharmony_ci EVP_PKEY_CTX **pctx, 223d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *el) 224d4afb5ceSopenharmony_ci{ 225d4afb5ceSopenharmony_ci EVP_PKEY *pkey = NULL; 226d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve; 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci if (el[LWS_GENCRYPTO_EC_KEYEL_CRV].len < 4) 229d4afb5ceSopenharmony_ci return -2; 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci curve = lws_genec_curve(curve_table, 232d4afb5ceSopenharmony_ci (char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf); 233d4afb5ceSopenharmony_ci if (!curve) 234d4afb5ceSopenharmony_ci return -3; 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci if ((el[LWS_GENCRYPTO_EC_KEYEL_D].len && 237d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_D].len != curve->key_bytes) || 238d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_X].len != curve->key_bytes || 239d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_Y].len != curve->key_bytes) 240d4afb5ceSopenharmony_ci return -4; 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len; 243d4afb5ceSopenharmony_ci 244d4afb5ceSopenharmony_ci pkey = EVP_PKEY_new(); 245d4afb5ceSopenharmony_ci if (!pkey) 246d4afb5ceSopenharmony_ci return -7; 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci if (lws_genec_eckey_import(curve->tls_lib_nid, pkey, el)) { 249d4afb5ceSopenharmony_ci lwsl_err("%s: lws_genec_eckey_import fail\n", __func__); 250d4afb5ceSopenharmony_ci goto bail; 251d4afb5ceSopenharmony_ci } 252d4afb5ceSopenharmony_ci 253d4afb5ceSopenharmony_ci *pctx = EVP_PKEY_CTX_new(pkey, NULL); 254d4afb5ceSopenharmony_ci EVP_PKEY_free(pkey); 255d4afb5ceSopenharmony_ci pkey = NULL; 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci if (!*pctx) 258d4afb5ceSopenharmony_ci goto bail; 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci return 0; 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_cibail: 263d4afb5ceSopenharmony_ci if (pkey) 264d4afb5ceSopenharmony_ci EVP_PKEY_free(pkey); 265d4afb5ceSopenharmony_ci 266d4afb5ceSopenharmony_ci if (*pctx) { 267d4afb5ceSopenharmony_ci EVP_PKEY_CTX_free(*pctx); 268d4afb5ceSopenharmony_ci *pctx = NULL; 269d4afb5ceSopenharmony_ci } 270d4afb5ceSopenharmony_ci 271d4afb5ceSopenharmony_ci return -9; 272d4afb5ceSopenharmony_ci} 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ciint 275d4afb5ceSopenharmony_cilws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context, 276d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve_table) 277d4afb5ceSopenharmony_ci{ 278d4afb5ceSopenharmony_ci ctx->context = context; 279d4afb5ceSopenharmony_ci ctx->ctx[0] = NULL; 280d4afb5ceSopenharmony_ci ctx->ctx[1] = NULL; 281d4afb5ceSopenharmony_ci ctx->curve_table = curve_table; 282d4afb5ceSopenharmony_ci ctx->genec_alg = LEGENEC_ECDH; 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci return 0; 285d4afb5ceSopenharmony_ci} 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ciint 288d4afb5ceSopenharmony_cilws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context, 289d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve_table) 290d4afb5ceSopenharmony_ci{ 291d4afb5ceSopenharmony_ci ctx->context = context; 292d4afb5ceSopenharmony_ci ctx->ctx[0] = NULL; 293d4afb5ceSopenharmony_ci ctx->ctx[1] = NULL; 294d4afb5ceSopenharmony_ci ctx->curve_table = curve_table; 295d4afb5ceSopenharmony_ci ctx->genec_alg = LEGENEC_ECDSA; 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_ci return 0; 298d4afb5ceSopenharmony_ci} 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ciint 301d4afb5ceSopenharmony_cilws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el, 302d4afb5ceSopenharmony_ci enum enum_lws_dh_side side) 303d4afb5ceSopenharmony_ci{ 304d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDH) 305d4afb5ceSopenharmony_ci return -1; 306d4afb5ceSopenharmony_ci 307d4afb5ceSopenharmony_ci return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[side], el); 308d4afb5ceSopenharmony_ci} 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_ciint 311d4afb5ceSopenharmony_cilws_genecdsa_set_key(struct lws_genec_ctx *ctx, 312d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *el) 313d4afb5ceSopenharmony_ci{ 314d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 315d4afb5ceSopenharmony_ci return -1; 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[0], el); 318d4afb5ceSopenharmony_ci} 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_cistatic void 321d4afb5ceSopenharmony_cilws_genec_keypair_destroy(EVP_PKEY_CTX **pctx) 322d4afb5ceSopenharmony_ci{ 323d4afb5ceSopenharmony_ci if (!*pctx) 324d4afb5ceSopenharmony_ci return; 325d4afb5ceSopenharmony_ci 326d4afb5ceSopenharmony_ci// lwsl_err("%p\n", EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx))); 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci// EC_KEY_free(EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx))); 329d4afb5ceSopenharmony_ci 330d4afb5ceSopenharmony_ci EVP_PKEY_CTX_free(*pctx); 331d4afb5ceSopenharmony_ci *pctx = NULL; 332d4afb5ceSopenharmony_ci} 333d4afb5ceSopenharmony_ci 334d4afb5ceSopenharmony_civoid 335d4afb5ceSopenharmony_cilws_genec_destroy(struct lws_genec_ctx *ctx) 336d4afb5ceSopenharmony_ci{ 337d4afb5ceSopenharmony_ci if (ctx->ctx[0]) 338d4afb5ceSopenharmony_ci lws_genec_keypair_destroy(&ctx->ctx[0]); 339d4afb5ceSopenharmony_ci if (ctx->ctx[1]) 340d4afb5ceSopenharmony_ci lws_genec_keypair_destroy(&ctx->ctx[1]); 341d4afb5ceSopenharmony_ci} 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_cistatic int 344d4afb5ceSopenharmony_cilws_genec_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, 345d4afb5ceSopenharmony_ci const char *curve_name, struct lws_gencrypto_keyelem *el) 346d4afb5ceSopenharmony_ci{ 347d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve; 348d4afb5ceSopenharmony_ci const EC_POINT *pubkey; 349d4afb5ceSopenharmony_ci EVP_PKEY *pkey = NULL; 350d4afb5ceSopenharmony_ci int ret = -29, n, m; 351d4afb5ceSopenharmony_ci BIGNUM *bn[3]; 352d4afb5ceSopenharmony_ci EC_KEY *ec; 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci curve = lws_genec_curve(ctx->curve_table, curve_name); 355d4afb5ceSopenharmony_ci if (!curve) { 356d4afb5ceSopenharmony_ci lwsl_err("%s: curve '%s' not supported\n", 357d4afb5ceSopenharmony_ci __func__, curve_name); 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci return -22; 360d4afb5ceSopenharmony_ci } 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci ec = EC_KEY_new_by_curve_name(curve->tls_lib_nid); 363d4afb5ceSopenharmony_ci if (!ec) { 364d4afb5ceSopenharmony_ci lwsl_err("%s: unknown nid %d\n", __func__, curve->tls_lib_nid); 365d4afb5ceSopenharmony_ci return -23; 366d4afb5ceSopenharmony_ci } 367d4afb5ceSopenharmony_ci 368d4afb5ceSopenharmony_ci if (EC_KEY_generate_key(ec) != 1) { 369d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_generate_key failed\n", __func__); 370d4afb5ceSopenharmony_ci goto bail; 371d4afb5ceSopenharmony_ci } 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci pkey = EVP_PKEY_new(); 374d4afb5ceSopenharmony_ci if (!pkey) 375d4afb5ceSopenharmony_ci goto bail; 376d4afb5ceSopenharmony_ci 377d4afb5ceSopenharmony_ci if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) { 378d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_PKEY_assign_EC_KEY failed\n", __func__); 379d4afb5ceSopenharmony_ci goto bail1; 380d4afb5ceSopenharmony_ci } 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci ctx->ctx[side] = EVP_PKEY_CTX_new(pkey, NULL); 383d4afb5ceSopenharmony_ci if (!ctx->ctx[side]) { 384d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_PKEY_CTX_new failed\n", __func__); 385d4afb5ceSopenharmony_ci goto bail1; 386d4afb5ceSopenharmony_ci } 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ci /* 389d4afb5ceSopenharmony_ci * we need to capture the individual element BIGNUMs into 390d4afb5ceSopenharmony_ci * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc 391d4afb5ceSopenharmony_ci */ 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci pubkey = EC_KEY_get0_public_key(ec); 394d4afb5ceSopenharmony_ci if (!pubkey) { 395d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__); 396d4afb5ceSopenharmony_ci goto bail1; 397d4afb5ceSopenharmony_ci } 398d4afb5ceSopenharmony_ci 399d4afb5ceSopenharmony_ci bn[0] = BN_new(); 400d4afb5ceSopenharmony_ci bn[1] = (BIGNUM *)EC_KEY_get0_private_key(ec); 401d4afb5ceSopenharmony_ci bn[2] = BN_new(); 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates) 404d4afb5ceSopenharmony_ci if (EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec), 405d4afb5ceSopenharmony_ci#else 406d4afb5ceSopenharmony_ci if (EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec), 407d4afb5ceSopenharmony_ci#endif 408d4afb5ceSopenharmony_ci pubkey, bn[0], bn[2], NULL) != 1) { 409d4afb5ceSopenharmony_ci lwsl_err("%s: EC_POINT_get_affine_coordinates_GFp failed\n", 410d4afb5ceSopenharmony_ci __func__); 411d4afb5ceSopenharmony_ci goto bail2; 412d4afb5ceSopenharmony_ci } 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1; 415d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf = 416d4afb5ceSopenharmony_ci lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec"); 417d4afb5ceSopenharmony_ci if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf) { 418d4afb5ceSopenharmony_ci lwsl_err("%s: OOM\n", __func__); 419d4afb5ceSopenharmony_ci goto bail2; 420d4afb5ceSopenharmony_ci } 421d4afb5ceSopenharmony_ci 422d4afb5ceSopenharmony_ci strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name); 423d4afb5ceSopenharmony_ci 424d4afb5ceSopenharmony_ci for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; 425d4afb5ceSopenharmony_ci n++) { 426d4afb5ceSopenharmony_ci el[n].len = curve->key_bytes; 427d4afb5ceSopenharmony_ci el[n].buf = lws_malloc(curve->key_bytes, "ec"); 428d4afb5ceSopenharmony_ci if (!el[n].buf) 429d4afb5ceSopenharmony_ci goto bail2; 430d4afb5ceSopenharmony_ci 431d4afb5ceSopenharmony_ci m = BN_bn2binpad(bn[n - 1], el[n].buf, (int32_t)el[n].len); 432d4afb5ceSopenharmony_ci if ((uint32_t)m != el[n].len) 433d4afb5ceSopenharmony_ci goto bail2; 434d4afb5ceSopenharmony_ci } 435d4afb5ceSopenharmony_ci 436d4afb5ceSopenharmony_ci ctx->has_private = 1; 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci ret = 0; 439d4afb5ceSopenharmony_ci 440d4afb5ceSopenharmony_cibail2: 441d4afb5ceSopenharmony_ci BN_clear_free(bn[0]); 442d4afb5ceSopenharmony_ci BN_clear_free(bn[2]); 443d4afb5ceSopenharmony_cibail1: 444d4afb5ceSopenharmony_ci EVP_PKEY_free(pkey); 445d4afb5ceSopenharmony_cibail: 446d4afb5ceSopenharmony_ci EC_KEY_free(ec); 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_ci return ret; 449d4afb5ceSopenharmony_ci} 450d4afb5ceSopenharmony_ci 451d4afb5ceSopenharmony_ciint 452d4afb5ceSopenharmony_cilws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, 453d4afb5ceSopenharmony_ci const char *curve_name, 454d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *el) 455d4afb5ceSopenharmony_ci{ 456d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDH) 457d4afb5ceSopenharmony_ci return -1; 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_ci return lws_genec_new_keypair(ctx, side, curve_name, el); 460d4afb5ceSopenharmony_ci} 461d4afb5ceSopenharmony_ci 462d4afb5ceSopenharmony_ciint 463d4afb5ceSopenharmony_cilws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name, 464d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *el) 465d4afb5ceSopenharmony_ci{ 466d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 467d4afb5ceSopenharmony_ci return -1; 468d4afb5ceSopenharmony_ci 469d4afb5ceSopenharmony_ci return lws_genec_new_keypair(ctx, LDHS_OURS, curve_name, el); 470d4afb5ceSopenharmony_ci} 471d4afb5ceSopenharmony_ci 472d4afb5ceSopenharmony_ci#if 0 473d4afb5ceSopenharmony_ciint 474d4afb5ceSopenharmony_cilws_genecdsa_hash_sign(struct lws_genec_ctx *ctx, const uint8_t *in, 475d4afb5ceSopenharmony_ci enum lws_genhash_types hash_type, 476d4afb5ceSopenharmony_ci uint8_t *sig, size_t sig_len) 477d4afb5ceSopenharmony_ci{ 478d4afb5ceSopenharmony_ci const EVP_MD *md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type); 479d4afb5ceSopenharmony_ci EVP_MD_CTX *mdctx = NULL; 480d4afb5ceSopenharmony_ci 481d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 482d4afb5ceSopenharmony_ci return -1; 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci if (!md) 485d4afb5ceSopenharmony_ci return -1; 486d4afb5ceSopenharmony_ci 487d4afb5ceSopenharmony_ci mdctx = EVP_MD_CTX_create(); 488d4afb5ceSopenharmony_ci if (!mdctx) 489d4afb5ceSopenharmony_ci goto bail; 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci if (EVP_DigestSignInit(mdctx, NULL, md, NULL, 492d4afb5ceSopenharmony_ci EVP_PKEY_CTX_get0_pkey(ctx->ctx))) { 493d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_DigestSignInit failed\n", __func__); 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ci goto bail; 496d4afb5ceSopenharmony_ci } 497d4afb5ceSopenharmony_ci if (EVP_DigestSignUpdate(mdctx, in, EVP_MD_size(md))) { 498d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_DigestSignUpdate failed\n", __func__); 499d4afb5ceSopenharmony_ci 500d4afb5ceSopenharmony_ci goto bail; 501d4afb5ceSopenharmony_ci } 502d4afb5ceSopenharmony_ci if (EVP_DigestSignFinal(mdctx, sig, &sig_len)) { 503d4afb5ceSopenharmony_ci lwsl_err("%s: EVP_DigestSignFinal failed\n", __func__); 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci goto bail; 506d4afb5ceSopenharmony_ci } 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci EVP_MD_CTX_free(mdctx); 509d4afb5ceSopenharmony_ci 510d4afb5ceSopenharmony_ci return (int)sig_len; 511d4afb5ceSopenharmony_cibail: 512d4afb5ceSopenharmony_ci if (mdctx) 513d4afb5ceSopenharmony_ci EVP_MD_CTX_free(mdctx); 514d4afb5ceSopenharmony_ci 515d4afb5ceSopenharmony_ci return -1; 516d4afb5ceSopenharmony_ci} 517d4afb5ceSopenharmony_ci#endif 518d4afb5ceSopenharmony_ci 519d4afb5ceSopenharmony_ciint 520d4afb5ceSopenharmony_cilws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, 521d4afb5ceSopenharmony_ci enum lws_genhash_types hash_type, int keybits, 522d4afb5ceSopenharmony_ci uint8_t *sig, size_t sig_len) 523d4afb5ceSopenharmony_ci{ 524d4afb5ceSopenharmony_ci int ret = -1, n, keybytes = lws_gencrypto_bits_to_bytes(keybits); 525d4afb5ceSopenharmony_ci size_t hs = lws_genhash_size(hash_type); 526d4afb5ceSopenharmony_ci const BIGNUM *r = NULL, *s = NULL; 527d4afb5ceSopenharmony_ci ECDSA_SIG *ecdsasig; 528d4afb5ceSopenharmony_ci EC_KEY *eckey; 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) { 531d4afb5ceSopenharmony_ci lwsl_notice("%s: ctx alg %d\n", __func__, ctx->genec_alg); 532d4afb5ceSopenharmony_ci return -1; 533d4afb5ceSopenharmony_ci } 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci if (!ctx->has_private) 536d4afb5ceSopenharmony_ci return -1; 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci if ((int)sig_len != (int)(keybytes * 2)) { 539d4afb5ceSopenharmony_ci lwsl_notice("%s: sig buff %d < %d\n", __func__, 540d4afb5ceSopenharmony_ci (int)sig_len, (int)(hs * 2)); 541d4afb5ceSopenharmony_ci return -1; 542d4afb5ceSopenharmony_ci } 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0])); 545d4afb5ceSopenharmony_ci 546d4afb5ceSopenharmony_ci /* 547d4afb5ceSopenharmony_ci * The ECDSA P-256 SHA-256 digital signature is generated as follows: 548d4afb5ceSopenharmony_ci * 549d4afb5ceSopenharmony_ci * 1. Generate a digital signature of the JWS Signing Input using ECDSA 550d4afb5ceSopenharmony_ci * P-256 SHA-256 with the desired private key. The output will be 551d4afb5ceSopenharmony_ci * the pair (R, S), where R and S are 256-bit unsigned integers. 552d4afb5ceSopenharmony_ci * 553d4afb5ceSopenharmony_ci * 2. Turn R and S into octet sequences in big-endian order, with each 554d4afb5ceSopenharmony_ci * array being be 32 octets long. The octet sequence 555d4afb5ceSopenharmony_ci * representations MUST NOT be shortened to omit any leading zero 556d4afb5ceSopenharmony_ci * octets contained in the values. 557d4afb5ceSopenharmony_ci * 558d4afb5ceSopenharmony_ci * 3. Concatenate the two octet sequences in the order R and then S. 559d4afb5ceSopenharmony_ci * (Note that many ECDSA implementations will directly produce this 560d4afb5ceSopenharmony_ci * concatenation as their output.) 561d4afb5ceSopenharmony_ci * 562d4afb5ceSopenharmony_ci * 4. The resulting 64-octet sequence is the JWS Signature value. 563d4afb5ceSopenharmony_ci */ 564d4afb5ceSopenharmony_ci 565d4afb5ceSopenharmony_ci ecdsasig = ECDSA_do_sign(in, (int)hs, eckey); 566d4afb5ceSopenharmony_ci EC_KEY_free(eckey); 567d4afb5ceSopenharmony_ci if (!ecdsasig) { 568d4afb5ceSopenharmony_ci lwsl_notice("%s: ECDSA_do_sign fail\n", __func__); 569d4afb5ceSopenharmony_ci goto bail; 570d4afb5ceSopenharmony_ci } 571d4afb5ceSopenharmony_ci 572d4afb5ceSopenharmony_ci ECDSA_SIG_get0(ecdsasig, &r, &s); 573d4afb5ceSopenharmony_ci 574d4afb5ceSopenharmony_ci /* 575d4afb5ceSopenharmony_ci * in the 521-bit case, we have to pad the last byte as it only 576d4afb5ceSopenharmony_ci * generates 65 bytes 577d4afb5ceSopenharmony_ci */ 578d4afb5ceSopenharmony_ci 579d4afb5ceSopenharmony_ci n = BN_bn2binpad(r, sig, keybytes); 580d4afb5ceSopenharmony_ci if (n != keybytes) { 581d4afb5ceSopenharmony_ci lwsl_notice("%s: bignum r fail %d %d\n", __func__, n, keybytes); 582d4afb5ceSopenharmony_ci goto bail; 583d4afb5ceSopenharmony_ci } 584d4afb5ceSopenharmony_ci 585d4afb5ceSopenharmony_ci n = BN_bn2binpad(s, sig + keybytes, keybytes); 586d4afb5ceSopenharmony_ci if (n != keybytes) { 587d4afb5ceSopenharmony_ci lwsl_notice("%s: bignum s fail %d %d\n", __func__, n, keybytes); 588d4afb5ceSopenharmony_ci goto bail; 589d4afb5ceSopenharmony_ci } 590d4afb5ceSopenharmony_ci 591d4afb5ceSopenharmony_ci ret = 0; 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_cibail: 594d4afb5ceSopenharmony_ci if (ecdsasig) 595d4afb5ceSopenharmony_ci ECDSA_SIG_free(ecdsasig); 596d4afb5ceSopenharmony_ci 597d4afb5ceSopenharmony_ci return ret; 598d4afb5ceSopenharmony_ci} 599d4afb5ceSopenharmony_ci 600d4afb5ceSopenharmony_ci/* in is the JWS Signing Input hash */ 601d4afb5ceSopenharmony_ci 602d4afb5ceSopenharmony_ciint 603d4afb5ceSopenharmony_cilws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, 604d4afb5ceSopenharmony_ci enum lws_genhash_types hash_type, int keybits, 605d4afb5ceSopenharmony_ci const uint8_t *sig, size_t sig_len) 606d4afb5ceSopenharmony_ci{ 607d4afb5ceSopenharmony_ci int ret = -1, n, hlen = (int)lws_genhash_size(hash_type), 608d4afb5ceSopenharmony_ci keybytes = lws_gencrypto_bits_to_bytes(keybits); 609d4afb5ceSopenharmony_ci ECDSA_SIG *ecsig = ECDSA_SIG_new(); 610d4afb5ceSopenharmony_ci BIGNUM *r = NULL, *s = NULL; 611d4afb5ceSopenharmony_ci EC_KEY *eckey; 612d4afb5ceSopenharmony_ci 613d4afb5ceSopenharmony_ci if (!ecsig) 614d4afb5ceSopenharmony_ci return -1; 615d4afb5ceSopenharmony_ci 616d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 617d4afb5ceSopenharmony_ci goto bail; 618d4afb5ceSopenharmony_ci 619d4afb5ceSopenharmony_ci if ((int)sig_len != keybytes * 2) { 620d4afb5ceSopenharmony_ci lwsl_err("%s: sig buf size %d vs %d\n", __func__, 621d4afb5ceSopenharmony_ci (int)sig_len, keybytes * 2); 622d4afb5ceSopenharmony_ci goto bail; 623d4afb5ceSopenharmony_ci } 624d4afb5ceSopenharmony_ci /* 625d4afb5ceSopenharmony_ci * 1. The JWS Signature value MUST be a 64-octet sequence. If it is 626d4afb5ceSopenharmony_ci * not a 64-octet sequence, the validation has failed. 627d4afb5ceSopenharmony_ci * 628d4afb5ceSopenharmony_ci * 2. Split the 64-octet sequence into two 32-octet sequences. The 629d4afb5ceSopenharmony_ci * first octet sequence represents R and the second S. The values R 630d4afb5ceSopenharmony_ci * and S are represented as octet sequences using the Integer-to- 631d4afb5ceSopenharmony_ci * OctetString Conversion defined in Section 2.3.7 of SEC1 [SEC1] 632d4afb5ceSopenharmony_ci * (in big-endian octet order). 633d4afb5ceSopenharmony_ci * 634d4afb5ceSopenharmony_ci * 3. Submit the JWS Signing Input, R, S, and the public key (x, y) to 635d4afb5ceSopenharmony_ci * the ECDSA P-256 SHA-256 validator. 636d4afb5ceSopenharmony_ci */ 637d4afb5ceSopenharmony_ci 638d4afb5ceSopenharmony_ci r = BN_bin2bn(sig, keybytes, NULL); 639d4afb5ceSopenharmony_ci if (!r) { 640d4afb5ceSopenharmony_ci lwsl_err("%s: BN_bin2bn (r) fail\n", __func__); 641d4afb5ceSopenharmony_ci goto bail; 642d4afb5ceSopenharmony_ci } 643d4afb5ceSopenharmony_ci 644d4afb5ceSopenharmony_ci s = BN_bin2bn(sig + keybytes, keybytes, NULL); 645d4afb5ceSopenharmony_ci if (!s) { 646d4afb5ceSopenharmony_ci lwsl_err("%s: BN_bin2bn (s) fail\n", __func__); 647d4afb5ceSopenharmony_ci goto bail1; 648d4afb5ceSopenharmony_ci } 649d4afb5ceSopenharmony_ci 650d4afb5ceSopenharmony_ci if (ECDSA_SIG_set0(ecsig, r, s) != 1) { 651d4afb5ceSopenharmony_ci lwsl_err("%s: ECDSA_SIG_set0 fail\n", __func__); 652d4afb5ceSopenharmony_ci goto bail1; 653d4afb5ceSopenharmony_ci } 654d4afb5ceSopenharmony_ci 655d4afb5ceSopenharmony_ci eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0])); 656d4afb5ceSopenharmony_ci 657d4afb5ceSopenharmony_ci n = ECDSA_do_verify(in, hlen, ecsig, eckey); 658d4afb5ceSopenharmony_ci EC_KEY_free(eckey); 659d4afb5ceSopenharmony_ci if (n != 1) { 660d4afb5ceSopenharmony_ci lwsl_err("%s: ECDSA_do_verify fail, hlen %d\n", __func__, (int)hlen); 661d4afb5ceSopenharmony_ci lws_tls_err_describe_clear(); 662d4afb5ceSopenharmony_ci goto bail; 663d4afb5ceSopenharmony_ci } 664d4afb5ceSopenharmony_ci 665d4afb5ceSopenharmony_ci ret = 0; 666d4afb5ceSopenharmony_ci goto bail; 667d4afb5ceSopenharmony_ci 668d4afb5ceSopenharmony_cibail1: 669d4afb5ceSopenharmony_ci if (r) 670d4afb5ceSopenharmony_ci BN_free(r); 671d4afb5ceSopenharmony_ci if (s) 672d4afb5ceSopenharmony_ci BN_free(s); 673d4afb5ceSopenharmony_ci 674d4afb5ceSopenharmony_cibail: 675d4afb5ceSopenharmony_ci ECDSA_SIG_free(ecsig); 676d4afb5ceSopenharmony_ci 677d4afb5ceSopenharmony_ci return ret; 678d4afb5ceSopenharmony_ci} 679d4afb5ceSopenharmony_ci 680d4afb5ceSopenharmony_ciint 681d4afb5ceSopenharmony_cilws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss, 682d4afb5ceSopenharmony_ci int *ss_len) 683d4afb5ceSopenharmony_ci{ 684d4afb5ceSopenharmony_ci int len, ret = -1; 685d4afb5ceSopenharmony_ci EC_KEY *eckey[2]; 686d4afb5ceSopenharmony_ci 687d4afb5ceSopenharmony_ci if (!ctx->ctx[LDHS_OURS] || !ctx->ctx[LDHS_THEIRS]) { 688d4afb5ceSopenharmony_ci lwsl_err("%s: both sides must be set up\n", __func__); 689d4afb5ceSopenharmony_ci 690d4afb5ceSopenharmony_ci return -1; 691d4afb5ceSopenharmony_ci } 692d4afb5ceSopenharmony_ci 693d4afb5ceSopenharmony_ci eckey[LDHS_OURS] = EVP_PKEY_get1_EC_KEY( 694d4afb5ceSopenharmony_ci EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_OURS])); 695d4afb5ceSopenharmony_ci eckey[LDHS_THEIRS] = EVP_PKEY_get1_EC_KEY( 696d4afb5ceSopenharmony_ci EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_THEIRS])); 697d4afb5ceSopenharmony_ci 698d4afb5ceSopenharmony_ci len = (EC_GROUP_get_degree(EC_KEY_get0_group(eckey[LDHS_OURS])) + 7) / 8; 699d4afb5ceSopenharmony_ci if (len <= *ss_len) { 700d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 701d4afb5ceSopenharmony_ci *ss_len = wolfSSL_ECDH_compute_key( 702d4afb5ceSopenharmony_ci#else 703d4afb5ceSopenharmony_ci *ss_len = ECDH_compute_key( 704d4afb5ceSopenharmony_ci#endif 705d4afb5ceSopenharmony_ci ss, (unsigned int)len, 706d4afb5ceSopenharmony_ci EC_KEY_get0_public_key(eckey[LDHS_THEIRS]), 707d4afb5ceSopenharmony_ci eckey[LDHS_OURS], NULL); 708d4afb5ceSopenharmony_ci ret = -(*ss_len < 0); 709d4afb5ceSopenharmony_ci } 710d4afb5ceSopenharmony_ci 711d4afb5ceSopenharmony_ci EC_KEY_free(eckey[LDHS_OURS]); 712d4afb5ceSopenharmony_ci EC_KEY_free(eckey[LDHS_THEIRS]); 713d4afb5ceSopenharmony_ci 714d4afb5ceSopenharmony_ci return ret; 715d4afb5ceSopenharmony_ci} 716