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