1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/crypto/crypto.h>
9 #include <zephyr/logging/log.h>
10 #include <hal/nrf_ecb.h>
11 
12 #define DT_DRV_COMPAT nordic_nrf_ecb
13 
14 #define ECB_AES_KEY_SIZE   16
15 #define ECB_AES_BLOCK_SIZE 16
16 
17 LOG_MODULE_REGISTER(crypto_nrf_ecb, CONFIG_CRYPTO_LOG_LEVEL);
18 
19 struct ecb_data {
20 	uint8_t key[ECB_AES_KEY_SIZE];
21 	uint8_t cleartext[ECB_AES_BLOCK_SIZE];
22 	uint8_t ciphertext[ECB_AES_BLOCK_SIZE];
23 };
24 
25 struct nrf_ecb_drv_state {
26 	struct ecb_data data;
27 	bool in_use;
28 };
29 
30 static struct nrf_ecb_drv_state drv_state;
31 
do_ecb_encrypt(struct cipher_ctx * ctx,struct cipher_pkt * pkt)32 static int do_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt)
33 {
34 	ARG_UNUSED(ctx);
35 
36 	if (pkt->in_len != ECB_AES_BLOCK_SIZE) {
37 		LOG_ERR("only 16-byte blocks are supported");
38 		return -EINVAL;
39 	}
40 	if (pkt->out_buf_max < pkt->in_len) {
41 		LOG_ERR("output buffer too small");
42 		return -EINVAL;
43 	}
44 
45 	if (pkt->in_buf != drv_state.data.cleartext) {
46 		memcpy(drv_state.data.cleartext, pkt->in_buf,
47 		       ECB_AES_BLOCK_SIZE);
48 	}
49 
50 	nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ENDECB);
51 	nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ERRORECB);
52 	nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
53 	while (!(nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ENDECB) ||
54 		 nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ERRORECB))) {
55 	}
56 	if (nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ERRORECB)) {
57 		LOG_ERR("ECB operation error");
58 		return -EIO;
59 	}
60 	if (pkt->out_buf != drv_state.data.ciphertext) {
61 		memcpy(pkt->out_buf, drv_state.data.ciphertext,
62 		       ECB_AES_BLOCK_SIZE);
63 	}
64 	pkt->out_len = pkt->in_len;
65 	return 0;
66 }
67 
nrf_ecb_driver_init(const struct device * dev)68 static int nrf_ecb_driver_init(const struct device *dev)
69 {
70 	ARG_UNUSED(dev);
71 
72 	nrf_ecb_data_pointer_set(NRF_ECB, &drv_state.data);
73 	drv_state.in_use = false;
74 	return 0;
75 }
76 
nrf_ecb_query_caps(const struct device * dev)77 static int nrf_ecb_query_caps(const struct device *dev)
78 {
79 	ARG_UNUSED(dev);
80 
81 	return (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
82 }
83 
nrf_ecb_session_setup(const struct device * dev,struct cipher_ctx * ctx,enum cipher_algo algo,enum cipher_mode mode,enum cipher_op op_type)84 static int nrf_ecb_session_setup(const struct device *dev,
85 				 struct cipher_ctx *ctx,
86 				 enum cipher_algo algo, enum cipher_mode mode,
87 				 enum cipher_op op_type)
88 {
89 	ARG_UNUSED(dev);
90 
91 	if ((algo != CRYPTO_CIPHER_ALGO_AES) ||
92 	    !(ctx->flags & CAP_SYNC_OPS) ||
93 	    (ctx->keylen != ECB_AES_KEY_SIZE) ||
94 	    (op_type != CRYPTO_CIPHER_OP_ENCRYPT) ||
95 	    (mode != CRYPTO_CIPHER_MODE_ECB)) {
96 		LOG_ERR("This driver only supports 128-bit AES ECB encryption"
97 			" in synchronous mode");
98 		return -EINVAL;
99 	}
100 
101 	if (ctx->key.bit_stream == NULL) {
102 		LOG_ERR("No key provided");
103 		return -EINVAL;
104 	}
105 
106 	if (drv_state.in_use) {
107 		LOG_ERR("Peripheral in use");
108 		return -EBUSY;
109 	}
110 
111 	drv_state.in_use = true;
112 
113 	ctx->ops.block_crypt_hndlr = do_ecb_encrypt;
114 	ctx->ops.cipher_mode = mode;
115 
116 	if (ctx->key.bit_stream != drv_state.data.key) {
117 		memcpy(drv_state.data.key, ctx->key.bit_stream,
118 		       ECB_AES_KEY_SIZE);
119 	}
120 
121 	return 0;
122 }
123 
nrf_ecb_session_free(const struct device * dev,struct cipher_ctx * sessn)124 static int nrf_ecb_session_free(const struct device *dev,
125 				struct cipher_ctx *sessn)
126 {
127 	ARG_UNUSED(dev);
128 	ARG_UNUSED(sessn);
129 
130 	drv_state.in_use = false;
131 
132 	return 0;
133 }
134 
135 static const struct crypto_driver_api crypto_enc_funcs = {
136 	.cipher_begin_session = nrf_ecb_session_setup,
137 	.cipher_free_session = nrf_ecb_session_free,
138 	.cipher_async_callback_set = NULL,
139 	.query_hw_caps = nrf_ecb_query_caps,
140 };
141 
142 DEVICE_DT_INST_DEFINE(0, nrf_ecb_driver_init, NULL,
143 		      NULL, NULL,
144 		      POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY,
145 		      &crypto_enc_funcs);
146