mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	
		
			
	
	
		
			322 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			322 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  *  PSA FFDH layer on top of Mbed TLS crypto | ||
|  |  */ | ||
|  | /*
 | ||
|  |  *  Copyright The Mbed TLS Contributors | ||
|  |  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "common.h"
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_CRYPTO_C)
 | ||
|  | 
 | ||
|  | /* This header is only needed because it defines
 | ||
|  |  * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in | ||
|  |  * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module | ||
|  |  * only uses bignum functions for arithmetic. */ | ||
|  | #include <mbedtls/dhm.h>
 | ||
|  | 
 | ||
|  | #include <psa/crypto.h>
 | ||
|  | #include "psa_crypto_core.h"
 | ||
|  | #include "psa_crypto_ffdh.h"
 | ||
|  | #include "psa_crypto_random_impl.h"
 | ||
|  | #include "mbedtls/platform.h"
 | ||
|  | #include "mbedtls/error.h"
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||   \
 | ||
|  |     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) ||   \ | ||
|  |     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ | ||
|  |     defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) | ||
|  | static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, | ||
|  |                                                          mbedtls_mpi *P, | ||
|  |                                                          mbedtls_mpi *G) | ||
|  | { | ||
|  |     const unsigned char *dhm_P = NULL; | ||
|  |     const unsigned char *dhm_G = NULL; | ||
|  |     size_t dhm_size_P = 0; | ||
|  |     size_t dhm_size_G = 0; | ||
|  |     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  |     if (P == NULL && G == NULL) { | ||
|  |         return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |     } | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
 | ||
|  |     static const unsigned char dhm_P_2048[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; | ||
|  |     static const unsigned char dhm_G_2048[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
 | ||
|  |     static const unsigned char dhm_P_3072[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; | ||
|  |     static const unsigned char dhm_G_3072[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
 | ||
|  |     static const unsigned char dhm_P_4096[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; | ||
|  |     static const unsigned char dhm_G_4096[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
 | ||
|  |     static const unsigned char dhm_P_6144[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; | ||
|  |     static const unsigned char dhm_G_6144[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
 | ||
|  |     static const unsigned char dhm_P_8192[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; | ||
|  |     static const unsigned char dhm_G_8192[] = | ||
|  |         MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
 | ||
|  | 
 | ||
|  |     switch (key_size) { | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
 | ||
|  |         case sizeof(dhm_P_2048): | ||
|  |             dhm_P = dhm_P_2048; | ||
|  |             dhm_G = dhm_G_2048; | ||
|  |             dhm_size_P = sizeof(dhm_P_2048); | ||
|  |             dhm_size_G = sizeof(dhm_G_2048); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
 | ||
|  |         case sizeof(dhm_P_3072): | ||
|  |             dhm_P = dhm_P_3072; | ||
|  |             dhm_G = dhm_G_3072; | ||
|  |             dhm_size_P = sizeof(dhm_P_3072); | ||
|  |             dhm_size_G = sizeof(dhm_G_3072); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
 | ||
|  |         case sizeof(dhm_P_4096): | ||
|  |             dhm_P = dhm_P_4096; | ||
|  |             dhm_G = dhm_G_4096; | ||
|  |             dhm_size_P = sizeof(dhm_P_4096); | ||
|  |             dhm_size_G = sizeof(dhm_G_4096); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
 | ||
|  |         case sizeof(dhm_P_6144): | ||
|  |             dhm_P = dhm_P_6144; | ||
|  |             dhm_G = dhm_G_6144; | ||
|  |             dhm_size_P = sizeof(dhm_P_6144); | ||
|  |             dhm_size_G = sizeof(dhm_G_6144); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
 | ||
|  |         case sizeof(dhm_P_8192): | ||
|  |             dhm_P = dhm_P_8192; | ||
|  |             dhm_G = dhm_G_8192; | ||
|  |             dhm_size_P = sizeof(dhm_P_8192); | ||
|  |             dhm_size_G = sizeof(dhm_G_8192); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
 | ||
|  |         default: | ||
|  |             return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (P != NULL) { | ||
|  |         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, | ||
|  |                                                 dhm_size_P)); | ||
|  |     } | ||
|  |     if (G != NULL) { | ||
|  |         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, | ||
|  |                                                 dhm_size_G)); | ||
|  |     } | ||
|  | 
 | ||
|  | cleanup: | ||
|  |     if (ret != 0) { | ||
|  |         return mbedtls_to_psa_error(ret); | ||
|  |     } | ||
|  | 
 | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
 | ||
|  |           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || | ||
|  |           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || | ||
|  |           MBEDTLS_PSA_BUILTIN_ALG_FFDH */ | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
 | ||
|  |     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) | ||
|  | psa_status_t mbedtls_psa_ffdh_export_public_key( | ||
|  |     const psa_key_attributes_t *attributes, | ||
|  |     const uint8_t *key_buffer, | ||
|  |     size_t key_buffer_size, | ||
|  |     uint8_t *data, | ||
|  |     size_t data_size, | ||
|  |     size_t *data_length) | ||
|  | { | ||
|  |     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     mbedtls_mpi GX, G, X, P; | ||
|  |     psa_key_type_t type = attributes->type; | ||
|  | 
 | ||
|  |     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { | ||
|  |         if (key_buffer_size > data_size) { | ||
|  |             return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         } | ||
|  |         memcpy(data, key_buffer, key_buffer_size); | ||
|  |         memset(data + key_buffer_size, 0, | ||
|  |                data_size - key_buffer_size); | ||
|  |         *data_length = key_buffer_size; | ||
|  |         return PSA_SUCCESS; | ||
|  |     } | ||
|  | 
 | ||
|  |     mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); | ||
|  |     mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); | ||
|  | 
 | ||
|  |     size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); | ||
|  | 
 | ||
|  |     status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); | ||
|  | 
 | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto cleanup; | ||
|  |     } | ||
|  | 
 | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, | ||
|  |                                             key_buffer_size)); | ||
|  | 
 | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); | ||
