⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efibis_authfxns.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

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 + -