xref: /optee_os/core/lib/libtomcrypt/dsa.c (revision 1ac17bb54d041c5a638904d737d960695b823afc)
1*1ac17bb5SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*1ac17bb5SJens Wiklander /*
3*1ac17bb5SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
4*1ac17bb5SJens Wiklander  */
5*1ac17bb5SJens Wiklander 
6*1ac17bb5SJens Wiklander #include <crypto/crypto.h>
7*1ac17bb5SJens Wiklander #include <stdlib.h>
8*1ac17bb5SJens Wiklander #include <string.h>
9*1ac17bb5SJens Wiklander #include <tee_api_types.h>
10*1ac17bb5SJens Wiklander #include <tee/tee_cryp_utl.h>
11*1ac17bb5SJens Wiklander #include <tomcrypt.h>
12*1ac17bb5SJens Wiklander #include <trace.h>
13*1ac17bb5SJens Wiklander #include <utee_defines.h>
14*1ac17bb5SJens Wiklander 
15*1ac17bb5SJens Wiklander #include "acipher_helpers.h"
16*1ac17bb5SJens Wiklander 
17*1ac17bb5SJens Wiklander TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s,
18*1ac17bb5SJens Wiklander 					    size_t key_size_bits __unused)
19*1ac17bb5SJens Wiklander {
20*1ac17bb5SJens Wiklander 	memset(s, 0, sizeof(*s));
21*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->g))
22*1ac17bb5SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
23*1ac17bb5SJens Wiklander 
24*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->p))
25*1ac17bb5SJens Wiklander 		goto err;
26*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->q))
27*1ac17bb5SJens Wiklander 		goto err;
28*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->y))
29*1ac17bb5SJens Wiklander 		goto err;
30*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->x))
31*1ac17bb5SJens Wiklander 		goto err;
32*1ac17bb5SJens Wiklander 	return TEE_SUCCESS;
33*1ac17bb5SJens Wiklander err:
34*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->g);
35*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->p);
36*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->q);
37*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->y);
38*1ac17bb5SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
39*1ac17bb5SJens Wiklander }
40*1ac17bb5SJens Wiklander 
41*1ac17bb5SJens Wiklander TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s,
42*1ac17bb5SJens Wiklander 					       size_t key_size_bits __unused)
43*1ac17bb5SJens Wiklander {
44*1ac17bb5SJens Wiklander 	memset(s, 0, sizeof(*s));
45*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->g))
46*1ac17bb5SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
47*1ac17bb5SJens Wiklander 
48*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->p))
49*1ac17bb5SJens Wiklander 		goto err;
50*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->q))
51*1ac17bb5SJens Wiklander 		goto err;
52*1ac17bb5SJens Wiklander 	if (!bn_alloc_max(&s->y))
53*1ac17bb5SJens Wiklander 		goto err;
54*1ac17bb5SJens Wiklander 	return TEE_SUCCESS;
55*1ac17bb5SJens Wiklander err:
56*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->g);
57*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->p);
58*1ac17bb5SJens Wiklander 	crypto_bignum_free(s->q);
59*1ac17bb5SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
60*1ac17bb5SJens Wiklander }
61*1ac17bb5SJens Wiklander 
62*1ac17bb5SJens Wiklander TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size)
63*1ac17bb5SJens Wiklander {
64*1ac17bb5SJens Wiklander 	TEE_Result res;
65*1ac17bb5SJens Wiklander 	dsa_key ltc_tmp_key;
66*1ac17bb5SJens Wiklander 	size_t group_size, modulus_size = key_size/8;
67*1ac17bb5SJens Wiklander 	int ltc_res;
68*1ac17bb5SJens Wiklander 
69*1ac17bb5SJens Wiklander 	if (modulus_size <= 128)
70*1ac17bb5SJens Wiklander 		group_size = 20;
71*1ac17bb5SJens Wiklander 	else if (modulus_size <= 256)
72*1ac17bb5SJens Wiklander 		group_size = 30;
73*1ac17bb5SJens Wiklander 	else if (modulus_size <= 384)
74*1ac17bb5SJens Wiklander 		group_size = 35;
75*1ac17bb5SJens Wiklander 	else
76*1ac17bb5SJens Wiklander 		group_size = 40;
77*1ac17bb5SJens Wiklander 
78*1ac17bb5SJens Wiklander 	/* Generate the DSA key */
79*1ac17bb5SJens Wiklander 	ltc_res = dsa_make_key(NULL, find_prng("prng_mpa"), group_size,
80*1ac17bb5SJens Wiklander 			       modulus_size, &ltc_tmp_key);
81*1ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
82*1ac17bb5SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
83*1ac17bb5SJens Wiklander 	} else if ((size_t)mp_count_bits(ltc_tmp_key.p) != key_size) {
84*1ac17bb5SJens Wiklander 		dsa_free(&ltc_tmp_key);
85*1ac17bb5SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
86*1ac17bb5SJens Wiklander 	} else {
87*1ac17bb5SJens Wiklander 		/* Copy the key */
88*1ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.g, key->g);
89*1ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.p, key->p);
90*1ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.q, key->q);
91*1ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.y, key->y);
92*1ac17bb5SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.x, key->x);
93*1ac17bb5SJens Wiklander 
94*1ac17bb5SJens Wiklander 		/* Free the tempory key */
95*1ac17bb5SJens Wiklander 		dsa_free(&ltc_tmp_key);
96*1ac17bb5SJens Wiklander 		res = TEE_SUCCESS;
97*1ac17bb5SJens Wiklander 	}
98*1ac17bb5SJens Wiklander 	return res;
99*1ac17bb5SJens Wiklander }
100*1ac17bb5SJens Wiklander 
101*1ac17bb5SJens Wiklander TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key,
102*1ac17bb5SJens Wiklander 				   const uint8_t *msg, size_t msg_len,
103*1ac17bb5SJens Wiklander 				   uint8_t *sig, size_t *sig_len)
104*1ac17bb5SJens Wiklander {
105*1ac17bb5SJens Wiklander 	TEE_Result res;
106*1ac17bb5SJens Wiklander 	size_t hash_size;
107*1ac17bb5SJens Wiklander 	int ltc_res;
108*1ac17bb5SJens Wiklander 	void *r, *s;
109*1ac17bb5SJens Wiklander 	dsa_key ltc_key = {
110*1ac17bb5SJens Wiklander 		.type = PK_PRIVATE,
111*1ac17bb5SJens Wiklander 		.qord = mp_unsigned_bin_size(key->g),
112*1ac17bb5SJens Wiklander 		.g = key->g,
113*1ac17bb5SJens Wiklander 		.p = key->p,
114*1ac17bb5SJens Wiklander 		.q = key->q,
115*1ac17bb5SJens Wiklander 		.y = key->y,
116*1ac17bb5SJens Wiklander 		.x = key->x,
117*1ac17bb5SJens Wiklander 	};
118*1ac17bb5SJens Wiklander 
119*1ac17bb5SJens Wiklander 	if (algo != TEE_ALG_DSA_SHA1 &&
120*1ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA224 &&
121*1ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA256) {
122*1ac17bb5SJens Wiklander 		res = TEE_ERROR_NOT_IMPLEMENTED;
123*1ac17bb5SJens Wiklander 		goto err;
124*1ac17bb5SJens Wiklander 	}
125*1ac17bb5SJens Wiklander 
126*1ac17bb5SJens Wiklander 	res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
127*1ac17bb5SJens Wiklander 				       &hash_size);
128*1ac17bb5SJens Wiklander 	if (res != TEE_SUCCESS)
129*1ac17bb5SJens Wiklander 		goto err;
130*1ac17bb5SJens Wiklander 	if (mp_unsigned_bin_size(ltc_key.q) < hash_size)
131*1ac17bb5SJens Wiklander 		hash_size = mp_unsigned_bin_size(ltc_key.q);
132*1ac17bb5SJens Wiklander 	if (msg_len != hash_size) {
133*1ac17bb5SJens Wiklander 		res = TEE_ERROR_SECURITY;
134*1ac17bb5SJens Wiklander 		goto err;
135*1ac17bb5SJens Wiklander 	}
136*1ac17bb5SJens Wiklander 
137*1ac17bb5SJens Wiklander 	if (*sig_len < 2 * mp_unsigned_bin_size(ltc_key.q)) {
138*1ac17bb5SJens Wiklander 		*sig_len = 2 * mp_unsigned_bin_size(ltc_key.q);
139*1ac17bb5SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
140*1ac17bb5SJens Wiklander 		goto err;
141*1ac17bb5SJens Wiklander 	}
142*1ac17bb5SJens Wiklander 
143*1ac17bb5SJens Wiklander 	ltc_res = mp_init_multi(&r, &s, NULL);
144*1ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
145*1ac17bb5SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
146*1ac17bb5SJens Wiklander 		goto err;
147*1ac17bb5SJens Wiklander 	}
148*1ac17bb5SJens Wiklander 
149*1ac17bb5SJens Wiklander 	ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, NULL,
150*1ac17bb5SJens Wiklander 				    find_prng("prng_mpa"), &ltc_key);
151*1ac17bb5SJens Wiklander 
152*1ac17bb5SJens Wiklander 	if (ltc_res == CRYPT_OK) {
153*1ac17bb5SJens Wiklander 		*sig_len = 2 * mp_unsigned_bin_size(ltc_key.q);
154*1ac17bb5SJens Wiklander 		memset(sig, 0, *sig_len);
155*1ac17bb5SJens Wiklander 		mp_to_unsigned_bin(r, (uint8_t *)sig + *sig_len/2 -
156*1ac17bb5SJens Wiklander 				   mp_unsigned_bin_size(r));
157*1ac17bb5SJens Wiklander 		mp_to_unsigned_bin(s, (uint8_t *)sig + *sig_len -
158*1ac17bb5SJens Wiklander 				   mp_unsigned_bin_size(s));
159*1ac17bb5SJens Wiklander 		res = TEE_SUCCESS;
160*1ac17bb5SJens Wiklander 	} else {
161*1ac17bb5SJens Wiklander 		res = TEE_ERROR_GENERIC;
162*1ac17bb5SJens Wiklander 	}
163*1ac17bb5SJens Wiklander 
164*1ac17bb5SJens Wiklander 	mp_clear_multi(r, s, NULL);
165*1ac17bb5SJens Wiklander 
166*1ac17bb5SJens Wiklander err:
167*1ac17bb5SJens Wiklander 	return res;
168*1ac17bb5SJens Wiklander }
169*1ac17bb5SJens Wiklander 
170*1ac17bb5SJens Wiklander TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key,
171*1ac17bb5SJens Wiklander 				     const uint8_t *msg, size_t msg_len,
172*1ac17bb5SJens Wiklander 				     const uint8_t *sig, size_t sig_len)
173*1ac17bb5SJens Wiklander {
174*1ac17bb5SJens Wiklander 	TEE_Result res;
175*1ac17bb5SJens Wiklander 	int ltc_stat, ltc_res;
176*1ac17bb5SJens Wiklander 	void *r, *s;
177*1ac17bb5SJens Wiklander 	dsa_key ltc_key = {
178*1ac17bb5SJens Wiklander 		.type = PK_PUBLIC,
179*1ac17bb5SJens Wiklander 		.qord = mp_unsigned_bin_size(key->g),
180*1ac17bb5SJens Wiklander 		.g = key->g,
181*1ac17bb5SJens Wiklander 		.p = key->p,
182*1ac17bb5SJens Wiklander 		.q = key->q,
183*1ac17bb5SJens Wiklander 		.y = key->y
184*1ac17bb5SJens Wiklander 	};
185*1ac17bb5SJens Wiklander 
186*1ac17bb5SJens Wiklander 	if (algo != TEE_ALG_DSA_SHA1 &&
187*1ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA224 &&
188*1ac17bb5SJens Wiklander 	    algo != TEE_ALG_DSA_SHA256) {
189*1ac17bb5SJens Wiklander 		res = TEE_ERROR_NOT_IMPLEMENTED;
190*1ac17bb5SJens Wiklander 		goto err;
191*1ac17bb5SJens Wiklander 	}
192*1ac17bb5SJens Wiklander 
193*1ac17bb5SJens Wiklander 	ltc_res = mp_init_multi(&r, &s, NULL);
194*1ac17bb5SJens Wiklander 	if (ltc_res != CRYPT_OK) {
195*1ac17bb5SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
196*1ac17bb5SJens Wiklander 		goto err;
197*1ac17bb5SJens Wiklander 	}
198*1ac17bb5SJens Wiklander 	mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2);
199*1ac17bb5SJens Wiklander 	mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2);
200*1ac17bb5SJens Wiklander 	ltc_res = dsa_verify_hash_raw(r, s, msg, msg_len, &ltc_stat, &ltc_key);
201*1ac17bb5SJens Wiklander 	mp_clear_multi(r, s, NULL);
202*1ac17bb5SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, ltc_stat);
203*1ac17bb5SJens Wiklander err:
204*1ac17bb5SJens Wiklander 	return res;
205*1ac17bb5SJens Wiklander }
206