-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added an internal HMAC implementation using the existing internal SHA APIs
- Loading branch information
Showing
6 changed files
with
494 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* HMAC-SHA-224/256/384/512 implementation | ||
* Last update: 06/15/2005 | ||
* Issue date: 06/15/2005 | ||
* | ||
* Copyright (C) 2005 Olivier Gay <[email protected]> | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* 2. 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. | ||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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 <string.h> | ||
|
||
#include "hmac256_i.h" | ||
|
||
|
||
void hmac_sha256_init(struct hmac_sha256_ctx *ctx, const uint8_t *key, | ||
uint32_t key_size) | ||
{ | ||
uint32_t fill = SHA256_BLOCK_SIZE - key_size; | ||
|
||
uint8_t block_ipad[SHA256_BLOCK_SIZE]; | ||
uint8_t block_opad[SHA256_BLOCK_SIZE]; | ||
|
||
memset(block_ipad + key_size, 0x36, fill); | ||
memset(block_opad + key_size, 0x5c, fill); | ||
|
||
for (int i = 0; i < (int) key_size; i++) { | ||
block_ipad[i] = key[i] ^ 0x36; | ||
block_opad[i] = key[i] ^ 0x5c; | ||
} | ||
|
||
sha256_init(&ctx->ctx_inside); | ||
sha256_compress(&ctx->ctx_inside, block_ipad); | ||
|
||
sha256_init(&ctx->ctx_outside); | ||
sha256_compress(&ctx->ctx_outside, block_opad); | ||
} | ||
|
||
void hmac_sha256_update(struct hmac_sha256_ctx *ctx, uint8_t *message) | ||
{ | ||
sha256_compress(&ctx->ctx_inside, message); | ||
} | ||
|
||
|
||
static inline void write32_be(uint32_t n, uint8_t out[4]) | ||
{ | ||
*(uint32_t *)(out) = __builtin_bswap32(n); | ||
} | ||
|
||
|
||
void hmac_sha256_final(struct hmac_sha256_ctx *ctx, uint8_t *mac, | ||
uint32_t mac_size) | ||
{ | ||
uint8_t block[SHA256_BLOCK_SIZE] = {0}; | ||
for(int i = 0 ; i < 8; i++) { | ||
write32_be(ctx->ctx_inside.state[i], block + i * 4); | ||
} | ||
// As the "ctx_inside" state will be the input of the SHA operation over "ctx_outside" | ||
// we need to pad the "ctx_inside" state because `sha256_compress` expects a padded input | ||
uint64_t bit_len = __builtin_bswap64(SHA256_DIGEST_SIZE * 8 + 512); | ||
block[SHA256_DIGEST_SIZE] = 0x80; | ||
memset(block + SHA256_DIGEST_SIZE + 1, 0, SHA256_BLOCK_SIZE - SHA256_DIGEST_SIZE - 1); | ||
memcpy(block + SHA256_BLOCK_SIZE - sizeof(bit_len), &bit_len, sizeof(bit_len)); | ||
|
||
sha256_compress(&ctx->ctx_outside, block); | ||
memcpy(mac, ctx->ctx_outside.state, SHA256_DIGEST_SIZE); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* HMAC-SHA-224/256/384/512 implementation | ||
* Last update: 06/15/2005 | ||
* Issue date: 06/15/2005 | ||
* | ||
* Copyright (C) 2005 Olivier Gay <[email protected]> | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* 2. 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. | ||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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. | ||
*/ | ||
|
||
#ifndef HMAC256_I_H | ||
#define HMAC256_I_H | ||
|
||
#include "qemu/osdep.h" | ||
#include "sha256_i.h" | ||
|
||
#define SHA256_DIGEST_SIZE 32 | ||
#define SHA256_BLOCK_SIZE 64 | ||
|
||
struct hmac_sha256_ctx { | ||
struct sha256_state ctx_inside; | ||
struct sha256_state ctx_outside; | ||
}; | ||
|
||
void hmac_sha256_init(struct hmac_sha256_ctx *ctx, const uint8_t *key, unsigned int key_size); | ||
void hmac_sha256_update(struct hmac_sha256_ctx *ctx, uint8_t *message); | ||
void hmac_sha256_final(struct hmac_sha256_ctx *ctx, uint8_t *mac, unsigned int mac_size); | ||
|
||
#endif /* HMAC256_I_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/* | ||
* ESP32-C3 HMAC emulation | ||
* | ||
* Copyright (c) 2023 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 "hw/sysbus.h" | ||
#include "hw/misc/esp32c3_hmac.h" | ||
#include "hw/nvram/esp32c3_efuse.h" | ||
#include "qemu/bswap.h" | ||
#include "qemu/error-report.h" | ||
|
||
#define HMAC_WARNING 0 | ||
#define HMAC_DEBUG 0 | ||
|
||
static void esp32c3_hmac_start(ESP32C3HmacState *s) | ||
{ | ||
uint8_t efuse_key[32]; | ||
esp32c3_efuse_get_key(s->efuse, s->efuse_block_num, efuse_key); | ||
hmac_sha256_init(&s->ctx, efuse_key, sizeof(efuse_key)); | ||
s->message_write_complete = 0; | ||
} | ||
|
||
|
||
static void esp32c3_hmac_update(ESP32C3HmacState *s, uint32_t *message) | ||
{ | ||
hmac_sha256_update(&s->ctx, (uint8_t*)(message)); | ||
} | ||
|
||
|
||
static void esp32c3_hmac_finish(ESP32C3HmacState *s, uint32_t *result) | ||
{ | ||
hmac_sha256_final(&s->ctx, (uint8_t*) result, sizeof(result)); | ||
} | ||
|
||
|
||
static uint64_t esp32c3_hmac_read(void *opaque, hwaddr addr, unsigned int size) | ||
{ | ||
ESP32C3HmacState *s = ESP32C3_HMAC(opaque); | ||
|
||
uint64_t r = 0; | ||
switch (addr) { | ||
case A_HMAC_DATE_REG: | ||
r = 0x20200618; | ||
break; | ||
|
||
case A_HMAC_QUERY_ERROR_REG: | ||
r = esp32c3_efuse_get_key_purpose(s->efuse, s->efuse_block_num) == s->efuse_key_purpose ? 0 : 1; | ||
break; | ||
|
||
case A_HMAC_QUERY_BUSY_REG: | ||
r = 0; | ||
break; | ||
|
||
case A_HMAC_RD_RESULT_0_REG ... A_HMAC_RD_RESULT_7_REG: | ||
r = be32_to_cpu(s->result[(addr - A_HMAC_RD_RESULT_0_REG) / sizeof(uint32_t)]); | ||
break; | ||
|
||
default: | ||
#if HMAC_WARNING | ||
/* Other registers are not supported yet */ | ||
warn_report("[HMAC] Unsupported read to %08lx\n", addr); | ||
#endif | ||
break; | ||
} | ||
|
||
#if HMAC_DEBUG | ||
info_report("[HMAC] Reading from %08lx (%08lx)\n", addr, r); | ||
#endif | ||
|
||
return r; | ||
} | ||
|
||
|
||
static void esp32c3_hmac_write(void *opaque, hwaddr addr, | ||
uint64_t value, unsigned int size) | ||
{ | ||
ESP32C3HmacClass *class = ESP32C3_HMAC_GET_CLASS(opaque); | ||
ESP32C3HmacState *s = ESP32C3_HMAC(opaque); | ||
|
||
switch (addr) { | ||
case A_HMAC_SET_START_REG: | ||
break; | ||
|
||
case A_HMAC_SET_PARA_FINISH_REG: | ||
esp32c3_hmac_start(s); | ||
break; | ||
|
||
case A_HMAC_SET_MESSAGE_ONE_REG: | ||
class->hmac_update(s, s->message); | ||
if(s->message_write_complete) { | ||
class->hmac_finish(s, s->result); | ||
} | ||
break; | ||
|
||
case A_HMAC_SET_MESSAGE_ING_REG: | ||
break; | ||
|
||
case A_HMAC_SET_RESULT_FINISH_REG: | ||
memset(s->result, 0, sizeof(s->result)); | ||
break; | ||
|
||
case A_HMAC_SET_INVALIDATE_JTAG_REG: | ||
break; | ||
|
||
case A_HMAC_SET_INVALIDATE_DS_REG: | ||
break; | ||
|
||
case A_HMAC_SET_PARA_PURPOSE_REG: | ||
s->efuse_key_purpose = FIELD_EX32(value, HMAC_SET_PARA_PURPOSE_REG, HMAC_PURPOSE_SET); | ||
break; | ||
|
||
case A_HMAC_SET_PARA_KEY_REG: | ||
s->efuse_block_num = EFUSE_BLOCK_KEY0 + FIELD_EX32(value, HMAC_SET_PARA_KEY_REG, HMAC_KEY_SET); | ||
break; | ||
|
||
case A_HMAC_WR_MESSAGE_0_REG ... A_HMAC_WR_MESSAGE_15_REG: | ||
s->message[(addr - A_HMAC_WR_MESSAGE_0_REG) / sizeof(uint32_t)] = value; | ||
break; | ||
|
||
case A_HMAC_SET_MESSAGE_PAD_REG: | ||
s->message_write_complete = 1; | ||
break; | ||
|
||
case A_HMAC_ONE_BLOCK_REG: | ||
s->message_write_complete = 1; | ||
esp32c3_hmac_finish(s, s->result); | ||
break; | ||
|
||
case A_HMAC_SET_MESSAGE_END_REG: | ||
case A_HMAC_SOFT_JTAG_CTRL_REG: | ||
case A_HMAC_WR_JTAG_REG: | ||
default: | ||
#if HMAC_WARNING | ||
/* Other registers are not supported yet */ | ||
warn_report("[HMAC] Unsupported write to %08lx (%08lx)\n", addr, value); | ||
#endif | ||
break; | ||
} | ||
|
||
#if HMAC_DEBUG | ||
info_report("[HMAC] Writing to %08lx (%08lx)\n", addr, value); | ||
#endif | ||
|
||
} | ||
|
||
|
||
static const MemoryRegionOps esp32c3_hmac_ops = { | ||
.read = esp32c3_hmac_read, | ||
.write = esp32c3_hmac_write, | ||
.endianness = DEVICE_LITTLE_ENDIAN, | ||
}; | ||
|
||
static void esp32c3_hmac_reset(DeviceState *dev) | ||
{ | ||
ESP32C3HmacState *s = ESP32C3_HMAC(dev); | ||
memset(s->message, 0, sizeof(s->message)); | ||
memset(s->result, 0, sizeof(s->result)); | ||
|
||
s->efuse_block_num = 0; | ||
s->efuse_key_purpose = 0; | ||
s->message_write_complete = 0; | ||
} | ||
|
||
static void esp32c3_hmac_realize(DeviceState *dev, Error **errp) | ||
{ | ||
ESP32C3HmacState *s = ESP32C3_HMAC(dev); | ||
|
||
/* Make sure Efuse was set of issue an error */ | ||
if (s->efuse == NULL) { | ||
error_report("[HMAC] Efuse controller must be set!"); | ||
} | ||
} | ||
|
||
static void esp32c3_hmac_init(Object *obj) | ||
{ | ||
ESP32C3HmacState *s = ESP32C3_HMAC(obj); | ||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
|
||
memory_region_init_io(&s->iomem, obj, &esp32c3_hmac_ops, s, | ||
TYPE_ESP32C3_HMAC, ESP32C3_HMAC_REGS_SIZE); | ||
sysbus_init_mmio(sbd, &s->iomem); | ||
} | ||
|
||
static void esp32c3_hmac_class_init(ObjectClass *klass, void *data) | ||
{ | ||
DeviceClass *dc = DEVICE_CLASS(klass); | ||
ESP32C3HmacClass* esp32c3_hmac = ESP32C3_HMAC_CLASS(klass); | ||
|
||
dc->realize = esp32c3_hmac_realize; | ||
dc->reset = esp32c3_hmac_reset; | ||
|
||
esp32c3_hmac->hmac_update = esp32c3_hmac_update; | ||
esp32c3_hmac->hmac_finish = esp32c3_hmac_finish; | ||
} | ||
|
||
static const TypeInfo esp32c3_hmac_info = { | ||
.name = TYPE_ESP32C3_HMAC, | ||
.parent = TYPE_SYS_BUS_DEVICE, | ||
.instance_size = sizeof(ESP32C3HmacState), | ||
.instance_init = esp32c3_hmac_init, | ||
.class_init = esp32c3_hmac_class_init, | ||
.class_size = sizeof(ESP32C3HmacClass) | ||
}; | ||
|
||
static void esp32c3_hmac_register_types(void) | ||
{ | ||
type_register_static(&esp32c3_hmac_info); | ||
} | ||
|
||
type_init(esp32c3_hmac_register_types) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.