1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019 Huawei Technologies Co., Ltd 4 */ 5 6 #include <crypto/crypto.h> 7 #include <io.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <tee_api_types.h> 11 #include <tee/tee_cryp_utl.h> 12 #include <trace.h> 13 #include <util.h> 14 #include <utee_defines.h> 15 16 #include "acipher_helpers.h" 17 18 static TEE_Result 19 sm2_uncompressed_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, 20 const uint8_t *x1y1, size_t max_size, 21 size_t *consumed) 22 { 23 uint8_t *ptr = (uint8_t *)x1y1; 24 TEE_Result res = TEE_SUCCESS; 25 uint8_t one[] = { 1 }; 26 int ltc_res = 0; 27 void *x1 = NULL; 28 void *y1 = NULL; 29 30 if (max_size < (size_t)(2 * dp->size)) 31 return TEE_ERROR_BAD_PARAMETERS; 32 33 ltc_res = mp_init_multi(&x1, &y1, &p->z, NULL); 34 if (ltc_res != CRYPT_OK) 35 return TEE_ERROR_OUT_OF_MEMORY; 36 37 ltc_res = mp_read_unsigned_bin(x1, ptr, dp->size); 38 if (ltc_res != CRYPT_OK) { 39 res = TEE_ERROR_BAD_PARAMETERS; 40 goto err; 41 } 42 43 ptr += dp->size; 44 45 ltc_res = mp_read_unsigned_bin(y1, ptr, dp->size); 46 if (ltc_res != CRYPT_OK) { 47 res = TEE_ERROR_BAD_PARAMETERS; 48 goto err; 49 } 50 51 ltc_res = ltc_ecc_is_point(dp, x1, y1); 52 if (ltc_res != CRYPT_OK) { 53 res = TEE_ERROR_BAD_PARAMETERS; 54 goto err; 55 } 56 57 p->x = x1; 58 p->y = y1; 59 mp_read_unsigned_bin(p->z, one, sizeof(one)); 60 61 *consumed = 2 * dp->size + 1; /* PC */ 62 63 return TEE_SUCCESS; 64 err: 65 mp_clear_multi(x1, y1, p->z, NULL); 66 return res; 67 } 68 69 /* 70 * GM/T 0003.1‒2012 Part 1 Section 4.2.9 71 * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve 72 * defined by domain parameters @dp. 73 * Note: only the uncompressed form is supported. Uncompressed and hybrid forms 74 * are TBD. 75 */ 76 static TEE_Result sm2_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, 77 const uint8_t *buf, size_t max_size, 78 size_t *consumed) 79 { 80 uint8_t PC = 0; 81 82 if (!max_size) 83 return TEE_ERROR_BAD_PARAMETERS; 84 85 PC = buf[0]; 86 87 switch (PC) { 88 case 0x02: 89 case 0x03: 90 /* Compressed form */ 91 return TEE_ERROR_NOT_SUPPORTED; 92 case 0x04: 93 /* UNcompressed form */ 94 return sm2_uncompressed_bytes_to_point(p, dp, buf + 1, 95 max_size - 1, consumed); 96 case 0x06: 97 case 0x07: 98 /* Hybrid form */ 99 return TEE_ERROR_NOT_SUPPORTED; 100 default: 101 return TEE_ERROR_BAD_PARAMETERS; 102 } 103 104 return TEE_ERROR_GENERIC; 105 } 106 107 /* 108 * GM/T 0003.1‒2012 Part 4 Sections 5.4.2 and 5.4.3 109 * Key derivation function based on the SM3 hash function 110 */ 111 static TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, 112 size_t tlen) 113 { 114 TEE_Result res = TEE_SUCCESS; 115 size_t remain = tlen; 116 uint32_t count = 1; 117 uint32_t be_count = 0; 118 void *ctx = NULL; 119 uint8_t *out = t; 120 121 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 122 if (res) 123 return res; 124 125 while (remain) { 126 uint8_t tmp[TEE_SM3_HASH_SIZE] = { }; 127 uint8_t *buf = NULL; 128 129 if (remain >= TEE_SM3_HASH_SIZE) 130 buf = out; 131 else 132 buf = tmp; 133 134 put_be32(&be_count, count); 135 res = crypto_hash_init(ctx); 136 if (res) 137 goto out; 138 res = crypto_hash_update(ctx, Z, Z_len); 139 if (res) 140 goto out; 141 res = crypto_hash_update(ctx, (const uint8_t *)&be_count, 142 sizeof(be_count)); 143 if (res) 144 goto out; 145 res = crypto_hash_final(ctx, buf, TEE_SM3_HASH_SIZE); 146 if (res) 147 goto out; 148 149 if (remain < TEE_SM3_HASH_SIZE) { 150 memcpy(out, tmp, remain); 151 break; 152 } 153 154 out += TEE_SM3_HASH_SIZE; 155 remain -= TEE_SM3_HASH_SIZE; 156 count++; 157 } 158 out: 159 crypto_hash_free_ctx(ctx); 160 return res; 161 } 162 163 static bool is_zero(const uint8_t *buf, size_t size) 164 { 165 uint8_t v = 0; 166 size_t i = 0; 167 168 for (i = 0; i < size; i++) 169 v |= buf[i]; 170 171 return !v; 172 } 173 174 /* 175 * GM/T 0003.1‒2012 Part 4 Section 7.1 176 * Decryption algorithm 177 */ 178 TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, 179 const uint8_t *src, size_t src_len, 180 uint8_t *dst, size_t *dst_len) 181 { 182 TEE_Result res = TEE_SUCCESS; 183 uint8_t x2y2[64] = { }; 184 ecc_key ltc_key = { }; 185 ecc_point *C1 = NULL; 186 size_t C1_len = 0; 187 ecc_point *S = NULL; 188 ecc_point *x2y2p = NULL; 189 void *ctx = NULL; 190 int ltc_res = 0; 191 void *h = NULL; 192 int inf = 0; 193 uint8_t *t = NULL; 194 size_t C2_len = 0; 195 size_t i = 0; 196 size_t out_len = 0; 197 uint8_t *eom = NULL; 198 uint8_t u[TEE_SM3_HASH_SIZE] = { }; 199 200 /* 201 * Input buffer src is (C1 || C2 || C3) 202 * - C1 represents a point (should be on the curve) 203 * - C2 is the encrypted message 204 * - C3 is a SM3 hash 205 */ 206 207 res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE, 208 NULL); 209 if (res) 210 goto out; 211 212 /* Step B1: read and validate point C1 from encrypted message */ 213 214 C1 = ltc_ecc_new_point(); 215 if (!C1) { 216 res = TEE_ERROR_OUT_OF_MEMORY; 217 goto out; 218 } 219 220 res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len); 221 if (res) 222 goto out; 223 224 /* Step B2: S = [h]C1 */ 225 226 if (ltc_key.dp.cofactor != 1) { 227 S = ltc_ecc_new_point(); 228 if (!S) { 229 res = TEE_ERROR_OUT_OF_MEMORY; 230 goto out; 231 } 232 233 ltc_res = mp_init_multi(&h, NULL); 234 if (ltc_res != CRYPT_OK) 235 return TEE_ERROR_OUT_OF_MEMORY; 236 237 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 238 if (ltc_res != CRYPT_OK) { 239 res = TEE_ERROR_BAD_STATE; 240 goto out; 241 } 242 243 ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A, 244 ltc_key.dp.prime, 1); 245 if (ltc_res != CRYPT_OK) { 246 res = TEE_ERROR_BAD_STATE; 247 goto out; 248 } 249 250 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 251 &inf); 252 } else { 253 ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime, 254 &inf); 255 } 256 if (inf) { 257 res = TEE_ERROR_BAD_STATE; 258 goto out; 259 } 260 261 /* Step B3: (x2, y2) = [dB]C1 */ 262 263 x2y2p = ltc_ecc_new_point(); 264 if (!x2y2p) { 265 res = TEE_ERROR_OUT_OF_MEMORY; 266 goto out; 267 } 268 269 ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A, 270 ltc_key.dp.prime, 1); 271 if (ltc_res != CRYPT_OK) { 272 res = TEE_ERROR_BAD_STATE; 273 goto out; 274 } 275 276 if (mp_unsigned_bin_size(x2y2p->x) != 32 || 277 mp_unsigned_bin_size(x2y2p->y) != 32) { 278 res = TEE_ERROR_BAD_STATE; 279 goto out; 280 } 281 282 mp_to_unsigned_bin(x2y2p->x, x2y2); 283 mp_to_unsigned_bin(x2y2p->y, x2y2 + 32); 284 285 /* Step B4: t = KDF(x2 || y2, klen) */ 286 287 /* C = C1 || C2 || C3 */ 288 if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { 289 res = TEE_ERROR_BAD_PARAMETERS; 290 goto out; 291 } 292 293 C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; 294 295 t = calloc(1, C2_len); 296 if (!t) { 297 res = TEE_ERROR_OUT_OF_MEMORY; 298 goto out; 299 } 300 301 res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); 302 if (res) 303 goto out; 304 305 if (is_zero(t, C2_len)) { 306 res = TEE_ERROR_CIPHERTEXT_INVALID; 307 goto out; 308 } 309 310 /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ 311 312 out_len = MIN(*dst_len, C2_len); 313 for (i = 0; i < out_len; i++) 314 dst[i] = src[C1_len + i] ^ t[i]; 315 *dst_len = out_len; 316 if (out_len < C2_len) { 317 eom = calloc(1, C2_len - out_len); 318 if (!eom) 319 goto out; 320 for (i = out_len; i < C2_len; i++) 321 eom[i - out_len] = src[C1_len + i] ^ t[i]; 322 } 323 324 /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ 325 326 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 327 if (res) 328 goto out; 329 res = crypto_hash_init(ctx); 330 if (res) 331 goto out; 332 res = crypto_hash_update(ctx, x2y2, 32); 333 if (res) 334 goto out; 335 res = crypto_hash_update(ctx, dst, out_len); 336 if (res) 337 goto out; 338 if (out_len < C2_len) { 339 res = crypto_hash_update(ctx, eom, C2_len - out_len); 340 if (res) 341 goto out; 342 } 343 res = crypto_hash_update(ctx, x2y2 + 32, 32); 344 if (res) 345 goto out; 346 res = crypto_hash_final(ctx, u, sizeof(u)); 347 if (res) 348 goto out; 349 350 if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { 351 res = TEE_ERROR_CIPHERTEXT_INVALID; 352 goto out; 353 } 354 out: 355 free(eom); 356 free(t); 357 crypto_hash_free_ctx(ctx); 358 ltc_ecc_del_point(x2y2p); 359 ltc_ecc_del_point(S); 360 ltc_ecc_del_point(C1); 361 mp_clear_multi(h, NULL); 362 return res; 363 } 364 365 /* 366 * GM/T 0003.1‒2012 Part 1 Section 4.2.8 367 * Conversion of point @p to a byte string @buf (uncompressed form). 368 */ 369 static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, 370 const ecc_point *p) 371 { 372 size_t xsize = mp_unsigned_bin_size(p->x); 373 size_t ysize = mp_unsigned_bin_size(p->y); 374 375 if (*size < xsize + ysize + 1) 376 return TEE_ERROR_BAD_STATE; 377 378 buf[0] = 0x04; /* Uncompressed form indicator */ 379 mp_to_unsigned_bin(p->x, buf + 1); 380 mp_to_unsigned_bin(p->y, buf + 1 + xsize); 381 382 *size = xsize + ysize + 1; 383 384 return TEE_SUCCESS; 385 } 386 387 /* 388 * GM/T 0003.1‒2012 Part 4 Section 6.1 389 * Encryption algorithm 390 */ 391 TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, 392 const uint8_t *src, size_t src_len, 393 uint8_t *dst, size_t *dst_len) 394 { 395 TEE_Result res = TEE_SUCCESS; 396 ecc_key ltc_key = { }; 397 ecc_point *x2y2p = NULL; 398 ecc_point *C1 = NULL; 399 ecc_point *S = NULL; 400 uint8_t x2y2[64] = { }; 401 uint8_t *t = NULL; 402 int ltc_res = 0; 403 void *k = NULL; 404 void *h = NULL; 405 int inf = 0; 406 size_t C1_len = 0; 407 void *ctx = NULL; 408 size_t i = 0; 409 410 ltc_res = mp_init_multi(&k, &h, NULL); 411 if (ltc_res != CRYPT_OK) 412 return TEE_ERROR_OUT_OF_MEMORY; 413 414 res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); 415 if (res) 416 goto out; 417 418 /* Step A1: generate random number 1 <= k < n */ 419 420 ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, 421 find_prng("prng_crypto")); 422 if (ltc_res != CRYPT_OK) { 423 res = TEE_ERROR_BAD_STATE; 424 goto out; 425 } 426 427 /* Step A2: compute C1 = [k]G */ 428 429 C1 = ltc_ecc_new_point(); 430 if (!C1) { 431 res = TEE_ERROR_OUT_OF_MEMORY; 432 goto out; 433 } 434 435 ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A, 436 ltc_key.dp.prime, 1); 437 if (ltc_res != CRYPT_OK) { 438 res = TEE_ERROR_BAD_STATE; 439 goto out; 440 } 441 442 /* Step A3: compute S = [h]PB and check for infinity */ 443 444 if (ltc_key.dp.cofactor != 1) { 445 S = ltc_ecc_new_point(); 446 if (!S) { 447 res = TEE_ERROR_OUT_OF_MEMORY; 448 goto out; 449 } 450 451 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 452 if (ltc_res != CRYPT_OK) { 453 res = TEE_ERROR_BAD_STATE; 454 goto out; 455 } 456 457 ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A, 458 ltc_key.dp.prime, 1); 459 if (ltc_res != CRYPT_OK) { 460 res = TEE_ERROR_BAD_STATE; 461 goto out; 462 } 463 464 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 465 &inf); 466 } else { 467 ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey, 468 ltc_key.dp.prime, &inf); 469 } 470 if (ltc_res != CRYPT_OK) { 471 res = TEE_ERROR_BAD_STATE; 472 goto out; 473 } 474 if (inf) { 475 res = TEE_ERROR_BAD_STATE; 476 goto out; 477 } 478 479 /* Step A4: compute (x2, y2) = [k]PB */ 480 481 x2y2p = ltc_ecc_new_point(); 482 if (!x2y2p) { 483 res = TEE_ERROR_OUT_OF_MEMORY; 484 goto out; 485 } 486 487 ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A, 488 ltc_key.dp.prime, 1); 489 if (ltc_res != CRYPT_OK) { 490 res = TEE_ERROR_BAD_STATE; 491 goto out; 492 } 493 494 if (mp_unsigned_bin_size(x2y2p->x) != 32 || 495 mp_unsigned_bin_size(x2y2p->y) != 32) { 496 res = TEE_ERROR_BAD_STATE; 497 goto out; 498 } 499 500 mp_to_unsigned_bin(x2y2p->x, x2y2); 501 mp_to_unsigned_bin(x2y2p->y, x2y2 + 32); 502 503 /* Step A5: compute t = KDF(x2 || y2, klen) */ 504 505 t = calloc(1, src_len); 506 if (!t) { 507 res = TEE_ERROR_OUT_OF_MEMORY; 508 goto out; 509 } 510 511 res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); 512 if (res) 513 goto out; 514 515 if (is_zero(t, src_len)) { 516 res = TEE_ERROR_CIPHERTEXT_INVALID; 517 goto out; 518 } 519 520 /* 521 * Steps A6, A7, A8: 522 * Compute C2 = M (+) t 523 * Compute C3 = Hash(x2 || M || y2) 524 * Output C = C1 || C2 || C3 525 */ 526 527 /* C1 */ 528 C1_len = *dst_len; 529 res = sm2_point_to_bytes(dst, &C1_len, C1); 530 if (res) 531 goto out; 532 533 if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { 534 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 535 res = TEE_ERROR_SHORT_BUFFER; 536 goto out; 537 } 538 539 /* C2 */ 540 for (i = 0; i < src_len; i++) 541 dst[i + C1_len] = src[i] ^ t[i]; 542 543 /* C3 */ 544 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 545 if (res) 546 goto out; 547 res = crypto_hash_init(ctx); 548 if (res) 549 goto out; 550 res = crypto_hash_update(ctx, x2y2, 32); 551 if (res) 552 goto out; 553 res = crypto_hash_update(ctx, src, src_len); 554 if (res) 555 goto out; 556 res = crypto_hash_update(ctx, x2y2 + 32, 32); 557 if (res) 558 goto out; 559 res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); 560 if (res) 561 goto out; 562 563 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 564 out: 565 crypto_hash_free_ctx(ctx); 566 free(t); 567 ltc_ecc_del_point(x2y2p); 568 ltc_ecc_del_point(S); 569 ltc_ecc_del_point(C1); 570 mp_clear_multi(k, h, NULL); 571 return res; 572 } 573