2010-12-31 08:22:48 +01:00
|
|
|
/** @file
|
|
|
|
X.509 Certificate Handler Wrapper Implementation over OpenSSL.
|
|
|
|
|
2019-11-21 02:14:16 +01:00
|
|
|
Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
|
2019-04-04 01:03:30 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "InternalCryptLib.h"
|
|
|
|
#include <openssl/x509.h>
|
2015-10-29 15:15:53 +01:00
|
|
|
#include <openssl/rsa.h>
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
Construct a X509 object from DER-encoded certificate data.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If SingleX509Cert is NULL, then return FALSE.
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded certificate data.
|
|
|
|
@param[in] CertSize The size of certificate data in bytes.
|
|
|
|
@param[out] SingleX509Cert The generated X509 object.
|
|
|
|
|
|
|
|
@retval TRUE The X509 object generation succeeded.
|
|
|
|
@retval FALSE The operation failed.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
X509ConstructCertificate (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT UINT8 **SingleX509Cert
|
|
|
|
)
|
|
|
|
{
|
2015-06-16 02:54:16 +02:00
|
|
|
X509 *X509Cert;
|
|
|
|
CONST UINT8 *Temp;
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
// Check input parameters.
|
2011-08-16 08:46:52 +02:00
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
if ((Cert == NULL) || (SingleX509Cert == NULL) || (CertSize > INT_MAX)) {
|
2012-03-19 06:52:16 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2011-10-28 09:41:26 +02:00
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
//
|
|
|
|
// Read DER-encoded X509 Certificate and Construct X509 object.
|
|
|
|
//
|
2015-06-16 02:54:16 +02:00
|
|
|
Temp = Cert;
|
2021-12-05 23:53:54 +01:00
|
|
|
X509Cert = d2i_X509 (NULL, &Temp, (long)CertSize);
|
2011-08-16 08:46:52 +02:00
|
|
|
if (X509Cert == NULL) {
|
2012-12-28 02:20:57 +01:00
|
|
|
return FALSE;
|
2011-08-16 08:46:52 +02:00
|
|
|
}
|
|
|
|
|
2021-12-05 23:53:54 +01:00
|
|
|
*SingleX509Cert = (UINT8 *)X509Cert;
|
2011-08-16 08:46:52 +02:00
|
|
|
|
2012-12-28 02:20:57 +01:00
|
|
|
return TRUE;
|
2011-08-16 08:46:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Construct a X509 stack object from a list of DER-encoded certificate data.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If X509Stack is NULL, then return FALSE.
|
2019-11-21 02:14:16 +01:00
|
|
|
If this interface is not supported, then return FALSE.
|
2011-08-16 08:46:52 +02:00
|
|
|
|
2015-06-19 04:46:51 +02:00
|
|
|
@param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object.
|
2011-08-16 08:46:52 +02:00
|
|
|
On output, pointer to the X509 stack object with new
|
|
|
|
inserted X509 certificate.
|
2019-11-21 02:14:16 +01:00
|
|
|
@param[in] Args VA_LIST marker for the variable argument list.
|
|
|
|
A list of DER-encoded single certificate data followed
|
2011-08-16 08:46:52 +02:00
|
|
|
by certificate size. A NULL terminates the list. The
|
|
|
|
pairs are the arguments to X509ConstructCertificate().
|
2017-03-21 15:58:07 +01:00
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
@retval TRUE The X509 stack construction succeeded.
|
|
|
|
@retval FALSE The construction operation failed.
|
2019-11-21 02:14:16 +01:00
|
|
|
@retval FALSE This interface is not supported.
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
2019-11-21 02:14:16 +01:00
|
|
|
X509ConstructCertificateStackV (
|
|
|
|
IN OUT UINT8 **X509Stack,
|
|
|
|
IN VA_LIST Args
|
2011-08-16 08:46:52 +02:00
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:53:54 +01:00
|
|
|
UINT8 *Cert;
|
|
|
|
UINTN CertSize;
|
|
|
|
X509 *X509Cert;
|
|
|
|
|
|
|
|
STACK_OF (X509) *CertStack;
|
|
|
|
BOOLEAN Status;
|
|
|
|
UINTN Index;
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
// Check input parameters.
|
2011-08-16 08:46:52 +02:00
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
if (X509Stack == NULL) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
Status = FALSE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize X509 stack object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
CertStack = (STACK_OF (X509) *)(*X509Stack);
|
2011-08-16 08:46:52 +02:00
|
|
|
if (CertStack == NULL) {
|
|
|
|
CertStack = sk_X509_new_null ();
|
|
|
|
if (CertStack == NULL) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Index = 0; ; Index++) {
|
|
|
|
//
|
|
|
|
// If Cert is NULL, then it is the end of the list.
|
|
|
|
//
|
|
|
|
Cert = VA_ARG (Args, UINT8 *);
|
|
|
|
if (Cert == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CertSize = VA_ARG (Args, UINTN);
|
2015-06-16 02:54:16 +02:00
|
|
|
if (CertSize == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Construct X509 Object from the given DER-encoded certificate data.
|
|
|
|
//
|
2015-06-19 04:46:51 +02:00
|
|
|
X509Cert = NULL;
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (
|
|
|
|
(CONST UINT8 *)Cert,
|
|
|
|
CertSize,
|
|
|
|
(UINT8 **)&X509Cert
|
|
|
|
);
|
2011-08-16 08:46:52 +02:00
|
|
|
if (!Status) {
|
2015-06-16 02:54:16 +02:00
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Insert the new X509 object into X509 stack object.
|
|
|
|
//
|
|
|
|
sk_X509_push (CertStack, X509Cert);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Status) {
|
|
|
|
sk_X509_pop_free (CertStack, X509_free);
|
|
|
|
} else {
|
2021-12-05 23:53:54 +01:00
|
|
|
*X509Stack = (UINT8 *)CertStack;
|
2011-08-16 08:46:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2019-11-21 02:14:16 +01:00
|
|
|
/**
|
|
|
|
Construct a X509 stack object from a list of DER-encoded certificate data.
|
|
|
|
|
|
|
|
If X509Stack is NULL, then return FALSE.
|
|
|
|
|
|
|
|
@param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object.
|
|
|
|
On output, pointer to the X509 stack object with new
|
|
|
|
inserted X509 certificate.
|
|
|
|
@param ... A list of DER-encoded single certificate data followed
|
|
|
|
by certificate size. A NULL terminates the list. The
|
|
|
|
pairs are the arguments to X509ConstructCertificate().
|
|
|
|
|
|
|
|
@retval TRUE The X509 stack construction succeeded.
|
|
|
|
@retval FALSE The construction operation failed.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
X509ConstructCertificateStack (
|
|
|
|
IN OUT UINT8 **X509Stack,
|
|
|
|
...
|
|
|
|
)
|
|
|
|
{
|
|
|
|
VA_LIST Args;
|
|
|
|
BOOLEAN Result;
|
|
|
|
|
|
|
|
VA_START (Args, X509Stack);
|
|
|
|
Result = X509ConstructCertificateStackV (X509Stack, Args);
|
|
|
|
VA_END (Args);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
/**
|
|
|
|
Release the specified X509 object.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If X509Cert is NULL, then return FALSE.
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
@param[in] X509Cert Pointer to the X509 object to be released.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
X509Free (
|
|
|
|
IN VOID *X509Cert
|
|
|
|
)
|
2017-03-21 15:58:07 +01:00
|
|
|
{
|
2012-03-19 06:52:16 +01:00
|
|
|
//
|
|
|
|
// Check input parameters.
|
|
|
|
//
|
|
|
|
if (X509Cert == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-21 15:58:07 +01:00
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
//
|
|
|
|
// Free OpenSSL X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
X509_free ((X509 *)X509Cert);
|
2011-08-16 08:46:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Release the specified X509 stack object.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If X509Stack is NULL, then return FALSE.
|
2011-08-16 08:46:52 +02:00
|
|
|
|
|
|
|
@param[in] X509Stack Pointer to the X509 stack object to be released.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
EFIAPI
|
|
|
|
X509StackFree (
|
|
|
|
IN VOID *X509Stack
|
|
|
|
)
|
|
|
|
{
|
2012-03-19 06:52:16 +01:00
|
|
|
//
|
|
|
|
// Check input parameters.
|
|
|
|
//
|
|
|
|
if (X509Stack == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-21 15:58:07 +01:00
|
|
|
|
2011-08-16 08:46:52 +02:00
|
|
|
//
|
|
|
|
// Free OpenSSL X509 stack object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
sk_X509_pop_free ((STACK_OF (X509) *) X509Stack, X509_free);
|
2011-08-16 08:46:52 +02:00
|
|
|
}
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
/**
|
|
|
|
Retrieve the subject bytes from one X.509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] CertSubject Pointer to the retrieved certificate subject bytes.
|
|
|
|
@param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input,
|
|
|
|
and the size of buffer returned CertSubject on output.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If SubjectSize is NULL, then return FALSE.
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
@retval TRUE The certificate subject retrieved successfully.
|
|
|
|
@retval FALSE Invalid certificate, or the SubjectSize is too small for the result.
|
|
|
|
The SubjectSize will be updated with the required size.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
X509GetSubjectName (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT UINT8 *CertSubject,
|
|
|
|
IN OUT UINTN *SubjectSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BOOLEAN Status;
|
|
|
|
X509 *X509Cert;
|
|
|
|
X509_NAME *X509Name;
|
2015-10-29 15:16:15 +01:00
|
|
|
UINTN X509NameSize;
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
// Check input parameters.
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
if ((Cert == NULL) || (SubjectSize == NULL)) {
|
2012-03-19 06:52:16 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
X509Cert = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read DER-encoded X509 Certificate and Construct X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
|
2011-08-16 08:46:52 +02:00
|
|
|
if ((X509Cert == NULL) || (!Status)) {
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
|
|
|
// Retrieve subject name from certificate object.
|
|
|
|
//
|
|
|
|
X509Name = X509_get_subject_name (X509Cert);
|
2012-08-02 04:49:24 +02:00
|
|
|
if (X509Name == NULL) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2021-12-05 23:53:54 +01:00
|
|
|
X509NameSize = i2d_X509_NAME (X509Name, NULL);
|
2015-10-29 15:16:15 +01:00
|
|
|
if (*SubjectSize < X509NameSize) {
|
|
|
|
*SubjectSize = X509NameSize;
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2015-10-29 15:16:15 +01:00
|
|
|
*SubjectSize = X509NameSize;
|
2010-12-31 08:22:48 +01:00
|
|
|
if (CertSubject != NULL) {
|
2021-12-05 23:53:54 +01:00
|
|
|
i2d_X509_NAME (X509Name, &CertSubject);
|
2010-12-31 08:22:48 +01:00
|
|
|
Status = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Exit:
|
|
|
|
//
|
|
|
|
// Release Resources.
|
|
|
|
//
|
2012-08-02 04:49:24 +02:00
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
2017-09-24 17:42:16 +02:00
|
|
|
|
|
|
|
/**
|
2019-03-25 05:01:09 +01:00
|
|
|
Retrieve a string from one X.509 certificate base on the Request_NID.
|
2017-09-24 17:42:16 +02:00
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
2019-03-25 05:01:09 +01:00
|
|
|
@param[in] Request_NID NID of string to obtain
|
2017-09-24 17:42:16 +02:00
|
|
|
@param[out] CommonName Buffer to contain the retrieved certificate common
|
2018-05-24 10:08:51 +02:00
|
|
|
name string (UTF8). At most CommonNameSize bytes will be
|
2017-09-24 17:42:16 +02:00
|
|
|
written and the string will be null terminated. May be
|
|
|
|
NULL in order to determine the size buffer needed.
|
|
|
|
@param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
|
|
|
|
and the size of buffer returned CommonName on output.
|
|
|
|
If CommonName is NULL then the amount of space needed
|
|
|
|
in buffer (including the final null) is returned.
|
|
|
|
|
|
|
|
@retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
|
|
|
|
@retval RETURN_INVALID_PARAMETER If Cert is NULL.
|
|
|
|
If CommonNameSize is NULL.
|
|
|
|
If CommonName is not NULL and *CommonNameSize is 0.
|
|
|
|
If Certificate is invalid.
|
2019-03-25 05:01:09 +01:00
|
|
|
@retval RETURN_NOT_FOUND If no NID Name entry exists.
|
2017-09-24 17:42:16 +02:00
|
|
|
@retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
|
2018-06-27 11:32:13 +02:00
|
|
|
(including the final null) is returned in the
|
2017-09-24 17:42:16 +02:00
|
|
|
CommonNameSize parameter.
|
|
|
|
@retval RETURN_UNSUPPORTED The operation is not supported.
|
|
|
|
|
|
|
|
**/
|
2019-03-25 05:01:09 +01:00
|
|
|
STATIC
|
2017-09-24 17:42:16 +02:00
|
|
|
RETURN_STATUS
|
2019-03-25 05:01:09 +01:00
|
|
|
InternalX509GetNIDName (
|
2021-12-05 23:53:54 +01:00
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
IN INT32 Request_NID,
|
|
|
|
OUT CHAR8 *CommonName OPTIONAL,
|
|
|
|
IN OUT UINTN *CommonNameSize
|
2017-09-24 17:42:16 +02:00
|
|
|
)
|
|
|
|
{
|
2018-05-24 10:08:51 +02:00
|
|
|
RETURN_STATUS ReturnStatus;
|
|
|
|
BOOLEAN Status;
|
|
|
|
X509 *X509Cert;
|
|
|
|
X509_NAME *X509Name;
|
|
|
|
INT32 Index;
|
|
|
|
INTN Length;
|
|
|
|
X509_NAME_ENTRY *Entry;
|
|
|
|
ASN1_STRING *EntryData;
|
|
|
|
UINT8 *UTF8Name;
|
2017-09-24 17:42:16 +02:00
|
|
|
|
|
|
|
ReturnStatus = RETURN_INVALID_PARAMETER;
|
2018-05-24 10:08:51 +02:00
|
|
|
UTF8Name = NULL;
|
2017-09-24 17:42:16 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Check input parameters.
|
|
|
|
//
|
|
|
|
if ((Cert == NULL) || (CertSize > INT_MAX) || (CommonNameSize == NULL)) {
|
|
|
|
return ReturnStatus;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2017-09-24 17:42:16 +02:00
|
|
|
if ((CommonName != NULL) && (*CommonNameSize == 0)) {
|
|
|
|
return ReturnStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
X509Cert = NULL;
|
|
|
|
//
|
|
|
|
// Read DER-encoded X509 Certificate and Construct X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
|
2017-09-24 17:42:16 +02:00
|
|
|
if ((X509Cert == NULL) || (!Status)) {
|
|
|
|
//
|
|
|
|
// Invalid X.509 Certificate
|
|
|
|
//
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = FALSE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Retrieve subject name from certificate object.
|
|
|
|
//
|
|
|
|
X509Name = X509_get_subject_name (X509Cert);
|
|
|
|
if (X509Name == NULL) {
|
|
|
|
//
|
|
|
|
// Fail to retrieve subject name content
|
|
|
|
//
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2019-03-25 05:01:09 +01:00
|
|
|
// Retrive the string from X.509 Subject base on the Request_NID
|
2017-09-24 17:42:16 +02:00
|
|
|
//
|
2019-03-25 05:01:09 +01:00
|
|
|
Index = X509_NAME_get_index_by_NID (X509Name, Request_NID, -1);
|
2018-05-24 10:08:51 +02:00
|
|
|
if (Index < 0) {
|
2017-09-24 17:42:16 +02:00
|
|
|
//
|
2019-03-25 05:01:09 +01:00
|
|
|
// No Request_NID name entry exists in X509_NAME object
|
2017-09-24 17:42:16 +02:00
|
|
|
//
|
|
|
|
*CommonNameSize = 0;
|
|
|
|
ReturnStatus = RETURN_NOT_FOUND;
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2018-05-24 10:08:51 +02:00
|
|
|
Entry = X509_NAME_get_entry (X509Name, Index);
|
|
|
|
if (Entry == NULL) {
|
|
|
|
//
|
|
|
|
// Fail to retrieve name entry data
|
|
|
|
//
|
|
|
|
*CommonNameSize = 0;
|
|
|
|
ReturnStatus = RETURN_NOT_FOUND;
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
EntryData = X509_NAME_ENTRY_get_data (Entry);
|
|
|
|
|
|
|
|
Length = ASN1_STRING_to_UTF8 (&UTF8Name, EntryData);
|
|
|
|
if (Length < 0) {
|
|
|
|
//
|
2019-03-25 05:01:09 +01:00
|
|
|
// Fail to convert the Name string
|
2018-05-24 10:08:51 +02:00
|
|
|
//
|
|
|
|
*CommonNameSize = 0;
|
|
|
|
ReturnStatus = RETURN_INVALID_PARAMETER;
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2017-09-24 17:42:16 +02:00
|
|
|
if (CommonName == NULL) {
|
2018-05-24 10:08:51 +02:00
|
|
|
*CommonNameSize = Length + 1;
|
2021-12-05 23:53:54 +01:00
|
|
|
ReturnStatus = RETURN_BUFFER_TOO_SMALL;
|
2017-09-24 17:42:16 +02:00
|
|
|
} else {
|
2018-05-24 10:08:51 +02:00
|
|
|
*CommonNameSize = MIN ((UINTN)Length, *CommonNameSize - 1) + 1;
|
|
|
|
CopyMem (CommonName, UTF8Name, *CommonNameSize - 1);
|
|
|
|
CommonName[*CommonNameSize - 1] = '\0';
|
2021-12-05 23:53:54 +01:00
|
|
|
ReturnStatus = RETURN_SUCCESS;
|
2017-09-24 17:42:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_Exit:
|
|
|
|
//
|
|
|
|
// Release Resources.
|
|
|
|
//
|
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2018-05-24 10:08:51 +02:00
|
|
|
if (UTF8Name != NULL) {
|
|
|
|
OPENSSL_free (UTF8Name);
|
|
|
|
}
|
2017-09-24 17:42:16 +02:00
|
|
|
|
|
|
|
return ReturnStatus;
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
2019-03-25 05:01:09 +01:00
|
|
|
/**
|
|
|
|
Retrieve the common name (CN) string from one X.509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] CommonName Buffer to contain the retrieved certificate common
|
|
|
|
name string. At most CommonNameSize bytes will be
|
|
|
|
written and the string will be null terminated. May be
|
|
|
|
NULL in order to determine the size buffer needed.
|
|
|
|
@param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
|
|
|
|
and the size of buffer returned CommonName on output.
|
|
|
|
If CommonName is NULL then the amount of space needed
|
|
|
|
in buffer (including the final null) is returned.
|
|
|
|
|
|
|
|
@retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
|
|
|
|
@retval RETURN_INVALID_PARAMETER If Cert is NULL.
|
|
|
|
If CommonNameSize is NULL.
|
|
|
|
If CommonName is not NULL and *CommonNameSize is 0.
|
|
|
|
If Certificate is invalid.
|
|
|
|
@retval RETURN_NOT_FOUND If no CommonName entry exists.
|
|
|
|
@retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
|
|
|
|
(including the final null) is returned in the
|
|
|
|
CommonNameSize parameter.
|
|
|
|
@retval RETURN_UNSUPPORTED The operation is not supported.
|
|
|
|
|
|
|
|
**/
|
|
|
|
RETURN_STATUS
|
|
|
|
EFIAPI
|
|
|
|
X509GetCommonName (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
2021-12-03 03:00:39 +01:00
|
|
|
OUT CHAR8 *CommonName OPTIONAL,
|
2019-03-25 05:01:09 +01:00
|
|
|
IN OUT UINTN *CommonNameSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return InternalX509GetNIDName (Cert, CertSize, NID_commonName, CommonName, CommonNameSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Retrieve the organization name (O) string from one X.509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] NameBuffer Buffer to contain the retrieved certificate organization
|
|
|
|
name string. At most NameBufferSize bytes will be
|
|
|
|
written and the string will be null terminated. May be
|
|
|
|
NULL in order to determine the size buffer needed.
|
|
|
|
@param[in,out] NameBufferSize The size in bytes of the Name buffer on input,
|
|
|
|
and the size of buffer returned Name on output.
|
|
|
|
If NameBuffer is NULL then the amount of space needed
|
|
|
|
in buffer (including the final null) is returned.
|
|
|
|
|
|
|
|
@retval RETURN_SUCCESS The certificate Organization Name retrieved successfully.
|
|
|
|
@retval RETURN_INVALID_PARAMETER If Cert is NULL.
|
|
|
|
If NameBufferSize is NULL.
|
|
|
|
If NameBuffer is not NULL and *CommonNameSize is 0.
|
|
|
|
If Certificate is invalid.
|
|
|
|
@retval RETURN_NOT_FOUND If no Organization Name entry exists.
|
|
|
|
@retval RETURN_BUFFER_TOO_SMALL If the NameBuffer is NULL. The required buffer size
|
|
|
|
(including the final null) is returned in the
|
|
|
|
CommonNameSize parameter.
|
|
|
|
@retval RETURN_UNSUPPORTED The operation is not supported.
|
|
|
|
|
|
|
|
**/
|
|
|
|
RETURN_STATUS
|
|
|
|
EFIAPI
|
|
|
|
X509GetOrganizationName (
|
2021-12-05 23:53:54 +01:00
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT CHAR8 *NameBuffer OPTIONAL,
|
|
|
|
IN OUT UINTN *NameBufferSize
|
2019-03-25 05:01:09 +01:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return InternalX509GetNIDName (Cert, CertSize, NID_organizationName, NameBuffer, NameBufferSize);
|
|
|
|
}
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
/**
|
|
|
|
Retrieve the RSA Public Key from one DER-encoded X509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
|
|
|
|
RSA public key component. Use RsaFree() function to free the
|
|
|
|
resource.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If RsaContext is NULL, then return FALSE.
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
@retval TRUE RSA Public Key was retrieved successfully.
|
|
|
|
@retval FALSE Fail to retrieve RSA public key from X509 certificate.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
RsaGetPublicKeyFromX509 (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT VOID **RsaContext
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BOOLEAN Status;
|
|
|
|
EVP_PKEY *Pkey;
|
|
|
|
X509 *X509Cert;
|
2017-03-21 15:58:07 +01:00
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
// Check input parameters.
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
if ((Cert == NULL) || (RsaContext == NULL)) {
|
2012-03-19 06:52:16 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
Pkey = NULL;
|
|
|
|
X509Cert = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read DER-encoded X509 Certificate and Construct X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
|
2011-08-16 08:46:52 +02:00
|
|
|
if ((X509Cert == NULL) || (!Status)) {
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
|
|
|
// Retrieve and check EVP_PKEY data from X509 Certificate.
|
|
|
|
//
|
|
|
|
Pkey = X509_get_pubkey (X509Cert);
|
2017-03-21 15:58:07 +01:00
|
|
|
if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_RSA)) {
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Duplicate RSA Context from the retrieved EVP_PKEY.
|
|
|
|
//
|
2017-03-21 15:58:07 +01:00
|
|
|
if ((*RsaContext = RSAPublicKey_dup (EVP_PKEY_get0_RSA (Pkey))) != NULL) {
|
2010-12-31 08:22:48 +01:00
|
|
|
Status = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Exit:
|
|
|
|
//
|
|
|
|
// Release Resources.
|
|
|
|
//
|
2012-08-02 04:49:24 +02:00
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Pkey != NULL) {
|
|
|
|
EVP_PKEY_free (Pkey);
|
2017-03-21 15:58:07 +01:00
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Verify one X509 certificate was issued by the trusted CA.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate to be verified.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[in] CACert Pointer to the DER-encoded trusted CA certificate.
|
|
|
|
@param[in] CACertSize Size of the CA Certificate in bytes.
|
|
|
|
|
2012-03-19 06:52:16 +01:00
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If CACert is NULL, then return FALSE.
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
@retval TRUE The certificate was issued by the trusted CA.
|
|
|
|
@retval FALSE Invalid certificate or the certificate was not issued by the given
|
|
|
|
trusted CA.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
X509VerifyCert (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
IN CONST UINT8 *CACert,
|
|
|
|
IN UINTN CACertSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BOOLEAN Status;
|
|
|
|
X509 *X509Cert;
|
|
|
|
X509 *X509CACert;
|
|
|
|
X509_STORE *CertStore;
|
2017-03-21 15:58:07 +01:00
|
|
|
X509_STORE_CTX *CertCtx;
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
2012-03-19 06:52:16 +01:00
|
|
|
// Check input parameters.
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
if ((Cert == NULL) || (CACert == NULL)) {
|
2012-03-19 06:52:16 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
Status = FALSE;
|
|
|
|
X509Cert = NULL;
|
|
|
|
X509CACert = NULL;
|
|
|
|
CertStore = NULL;
|
2017-03-21 15:58:07 +01:00
|
|
|
CertCtx = NULL;
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Register & Initialize necessary digest algorithms for certificate verification.
|
|
|
|
//
|
2012-08-02 04:49:24 +02:00
|
|
|
if (EVP_add_digest (EVP_md5 ()) == 0) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
if (EVP_add_digest (EVP_sha1 ()) == 0) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
if (EVP_add_digest (EVP_sha256 ()) == 0) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Read DER-encoded certificate to be verified and Construct X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
|
2011-08-16 08:46:52 +02:00
|
|
|
if ((X509Cert == NULL) || (!Status)) {
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read DER-encoded root certificate and Construct X509 object.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **)&X509CACert);
|
2011-08-16 08:46:52 +02:00
|
|
|
if ((X509CACert == NULL) || (!Status)) {
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
Status = FALSE;
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
|
|
|
// Set up X509 Store for trusted certificate.
|
|
|
|
//
|
|
|
|
CertStore = X509_STORE_new ();
|
|
|
|
if (CertStore == NULL) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
if (!(X509_STORE_add_cert (CertStore, X509CACert))) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
2015-10-29 15:16:45 +01:00
|
|
|
//
|
|
|
|
// Allow partial certificate chains, terminated by a non-self-signed but
|
2015-10-29 15:16:54 +01:00
|
|
|
// still trusted intermediate certificate. Also disable time checks.
|
2015-10-29 15:16:45 +01:00
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
X509_STORE_set_flags (
|
|
|
|
CertStore,
|
|
|
|
X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
|
|
|
|
);
|
2015-10-29 15:16:45 +01:00
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
//
|
|
|
|
// Set up X509_STORE_CTX for the subsequent verification operation.
|
|
|
|
//
|
2017-03-21 15:58:07 +01:00
|
|
|
CertCtx = X509_STORE_CTX_new ();
|
|
|
|
if (CertCtx == NULL) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
2021-12-05 23:53:54 +01:00
|
|
|
|
2017-03-21 15:58:07 +01:00
|
|
|
if (!X509_STORE_CTX_init (CertCtx, CertStore, X509Cert, NULL)) {
|
2010-12-31 08:22:48 +01:00
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// X509 Certificate Verification.
|
|
|
|
//
|
2021-12-05 23:53:54 +01:00
|
|
|
Status = (BOOLEAN)X509_verify_cert (CertCtx);
|
2017-03-21 15:58:07 +01:00
|
|
|
X509_STORE_CTX_cleanup (CertCtx);
|
2010-12-31 08:22:48 +01:00
|
|
|
|
|
|
|
_Exit:
|
|
|
|
//
|
|
|
|
// Release Resources.
|
|
|
|
//
|
2012-08-02 04:49:24 +02:00
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (X509CACert != NULL) {
|
|
|
|
X509_free (X509CACert);
|
|
|
|
}
|
2010-12-31 08:22:48 +01:00
|
|
|
|
2012-08-02 04:49:24 +02:00
|
|
|
if (CertStore != NULL) {
|
|
|
|
X509_STORE_free (CertStore);
|
|
|
|
}
|
2017-03-21 15:58:07 +01:00
|
|
|
|
|
|
|
X509_STORE_CTX_free (CertCtx);
|
|
|
|
|
2010-12-31 08:22:48 +01:00
|
|
|
return Status;
|
|
|
|
}
|
2014-12-25 09:37:08 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
Retrieve the TBSCertificate from one given X.509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the given DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] TBSCert DER-Encoded To-Be-Signed certificate.
|
|
|
|
@param[out] TBSCertSize Size of the TBS certificate in bytes.
|
|
|
|
|
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If TBSCert is NULL, then return FALSE.
|
|
|
|
If TBSCertSize is NULL, then return FALSE.
|
|
|
|
|
|
|
|
@retval TRUE The TBSCertificate was retrieved successfully.
|
|
|
|
@retval FALSE Invalid X.509 certificate.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
X509GetTBSCert (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT UINT8 **TBSCert,
|
|
|
|
OUT UINTN *TBSCertSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CONST UINT8 *Temp;
|
2018-01-15 02:50:38 +01:00
|
|
|
UINT32 Asn1Tag;
|
|
|
|
UINT32 ObjClass;
|
2014-12-25 09:37:08 +01:00
|
|
|
UINTN Length;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check input parameters.
|
|
|
|
//
|
2015-06-16 02:54:16 +02:00
|
|
|
if ((Cert == NULL) || (TBSCert == NULL) ||
|
2021-12-05 23:53:54 +01:00
|
|
|
(TBSCertSize == NULL) || (CertSize > INT_MAX))
|
|
|
|
{
|
2014-12-25 09:37:08 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// An X.509 Certificate is: (defined in RFC3280)
|
|
|
|
// Certificate ::= SEQUENCE {
|
|
|
|
// tbsCertificate TBSCertificate,
|
|
|
|
// signatureAlgorithm AlgorithmIdentifier,
|
|
|
|
// signature BIT STRING }
|
|
|
|
//
|
|
|
|
// and
|
|
|
|
//
|
|
|
|
// TBSCertificate ::= SEQUENCE {
|
|
|
|
// version [0] Version DEFAULT v1,
|
|
|
|
// ...
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// So we can just ASN1-parse the x.509 DER-encoded data. If we strip
|
|
|
|
// the first SEQUENCE, the second SEQUENCE is the TBSCertificate.
|
|
|
|
//
|
2018-01-15 02:50:38 +01:00
|
|
|
Temp = Cert;
|
|
|
|
Length = 0;
|
2014-12-25 09:37:08 +01:00
|
|
|
ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize);
|
|
|
|
|
|
|
|
if (Asn1Tag != V_ASN1_SEQUENCE) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*TBSCert = (UINT8 *)Temp;
|
|
|
|
|
|
|
|
ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length);
|
|
|
|
//
|
|
|
|
// Verify the parsed TBSCertificate is one correct SEQUENCE data.
|
|
|
|
//
|
|
|
|
if (Asn1Tag != V_ASN1_SEQUENCE) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*TBSCertSize = Length + (Temp - *TBSCert);
|
2017-03-21 15:58:07 +01:00
|
|
|
|
2014-12-25 09:37:08 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
2022-10-12 04:47:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
Retrieve the EC Public Key from one DER-encoded X509 certificate.
|
|
|
|
|
|
|
|
@param[in] Cert Pointer to the DER-encoded X509 certificate.
|
|
|
|
@param[in] CertSize Size of the X509 certificate in bytes.
|
|
|
|
@param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
|
|
|
|
EC public key component. Use EcFree() function to free the
|
|
|
|
resource.
|
|
|
|
|
|
|
|
If Cert is NULL, then return FALSE.
|
|
|
|
If EcContext is NULL, then return FALSE.
|
|
|
|
|
|
|
|
@retval TRUE EC Public Key was retrieved successfully.
|
|
|
|
@retval FALSE Fail to retrieve EC public key from X509 certificate.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
EcGetPublicKeyFromX509 (
|
|
|
|
IN CONST UINT8 *Cert,
|
|
|
|
IN UINTN CertSize,
|
|
|
|
OUT VOID **EcContext
|
|
|
|
)
|
|
|
|
{
|
|
|
|
#if FixedPcdGetBool (PcdOpensslEcEnabled)
|
|
|
|
BOOLEAN Status;
|
|
|
|
EVP_PKEY *Pkey;
|
|
|
|
X509 *X509Cert;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check input parameters.
|
|
|
|
//
|
|
|
|
if ((Cert == NULL) || (EcContext == NULL)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pkey = NULL;
|
|
|
|
X509Cert = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read DER-encoded X509 Certificate and Construct X509 object.
|
|
|
|
//
|
|
|
|
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
|
|
|
|
if ((X509Cert == NULL) || (!Status)) {
|
|
|
|
Status = FALSE;
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = FALSE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Retrieve and check EVP_PKEY data from X509 Certificate.
|
|
|
|
//
|
|
|
|
Pkey = X509_get_pubkey (X509Cert);
|
|
|
|
if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_EC)) {
|
|
|
|
goto _Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Duplicate EC Context from the retrieved EVP_PKEY.
|
|
|
|
//
|
|
|
|
if ((*EcContext = EC_KEY_dup (EVP_PKEY_get0_EC_KEY (Pkey))) != NULL) {
|
|
|
|
Status = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Exit:
|
|
|
|
//
|
|
|
|
// Release Resources.
|
|
|
|
//
|
|
|
|
if (X509Cert != NULL) {
|
|
|
|
X509_free (X509Cert);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Pkey != NULL) {
|
|
|
|
EVP_PKEY_free (Pkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|