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, <c_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(<c_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(<c_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"), <c_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, <c_stat, <c_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