hw/misc: add ESP32 SHA
Co-authored-by: Maksim Naumenko <maksim.naumenko@espressif.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* ESP32 SHA accelerator
|
||||
*
|
||||
* Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/registerfields.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/misc/esp32_sha.h"
|
||||
|
||||
#define ESP32_SHA_REGS_SIZE (A_SHA512_BUSY + 4)
|
||||
|
||||
static void esp32_sha_text_reg_byteswap_to(Esp32ShaState* s, uint32_t* dst, size_t len_words)
|
||||
{
|
||||
for (int i = 0; i < len_words; ++i) {
|
||||
dst[i] = __builtin_bswap32(s->text[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t esp32_sha_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
Esp32ShaState *s = ESP32_SHA(opaque);
|
||||
uint64_t r = 0;
|
||||
switch (addr) {
|
||||
case 0 ... (ESP32_SHA_TEXT_REG_CNT - 1) * sizeof(uint32_t):
|
||||
r = s->text[addr / sizeof(uint32_t)];
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void esp32_sha_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned int size)
|
||||
{
|
||||
Esp32ShaState *s = ESP32_SHA(opaque);
|
||||
switch (addr) {
|
||||
case 0 ... (ESP32_SHA_TEXT_REG_CNT - 1) * sizeof(uint32_t):
|
||||
s->text[addr / sizeof(uint32_t)] = value;
|
||||
break;
|
||||
case A_SHA1_START:
|
||||
sha1_init(&s->sha1);
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16);
|
||||
sha1_compress((uint32_t *)&s->sha1.state, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA256_START:
|
||||
sha256_init(&s->sha256);
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16);
|
||||
sha256_compress(&s->sha256, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA384_START:
|
||||
sha384_init(&s->sha512);
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32);
|
||||
sha512_compress(&s->sha512, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA512_START:
|
||||
sha512_init(&s->sha512);
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32);
|
||||
sha512_compress(&s->sha512, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA1_CONTINUE:
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16);
|
||||
sha1_compress((uint32_t *)&s->sha1.state, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA256_CONTINUE:
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16);
|
||||
sha256_compress(&s->sha256, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA384_CONTINUE:
|
||||
case A_SHA512_CONTINUE:
|
||||
esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32);
|
||||
sha512_compress(&s->sha512, (unsigned char *)s->text);
|
||||
break;
|
||||
case A_SHA1_LOAD:
|
||||
for (int i = 0; i < 5; i++) {
|
||||
s->text[i] = s->sha1.state[i];
|
||||
}
|
||||
break;
|
||||
case A_SHA256_LOAD:
|
||||
for (int i = 0; i < 8; i++) {
|
||||
s->text[i] = s->sha256.state[i];
|
||||
}
|
||||
break;
|
||||
case A_SHA384_LOAD:
|
||||
case A_SHA512_LOAD:
|
||||
for (int i = 0; i < 8; i++) {
|
||||
s->text[i * 2] = (uint32_t)(s->sha512.state[i] >> 32);
|
||||
s->text[1 + (i * 2)] = (uint32_t)(s->sha512.state[i] & 0xffffffff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps esp32_sha_ops = {
|
||||
.read = esp32_sha_read,
|
||||
.write = esp32_sha_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void esp32_sha_init(Object *obj)
|
||||
{
|
||||
Esp32ShaState *s = ESP32_SHA(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &esp32_sha_ops, s,
|
||||
TYPE_ESP32_SHA, ESP32_SHA_REGS_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static const TypeInfo esp32_sha_info = {
|
||||
.name = TYPE_ESP32_SHA,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(Esp32ShaState),
|
||||
.instance_init = esp32_sha_init,
|
||||
};
|
||||
|
||||
static void esp32_sha_register_types(void)
|
||||
{
|
||||
type_register_static(&esp32_sha_info);
|
||||
}
|
||||
|
||||
type_init(esp32_sha_register_types)
|
||||
@@ -141,6 +141,7 @@ system_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files(
|
||||
'esp32_dport.c',
|
||||
'esp32_rng.c',
|
||||
'esp32_rtc_cntl.c',
|
||||
'esp32_sha.c',
|
||||
))
|
||||
if gcrypt.found()
|
||||
system_ss.add(when: [gcrypt, 'CONFIG_XTENSA_ESP32'], if_true: files(
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/registerfields.h"
|
||||
#include "crypto/sha512_i.h"
|
||||
#include "crypto/sha384_i.h"
|
||||
#include "crypto/sha256_i.h"
|
||||
#include "crypto/sha1_i.h"
|
||||
|
||||
#define TYPE_ESP32_SHA "misc.esp32.sha"
|
||||
#define ESP32_SHA(obj) OBJECT_CHECK(Esp32ShaState, (obj), TYPE_ESP32_SHA)
|
||||
|
||||
#define ESP32_SHA_TEXT_REG_CNT 32
|
||||
|
||||
typedef struct Esp32ShaState {
|
||||
SysBusDevice parent_obj;
|
||||
MemoryRegion iomem;
|
||||
uint32_t text[ESP32_SHA_TEXT_REG_CNT];
|
||||
struct sha512_state sha512;
|
||||
struct sha512_state sha384;
|
||||
struct sha256_state sha256;
|
||||
struct sha1_state sha1;
|
||||
} Esp32ShaState;
|
||||
|
||||
#define SHA_REG_GROUP(name, base) \
|
||||
REG32(name ## _START, (base)) \
|
||||
REG32(name ## _CONTINUE, (base + 0x4)) \
|
||||
REG32(name ## _LOAD, (base + 0x8)) \
|
||||
REG32(name ## _BUSY, (base + 0xc))
|
||||
|
||||
SHA_REG_GROUP(SHA1, 0x80)
|
||||
SHA_REG_GROUP(SHA256, 0x90)
|
||||
SHA_REG_GROUP(SHA384, 0xa0)
|
||||
SHA_REG_GROUP(SHA512, 0xb0)
|
||||
Reference in New Issue
Block a user