1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * CRACEN CryptoMaster, AES engine model
9 *
10 * Notes:
11 * * Only ECB mode is supported by now
12 *
13 * * Only SW programmed key is supported by now
14 *
15 * * This AES model does not bother clearing the AES Keys if they are incorrectly programmed
16 * or between runs
17 */
18
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include "bs_tracing.h"
24 #include "NHW_config.h"
25 #include "NHW_CRACEN_CM.h"
26 #include "BLECrypt_if.h"
27 #include "nsi_hws_models_if.h"
28
29 #define CONFIG_ENCORDEC_MASK 0x1
30 #define CONFIG_MODE_MASK 0x1FF00
31 #define BLOCK_SIZE 128/8
32
33 static struct CM_AES_regs_t {
34 uint32_t CONFIG;
35 uint32_t reserved;
36 uint32_t KEY[8];
37 uint32_t IV[4];
38 uint32_t IV2[4];
39 uint32_t KEY2[8];
40 uint32_t MASK;
41 } CM_AES_regs;
42
43 static int t_ecb[] = NHW_CRACEN_CM_AES_t_ECB;
44
45 static struct CM_AES_st_t {
46 int AES_KEY_size;
47 char data_out[BLOCK_SIZE];
48 } CM_AES_st;
49
50 bs_time_t Timer_CRACEN_CM_AES;
51
nhw_CRACEN_CM_AES_init(void)52 void nhw_CRACEN_CM_AES_init(void) {
53 memset(&CM_AES_regs, 0, sizeof(CM_AES_regs));
54 memset(&CM_AES_st, 0, sizeof(CM_AES_st));
55
56 Timer_CRACEN_CM_AES = TIME_NEVER;
57 }
58
nhw_CRACEN_CM_AES_get_mode(void)59 static int nhw_CRACEN_CM_AES_get_mode(void) {
60 return (CM_AES_regs.CONFIG & CONFIG_MODE_MASK) >> 8;
61 }
62
nhw_CRACEN_CM_AES_get_KeySel(void)63 static int nhw_CRACEN_CM_AES_get_KeySel(void) {
64 return ((CM_AES_regs.CONFIG >> 6) & 0x3) | ((CM_AES_regs.CONFIG >> 26) & 0x7);;
65 }
66
nhw_CRACEN_CM_AES_process_data(struct CM_tag * tag_st,char * buf,size_t len)67 static void nhw_CRACEN_CM_AES_process_data(struct CM_tag *tag_st, char* buf, size_t len) {
68 if (nhw_CRACEN_CM_AES_get_mode() != 1) {
69 bs_trace_error_time_line("%s: Only ECB mode supported by now\n",
70 __func__);
71 }
72 if (nhw_CRACEN_CM_AES_get_KeySel() != 0) {
73 bs_trace_error_time_line("%s: Only SW programmed key supported by now\n",
74 __func__);
75 }
76 if (len != BLOCK_SIZE) {
77 bs_trace_error_time_line("Block size of 128b excedded for payload\n");
78 }
79 BLECrypt_if_aes_ecb((uint8_t *)CM_AES_regs.KEY, CM_AES_st.AES_KEY_size,
80 (uint8_t *)buf, (uint8_t *)CM_AES_st.data_out);
81
82 Timer_CRACEN_CM_AES = nsi_hws_get_time() + t_ecb[(CM_AES_st.AES_KEY_size - 128)/64];
83 nhw_CRACEN_CM_update_timer();
84 }
85
nhw_CRACEN_CM_AES_feed_data(struct CM_tag * tag_st,char * buf,size_t len)86 bool nhw_CRACEN_CM_AES_feed_data(struct CM_tag *tag_st, char* buf, size_t len) {
87
88 if (tag_st->DataOrConf == 1) { // Config
89 int OffsetStartAddr = tag_st->OffsetStartAddr;
90 if (OffsetStartAddr + len > sizeof(CM_AES_regs)) {
91 bs_trace_error_time_line("%s: Attempted to write into non existent CONFIG register (%i..%i)\n",
92 __func__, OffsetStartAddr, OffsetStartAddr + len);
93 }
94 memcpy(&((char *)&CM_AES_regs)[OffsetStartAddr], buf, len);
95 if (OffsetStartAddr == offsetof(struct CM_AES_regs_t , KEY)) {
96 if ((len*8 != 128) && (len*8 != 192) && (len*8 != 256)) {
97 bs_trace_warning_time_line("%s: Invalid key length (%i)\n", __func__, len*8);
98 } else {
99 CM_AES_st.AES_KEY_size = len*8;
100 }
101 }
102 return false;
103 } else { // Data
104 if (tag_st->DataType == 0) { // Payload
105 if (tag_st->Invalid_bytes != 0) {
106 bs_trace_error_time_line("%s: Invalid_bytes != 0 not supported\n", __func__);
107 }
108 nhw_CRACEN_CM_AES_process_data(tag_st, buf, len);
109 } else { // Header
110 bs_trace_error_time_line("Only ECB mode implemented by now => DataType %i not supported\n",
111 tag_st->DataType);
112 }
113 return false;
114 }
115 }
116
nhw_CRACEN_CM_AES_timer_triggered(void)117 void nhw_CRACEN_CM_AES_timer_triggered(void) {
118 Timer_CRACEN_CM_AES = TIME_NEVER;
119 nhw_CRACEN_CM_update_timer();
120 nhw_CRACEN_CM_give_pusher_data(CM_AES_st.data_out, BLOCK_SIZE);
121 }
122
nhw_CRACEN_CM_AES_hard_stop(void)123 void nhw_CRACEN_CM_AES_hard_stop(void) {
124 nhw_CRACEN_CM_AES_init();
125 nhw_CRACEN_CM_update_timer();
126 }
127