summaryrefslogtreecommitdiff
path: root/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
diff options
context:
space:
mode:
Diffstat (limited to 'CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c')
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
new file mode 100644
index 0000000..5fe76f1
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
@@ -0,0 +1,352 @@
+/** @file
+ RSA Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+ This file implements following APIs which provide more capabilities for RSA:
+ 1) RsaGetKey
+ 2) RsaGenerateKey
+ 3) RsaCheckKey
+ 4) RsaPkcs1Sign
+
+ RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+
+/**
+ Gets the tag-designated RSA key component from the established RSA context.
+
+ This function retrieves the tag-designated RSA key component from the
+ established RSA context as a non-negative integer (octet string format
+ represented in RSA PKCS#1).
+ If specified key component has not been set or has been cleared, then returned
+ BnSize is set to 0.
+ If the BigNumber buffer is too small to hold the contents of the key, FALSE
+ is returned and BnSize is set to the required buffer size to obtain the key.
+
+ If RsaContext is NULL, then return FALSE.
+ If BnSize is NULL, then return FALSE.
+ If BnSize is large enough but BigNumber is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] KeyTag Tag of RSA key component being set.
+ @param[out] BigNumber Pointer to octet integer buffer.
+ @param[in, out] BnSize On input, the size of big number buffer in bytes.
+ On output, the size of data returned in big number buffer in bytes.
+
+ @retval TRUE RSA key component was retrieved successfully.
+ @retval FALSE Invalid RSA key component tag.
+ @retval FALSE BnSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetKey (
+ IN OUT VOID *RsaContext,
+ IN RSA_KEY_TAG KeyTag,
+ OUT UINT8 *BigNumber,
+ IN OUT UINTN *BnSize
+ )
+{
+ mbedtls_rsa_context *RsaKey;
+ INT32 Ret;
+ mbedtls_mpi Value;
+ UINTN Size;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (*BnSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ //
+ // Init mbedtls_mpi
+ //
+ mbedtls_mpi_init (&Value);
+ Size = *BnSize;
+ *BnSize = 0;
+
+ RsaKey = (mbedtls_rsa_context *)RsaContext;
+
+ switch (KeyTag) {
+ case RsaKeyN:
+ Ret = mbedtls_rsa_export (RsaKey, &Value, NULL, NULL, NULL, NULL);
+ break;
+ case RsaKeyE:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, NULL, &Value);
+ break;
+ case RsaKeyD:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, &Value, NULL);
+ break;
+ case RsaKeyQ:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, &Value, NULL, NULL);
+ break;
+ case RsaKeyP:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, &Value, NULL, NULL, NULL);
+ break;
+ case RsaKeyDp:
+ case RsaKeyDq:
+ case RsaKeyQInv:
+ default:
+ Ret = -1;
+ break;
+ }
+
+ if (Ret != 0) {
+ goto End;
+ }
+
+ if (mbedtls_mpi_size (&Value) == 0) {
+ Ret = 0;
+ goto End;
+ }
+
+ *BnSize = Size;
+
+ Size = mbedtls_mpi_size (&Value);
+ if (*BnSize < Size) {
+ Ret = 1;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if (BigNumber == NULL) {
+ Ret = 0;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if ((BigNumber != NULL) && (Ret == 0)) {
+ Ret = mbedtls_mpi_write_binary (&Value, BigNumber, Size);
+ *BnSize = Size;
+ }
+
+End:
+ mbedtls_mpi_free (&Value);
+ return Ret == 0;
+}
+
+/**
+ Generates RSA key components.
+
+ This function generates RSA key components. It takes RSA public exponent Pe and
+ length in bits of RSA modulus N as input, and generates all key components.
+ If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
+
+ Before this function can be invoked, pseudorandom number generator must be correctly
+ initialized by RandomSeed().
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] ModulusLength Length of RSA modulus N in bits.
+ @param[in] PublicExponent Pointer to RSA public exponent.
+ @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes.
+
+ @retval TRUE RSA key component was generated successfully.
+ @retval FALSE Invalid RSA key component tag.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGenerateKey (
+ IN OUT VOID *RsaContext,
+ IN UINTN ModulusLength,
+ IN CONST UINT8 *PublicExponent,
+ IN UINTN PublicExponentSize
+ )
+{
+ INT32 Ret;
+ mbedtls_rsa_context *Rsa;
+ INT32 Pe;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ Rsa = (mbedtls_rsa_context *)RsaContext;
+
+ if (PublicExponent == NULL) {
+ Pe = 0x10001;
+ } else {
+ if (PublicExponentSize == 0) {
+ return FALSE;
+ }
+
+ switch (PublicExponentSize) {
+ case 1:
+ Pe = PublicExponent[0];
+ break;
+ case 2:
+ Pe = PublicExponent[0] << 8 | PublicExponent[1];
+ break;
+ case 3:
+ Pe = PublicExponent[0] << 16 | PublicExponent[1] << 8 |
+ PublicExponent[2];
+ break;
+ case 4:
+ Pe = PublicExponent[0] << 24 | PublicExponent[1] << 16 |
+ PublicExponent[2] << 8 | PublicExponent[3];
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ Ret = mbedtls_rsa_gen_key (
+ Rsa,
+ MbedtlsRand,
+ NULL,
+ (UINT32)ModulusLength,
+ Pe
+ );
+
+ return Ret == 0;
+}
+
+/**
+ Validates key components of RSA context.
+ NOTE: This function performs integrity checks on all the RSA key material, so
+ the RSA key structure must contain all the private key data.
+
+ This function validates key components of RSA context in following aspects:
+ - Whether p is a prime
+ - Whether q is a prime
+ - Whether n = p * q
+ - Whether d*e = 1 mod lcm(p-1,q-1)
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context to check.
+
+ @retval TRUE RSA key components are valid.
+ @retval FALSE RSA key components are not valid.
+
+**/
+BOOLEAN
+EFIAPI
+RsaCheckKey (
+ IN VOID *RsaContext
+ )
+{
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+
+ UINT32 Ret;
+
+ Ret = mbedtls_rsa_complete (RsaContext);
+ if (Ret == 0) {
+ Ret = mbedtls_rsa_check_privkey (RsaContext);
+ }
+
+ return Ret == 0;
+}
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
+ RSA PKCS#1.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digest, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in PKCS1-v1_5.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPkcs1Sign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ INT32 Ret;
+ mbedtls_md_type_t MdAlg;
+
+ if ((RsaContext == NULL) || (MessageHash == NULL)) {
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+ return FALSE;
+ }
+
+ switch (HashSize) {
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ case SHA1_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA1;
+ break;
+ #endif
+
+ case SHA256_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA256;
+ break;
+
+ case SHA384_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA384;
+ break;
+
+ case SHA512_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA512;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_get_len (RsaContext) > *SigSize) {
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, MdAlg);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_pkcs1_sign (
+ RsaContext,
+ MbedtlsRand,
+ NULL,
+ MdAlg,
+ (UINT32)HashSize,
+ MessageHash,
+ Signature
+ );
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return TRUE;
+}