207 lines
6.6 KiB
C
207 lines
6.6 KiB
C
/*
|
|
* Copyright (c) 2015-2023, Texas Instruments Incorporated
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "msp-crypto/msp_crypto.h"
|
|
#include <stdint.h>
|
|
#include "mcuboot_config/mcuboot_logging.h"
|
|
#include "string.h"
|
|
|
|
#include "sha256sw.h"
|
|
#include "ECCSW.h"
|
|
#include "scalarMul.h"
|
|
|
|
#define MAXLEN 8 // for NIST-256
|
|
#define KEYLEN 32 // in bytes
|
|
#define ECDSA_SHA_TEMPWORKSZONE_LEN (6 * KEYLEN)
|
|
|
|
|
|
/* NIST p256 curve parameters, DO NOT EDIT */
|
|
const uint32_t NIST256_p[MAXLEN + 1] = {8ul, 4294967295ul, 4294967295ul,
|
|
4294967295ul, 0ul, 0ul, 0ul, 1ul, 4294967295ul};
|
|
const uint32_t NIST256_r[MAXLEN + 1] = {8ul, 4234356049ul, 4089039554ul,
|
|
2803342980ul, 3169254061ul, 4294967295ul, 4294967295ul, 0ul, 4294967295ul};
|
|
const uint32_t NIST256_a[MAXLEN + 1] = {8ul, 4294967292ul, 4294967295ul,
|
|
4294967295ul, 0ul, 0ul, 0ul, 1ul, 4294967295ul};
|
|
const uint32_t NIST256_b[MAXLEN + 1] = {8ul, 668098635ul, 1003371582ul,
|
|
3428036854ul, 1696401072ul, 1989707452ul, 3018571093ul, 2855965671ul,
|
|
1522939352ul};
|
|
const uint32_t NIST256_Gx[MAXLEN + 1] = {8ul, 3633889942ul, 4104206661ul,
|
|
770388896ul, 1996717441ul, 1671708914ul, 4173129445ul, 3777774151ul,
|
|
1796723186ul};
|
|
const uint32_t NIST256_Gy[MAXLEN + 1] = {8ul, 935285237ul, 3417718888ul,
|
|
1798397646ul, 734933847ul, 2081398294ul, 2397563722ul, 4263149467ul,
|
|
1340293858ul};
|
|
|
|
/* SHA256 Objects */
|
|
SHA256SW_Object sha256SWObject;
|
|
SHA256SW_Handle sha256SWHandle = &sha256SWObject;
|
|
int_fast16_t sha2SWresult;
|
|
uint32_t finalDigest[8];
|
|
|
|
/* ECC Workzone declared
|
|
*
|
|
* Size considerations:
|
|
* Window Size: 2 (currently used and non adjustable)
|
|
* Maximum workzone size: 904 (0x388)
|
|
*
|
|
*/
|
|
uint32_t ecc_workzone[ECC_WORKZONE_SIZE / sizeof(uint32_t)];
|
|
|
|
/* ECC Defines */
|
|
uint8_t ret;
|
|
uint32_t len;
|
|
volatile uint32_t err = 0;
|
|
volatile uint8_t j, w;
|
|
ECC_State ecc_state;
|
|
|
|
void copy(uint8_t *to, const uint8_t *from, int len)
|
|
{
|
|
for (int i = 0; i < len; i++) {
|
|
to[i] = from[i];
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn reverseOrder
|
|
* @brief Reverse the byte order and copy to output buffer
|
|
*
|
|
* @param pBufIn - pointer to input buffer
|
|
* @param pBufOut - pointer to output buffer
|
|
*/
|
|
static void reverseOrder(const uint8_t *pBufIn, uint8_t *pBufOut)
|
|
{
|
|
uint8_t i = 0;
|
|
uint32_t sign_length = 32;
|
|
for (i = 0; i < sign_length; i++) {
|
|
pBufOut[i] = pBufIn[sign_length - 1 - i];
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn copyBytes
|
|
* @brief Copy data between memory locatins
|
|
*
|
|
* @param pDst - pointer to destination buffer
|
|
* @param pSrc - pointer to source buffer
|
|
* @param len - length of data to be copied
|
|
*/
|
|
static void copyBytes(uint8_t *pDst, const uint8_t *pSrc, uint32_t len)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < len; i++) {
|
|
pDst[i] = pSrc[i];
|
|
}
|
|
}
|
|
|
|
void MSPCrypto_sha256_init(void)
|
|
{
|
|
sha2SWresult = SHA256SW_start(sha256SWHandle, SHA2SW_HASH_TYPE_256);
|
|
}
|
|
|
|
void MSPCrypto_sha256_drop(void)
|
|
{
|
|
SHA256SW_cancel(sha256SWHandle);
|
|
return;
|
|
}
|
|
|
|
int MSPCrypto_sha256_update(const void *data, uint32_t data_len)
|
|
{
|
|
if (sha2SWresult == SHA2SW_STATUS_SUCCESS) {
|
|
sha2SWresult = SHA256SW_addData(sha256SWHandle, data, data_len);
|
|
}
|
|
return sha2SWresult;
|
|
}
|
|
|
|
int MSPCrypto_sha256_finish(uint8_t *output)
|
|
{
|
|
if (sha2SWresult == SHA2SW_STATUS_SUCCESS) {
|
|
sha2SWresult = SHA256SW_finalize(sha256SWHandle, (uint32_t *) output);
|
|
}
|
|
return sha2SWresult;
|
|
}
|
|
|
|
void MSPCrypto_ecdsa_p256_init(void)
|
|
{
|
|
ecc_state.data_p = NIST256_p;
|
|
ecc_state.data_r = NIST256_r;
|
|
ecc_state.data_a = NIST256_a;
|
|
ecc_state.data_b = NIST256_b;
|
|
ecc_state.data_Gx = NIST256_Gx;
|
|
ecc_state.data_Gy = NIST256_Gy;
|
|
ecc_state.workzone = ecc_workzone;
|
|
ecc_state.win = SECURE_FW_ECC_WINDOW_SIZE;
|
|
}
|
|
|
|
void MSPCrypto_ecdsa_p256_drop(void)
|
|
{
|
|
/* Nothing required to drop */
|
|
return;
|
|
}
|
|
|
|
int MSPCrypto_ecdsa_p256_verify(
|
|
const uint8_t *pk, const uint8_t *hash, const uint8_t *sig)
|
|
{
|
|
/* Key comes in pre-processed from DER format with x coordinate, then y. */
|
|
uint32_t publicKeyXBuf[MAXLEN + 1] = {0};
|
|
uint32_t publicKeyYBuf[MAXLEN + 1] = {0};
|
|
uint32_t digest[MAXLEN + 1] = {0};
|
|
uint32_t sign1[MAXLEN + 1] = {0};
|
|
uint32_t sign2[MAXLEN + 1] = {0};
|
|
uint32_t ret;
|
|
|
|
/* ECC library expects inputs in uint32_t format, whereas mcuboot provides
|
|
* byte length. Set length accordingly */
|
|
publicKeyXBuf[0] = KEYLEN / 4;
|
|
reverseOrder(pk, (uint8_t *) &publicKeyXBuf[1]);
|
|
|
|
publicKeyYBuf[0] = KEYLEN / 4;
|
|
reverseOrder(pk + KEYLEN, (uint8_t *) &publicKeyYBuf[1]);
|
|
|
|
digest[0] = KEYLEN / 4;
|
|
reverseOrder(hash, (uint8_t *) &digest[1]);
|
|
|
|
sign1[0] = KEYLEN / 4;
|
|
reverseOrder(sig, (uint8_t *) &sign1[1]);
|
|
|
|
sign2[0] = KEYLEN / 4;
|
|
reverseOrder(sig + KEYLEN, (uint8_t *) &sign2[1]);
|
|
|
|
ret = ECCSW_ECDSAVerify(
|
|
&ecc_state, publicKeyXBuf, publicKeyYBuf, digest, sign1, sign2);
|
|
|
|
if (ret != STATUS_ECDSA_VALID_SIGNATURE) {
|
|
MCUBOOT_LOG_ERR("MSPCrypto_ecdsa_p256_verify: fail");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} |