📄 efibis_authfxns.c
字号:
&sig_buffer); // User data
}
else
{
Output(QUERY_BAD_SIG);
}
}
Input(QUERY_QUESTION, // Query
resp, // character to read
RESP_BUFFER_LENGTH); // maximum characters to read
if ((*resp == L'y') ||
(*resp == L'Y'))
{
to_return = TRUE;
}
else
{
to_return = FALSE;
}
if (resp)
{
FreePool(resp);
}
Output(L"\n\n"); // give a couple of blank lines for readability purpose
// I don't know how to clear the screen.....
// Clear the screen by writing a form-feed '\f'.
//query_buffer[0]= '\f';
//AuthWriteConsoleString(
// query_buffer, // msgBuffer
// 1); // msgLength
return to_return;
} // QueryUserAuthorization
///////////////////////////////////////////////////////////////////////////////
// Function Name: AppendToString
//
// Description:
// This internal function appends the indicated bytes to the end of the
// accumulated string.
//
// Parameters:
// currentString - (IN OUT) The accumulated string so far
// newString - (IN) The buffer containing contents to be added
// newLength - (IN) Number of bytes to be added
//
// Returns:
// TRUE if there was room to add the newString. Otherwise the function
// returns FALSE and currentString is not modified.
///////////////////////////////////////////////////////////////////////////////
static
BOOLEAN
AppendToString(
IN OUT ACCUMULATED_STRING *currentString,
IN CHAR16 *newString,
IN UINT32 newLength
)
{
BOOLEAN to_return;
UINT32 current_length = currentString->length;
UINT16 *target_buffer = currentString->buffer;
if (current_length + newLength > currentString->maxLength)
{
to_return = FALSE;
}
else
{
UINT32 i;
to_return = TRUE;
for (i=0; i<newLength; i++)
{
target_buffer[current_length + i] = newString[i];
}
currentString->length += newLength;
}
return to_return;
} // AppendToString
///////////////////////////////////////////////////////////////////////////////
// Basic Certificate-parsing functions
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// The following is a small collection of types and procedures that are used to
// extract a minimal amount of information from a certificate, in particular,
// some or all of the digital signature bit string. These procedures are
// designed to handle a DER-encoded PKCS-6 ExtendedCertificate or a X.509
// Certificate. From the point of view of these procedures, the overall
// structure of these two types is basically the same, consisting of:
//
// SEQUENCE {
// SEQUENCE {
// -- main contents of certificate
// }
// SEQUENCE {
// -- signature algorithm identifier and parameters
// }
// signature BIT STRING
// }
//
// PKCS-6 and X.509 certificate definitions are described in "PKCS#6:
// Extended-Certificate Syntax Standard". A useful explanation of the syntax
// notation and a guide to the BER/DER encoding of certificates can be found in
// "A Layman's Guide to a Subset of ASN.1, BER, and DER". Both of these
// documents can be retrieved online through the URL:
//
// http://www.rsa.com/rsalabs/pubs/PKCS/index.html
//
// Another extensive and readable explanation of X.509v3 certificates is the
// "X.509 Style Guide", which can be found at the URL:
//
// http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Type Name: CERT_SCAN_STATE, CERT_SCAN_STATE_PTR
//
// Description:
// This internal type is used by the collection of procedures that
// scan through a certificate. The type keeps track of how far the
// scan has proceeded. This type is only intended to be manipulated
// by those procedures.
//
// Definitions:
// certBuffer - A pointer to the in-memory copy of the certificate data
// certLength - The length, in bytes, of the in-memory copy of the
// certificate data
// currentOffset - The current offset, in bytes, of the next byte to be
// examined in the certificate buffer.
///////////////////////////////////////////////////////////////////////////////
typedef
struct tag_CERT_SCAN_STATE {
UINT8 *certBuffer;
UINT32 certLength;
UINT32 currentOffset;
} CERT_SCAN_STATE;
///////////////////////////////////////////////////////////////////////////////
// Function Name: GetSignatureFromCert
//
// Description:
// This internal function extracts and returns up to the indicated number
// of bytes of the raw signature BIT STRING from a PKCS-6
// ExtendedCertificateOrCertificate.
//
// Parameters:
// cert - (IN) Supplies the certificate to be examined
// maxLength - (IN) Supplies the maximum number of bytes of signature BIT
// STRING that may be returned.
// length - (OUT) Returns the number of bytes of signature BIT STRING
// that were retrieved if the function is successful.
// signature - (OUT) Returns the signature BIT STRING contents if the
// function is successful.
//
// Returns:
// TRUE if successful, otherwise the function returns FALSE and
// the OUT parameters are undefined.
//
///////////////////////////////////////////////////////////////////////////////
static
BOOLEAN
GetSignatureFromCert(
IN EFI_BIS_DATA *cert,
IN UINT32 maxLength,
OUT UINT32 *length,
OUT UINT8 *signature)
{
CERT_SCAN_STATE scanState;
BOOLEAN ok_so_far;
UINT8 tag;
UINT32 sig_length;
scanState.certBuffer = cert->Data;
scanState.certLength = cert->Length;
scanState.currentOffset = 0;
// Extract and check the outer sequence tag
ok_so_far = ExtractTag(
& scanState, // scanState
& tag); // tag
if (ok_so_far)
{
// The first tag should be either 0x30 (sequence) for a X.509
// certificate or 0xA0 (implicit context-specific contructed id 0) for
// a PKCS-6 ExtendedCertificate. In either case, the tag actually
// represents the outer SEQUENCE.
#define BISCERT_X509_OUTERTAG (0x30)
#define BISCERT_PKCS6_EXT_OUTERTAG (0xA0)
if ((tag != BISCERT_X509_OUTERTAG) &&
(tag != BISCERT_PKCS6_EXT_OUTERTAG))
{
ok_so_far = FALSE;
}
}
// Extract and ignore the outer length
if (ok_so_far)
{
UINT32 dont_care;
ok_so_far = ExtractLength(
& scanState, // scanState
& dont_care); // length
}
// Skip the main Certificate body sequence
if (ok_so_far)
{
ok_so_far = SkipSequence(
& scanState); // scanState
}
// Skip the signature algorithm identifier sequence
if (ok_so_far)
{
ok_so_far = SkipSequence(
& scanState); // scanState
}
// Remainder should be a Universal, Primitive, BIT STRING which is the
// signature. Check and extract it.
if (ok_so_far)
{
ok_so_far = ExtractTag(
& scanState, // scanState
& tag); // tag
}
// The tag should be 0x03, representing a BIT STRING
#define BISCERT_BIT_STRING_TAG (0x03)
if (ok_so_far)
{
if (tag != BISCERT_BIT_STRING_TAG)
{
ok_so_far = FALSE;
}
}
if (ok_so_far)
{
ok_so_far = ExtractLength(
& scanState, // scanState
& sig_length); // length
}
// Check containment of the BIT STRING contents
if (ok_so_far)
{
ok_so_far = IsWithinBuffer(
& scanState, // scanState
sig_length); // numBytes
}
// First byte of BIT STRING contents tells how many non-significant bits
// are in the last byte of the BIT STRING bits. We simply ignore this,
// skip it, and reduce our expected remaining content length accordingly.
if (ok_so_far)
{
scanState.currentOffset ++;
sig_length --;
// Require at least one byte of actual signature BIT STRING bits
if (sig_length < 1)
{
ok_so_far = FALSE;
}
}
if (ok_so_far)
{
UINT32 bytes_to_copy;
UINT32 start_offset;
UINT32 i;
bytes_to_copy = maxLength;
if (bytes_to_copy > sig_length)
{
bytes_to_copy = sig_length;
}
start_offset = scanState.currentOffset;
for (i=0; i<bytes_to_copy; i++)
{
signature[i] = cert->Data[start_offset + i];
}
scanState.currentOffset += sig_length; // for consistency
* length = bytes_to_copy;
}
return ok_so_far;
} // GetSignatureFromCert
///////////////////////////////////////////////////////////////////////////////
// Function Name: SkipSequence
//
// Description:
// This internal function scans past a SEQUENCE in the indicated
// certificate. It does not extract and return any values. The scan
// state is updated appropriately.
//
// The scan state must be pointing to the beginning of the SEQUENCE (i.e.,
// the SEQUENCE type tag) when called. When this function returns the
// scan state points to the next byte past the SEQUENCE content.
//
// Parameters:
// scanState - (IN OUT) Holds information about the certificate and the
// state of the scan
//
// Returns:
// TRUE if successful, otherwise FALSE.
//
///////////////////////////////////////////////////////////////////////////////
static
BOOLEAN
SkipSequence(
IN OUT CERT_SCAN_STATE *scanState
)
{
UINT32 seq_len;
UINT8 tag;
BOOLEAN ok_so_far;
ok_so_far = ExtractTag(
scanState, // scanState
& tag); // tag
if (ok_so_far)
{
// Tag must be 0x30 for sequence
#define BISCERT_SEQUENCE_TAG (0x30)
if (tag != BISCERT_SEQUENCE_TAG)
{
ok_so_far = FALSE;
}
}
if (ok_so_far)
{
ok_so_far = ExtractLength(
scanState, // scanState
& seq_len); // length
}
if (ok_so_far)
{
// check containment of skipped sequence content bytes
ok_so_far = IsWithinBuffer(
scanState, // scanState
seq_len); // numBytes
}
if (ok_so_far)
{
// skip the sequence content bytes
scanState->currentOffset += seq_len;
}
return ok_so_far;
} // SkipSequence
///////////////////////////////////////////////////////////////////////////////
// Function Name: ExtractTag
//
// Description:
// This internal function extracts and returns a type tag from the
// indicated certificate. The scan state is updated appropriately.
//
// The scan state must be pointing to the beginning of the type tag when
// called. When this function returns the scan state points to the next
// byte past the type tag.
//
// Parameters:
// scanState - (IN OUT) Holds information about the certificate and the
// state of the scan
// tag - (OUT) Returns the retrieved tag if the function is
// successful.
//
// Returns:
// TRUE if successful, otherwise FALSE.
//
///////////////////////////////////////////////////////////////////////////////
static
BOOLEAN
ExtractTag(
IN OUT CERT_SCAN_STATE *scanState,
OUT UINT8 * tag
)
{
BOOLEAN ok_so_far;
UINT8 temp_tag;
// The first byte of a type tag is as follows:
// 8 7 6 5 4 3 2 1
// +---+---+---+---+---+---+---+---+
// | C C |P/C| ID Code |
// +---+---+---+---+---+---+---+---+
// CC is the "class", meaning:
// 00 Universal
// 01 Application-specific
// 10 Context-specific
// 11 Private
//
// P/C indicates Primitive or Constructed:
// 0 Primitive type
// 1 Constructed type
//
// ID Code is a type identifier code. The special identifier code 0x1F
// indicates that the type tag extends into additional bytes. We'll
// simply report a failure for this since we don't expect to encounter
// any such type tags.
#define BISCERT_IDCODE_MASK (0x1F)
#define BISCERT_EXTENDED_TYPE_TAG (0x1F)
ok_so_far = IsWithinBuffer(
scanState, // scanState
1); // numBytes
if (ok_so_far)
{
temp_tag = scanState->certBuffer[scanState->currentOffset];
* tag = temp_tag;
scanState->currentOffset ++;
if ((temp_tag & BISCERT_IDCODE_MASK) == BISCERT_EXTENDED_TYPE_TAG)
{
ok_so_far = FALSE; // fail due to expanding tag
}
}
return ok_so_far;
} // ExtractTag
///////////////////////////////////////////////////////////////////////////////
// Function Name: ExtractLength
//
// Description:
// This internal function extracts and returns a length value from the
// indicated certificate. The scan state is updated appropriately.
//
// The scan state must be pointing to the beginning of the length value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -