blob: 47c996779a715a5259b4e5f99abb4a6af9c967dc [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2019 Huawei Technologies Co., Ltd
*/
#include <crypto/crypto.h>
#include <stdlib.h>
#include <string.h>
#include <tee_api_types.h>
#include <util.h>
#include <utee_defines.h>
#include "acipher_helpers.h"
/*
* GM/T 0003.1‒2012 Part1 2 Section 6.1
*/
TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo,
struct ecc_keypair *key,
const uint8_t *msg, size_t msg_len,
uint8_t *sig, size_t *sig_len)
{
TEE_Result res = TEE_SUCCESS;
ecc_point *x1y1p = NULL;
ecc_key ltc_key = { };
int ltc_res = 0;
void *k = NULL;
void *e = NULL;
void *r = NULL;
void *s = NULL;
void *tmp = NULL;
if (*sig_len < 64) {
*sig_len = 64;
return TEE_ERROR_SHORT_BUFFER;
}
ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL);
if (ltc_res != CRYPT_OK)
return TEE_ERROR_OUT_OF_MEMORY;
x1y1p = ltc_ecc_new_point();
if (!x1y1p) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
res = ecc_populate_ltc_private_key(&ltc_key, key, algo, NULL);
if (res)
goto out;
/*
* Steps A1 and A2 are the generation of the hash value e from user
* information (ZA) and the message to be signed (M). There are not done
* here since @msg is expected to be the hash value e already.
*/
/* Step A3: generate random number 1 <= k < n */
A3:
ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL,
find_prng("prng_crypto"));
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
/* Step A4: compute (x1, y1) = [k]G */
ltc_res = ltc_ecc_mulmod(k, &ltc_key.dp.base, x1y1p, ltc_key.dp.A,
ltc_key.dp.prime, 1);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
/* Step A5: compute r = (e + x1) mod n */
mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len);
ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_add(r, k, tmp);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
if (mp_cmp_d(r, 0) == LTC_MP_EQ ||
mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ)
goto A3;
/* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */
ltc_res = mp_add_d(ltc_key.k, 1, s);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_invmod(s, ltc_key.dp.order, s);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_mul(r, ltc_key.k, tmp);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_sub(k, tmp, tmp);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
/* Step A7: convert (r, s) to binary for output */
memset(sig, 0, 64);
mp_to_unsigned_bin(r, sig);
mp_to_unsigned_bin(s, sig + 32);
*sig_len = 64;
out:
ecc_free(&ltc_key);
ltc_ecc_del_point(x1y1p);
mp_clear_multi(k, e, r, s, tmp, NULL);
return res;
}
/*
* GM/T 0003.1‒2012 Part1 2 Section 7.1
*/
TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo,
struct ecc_public_key *key,
const uint8_t *msg, size_t msg_len,
const uint8_t *sig, size_t sig_len)
{
TEE_Result res = TEE_SUCCESS;
ecc_key ltc_key = { };
int ltc_res = 0;
void *rprime = NULL;
void *sprime = NULL;
void *t = NULL;
void *mp = NULL;
void *mu = NULL;
void *ma = NULL;
void *eprime = NULL;
void *R = NULL;
ecc_point *x1y1p = NULL;
if (sig_len != 64)
return TEE_ERROR_BAD_PARAMETERS;
ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R,
NULL);
if (ltc_res != CRYPT_OK)
return TEE_ERROR_OUT_OF_MEMORY;
mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32);
mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32);
res = ecc_populate_ltc_public_key(&ltc_key, key, algo, NULL);
if (res)
goto out;
/* Step B1: verify r' in [1, n - 1] */
if (mp_cmp_d(rprime, 1) == LTC_MP_LT ||
mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) {
res = TEE_ERROR_SIGNATURE_INVALID;
goto out;
}
/* Step B2: verify s' in [1, n - 1] */
if (mp_cmp_d(sprime, 1) == LTC_MP_LT ||
mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) {
res = TEE_ERROR_SIGNATURE_INVALID;
goto out;
}
/*
* Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here
* because @msg is supposed to contain the hash value e' already.
*/
/* Step B5: t = (r' + s') mod n and check t != 0 */
ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
if (mp_cmp_d(t, 0) == LTC_MP_EQ) {
res = TEE_ERROR_SIGNATURE_INVALID;
goto out;
}
/* Step B6: (x1', y1') = [s']G + [t]PA */
x1y1p = ltc_ecc_new_point();
if (!x1y1p) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
ltc_res = ltc_ecc_mul2add(&ltc_key.dp.base, sprime, &ltc_key.pubkey, t,
x1y1p, ma, ltc_key.dp.prime);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
/* Step B7: compute R = (e' + x1') mod n and verify R == r' */
mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len);
ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R);
if (ltc_res != CRYPT_OK) {
res = TEE_ERROR_BAD_STATE;
goto out;
}
if (mp_cmp(R, rprime) != LTC_MP_EQ)
res = TEE_ERROR_SIGNATURE_INVALID;
out:
mp_montgomery_free(mp);
ltc_ecc_del_point(x1y1p);
ecc_free(&ltc_key);
mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL);
return res;
}