/** @file | |
RSA Asymmetric Cipher Wrapper Implementation over MbedTLS. | |
This file implements following APIs which provide basic capabilities for RSA: | |
1) RsaNew | |
2) RsaFree | |
3) RsaSetKey | |
4) RsaPkcs1Verify | |
RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2 | |
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "InternalCryptLib.h" | |
#include <mbedtls/rsa.h> | |
/** | |
Allocates and initializes one RSA context for subsequent use. | |
@return Pointer to the RSA context that has been initialized. | |
If the allocations fails, RsaNew() returns NULL. | |
**/ | |
VOID * | |
EFIAPI | |
RsaNew ( | |
VOID | |
) | |
{ | |
VOID *RsaContext; | |
RsaContext = AllocateZeroPool (sizeof (mbedtls_rsa_context)); | |
if (RsaContext == NULL) { | |
return RsaContext; | |
} | |
mbedtls_rsa_init (RsaContext); | |
if (mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE) != 0) { | |
return NULL; | |
} | |
return RsaContext; | |
} | |
/** | |
Release the specified RSA context. | |
@param[in] RsaContext Pointer to the RSA context to be released. | |
**/ | |
VOID | |
EFIAPI | |
RsaFree ( | |
IN VOID *RsaContext | |
) | |
{ | |
mbedtls_rsa_free (RsaContext); | |
if (RsaContext != NULL) { | |
FreePool (RsaContext); | |
} | |
} | |
/** | |
Sets the tag-designated key component into the established RSA context. | |
This function sets the tag-designated RSA key component into the established | |
RSA context from the user-specified non-negative integer (octet string format | |
represented in RSA PKCS#1). | |
If BigNumber is NULL, then the specified key component in RSA context is cleared. | |
If RsaContext 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[in] BigNumber Pointer to octet integer buffer. | |
If NULL, then the specified key component in RSA | |
context is cleared. | |
@param[in] BnSize Size of big number buffer in bytes. | |
If BigNumber is NULL, then it is ignored. | |
@retval TRUE RSA key component was set successfully. | |
@retval FALSE Invalid RSA key component tag. | |
**/ | |
BOOLEAN | |
EFIAPI | |
RsaSetKey ( | |
IN OUT VOID *RsaContext, | |
IN RSA_KEY_TAG KeyTag, | |
IN CONST UINT8 *BigNumber, | |
IN UINTN BnSize | |
) | |
{ | |
mbedtls_rsa_context *RsaKey; | |
INT32 Ret; | |
mbedtls_mpi Value; | |
// | |
// Check input parameters. | |
// | |
if ((RsaContext == NULL) || (BnSize > INT_MAX)) { | |
return FALSE; | |
} | |
mbedtls_mpi_init (&Value); | |
RsaKey = (mbedtls_rsa_context *)RsaContext; | |
// if BigNumber is Null clear | |
if (BigNumber != NULL) { | |
Ret = mbedtls_mpi_read_binary (&Value, BigNumber, BnSize); | |
if (Ret != 0) { | |
mbedtls_mpi_free (&Value); | |
return FALSE; | |
} | |
} | |
switch (KeyTag) { | |
case RsaKeyN: | |
Ret = mbedtls_rsa_import ( | |
RsaKey, | |
&Value, | |
NULL, | |
NULL, | |
NULL, | |
NULL | |
); | |
break; | |
case RsaKeyE: | |
Ret = mbedtls_rsa_import ( | |
RsaKey, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
&Value | |
); | |
break; | |
case RsaKeyD: | |
Ret = mbedtls_rsa_import ( | |
RsaKey, | |
NULL, | |
NULL, | |
NULL, | |
&Value, | |
NULL | |
); | |
break; | |
case RsaKeyQ: | |
Ret = mbedtls_rsa_import ( | |
RsaKey, | |
NULL, | |
NULL, | |
&Value, | |
NULL, | |
NULL | |
); | |
break; | |
case RsaKeyP: | |
Ret = mbedtls_rsa_import ( | |
RsaKey, | |
NULL, | |
&Value, | |
NULL, | |
NULL, | |
NULL | |
); | |
break; | |
case RsaKeyDp: | |
case RsaKeyDq: | |
case RsaKeyQInv: | |
default: | |
Ret = -1; | |
break; | |
} | |
mbedtls_mpi_free (&Value); | |
return Ret == 0; | |
} | |
/** | |
Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in | |
RSA PKCS#1. | |
If RsaContext is NULL, then return FALSE. | |
If MessageHash is NULL, then return FALSE. | |
If Signature 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. | |
@param[in] RsaContext Pointer to RSA context for signature verification. | |
@param[in] MessageHash Pointer to octet message hash to be checked. | |
@param[in] HashSize Size of the message hash in bytes. | |
@param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified. | |
@param[in] SigSize Size of signature in bytes. | |
@retval TRUE Valid signature encoded in PKCS1-v1_5. | |
@retval FALSE Invalid signature or invalid RSA context. | |
**/ | |
BOOLEAN | |
EFIAPI | |
RsaPkcs1Verify ( | |
IN VOID *RsaContext, | |
IN CONST UINT8 *MessageHash, | |
IN UINTN HashSize, | |
IN CONST UINT8 *Signature, | |
IN UINTN SigSize | |
) | |
{ | |
INT32 Ret; | |
mbedtls_md_type_t md_alg; | |
mbedtls_rsa_context *RsaKey; | |
if ((RsaContext == NULL) || (MessageHash == NULL) || (Signature == NULL)) { | |
return FALSE; | |
} | |
if ((SigSize > INT_MAX) || (SigSize == 0)) { | |
return FALSE; | |
} | |
RsaKey = (mbedtls_rsa_context *)RsaContext; | |
if (mbedtls_rsa_complete (RsaKey) != 0) { | |
return FALSE; | |
} | |
switch (HashSize) { | |
#ifdef ENABLE_MD5_DEPRECATED_INTERFACES | |
case MD5_DIGEST_SIZE: | |
md_alg = MBEDTLS_MD_MD5; | |
break; | |
#endif | |
#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES | |
case SHA1_DIGEST_SIZE: | |
md_alg = MBEDTLS_MD_SHA1; | |
break; | |
#endif | |
case SHA256_DIGEST_SIZE: | |
md_alg = MBEDTLS_MD_SHA256; | |
break; | |
case SHA384_DIGEST_SIZE: | |
md_alg = MBEDTLS_MD_SHA384; | |
break; | |
case SHA512_DIGEST_SIZE: | |
md_alg = MBEDTLS_MD_SHA512; | |
break; | |
default: | |
return FALSE; | |
} | |
if (mbedtls_rsa_get_len (RsaContext) != SigSize) { | |
return FALSE; | |
} | |
mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, md_alg); | |
Ret = mbedtls_rsa_pkcs1_verify ( | |
RsaContext, | |
md_alg, | |
(UINT32)HashSize, | |
MessageHash, | |
Signature | |
); | |
if (Ret != 0) { | |
return FALSE; | |
} | |
return TRUE; | |
} |