Пример #1
0
static void _Sha256HmacInit(Sha256HmacCtx *Ctx, BYTE *key, size_t klen)
{
	BYTE  IPad[64];
	unsigned int  i;

	memset(IPad, 0x36, sizeof(IPad));
	memset(Ctx->OPad, 0x5C, sizeof(Ctx->OPad));

	if ( klen > 64 )
	{
		BYTE *temp = (BYTE*)alloca(32);
		Sha256(key, klen, temp);
		klen = 32;
		key  = temp;
	}

	for (i = 0; i < klen; i++)
	{
		IPad[ i ]      ^= key[ i ];
		Ctx->OPad[ i ] ^= key[ i ];
	}

	Sha256Init(&Ctx->ShaCtx);
	Sha256Update(&Ctx->ShaCtx, IPad, sizeof(IPad));
}
Пример #2
0
void Sha256(BYTE *data, size_t len, BYTE *hash)
{
	Sha256Ctx Ctx;

	Sha256Init(&Ctx);
	Sha256Update(&Ctx, data, len);
	Sha256Finish(&Ctx, hash);
}
Пример #3
0
static void _Sha256HmacFinish(Sha256HmacCtx *Ctx, BYTE *hmac)
{
	BYTE  temp[32];

	Sha256Finish(&Ctx->ShaCtx, temp);
	Sha256Init(&Ctx->ShaCtx);
	Sha256Update(&Ctx->ShaCtx, Ctx->OPad, sizeof(Ctx->OPad));
	Sha256Update(&Ctx->ShaCtx, temp, sizeof(temp));
	Sha256Finish(&Ctx->ShaCtx, hmac);
}
Пример #4
0
/**
  Start hash sequence.

  @param HashHandle Hash handle.

  @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.
  @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.
**/
EFI_STATUS
EFIAPI
Sha256HashInit (
  OUT HASH_HANDLE    *HashHandle
  )
{
  VOID     *Sha256Ctx;
  UINTN    CtxSize;

  CtxSize = Sha256GetContextSize ();
  Sha256Ctx = AllocatePool (CtxSize);
  ASSERT (Sha256Ctx != NULL);

  Sha256Init (Sha256Ctx);

  *HashHandle = (HASH_HANDLE)Sha256Ctx;

  return EFI_SUCCESS;
}
Пример #5
0
/**
  Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
  Follow the steps in UEFI2.2.

  @param[in]  VirtualMode             The current calling mode for this function.
  @param[in]  Global                  The context of this Extended SAL Variable Services Class call.
  @param[in]  Data                    The pointer to data with AuthInfo.
  @param[in]  DataSize                The size of Data.
  @param[in]  PubKey                  The public key used for verification.

  @retval EFI_INVALID_PARAMETER       Invalid parameter.
  @retval EFI_SECURITY_VIOLATION      Authentication failed.
  @retval EFI_SUCCESS                 Authentication successful.

**/
EFI_STATUS
VerifyDataPayload (
  IN  BOOLEAN                   VirtualMode,
  IN  ESAL_VARIABLE_GLOBAL      *Global,
  IN  UINT8                     *Data,
  IN  UINTN                     DataSize,
  IN  UINT8                     *PubKey
  )
{
  BOOLEAN                         Status;
  EFI_VARIABLE_AUTHENTICATION     *CertData;
  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;
  UINT8                           Digest[SHA256_DIGEST_SIZE];
  VOID                            *Rsa;
  VOID                            *HashContext;

  Rsa         = NULL;
  CertData    = NULL;
  CertBlock   = NULL;

  if (Data == NULL || PubKey == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;
  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);

  //
  // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
  // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256.
  //
  if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
      !CompareGuid (&CertData->AuthInfo.CertType, Global->CertRsa2048Sha256Guid[VirtualMode])
        ) {
    //
    // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
    //
    return EFI_SECURITY_VIOLATION;
  }

  //
  // Hash data payload with SHA256.
  //
  ZeroMem (Digest, SHA256_DIGEST_SIZE);
  HashContext = Global->HashContext[VirtualMode];
  Status  = Sha256Init (HashContext);
  if (!Status) {
    goto Done;
  }
  Status  = Sha256Update (HashContext, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));
  if (!Status) {
    goto Done;
  }
  //
  // Hash Monotonic Count.
  //
  Status  = Sha256Update (HashContext, &CertData->MonotonicCount, sizeof (UINT64));
  if (!Status) {
    goto Done;
  }
  Status  = Sha256Final (HashContext, Digest);
  if (!Status) {
    goto Done;
  }
  //
  // Generate & Initialize RSA Context.
  //
  Rsa = RsaNew ();
  ASSERT (Rsa != NULL);
  // 
  // Set RSA Key Components.
  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
  //
  Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
  if (!Status) {
    goto Done;
  }
  Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
  if (!Status) {
    goto Done;
  }
  //
  // Verify the signature.
  //
  Status = RsaPkcs1Verify (
             Rsa, 
             Digest, 
             SHA256_DIGEST_SIZE, 
             CertBlock->Signature, 
             EFI_CERT_TYPE_RSA2048_SHA256_SIZE
             );

Done:
  if (Rsa != NULL) {
    RsaFree (Rsa);
  }
  if (Status) {
    return EFI_SUCCESS;
  } else {
    return EFI_SECURITY_VIOLATION;
  }
}
/**

  Extraction handler tries to extract raw data from the input guided section.
  It also does authentication check for RSA 2048 SHA 256 signature in the input guided section.
  It first checks whether the input guid section is supported. 
  If not, EFI_INVALID_PARAMETER will return.

  @param InputSection    Buffer containing the input GUIDed section to be processed.
  @param OutputBuffer    Buffer to contain the output raw data allocated by the caller.
  @param ScratchBuffer   A pointer to a caller-allocated buffer for function internal use.
  @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
                              authentication status of the output buffer.

  @retval EFI_SUCCESS            Section Data and Auth Status is extracted successfully.
  @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.

**/
EFI_STATUS
EFIAPI
Rsa2048Sha256GuidedSectionHandler (
  IN CONST  VOID    *InputSection,
  OUT       VOID    **OutputBuffer,
  IN        VOID    *ScratchBuffer,        OPTIONAL
  OUT       UINT32  *AuthenticationStatus
  )
{
  EFI_STATUS                      Status;
  UINT32                          OutputBufferSize;
  VOID                            *DummyInterface;
  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlockRsa2048Sha256;
  BOOLEAN                         CryptoStatus;
  UINT8                           Digest[SHA256_DIGEST_SIZE];
  UINT8                           *PublicKey;
  UINTN                           PublicKeyBufferSize;
  VOID                            *HashContext;
  VOID                            *Rsa;
  
  HashContext = NULL;
  Rsa         = NULL;
  
  if (IS_SECTION2 (InputSection)) {
    //
    // Check whether the input guid section is recognized.
    //
    if (!CompareGuid (
        &gEfiCertTypeRsa2048Sha256Guid,
        &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid))) {
      return EFI_INVALID_PARAMETER;
    }
  
    //
    // Get the RSA 2048 SHA 256 information.
    //
    CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *) InputSection)->CertBlockRsa2048Sha256;
    OutputBufferSize       = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
    if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
      PERF_START (NULL, "RsaCopy", "DXE", 0);
      CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
      PERF_END (NULL, "RsaCopy", "DXE", 0);
    } else {
      *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
    }

    //
    // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
    //
    ASSERT ((((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
    *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
  } else {
    //
    // Check whether the input guid section is recognized.
    //
    if (!CompareGuid (
        &gEfiCertTypeRsa2048Sha256Guid,
        &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid))) {
      return EFI_INVALID_PARAMETER;
    }
  
    //
    // Get the RSA 2048 SHA 256 information.
    //
    CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
    OutputBufferSize       = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
    if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
      PERF_START (NULL, "RsaCopy", "DXE", 0);
      CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
      PERF_END (NULL, "RsaCopy", "DXE", 0);
    } else {
      *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
    }

    //
    // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
    //
    ASSERT ((((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
    *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
  }

  //
  // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
  //
  Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface);
  if (!EFI_ERROR (Status)) {
    //
    // If SecurityPolicy Protocol exist, AUTH platform override bit is set.
    //
    *AuthenticationStatus |= EFI_AUTH_STATUS_PLATFORM_OVERRIDE;
    
    return EFI_SUCCESS;
  }

  //
  // All paths from here return EFI_SUCESS and result is returned in AuthenticationStatus
  //
  Status = EFI_SUCCESS;
  
  //
  // Fail if the HashType is not SHA 256
  //
  if (!CompareGuid (&gEfiHashAlgorithmSha256Guid, &CertBlockRsa2048Sha256->HashType)) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: HASH type of section is not supported\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }

  //
  // Allocate hash context buffer required for SHA 256
  //
  HashContext = AllocatePool (Sha256GetContextSize ());
  if (HashContext == NULL) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Can not allocate hash context\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }

  //
  // Hash public key from data payload with SHA256.
  //
  ZeroMem (Digest, SHA256_DIGEST_SIZE);
  CryptoStatus = Sha256Init (HashContext);
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  CryptoStatus = Sha256Update (HashContext, &CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  CryptoStatus  = Sha256Final (HashContext, Digest);
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  
  //
  // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
  //
  PublicKey = (UINT8 *)PcdGetPtr (PcdRsa2048Sha256PublicKeyBuffer);
  DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer = %p\n", PublicKey));
  ASSERT (PublicKey != NULL);
  DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer Token = %08x\n", PcdToken (PcdRsa2048Sha256PublicKeyBuffer)));
  PublicKeyBufferSize = LibPcdGetExSize (&gEfiSecurityPkgTokenSpaceGuid, PcdToken (PcdRsa2048Sha256PublicKeyBuffer));
  DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer Size = %08x\n", PublicKeyBufferSize));
  ASSERT ((PublicKeyBufferSize % SHA256_DIGEST_SIZE) == 0);
  CryptoStatus = FALSE;
  while (PublicKeyBufferSize != 0) {
    if (CompareMem (Digest, PublicKey, SHA256_DIGEST_SIZE) == 0) {
      CryptoStatus = TRUE;
      break;
    }
    PublicKey = PublicKey + SHA256_DIGEST_SIZE;
    PublicKeyBufferSize = PublicKeyBufferSize - SHA256_DIGEST_SIZE;
  }
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Public key in section is not supported\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }

  //
  // Generate & Initialize RSA Context.
  //
  Rsa = RsaNew ();
  if (Rsa == NULL) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaNew() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  
  // 
  // Set RSA Key Components.
  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
  //
  CryptoStatus = RsaSetKey (Rsa, RsaKeyN, CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  CryptoStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }

  //
  // Hash data payload with SHA256.
  //
  ZeroMem (Digest, SHA256_DIGEST_SIZE);
  CryptoStatus = Sha256Init (HashContext);
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  PERF_START (NULL, "RsaShaData", "DXE", 0);
  CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
  PERF_END (NULL, "RsaShaData", "DXE", 0);
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }
  CryptoStatus  = Sha256Final (HashContext, Digest);
  if (!CryptoStatus) {
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    goto Done;
  }

  //
  // Verify the RSA 2048 SHA 256 signature.
  //
  PERF_START (NULL, "RsaVerify", "DXE", 0);
  CryptoStatus = RsaPkcs1Verify (
                   Rsa, 
                   Digest, 
                   SHA256_DIGEST_SIZE, 
                   CertBlockRsa2048Sha256->Signature, 
                   sizeof (CertBlockRsa2048Sha256->Signature)
                   );
  PERF_END (NULL, "RsaVerify", "DXE", 0);
  if (!CryptoStatus) {
    //
    // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
    //
    DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n"));
    *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
  }

Done:
  //
  // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
  //
  if (Rsa != NULL) {
    RsaFree (Rsa);
  }
  if (HashContext != NULL) {
    FreePool (HashContext);
  }

  DEBUG ((DEBUG_VERBOSE, "DxeRsa2048Sha256: Status = %r  AuthenticationStatus = %08x\n", Status, *AuthenticationStatus));

  return Status;
}
Пример #7
0
/**
  Calculates the hash of the given data based on the specified hash GUID.

  @param[in]  Data      Pointer to the data buffer to be hashed.
  @param[in]  DataSize  The size of data buffer in bytes.
  @param[in]  CertGuid  The GUID to identify the hash algorithm to be used.
  @param[out] HashValue Pointer to a buffer that receives the hash result.

  @retval TRUE          Data hash calculation succeeded.
  @retval FALSE         Data hash calculation failed.

**/
BOOLEAN
CalculateDataHash (
  IN  VOID               *Data,
  IN  UINTN              DataSize,
  IN  EFI_GUID           *CertGuid,
  OUT UINT8              *HashValue
  )
{
  BOOLEAN  Status;
  VOID     *HashCtx;
  UINTN    CtxSize;

  Status  = FALSE;
  HashCtx = NULL;

  if (CompareGuid (CertGuid, &gEfiCertSha1Guid)) {
    //
    // SHA-1 Hash
    //
    CtxSize = Sha1GetContextSize ();
    HashCtx = AllocatePool (CtxSize);
    if (HashCtx == NULL) {
      goto _Exit;
    }
    Status = Sha1Init   (HashCtx);
    Status = Sha1Update (HashCtx, Data, DataSize);
    Status = Sha1Final  (HashCtx, HashValue);

  } else if (CompareGuid (CertGuid, &gEfiCertSha256Guid)) {
    //
    // SHA256 Hash
    //
    CtxSize = Sha256GetContextSize ();
    HashCtx = AllocatePool (CtxSize);
    if (HashCtx == NULL) {
      goto _Exit;
    }
    Status = Sha256Init   (HashCtx);
    Status = Sha256Update (HashCtx, Data, DataSize);
    Status = Sha256Final  (HashCtx, HashValue);

  } else if (CompareGuid (CertGuid, &gEfiCertSha384Guid)) {
    //
    // SHA384 Hash
    //
    CtxSize = Sha384GetContextSize ();
    HashCtx = AllocatePool (CtxSize);
    if (HashCtx == NULL) {
      goto _Exit;
    }
    Status = Sha384Init   (HashCtx);
    Status = Sha384Update (HashCtx, Data, DataSize);
    Status = Sha384Final  (HashCtx, HashValue);

  } else if (CompareGuid (CertGuid, &gEfiCertSha512Guid)) {
    //
    // SHA512 Hash
    //
    CtxSize = Sha512GetContextSize ();
    HashCtx = AllocatePool (CtxSize);
    if (HashCtx == NULL) {
      goto _Exit;
    }
    Status = Sha512Init   (HashCtx);
    Status = Sha512Update (HashCtx, Data, DataSize);
    Status = Sha512Final  (HashCtx, HashValue);
  }

_Exit:
  if (HashCtx != NULL) {
    FreePool (HashCtx);
  }

  return Status;
}