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 sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, 108 size_t src_len, uint8_t *dst, size_t *dst_len) 109 { 110 TEE_Result res = TEE_SUCCESS; 111 uint8_t x2y2[64] = { }; 112 ecc_key ltc_key = { }; 113 ecc_point *C1 = NULL; 114 size_t C1_len = 0; 115 ecc_point *S = NULL; 116 ecc_point *x2y2p = NULL; 117 void *ctx = NULL; 118 int ltc_res = 0; 119 void *h = NULL; 120 int inf = 0; 121 uint8_t *t = NULL; 122 size_t C2_len = 0; 123 size_t i = 0; 124 size_t out_len = 0; 125 uint8_t *eom = NULL; 126 uint8_t u[TEE_SM3_HASH_SIZE] = { }; 127 128 /* 129 * Input buffer src is (C1 || C2 || C3) 130 * - C1 represents a point (should be on the curve) 131 * - C2 is the encrypted message 132 * - C3 is a SM3 hash 133 */ 134 135 res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE, 136 NULL); 137 if (res) 138 goto out; 139 140 /* Step B1: read and validate point C1 from encrypted message */ 141 142 C1 = ltc_ecc_new_point(); 143 if (!C1) { 144 res = TEE_ERROR_OUT_OF_MEMORY; 145 goto out; 146 } 147 148 res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len); 149 if (res) 150 goto out; 151 152 /* Step B2: S = [h]C1 */ 153 154 if (ltc_key.dp.cofactor != 1) { 155 S = ltc_ecc_new_point(); 156 if (!S) { 157 res = TEE_ERROR_OUT_OF_MEMORY; 158 goto out; 159 } 160 161 ltc_res = mp_init_multi(&h, NULL); 162 if (ltc_res != CRYPT_OK) { 163 res = TEE_ERROR_OUT_OF_MEMORY; 164 goto out; 165 } 166 167 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 168 if (ltc_res != CRYPT_OK) { 169 res = TEE_ERROR_BAD_STATE; 170 goto out; 171 } 172 173 ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A, 174 ltc_key.dp.prime, 1); 175 if (ltc_res != CRYPT_OK) { 176 res = TEE_ERROR_BAD_STATE; 177 goto out; 178 } 179 180 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 181 &inf); 182 } else { 183 ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime, 184 &inf); 185 } 186 if (ltc_res != CRYPT_OK || inf) { 187 res = TEE_ERROR_BAD_STATE; 188 goto out; 189 } 190 191 /* Step B3: (x2, y2) = [dB]C1 */ 192 193 x2y2p = ltc_ecc_new_point(); 194 if (!x2y2p) { 195 res = TEE_ERROR_OUT_OF_MEMORY; 196 goto out; 197 } 198 199 ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A, 200 ltc_key.dp.prime, 1); 201 if (ltc_res != CRYPT_OK) { 202 res = TEE_ERROR_BAD_STATE; 203 goto out; 204 } 205 206 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || 207 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { 208 res = TEE_ERROR_BAD_STATE; 209 goto out; 210 } 211 212 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); 213 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, 214 SM2_INT_SIZE_BYTES); 215 216 /* Step B4: t = KDF(x2 || y2, klen) */ 217 218 /* C = C1 || C2 || C3 */ 219 if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { 220 res = TEE_ERROR_BAD_PARAMETERS; 221 goto out; 222 } 223 224 C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; 225 226 t = calloc(1, C2_len); 227 if (!t) { 228 res = TEE_ERROR_OUT_OF_MEMORY; 229 goto out; 230 } 231 232 res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); 233 if (res) 234 goto out; 235 236 if (is_zero(t, C2_len)) { 237 res = TEE_ERROR_CIPHERTEXT_INVALID; 238 goto out; 239 } 240 241 /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ 242 243 out_len = MIN(*dst_len, C2_len); 244 for (i = 0; i < out_len; i++) 245 dst[i] = src[C1_len + i] ^ t[i]; 246 *dst_len = out_len; 247 if (out_len < C2_len) { 248 eom = calloc(1, C2_len - out_len); 249 if (!eom) 250 goto out; 251 for (i = out_len; i < C2_len; i++) 252 eom[i - out_len] = src[C1_len + i] ^ t[i]; 253 } 254 255 /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ 256 257 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 258 if (res) 259 goto out; 260 res = crypto_hash_init(ctx); 261 if (res) 262 goto out; 263 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); 264 if (res) 265 goto out; 266 res = crypto_hash_update(ctx, dst, out_len); 267 if (res) 268 goto out; 269 if (out_len < C2_len) { 270 res = crypto_hash_update(ctx, eom, C2_len - out_len); 271 if (res) 272 goto out; 273 } 274 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, 275 SM2_INT_SIZE_BYTES); 276 if (res) 277 goto out; 278 res = crypto_hash_final(ctx, u, sizeof(u)); 279 if (res) 280 goto out; 281 282 if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { 283 res = TEE_ERROR_CIPHERTEXT_INVALID; 284 goto out; 285 } 286 out: 287 free(eom); 288 free(t); 289 crypto_hash_free_ctx(ctx); 290 ltc_ecc_del_point(x2y2p); 291 ltc_ecc_del_point(S); 292 ltc_ecc_del_point(C1); 293 mp_clear_multi(h, NULL); 294 ecc_free(<c_key); 295 return res; 296 } 297 298 /* 299 * GM/T 0003.1‒2012 Part 1 Section 4.2.8 300 * Conversion of point @p to a byte string @buf (uncompressed form). 301 */ 302 static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, 303 const ecc_point *p) 304 { 305 size_t xsize = mp_unsigned_bin_size(p->x); 306 size_t ysize = mp_unsigned_bin_size(p->y); 307 size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; 308 309 if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || 310 *size < sz) 311 return TEE_ERROR_BAD_STATE; 312 313 memset(buf, 0, sz); 314 buf[0] = 0x04; /* Uncompressed form indicator */ 315 mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES); 316 mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES, 317 SM2_INT_SIZE_BYTES); 318 319 *size = sz; 320 321 return TEE_SUCCESS; 322 } 323 324 /* 325 * GM/T 0003.1‒2012 Part 4 Section 6.1 326 * Encryption algorithm 327 */ 328 TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, 329 size_t src_len, 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