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-mbedtls.h" 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 31d4afb5ceSopenharmony_ci#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->MBEDTLS_PRIVATE(ctx).\ 32d4afb5ceSopenharmony_ci MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(_ins) 33d4afb5ceSopenharmony_ci#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->MBEDTLS_PRIVATE(_ins) 34d4afb5ceSopenharmony_ci#else 35d4afb5ceSopenharmony_ci#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->_ins 36d4afb5ceSopenharmony_ci#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->_ins 37d4afb5ceSopenharmony_ci#endif 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ciconst struct lws_ec_curves lws_ec_curves[] = { 40d4afb5ceSopenharmony_ci /* 41d4afb5ceSopenharmony_ci * These are the curves we are willing to use by default... 42d4afb5ceSopenharmony_ci * 43d4afb5ceSopenharmony_ci * The 3 recommended+ (P-256) and optional curves in RFC7518 7.6 44d4afb5ceSopenharmony_ci * 45d4afb5ceSopenharmony_ci * Specific keys lengths from RFC8422 p20 46d4afb5ceSopenharmony_ci */ 47d4afb5ceSopenharmony_ci { "P-256", MBEDTLS_ECP_DP_SECP256R1, 32 }, 48d4afb5ceSopenharmony_ci { "P-384", MBEDTLS_ECP_DP_SECP384R1, 48 }, 49d4afb5ceSopenharmony_ci { "P-521", MBEDTLS_ECP_DP_SECP521R1, 66 }, 50d4afb5ceSopenharmony_ci 51d4afb5ceSopenharmony_ci { NULL, 0, 0 } 52d4afb5ceSopenharmony_ci}; 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_cistatic int 55d4afb5ceSopenharmony_cilws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, 56d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *el) 57d4afb5ceSopenharmony_ci{ 58d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve; 59d4afb5ceSopenharmony_ci mbedtls_ecp_keypair kp; 60d4afb5ceSopenharmony_ci int ret = -1; 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci if (el[LWS_GENCRYPTO_EC_KEYEL_CRV].len < 4) { 63d4afb5ceSopenharmony_ci lwsl_notice("%s: crv '%s' (%d)\n", __func__, 64d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf ? 65d4afb5ceSopenharmony_ci (char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf : 66d4afb5ceSopenharmony_ci "null", 67d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].len); 68d4afb5ceSopenharmony_ci return -21; 69d4afb5ceSopenharmony_ci } 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci curve = lws_genec_curve(ctx->curve_table, 72d4afb5ceSopenharmony_ci (char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf); 73d4afb5ceSopenharmony_ci if (!curve) 74d4afb5ceSopenharmony_ci return -22; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci /* 77d4afb5ceSopenharmony_ci * d (the private part) may be missing, otherwise it and everything 78d4afb5ceSopenharmony_ci * else must match the expected bignum size 79d4afb5ceSopenharmony_ci */ 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci if ((el[LWS_GENCRYPTO_EC_KEYEL_D].len && 82d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_D].len != curve->key_bytes) || 83d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_X].len != curve->key_bytes || 84d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_Y].len != curve->key_bytes) 85d4afb5ceSopenharmony_ci return -23; 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci mbedtls_ecp_keypair_init(&kp); 88d4afb5ceSopenharmony_ci if (mbedtls_ecp_group_load(&kp.MBEDTLS_PRIVATE(grp), 89d4afb5ceSopenharmony_ci (mbedtls_ecp_group_id)curve->tls_lib_nid)) 90d4afb5ceSopenharmony_ci goto bail1; 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ci ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len; 93d4afb5ceSopenharmony_ci 94d4afb5ceSopenharmony_ci /* d (the private key) is directly an mpi */ 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci if (ctx->has_private && 97d4afb5ceSopenharmony_ci mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(d), 98d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_D].buf, 99d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_D].len)) 100d4afb5ceSopenharmony_ci goto bail1; 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci mbedtls_ecp_set_zero(&kp.MBEDTLS_PRIVATE(Q)); 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 105d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_X].buf, 106d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_X].len)) 107d4afb5ceSopenharmony_ci goto bail1; 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 110d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_Y].buf, 111d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_Y].len)) 112d4afb5ceSopenharmony_ci goto bail1; 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci mbedtls_mpi_lset(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1); 115d4afb5ceSopenharmony_ci 116d4afb5ceSopenharmony_ci switch (ctx->genec_alg) { 117d4afb5ceSopenharmony_ci case LEGENEC_ECDH: 118d4afb5ceSopenharmony_ci if (mbedtls_ecdh_get_params(ctx->u.ctx_ecdh, &kp, 119d4afb5ceSopenharmony_ci (mbedtls_ecdh_side)side)) 120d4afb5ceSopenharmony_ci goto bail1; 121d4afb5ceSopenharmony_ci /* verify the key is consistent with the claimed curve */ 122d4afb5ceSopenharmony_ci if (ctx->has_private && 123d4afb5ceSopenharmony_ci mbedtls_ecp_check_privkey(&ECDHCTX(ctx, grp), 124d4afb5ceSopenharmony_ci &ECDHCTX(ctx, d))) 125d4afb5ceSopenharmony_ci goto bail1; 126d4afb5ceSopenharmony_ci if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), 127d4afb5ceSopenharmony_ci &ECDHCTX(ctx, Q))) 128d4afb5ceSopenharmony_ci goto bail1; 129d4afb5ceSopenharmony_ci break; 130d4afb5ceSopenharmony_ci case LEGENEC_ECDSA: 131d4afb5ceSopenharmony_ci if (mbedtls_ecdsa_from_keypair(ctx->u.ctx_ecdsa, &kp)) 132d4afb5ceSopenharmony_ci goto bail1; 133d4afb5ceSopenharmony_ci /* verify the key is consistent with the claimed curve */ 134d4afb5ceSopenharmony_ci if (ctx->has_private && 135d4afb5ceSopenharmony_ci mbedtls_ecp_check_privkey(&ECDSACTX(ctx, grp), 136d4afb5ceSopenharmony_ci &ECDSACTX(ctx, d))) 137d4afb5ceSopenharmony_ci goto bail1; 138d4afb5ceSopenharmony_ci if (mbedtls_ecp_check_pubkey(&ECDSACTX(ctx, grp), 139d4afb5ceSopenharmony_ci &ECDSACTX(ctx, Q))) 140d4afb5ceSopenharmony_ci goto bail1; 141d4afb5ceSopenharmony_ci break; 142d4afb5ceSopenharmony_ci default: 143d4afb5ceSopenharmony_ci goto bail1; 144d4afb5ceSopenharmony_ci } 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci ret = 0; 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_cibail1: 149d4afb5ceSopenharmony_ci mbedtls_ecp_keypair_free(&kp); 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci return ret; 152d4afb5ceSopenharmony_ci} 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ciint 155d4afb5ceSopenharmony_cilws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context, 156d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve_table) 157d4afb5ceSopenharmony_ci{ 158d4afb5ceSopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci ctx->context = context; 161d4afb5ceSopenharmony_ci ctx->curve_table = curve_table; 162d4afb5ceSopenharmony_ci ctx->genec_alg = LEGENEC_ECDH; 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci ctx->u.ctx_ecdh = lws_zalloc(sizeof(*ctx->u.ctx_ecdh), "genecdh"); 165d4afb5ceSopenharmony_ci if (!ctx->u.ctx_ecdh) 166d4afb5ceSopenharmony_ci return 1; 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci mbedtls_ecdh_init(ctx->u.ctx_ecdh); 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci return 0; 171d4afb5ceSopenharmony_ci} 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ciint 174d4afb5ceSopenharmony_cilws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context, 175d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve_table) 176d4afb5ceSopenharmony_ci{ 177d4afb5ceSopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci ctx->context = context; 180d4afb5ceSopenharmony_ci ctx->curve_table = curve_table; 181d4afb5ceSopenharmony_ci ctx->genec_alg = LEGENEC_ECDSA; 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci ctx->u.ctx_ecdsa = lws_zalloc(sizeof(*ctx->u.ctx_ecdsa), "genecdsa"); 184d4afb5ceSopenharmony_ci if (!ctx->u.ctx_ecdsa) 185d4afb5ceSopenharmony_ci return 1; 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci mbedtls_ecdsa_init(ctx->u.ctx_ecdsa); 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci return 0; 190d4afb5ceSopenharmony_ci} 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ciint 194d4afb5ceSopenharmony_cilws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el, 195d4afb5ceSopenharmony_ci enum enum_lws_dh_side side) 196d4afb5ceSopenharmony_ci{ 197d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDH) 198d4afb5ceSopenharmony_ci return -1; 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci return lws_genec_keypair_import(ctx, side, el); 201d4afb5ceSopenharmony_ci} 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ciint 204d4afb5ceSopenharmony_cilws_genecdsa_set_key(struct lws_genec_ctx *ctx, 205d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *el) 206d4afb5ceSopenharmony_ci{ 207d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 208d4afb5ceSopenharmony_ci return -1; 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci return lws_genec_keypair_import(ctx, 0, el); 211d4afb5ceSopenharmony_ci} 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_civoid 214d4afb5ceSopenharmony_cilws_genec_destroy(struct lws_genec_ctx *ctx) 215d4afb5ceSopenharmony_ci{ 216d4afb5ceSopenharmony_ci switch (ctx->genec_alg) { 217d4afb5ceSopenharmony_ci case LEGENEC_ECDH: 218d4afb5ceSopenharmony_ci if (ctx->u.ctx_ecdh) { 219d4afb5ceSopenharmony_ci mbedtls_ecdh_free(ctx->u.ctx_ecdh); 220d4afb5ceSopenharmony_ci lws_free(ctx->u.ctx_ecdh); 221d4afb5ceSopenharmony_ci ctx->u.ctx_ecdh = NULL; 222d4afb5ceSopenharmony_ci } 223d4afb5ceSopenharmony_ci break; 224d4afb5ceSopenharmony_ci case LEGENEC_ECDSA: 225d4afb5ceSopenharmony_ci if (ctx->u.ctx_ecdsa) { 226d4afb5ceSopenharmony_ci mbedtls_ecdsa_free(ctx->u.ctx_ecdsa); 227d4afb5ceSopenharmony_ci lws_free(ctx->u.ctx_ecdsa); 228d4afb5ceSopenharmony_ci ctx->u.ctx_ecdsa = NULL; 229d4afb5ceSopenharmony_ci } 230d4afb5ceSopenharmony_ci break; 231d4afb5ceSopenharmony_ci default: 232d4afb5ceSopenharmony_ci break; 233d4afb5ceSopenharmony_ci } 234d4afb5ceSopenharmony_ci} 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ciint 237d4afb5ceSopenharmony_cilws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, 238d4afb5ceSopenharmony_ci const char *curve_name, 239d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *el) 240d4afb5ceSopenharmony_ci{ 241d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve; 242d4afb5ceSopenharmony_ci mbedtls_ecdsa_context ecdsa; 243d4afb5ceSopenharmony_ci mbedtls_ecp_keypair *kp; 244d4afb5ceSopenharmony_ci mbedtls_mpi *mpi[3]; 245d4afb5ceSopenharmony_ci int n; 246d4afb5ceSopenharmony_ci 247d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDH) 248d4afb5ceSopenharmony_ci return -1; 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci curve = lws_genec_curve(ctx->curve_table, curve_name); 251d4afb5ceSopenharmony_ci if (!curve) { 252d4afb5ceSopenharmony_ci lwsl_err("%s: curve '%s' not supported\n", 253d4afb5ceSopenharmony_ci __func__, curve_name); 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci return -22; 256d4afb5ceSopenharmony_ci } 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci mbedtls_ecdsa_init(&ecdsa); 259d4afb5ceSopenharmony_ci n = mbedtls_ecdsa_genkey(&ecdsa, (mbedtls_ecp_group_id)curve->tls_lib_nid, 260d4afb5ceSopenharmony_ci lws_gencrypto_mbedtls_rngf, 261d4afb5ceSopenharmony_ci ctx->context); 262d4afb5ceSopenharmony_ci if (n) { 263d4afb5ceSopenharmony_ci lwsl_err("mbedtls_ecdsa_genkey failed 0x%x\n", -n); 264d4afb5ceSopenharmony_ci goto bail1; 265d4afb5ceSopenharmony_ci } 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci kp = (mbedtls_ecp_keypair *)&ecdsa; 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci n = mbedtls_ecdh_get_params(ctx->u.ctx_ecdh, kp, 270d4afb5ceSopenharmony_ci (mbedtls_ecdh_side)side); 271d4afb5ceSopenharmony_ci if (n) { 272d4afb5ceSopenharmony_ci lwsl_err("mbedtls_ecdh_get_params failed 0x%x\n", -n); 273d4afb5ceSopenharmony_ci goto bail1; 274d4afb5ceSopenharmony_ci } 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci /* 277d4afb5ceSopenharmony_ci * we need to capture the individual element BIGNUMs into 278d4afb5ceSopenharmony_ci * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc 279d4afb5ceSopenharmony_ci */ 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); 282d4afb5ceSopenharmony_ci mpi[1] = &kp->MBEDTLS_PRIVATE(d); 283d4afb5ceSopenharmony_ci mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1; 286d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf = 287d4afb5ceSopenharmony_ci lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec"); 288d4afb5ceSopenharmony_ci if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf) 289d4afb5ceSopenharmony_ci goto bail1; 290d4afb5ceSopenharmony_ci strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name); 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; 293d4afb5ceSopenharmony_ci n++) { 294d4afb5ceSopenharmony_ci el[n].len = curve->key_bytes; 295d4afb5ceSopenharmony_ci el[n].buf = lws_malloc(curve->key_bytes, "ec"); 296d4afb5ceSopenharmony_ci if (!el[n].buf) 297d4afb5ceSopenharmony_ci goto bail2; 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_binary(mpi[n - 1], el[n].buf, 300d4afb5ceSopenharmony_ci curve->key_bytes)) 301d4afb5ceSopenharmony_ci goto bail2; 302d4afb5ceSopenharmony_ci } 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci mbedtls_ecdsa_free(&ecdsa); 305d4afb5ceSopenharmony_ci 306d4afb5ceSopenharmony_ci return 0; 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_cibail2: 309d4afb5ceSopenharmony_ci for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++) 310d4afb5ceSopenharmony_ci if (el[n].buf) 311d4afb5ceSopenharmony_ci lws_free_set_NULL(el[n].buf); 312d4afb5ceSopenharmony_cibail1: 313d4afb5ceSopenharmony_ci mbedtls_ecdsa_free(&ecdsa); 314d4afb5ceSopenharmony_ci 315d4afb5ceSopenharmony_ci lws_free_set_NULL(ctx->u.ctx_ecdh); 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci return -1; 318d4afb5ceSopenharmony_ci} 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ciint 321d4afb5ceSopenharmony_cilws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name, 322d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *el) 323d4afb5ceSopenharmony_ci{ 324d4afb5ceSopenharmony_ci const struct lws_ec_curves *curve; 325d4afb5ceSopenharmony_ci mbedtls_ecp_keypair *kp; 326d4afb5ceSopenharmony_ci mbedtls_mpi *mpi[3]; 327d4afb5ceSopenharmony_ci int n; 328d4afb5ceSopenharmony_ci 329d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 330d4afb5ceSopenharmony_ci return -1; 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci curve = lws_genec_curve(ctx->curve_table, curve_name); 333d4afb5ceSopenharmony_ci if (!curve) { 334d4afb5ceSopenharmony_ci lwsl_err("%s: curve '%s' not supported\n", 335d4afb5ceSopenharmony_ci __func__, curve_name); 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci return -22; 338d4afb5ceSopenharmony_ci } 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci //mbedtls_ecdsa_init(ctx->u.ctx_ecdsa); 341d4afb5ceSopenharmony_ci n = mbedtls_ecdsa_genkey(ctx->u.ctx_ecdsa, (mbedtls_ecp_group_id)curve->tls_lib_nid, 342d4afb5ceSopenharmony_ci lws_gencrypto_mbedtls_rngf, ctx->context); 343d4afb5ceSopenharmony_ci if (n) { 344d4afb5ceSopenharmony_ci lwsl_err("mbedtls_ecdsa_genkey failed 0x%x\n", -n); 345d4afb5ceSopenharmony_ci goto bail1; 346d4afb5ceSopenharmony_ci } 347d4afb5ceSopenharmony_ci 348d4afb5ceSopenharmony_ci /* 349d4afb5ceSopenharmony_ci * we need to capture the individual element BIGNUMs into 350d4afb5ceSopenharmony_ci * lws_gencrypto_keyelems, so they can be serialized, used in jwk etc 351d4afb5ceSopenharmony_ci */ 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci kp = (mbedtls_ecp_keypair *)ctx->u.ctx_ecdsa; 354d4afb5ceSopenharmony_ci 355d4afb5ceSopenharmony_ci mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); 356d4afb5ceSopenharmony_ci mpi[1] = &kp->MBEDTLS_PRIVATE(d); 357d4afb5ceSopenharmony_ci mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1; 360d4afb5ceSopenharmony_ci el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf = 361d4afb5ceSopenharmony_ci lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec"); 362d4afb5ceSopenharmony_ci if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf) 363d4afb5ceSopenharmony_ci goto bail1; 364d4afb5ceSopenharmony_ci strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name); 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; 367d4afb5ceSopenharmony_ci n++) { 368d4afb5ceSopenharmony_ci el[n].len = curve->key_bytes; 369d4afb5ceSopenharmony_ci el[n].buf = lws_malloc(curve->key_bytes, "ec"); 370d4afb5ceSopenharmony_ci if (!el[n].buf) 371d4afb5ceSopenharmony_ci goto bail2; 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_binary(mpi[n - 1], el[n].buf, el[n].len)) { 375d4afb5ceSopenharmony_ci lwsl_err("%s: mbedtls_mpi_write_binary failed\n", __func__); 376d4afb5ceSopenharmony_ci goto bail2; 377d4afb5ceSopenharmony_ci } 378d4afb5ceSopenharmony_ci } 379d4afb5ceSopenharmony_ci 380d4afb5ceSopenharmony_ci return 0; 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_cibail2: 383d4afb5ceSopenharmony_ci for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++) 384d4afb5ceSopenharmony_ci if (el[n].buf) 385d4afb5ceSopenharmony_ci lws_free_set_NULL(el[n].buf); 386d4afb5ceSopenharmony_cibail1: 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ci lws_free_set_NULL(ctx->u.ctx_ecdsa); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci return -1; 391d4afb5ceSopenharmony_ci} 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ciint 394d4afb5ceSopenharmony_cilws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, 395d4afb5ceSopenharmony_ci enum lws_genhash_types hash_type, int keybits, 396d4afb5ceSopenharmony_ci uint8_t *sig, size_t sig_len) 397d4afb5ceSopenharmony_ci{ 398d4afb5ceSopenharmony_ci int n, keybytes = lws_gencrypto_bits_to_bytes(keybits); 399d4afb5ceSopenharmony_ci size_t hlen = lws_genhash_size(hash_type); 400d4afb5ceSopenharmony_ci mbedtls_mpi mpi_r, mpi_s; 401d4afb5ceSopenharmony_ci size_t slen = sig_len; 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 404d4afb5ceSopenharmony_ci return -1; 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci /* 407d4afb5ceSopenharmony_ci * The ECDSA P-256 SHA-256 digital signature is generated as follows: 408d4afb5ceSopenharmony_ci * 409d4afb5ceSopenharmony_ci * 1. Generate a digital signature of the JWS Signing Input using ECDSA 410d4afb5ceSopenharmony_ci * P-256 SHA-256 with the desired private key. The output will be 411d4afb5ceSopenharmony_ci * the pair (R, S), where R and S are 256-bit unsigned integers. 412d4afb5ceSopenharmony_ci * 413d4afb5ceSopenharmony_ci * 2. Turn R and S into octet sequences in big-endian order, with each 414d4afb5ceSopenharmony_ci * array being be 32 octets long. The octet sequence 415d4afb5ceSopenharmony_ci * representations MUST NOT be shortened to omit any leading zero 416d4afb5ceSopenharmony_ci * octets contained in the values. 417d4afb5ceSopenharmony_ci * 418d4afb5ceSopenharmony_ci * 3. Concatenate the two octet sequences in the order R and then S. 419d4afb5ceSopenharmony_ci * (Note that many ECDSA implementations will directly produce this 420d4afb5ceSopenharmony_ci * concatenation as their output.) 421d4afb5ceSopenharmony_ci * 422d4afb5ceSopenharmony_ci * 4. The resulting 64-octet sequence is the JWS Signature value. 423d4afb5ceSopenharmony_ci */ 424d4afb5ceSopenharmony_ci 425d4afb5ceSopenharmony_ci mbedtls_mpi_init(&mpi_r); 426d4afb5ceSopenharmony_ci mbedtls_mpi_init(&mpi_s); 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci n = mbedtls_ecdsa_sign(&ECDSACTX(ctx, grp), &mpi_r, &mpi_s, 429d4afb5ceSopenharmony_ci &ECDSACTX(ctx, d), in, hlen, 430d4afb5ceSopenharmony_ci lws_gencrypto_mbedtls_rngf, ctx->context); 431d4afb5ceSopenharmony_ci if (n) { 432d4afb5ceSopenharmony_ci lwsl_err("%s: mbedtls_ecdsa_sign failed: -0x%x\n", 433d4afb5ceSopenharmony_ci __func__, -n); 434d4afb5ceSopenharmony_ci 435d4afb5ceSopenharmony_ci goto bail2; 436d4afb5ceSopenharmony_ci } 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_binary(&mpi_r, sig, (unsigned int)keybytes)) 439d4afb5ceSopenharmony_ci goto bail2; 440d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_r); 441d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_binary(&mpi_s, sig + keybytes, (unsigned int)keybytes)) 442d4afb5ceSopenharmony_ci goto bail1; 443d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_s); 444d4afb5ceSopenharmony_ci 445d4afb5ceSopenharmony_ci return (int)slen; 446d4afb5ceSopenharmony_ci 447d4afb5ceSopenharmony_cibail2: 448d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_r); 449d4afb5ceSopenharmony_cibail1: 450d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_s); 451d4afb5ceSopenharmony_ci 452d4afb5ceSopenharmony_ci return -3; 453d4afb5ceSopenharmony_ci} 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_ciint 456d4afb5ceSopenharmony_cilws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, 457d4afb5ceSopenharmony_ci enum lws_genhash_types hash_type, int keybits, 458d4afb5ceSopenharmony_ci const uint8_t *sig, size_t sig_len) 459d4afb5ceSopenharmony_ci{ 460d4afb5ceSopenharmony_ci int n, keybytes = lws_gencrypto_bits_to_bytes(keybits); 461d4afb5ceSopenharmony_ci size_t hlen = lws_genhash_size(hash_type); 462d4afb5ceSopenharmony_ci mbedtls_mpi mpi_r, mpi_s; 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ci if (ctx->genec_alg != LEGENEC_ECDSA) 465d4afb5ceSopenharmony_ci return -1; 466d4afb5ceSopenharmony_ci 467d4afb5ceSopenharmony_ci if ((int)sig_len != keybytes * 2) 468d4afb5ceSopenharmony_ci return -1; 469d4afb5ceSopenharmony_ci 470d4afb5ceSopenharmony_ci /* 471d4afb5ceSopenharmony_ci * 1. The JWS Signature value MUST be a 64-octet sequence. If it is 472d4afb5ceSopenharmony_ci * not a 64-octet sequence, the validation has failed. 473d4afb5ceSopenharmony_ci * 474d4afb5ceSopenharmony_ci * 2. Split the 64-octet sequence into two 32-octet sequences. The 475d4afb5ceSopenharmony_ci * first octet sequence represents R and the second S. The values R 476d4afb5ceSopenharmony_ci * and S are represented as octet sequences using the Integer-to- 477d4afb5ceSopenharmony_ci * OctetString Conversion defined in Section 2.3.7 of SEC1 [SEC1] 478d4afb5ceSopenharmony_ci * (in big-endian octet order). 479d4afb5ceSopenharmony_ci * 480d4afb5ceSopenharmony_ci * 3. Submit the JWS Signing Input, R, S, and the public key (x, y) to 481d4afb5ceSopenharmony_ci * the ECDSA P-256 SHA-256 validator. 482d4afb5ceSopenharmony_ci */ 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci mbedtls_mpi_init(&mpi_r); 485d4afb5ceSopenharmony_ci mbedtls_mpi_init(&mpi_s); 486d4afb5ceSopenharmony_ci 487d4afb5ceSopenharmony_ci if (mbedtls_mpi_read_binary(&mpi_r, sig, (unsigned int)keybytes)) 488d4afb5ceSopenharmony_ci return -1; 489d4afb5ceSopenharmony_ci if (mbedtls_mpi_read_binary(&mpi_s, sig + keybytes, (unsigned int)keybytes)) 490d4afb5ceSopenharmony_ci goto bail1; 491d4afb5ceSopenharmony_ci 492d4afb5ceSopenharmony_ci n = mbedtls_ecdsa_verify(&ECDSACTX(ctx, grp), in, hlen, 493d4afb5ceSopenharmony_ci &ECDSACTX(ctx, Q), &mpi_r, &mpi_s); 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_s); 496d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_r); 497d4afb5ceSopenharmony_ci 498d4afb5ceSopenharmony_ci if (n) { 499d4afb5ceSopenharmony_ci lwsl_err("%s: mbedtls_ecdsa_verify failed: -0x%x\n", 500d4afb5ceSopenharmony_ci __func__, -n); 501d4afb5ceSopenharmony_ci 502d4afb5ceSopenharmony_ci goto bail; 503d4afb5ceSopenharmony_ci } 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci return 0; 506d4afb5ceSopenharmony_cibail1: 507d4afb5ceSopenharmony_ci mbedtls_mpi_free(&mpi_r); 508d4afb5ceSopenharmony_ci 509d4afb5ceSopenharmony_cibail: 510d4afb5ceSopenharmony_ci 511d4afb5ceSopenharmony_ci return -3; 512d4afb5ceSopenharmony_ci} 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ciint 515d4afb5ceSopenharmony_cilws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss, 516d4afb5ceSopenharmony_ci int *ss_len) 517d4afb5ceSopenharmony_ci{ 518d4afb5ceSopenharmony_ci int n; 519d4afb5ceSopenharmony_ci size_t st; 520d4afb5ceSopenharmony_ci if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Q)) || 521d4afb5ceSopenharmony_ci mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Qp))) { 522d4afb5ceSopenharmony_ci lwsl_err("%s: both sides must be set up\n", __func__); 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci return -1; 525d4afb5ceSopenharmony_ci } 526d4afb5ceSopenharmony_ci 527d4afb5ceSopenharmony_ci n = mbedtls_ecdh_calc_secret(ctx->u.ctx_ecdh, &st, ss, (size_t)*ss_len, 528d4afb5ceSopenharmony_ci lws_gencrypto_mbedtls_rngf, ctx->context); 529d4afb5ceSopenharmony_ci if (n) 530d4afb5ceSopenharmony_ci return -1; 531d4afb5ceSopenharmony_ci 532d4afb5ceSopenharmony_ci *ss_len = (int)st; 533d4afb5ceSopenharmony_ci 534d4afb5ceSopenharmony_ci return 0; 535d4afb5ceSopenharmony_ci} 536