331 lines
7.9 KiB
C
331 lines
7.9 KiB
C
/******************************************************************************
|
||
* Copyright (c) 2012 - 2022 Xilinx, Inc. All rights reserved.
|
||
* SPDX-License-Identifier: MIT
|
||
******************************************************************************/
|
||
|
||
/*****************************************************************************/
|
||
/**
|
||
*
|
||
* @file rsa.c
|
||
*
|
||
* Contains code for the RSA authentication
|
||
*
|
||
* <pre>
|
||
* MODIFICATION HISTORY:
|
||
*
|
||
* Ver Who Date Changes
|
||
* ----- ---- -------- -------------------------------------------------------
|
||
* 4.00a sgd 02/28/13 Initial release
|
||
* 6.00a kc 07/30/13 Added FSBL_DEBUG_RSA to print more RSA buffers
|
||
* Fix for CR#724165 - Partition Header used by FSBL is
|
||
* not authenticated
|
||
* Fix for CR#724166 - FSBL doesn’t use PPK authenticated
|
||
* by Boot ROM for authenticating
|
||
* the Partition images
|
||
* Fix for CR#722979 - Provide customer-friendly
|
||
* changelogs in FSBL
|
||
* 9.00a kc 04/16/14 Fix for CR#724166 - SetPpk() will fail on secure
|
||
* fallback unless FSBL* and FSBL are
|
||
* identical in length
|
||
* Fix for CR#791245 - Use of xilrsa in FSBL
|
||
* 10.0 vns 03/18/22 Fixed CR#1125470 to authenticate the parition header buffer
|
||
* which is being used instead of one from DDR. Modified
|
||
* prototype of AuthenticatePartition() API
|
||
* </pre>
|
||
*
|
||
* @note
|
||
*
|
||
******************************************************************************/
|
||
|
||
/***************************** Include Files *********************************/
|
||
#ifdef RSA_SUPPORT
|
||
#include "fsbl.h"
|
||
#include "rsa.h"
|
||
#include "xilrsa.h"
|
||
|
||
#ifdef XPAR_XWDTPS_0_BASEADDR
|
||
#include "xwdtps.h"
|
||
#endif
|
||
|
||
/************************** Constant Definitions *****************************/
|
||
|
||
/**************************** Type Definitions *******************************/
|
||
|
||
|
||
/***************** Macros (Inline Functions) Definitions *********************/
|
||
|
||
|
||
/************************** Function Prototypes ******************************/
|
||
#ifdef XPAR_XWDTPS_0_BASEADDR
|
||
extern XWdtPs Watchdog; /* Instance of WatchDog Timer */
|
||
#endif
|
||
|
||
|
||
/************************** Variable Definitions *****************************/
|
||
|
||
static u8 *PpkModular;
|
||
static u8 *PpkModularEx;
|
||
static u32 PpkExp;
|
||
static u32 PpkAlreadySet=0;
|
||
|
||
extern u32 FsblLength;
|
||
|
||
void FsblPrintArray (u8 *Buf, u32 Len, char *Str)
|
||
{
|
||
#ifdef FSBL_DEBUG_RSA
|
||
int Index;
|
||
fsbl_printf(DEBUG_INFO, "%s START\r\n", Str);
|
||
for (Index=0;Index<Len;Index++)
|
||
{
|
||
fsbl_printf(DEBUG_INFO, "%02x",Buf[Index]);
|
||
if ((Index+1)%16 == 0){
|
||
fsbl_printf(DEBUG_INFO, "\r\n");
|
||
}
|
||
}
|
||
fsbl_printf(DEBUG_INFO, "\r\n %s END\r\n",Str);
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
/**
|
||
*
|
||
* This function is used to set ppk pointer to ppk in OCM
|
||
*
|
||
* @param None
|
||
*
|
||
* @return
|
||
*
|
||
* @note None
|
||
*
|
||
******************************************************************************/
|
||
|
||
void SetPpk(void )
|
||
{
|
||
u32 PadSize;
|
||
u8 *PpkPtr;
|
||
|
||
/*
|
||
* Set PPK only if is not already set
|
||
*/
|
||
if(PpkAlreadySet == 0)
|
||
{
|
||
|
||
/*
|
||
* Set PpkPtr to PPK in OCM
|
||
*/
|
||
|
||
/*
|
||
* Skip FSBL Length
|
||
*/
|
||
PpkPtr = (u8 *)(FsblLength);
|
||
/*
|
||
* Skip to 64 byte Boundary
|
||
*/
|
||
PadSize = ((u32)PpkPtr % 64);
|
||
if(PadSize != 0)
|
||
{
|
||
PpkPtr += (64 - PadSize);
|
||
}
|
||
|
||
/*
|
||
* Increment the pointer by authentication Header size
|
||
*/
|
||
PpkPtr += RSA_HEADER_SIZE;
|
||
|
||
/*
|
||
* Increment the pointer by Magic word size
|
||
*/
|
||
PpkPtr += RSA_MAGIC_WORD_SIZE;
|
||
|
||
/*
|
||
* Set pointer to PPK
|
||
*/
|
||
PpkModular = (u8 *)PpkPtr;
|
||
PpkPtr += RSA_PPK_MODULAR_SIZE;
|
||
PpkModularEx = (u8 *)PpkPtr;
|
||
PpkPtr += RSA_PPK_MODULAR_EXT_SIZE;
|
||
PpkExp = *((u32 *)PpkPtr);
|
||
|
||
/*
|
||
* Setting variable to avoid resetting PPK pointers
|
||
*/
|
||
PpkAlreadySet=1;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
/**
|
||
*
|
||
* This function Authenticate Partition Signature
|
||
*
|
||
* @param AC is the pointer to authentication certificate
|
||
* @param Hash is the pointer which holds the SHA2 digest of data
|
||
* to be authenticated.
|
||
*
|
||
* @return
|
||
* - XST_SUCCESS if Authentication passed
|
||
* - XST_FAILURE if Authentication failed
|
||
*
|
||
* @note None
|
||
*
|
||
******************************************************************************/
|
||
u32 AuthenticatePartition(u8 *Ac, u8* Hash)
|
||
{
|
||
u8 DecryptSignature[256];
|
||
u8 HashSignature[32];
|
||
u8 *SpkModular;
|
||
u8 *SpkModularEx;
|
||
u32 SpkExp;
|
||
u8 *SignaturePtr;
|
||
u32 Status;
|
||
|
||
#ifdef XPAR_XWDTPS_0_BASEADDR
|
||
/*
|
||
* Prevent WDT reset
|
||
*/
|
||
XWdtPs_RestartWdt(&Watchdog);
|
||
#endif
|
||
|
||
/*
|
||
* Point to Authentication Certificate
|
||
*/
|
||
SignaturePtr = (u8 *)Ac;
|
||
|
||
/*
|
||
* Increment the pointer by authentication Header size
|
||
*/
|
||
SignaturePtr += RSA_HEADER_SIZE;
|
||
|
||
/*
|
||
* Increment the pointer by Magic word size
|
||
*/
|
||
SignaturePtr += RSA_MAGIC_WORD_SIZE;
|
||
|
||
/*
|
||
* Increment the pointer beyond the PPK
|
||
*/
|
||
SignaturePtr += RSA_PPK_MODULAR_SIZE;
|
||
SignaturePtr += RSA_PPK_MODULAR_EXT_SIZE;
|
||
SignaturePtr += RSA_PPK_EXPO_SIZE;
|
||
|
||
/*
|
||
* Calculate Hash Signature
|
||
*/
|
||
sha_256((u8 *)SignaturePtr, (RSA_SPK_MODULAR_EXT_SIZE +
|
||
RSA_SPK_EXPO_SIZE + RSA_SPK_MODULAR_SIZE),
|
||
HashSignature);
|
||
FsblPrintArray(HashSignature, 32, "SPK Hash Calculated");
|
||
|
||
/*
|
||
* Extract SPK signature
|
||
*/
|
||
SpkModular = (u8 *)SignaturePtr;
|
||
SignaturePtr += RSA_SPK_MODULAR_SIZE;
|
||
SpkModularEx = (u8 *)SignaturePtr;
|
||
SignaturePtr += RSA_SPK_MODULAR_EXT_SIZE;
|
||
SpkExp = *((u32 *)SignaturePtr);
|
||
SignaturePtr += RSA_SPK_EXPO_SIZE;
|
||
|
||
/*
|
||
* Decrypt SPK Signature
|
||
*/
|
||
rsa2048_pubexp((RSA_NUMBER)DecryptSignature,
|
||
(RSA_NUMBER)SignaturePtr,
|
||
(u32)PpkExp,
|
||
(RSA_NUMBER)PpkModular,
|
||
(RSA_NUMBER)PpkModularEx);
|
||
FsblPrintArray(DecryptSignature, RSA_SPK_SIGNATURE_SIZE,
|
||
"SPK Decrypted Hash");
|
||
|
||
|
||
Status = RecreatePaddingAndCheck(DecryptSignature, HashSignature);
|
||
if (Status != XST_SUCCESS) {
|
||
fsbl_printf(DEBUG_INFO, "Partition SPK Signature "
|
||
"Authentication failed\r\n");
|
||
return XST_FAILURE;
|
||
}
|
||
SignaturePtr += RSA_SPK_SIGNATURE_SIZE;
|
||
|
||
/*
|
||
* Decrypt Partition Signature
|
||
*/
|
||
rsa2048_pubexp((RSA_NUMBER)DecryptSignature,
|
||
(RSA_NUMBER)SignaturePtr,
|
||
(u32)SpkExp,
|
||
(RSA_NUMBER)SpkModular,
|
||
(RSA_NUMBER)SpkModularEx);
|
||
FsblPrintArray(DecryptSignature, RSA_PARTITION_SIGNATURE_SIZE,
|
||
"Partition Decrypted Hash");
|
||
|
||
Status = RecreatePaddingAndCheck(DecryptSignature, Hash);
|
||
if (Status != XST_SUCCESS) {
|
||
fsbl_printf(DEBUG_INFO, "Partition Signature "
|
||
"Authentication failed\r\n");
|
||
return XST_FAILURE;
|
||
}
|
||
|
||
return XST_SUCCESS;
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
/**
|
||
*
|
||
* This function recreates the and check signature
|
||
*
|
||
* @param Partition signature
|
||
* @param Partition hash value which includes boot header, partition data
|
||
* @return
|
||
* - XST_SUCCESS if check passed
|
||
* - XST_FAILURE if check failed
|
||
*
|
||
* @note None
|
||
*
|
||
******************************************************************************/
|
||
u32 RecreatePaddingAndCheck(u8 *signature, u8 *hash)
|
||
{
|
||
u8 T_padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
|
||
0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
|
||
u8 * pad_ptr = signature + 256;
|
||
u32 pad = 256 - 3 - 19 - 32;
|
||
u32 ii;
|
||
|
||
/*
|
||
* Re-Create PKCS#1v1.5 Padding
|
||
* MSB ----------------------------------------------------LSB
|
||
* 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || T_padding || SHA256 Hash
|
||
*/
|
||
if (*--pad_ptr != 0x00 || *--pad_ptr != 0x01) {
|
||
return XST_FAILURE;
|
||
}
|
||
|
||
for (ii = 0; ii < pad; ii++) {
|
||
if (*--pad_ptr != 0xFF) {
|
||
return XST_FAILURE;
|
||
}
|
||
}
|
||
|
||
if (*--pad_ptr != 0x00) {
|
||
return XST_FAILURE;
|
||
}
|
||
|
||
for (ii = 0; ii < sizeof(T_padding); ii++) {
|
||
if (*--pad_ptr != T_padding[ii]) {
|
||
return XST_FAILURE;
|
||
}
|
||
}
|
||
|
||
for (ii = 0; ii < 32; ii++) {
|
||
if (*--pad_ptr != hash[ii])
|
||
return XST_FAILURE;
|
||
}
|
||
|
||
return XST_SUCCESS;
|
||
}
|
||
#endif
|