|  | 
 | ||
|  |     *data_length = key_len; | ||
|  | 
 | ||
|  |     ret = 0; | ||
|  | cleanup: | ||
|  |     mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); | ||
|  |     mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS && ret != 0) { | ||
|  |         status = mbedtls_to_psa_error(ret); | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
 | ||
|  |           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
 | ||
|  | psa_status_t mbedtls_psa_ffdh_generate_key( | ||
|  |     const psa_key_attributes_t *attributes, | ||
|  |     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) | ||
|  | { | ||
|  |     mbedtls_mpi X, P; | ||
|  |     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); | ||
|  |     (void) attributes; | ||
|  | 
 | ||
|  |     status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); | ||
|  | 
 | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto cleanup; | ||
|  |     } | ||
|  | 
 | ||
|  |     /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their
 | ||
|  |         secret exponent from the range [2, P-2]. | ||
|  |         Select random value in range [3, P-1] and decrease it by 1. */ | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, | ||
|  |                                        MBEDTLS_PSA_RANDOM_STATE)); | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); | ||
|  |     *key_buffer_length = key_buffer_size; | ||
|  | 
 | ||
|  | cleanup: | ||
|  |     mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); | ||
|  |     if (status == PSA_SUCCESS && ret != 0) { | ||
|  |         return mbedtls_to_psa_error(ret); | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT)
 | ||
|  | psa_status_t mbedtls_psa_ffdh_import_key( | ||
|  |     const psa_key_attributes_t *attributes, | ||
|  |     const uint8_t *data, size_t data_length, | ||
|  |     uint8_t *key_buffer, size_t key_buffer_size, | ||
|  |     size_t *key_buffer_length, size_t *bits) | ||
|  | { | ||
|  |     (void) attributes; | ||
|  | 
 | ||
|  |     if (key_buffer_size < data_length) { | ||
|  |         return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |     } | ||
|  |     memcpy(key_buffer, data, data_length); | ||
|  |     *key_buffer_length = data_length; | ||
|  |     *bits = PSA_BYTES_TO_BITS(data_length); | ||
|  | 
 | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
 | ||
|  | psa_status_t mbedtls_psa_ffdh_key_agreement( | ||
|  |     const psa_key_attributes_t *attributes, | ||
|  |     const uint8_t *peer_key, | ||
|  |     size_t peer_key_length, | ||
|  |     const uint8_t *key_buffer, | ||
|  |     size_t key_buffer_size, | ||
|  |     uint8_t *shared_secret, | ||
|  |     size_t shared_secret_size, | ||
|  |     size_t *shared_secret_length) | ||
|  | { | ||
|  |     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     mbedtls_mpi P, G, X, GY, K; | ||
|  |     const size_t calculated_shared_secret_size = peer_key_length; | ||
|  | 
 | ||
|  |     if (peer_key_length != key_buffer_size || | ||
|  |         calculated_shared_secret_size > shared_secret_size) { | ||
|  |         return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { | ||
|  |         return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |     } | ||
|  | 
 | ||
|  |     mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); | ||
|  |     mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); | ||
|  |     mbedtls_mpi_init(&K); | ||
|  | 
 | ||
|  |     status = mbedtls_psa_ffdh_set_prime_generator( | ||
|  |         PSA_BITS_TO_BYTES(attributes->bits), &P, &G); | ||
|  | 
 | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto cleanup; | ||
|  |     } | ||
|  | 
 | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, | ||
|  |                                             key_buffer_size)); | ||
|  | 
 | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, | ||
|  |                                             peer_key_length)); | ||
|  | 
 | ||
|  |     /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); | ||
|  | 
 | ||
|  |     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, | ||
|  |                                              calculated_shared_secret_size)); | ||
|  | 
 | ||
|  |     *shared_secret_length = calculated_shared_secret_size; | ||
|  | 
 | ||
|  |     ret = 0; | ||
|  | 
 | ||
|  | cleanup: | ||
|  |     mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); | ||
|  |     mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); | ||
|  |     mbedtls_mpi_free(&K); | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS && ret != 0) { | ||
|  |         status = mbedtls_to_psa_error(ret); | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
 | ||
|  | 
 | ||
|  | #endif /* MBEDTLS_PSA_CRYPTO_C */
 |