| // SPDX-License-Identifier: BSD-2-Clause |
| /* |
| * Copyright (C) 2018, ARM Limited |
| * Copyright (C) 2019, Linaro Limited |
| */ |
| |
| #include <assert.h> |
| #include <crypto/crypto.h> |
| #include <mbedtls/ctr_drbg.h> |
| #include <mbedtls/entropy.h> |
| #include <mbedtls/dhm.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "mbd_rand.h" |
| |
| TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, |
| size_t key_size_bits) |
| { |
| memset(s, 0, sizeof(*s)); |
| s->g = crypto_bignum_allocate(key_size_bits); |
| if (!s->g) |
| goto err; |
| s->p = crypto_bignum_allocate(key_size_bits); |
| if (!s->p) |
| goto err; |
| s->y = crypto_bignum_allocate(key_size_bits); |
| if (!s->y) |
| goto err; |
| s->x = crypto_bignum_allocate(key_size_bits); |
| if (!s->x) |
| goto err; |
| s->q = crypto_bignum_allocate(key_size_bits); |
| if (!s->q) |
| goto err; |
| return TEE_SUCCESS; |
| err: |
| crypto_bignum_free(s->g); |
| crypto_bignum_free(s->p); |
| crypto_bignum_free(s->y); |
| crypto_bignum_free(s->x); |
| return TEE_ERROR_OUT_OF_MEMORY; |
| } |
| |
| TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, |
| struct bignum *q __unused, |
| size_t xbits) |
| { |
| TEE_Result res = TEE_SUCCESS; |
| int lmd_res = 0; |
| mbedtls_dhm_context dhm; |
| unsigned char *buf = NULL; |
| |
| memset(&dhm, 0, sizeof(dhm)); |
| mbedtls_dhm_init(&dhm); |
| |
| dhm.G = *(mbedtls_mpi *)key->g; |
| dhm.P = *(mbedtls_mpi *)key->p; |
| |
| dhm.len = crypto_bignum_num_bytes(key->p); |
| |
| if (xbits == 0) |
| xbits = dhm.len; |
| else |
| xbits = xbits / 8; |
| |
| buf = malloc(dhm.len); |
| if (!buf) { |
| res = TEE_ERROR_OUT_OF_MEMORY; |
| goto out; |
| } |
| lmd_res = mbedtls_dhm_make_public(&dhm, (int)xbits, buf, |
| dhm.len, mbd_rand, NULL); |
| if (lmd_res != 0) { |
| FMSG("mbedtls_dhm_make_public err, return is 0x%x", -lmd_res); |
| res = TEE_ERROR_BAD_PARAMETERS; |
| } else { |
| crypto_bignum_bin2bn(buf, xbits / 8, key->y); |
| crypto_bignum_copy(key->x, (void *)&dhm.X); |
| res = TEE_SUCCESS; |
| } |
| out: |
| free(buf); |
| /* Reset mpi to skip freeing here, those mpis will be freed with key */ |
| mbedtls_mpi_init(&dhm.G); |
| mbedtls_mpi_init(&dhm.P); |
| mbedtls_dhm_free(&dhm); |
| return res; |
| } |
| |
| TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, |
| struct bignum *public_key, |
| struct bignum *secret) |
| { |
| TEE_Result res = TEE_SUCCESS; |
| int lmd_res = 0; |
| mbedtls_dhm_context dhm; |
| unsigned char *buf = NULL; |
| size_t olen = 0; |
| |
| memset(&dhm, 0, sizeof(dhm)); |
| mbedtls_dhm_init(&dhm); |
| |
| dhm.G = *(mbedtls_mpi *)private_key->g; |
| dhm.P = *(mbedtls_mpi *)private_key->p; |
| dhm.GX = *(mbedtls_mpi *)private_key->y; |
| dhm.X = *(mbedtls_mpi *)private_key->x; |
| dhm.GY = *(mbedtls_mpi *)public_key; |
| |
| dhm.len = crypto_bignum_num_bytes(private_key->p); |
| |
| buf = malloc(dhm.len); |
| if (!buf) { |
| res = TEE_ERROR_OUT_OF_MEMORY; |
| goto out; |
| } |
| |
| lmd_res = mbedtls_dhm_calc_secret(&dhm, buf, dhm.len, |
| &olen, mbd_rand, NULL); |
| if (lmd_res != 0) { |
| FMSG("mbedtls_dhm_calc_secret failed, ret is 0x%x", -lmd_res); |
| res = TEE_ERROR_BAD_PARAMETERS; |
| } else { |
| crypto_bignum_bin2bn(buf, olen, secret); |
| res = TEE_SUCCESS; |
| } |
| out: |
| free(buf); |
| /* Reset mpi to skip freeing here, those mpis will be freed with key */ |
| mbedtls_mpi_init(&dhm.G); |
| mbedtls_mpi_init(&dhm.P); |
| mbedtls_mpi_init(&dhm.GX); |
| mbedtls_mpi_init(&dhm.X); |
| mbedtls_mpi_init(&dhm.GY); |
| mbedtls_dhm_free(&dhm); |
| return res; |
| } |