155 lines
3.6 KiB
C
155 lines
3.6 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <dma.h>
|
|
#include <asm/arch/regs.h>
|
|
#include <asm/arch/secure_apb.h>
|
|
#include <u-boot/sha256.h>
|
|
#include <amlogic/aml_crypto.h>
|
|
|
|
static sha2_ctx *cur_ctx;
|
|
|
|
static void SHA2_HW_init(sha2_ctx *ctx, uint32_t digest_len)
|
|
{
|
|
if (ctx == NULL) {
|
|
return ;
|
|
}
|
|
if (cur_ctx != NULL) {
|
|
serial_puts("Err:sha4\n");
|
|
// sha2 usage problem
|
|
return;
|
|
}
|
|
cur_ctx = ctx;
|
|
|
|
aml_hw_sha_init(ctx, digest_len == 224);
|
|
|
|
ctx->len = 0;
|
|
}
|
|
|
|
static void SHA2_HW_update(sha2_ctx *ctx, const uint8_t *data, uint32_t len)
|
|
{
|
|
|
|
unsigned int fill_len, data_len, rem_len,offset;
|
|
|
|
if (cur_ctx != ctx) {
|
|
serial_puts("Err:sha3\n");
|
|
// sha2 usage problem
|
|
return;
|
|
}
|
|
/* This method updates the hash for the input data in blocks, except the last
|
|
* partial|full block, which is saved in ctx->block. The last partial|full
|
|
* block will be added to the hash in SHA2_final.
|
|
*/
|
|
data_len = len;
|
|
offset = 0;
|
|
/* fill saved block from beginning of input data */
|
|
if (ctx->len) {
|
|
fill_len = SHA256_BLOCK_SIZE - ctx->len;
|
|
memcpy(&ctx->block[ctx->len], data, fill_len);
|
|
flush_dcache_range((unsigned long)ctx->block,(unsigned long)ctx->block+128);
|
|
data_len -= fill_len;
|
|
offset = fill_len;
|
|
ctx->len += fill_len;
|
|
}
|
|
if (ctx->len == SHA256_BLOCK_SIZE && data_len > 0) {
|
|
/* saved block is full and is not last block, hash it */
|
|
aml_hw_sha_update(ctx, ctx->block, SHA256_BLOCK_SIZE, ctx->buf, 0);
|
|
ctx->len = 0;
|
|
}
|
|
if (data_len > SHA256_BLOCK_SIZE) {
|
|
/* still have more than 1 block. hash up until last [partial|full] block */
|
|
rem_len = data_len % SHA256_BLOCK_SIZE;
|
|
|
|
if (rem_len == 0) {
|
|
rem_len = SHA256_BLOCK_SIZE;
|
|
}
|
|
|
|
data_len -= rem_len;
|
|
aml_hw_sha_update(ctx, &data[offset], data_len, ctx->buf, 0);
|
|
offset += data_len;
|
|
} else {
|
|
rem_len = data_len;
|
|
}
|
|
if (rem_len) {
|
|
/* save the remaining data */
|
|
memcpy(ctx->block, &data[offset], rem_len);
|
|
flush_dcache_range((unsigned long)ctx->block,(unsigned long)ctx->block+128);
|
|
ctx->len = rem_len;
|
|
}
|
|
}
|
|
|
|
static uint8_t *SHA2_HW_final(sha2_ctx *ctx)
|
|
{
|
|
if (cur_ctx != ctx) {
|
|
serial_puts("Err:sha1\n");
|
|
// sha2 usage problem
|
|
return ctx->buf;
|
|
}
|
|
if (ctx->len == 0 || ctx->len > SHA256_BLOCK_SIZE) {
|
|
serial_puts("Err:sha2\n");
|
|
// internal sha2 problem
|
|
return ctx->buf;
|
|
}
|
|
|
|
aml_hw_sha_update(ctx, ctx->block, ctx->len, ctx->buf, 1);
|
|
cur_ctx = NULL;
|
|
return ctx->buf;
|
|
}
|
|
|
|
void sha256_starts(sha256_context * ctx)
|
|
{
|
|
if (ctx)
|
|
memset(ctx,0,sizeof(sha256_context));
|
|
SHA2_HW_init(ctx, 256);
|
|
}
|
|
|
|
void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
|
|
{
|
|
int nOffset = 0;
|
|
int nStep = (128<<19); //64MB
|
|
|
|
if (length > nStep)
|
|
{
|
|
for (;nOffset < length;)
|
|
{
|
|
SHA2_HW_update(ctx, input+nOffset, nStep);
|
|
nOffset+=nStep;
|
|
if ((length - nOffset ) < nStep)
|
|
nStep = length - nOffset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SHA2_HW_update(ctx, input, length);
|
|
}
|
|
}
|
|
|
|
void sha256_finish(sha256_context * ctx, uint8_t digest[SHA256_SUM_LEN])
|
|
{
|
|
SHA2_HW_final(ctx);
|
|
/*before memcpy,must invalidate dcache.so memcpy data from ddr*/
|
|
invalidate_dcache_range((unsigned long)digest,(unsigned long)(digest+32));
|
|
invalidate_dcache_range((unsigned long)ctx->buf,(unsigned long)(ctx->buf+32));
|
|
|
|
memcpy(digest,ctx->buf,32);
|
|
}
|
|
|
|
void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
|
unsigned char *output, unsigned int chunk_sz)
|
|
{
|
|
flush_dcache_range((unsigned long)input,(unsigned long)input+ilen);
|
|
|
|
sha2_ctx sha_ctx;
|
|
|
|
sha256_starts(&sha_ctx);
|
|
|
|
sha256_update(&sha_ctx, input, ilen);
|
|
|
|
sha256_finish(&sha_ctx, output);
|
|
}
|