added sha (polling)
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11025 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
bff0267ac4
commit
b8bb3e95c4
|
@ -1,6 +1,7 @@
|
||||||
PLATFORMSRC +=$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c \
|
PLATFORMSRC +=$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c \
|
||||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c \
|
$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c \
|
||||||
$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
|
$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c \
|
||||||
|
$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_sha_lld.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ extern uint32_t key0_buffer[HAL_CRY_MAX_KEY_SIZE/4];
|
||||||
|
|
||||||
#include "sama_aes_lld.h"
|
#include "sama_aes_lld.h"
|
||||||
#include "sama_tdes_lld.h"
|
#include "sama_tdes_lld.h"
|
||||||
|
#include "sama_sha_lld.h"
|
||||||
|
|
||||||
#endif /* HAL_USE_CRY */
|
#endif /* HAL_USE_CRY */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,331 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
#include "hal.h"
|
||||||
|
#include <string.h>
|
||||||
|
#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
#include "sama_crypto_lld.h"
|
||||||
|
|
||||||
|
#define SHA_MAX_PADDING_LEN (2 * 128)
|
||||||
|
#define SHA_UPDATE_LEN (128 * 1024)
|
||||||
|
|
||||||
|
struct sha_data {
|
||||||
|
uint32_t remaining;
|
||||||
|
uint32_t processed;
|
||||||
|
uint32_t block_size;
|
||||||
|
uint32_t output_size;
|
||||||
|
shadalgo_t algo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t sha_buffer[SHA_MAX_PADDING_LEN];
|
||||||
|
|
||||||
|
static uint32_t shaOutputSize(shadalgo_t algo);
|
||||||
|
static uint32_t shadPaddedMessSize(uint8_t mode, uint32_t len);
|
||||||
|
static uint8_t shaBlockSize(shadalgo_t algo);
|
||||||
|
static void loadData(const uint8_t* data, int len);
|
||||||
|
static void readData(const uint8_t* data, int len);
|
||||||
|
static uint32_t processBlock(const uint8_t* data, uint32_t len, uint32_t block_size);
|
||||||
|
static void updatePollingMode(struct sha_data *shadata,const uint8_t* data, uint32_t data_size);
|
||||||
|
static void updateDMA(struct sha_data *shadata,const uint8_t* data, uint32_t data_size);
|
||||||
|
|
||||||
|
static uint32_t fillPadding(struct sha_data *shadata, uint32_t len, uint8_t* buffer);
|
||||||
|
|
||||||
|
static inline uint32_t min_u32(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int sha_finish(struct sha_data *shadata,const uint8_t* buffer,uint32_t buffer_size)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint32_t padding_len;
|
||||||
|
|
||||||
|
if (buffer_size < shadata->output_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
//pad data for the end of the buffer
|
||||||
|
padding_len = fillPadding(shadata,
|
||||||
|
shadata->processed + shadata->remaining,
|
||||||
|
&sha_buffer[shadata->remaining]
|
||||||
|
);
|
||||||
|
|
||||||
|
processBlock(sha_buffer, shadata->remaining + padding_len, shadata->block_size);
|
||||||
|
|
||||||
|
readData(buffer, buffer_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cryerror_t sama_sha_lld_process(CRYDriver *cryp,
|
||||||
|
shaparams_t *params,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t indata_len,
|
||||||
|
size_t out_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t algoregval;
|
||||||
|
struct sha_data shadata;
|
||||||
|
//uint8_t *data_in;
|
||||||
|
|
||||||
|
if (!(cryp->enabledPer & SHA_PER)) {
|
||||||
|
cryp->enabledPer |= SHA_PER;
|
||||||
|
pmcEnableSHA();
|
||||||
|
}
|
||||||
|
|
||||||
|
shadata.processed = 0;
|
||||||
|
shadata.remaining = 0;
|
||||||
|
shadata.output_size = shaOutputSize(params->algo);
|
||||||
|
shadata.block_size = shaBlockSize(params->algo);
|
||||||
|
shadata.algo = params->algo;
|
||||||
|
|
||||||
|
if (shadata.output_size == 0) {
|
||||||
|
return CRY_ERR_INV_ALGO;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (params->algo) {
|
||||||
|
case CRY_SHA_1:
|
||||||
|
algoregval = SHA_MR_ALGO_SHA1;
|
||||||
|
break;
|
||||||
|
case CRY_SHA_224:
|
||||||
|
algoregval = SHA_MR_ALGO_SHA224;
|
||||||
|
break;
|
||||||
|
case CRY_SHA_256:
|
||||||
|
algoregval = SHA_MR_ALGO_SHA256;
|
||||||
|
break;
|
||||||
|
#ifdef SHA_MR_ALGO_SHA384
|
||||||
|
case CRY_SHA_384:
|
||||||
|
algoregval = SHA_MR_ALGO_SHA384;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef SHA_MR_ALGO_SHA512
|
||||||
|
case CRY_SHA_512:
|
||||||
|
algoregval = SHA_MR_ALGO_SHA512;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return CRY_ERR_INV_ALGO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//soft reset
|
||||||
|
SHA->SHA_CR = SHA_CR_SWRST;
|
||||||
|
//configure
|
||||||
|
SHA->SHA_MR = algoregval | SHA_MR_SMOD_MANUAL_START | SHA_MR_PROCDLY_LONGEST;
|
||||||
|
|
||||||
|
//enable interrupt
|
||||||
|
SHA->SHA_IER = SHA_IER_DATRDY;
|
||||||
|
|
||||||
|
uint32_t buf_in_size;
|
||||||
|
uint8_t *p=in;
|
||||||
|
|
||||||
|
while (indata_len) {
|
||||||
|
buf_in_size = min_u32(indata_len, SHA_UPDATE_LEN);
|
||||||
|
|
||||||
|
//First block
|
||||||
|
if (!shadata.processed) {
|
||||||
|
SHA->SHA_CR = SHA_CR_FIRST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cryp->config->transfer_mode == TRANSFER_POLLING)
|
||||||
|
updatePollingMode(&shadata, in, buf_in_size);
|
||||||
|
else
|
||||||
|
updateDMA(&shadata, in, buf_in_size);
|
||||||
|
|
||||||
|
p += buf_in_size;
|
||||||
|
indata_len -= buf_in_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha_finish(&shadata, out, out_size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return CRY_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t shaOutputSize(shadalgo_t algo)
|
||||||
|
{
|
||||||
|
switch (algo) {
|
||||||
|
case CRY_SHA_1:
|
||||||
|
return 20;
|
||||||
|
case CRY_SHA_224:
|
||||||
|
return 28;
|
||||||
|
case CRY_SHA_256:
|
||||||
|
return 32;
|
||||||
|
case CRY_SHA_384:
|
||||||
|
return 48;
|
||||||
|
case CRY_SHA_512:
|
||||||
|
return 64;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t shadPaddedMessSize(uint8_t mode, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t k;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case CRY_SHA_1:
|
||||||
|
case CRY_SHA_224:
|
||||||
|
case CRY_SHA_256:
|
||||||
|
k = (512 + 448 - (((len * 8) % 512) + 1)) % 512;
|
||||||
|
len += (k - 7) / 8 + 9;
|
||||||
|
break;
|
||||||
|
case CRY_SHA_384:
|
||||||
|
case CRY_SHA_512:
|
||||||
|
k = (1024 + 896 - (((len * 8) % 1024) + 1)) % 1024;
|
||||||
|
len += (k - 7) / 8 + 17;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t shaBlockSize(shadalgo_t algo)
|
||||||
|
{
|
||||||
|
if ( (algo == CRY_SHA_384) || (algo == CRY_SHA_512) ) {
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void loadData(const uint8_t* data, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int32_t value;
|
||||||
|
|
||||||
|
for (i = 0; i < (len / 4) && i < 32; i++) {
|
||||||
|
memcpy(&value, &data[i * 4], 4);
|
||||||
|
if (i < 16)
|
||||||
|
SHA->SHA_IDATAR[i] = value;
|
||||||
|
else
|
||||||
|
SHA->SHA_IODATAR[i - 16] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void readData(const uint8_t* data, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int32_t value;
|
||||||
|
|
||||||
|
for (i = 0; i < (len / 4) && i < 16; i++) {
|
||||||
|
value = SHA->SHA_IODATAR[i];
|
||||||
|
memcpy(&data[i * 4], &value, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t processBlock(const uint8_t* data, uint32_t len, uint32_t block_size)
|
||||||
|
{
|
||||||
|
uint32_t processed = 0;
|
||||||
|
|
||||||
|
while ((len - processed) >= block_size) {
|
||||||
|
|
||||||
|
// load data in the sha input registers
|
||||||
|
loadData(&data[processed], block_size);
|
||||||
|
|
||||||
|
SHA->SHA_CR = SHA_CR_START;
|
||||||
|
|
||||||
|
// Wait for data ready
|
||||||
|
while ((SHA->SHA_ISR & SHA_ISR_DATRDY) == 0);
|
||||||
|
|
||||||
|
processed += block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateDMA(struct sha_data *shadata,const uint8_t* data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
(void)shadata;
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
}
|
||||||
|
static void updatePollingMode(struct sha_data *shadata,const uint8_t* data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t processed;
|
||||||
|
|
||||||
|
//check data from previous update
|
||||||
|
if (shadata->remaining) {
|
||||||
|
//complete previous data
|
||||||
|
uint32_t complement = min_u32(data_size, shadata->block_size - shadata->remaining);
|
||||||
|
memcpy(&sha_buffer[shadata->remaining], data, complement);
|
||||||
|
shadata->remaining += complement;
|
||||||
|
data += complement;
|
||||||
|
data_size -= complement;
|
||||||
|
|
||||||
|
//if data is complete process the block
|
||||||
|
if (shadata->remaining == shadata->block_size) {
|
||||||
|
processBlock(sha_buffer, shadata->remaining, shadata->block_size);
|
||||||
|
|
||||||
|
shadata->processed += shadata->block_size;
|
||||||
|
shadata->remaining = 0;
|
||||||
|
} else {
|
||||||
|
//complete processing in the next update/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process blocks
|
||||||
|
processed = processBlock(data, data_size, shadata->block_size);
|
||||||
|
shadata->processed += processed;
|
||||||
|
|
||||||
|
//check remaining data and process
|
||||||
|
shadata->remaining = data_size - processed;
|
||||||
|
if (shadata->remaining)
|
||||||
|
{
|
||||||
|
for (i=0;i<shadata->remaining;i++)
|
||||||
|
sha_buffer[i] = data[processed+i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t fillPadding(struct sha_data *shadata, uint32_t len, uint8_t* buffer)
|
||||||
|
{
|
||||||
|
uint32_t padding_len = shadPaddedMessSize(shadata->algo, len) - len;
|
||||||
|
uint32_t k = padding_len - 9;
|
||||||
|
|
||||||
|
osalDbgAssert( padding_len <= (SHA_MAX_PADDING_LEN - shadata->remaining),
|
||||||
|
"invalid buffer size");
|
||||||
|
|
||||||
|
|
||||||
|
// Append "1" bit and seven "0" bits to the end of the message
|
||||||
|
*buffer++ = 0x80;
|
||||||
|
// Add k "0" bits
|
||||||
|
memset(buffer, 0, k);
|
||||||
|
buffer += k;
|
||||||
|
// length is at the end of message (64-bit)
|
||||||
|
*buffer++ = 0;
|
||||||
|
*buffer++ = 0;
|
||||||
|
*buffer++ = 0;
|
||||||
|
*buffer++ = (len >> 29) & 0xFF;
|
||||||
|
*buffer++ = (len >> 21) & 0xFF;
|
||||||
|
*buffer++ = (len >> 13) & 0xFF;
|
||||||
|
*buffer++ = (len >> 5) & 0xFF;
|
||||||
|
*buffer++ = (len << 3) & 0xFF;
|
||||||
|
return padding_len;
|
||||||
|
}
|
||||||
|
#endif /* HAL_USE_CRY */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef CRYPTOLIB_LLD_SAMA_SHA_H_
|
||||||
|
#define CRYPTOLIB_LLD_SAMA_SHA_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cryerror_t sama_sha_lld_process(CRYDriver *cryp,
|
||||||
|
shaparams_t *params,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t indata_len,
|
||||||
|
size_t out_size
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CRYPTOLIB_LLD_SAMA_SHA_H_ */
|
|
@ -94,6 +94,20 @@ typedef enum {
|
||||||
}aesciphersize_t;
|
}aesciphersize_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CRY_SHA_1,
|
||||||
|
CRY_SHA_224,
|
||||||
|
CRY_SHA_256,
|
||||||
|
CRY_SHA_384,
|
||||||
|
CRY_SHA_512,
|
||||||
|
}shadalgo_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
shadalgo_t algo;
|
||||||
|
|
||||||
|
}shaparams_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief CRY key identifier type.
|
* @brief CRY key identifier type.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue