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 res = TEE_ERROR_OUT_OF_MEMORY; 251 goto out; 252 } 253 for (i = out_len; i < C2_len; i++) 254 eom[i - out_len] = src[C1_len + i] ^ t[i]; 255 } 256 257 /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ 258 259 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 260 if (res) 261 goto out; 262 res = crypto_hash_init(ctx); 263 if (res) 264 goto out; 265 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); 266 if (res) 267 goto out; 268 res = crypto_hash_update(ctx, dst, out_len); 269 if (res) 270 goto out; 271 if (out_len < C2_len) { 272 res = crypto_hash_update(ctx, eom, C2_len - out_len); 273 if (res) 274 goto out; 275 } 276 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, 277 SM2_INT_SIZE_BYTES); 278 if (res) 279 goto out; 280 res = crypto_hash_final(ctx, u, sizeof(u)); 281 if (res) 282 goto out; 283 284 if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { 285 res = TEE_ERROR_CIPHERTEXT_INVALID; 286 goto out; 287 } 288 out: 289 free(eom); 290 free(t); 291 crypto_hash_free_ctx(ctx); 292 ltc_ecc_del_point(x2y2p); 293 ltc_ecc_del_point(S); 294 ltc_ecc_del_point(C1); 295 mp_clear_multi(h, NULL); 296 ecc_free(<c_key); 297 return res; 298 } 299 300 /* 301 * GM/T 0003.1‒2012 Part 1 Section 4.2.8 302 * Conversion of point @p to a byte string @buf (uncompressed form). 303 */ 304 static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, 305 const ecc_point *p) 306 { 307 size_t xsize = mp_unsigned_bin_size(p->x); 308 size_t ysize = mp_unsigned_bin_size(p->y); 309 size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; 310 311 if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || 312 *size < sz) 313 return TEE_ERROR_BAD_STATE; 314 315 memset(buf, 0, sz); 316 buf[0] = 0x04; /* Uncompressed form indicator */ 317 mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES); 318 mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES, 319 SM2_INT_SIZE_BYTES); 320 321 *size = sz; 322 323 return TEE_SUCCESS; 324 } 325 326 /* 327 * GM/T 0003.1‒2012 Part 4 Section 6.1 328 * Encryption algorithm 329 */ 330 TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, 331 size_t src_len, uint8_t *dst, size_t *dst_len) 332 { 333 TEE_Result res = TEE_SUCCESS; 334 ecc_key ltc_key = { }; 335 ecc_point *x2y2p = NULL; 336 ecc_point *C1 = NULL; 337 ecc_point *S = NULL; 338 uint8_t x2y2[64] = { }; 339 uint8_t *t = NULL; 340 int ltc_res = 0; 341 void *k = NULL; 342 void *h = NULL; 343 int inf = 0; 344 size_t C1_len = 0; 345 void *ctx = NULL; 346 size_t i = 0; 347 348 ltc_res = mp_init_multi(&k, &h, NULL); 349 if (ltc_res != CRYPT_OK) 350 return TEE_ERROR_OUT_OF_MEMORY; 351 352 res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); 353 if (res) 354 goto out; 355 356 /* Step A1: generate random number 1 <= k < n */ 357 358 ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, 359 find_prng("prng_crypto")); 360 if (ltc_res != CRYPT_OK) { 361 res = TEE_ERROR_BAD_STATE; 362 goto out; 363 } 364 365 /* Step A2: compute C1 = [k]G */ 366 367 C1 = ltc_ecc_new_point(); 368 if (!C1) { 369 res = TEE_ERROR_OUT_OF_MEMORY; 370 goto out; 371 } 372 373 ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A, 374 ltc_key.dp.prime, 1); 375 if (ltc_res != CRYPT_OK) { 376 res = TEE_ERROR_BAD_STATE; 377 goto out; 378 } 379 380 /* Step A3: compute S = [h]PB and check for infinity */ 381 382 if (ltc_key.dp.cofactor != 1) { 383 S = ltc_ecc_new_point(); 384 if (!S) { 385 res = TEE_ERROR_OUT_OF_MEMORY; 386 goto out; 387 } 388 389 ltc_res = mp_set_int(h, ltc_key.dp.cofactor); 390 if (ltc_res != CRYPT_OK) { 391 res = TEE_ERROR_BAD_STATE; 392 goto out; 393 } 394 395 ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A, 396 ltc_key.dp.prime, 1); 397 if (ltc_res != CRYPT_OK) { 398 res = TEE_ERROR_BAD_STATE; 399 goto out; 400 } 401 402 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, 403 &inf); 404 } else { 405 ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey, 406 ltc_key.dp.prime, &inf); 407 } 408 if (ltc_res != CRYPT_OK) { 409 res = TEE_ERROR_BAD_STATE; 410 goto out; 411 } 412 if (inf) { 413 res = TEE_ERROR_BAD_STATE; 414 goto out; 415 } 416 417 /* Step A4: compute (x2, y2) = [k]PB */ 418 419 x2y2p = ltc_ecc_new_point(); 420 if (!x2y2p) { 421 res = TEE_ERROR_OUT_OF_MEMORY; 422 goto out; 423 } 424 425 ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A, 426 ltc_key.dp.prime, 1); 427 if (ltc_res != CRYPT_OK) { 428 res = TEE_ERROR_BAD_STATE; 429 goto out; 430 } 431 432 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || 433 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { 434 res = TEE_ERROR_BAD_STATE; 435 goto out; 436 } 437 438 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); 439 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, 440 SM2_INT_SIZE_BYTES); 441 442 /* Step A5: compute t = KDF(x2 || y2, klen) */ 443 444 t = calloc(1, src_len); 445 if (!t) { 446 res = TEE_ERROR_OUT_OF_MEMORY; 447 goto out; 448 } 449 450 res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); 451 if (res) 452 goto out; 453 454 if (is_zero(t, src_len)) { 455 res = TEE_ERROR_CIPHERTEXT_INVALID; 456 goto out; 457 } 458 459 /* 460 * Steps A6, A7, A8: 461 * Compute C2 = M (+) t 462 * Compute C3 = Hash(x2 || M || y2) 463 * Output C = C1 || C2 || C3 464 */ 465 466 /* C1 */ 467 C1_len = *dst_len; 468 res = sm2_point_to_bytes(dst, &C1_len, C1); 469 if (res) 470 goto out; 471 472 if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { 473 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 474 res = TEE_ERROR_SHORT_BUFFER; 475 goto out; 476 } 477 478 /* C2 */ 479 for (i = 0; i < src_len; i++) 480 dst[i + C1_len] = src[i] ^ t[i]; 481 482 /* C3 */ 483 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); 484 if (res) 485 goto out; 486 res = crypto_hash_init(ctx); 487 if (res) 488 goto out; 489 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); 490 if (res) 491 goto out; 492 res = crypto_hash_update(ctx, src, src_len); 493 if (res) 494 goto out; 495 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, 496 SM2_INT_SIZE_BYTES); 497 if (res) 498 goto out; 499 res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); 500 if (res) 501 goto out; 502 503 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; 504 out: 505 crypto_hash_free_ctx(ctx); 506 free(t); 507 ltc_ecc_del_point(x2y2p); 508 ltc_ecc_del_point(S); 509 ltc_ecc_del_point(C1); 510 ecc_free(<c_key); 511 mp_clear_multi(k, h, NULL); 512 return res; 513 } 514