📄 efibis_authfxns.c
字号:
/*++
Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name: efibis_authFxns.c
Abstract: contain the replaceable authorization functions that bis
calls when no certificate is currently installed on a
platform.
Revision History
--*/
#include <efi.h>
#include <efidriverlib.h>
#include <bisBaseCode.h>
///////////////////////////////////////////////////////////////////////////////
//
// The following functions are compiled only if the interactive version of
// the authorization functions are to be used. Uncomment the #define
// below to enable the interactive authorization function.
//
///////////////////////////////////////////////////////////////////////////////
//#define INTERACTIVE_AUTHORIZATION_REQUIRED
#ifdef INTERACTIVE_AUTHORIZATION_REQUIRED
///////////////////////////////////////////////////////////////////////////////
//
// Type Name: AUTHORIZATION_STATE, AUTHORIZATION_STATE_PTR
//
// Description:
// This is a type internal to the authorization sample. It stores the
// previous authorized identity certificate if there is one. This is used
// for subsequent automatic authorization if the same identity is
// presented, or updated if a different identity is presented.
//
// Definitions:
// AUTH_MAX_STORED_CERT - length in bytes of maximum storage space for a
// remembered authorized identity.
// hasAuthorityCert - TRUE if the authorization state is currently
// storing a (possibly truncated) authorized
// identity certificate.
// authorityCertLen - The length in bytes of the (possibly truncated)
// authorized identity certificate. Valid only
// when hasAuthorityCert is TRUE.
// authorityCert - A pointer to the (possibly truncated) authorized
// identity certificate data. Data is valid only
// when hasAuthorityCert is TRUE.
///////////////////////////////////////////////////////////////////////////////
#define AUTH_MAX_STORED_CERT 2048
typedef
struct tag_AUTHORIZATION_STATE {
BOOLEAN hasAuthorityCert;
UINT32 authorityCertLen;
UINT8 * authorityCert;
} AUTHORIZATION_STATE;
///////////////////////////////////////////////////////////////////////////////
// Forward declarations:
///////////////////////////////////////////////////////////////////////////////
typedef
struct tag_CERT_SCAN_STATE
CERT_SCAN_STATE;
static
BOOLEAN
IsWithinBuffer(
IN CERT_SCAN_STATE *scanState,
IN UINT32 numBytes
);
static
BOOLEAN
ExtractTag(
IN OUT CERT_SCAN_STATE *scanState,
OUT UINT8 *tag
);
static
BOOLEAN
ExtractLength(
IN OUT CERT_SCAN_STATE *scanState,
OUT UINT32 *length
);
static
BOOLEAN
SkipSequence(
IN OUT CERT_SCAN_STATE *scanState
);
static
BOOLEAN
GetSignatureFromCert(
IN EFI_BIS_DATA *cert,
IN UINT32 maxLength,
OUT UINT32 *length,
OUT UINT8 *signature);
static
BOOLEAN
QueryUserAuthorization(
IN EFI_BIS_CALLING_FUNCTION CallingFunction,
IN EFI_BIS_DATA *thisAuthority
);
static
BOOLEAN
MatchesAuthorityCert(
IN AUTHORIZATION_STATE *rememberedAuthority,
IN EFI_BIS_DATA *thisAuthority
);
static
EFI_STATUS
SaveAuthority(
IN OUT AUTHORIZATION_STATE *rememberedAuthority,
IN EFI_BIS_DATA *thisAuthority
);
typedef
struct tag_ACCUMULATED_STRING
ACCUMULATED_STRING;
static
BOOLEAN
AppendToString(
IN OUT ACCUMULATED_STRING *currentString,
IN CHAR16 *newString,
IN UINT32 newLength
);
///////////////////////////////////////////////////////////////////////////////
// Function Name: MatchesAuthorityCert
//
// Description:
// This internal function tests whether the passed thisAuthority
// certificate matches the stored authority certificate, if any, at least
// up to the point where the stored authority certificate is truncated.
//
// Parameters:
// rememberedAuthority - (IN) Supplies a pointer to the remembered
// authority state structure
// thisAuthority - (IN) Supplies a pointer to the new signer
// certificate to be tested to see if it
// matches the remembered certificate.
//
// Returns:
// TRUE if there is a remembered certificate and the new certificate
// matches up to the truncation point, otherwise FALSE.
//
///////////////////////////////////////////////////////////////////////////////
static
BOOLEAN
MatchesAuthorityCert(
IN AUTHORIZATION_STATE *rememberedAuthority,
IN EFI_BIS_DATA *thisAuthority
)
{
BOOLEAN to_return;
if (rememberedAuthority->hasAuthorityCert)
{
UINT32 target_len = rememberedAuthority->authorityCertLen;
UINT32 new_len = thisAuthority->Length;
// Truncate the length we may compare
if (new_len > AUTH_MAX_STORED_CERT)
{
new_len = AUTH_MAX_STORED_CERT;
}
// If the lengths don't match, the certs are different
if (target_len != new_len)
{
to_return = FALSE;
}
// Otherwise the (possibly truncated) lengths are the same, so we must
// compare the contents
else
{
UINT32 i;
UINT8 * target_array = rememberedAuthority->authorityCert;
UINT8 * new_array = thisAuthority->Data;
// Setup a "success" result in case we fall through the loop
// without finding a difference.
to_return = TRUE;
for (i=0; i<target_len; i++)
{
if (target_array[i] != new_array[i])
{
to_return = FALSE;
break;
}
}
} // else compare contents
} // if ... hasAuthorityCert
else
{
to_return = FALSE;
}
return to_return;
} // MatchesAuthorityCert
///////////////////////////////////////////////////////////////////////////////
// Function Name: SaveAuthority
//
// Description:
// This internal procedure saves up to the allowed maximum number of bytes
// of the indicated new thisAuthority certificate.
//
// Parameters:
// rememberedAuthority - (IN OUT) Supplies a pointer to the remembered
// authority state structure where the
// (possibly truncated) new certificate
// will be stored.
// thisAuthority - (IN) Supplies a pointer to the new signer
// certificate to be saved.
//
// Returns:
// none
//
///////////////////////////////////////////////////////////////////////////////
static
EFI_STATUS
SaveAuthority(
IN OUT AUTHORIZATION_STATE *rememberedAuthority,
IN EFI_BIS_DATA *thisAuthority
)
{
EFI_STATUS to_return = EFI_SUCCESS;
UINT32 new_len = thisAuthority->Length;
UINT8 *new_array = thisAuthority->Data;
UINT8 *target_array;
UINT32 i;
// Truncate if required
if (new_len > AUTH_MAX_STORED_CERT)
{
new_len = AUTH_MAX_STORED_CERT;
}
rememberedAuthority->authorityCert = (UINT8*)AllocateZeroPool(new_len);
if (rememberedAuthority->authorityCert)
{
target_array = rememberedAuthority->authorityCert;
for (i=0; i<new_len; i++)
{
target_array[i] = new_array[i];
}
rememberedAuthority->authorityCertLen = new_len;
rememberedAuthority->hasAuthorityCert = TRUE;
}
else
{
DEBUG((D_ERROR,
"AUTHFXNS: Memory allocation failed\n"));
to_return = EFI_OUT_OF_RESOURCES;
}
return to_return;
} // SaveAuthority
///////////////////////////////////////////////////////////////////////////////
// Internal user-interaction and string-fomatting functions
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Type Name: ACCUMULATED_STRING, * ACCUMULATED_STRING_PTR
//
// Description:
// This type is used to accumulate a string by appending characters to the
// end.
//
// Definitions:
// buffer - The buffer where the string is assembled
// maxLength - The length of the buffer in bytes
// length - Number of bytes currently in the string
///////////////////////////////////////////////////////////////////////////////
typedef
struct tag_ACCUMULATED_STRING {
CHAR16 *buffer;
UINT32 maxLength;
UINT32 length;
} ACCUMULATED_STRING;
///////////////////////////////////////////////////////////////////////////////
// Function Name: QueryUserAuthorization
//
// Description:
// This internal procedure queries the user to see if the indicated signer
// certificate for the indicated operation is from an accepted authority.
//
// Parameters:
// CallingFunction - (IN) Supplies the operation code of the operation
// that needed external authorization.
// thisAuthority - (IN) Supplies a pointer to the new signer
// certificate to be tested.
//
// Returns:
// TRUE if the user accepts the indicated certificate, otherwise
// FALSE;
//
///////////////////////////////////////////////////////////////////////////////
// The following strings are really intended to be constants. They are
// declared as static globals instead of #define strings to keep multiple
// references from causing them to appear multiple times in the generated code.
static UINT16 QUERY_LEAD[] = L"\n\nRequest to ";
static UINT16 QUERY_BOOT[] = L"boot";
static UINT16 QUERY_UPDATE[] = L"change boot security";
static UINT16 QUERY_UNKNOWN[] = L"do <unknown>";
static UINT16 QUERY_TRAIL[] = L" with signature:\n\r";
static UINT16 QUERY_BAD_SIG[] = L"UNRECOGNIZED CERTIFICATE FORMAT\n\r";
static UINT16 QUERY_QUESTION[] = L"Allow request to proceed? (y or n) --> ";
// A raw DSA signature is actually a SEQUENCE of two DER-encoded 20-byte
// integers. Each raw integer needs a 1-byte sequence tag plus a 1-byte length
// value, plus a possible 1-byte leading-0 extension (depending on the value of
// the most significant bit of the integer). So each integer may take as many
// as 23 bytes to represent. The SEQUENCE header in front of these consists of
// a 1-byte SEQUENCE tag plus a 1-byte length value. Altogether the raw DSA
// signature takes up a maximum of 1+1+(2*23) = 48 bytes. The minimum is 46
// bytes.
#define MAX_SIGNATURE_BYTES_TO_SHOW (48)
#define RESP_BUFFER_LENGTH 2
#define QUERY_BUFFER_LEN ( \
sizeof(QUERY_LEAD) - 2 + \
sizeof(QUERY_UPDATE) - 2 + \
sizeof(QUERY_TRAIL) - 2 + \
2)
static
BOOLEAN
QueryUserAuthorization(
IN EFI_BIS_CALLING_FUNCTION CallingFunction,
IN EFI_BIS_DATA *thisAuthority
)
{
CHAR16 query_buffer[QUERY_BUFFER_LEN];
ACCUMULATED_STRING query;
BOOLEAN ok_so_far;
UINT8 sig_buffer[MAX_SIGNATURE_BYTES_TO_SHOW];
UINT32 sig_len;
BOOLEAN got_sig;
BOOLEAN to_return;
CHAR16 *resp = NULL;
query.buffer = query_buffer;
query.maxLength = QUERY_BUFFER_LEN;
query.length = 0;
resp = AllocateZeroPool(RESP_BUFFER_LENGTH);
if (!resp)
{
ok_so_far = FALSE;
}
if (ok_so_far)
{
ok_so_far = AppendToString(
& query, // currentString
QUERY_LEAD, // newString
BisStrLen(QUERY_LEAD)); // newLength
}
if (ok_so_far)
{
switch (CallingFunction)
{
case BisCallingFunctionVerify:
ok_so_far = AppendToString(
& query, // currentString
QUERY_BOOT, // newString
BisStrLen(QUERY_BOOT)); // newLength
break;
case BisCallingFunctionUpdate:
ok_so_far = AppendToString(
& query, // currentString
QUERY_UPDATE, // newString
BisStrLen(QUERY_UPDATE)); // newLength
break;
default:
ok_so_far = AppendToString(
& query, // currentString
QUERY_UNKNOWN, // newString
BisStrLen(QUERY_UNKNOWN)); // newLength
break;
} // switch CallingFunction
}
if (ok_so_far)
{
ok_so_far = AppendToString(
& query, // currentString
QUERY_TRAIL, // newString
BisStrLen(QUERY_TRAIL)); // newLength
}
if (ok_so_far)
{
// Null terminate the query
ok_so_far = AppendToString(
&query, // currentSgtring
L"\0", // newString
2); // newLength
Output(query.buffer);
}
if (ok_so_far)
{
got_sig = GetSignatureFromCert(
thisAuthority, // cert
MAX_SIGNATURE_BYTES_TO_SHOW, // maxLength
& sig_len, // length
sig_buffer); // signature
}
if (ok_so_far)
{
if (got_sig)
{
DumpHex( 2, // Indent
0, // Byte offset into UserData
MAX_SIGNATURE_BYTES_TO_SHOW, // bytes to print
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -