/* * Serpent SBox Expressions * (C) 1999-2007,2013 Jack Lloyd * * The sbox expressions used here were discovered by Dag Arne Osvik and * are described in his paper "Speeding Up Serpent". * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_SERPENT_SBOX_H__ #define BOTAN_SERPENT_SBOX_H__ #define SBoxE1(T, B0, B1, B2, B3) \ do { \ T B4; \ B3 ^= B0; \ B4 = B1; \ B1 &= B3; \ B4 ^= B2; \ B1 ^= B0; \ B0 |= B3; \ B0 ^= B4; \ B4 ^= B3; \ B3 ^= B2; \ B2 |= B1; \ B2 ^= B4; \ B4 = ~B4; \ B4 |= B1; \ B1 ^= B3; \ B1 ^= B4; \ B3 |= B0; \ B1 ^= B3; \ B4 ^= B3; \ B3 = B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxE2(T, B0, B1, B2, B3) \ do { \ T B4; \ B0 = ~B0; \ B2 = ~B2; \ B4 = B0; \ B0 &= B1; \ B2 ^= B0; \ B0 |= B3; \ B3 ^= B2; \ B1 ^= B0; \ B0 ^= B4; \ B4 |= B1; \ B1 ^= B3; \ B2 |= B0; \ B2 &= B4; \ B0 ^= B1; \ B1 &= B2; \ B1 ^= B0; \ B0 &= B2; \ B4 ^= B0; \ B0 = B2; \ B2 = B3; \ B3 = B1; \ B1 = B4; \ } while(0); #define SBoxE3(T, B0, B1, B2, B3) \ do { \ T B4 = B0; \ B0 &= B2; \ B0 ^= B3; \ B2 ^= B1; \ B2 ^= B0; \ B3 |= B4; \ B3 ^= B1; \ B4 ^= B2; \ B1 = B3; \ B3 |= B4; \ B3 ^= B0; \ B0 &= B1; \ B4 ^= B0; \ B1 ^= B3; \ B1 ^= B4; \ B0 = B2; \ B2 = B1; \ B1 = B3; \ B3 = ~B4; \ } while(0); #define SBoxE4(T, B0, B1, B2, B3) \ do { \ T B4 = B0; \ B0 |= B3; \ B3 ^= B1; \ B1 &= B4; \ B4 ^= B2; \ B2 ^= B3; \ B3 &= B0; \ B4 |= B1; \ B3 ^= B4; \ B0 ^= B1; \ B4 &= B0; \ B1 ^= B3; \ B4 ^= B2; \ B1 |= B0; \ B1 ^= B2; \ B0 ^= B3; \ B2 = B1; \ B1 |= B3; \ B0 ^= B1; \ B1 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxE5(T, B0, B1, B2, B3) \ do { \ T B4; \ B1 ^= B3; \ B3 = ~B3; \ B2 ^= B3; \ B3 ^= B0; \ B4 = B1; \ B1 &= B3; \ B1 ^= B2; \ B4 ^= B3; \ B0 ^= B4; \ B2 &= B4; \ B2 ^= B0; \ B0 &= B1; \ B3 ^= B0; \ B4 |= B1; \ B4 ^= B0; \ B0 |= B3; \ B0 ^= B2; \ B2 &= B3; \ B0 = ~B0; \ B4 ^= B2; \ B2 = B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxE6(T, B0, B1, B2, B3) \ do { \ T B4; \ B0 ^= B1; \ B1 ^= B3; \ B3 = ~B3; \ B4 = B1; \ B1 &= B0; \ B2 ^= B3; \ B1 ^= B2; \ B2 |= B4; \ B4 ^= B3; \ B3 &= B1; \ B3 ^= B0; \ B4 ^= B1; \ B4 ^= B2; \ B2 ^= B0; \ B0 &= B3; \ B2 = ~B2; \ B0 ^= B4; \ B4 |= B3; \ B4 ^= B2; \ B2 = B0; \ B0 = B1; \ B1 = B3; \ B3 = B4; \ } while(0); #define SBoxE7(T, B0, B1, B2, B3) \ do { \ T B4; \ B2 = ~B2; \ B4 = B3; \ B3 &= B0; \ B0 ^= B4; \ B3 ^= B2; \ B2 |= B4; \ B1 ^= B3; \ B2 ^= B0; \ B0 |= B1; \ B2 ^= B1; \ B4 ^= B0; \ B0 |= B3; \ B0 ^= B2; \ B4 ^= B3; \ B4 ^= B0; \ B3 = ~B3; \ B2 &= B4; \ B3 ^= B2; \ B2 = B4; \ } while(0); #define SBoxE8(T, B0, B1, B2, B3) \ do { \ T B4 = B1; \ B1 |= B2; \ B1 ^= B3; \ B4 ^= B2; \ B2 ^= B1; \ B3 |= B4; \ B3 &= B0; \ B4 ^= B2; \ B3 ^= B1; \ B1 |= B4; \ B1 ^= B0; \ B0 |= B4; \ B0 ^= B2; \ B1 ^= B4; \ B2 ^= B1; \ B1 &= B0; \ B1 ^= B4; \ B2 = ~B2; \ B2 |= B0; \ B4 ^= B2; \ B2 = B1; \ B1 = B3; \ B3 = B0; \ B0 = B4; \ } while(0); #define SBoxD1(T, B0, B1, B2, B3) \ do { \ T B4; \ B2 = ~B2; \ B4 = B1; \ B1 |= B0; \ B4 = ~B4; \ B1 ^= B2; \ B2 |= B4; \ B1 ^= B3; \ B0 ^= B4; \ B2 ^= B0; \ B0 &= B3; \ B4 ^= B0; \ B0 |= B1; \ B0 ^= B2; \ B3 ^= B4; \ B2 ^= B1; \ B3 ^= B0; \ B3 ^= B1; \ B2 &= B3; \ B4 ^= B2; \ B2 = B1; \ B1 = B4; \ } while(0); #define SBoxD2(T, B0, B1, B2, B3) \ do { \ T B4 = B1; \ B1 ^= B3; \ B3 &= B1; \ B4 ^= B2; \ B3 ^= B0; \ B0 |= B1; \ B2 ^= B3; \ B0 ^= B4; \ B0 |= B2; \ B1 ^= B3; \ B0 ^= B1; \ B1 |= B3; \ B1 ^= B0; \ B4 = ~B4; \ B4 ^= B1; \ B1 |= B0; \ B1 ^= B0; \ B1 |= B4; \ B3 ^= B1; \ B1 = B0; \ B0 = B4; \ B4 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxD3(T, B0, B1, B2, B3) \ do { \ T B4; \ B2 ^= B3; \ B3 ^= B0; \ B4 = B3; \ B3 &= B2; \ B3 ^= B1; \ B1 |= B2; \ B1 ^= B4; \ B4 &= B3; \ B2 ^= B3; \ B4 &= B0; \ B4 ^= B2; \ B2 &= B1; \ B2 |= B0; \ B3 = ~B3; \ B2 ^= B3; \ B0 ^= B3; \ B0 &= B1; \ B3 ^= B4; \ B3 ^= B0; \ B0 = B1; \ B1 = B4; \ } while(0); #define SBoxD4(T, B0, B1, B2, B3) \ do { \ T B4 = B2; \ B2 ^= B1; \ B0 ^= B2; \ B4 &= B2; \ B4 ^= B0; \ B0 &= B1; \ B1 ^= B3; \ B3 |= B4; \ B2 ^= B3; \ B0 ^= B3; \ B1 ^= B4; \ B3 &= B2; \ B3 ^= B1; \ B1 ^= B0; \ B1 |= B2; \ B0 ^= B3; \ B1 ^= B4; \ B0 ^= B1; \ B4 = B0; \ B0 = B2; \ B2 = B3; \ B3 = B4; \ } while(0); #define SBoxD5(T, B0, B1, B2, B3) \ do { \ T B4 = B2; \ B2 &= B3; \ B2 ^= B1; \
/** @file
GPT low level actions
Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the GNU Lesser General Public License, version 3.0 (LGPL-3.0).
The full text of the license may be found at
https://opensource.org/licenses/LGPL-3.0
**/
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <Library/BaseMemoryLib.h>
#include <Uefi/UefiGpt.h>
#include <Guid/Gpt.h>
#include <Library/CommonLib.h>
/**
Checks the CRC32 value in the table header.
@param MaxSize Max Size limit
@param Size The size of the table
@param Hdr Table to check
@return TRUE CRC Valid
@return FALSE CRC Invalid
**/
BOOLEAN
GptHeaderCheckCrcAltSize(
IN UINTN MaxSize,
IN UINTN Size,
IN OUT EFI_TABLE_HEADER *Hdr
)
{
UINT32 Crc;
UINT32 OrgCrc;
EFI_STATUS Status;
Crc = 0;
if (Size == 0) {
//
// If header size is 0 CRC will pass so return FALSE here
//
return FALSE;
}
if ((MaxSize != 0) && (Size > MaxSize)) {
return FALSE;
}
//
// clear old crc from header
//
OrgCrc = Hdr->CRC32;
Hdr->CRC32 = 0;
Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc);
Hdr->CRC32 = OrgCrc;
if (EFI_ERROR(Status)) {
return FALSE;
}
// set results
return (BOOLEAN)(OrgCrc == Crc);
}
/**
Checks the CRC32 value in the table header.
@param MaxSize Max Size limit
@param Hdr Table to check
@return TRUE CRC Valid
@return FALSE CRC Invalid
**/
BOOLEAN
GptHeaderCheckCrc(
IN UINTN MaxSize,
IN OUT EFI_TABLE_HEADER *Hdr
)
{
return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr);
}
EFI_STATUS
GptCheckEntryArray(
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
IN EFI_PARTITION_ENTRY *Entrys
)
{
EFI_STATUS Status;
UINT32 Crc;
UINTN Size;
Size = (UINTN)PartHeader->NumberOfPartitionEntries * (UINTN)PartHeader->SizeOfPartitionEntry;
Status = gBS->CalculateCrc32(Entrys, Size, &Crc);
if (EFI_ERROR(Status)) {
return EFI_CRC_ERROR;
}
Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR;
return Status;
}
EFI_STATUS
GptUpdateCRC(
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
IN EFI_PARTITION_ENTRY *Entrys
)
{
EFI_STATUS Status;
UINT32 Crc;
UINTN Size;
Size = (UINTN)PartHeader->NumberOfPartitionEntries * (UINTN)PartHeader->SizeOfPartitionEntry;
Status = gBS->CalculateCrc32(Entrys, Size, &Crc);
if (EFI_ERROR(Status)) {
return Status;
}
PartHeader->PartitionEntryArrayCRC32 = Crc;
PartHeader->Header.CRC32 = 0;
Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc);
if (EFI_ERROR(Status)) {
return Status;
}
PartHeader->Header.CRC32 = Crc;
return Status;
}
/**
Read GPT
Check if the CRC field in the Partition table header is valid
for Partition entry array.
@param[in] BlockIo Disk Io Protocol.
@param[in] PartHeader Partition table header structure
@retval EFI_SUCCESS the CRC is valid
**/
EFI_STATUS
GptReadEntryArray(
IN EFI_BLOCK_IO_PROTOCOL* BlockIo,
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
OUT EFI_PARTITION_ENTRY **Entrys
)
{
EFI_STATUS Status;
UINT8 *Ptr;
//
// Read the EFI Partition Entries
//
Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
if (Ptr == NULL) {
return EFI_BUFFER_TOO_SMALL;
}
Status = BlockIo->ReadBlocks(
BlockIo,
BlockIo->Media->MediaId,
PartHeader->PartitionEntryLBA,
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
Ptr
);
if (EFI_ERROR(Status)) {
MEM_FREE(Ptr);
return Status;
}
*Entrys = (EFI_PARTITION_ENTRY*)Ptr;
return GptCheckEntryArray(PartHeader, *Entrys);
}
EFI_STATUS
GptReadHeader(
IN EFI_BLOCK_IO_PROTOCOL* BlockIo,
IN EFI_LBA HeaderLba,
OUT EFI_PARTITION_TABLE_HEADER **PartHeader
)
{
EFI_STATUS res = EFI_SUCCESS;
UINT32 BlockSize;
EFI_PARTITION_TABLE_HEADER *PartHdr;
UINT32 MediaId;
BlockSize = BlockIo->Media->BlockSize;
MediaId = BlockIo->Media->MediaId;
PartHdr = MEM_ALLOC(BlockSize);
res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr);
if (EFI_ERROR(res)) {
MEM_FREE(PartHdr);
return res;
}
// Check header
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
!GptHeaderCheckCrc(BlockSize, &PartHdr->Header) ||
PartHdr->MyLBA != HeaderLba ||
(PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))
) {
MEM_FREE(PartHdr);
return EFI_CRC_ERROR;
}
*PartHeader = PartHdr;
return EFI_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////
// General EFI tables
//////////////////////////////////////////////////////////////////////////
BOOLEAN
TablesVerify(
IN UINTN maxSize,
IN VOID* tables)
{
EFI_TABLE_HEADER *mhdr = (EFI_TABLE_HEADER *)tables;
if (tables != NULL &&
mhdr->Signature == EFITABLE_HEADER_SIGN &&
GptHeaderCheckCrc(maxSize, mhdr)) {
UINT8* raw = (UINT8*)tables;
UINTN rawSize = mhdr->HeaderSize;
UINTN tpos = sizeof(EFI_TABLE_HEADER);
while (tpos < rawSize) {
EFI_TABLE_HEADER *hdr = (EFI_TABLE_HEADER *)(raw + tpos);
if (!GptHeaderCheckCrc(rawSize - tpos, hdr)) {
return FALSE; // wrong crc
}
tpos += hdr->HeaderSize;
}
return TRUE;
}
return FALSE;
}
BOOLEAN
TablesGetData(
IN VOID* tables,
IN UINT64 sign,
OUT VOID** data,
OUT UINTN* size)
{
EFI_TABLE_HEADER *mhdr = (EFI_TABLE_HEADER *)tables;
if (tables != NULL &&
mhdr->Signature == EFITABLE_HEADER_SIGN &&
GptHeaderCheckCrc(0, mhdr)) {
UINT8* raw = (UINT8*)tables;
UINTN rawSize = mhdr->HeaderSize;
UINTN tpos = sizeof(EFI_TABLE_HEADER);
while (tpos < rawSize) {
EFI_TABLE_HEADER *hdr = (EFI_TABLE_HEADER *)(raw + tpos);
if (GptHeaderCheckCrc(rawSize - tpos, hdr)) {
if (hdr->Signature == sign) {
*data = raw + tpos + sizeof(EFI_TABLE_HEADER);
*size = hdr->HeaderSize - sizeof(EFI_TABLE_HEADER);
return TRUE;
}
tpos += hdr->HeaderSize;
}
else {
return FALSE;
}
}
}
return FALSE;
}
BOOLEAN
TablesDelete(
IN VOID* tables,
IN UINT64 sign
)
{
EFI_TABLE_HEADER *mhdr = (EFI_TABLE_HEADER *)tables;
EFI_TABLE_HEADER *thdr = NULL;
UINT8* raw = (UINT8*)tables;
UINTN rawSize = mhdr->HeaderSize;
UINTN tpos = sizeof(EFI_TABLE_HEADER);
if (tables != NULL &&
mhdr->Signature == EFITABLE_HEADER_SIGN &&
GptHeaderCheckCrc(0, mhdr)) {
while (tpos < rawSize) {
EFI_TABLE_HEADER *hdr = (EFI_TABLE_HEADER *)(raw + tpos);
if (GptHeaderCheckCrc(rawSize - tpos, hdr)) {
if (hdr->Signature == sign) {
thdr = hdr;
break;
}
tpos += hdr->HeaderSize;
} else {
return FALSE;
}
}
if (thdr != NULL) {
UINT32 Crc;
UINTN pos;
mhdr->HeaderSize -= thdr->HeaderSize;
pos = tpos + thdr->HeaderSize;
while (pos < rawSize) {
raw[tpos] = raw[pos];
++tpos;
++pos;
}
mhdr->CRC32 = 0;
if (EFI_ERROR(gBS->CalculateCrc32((UINT8 *)raw, mhdr->HeaderSize, &Crc))) {
return FALSE;
}
mhdr->CRC32 = Crc;
return TRUE;
}
}
return FALSE;
}
BOOLEAN
TablesAppend(
IN OUT VOID** tables,
IN UINT64 sign,
IN VOID* data,
IN UINTN size)
{
EFI_TABLE_HEADER *mhdr = NULL;
EFI_TABLE_HEADER *thdr = NULL;
UINTN rawSize = 0;
UINT8* raw = (UINT8*)tables;
if (tables != NULL &&
(mhdr = (EFI_TABLE_HEADER *)*tables) != NULL &&
mhdr->Signature == EFITABLE_HEADER_SIGN &&
GptHeaderCheckCrc(0, mhdr)) {
UINT32 Crc;
rawSize = mhdr->HeaderSize;
raw = MEM_REALLOC(rawSize, rawSize + sizeof(EFI_TABLE_HEADER) + size, mhdr);
if (raw == NULL) {
return FALSE;
}
mhdr = (EFI_TABLE_HEADER *)raw;
thdr = (EFI_TABLE_HEADER *)(raw + rawSize);
thdr->HeaderSize = (UINT32)(sizeof(EFI_TABLE_HEADER) + size);
thdr->Signature = sign;
CopyMem(((UINT8 *)thdr) + sizeof(EFI_TABLE_HEADER), data, size);
thdr->CRC32 = 0;
if (EFI_ERROR(gBS->CalculateCrc32((UINT8 *)thdr, thdr->HeaderSize, &Crc))) {
return FALSE;
}
thdr->CRC32 = Crc;
mhdr->HeaderSize += (UINT32)(size + sizeof(EFI_TABLE_HEADER));
mhdr->CRC32 = 0;
if (EFI_ERROR(gBS->CalculateCrc32((UINT8 *)raw, mhdr->HeaderSize, &Crc))) {
return FALSE;
}
mhdr->CRC32 = Crc;
*tables = raw;
return TRUE;
}
return FALSE;
}