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