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 static bool is_zero(const uint8_t *buf, size_t size) 93 { 94 uint8_t v = 0; 95 size_t i = 0; 96 97 for (i = 0; i < size; i++) 98 v |= buf[i]; 99 100 return !v; 101 } 102 103 /* 104 * GM/T 0003.1‒2012 Part 4 Section 7.1 105 * Decryption algorithm 106 */ 107 TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, 108 const uint8_t *src, size_t src_len, 109 uint8_t *dst, size_t *dst_len) 110 { 111 TEE_Result res = TEE_SUCCESS; 112 uint8_t x2y2[64] = { }; 113 ecc_key ltc_key = { }; 114 ecc_point *C1 = NULL; 115 size_t C1_len = 0; 116 ecc_point *S = NULL; 117 ecc_point *x2y2p = NULL; 118 void *ctx = NULL; 119 int ltc_res = 0; 120 void *h = NULL; 121 int inf = 0; 122 uint8_t *t = NULL; 123 size_t C2_len = 0; 124 size_t i = 0; 125 size_t out_len = 0; 126 uint8_t *eom = NULL; 127 uint8_t u[TEE_SM3_HASH_SIZE] = { }; 128 129 /* 130 * Input buffer src is (C1 || C2 || C3) 131 * - C1 represents a point (should be on the curve) 132 * - C2 is the encrypted message 133 * - C3 is a SM3 hash 134 */ 135 136 res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE, 137 NULL); 138 if (res) 139 goto out; 140 141 /* Step B1: read and validate point C1 from encrypted message */ 142 143 C1 = ltc_ecc_new_point(); 144 if (!C1) { 145 res = TEE_ERROR_OUT_OF_MEMORY; 146 goto out; 147 } 148 149 res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len); 150 if (res) 151 goto out; 152 153 /* Step B2: S = [h]C1 */ 154 155 if (ltc_key.dp.cofactor != 1) { 156 S = ltc_ecc_new_point(); 157 if (!S) { 158 res = TEE_ERROR_OUT_OF_MEMORY; 159 goto out; 160 } 161 162 ltc_res = mp_init_multi(&h, NULL); 163 if (ltc_res != CRYPT_OK) 164 return TEE_ERROR_OUT_OF_MEMORY; 165 166 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 167 if (ltc_res != CRYPT_OK) { 168 res = TEE_ERROR_BAD_STATE; 169 goto out; 170 } 171 172 ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A, 173 ltc_key.dp.prime, 1); 174 if (ltc_res != CRYPT_OK) { 175 res = TEE_ERROR_BAD_STATE; 176 goto out; 177 } 178 179 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 180 &inf); 181 } else { 182 ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime, 183 &inf); 184 } 185 if (ltc_res != CRYPT_OK || inf) { 186 res = TEE_ERROR_BAD_STATE; 187 goto out; 188 } 189 190 /* Step B3: (x2, y2) = [dB]C1 */ 191 192 x2y2p = ltc_ecc_new_point(); 193 if (!x2y2p) { 194 res = TEE_ERROR_OUT_OF_MEMORY; 195 goto out; 196 } 197 198 ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A, 199 ltc_key.dp.prime, 1); 200 if (ltc_res != CRYPT_OK) { 201 res = TEE_ERROR_BAD_STATE; 202 goto out; 203 } 204 205 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || 206 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { 207 res = TEE_ERROR_BAD_STATE; 208 goto out; 209 } 210 211 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); 212 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, 213 SM2_INT_SIZE_BYTES); 214 215 /* Step B4: t = KDF(x2 || y2, klen) */ 216 217 /* C = C1 || C2 || C3 */ 218 if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { 219 res = TEE_ERROR_BAD_PARAMETERS; 220 goto out; 221 } 222 223 C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; 224 225 t = calloc(1, C2_len); 226 if (!t) { 227 res = TEE_ERROR_OUT_OF_MEMORY; 228 goto out; 229 } 230 231 res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); 232 if (res) 233 goto out; 234 235 if (is_zero(t, C2_len)) { 236 res = TEE_ERROR_CIPHERTEXT_INVALID; 237 goto out; 238 } 239 240 /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ 241 242 out_len = MIN(*dst_len, C2_len); 243 for (i = 0; i < out_len; i++) 244 dst[i] = src[C1_len + i] ^ t[i]; 245 *dst_len = out_len; 246 if (out_len < C2_len) { 247 eom = calloc(1, C2_len - out_len); 248 if (!eom) 249 goto out; 250 for (i = out_len; i < C2_len; i++) 251 eom[i - out_len] = src[C1_len + i] ^ t[i]; 252 } 253 254 /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ 255 256 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 257 if (res) 258 goto out; 259 res = crypto_hash_init(ctx); 260 if (res) 261 goto out; 262 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); 263 if (res) 264 goto out; 265 res = crypto_hash_update(ctx, dst, out_len); 266 if (res) 267 goto out; 268 if (out_len < C2_len) { 269 res = crypto_hash_update(ctx, eom, C2_len - out_len); 270 if (res) 271 goto out; 272 } 273 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, 274 SM2_INT_SIZE_BYTES); 275 if (res) 276 goto out; 277 res = crypto_hash_final(ctx, u, sizeof(u)); 278 if (res) 279 goto out; 280 281 if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { 282 res = TEE_ERROR_CIPHERTEXT_INVALID; 283 goto out; 284 } 285 out: 286 free(eom); 287 free(t); 288 crypto_hash_free_ctx(ctx); 289 ltc_ecc_del_point(x2y2p); 290 ltc_ecc_del_point(S); 291 ltc_ecc_del_point(C1); 292 mp_clear_multi(h, NULL); 293 ecc_free(<c_key); 294 return res; 295 } 296 297 /* 298 * GM/T 0003.1‒2012 Part 1 Section 4.2.8 299 * Conversion of point @p to a byte string @buf (uncompressed form). 300 */ 301 static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, 302 const ecc_point *p) 303 { 304 size_t xsize = mp_unsigned_bin_size(p->x); 305 size_t ysize = mp_unsigned_bin_size(p->y); 306 size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; 307 308 if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || 309 *size < sz) 310 return TEE_ERROR_BAD_STATE; 311 312 memset(buf, 0, sz); 313 buf[0] = 0x04; /* Uncompressed form indicator */ 314 mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES); 315 mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES, 316 SM2_INT_SIZE_BYTES); 317 318 *size = sz; 319 320 return TEE_SUCCESS; 321 } 322 323 /* 324 * GM/T 0003.1‒2012 Part 4 Section 6.1 325 * Encryption algorithm 326 */ 327 TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, 328 const uint8_t *src, size_t src_len, 329 uint8_t *dst, size_t *dst_len) 330 { 331 TEE_Result res = TEE_SUCCESS; 332 ecc_key ltc_key = { }; 333 ecc_point *x2y2p = NULL; 334 ecc_point *C1 = NULL; 335 ecc_point *S = NULL; 336 uint8_t x2y2[64] = { }; 337 uint8_t *t = NULL; 338 int ltc_res = 0; 339 void *k = NULL; 340 void *h = NULL; 341 int inf = 0; 342 size_t C1_len = 0; 343 void *ctx = NULL; 344 size_t i = 0; 345 346 ltc_res = mp_init_multi(&k, &h, NULL); 347 if (ltc_res != CRYPT_OK) 348 return TEE_ERROR_OUT_OF_MEMORY; 349 350 res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); 351 if (res) 352 goto out; 353 354 /* Step A1: generate random number 1 <= k < n */ 355 356 ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, 357 find_prng("prng_crypto")); 358 if (ltc_res != CRYPT_OK) { 359 res = TEE_ERROR_BAD_STATE; 360 goto out; 361 } 362 363 /* Step A2: compute C1 = [k]G */ 364 365 C1 = ltc_ecc_new_point(); 366 if (!C1) { 367 res = TEE_ERROR_OUT_OF_MEMORY; 368 goto out; 369 } 370 371 ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A, 372 ltc_key.dp.prime, 1); 373 if (ltc_res != CRYPT_OK) { 374 res = TEE_ERROR_BAD_STATE; 375 goto out; 376 } 377 378 /* Step A3: compute S = [h]PB and check for infinity */ 379 380 if (ltc_key.dp.cofactor != 1) { 381 S = ltc_ecc_new_point(); 382 if (!S) { 383 res = TEE_ERROR_OUT_OF_MEMORY; 384 goto out; 385 } 386 387 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 388 if (ltc_res != CRYPT_OK) { 389 res = TEE_ERROR_BAD_STATE; 390 goto out; 391 } 392 393 ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A, 394 ltc_key.dp.prime, 1); 395 if (ltc_res != CRYPT_OK) { 396 res = TEE_ERROR_BAD_STATE; 397 goto out; 398 } 399 400 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 401 &inf); 402 } else { 403 ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey, 404 ltc_key.dp.prime, &inf); 405 } 406 if (ltc_res != CRYPT_OK) { 407 res = TEE_ERROR_BAD_STATE; 408 goto out; 409 } 410 if (inf) { 411 res = TEE_ERROR_BAD_STATE; 412 goto out; 413 } 414 415 /* Step A4: compute (x2, y2) = [k]PB */ 416 417 x2y2p = ltc_ecc_new_point(); 418 if (!x2y2p) { 419 res = TEE_ERROR_OUT_OF_MEMORY; 420 goto out; 421 } 422 423 ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A, 424 ltc_key.dp.prime, 1); 425 if (ltc_res != CRYPT_OK) { 426 res = TEE_ERROR_BAD_STATE; 427 goto out; 428 } 429 430 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || 431 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { 432 res = TEE_ERROR_BAD_STATE; 433 goto out; 434 } 435 436 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); 437 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, 438 SM2_INT_SIZE_BYTES); 439 440 /* Step A5: compute t = KDF(x2 || y2, klen) */ 441 442 t = calloc(1, src_len); 443 if (!t) { 444 res = TEE_ERROR_OUT_OF_MEMORY; 445 goto out; 446 } 447 448 res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); 449 if (res) 450 goto out; 451 452 if (is_zero(t, src_len)) { 453 res = TEE_ERROR_CIPHERTEXT_INVALID; 454 goto out; 455 } 456 457 /* 458 * Steps A6, A7, A8: 459 * Compute C2 = M (+) t 460 * Compute C3 = Hash(x2 || M || y2) 461 * Output C = C1 || C2 || C3 462 */ 463 464 /* C1 */ 465 C1_len = *dst_len; 466 res = sm2_point_to_bytes(dst, &C1_len, C1); 467 if (res) 468 goto out; 469 470 if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { 471 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 472 res = TEE_ERROR_SHORT_BUFFER; 473 goto out; 474 } 475 476 /* C2 */ 477 for (i = 0; i < src_len; i++) 478 dst[i + C1_len] = src[i] ^ t[i]; 479 480 /* C3 */ 481 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 482 if (res) 483 goto out; 484 res = crypto_hash_init(ctx); 485 if (res) 486 goto out; 487 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); 488 if (res) 489 goto out; 490 res = crypto_hash_update(ctx, src, src_len); 491 if (res) 492 goto out; 493 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, 494 SM2_INT_SIZE_BYTES); 495 if (res) 496 goto out; 497 res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); 498 if (res) 499 goto out; 500 501 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 502 out: 503 crypto_hash_free_ctx(ctx); 504 free(t); 505 ltc_ecc_del_point(x2y2p); 506 ltc_ecc_del_point(S); 507 ltc_ecc_del_point(C1); 508 ecc_free(<c_key); 509 mp_clear_multi(k, h, NULL); 510 return res; 511 } 512