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