diff --git a/CryptoPkg/Library/OpensslLib/ossl_store.c b/CryptoPkg/Library/OpensslLib/ossl_store.c new file mode 100644 index 0000000000..29e1506048 --- /dev/null +++ b/CryptoPkg/Library/OpensslLib/ossl_store.c @@ -0,0 +1,17 @@ +/** @file + Dummy implement ossl_store(Store retrieval functions) for UEFI. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* + * This function is cleanup ossl store. + * + * Dummy Implement for UEFI + */ +void ossl_store_cleanup_int(void) +{ +} + diff --git a/CryptoPkg/Library/OpensslLib/rand_pool.c b/CryptoPkg/Library/OpensslLib/rand_pool.c new file mode 100644 index 0000000000..9d2a4ad138 --- /dev/null +++ b/CryptoPkg/Library/OpensslLib/rand_pool.c @@ -0,0 +1,316 @@ +/** @file + OpenSSL_1_1_1b doesn't implement rand_pool_* functions for UEFI. + The file implement these functions. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "internal/rand_int.h" +#include + +#include +#include + +#include "rand_pool_noise.h" + +/** + Get some randomness from low-order bits of GetPerformanceCounter results. + And combine them to the 64-bit value + + @param[out] Rand Buffer pointer to store the 64-bit random value. + + @retval TRUE Random number generated successfully. + @retval FALSE Failed to generate. +**/ +STATIC +BOOLEAN +EFIAPI +GetRandNoise64FromPerformanceCounter( + OUT UINT64 *Rand + ) +{ + UINT32 Index; + UINT32 *RandPtr; + + if (NULL == Rand) { + return FALSE; + } + + RandPtr = (UINT32 *) Rand; + + for (Index = 0; Index < 2; Index ++) { + *RandPtr = (UINT32) (GetPerformanceCounter () & 0xFF); + MicroSecondDelay (10); + RandPtr++; + } + + return TRUE; +} + +/** + Calls RandomNumber64 to fill + a buffer of arbitrary size with random bytes. + + @param[in] Length Size of the buffer, in bytes, to fill with. + @param[out] RandBuffer Pointer to the buffer to store the random result. + + @retval EFI_SUCCESS Random bytes generation succeeded. + @retval EFI_NOT_READY Failed to request random bytes. + +**/ +STATIC +BOOLEAN +EFIAPI +RandGetBytes ( + IN UINTN Length, + OUT UINT8 *RandBuffer + ) +{ + BOOLEAN Ret; + UINT64 TempRand; + + Ret = FALSE; + + while (Length > 0) { + // + // Get random noise from platform. + // If it failed, fallback to PerformanceCounter + // If you really care about security, you must override + // GetRandomNoise64FromPlatform. + // + Ret = GetRandomNoise64 (&TempRand); + if (Ret == FALSE) { + Ret = GetRandNoise64FromPerformanceCounter (&TempRand); + } + if (!Ret) { + return Ret; + } + if (Length >= sizeof (TempRand)) { + *((UINT64*) RandBuffer) = TempRand; + RandBuffer += sizeof (UINT64); + Length -= sizeof (TempRand); + } else { + CopyMem (RandBuffer, &TempRand, Length); + Length = 0; + } + } + + return Ret; +} + +/** + Creates a 128bit random value that is fully forward and backward prediction resistant, + suitable for seeding a NIST SP800-90 Compliant. + This function takes multiple random numbers from PerformanceCounter to ensure reseeding + and performs AES-CBC-MAC over the data to compute the seed value. + + @param[out] SeedBuffer Pointer to a 128bit buffer to store the random seed. + + @retval TRUE Random seed generation succeeded. + @retval FALSE Failed to request random bytes. + +**/ +STATIC +BOOLEAN +EFIAPI +RandGetSeed128 ( + OUT UINT8 *SeedBuffer + ) +{ + BOOLEAN Ret; + UINT8 RandByte[16]; + UINT8 Key[16]; + UINT8 Ffv[16]; + UINT8 Xored[16]; + UINT32 Index; + UINT32 Index2; + AES_KEY AESKey; + + // + // Chose an arbitary key and zero the feed_forward_value (FFV) + // + for (Index = 0; Index < 16; Index++) { + Key[Index] = (UINT8) Index; + Ffv[Index] = 0; + } + + AES_set_encrypt_key (Key, 16 * 8, &AESKey); + + // + // Perform CBC_MAC over 32 * 128 bit values, with 10us gaps between 128 bit value + // The 10us gaps will ensure multiple reseeds within the system time with a large + // design margin. + // + for (Index = 0; Index < 32; Index++) { + MicroSecondDelay (10); + Ret = RandGetBytes (16, RandByte); + if (!Ret) { + return Ret; + } + + // + // Perform XOR operations on two 128-bit value. + // + for (Index2 = 0; Index2 < 16; Index2++) { + Xored[Index2] = RandByte[Index2] ^ Ffv[Index2]; + } + + AES_encrypt (Xored, Ffv, &AESKey); + } + + for (Index = 0; Index < 16; Index++) { + SeedBuffer[Index] = Ffv[Index]; + } + + return Ret; +} + +/** + Generate high-quality entropy source. + + @param[in] Length Size of the buffer, in bytes, to fill with. + @param[out] Entropy Pointer to the buffer to store the entropy data. + + @retval EFI_SUCCESS Entropy generation succeeded. + @retval EFI_NOT_READY Failed to request random data. + +**/ +STATIC +BOOLEAN +EFIAPI +RandGenerateEntropy ( + IN UINTN Length, + OUT UINT8 *Entropy + ) +{ + BOOLEAN Ret; + UINTN BlockCount; + UINT8 Seed[16]; + UINT8 *Ptr; + + BlockCount = Length / 16; + Ptr = (UINT8 *) Entropy; + + // + // Generate high-quality seed for DRBG Entropy + // + while (BlockCount > 0) { + Ret = RandGetSeed128 (Seed); + if (!Ret) { + return Ret; + } + CopyMem (Ptr, Seed, 16); + + BlockCount--; + Ptr = Ptr + 16; + } + + // + // Populate the remained data as request. + // + Ret = RandGetSeed128 (Seed); + if (!Ret) { + return Ret; + } + CopyMem (Ptr, Seed, (Length % 16)); + + return Ret; +} + +/* + * Add random bytes to the pool to acquire requested amount of entropy + * + * This function is platform specific and tries to acquire the requested + * amount of entropy by polling platform specific entropy sources. + * + * This is OpenSSL required interface. + */ +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ + BOOLEAN Ret; + size_t bytes_needed; + unsigned char * buffer; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + if (bytes_needed > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + + if (buffer != NULL) { + Ret = RandGenerateEntropy(bytes_needed, buffer); + if (FALSE == Ret) { + rand_pool_add_end(pool, 0, 0); + } else { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); + } + } + } + + return rand_pool_entropy_available(pool); +} + +/* + * Implementation for UEFI + * + * This is OpenSSL required interface. + */ +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + struct { + UINT64 Rand; + UINT64 TimerValue; + } data = { 0 }; + + RandGetBytes(8, (UINT8 *)&(data.Rand)); + data.TimerValue = GetPerformanceCounter(); + + return rand_pool_add(pool, (unsigned char*)&data, sizeof(data), 0); +} + +/* + * Implementation for UEFI + * + * This is OpenSSL required interface. + */ +int rand_pool_add_additional_data(RAND_POOL *pool) +{ + struct { + UINT64 Rand; + UINT64 TimerValue; + } data = { 0 }; + + RandGetBytes(8, (UINT8 *)&(data.Rand)); + data.TimerValue = GetPerformanceCounter(); + + return rand_pool_add(pool, (unsigned char*)&data, sizeof(data), 0); +} + +/* + * Dummy Implememtation for UEFI + * + * This is OpenSSL required interface. + */ +int rand_pool_init(void) +{ + return 1; +} + +/* + * Dummy Implememtation for UEFI + * + * This is OpenSSL required interface. + */ +void rand_pool_cleanup(void) +{ +} + +/* + * Dummy Implememtation for UEFI + * + * This is OpenSSL required interface. + */ +void rand_pool_keep_random_devices_open(int keep) +{ +} + diff --git a/CryptoPkg/Library/OpensslLib/rand_pool_noise.c b/CryptoPkg/Library/OpensslLib/rand_pool_noise.c new file mode 100644 index 0000000000..c16ed8b454 --- /dev/null +++ b/CryptoPkg/Library/OpensslLib/rand_pool_noise.c @@ -0,0 +1,29 @@ +/** @file + Provide rand noise source. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Get 64-bit noise source + + @param[out] Rand Buffer pointer to store 64-bit noise source + + @retval FALSE Failed to generate +**/ +BOOLEAN +EFIAPI +GetRandomNoise64 ( + OUT UINT64 *Rand + ) +{ + // + // Return FALSE will fallback to use PerformaceCounter to + // generate noise. + // + return FALSE; +} diff --git a/CryptoPkg/Library/OpensslLib/rand_pool_noise.h b/CryptoPkg/Library/OpensslLib/rand_pool_noise.h new file mode 100644 index 0000000000..75acc686a9 --- /dev/null +++ b/CryptoPkg/Library/OpensslLib/rand_pool_noise.h @@ -0,0 +1,29 @@ +/** @file + Provide rand noise source. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __RAND_POOL_NOISE_H__ +#define __RAND_POOL_NOISE_H__ + +#include + +/** + Get 64-bit noise source. + + @param[out] Rand Buffer pointer to store 64-bit noise source + + @retval TRUE Get randomness successfully. + @retval FALSE Failed to generate +**/ +BOOLEAN +EFIAPI +GetRandomNoise64 ( + OUT UINT64 *Rand + ); + + +#endif // __RAND_POOL_NOISE_H__ diff --git a/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c b/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c new file mode 100644 index 0000000000..4158106231 --- /dev/null +++ b/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c @@ -0,0 +1,43 @@ +/** @file + Provide rand noise source. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Get 64-bit noise source + + @param[out] Rand Buffer pointer to store 64-bit noise source + + @retval TRUE Get randomness successfully. + @retval FALSE Failed to generate +**/ +BOOLEAN +EFIAPI +GetRandomNoise64 ( + OUT UINT64 *Rand + ) +{ + UINT32 Index; + UINT32 *RandPtr; + + if (NULL == Rand) { + return FALSE; + } + + RandPtr = (UINT32 *)Rand; + + for (Index = 0; Index < 2; Index ++) { + *RandPtr = (UINT32) ((AsmReadTsc ()) & 0xFF); + RandPtr++; + MicroSecondDelay (10); + } + + return TRUE; +}