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