Fix some typo and coding style issues in BaseCryptLib instances.

Signed-off by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Fu, Siyuan <Siyuan.fu@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13564 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
tye1 2012-07-27 07:49:42 +00:00
parent 805c2dd119
commit 6b8ebcb8de
20 changed files with 50 additions and 1526 deletions

View File

@ -778,7 +778,7 @@ TdesGetContextSize (
Initializes user-supplied memory as TDES context for subsequent use.
This function initializes user-supplied memory pointed by TdesContext as TDES context.
In addtion, it sets up all TDES key materials for subsequent encryption and decryption
In addition, it sets up all TDES key materials for subsequent encryption and decryption
operations.
There are 3 key options as follows:
KeyLength = 64, Keying option 1: K1 == K2 == K3 (Backward compatibility with DES)
@ -974,7 +974,7 @@ AesGetContextSize (
Initializes user-supplied memory as AES context for subsequent use.
This function initializes user-supplied memory pointed by AesContext as AES context.
In addtion, it sets up all AES key materials for subsequent encryption and decryption
In addition, it sets up all AES key materials for subsequent encryption and decryption
operations.
There are 3 options for key length, 128 bits, 192 bits, and 256 bits.
@ -1167,7 +1167,7 @@ Arc4GetContextSize (
Initializes user-supplied memory as ARC4 context for subsequent use.
This function initializes user-supplied memory pointed by Arc4Context as ARC4 context.
In addtion, it sets up all ARC4 key materials for subsequent encryption and decryption
In addition, it sets up all ARC4 key materials for subsequent encryption and decryption
operations.
If Arc4Context is NULL, then return FALSE.

View File

@ -38,7 +38,7 @@ AesGetContextSize (
Initializes user-supplied memory as AES context for subsequent use.
This function initializes user-supplied memory pointed by AesContext as AES context.
In addtion, it sets up all AES key materials for subsequent encryption and decryption
In addition, it sets up all AES key materials for subsequent encryption and decryption
operations.
There are 3 options for key length, 128 bits, 192 bits, and 256 bits.

View File

@ -39,7 +39,7 @@ Arc4GetContextSize (
Initializes user-supplied memory as ARC4 context for subsequent use.
This function initializes user-supplied memory pointed by Arc4Context as ARC4 context.
In addtion, it sets up all ARC4 key materials for subsequent encryption and decryption
In addition, it sets up all ARC4 key materials for subsequent encryption and decryption
operations.
If Arc4Context is NULL, then return FALSE.

View File

@ -37,7 +37,7 @@ TdesGetContextSize (
Initializes user-supplied memory as TDES context for subsequent use.
This function initializes user-supplied memory pointed by TdesContext as TDES context.
In addtion, it sets up all TDES key materials for subsequent encryption and decryption
In addition, it sets up all TDES key materials for subsequent encryption and decryption
operations.
There are 3 key options as follows:
KeyLength = 64, Keying option 1: K1 == K2 == K3 (Backward compatibility with DES)
@ -76,9 +76,9 @@ TdesInit (
KeySchedule = (DES_key_schedule *) TdesContext;
//
// If input Key is a weak key, return error.
//
//
if (DES_is_weak_key ((const_DES_cblock *) Key)) {
if (DES_is_weak_key ((const_DES_cblock *) Key) == 1) {
return FALSE;
}
@ -90,7 +90,7 @@ TdesInit (
return TRUE;
}
if (DES_is_weak_key ((const_DES_cblock *) Key + 8)) {
if (DES_is_weak_key ((const_DES_cblock *) Key + 8) == 1) {
return FALSE;
}
@ -101,7 +101,7 @@ TdesInit (
return TRUE;
}
if (DES_is_weak_key ((const_DES_cblock *) Key + 16)) {
if (DES_is_weak_key ((const_DES_cblock *) Key + 16) == 1) {
return FALSE;
}

View File

@ -1,753 +0,0 @@
/** @file
PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL.
Caution: This module requires additional review when modified.
This library will have external input - signature (e.g. UEFI Authenticated
Variable). It may by input in SMM mode.
This external input must be validated carefully to avoid security issue like
buffer overflow, integer overflow.
WrapPkcs7Data(), Pkcs7GetSigners(), Pkcs7Verify() will get UEFI Authenticated
Variable and will do basic check for data structure.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalCryptLib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pkcs7.h>
UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
/**
Verification callback function to override any existing callbacks in OpenSSL
for intermediate certificate supports.
@param[in] Status Original status before calling this callback.
@param[in] Context X509 store context.
@retval 1 Current X509 certificate is verified successfully.
@retval 0 Verification failed.
**/
int
X509VerifyCb (
IN int Status,
IN X509_STORE_CTX *Context
)
{
X509_OBJECT *Obj;
INTN Error;
INTN Index;
INTN Count;
Obj = NULL;
Error = (INTN) X509_STORE_CTX_get_error (Context);
//
// X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT and X509_V_ERR_UNABLE_TO_GET_ISSUER_
// CERT_LOCALLY mean a X509 certificate is not self signed and its issuer
// can not be found in X509_verify_cert of X509_vfy.c.
// In order to support intermediate certificate node, we override the
// errors if the certification is obtained from X509 store, i.e. it is
// a trusted ceritifcate node that is enrolled by user.
// Besides,X509_V_ERR_CERT_UNTRUSTED and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
// are also ignored to enable such feature.
//
if ((Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) ||
(Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {
Obj = (X509_OBJECT *) malloc (sizeof (X509_OBJECT));
if (Obj == NULL) {
return 0;
}
Obj->type = X509_LU_X509;
Obj->data.x509 = Context->current_cert;
CRYPTO_w_lock (CRYPTO_LOCK_X509_STORE);
if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
Status = 1;
} else {
//
// If any certificate in the chain is enrolled as trusted certificate,
// pass the certificate verification.
//
if (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
Count = (INTN) sk_X509_num (Context->chain);
for (Index = 0; Index < Count; Index++) {
Obj->data.x509 = sk_X509_value (Context->chain, (int) Index);
if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
Status = 1;
break;
}
}
}
}
CRYPTO_w_unlock (CRYPTO_LOCK_X509_STORE);
}
if ((Error == X509_V_ERR_CERT_UNTRUSTED) ||
(Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) {
Status = 1;
}
if (Obj != NULL) {
OPENSSL_free (Obj);
}
return Status;
}
/**
Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
Syntax Standard, version 1.5". This interface is only intended to be used for
application to perform PKCS#7 functionality validation.
@param[in] PrivateKey Pointer to the PEM-formatted private key data for
data signing.
@param[in] PrivateKeySize Size of the PEM private key data in bytes.
@param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM
key data.
@param[in] InData Pointer to the content to be signed.
@param[in] InDataSize Size of InData in bytes.
@param[in] SignCert Pointer to signer's DER-encoded certificate to sign with.
@param[in] OtherCerts Pointer to an optional additional set of certificates to
include in the PKCS#7 signedData (e.g. any intermediate
CAs in the chain).
@param[out] SignedData Pointer to output PKCS#7 signedData.
@param[out] SignedDataSize Size of SignedData in bytes.
@retval TRUE PKCS#7 data signing succeeded.
@retval FALSE PKCS#7 data signing failed.
**/
BOOLEAN
EFIAPI
Pkcs7Sign (
IN CONST UINT8 *PrivateKey,
IN UINTN PrivateKeySize,
IN CONST UINT8 *KeyPassword,
IN UINT8 *InData,
IN UINTN InDataSize,
IN UINT8 *SignCert,
IN UINT8 *OtherCerts OPTIONAL,
OUT UINT8 **SignedData,
OUT UINTN *SignedDataSize
)
{
BOOLEAN Status;
EVP_PKEY *Key;
BIO *DataBio;
PKCS7 *Pkcs7;
UINT8 *RsaContext;
UINT8 *P7Data;
UINTN P7DataSize;
UINT8 *Tmp;
//
// Check input parameters.
//
if (PrivateKey == NULL || KeyPassword == NULL || InData == NULL ||
SignCert == NULL || SignedData == NULL || SignedDataSize == NULL || InDataSize > INT_MAX) {
return FALSE;
}
RsaContext = NULL;
Key = NULL;
Pkcs7 = NULL;
DataBio = NULL;
Status = FALSE;
//
// Retrieve RSA private key from PEM data.
//
Status = RsaGetPrivateKeyFromPem (
PrivateKey,
PrivateKeySize,
(CONST CHAR8 *) KeyPassword,
(VOID **) &RsaContext
);
if (!Status) {
return Status;
}
//
// Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling
//
EVP_add_digest (EVP_md5());
EVP_add_digest (EVP_sha1());
EVP_add_digest (EVP_sha256());
RandomSeed (NULL, 0);
//
// Construct OpenSSL EVP_PKEY for private key.
//
Key = EVP_PKEY_new ();
if (Key == NULL) {
Status = FALSE;
goto _Exit;
}
Key->save_type = EVP_PKEY_RSA;
Key->type = EVP_PKEY_type (EVP_PKEY_RSA);
Key->pkey.rsa = (RSA *) RsaContext;
//
// Convert the data to be signed to BIO format.
//
DataBio = BIO_new (BIO_s_mem ());
BIO_write (DataBio, InData, (int) InDataSize);
//
// Create the PKCS#7 signedData structure.
//
Pkcs7 = PKCS7_sign (
(X509 *) SignCert,
Key,
(STACK_OF(X509) *) OtherCerts,
DataBio,
PKCS7_BINARY | PKCS7_NOATTR | PKCS7_DETACHED
);
if (Pkcs7 == NULL) {
Status = FALSE;
goto _Exit;
}
//
// Convert PKCS#7 signedData structure into DER-encoded buffer.
//
P7DataSize = i2d_PKCS7 (Pkcs7, NULL);
if (P7DataSize <= 19) {
Status = FALSE;
goto _Exit;
}
P7Data = malloc (P7DataSize);
if (P7Data == NULL) {
Status = FALSE;
goto _Exit;
}
Tmp = P7Data;
P7DataSize = i2d_PKCS7 (Pkcs7, (unsigned char **) &Tmp);
//
// Strip ContentInfo to content only for signeddata. The data be trimmed off
// is totally 19 bytes.
//
*SignedDataSize = P7DataSize - 19;
*SignedData = malloc (*SignedDataSize);
if (*SignedData == NULL) {
Status = FALSE;
OPENSSL_free (P7Data);
goto _Exit;
}
CopyMem (*SignedData, P7Data + 19, *SignedDataSize);
OPENSSL_free (P7Data);
Status = TRUE;
_Exit:
//
// Release Resources
//
if (RsaContext != NULL) {
RsaFree (RsaContext);
if (Key != NULL) {
Key->pkey.rsa = NULL;
}
}
if (Key != NULL) {
EVP_PKEY_free (Key);
}
if (DataBio != NULL) {
BIO_free (DataBio);
}
if (Pkcs7 != NULL) {
PKCS7_free (Pkcs7);
}
return Status;
}
/**
Check input P7Data is a wrapped ContentInfo structure or not. If not construct
a new structure to wrap P7Data.
Caution: This function may receive untrusted input.
UEFI Authenticated Variable is external input, so this function will do basic
check for PKCS#7 data structure.
@param[in] P7Data Pointer to the PKCS#7 message to verify.
@param[in] P7Length Length of the PKCS#7 message in bytes.
@param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise
return FALSE.
@param[out] WrapData If return status of this function is TRUE:
1) when WrapFlag is TRUE, pointer to P7Data.
2) when WrapFlag is FALSE, pointer to a new ContentInfo
structure. It's caller's responsibility to free this
buffer.
@param[out] WrapDataSize Length of ContentInfo structure in bytes.
@retval TRUE The operation is finished successfully.
@retval FALSE The operation is failed due to lack of resources.
**/
BOOLEAN
WrapPkcs7Data (
IN CONST UINT8 *P7Data,
IN UINTN P7Length,
OUT BOOLEAN *WrapFlag,
OUT UINT8 **WrapData,
OUT UINTN *WrapDataSize
)
{
BOOLEAN Wrapped;
UINT8 *SignedData;
//
// Check whether input P7Data is a wrapped ContentInfo structure or not.
//
Wrapped = FALSE;
if ((P7Data[4] == 0x06) && (P7Data[5] == 0x09)) {
if (CompareMem (P7Data + 6, mOidValue, sizeof (mOidValue)) == 0) {
if ((P7Data[15] == 0xA0) && (P7Data[16] == 0x82)) {
Wrapped = TRUE;
}
}
}
if (Wrapped) {
*WrapData = (UINT8 *) P7Data;
*WrapDataSize = P7Length;
} else {
//
// Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.
//
*WrapDataSize = P7Length + 19;
*WrapData = malloc (*WrapDataSize);
if (*WrapData == NULL) {
*WrapFlag = Wrapped;
return FALSE;
}
SignedData = *WrapData;
//
// Part1: 0x30, 0x82.
//
SignedData[0] = 0x30;
SignedData[1] = 0x82;
//
// Part2: Length1 = P7Length + 19 - 4, in big endian.
//
SignedData[2] = (UINT8) (((UINT16) (*WrapDataSize - 4)) >> 8);
SignedData[3] = (UINT8) (((UINT16) (*WrapDataSize - 4)) & 0xff);
//
// Part3: 0x06, 0x09.
//
SignedData[4] = 0x06;
SignedData[5] = 0x09;
//
// Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.
//
CopyMem (SignedData + 6, mOidValue, sizeof (mOidValue));
//
// Part5: 0xA0, 0x82.
//
SignedData[15] = 0xA0;
SignedData[16] = 0x82;
//
// Part6: Length2 = P7Length, in big endian.
//
SignedData[17] = (UINT8) (((UINT16) P7Length) >> 8);
SignedData[18] = (UINT8) (((UINT16) P7Length) & 0xff);
//
// Part7: P7Data.
//
CopyMem (SignedData + 19, P7Data, P7Length);
}
*WrapFlag = Wrapped;
return TRUE;
}
/**
Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:
Cryptographic Message Syntax Standard". The input signed data could be wrapped
in a ContentInfo structure.
If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then
return FALSE. If P7Length overflow, then return FAlSE.
Caution: This function may receive untrusted input.
UEFI Authenticated Variable is external input, so this function will do basic
check for PKCS#7 data structure.
@param[in] P7Data Pointer to the PKCS#7 message to verify.
@param[in] P7Length Length of the PKCS#7 message in bytes.
@param[out] CertStack Pointer to Signer's certificates retrieved from P7Data.
It's caller's responsiblity to free the buffer.
@param[out] StackLength Length of signer's certificates in bytes.
@param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates.
It's caller's responsiblity to free the buffer.
@param[out] CertLength Length of the trusted certificate in bytes.
@retval TRUE The operation is finished successfully.
@retval FALSE Error occurs during the operation.
**/
BOOLEAN
EFIAPI
Pkcs7GetSigners (
IN CONST UINT8 *P7Data,
IN UINTN P7Length,
OUT UINT8 **CertStack,
OUT UINTN *StackLength,
OUT UINT8 **TrustedCert,
OUT UINTN *CertLength
)
{
PKCS7 *Pkcs7;
BOOLEAN Status;
UINT8 *SignedData;
UINT8 *Temp;
UINTN SignedDataSize;
BOOLEAN Wrapped;
STACK_OF(X509) *Stack;
UINT8 Index;
UINT8 *CertBuf;
UINT8 *OldBuf;
UINTN BufferSize;
UINTN OldSize;
UINT8 *SingleCert;
UINTN SingleCertSize;
if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||
(TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) {
return FALSE;
}
Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
if (!Status) {
return Status;
}
Status = FALSE;
Pkcs7 = NULL;
Stack = NULL;
CertBuf = NULL;
OldBuf = NULL;
SingleCert = NULL;
//
// Retrieve PKCS#7 Data (DER encoding)
//
if (SignedDataSize > INT_MAX) {
goto _Exit;
}
Temp = SignedData;
Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize);
if (Pkcs7 == NULL) {
goto _Exit;
}
//
// Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
//
if (!PKCS7_type_is_signed (Pkcs7)) {
goto _Exit;
}
Stack = PKCS7_get0_signers(Pkcs7, NULL, PKCS7_BINARY);
if (Stack == NULL) {
goto _Exit;
}
//
// Convert CertStack to buffer in following format:
// UINT8 CertNumber;
// UINT32 Cert1Length;
// UINT8 Cert1[];
// UINT32 Cert2Length;
// UINT8 Cert2[];
// ...
// UINT32 CertnLength;
// UINT8 Certn[];
//
BufferSize = sizeof (UINT8);
OldSize = BufferSize;
for (Index = 0; ; Index++) {
Status = X509PopCertificate (Stack, &SingleCert, &SingleCertSize);
if (!Status) {
break;
}
OldSize = BufferSize;
OldBuf = CertBuf;
BufferSize = OldSize + SingleCertSize + sizeof (UINT32);
CertBuf = malloc (BufferSize);
if (CertBuf == NULL) {
goto _Exit;
}
if (OldBuf != NULL) {
CopyMem (CertBuf, OldBuf, OldSize);
free (OldBuf);
OldBuf = NULL;
}
WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) SingleCertSize);
CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize);
free (SingleCert);
SingleCert = NULL;
}
if (CertBuf != NULL) {
//
// Update CertNumber.
//
CertBuf[0] = Index;
*CertLength = BufferSize - OldSize - sizeof (UINT32);
*TrustedCert = malloc (*CertLength);
if (*TrustedCert == NULL) {
goto _Exit;
}
CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);
*CertStack = CertBuf;
*StackLength = BufferSize;
Status = TRUE;
}
_Exit:
//
// Release Resources
//
if (!Wrapped) {
free (SignedData);
}
if (Pkcs7 != NULL) {
PKCS7_free (Pkcs7);
}
if (Stack != NULL) {
sk_X509_pop_free(Stack, X509_free);
}
if (SingleCert != NULL) {
free (SingleCert);
}
if (!Status && (CertBuf != NULL)) {
free (CertBuf);
*CertStack = NULL;
}
if (OldBuf != NULL) {
free (OldBuf);
}
return Status;
}
/**
Wrap function to use free() to free allocated memory for certificates.
@param[in] Certs Pointer to the certificates to be freed.
**/
VOID
EFIAPI
Pkcs7FreeSigners (
IN UINT8 *Certs
)
{
if (Certs == NULL) {
return;
}
free (Certs);
}
/**
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:
Cryptographic Message Syntax Standard". The input signed data could be wrapped
in a ContentInfo structure.
If P7Data, TrustedCert or InData is NULL, then return FALSE.
If P7Length, CertLength or DataLength overflow, then return FAlSE.
Caution: This function may receive untrusted input.
UEFI Authenticated Variable is external input, so this function will do basic
check for PKCS#7 data structure.
@param[in] P7Data Pointer to the PKCS#7 message to verify.
@param[in] P7Length Length of the PKCS#7 message in bytes.
@param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
is used for certificate chain verification.
@param[in] CertLength Length of the trusted certificate in bytes.
@param[in] InData Pointer to the content to be verified.
@param[in] DataLength Length of InData in bytes.
@retval TRUE The specified PKCS#7 signed data is valid.
@retval FALSE Invalid PKCS#7 signed data.
**/
BOOLEAN
EFIAPI
Pkcs7Verify (
IN CONST UINT8 *P7Data,
IN UINTN P7Length,
IN CONST UINT8 *TrustedCert,
IN UINTN CertLength,
IN CONST UINT8 *InData,
IN UINTN DataLength
)
{
PKCS7 *Pkcs7;
BIO *CertBio;
BIO *DataBio;
BOOLEAN Status;
X509 *Cert;
X509_STORE *CertStore;
UINT8 *SignedData;
UINT8 *Temp;
UINTN SignedDataSize;
BOOLEAN Wrapped;
//
// Check input parameters.
//
if (P7Data == NULL || TrustedCert == NULL || InData == NULL ||
P7Length > INT_MAX || CertLength > INT_MAX || DataLength > INT_MAX) {
return FALSE;
}
Pkcs7 = NULL;
CertBio = NULL;
DataBio = NULL;
Cert = NULL;
CertStore = NULL;
//
// Register & Initialize necessary digest algorithms for PKCS#7 Handling
//
EVP_add_digest (EVP_md5());
EVP_add_digest (EVP_sha1());
EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA);
EVP_add_digest (EVP_sha256());
Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
if (!Status) {
return Status;
}
Status = FALSE;
//
// Retrieve PKCS#7 Data (DER encoding)
//
if (SignedDataSize > INT_MAX) {
goto _Exit;
}
Temp = SignedData;
Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize);
if (Pkcs7 == NULL) {
goto _Exit;
}
//
// Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
//
if (!PKCS7_type_is_signed (Pkcs7)) {
goto _Exit;
}
//
// Read DER-encoded root certificate and Construct X509 Certificate
//
CertBio = BIO_new (BIO_s_mem ());
BIO_write (CertBio, TrustedCert, (int)CertLength);
if (CertBio == NULL) {
goto _Exit;
}
Cert = d2i_X509_bio (CertBio, NULL);
if (Cert == NULL) {
goto _Exit;
}
//
// Setup X509 Store for trusted certificate
//
CertStore = X509_STORE_new ();
if (CertStore == NULL) {
goto _Exit;
}
if (!(X509_STORE_add_cert (CertStore, Cert))) {
goto _Exit;
}
//
// Register customized X509 verification callback function to support
// trusted intermediate certificate anchor.
//
CertStore->verify_cb = X509VerifyCb;
//
// For generic PKCS#7 handling, InData may be NULL if the content is present
// in PKCS#7 structure. So ignore NULL checking here.
//
DataBio = BIO_new (BIO_s_mem ());
BIO_write (DataBio, InData, (int)DataLength);
//
// Verifies the PKCS#7 signedData structure
//
Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, PKCS7_BINARY);
_Exit:
//
// Release Resources
//
BIO_free (DataBio);
BIO_free (CertBio);
X509_free (Cert);
X509_STORE_free (CertStore);
PKCS7_free (Pkcs7);
if (!Wrapped) {
OPENSSL_free (SignedData);
}
return Status;
}

View File

@ -194,4 +194,3 @@ _Exit:
return Status;
}

View File

@ -1,722 +0,0 @@
/** @file
RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalCryptLib.h"
#include <openssl/rsa.h>
#include <openssl/err.h>
//
// ASN.1 value for Hash Algorithm ID with the Distringuished Encoding Rules (DER)
// Refer to Section 9.2 of PKCS#1 v2.1
//
CONST UINT8 Asn1IdMd5[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
};
CONST UINT8 Asn1IdSha1[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
};
CONST UINT8 Asn1IdSha256[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20
};
/**
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
)
{
//
// Allocates & Initializes RSA Context by OpenSSL RSA_new()
//
return (VOID *)RSA_new ();
}
/**
Release the specified RSA context.
If RsaContext is NULL, then return FALSE.
@param[in] RsaContext Pointer to the RSA context to be released.
**/
VOID
EFIAPI
RsaFree (
IN VOID *RsaContext
)
{
//
// Free OpenSSL RSA Context
//
RSA_free ((RSA *)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 componenet 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 componenet 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
)
{
RSA *RsaKey;
//
// Check input parameters.
//
if (RsaContext == NULL) {
return FALSE;
}
RsaKey = (RSA *)RsaContext;
//
// Set RSA Key Components by converting octet string to OpenSSL BN representation.
// NOTE: For RSA public key (used in signature verification), only public components
// (N, e) are needed.
//
switch (KeyTag) {
//
// RSA Public Modulus (N)
//
case RsaKeyN:
if (RsaKey->n != NULL) {
BN_free (RsaKey->n);
}
RsaKey->n = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->n = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->n);
break;
//
// RSA Public Exponent (e)
//
case RsaKeyE:
if (RsaKey->e != NULL) {
BN_free (RsaKey->e);
}
RsaKey->e = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->e = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->e);
break;
//
// RSA Private Exponent (d)
//
case RsaKeyD:
if (RsaKey->d != NULL) {
BN_free (RsaKey->d);
}
RsaKey->d = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->d = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->d);
break;
//
// RSA Secret Prime Factor of Modulus (p)
//
case RsaKeyP:
if (RsaKey->p != NULL) {
BN_free (RsaKey->p);
}
RsaKey->p = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->p = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->p);
break;
//
// RSA Secret Prime Factor of Modules (q)
//
case RsaKeyQ:
if (RsaKey->q != NULL) {
BN_free (RsaKey->q);
}
RsaKey->q = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->q = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->q);
break;
//
// p's CRT Exponent (== d mod (p - 1))
//
case RsaKeyDp:
if (RsaKey->dmp1 != NULL) {
BN_free (RsaKey->dmp1);
}
RsaKey->dmp1 = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->dmp1 = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->dmp1);
break;
//
// q's CRT Exponent (== d mod (q - 1))
//
case RsaKeyDq:
if (RsaKey->dmq1 != NULL) {
BN_free (RsaKey->dmq1);
}
RsaKey->dmq1 = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->dmq1 = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->dmq1);
break;
//
// The CRT Coefficient (== 1/q mod p)
//
case RsaKeyQInv:
if (RsaKey->iqmp != NULL) {
BN_free (RsaKey->iqmp);
}
RsaKey->iqmp = NULL;
if (BigNumber == NULL) {
break;
}
RsaKey->iqmp = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->iqmp);
break;
default:
return FALSE;
}
return TRUE;
}
/**
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
)
{
RSA *RsaKey;
BIGNUM *BnKey;
UINTN Size;
//
// Check input parameters.
//
if (RsaContext == NULL || BnSize == NULL) {
return FALSE;
}
RsaKey = (RSA *) RsaContext;
Size = *BnSize;
*BnSize = 0;
switch (KeyTag) {
//
// RSA Public Modulus (N)
//
case RsaKeyN:
if (RsaKey->n == NULL) {
return TRUE;
}
BnKey = RsaKey->n;
break;
//
// RSA Public Exponent (e)
//
case RsaKeyE:
if (RsaKey->e == NULL) {
return TRUE;
}
BnKey = RsaKey->e;
break;
//
// RSA Private Exponent (d)
//
case RsaKeyD:
if (RsaKey->d == NULL) {
return TRUE;
}
BnKey = RsaKey->d;
break;
//
// RSA Secret Prime Factor of Modulus (p)
//
case RsaKeyP:
if (RsaKey->p == NULL) {
return TRUE;
}
BnKey = RsaKey->p;
break;
//
// RSA Secret Prime Factor of Modules (q)
//
case RsaKeyQ:
if (RsaKey->q == NULL) {
return TRUE;
}
BnKey = RsaKey->q;
break;
//
// p's CRT Exponent (== d mod (p - 1))
//
case RsaKeyDp:
if (RsaKey->dmp1 == NULL) {
return TRUE;
}
BnKey = RsaKey->dmp1;
break;
//
// q's CRT Exponent (== d mod (q - 1))
//
case RsaKeyDq:
if (RsaKey->dmq1 == NULL) {
return TRUE;
}
BnKey = RsaKey->dmq1;
break;
//
// The CRT Coefficient (== 1/q mod p)
//
case RsaKeyQInv:
if (RsaKey->iqmp == NULL) {
return TRUE;
}
BnKey = RsaKey->iqmp;
break;
default:
return FALSE;
}
*BnSize = Size;
Size = BN_num_bytes (BnKey);
if (*BnSize < Size) {
*BnSize = Size;
return FALSE;
}
if (BigNumber == NULL) {
return FALSE;
}
*BnSize = BN_bn2bin (BnKey, BigNumber) ;
return TRUE;
}
/**
Generates RSA key components.
This function generates RSA key components. It takes RSA public exponent E 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
)
{
BIGNUM *KeyE;
BOOLEAN RetVal;
//
// Check input parameters.
//
if (RsaContext == NULL) {
return FALSE;
}
KeyE = BN_new ();
if (PublicExponent == NULL) {
BN_set_word (KeyE, 0x10001);
} else {
BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE);
}
RetVal = FALSE;
if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) {
RetVal = TRUE;
}
BN_free (KeyE);
return RetVal;
}
/**
Validates key components of RSA context.
This function validates key compoents 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
)
{
UINTN Reason;
//
// Check input parameters.
//
if (RsaContext == NULL) {
return FALSE;
}
if (RSA_check_key ((RSA *) RsaContext) != 1) {
Reason = ERR_GET_REASON (ERR_peek_last_error ());
if (Reason == RSA_R_P_NOT_PRIME ||
Reason == RSA_R_Q_NOT_PRIME ||
Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q ||
Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1) {
return FALSE;
}
}
return TRUE;
}
/**
Performs the PKCS1-v1_5 encoding methods defined in RSA PKCS #1.
@param Message Message buffer to be encoded.
@param MessageSize Size of message buffer in bytes.
@param DigestInfo Pointer to buffer of digest info for output.
@return Size of DigestInfo in bytes.
**/
UINTN
DigestInfoEncoding (
IN CONST UINT8 *Message,
IN UINTN MessageSize,
OUT UINT8 *DigestInfo
)
{
CONST UINT8 *HashDer;
UINTN DerSize;
//
// Check input parameters.
//
if (Message == NULL || DigestInfo == NULL) {
return FALSE;
}
//
// The original message length is used to determine the hash algorithm since
// message is digest value hashed by the specified algorithm.
//
switch (MessageSize) {
case MD5_DIGEST_SIZE:
HashDer = Asn1IdMd5;
DerSize = sizeof (Asn1IdMd5);
break;
case SHA1_DIGEST_SIZE:
HashDer = Asn1IdSha1;
DerSize = sizeof (Asn1IdSha1);
break;
case SHA256_DIGEST_SIZE:
HashDer = Asn1IdSha256;
DerSize = sizeof (Asn1IdSha256);
break;
default:
return FALSE;
}
CopyMem (DigestInfo, HashDer, DerSize);
CopyMem (DigestInfo + DerSize, Message, MessageSize);
return (DerSize + MessageSize);
}
/**
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 or SHA-256 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
)
{
RSA *Rsa;
UINTN Size;
INTN ReturnVal;
//
// Check input parameters.
//
if (RsaContext == NULL || MessageHash == NULL ||
(HashSize != MD5_DIGEST_SIZE && HashSize != SHA1_DIGEST_SIZE && HashSize != SHA256_DIGEST_SIZE)) {
return FALSE;
}
Rsa = (RSA *) RsaContext;
Size = BN_num_bytes (Rsa->n);
if (*SigSize < Size) {
*SigSize = Size;
return FALSE;
}
if (Signature == NULL) {
return FALSE;
}
Size = DigestInfoEncoding (MessageHash, HashSize, Signature);
ReturnVal = RSA_private_encrypt (
(UINT32) Size,
Signature,
Signature,
Rsa,
RSA_PKCS1_PADDING
);
if (ReturnVal < (INTN) Size) {
return FALSE;
}
*SigSize = (UINTN)ReturnVal;
return TRUE;
}
/**
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 or SHA-256 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 UINT8 *Signature,
IN UINTN SigSize
)
{
INTN Length;
//
// Check input parameters.
//
if (RsaContext == NULL || MessageHash == NULL || Signature == NULL) {
return FALSE;
}
//
// Check for unsupported hash size:
// Only MD5, SHA-1 or SHA-256 digest size is supported
//
if (HashSize != MD5_DIGEST_SIZE && HashSize != SHA1_DIGEST_SIZE && HashSize != SHA256_DIGEST_SIZE) {
return FALSE;
}
//
// RSA PKCS#1 Signature Decoding using OpenSSL RSA Decryption with Public Key
//
Length = RSA_public_decrypt (
(UINT32) SigSize,
Signature,
Signature,
RsaContext,
RSA_PKCS1_PADDING
);
//
// Invalid RSA Key or PKCS#1 Padding Checking Failed (if Length < 0)
// NOTE: Length should be the addition of HashSize and some DER value.
// Ignore more strict length checking here.
//
if (Length < (INTN) HashSize) {
return FALSE;
}
//
// Validate the MessageHash and Decoded Signature
// NOTE: The decoded Signature should be the DER encoding of the DigestInfo value
// DigestInfo ::= SEQUENCE {
// digestAlgorithm AlgorithmIdentifier
// digest OCTET STRING
// }
// Then Memory Comparing should skip the DER value of the underlying SEQUENCE
// type and AlgorithmIdentifier.
//
if (CompareMem (MessageHash, Signature + Length - HashSize, HashSize) == 0) {
//
// Valid RSA PKCS#1 Signature
//
return TRUE;
} else {
//
// Failed to verification
//
return FALSE;
}
}

View File

@ -2,7 +2,7 @@
Base Memory Allocation Routines Wrapper for Crypto library over OpenSSL
during PEI & DXE phases.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at

View File

@ -2,7 +2,7 @@
Light-weight Memory Management Routines for OpenSSL-based Crypto
Library at Runtime Phase.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at

View File

@ -37,7 +37,7 @@
[Sources]
RuntimeDxeIpfCryptLib.c
InternalCryptLib.h
Hash/CryptMd4Null.c
Hash/CryptMd5Null.c
Hash/CryptSha1Null.c