xref: /optee_os/core/lib/libtomcrypt/dsa.c (revision 1f3b11151257f0984bf32070f56b542e58b788a0)
11ac17bb5SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
21ac17bb5SJens Wiklander /*
31ac17bb5SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
41ac17bb5SJens Wiklander  */
51ac17bb5SJens Wiklander 
61ac17bb5SJens Wiklander #include <crypto/crypto.h>
71ac17bb5SJens Wiklander #include <stdlib.h>
81ac17bb5SJens Wiklander #include <string.h>
91ac17bb5SJens Wiklander #include <tee_api_types.h>
101ac17bb5SJens Wiklander #include <tee/tee_cryp_utl.h>
111ac17bb5SJens Wiklander #include <tomcrypt.h>
121ac17bb5SJens Wiklander #include <trace.h>
131ac17bb5SJens Wiklander #include <utee_defines.h>
141ac17bb5SJens Wiklander 
151ac17bb5SJens Wiklander #include "acipher_helpers.h"
161ac17bb5SJens Wiklander 
171ac17bb5SJens Wiklander TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s,
181ac17bb5SJens Wiklander 					    size_t key_size_bits __unused)
191ac17bb5SJens Wiklander {
201ac17bb5SJens Wiklander 	memset(s, 0, sizeof(*s));
211ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->g))
221ac17bb5SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
231ac17bb5SJens Wiklander 
241ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->p))
251ac17bb5SJens Wiklander 		goto err;
261ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->q))
271ac17bb5SJens Wiklander 		goto err;
281ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->y))
291ac17bb5SJens Wiklander 		goto err;
301ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->x))
311ac17bb5SJens Wiklander 		goto err;
321ac17bb5SJens Wiklander 	return TEE_SUCCESS;
331ac17bb5SJens Wiklander err:
341ac17bb5SJens Wiklander 	crypto_bignum_free(s->g);
351ac17bb5SJens Wiklander 	crypto_bignum_free(s->p);
361ac17bb5SJens Wiklander 	crypto_bignum_free(s->q);
371ac17bb5SJens Wiklander 	crypto_bignum_free(s->y);
381ac17bb5SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
391ac17bb5SJens Wiklander }
401ac17bb5SJens Wiklander 
411ac17bb5SJens Wiklander TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s,
421ac17bb5SJens Wiklander 					       size_t key_size_bits __unused)
431ac17bb5SJens Wiklander {
441ac17bb5SJens Wiklander 	memset(s, 0, sizeof(*s));
451ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->g))
461ac17bb5SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
471ac17bb5SJens Wiklander 
481ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->p))
491ac17bb5SJens Wiklander 		goto err;
501ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->q))
511ac17bb5SJens Wiklander 		goto err;
521ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->y))
531ac17bb5SJens Wiklander 		goto err;
541ac17bb5SJens Wiklander 	return TEE_SUCCESS;
551ac17bb5SJens Wiklander err:
561ac17bb5SJens Wiklander 	crypto_bignum_free(s->g);
571ac17bb5SJens Wiklander 	crypto_bignum_free(s->p);
581ac17bb5SJens Wiklander 	crypto_bignum_free(s->q);
591ac17bb5SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
601ac17bb5SJens Wiklander }
611ac17bb5SJens Wiklander 
621ac17bb5SJens Wiklander TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size)
631ac17bb5SJens Wiklander {
641ac17bb5SJens Wiklander 	TEE_Result res;
651ac17bb5SJens Wiklander 	dsa_key ltc_tmp_key;
661ac17bb5SJens Wiklander 	size_t group_size, modulus_size = key_size/8;
671ac17bb5SJens Wiklander 	int ltc_res;
681ac17bb5SJens Wiklander 
691ac17bb5SJens Wiklander 	if (modulus_size <= 128)
701ac17bb5SJens Wiklander 		group_size = 20;
711ac17bb5SJens Wiklander 	else if (modulus_size <= 256)
721ac17bb5SJens Wiklander 		group_size = 30;
731ac17bb5SJens Wiklander 	else if (modulus_size <= 384)
741ac17bb5SJens Wiklander 		group_size = 35;
751ac17bb5SJens Wiklander 	else
761ac17bb5SJens Wiklander 		group_size = 40;
771ac17bb5SJens Wiklander 
781ac17bb5SJens Wiklander 	/* Generate the DSA key */
79*1f3b1115SJens Wiklander 	ltc_res = dsa_make_key(NULL, find_prng("prng_crypto"), group_size,
801ac17bb5SJens Wiklander 			       modulus_size, &ltc_tmp_key);
811ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
821ac17bb5SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
831ac17bb5SJens Wiklander 	} else if ((size_t)mp_count_bits(ltc_tmp_key.p) != key_size) {
841ac17bb5SJens Wiklander 		dsa_free(&ltc_tmp_key);
851ac17bb5SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
861ac17bb5SJens Wiklander 	} else {
871ac17bb5SJens Wiklander 		/* Copy the key */
881ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.g, key->g);
891ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.p, key->p);
901ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.q, key->q);
911ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.y, key->y);
921ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.x, key->x);
931ac17bb5SJens Wiklander 
941ac17bb5SJens Wiklander 		/* Free the tempory key */
951ac17bb5SJens Wiklander 		dsa_free(&ltc_tmp_key);
961ac17bb5SJens Wiklander 		res = TEE_SUCCESS;
971ac17bb5SJens Wiklander 	}
981ac17bb5SJens Wiklander 	return res;
991ac17bb5SJens Wiklander }
1001ac17bb5SJens Wiklander 
1011ac17bb5SJens Wiklander TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key,
1021ac17bb5SJens Wiklander 				   const uint8_t *msg, size_t msg_len,
1031ac17bb5SJens Wiklander 				   uint8_t *sig, size_t *sig_len)
1041ac17bb5SJens Wiklander {
1051ac17bb5SJens Wiklander 	TEE_Result res;
1061ac17bb5SJens Wiklander 	size_t hash_size;
1071ac17bb5SJens Wiklander 	int ltc_res;
1081ac17bb5SJens Wiklander 	void *r, *s;
1091ac17bb5SJens Wiklander 	dsa_key ltc_key = {
1101ac17bb5SJens Wiklander 		.type = PK_PRIVATE,
1111ac17bb5SJens Wiklander 		.qord = mp_unsigned_bin_size(key->g),
1121ac17bb5SJens Wiklander 		.g = key->g,
1131ac17bb5SJens Wiklander 		.p = key->p,
1141ac17bb5SJens Wiklander 		.q = key->q,
1151ac17bb5SJens Wiklander 		.y = key->y,
1161ac17bb5SJens Wiklander 		.x = key->x,
1171ac17bb5SJens Wiklander 	};
1181ac17bb5SJens Wiklander 
1191ac17bb5SJens Wiklander 	if (algo != TEE_ALG_DSA_SHA1 &&
1201ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA224 &&
1211ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA256) {
1221ac17bb5SJens Wiklander 		res = TEE_ERROR_NOT_IMPLEMENTED;
1231ac17bb5SJens Wiklander 		goto err;
1241ac17bb5SJens Wiklander 	}
1251ac17bb5SJens Wiklander 
1261ac17bb5SJens Wiklander 	res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
1271ac17bb5SJens Wiklander 				       &hash_size);
1281ac17bb5SJens Wiklander 	if (res != TEE_SUCCESS)
1291ac17bb5SJens Wiklander 		goto err;
1301ac17bb5SJens Wiklander 	if (mp_unsigned_bin_size(ltc_key.q) < hash_size)
1311ac17bb5SJens Wiklander 		hash_size = mp_unsigned_bin_size(ltc_key.q);
1321ac17bb5SJens Wiklander 	if (msg_len != hash_size) {
1331ac17bb5SJens Wiklander 		res = TEE_ERROR_SECURITY;
1341ac17bb5SJens Wiklander 		goto err;
1351ac17bb5SJens Wiklander 	}
1361ac17bb5SJens Wiklander 
1371ac17bb5SJens Wiklander 	if (*sig_len < 2 * mp_unsigned_bin_size(ltc_key.q)) {
1381ac17bb5SJens Wiklander 		*sig_len = 2 * mp_unsigned_bin_size(ltc_key.q);
1391ac17bb5SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
1401ac17bb5SJens Wiklander 		goto err;
1411ac17bb5SJens Wiklander 	}
1421ac17bb5SJens Wiklander 
1431ac17bb5SJens Wiklander 	ltc_res = mp_init_multi(&r, &s, NULL);
1441ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
1451ac17bb5SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
1461ac17bb5SJens Wiklander 		goto err;
1471ac17bb5SJens Wiklander 	}
1481ac17bb5SJens Wiklander 
1491ac17bb5SJens Wiklander 	ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, NULL,
150*1f3b1115SJens Wiklander 				    find_prng("prng_crypto"), &ltc_key);
1511ac17bb5SJens Wiklander 
1521ac17bb5SJens Wiklander 	if (ltc_res == CRYPT_OK) {
1531ac17bb5SJens Wiklander 		*sig_len = 2 * mp_unsigned_bin_size(ltc_key.q);
1541ac17bb5SJens Wiklander 		memset(sig, 0, *sig_len);
1551ac17bb5SJens Wiklander 		mp_to_unsigned_bin(r, (uint8_t *)sig + *sig_len/2 -
1561ac17bb5SJens Wiklander 				   mp_unsigned_bin_size(r));
1571ac17bb5SJens Wiklander 		mp_to_unsigned_bin(s, (uint8_t *)sig + *sig_len -
1581ac17bb5SJens Wiklander 				   mp_unsigned_bin_size(s));
1591ac17bb5SJens Wiklander 		res = TEE_SUCCESS;
1601ac17bb5SJens Wiklander 	} else {
1611ac17bb5SJens Wiklander 		res = TEE_ERROR_GENERIC;
1621ac17bb5SJens Wiklander 	}
1631ac17bb5SJens Wiklander 
1641ac17bb5SJens Wiklander 	mp_clear_multi(r, s, NULL);
1651ac17bb5SJens Wiklander 
1661ac17bb5SJens Wiklander err:
1671ac17bb5SJens Wiklander 	return res;
1681ac17bb5SJens Wiklander }
1691ac17bb5SJens Wiklander 
1701ac17bb5SJens Wiklander TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key,
1711ac17bb5SJens Wiklander 				     const uint8_t *msg, size_t msg_len,
1721ac17bb5SJens Wiklander 				     const uint8_t *sig, size_t sig_len)
1731ac17bb5SJens Wiklander {
1741ac17bb5SJens Wiklander 	TEE_Result res;
1751ac17bb5SJens Wiklander 	int ltc_stat, ltc_res;
1761ac17bb5SJens Wiklander 	void *r, *s;
1771ac17bb5SJens Wiklander 	dsa_key ltc_key = {
1781ac17bb5SJens Wiklander 		.type = PK_PUBLIC,
1791ac17bb5SJens Wiklander 		.qord = mp_unsigned_bin_size(key->g),
1801ac17bb5SJens Wiklander 		.g = key->g,
1811ac17bb5SJens Wiklander 		.p = key->p,
1821ac17bb5SJens Wiklander 		.q = key->q,
1831ac17bb5SJens Wiklander 		.y = key->y
1841ac17bb5SJens Wiklander 	};
1851ac17bb5SJens Wiklander 
1861ac17bb5SJens Wiklander 	if (algo != TEE_ALG_DSA_SHA1 &&
1871ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA224 &&
1881ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA256) {
1891ac17bb5SJens Wiklander 		res = TEE_ERROR_NOT_IMPLEMENTED;
1901ac17bb5SJens Wiklander 		goto err;
1911ac17bb5SJens Wiklander 	}
1921ac17bb5SJens Wiklander 
1931ac17bb5SJens Wiklander 	ltc_res = mp_init_multi(&r, &s, NULL);
1941ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
1951ac17bb5SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
1961ac17bb5SJens Wiklander 		goto err;
1971ac17bb5SJens Wiklander 	}
1981ac17bb5SJens Wiklander 	mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2);
1991ac17bb5SJens Wiklander 	mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2);
2001ac17bb5SJens Wiklander 	ltc_res = dsa_verify_hash_raw(r, s, msg, msg_len, &ltc_stat, &ltc_key);
2011ac17bb5SJens Wiklander 	mp_clear_multi(r, s, NULL);
2021ac17bb5SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
2031ac17bb5SJens Wiklander err:
2041ac17bb5SJens Wiklander 	return res;
2051ac17bb5SJens Wiklander }
206