1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2019-04-25     tyx          the first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <hw_symmetric.h>
14 
15 /**
16  * @brief           Creating Symmetric Encryption and Decryption Context
17  *
18  * @param device    Hardware crypto device
19  * @param type      Type of symmetric crypto context
20  *
21  * @return          Symmetric crypto context
22  */
rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device * device,hwcrypto_type type)23 struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, hwcrypto_type type)
24 {
25     struct rt_hwcrypto_ctx *ctx;
26 
27     ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_symmetric));
28     return ctx;
29 }
30 
31 /**
32  * @brief           Destroy Symmetric Encryption and Decryption Context
33  *
34  * @param ctx       Symmetric crypto context
35  */
rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx * ctx)36 void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx)
37 {
38     rt_hwcrypto_ctx_destroy(ctx);
39 }
40 
41 /**
42  * @brief           This function performs a symmetric encryption or decryption operation
43  *
44  * @param ctx       Symmetric crypto context
45  * @param mode      Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT
46  * @param length    The length of the input data in Bytes. This must be a multiple of the block size
47  * @param in        The buffer holding the input data
48  * @param out       The buffer holding the output data
49  *
50  * @return          RT_EOK on success.
51  */
rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx * ctx,hwcrypto_mode mode,rt_size_t length,const rt_uint8_t * in,rt_uint8_t * out)52 rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out)
53 {
54     struct hwcrypto_symmetric *symmetric_ctx;
55     struct hwcrypto_symmetric_info symmetric_info;
56     rt_err_t err;
57 
58     if (ctx == RT_NULL)
59     {
60         return -RT_EINVAL;
61     }
62     symmetric_ctx = (struct hwcrypto_symmetric *)ctx;
63     if (symmetric_ctx->ops->crypt == RT_NULL)
64     {
65         return -RT_ERROR;
66     }
67     if (mode != HWCRYPTO_MODE_ENCRYPT && mode != HWCRYPTO_MODE_DECRYPT)
68     {
69         return -RT_EINVAL;
70     }
71 
72     /* Input information packaging */
73     symmetric_info.mode = mode;
74     symmetric_info.in = in;
75     symmetric_info.out = out;
76     symmetric_info.length = length;
77 
78     /* Calling Hardware Encryption and Decryption Function */
79     err = symmetric_ctx->ops->crypt(symmetric_ctx, &symmetric_info);
80 
81     /* clean up flags */
82     symmetric_ctx->flags &= ~(SYMMTRIC_MODIFY_KEY | SYMMTRIC_MODIFY_IV | SYMMTRIC_MODIFY_IVOFF);
83     return err;
84 }
85 
86 /**
87  * @brief           Set Symmetric Encryption and Decryption Key
88  *
89  * @param ctx       Symmetric crypto context
90  * @param key       The crypto key
91  * @param bitlen    The crypto key bit length
92  *
93  * @return          RT_EOK on success.
94  */
rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx * ctx,const rt_uint8_t * key,rt_uint32_t bitlen)95 rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen)
96 {
97     struct hwcrypto_symmetric *symmetric_ctx;
98 
99     if (ctx && bitlen <= RT_HWCRYPTO_KEYBIT_MAX_SIZE)
100     {
101         symmetric_ctx = (struct hwcrypto_symmetric *)ctx;
102         rt_memcpy(symmetric_ctx->key, key, bitlen >> 3);
103         /* Record key length */
104         symmetric_ctx->key_bitlen = bitlen;
105         /* Key change flag set up */
106         symmetric_ctx->flags |= SYMMTRIC_MODIFY_KEY;
107         return RT_EOK;
108     }
109 
110     return -RT_EINVAL;
111 }
112 
113 /**
114  * @brief           Get Symmetric Encryption and Decryption Key
115  *
116  * @param ctx       Symmetric crypto context
117  * @param key       The crypto key buffer
118  * @param bitlen    The crypto key bit length
119  *
120  * @return          Key length of copy
121  */
rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx * ctx,rt_uint8_t * key,rt_uint32_t bitlen)122 int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen)
123 {
124     struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;
125 
126     if (ctx && bitlen >= symmetric_ctx->key_bitlen)
127     {
128         rt_memcpy(key, symmetric_ctx->key, symmetric_ctx->key_bitlen >> 3);
129         return symmetric_ctx->key_bitlen;
130     }
131 
132     return 0;
133 }
134 
135 /**
136  * @brief           Set Symmetric Encryption and Decryption initialization vector
137  *
138  * @param ctx       Symmetric crypto context
139  * @param iv        The crypto initialization vector
140  * @param len       The crypto initialization vector length
141  *
142  * @return          RT_EOK on success.
143  */
rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx * ctx,const rt_uint8_t * iv,rt_size_t len)144 rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len)
145 {
146     struct hwcrypto_symmetric *symmetric_ctx;
147 
148     if (ctx && len <= RT_HWCRYPTO_IV_MAX_SIZE)
149     {
150         symmetric_ctx = (struct hwcrypto_symmetric *)ctx;
151         rt_memcpy(symmetric_ctx->iv, iv, len);
152         symmetric_ctx->iv_len = len;
153         /* IV change flag set up */
154         symmetric_ctx->flags |= SYMMTRIC_MODIFY_IV;
155         return RT_EOK;
156     }
157 
158     return -RT_EINVAL;
159 }
160 
161 /**
162  * @brief           Get Symmetric Encryption and Decryption initialization vector
163  *
164  * @param ctx       Symmetric crypto context
165  * @param iv        The crypto initialization vector buffer
166  * @param len       The crypto initialization vector buffer length
167  *
168  * @return          IV length of copy
169  */
rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx * ctx,rt_uint8_t * iv,rt_size_t len)170 int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len)
171 {
172     struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;;
173 
174     if (ctx && len >= symmetric_ctx->iv_len)
175     {
176         rt_memcpy(iv, symmetric_ctx->iv, symmetric_ctx->iv_len);
177         return symmetric_ctx->iv_len;
178     }
179 
180     return 0;
181 }
182 
183 /**
184  * @brief           Set offset in initialization vector
185  *
186  * @param ctx       Symmetric crypto context
187  * @param iv_off    The offset in IV
188  */
rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx * ctx,rt_int32_t iv_off)189 void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off)
190 {
191     if (ctx)
192     {
193         ((struct hwcrypto_symmetric *)ctx)->iv_off = iv_off;
194         /* iv_off change flag set up */
195         ((struct hwcrypto_symmetric *)ctx)->flags |= SYMMTRIC_MODIFY_IVOFF;
196     }
197 }
198 
199 /**
200  * @brief           Get offset in initialization vector
201  *
202  * @param ctx       Symmetric crypto context
203  * @param iv_off    It must point to a valid memory
204  */
rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx * ctx,rt_int32_t * iv_off)205 void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off)
206 {
207     if (ctx && iv_off)
208     {
209         *iv_off = ((struct hwcrypto_symmetric *)ctx)->iv_off;
210     }
211 }
212 
213 /**
214  * @brief           This function copy symmetric crypto context
215  *
216  * @param des       The destination symmetric crypto context
217  * @param src       The symmetric crypto context to be copy
218  *
219  * @return          RT_EOK on success.
220  */
rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx * des,const struct rt_hwcrypto_ctx * src)221 rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
222 {
223     struct hwcrypto_symmetric *symmetric_des = (struct hwcrypto_symmetric *)des;
224     struct hwcrypto_symmetric *symmetric_src = (struct hwcrypto_symmetric *)src;
225 
226     if (des != RT_NULL && src != RT_NULL)
227     {
228         /* Copy Symmetric Encryption and Decryption Context Information */
229         symmetric_des->flags      = symmetric_src->flags     ;
230         symmetric_des->iv_len     = symmetric_src->iv_len    ;
231         symmetric_des->iv_off     = symmetric_src->iv_off    ;
232         symmetric_des->key_bitlen = symmetric_src->key_bitlen;
233         rt_memcpy(symmetric_des->iv, symmetric_src->iv, symmetric_src->iv_len);
234         rt_memcpy(symmetric_des->key, symmetric_src->key, symmetric_src->key_bitlen >> 3);
235 
236         /* Hardware context copy */
237         return rt_hwcrypto_ctx_cpy(des, src);
238     }
239     return -RT_EINVAL;
240 }
241 
242 /**
243  * @brief           Reset symmetric crypto context
244  *
245  * @param ctx       Symmetric crypto context
246  */
rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx * ctx)247 void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx)
248 {
249     struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;
250     if (ctx != RT_NULL)
251     {
252         /* Copy Symmetric Encryption and Decryption Context Information */
253         symmetric_ctx->flags      = 0x00;
254         symmetric_ctx->iv_len     = 0x00;
255         symmetric_ctx->iv_off     = 0x00;
256         symmetric_ctx->key_bitlen = 0x00;
257         rt_memset(symmetric_ctx->iv, 0, RT_HWCRYPTO_IV_MAX_SIZE);
258         rt_memset(symmetric_ctx->key, 0, RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3);
259 
260         /* Hardware context reset */
261         rt_hwcrypto_ctx_reset(ctx);
262     }
263 }
264 
265 /**
266  * @brief           Setting symmetric crypto context type
267  *
268  * @param ctx       Symmetric crypto context
269  * @param type      Types of settings
270  *
271  * @return          RT_EOK on success.
272  */
rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx * ctx,hwcrypto_type type)273 rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type)
274 {
275     return rt_hwcrypto_set_type(ctx, type);
276 }
277