176c7ba4bSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 276c7ba4bSJerome Forissier /* 376c7ba4bSJerome Forissier * Copyright (c) 2019 Huawei Technologies Co., Ltd 476c7ba4bSJerome Forissier */ 576c7ba4bSJerome Forissier 676c7ba4bSJerome Forissier #include <crypto/crypto.h> 776c7ba4bSJerome Forissier #include <stdlib.h> 876c7ba4bSJerome Forissier #include <string.h> 976c7ba4bSJerome Forissier #include <tee_api_types.h> 1076c7ba4bSJerome Forissier #include <util.h> 1176c7ba4bSJerome Forissier #include <utee_defines.h> 1276c7ba4bSJerome Forissier 1376c7ba4bSJerome Forissier #include "acipher_helpers.h" 1476c7ba4bSJerome Forissier 1576c7ba4bSJerome Forissier /* 1676c7ba4bSJerome Forissier * GM/T 0003.1‒2012 Part1 2 Section 6.1 1776c7ba4bSJerome Forissier */ 1876c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo, 1976c7ba4bSJerome Forissier struct ecc_keypair *key, 2076c7ba4bSJerome Forissier const uint8_t *msg, size_t msg_len, 2176c7ba4bSJerome Forissier uint8_t *sig, size_t *sig_len) 2276c7ba4bSJerome Forissier { 2376c7ba4bSJerome Forissier TEE_Result res = TEE_SUCCESS; 2476c7ba4bSJerome Forissier ecc_point *x1y1p = NULL; 2576c7ba4bSJerome Forissier ecc_key ltc_key = { }; 2676c7ba4bSJerome Forissier int ltc_res = 0; 2776c7ba4bSJerome Forissier void *k = NULL; 2876c7ba4bSJerome Forissier void *e = NULL; 2976c7ba4bSJerome Forissier void *r = NULL; 3076c7ba4bSJerome Forissier void *s = NULL; 3176c7ba4bSJerome Forissier void *tmp = NULL; 3276c7ba4bSJerome Forissier 3376c7ba4bSJerome Forissier if (*sig_len < 64) { 3476c7ba4bSJerome Forissier *sig_len = 64; 3576c7ba4bSJerome Forissier return TEE_ERROR_SHORT_BUFFER; 3676c7ba4bSJerome Forissier } 3776c7ba4bSJerome Forissier 3876c7ba4bSJerome Forissier ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL); 3976c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) 4076c7ba4bSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 4176c7ba4bSJerome Forissier 4276c7ba4bSJerome Forissier x1y1p = ltc_ecc_new_point(); 4376c7ba4bSJerome Forissier if (!x1y1p) { 4476c7ba4bSJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 4576c7ba4bSJerome Forissier goto out; 4676c7ba4bSJerome Forissier } 4776c7ba4bSJerome Forissier 4876c7ba4bSJerome Forissier res = ecc_populate_ltc_private_key(<c_key, key, algo, NULL); 4976c7ba4bSJerome Forissier if (res) 5076c7ba4bSJerome Forissier goto out; 5176c7ba4bSJerome Forissier 5276c7ba4bSJerome Forissier /* 5376c7ba4bSJerome Forissier * Steps A1 and A2 are the generation of the hash value e from user 5476c7ba4bSJerome Forissier * information (ZA) and the message to be signed (M). There are not done 5576c7ba4bSJerome Forissier * here since @msg is expected to be the hash value e already. 5676c7ba4bSJerome Forissier */ 5776c7ba4bSJerome Forissier 5876c7ba4bSJerome Forissier /* Step A3: generate random number 1 <= k < n */ 5976c7ba4bSJerome Forissier A3: 6076c7ba4bSJerome Forissier ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, 6176c7ba4bSJerome Forissier find_prng("prng_crypto")); 6276c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 6376c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 6476c7ba4bSJerome Forissier goto out; 6576c7ba4bSJerome Forissier } 6676c7ba4bSJerome Forissier 6776c7ba4bSJerome Forissier /* Step A4: compute (x1, y1) = [k]G */ 6876c7ba4bSJerome Forissier 6976c7ba4bSJerome Forissier ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, x1y1p, ltc_key.dp.A, 7076c7ba4bSJerome Forissier ltc_key.dp.prime, 1); 7176c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 7276c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 7376c7ba4bSJerome Forissier goto out; 7476c7ba4bSJerome Forissier } 7576c7ba4bSJerome Forissier 7676c7ba4bSJerome Forissier /* Step A5: compute r = (e + x1) mod n */ 7776c7ba4bSJerome Forissier 7876c7ba4bSJerome Forissier mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len); 7976c7ba4bSJerome Forissier ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r); 8076c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 8176c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 8276c7ba4bSJerome Forissier goto out; 8376c7ba4bSJerome Forissier } 8476c7ba4bSJerome Forissier ltc_res = mp_add(r, k, tmp); 8576c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 8676c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 8776c7ba4bSJerome Forissier goto out; 8876c7ba4bSJerome Forissier } 8976c7ba4bSJerome Forissier if (mp_cmp_d(r, 0) == LTC_MP_EQ || 9076c7ba4bSJerome Forissier mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ) 9176c7ba4bSJerome Forissier goto A3; 9276c7ba4bSJerome Forissier 9376c7ba4bSJerome Forissier /* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */ 9476c7ba4bSJerome Forissier 9576c7ba4bSJerome Forissier ltc_res = mp_add_d(ltc_key.k, 1, s); 9676c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 9776c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 9876c7ba4bSJerome Forissier goto out; 9976c7ba4bSJerome Forissier } 10076c7ba4bSJerome Forissier ltc_res = mp_invmod(s, ltc_key.dp.order, s); 10176c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 10276c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 10376c7ba4bSJerome Forissier goto out; 10476c7ba4bSJerome Forissier } 10576c7ba4bSJerome Forissier ltc_res = mp_mul(r, ltc_key.k, tmp); 10676c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 10776c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 10876c7ba4bSJerome Forissier goto out; 10976c7ba4bSJerome Forissier } 11076c7ba4bSJerome Forissier ltc_res = mp_sub(k, tmp, tmp); 11176c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 11276c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 11376c7ba4bSJerome Forissier goto out; 11476c7ba4bSJerome Forissier } 11576c7ba4bSJerome Forissier ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s); 11676c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 11776c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 11876c7ba4bSJerome Forissier goto out; 11976c7ba4bSJerome Forissier } 12076c7ba4bSJerome Forissier 12176c7ba4bSJerome Forissier /* Step A7: convert (r, s) to binary for output */ 12276c7ba4bSJerome Forissier 12376c7ba4bSJerome Forissier memset(sig, 0, 64); 12476c7ba4bSJerome Forissier mp_to_unsigned_bin(r, sig); 12576c7ba4bSJerome Forissier mp_to_unsigned_bin(s, sig + 32); 12676c7ba4bSJerome Forissier *sig_len = 64; 12776c7ba4bSJerome Forissier out: 128*0b38353cSJerome Forissier ecc_free(<c_key); 12976c7ba4bSJerome Forissier ltc_ecc_del_point(x1y1p); 13076c7ba4bSJerome Forissier mp_clear_multi(k, e, r, s, tmp, NULL); 13176c7ba4bSJerome Forissier return res; 13276c7ba4bSJerome Forissier } 13376c7ba4bSJerome Forissier 13476c7ba4bSJerome Forissier /* 13576c7ba4bSJerome Forissier * GM/T 0003.1‒2012 Part1 2 Section 7.1 13676c7ba4bSJerome Forissier */ 13776c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo, 13876c7ba4bSJerome Forissier struct ecc_public_key *key, 13976c7ba4bSJerome Forissier const uint8_t *msg, size_t msg_len, 14076c7ba4bSJerome Forissier const uint8_t *sig, size_t sig_len) 14176c7ba4bSJerome Forissier { 14276c7ba4bSJerome Forissier TEE_Result res = TEE_SUCCESS; 14376c7ba4bSJerome Forissier ecc_key ltc_key = { }; 14476c7ba4bSJerome Forissier int ltc_res = 0; 14576c7ba4bSJerome Forissier void *rprime = NULL; 14676c7ba4bSJerome Forissier void *sprime = NULL; 14776c7ba4bSJerome Forissier void *t = NULL; 14876c7ba4bSJerome Forissier void *mp = NULL; 14976c7ba4bSJerome Forissier void *mu = NULL; 15076c7ba4bSJerome Forissier void *ma = NULL; 15176c7ba4bSJerome Forissier void *eprime = NULL; 15276c7ba4bSJerome Forissier void *R = NULL; 15376c7ba4bSJerome Forissier ecc_point *x1y1p = NULL; 15476c7ba4bSJerome Forissier 15576c7ba4bSJerome Forissier if (sig_len != 64) 15676c7ba4bSJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 15776c7ba4bSJerome Forissier 15876c7ba4bSJerome Forissier ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R, 15976c7ba4bSJerome Forissier NULL); 16076c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) 16176c7ba4bSJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 16276c7ba4bSJerome Forissier 16376c7ba4bSJerome Forissier mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32); 16476c7ba4bSJerome Forissier mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32); 16576c7ba4bSJerome Forissier 16676c7ba4bSJerome Forissier res = ecc_populate_ltc_public_key(<c_key, key, algo, NULL); 16776c7ba4bSJerome Forissier if (res) 16876c7ba4bSJerome Forissier goto out; 16976c7ba4bSJerome Forissier 17076c7ba4bSJerome Forissier /* Step B1: verify r' in [1, n - 1] */ 17176c7ba4bSJerome Forissier 17276c7ba4bSJerome Forissier if (mp_cmp_d(rprime, 1) == LTC_MP_LT || 17376c7ba4bSJerome Forissier mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) { 17476c7ba4bSJerome Forissier res = TEE_ERROR_SIGNATURE_INVALID; 17576c7ba4bSJerome Forissier goto out; 17676c7ba4bSJerome Forissier } 17776c7ba4bSJerome Forissier 17876c7ba4bSJerome Forissier /* Step B2: verify s' in [1, n - 1] */ 17976c7ba4bSJerome Forissier 18076c7ba4bSJerome Forissier if (mp_cmp_d(sprime, 1) == LTC_MP_LT || 18176c7ba4bSJerome Forissier mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) { 18276c7ba4bSJerome Forissier res = TEE_ERROR_SIGNATURE_INVALID; 18376c7ba4bSJerome Forissier goto out; 18476c7ba4bSJerome Forissier } 18576c7ba4bSJerome Forissier 18676c7ba4bSJerome Forissier /* 18776c7ba4bSJerome Forissier * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here 18876c7ba4bSJerome Forissier * because @msg is supposed to contain the hash value e' already. 18976c7ba4bSJerome Forissier */ 19076c7ba4bSJerome Forissier 19176c7ba4bSJerome Forissier /* Step B5: t = (r' + s') mod n and check t != 0 */ 19276c7ba4bSJerome Forissier 19376c7ba4bSJerome Forissier ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t); 19476c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 19576c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 19676c7ba4bSJerome Forissier goto out; 19776c7ba4bSJerome Forissier } 19876c7ba4bSJerome Forissier if (mp_cmp_d(t, 0) == LTC_MP_EQ) { 19976c7ba4bSJerome Forissier res = TEE_ERROR_SIGNATURE_INVALID; 20076c7ba4bSJerome Forissier goto out; 20176c7ba4bSJerome Forissier } 20276c7ba4bSJerome Forissier 20376c7ba4bSJerome Forissier /* Step B6: (x1', y1') = [s']G + [t]PA */ 20476c7ba4bSJerome Forissier 20576c7ba4bSJerome Forissier x1y1p = ltc_ecc_new_point(); 20676c7ba4bSJerome Forissier if (!x1y1p) { 20776c7ba4bSJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 20876c7ba4bSJerome Forissier goto out; 20976c7ba4bSJerome Forissier } 21076c7ba4bSJerome Forissier ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp); 21176c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 21276c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 21376c7ba4bSJerome Forissier goto out; 21476c7ba4bSJerome Forissier } 21576c7ba4bSJerome Forissier ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime); 21676c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 21776c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 21876c7ba4bSJerome Forissier goto out; 21976c7ba4bSJerome Forissier } 22076c7ba4bSJerome Forissier ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma); 22176c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 22276c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 22376c7ba4bSJerome Forissier goto out; 22476c7ba4bSJerome Forissier } 22576c7ba4bSJerome Forissier ltc_res = ltc_ecc_mul2add(<c_key.dp.base, sprime, <c_key.pubkey, t, 22676c7ba4bSJerome Forissier x1y1p, ma, ltc_key.dp.prime); 22776c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 22876c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 22976c7ba4bSJerome Forissier goto out; 23076c7ba4bSJerome Forissier } 23176c7ba4bSJerome Forissier 23276c7ba4bSJerome Forissier /* Step B7: compute R = (e' + x1') mod n and verify R == r' */ 23376c7ba4bSJerome Forissier 23476c7ba4bSJerome Forissier mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len); 23576c7ba4bSJerome Forissier ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R); 23676c7ba4bSJerome Forissier if (ltc_res != CRYPT_OK) { 23776c7ba4bSJerome Forissier res = TEE_ERROR_BAD_STATE; 23876c7ba4bSJerome Forissier goto out; 23976c7ba4bSJerome Forissier } 24076c7ba4bSJerome Forissier if (mp_cmp(R, rprime) != LTC_MP_EQ) 24176c7ba4bSJerome Forissier res = TEE_ERROR_SIGNATURE_INVALID; 24276c7ba4bSJerome Forissier out: 24376c7ba4bSJerome Forissier mp_montgomery_free(mp); 24476c7ba4bSJerome Forissier ltc_ecc_del_point(x1y1p); 245*0b38353cSJerome Forissier ecc_free(<c_key); 24676c7ba4bSJerome Forissier mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL); 24776c7ba4bSJerome Forissier return res; 24876c7ba4bSJerome Forissier } 249