1/* 2 * PSA FFDH layer on top of Mbed TLS crypto 3 */ 4/* 5 * Copyright The Mbed TLS Contributors 6 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7 */ 8 9#include "common.h" 10 11#if defined(MBEDTLS_PSA_CRYPTO_C) 12 13/* This header is only needed because it defines 14 * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in 15 * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module 16 * only uses bignum functions for arithmetic. */ 17#include <mbedtls/dhm.h> 18 19#include <psa/crypto.h> 20#include "psa_crypto_core.h" 21#include "psa_crypto_ffdh.h" 22#include "psa_crypto_random_impl.h" 23#include "mbedtls/platform.h" 24#include "mbedtls/error.h" 25 26#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ 27 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ 28 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ 29 defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) 30static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, 31 mbedtls_mpi *P, 32 mbedtls_mpi *G) 33{ 34 const unsigned char *dhm_P = NULL; 35 const unsigned char *dhm_G = NULL; 36 size_t dhm_size_P = 0; 37 size_t dhm_size_G = 0; 38 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 39 40 if (P == NULL && G == NULL) { 41 return PSA_ERROR_INVALID_ARGUMENT; 42 } 43 44#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) 45 static const unsigned char dhm_P_2048[] = 46 MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; 47 static const unsigned char dhm_G_2048[] = 48 MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; 49#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ 50#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) 51 static const unsigned char dhm_P_3072[] = 52 MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; 53 static const unsigned char dhm_G_3072[] = 54 MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; 55#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ 56#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) 57 static const unsigned char dhm_P_4096[] = 58 MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; 59 static const unsigned char dhm_G_4096[] = 60 MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; 61#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ 62#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) 63 static const unsigned char dhm_P_6144[] = 64 MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; 65 static const unsigned char dhm_G_6144[] = 66 MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; 67#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ 68#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) 69 static const unsigned char dhm_P_8192[] = 70 MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; 71 static const unsigned char dhm_G_8192[] = 72 MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; 73#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ 74 75 switch (key_size) { 76#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) 77 case sizeof(dhm_P_2048): 78 dhm_P = dhm_P_2048; 79 dhm_G = dhm_G_2048; 80 dhm_size_P = sizeof(dhm_P_2048); 81 dhm_size_G = sizeof(dhm_G_2048); 82 break; 83#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ 84#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) 85 case sizeof(dhm_P_3072): 86 dhm_P = dhm_P_3072; 87 dhm_G = dhm_G_3072; 88 dhm_size_P = sizeof(dhm_P_3072); 89 dhm_size_G = sizeof(dhm_G_3072); 90 break; 91#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ 92#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) 93 case sizeof(dhm_P_4096): 94 dhm_P = dhm_P_4096; 95 dhm_G = dhm_G_4096; 96 dhm_size_P = sizeof(dhm_P_4096); 97 dhm_size_G = sizeof(dhm_G_4096); 98 break; 99#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ 100#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) 101 case sizeof(dhm_P_6144): 102 dhm_P = dhm_P_6144; 103 dhm_G = dhm_G_6144; 104 dhm_size_P = sizeof(dhm_P_6144); 105 dhm_size_G = sizeof(dhm_G_6144); 106 break; 107#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ 108#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) 109 case sizeof(dhm_P_8192): 110 dhm_P = dhm_P_8192; 111 dhm_G = dhm_G_8192; 112 dhm_size_P = sizeof(dhm_P_8192); 113 dhm_size_G = sizeof(dhm_G_8192); 114 break; 115#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ 116 default: 117 return PSA_ERROR_INVALID_ARGUMENT; 118 } 119 120 if (P != NULL) { 121 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, 122 dhm_size_P)); 123 } 124 if (G != NULL) { 125 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, 126 dhm_size_G)); 127 } 128 129cleanup: 130 if (ret != 0) { 131 return mbedtls_to_psa_error(ret); 132 } 133 134 return PSA_SUCCESS; 135} 136#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || 137 MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || 138 MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || 139 MBEDTLS_PSA_BUILTIN_ALG_FFDH */ 140 141#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ 142 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) 143psa_status_t mbedtls_psa_ffdh_export_public_key( 144 const psa_key_attributes_t *attributes, 145 const uint8_t *key_buffer, 146 size_t key_buffer_size, 147 uint8_t *data, 148 size_t data_size, 149 size_t *data_length) 150{ 151 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 152 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 153 mbedtls_mpi GX, G, X, P; 154 psa_key_type_t type = attributes->type; 155 156 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { 157 if (key_buffer_size > data_size) { 158 return PSA_ERROR_BUFFER_TOO_SMALL; 159 } 160 memcpy(data, key_buffer, key_buffer_size); 161 memset(data + key_buffer_size, 0, 162 data_size - key_buffer_size); 163 *data_length = key_buffer_size; 164 return PSA_SUCCESS; 165 } 166 167 mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); 168 mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); 169 170 size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); 171 172 status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); 173 174 if (status != PSA_SUCCESS) { 175 goto cleanup; 176 } 177 178 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, 179 key_buffer_size)); 180 181 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); 182 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); 183 184 *data_length = key_len; 185 186 ret = 0; 187cleanup: 188 mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); 189 mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); 190 191 if (status == PSA_SUCCESS && ret != 0) { 192 status = mbedtls_to_psa_error(ret); 193 } 194 195 return status; 196} 197#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || 198 MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ 199 200#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) 201psa_status_t mbedtls_psa_ffdh_generate_key( 202 const psa_key_attributes_t *attributes, 203 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) 204{ 205 mbedtls_mpi X, P; 206 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 207 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 208 mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); 209 (void) attributes; 210 211 status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); 212 213 if (status != PSA_SUCCESS) { 214 goto cleanup; 215 } 216 217 /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their 218 secret exponent from the range [2, P-2]. 219 Select random value in range [3, P-1] and decrease it by 1. */ 220 MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, 221 MBEDTLS_PSA_RANDOM_STATE)); 222 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); 223 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); 224 *key_buffer_length = key_buffer_size; 225 226cleanup: 227 mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); 228 if (status == PSA_SUCCESS && ret != 0) { 229 return mbedtls_to_psa_error(ret); 230 } 231 232 return status; 233} 234#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */ 235 236#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) 237psa_status_t mbedtls_psa_ffdh_import_key( 238 const psa_key_attributes_t *attributes, 239 const uint8_t *data, size_t data_length, 240 uint8_t *key_buffer, size_t key_buffer_size, 241 size_t *key_buffer_length, size_t *bits) 242{ 243 (void) attributes; 244 245 if (key_buffer_size < data_length) { 246 return PSA_ERROR_BUFFER_TOO_SMALL; 247 } 248 memcpy(key_buffer, data, data_length); 249 *key_buffer_length = data_length; 250 *bits = PSA_BYTES_TO_BITS(data_length); 251 252 return PSA_SUCCESS; 253} 254#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */ 255 256#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) 257psa_status_t mbedtls_psa_ffdh_key_agreement( 258 const psa_key_attributes_t *attributes, 259 const uint8_t *peer_key, 260 size_t peer_key_length, 261 const uint8_t *key_buffer, 262 size_t key_buffer_size, 263 uint8_t *shared_secret, 264 size_t shared_secret_size, 265 size_t *shared_secret_length) 266{ 267 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 268 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 269 mbedtls_mpi P, G, X, GY, K; 270 const size_t calculated_shared_secret_size = peer_key_length; 271 272 if (peer_key_length != key_buffer_size || 273 calculated_shared_secret_size > shared_secret_size) { 274 return PSA_ERROR_INVALID_ARGUMENT; 275 } 276 277 if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { 278 return PSA_ERROR_INVALID_ARGUMENT; 279 } 280 281 mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); 282 mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); 283 mbedtls_mpi_init(&K); 284 285 status = mbedtls_psa_ffdh_set_prime_generator( 286 PSA_BITS_TO_BYTES(attributes->bits), &P, &G); 287 288 if (status != PSA_SUCCESS) { 289 goto cleanup; 290 } 291 292 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, 293 key_buffer_size)); 294 295 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, 296 peer_key_length)); 297 298 /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ 299 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); 300 301 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, 302 calculated_shared_secret_size)); 303 304 *shared_secret_length = calculated_shared_secret_size; 305 306 ret = 0; 307 308cleanup: 309 mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); 310 mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); 311 mbedtls_mpi_free(&K); 312 313 if (status == PSA_SUCCESS && ret != 0) { 314 status = mbedtls_to_psa_error(ret); 315 } 316 317 return status; 318} 319#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ 320 321#endif /* MBEDTLS_PSA_CRYPTO_C */ 322