Skip to content
This repository has been archived by the owner on Aug 24, 2022. It is now read-only.

Commit

Permalink
Verify signed IAS vbmeta image for AIC
Browse files Browse the repository at this point in the history
Change-Id: I9b69a7d4c36d04b932a39889761b27801726e0d2
Tracked-On: OAM-85491
Signed-off-by: Yang, Kai <kaix.yang@intel.com>
Reviewed-on: https://android.intel.com:443/679347
  • Loading branch information
yang-kaix authored and buildslave committed Sep 4, 2019
1 parent 69f4106 commit 2534a6c
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 13 deletions.
30 changes: 29 additions & 1 deletion Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -577,5 +577,33 @@ ifeq ($(TARGET_USE_TRUSTY),true)
endif
LOCAL_STATIC_LIBRARIES += libavb_kernelflinger-$(TARGET_BUILD_VARIANT)

include $(BUILD_EFI_EXECUTABLE) # For kf4aic-$(TARGET_BUILD_VARIANT)
keys4aic_intermediates := $(call intermediates-dir-for,EFI,keys)

AIC_VERITY_CERT := $(keys4aic_intermediates)/verity.cer
AIC_PADDED_VERITY_CERT := $(keys4aic_intermediates)/verity.padded.cer
AIC_OEMCERT_OBJ := $(keys4aic_intermediates)/oemcert.o

$(AIC_VERITY_CERT): $(INTEL_PATH_BUILD)/testkeys/xbl_default.x509.pem $(OPENSSL)
$(transform-pem-cert-to-der-cert)

$(AIC_PADDED_VERITY_CERT): $(AIC_VERITY_CERT)
$(call pad-binary, 4096)

ifeq ($(TARGET_IAFW_ARCH),x86_64)
ELF_OUTPUT := elf64-x86-64
else
ELF_OUTPUT := elf32-i386
endif

aic_sym_binary := $(shell echo _binary_$(AIC_PADDED_VERITY_CERT) | sed "s/[\/\.-]/_/g")
$(AIC_OEMCERT_OBJ): $(AIC_PADDED_VERITY_CERT)
mkdir -p $(@D) && \
$(EFI_OBJCOPY) --input binary --output $(ELF_OUTPUT) --binary-architecture i386 $< $@ && \
$(EFI_OBJCOPY) --redefine-sym $(aic_sym_binary)_start=_binary_oemcert_start \
--redefine-sym $(aic_sym_binary)_end=_binary_oemcert_end \
--redefine-sym $(aic_sym_binary)_size=_binary_oemcert_size \
--rename-section .data=.oemkeys $@ $@

LOCAL_GENERATED_SOURCES := $(AIC_OEMCERT_OBJ)

include $(BUILD_EFI_EXECUTABLE) # For kf4aic-$(TARGET_BUILD_VARIANT)
109 changes: 97 additions & 12 deletions libkernelflinger/vbmeta_ias.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "protocol.h"
#include "gpt.h"
#include "log.h"
#include "vars.h"
#include "security.h"

#define IASIMAGE_MAX_SUB_IMAGE 32
Expand All @@ -58,23 +59,27 @@ typedef struct { // an IAS image generic header:
UINT32 headerCrc; // CRC-32C over entire header
} IASIMAGE_HEADER;

#define IAS_EXT_HDR(h) ((UINT32*) (((UINT64) (h)) + sizeof(IASIMAGE_HEADER)))
#define IAS_PAYLOAD(h) ((UINT32*) ((h)->dataOffset + ((UINT64) (h))))
#define MAGIC_PATTERN 0x2E6B7069
#define IAS_IMAGE_TYPE(it) (((it) & 0xffff0000) >> 16)
#define IAS_IMAGE_IS_SIGNED(it) ((it) & 0x100)
#define IAS_EXT_HDR(h) ((UINTN) (h) + sizeof(IASIMAGE_HEADER))
#define IAS_PAYLOAD(h) ((UINTN) (h) + (h)->dataOffset)
#define IAS_PAYLOAD_END(h) (IAS_PAYLOAD(h) + (h)->dataLength + sizeof(UINT32))
#define IAS_EXT_HDR_SIZE(h) ((h)->dataOffset - sizeof(IASIMAGE_HEADER))
#define ROUNDED_DOWN(val, align) ((val) & ~((align) - 1))
#define ROUNDED_UP(val, align) ROUNDED_DOWN((val) + (align) - 1, (align))

#define IAS_SIGNATURE(h) (((UINTN)(h)) + ROUNDED_UP((h)->dataOffset + (h)->dataLength + sizeof(UINT32), 256))

/*Obtain sub files from ias image*/
static EFI_STATUS ias_get_sub_files(void *iasimage, UINT32 numImg,
IASIMAGE_DATA *img, UINT32 *numFile)
{
UINT32 *imgSize;
UINT32 *addr;
UINT32 *subFileSizeArray;
VOID *addr;
UINT32 index;
IASIMAGE_HEADER *header = (IASIMAGE_HEADER*)iasimage;

imgSize = IAS_EXT_HDR(header);
subFileSizeArray = (UINT32 *)IAS_EXT_HDR(header);
*numFile = IAS_EXT_HDR_SIZE (header) / sizeof (UINT32);

//Return error if num of sub files is not even, as filepath and filehash should exist as pair
Expand All @@ -83,12 +88,12 @@ static EFI_STATUS ias_get_sub_files(void *iasimage, UINT32 numImg,

if (numImg != 0) {
ZeroMem(img, numImg * sizeof(img[0]));
addr = IAS_PAYLOAD(header);
addr = (VOID *)IAS_PAYLOAD(header);

// If there are sub-images (Index.e NumFile > 0) return their addresses and sizes.
for (index = 0 ; index < numImg && index < *numFile ; index += 1) {
img[index].addr = addr;
img[index].size = imgSize[index];
img[index].size = subFileSizeArray[index];
addr = (UINT32 *) ((UINT8 *)addr + ROUNDED_UP(img[index].size, 4));
}
}
Expand Down Expand Up @@ -167,14 +172,94 @@ static EFI_STATUS verify_file_hash(CHAR8* filename,
return ret;
}

static X509 *der_to_x509(CONST UINT8 *der, UINTN size)
{
BIO *bio;
X509 *x509;

/* BIO is the OpenSSL input/output abstraction. Instantiate
* one using a memory buffer containing the certificate */
bio = BIO_new_mem_buf((void *)der, size);
if (!bio)
return NULL;

/* Obtain an x509 structure from the DER cert data */
x509 = d2i_X509_bio(bio, NULL);
BIO_free(bio);
return x509;
}

static EVP_PKEY *get_rsa_pubkey(X509 *cert)
{
EVP_PKEY *pkey = X509_get_pubkey(cert);
if (!pkey)
return NULL;

if (EVP_PKEY_RSA != EVP_PKEY_type(pkey->type)) {
EVP_PKEY_free(pkey);
return NULL;
}
return pkey;
}

/*Signature check ias iamge*/
static EFI_STATUS verify_ias_image(void *iasimage,BOOLEAN* verify_pass)
static EFI_STATUS verify_ias_image(void *iasimage, BOOLEAN* verify_pass)
{
UINT8 *signature_data;
CHAR8 datahash[32] = {0};
UINT32 datalen = 0;
EVP_PKEY *pkey = NULL;
RSA *rsa;
EFI_STATUS ret;
int rsa_ret;

IASIMAGE_HEADER *header = (IASIMAGE_HEADER*)iasimage;
Print(L"iasimge->imageType = %x: verify ias image TBD\n", header->imageType);
if (header->magicPattern != MAGIC_PATTERN){
error(L"[IAS image] Check magic pattern fail\n");
return EFI_INVALID_PARAMETER;
}

if (IAS_IMAGE_TYPE(header->imageType)!= 0x4){
error(L"[IAS image] Check imageType fail\n");
return EFI_INVALID_PARAMETER;
}

//TBD
*verify_pass = TRUE;
return EFI_SUCCESS;
//CRC check

if (!IAS_IMAGE_IS_SIGNED(header->imageType)){
error(L"[IAS image] Image is unsigned\n");
return EFI_INVALID_PARAMETER;
}

signature_data = (UINT8*)IAS_SIGNATURE(header);
datalen = (UINTN)IAS_PAYLOAD_END(header) - (UINTN) header;

SHA256(iasimage, datalen, datahash);

X509 *cert = der_to_x509(oem_cert, oem_cert_size);
pkey = get_rsa_pubkey(cert);
if (!pkey)
return EFI_INVALID_PARAMETER;

rsa = EVP_PKEY_get1_RSA(pkey);
if (!rsa) {
ret = EFI_INVALID_PARAMETER;
goto free_pkey;
}

rsa_ret = RSA_verify(NID_sha256,
datahash, 32, signature_data, 256, rsa);
if (rsa_ret == 1)
*verify_pass = TRUE;
else
*verify_pass = FALSE;

ret = EFI_SUCCESS;

free_pkey:
EVP_PKEY_free(pkey);
return ret;
}

/*Verify vbmeta iasimage's integerity*/
Expand Down

0 comments on commit 2534a6c

Please sign in to comment.