13
13
#include <re_aes.h>
14
14
15
15
16
- #ifdef EVP_CIPH_CTR_MODE
17
-
18
-
19
16
struct aes {
20
17
EVP_CIPHER_CTX * ctx ;
18
+ enum aes_mode mode ;
19
+ bool encr ;
21
20
};
22
21
23
22
23
+ static const EVP_CIPHER * aes_cipher (enum aes_mode mode , size_t key_bits )
24
+ {
25
+ if (mode == AES_MODE_CTR ) {
26
+
27
+ switch (key_bits ) {
28
+
29
+ case 128 : return EVP_aes_128_ctr ();
30
+ case 192 : return EVP_aes_192_ctr ();
31
+ case 256 : return EVP_aes_256_ctr ();
32
+ default :
33
+ return NULL ;
34
+ }
35
+ }
36
+ else if (mode == AES_MODE_GCM ) {
37
+
38
+ switch (key_bits ) {
39
+
40
+ case 128 : return EVP_aes_128_gcm ();
41
+ case 256 : return EVP_aes_256_gcm ();
42
+ default :
43
+ return NULL ;
44
+ }
45
+ }
46
+ else {
47
+ return NULL ;
48
+ }
49
+ }
50
+
51
+
52
+ static inline bool set_crypt_dir (struct aes * aes , bool encr )
53
+ {
54
+ if (aes -> encr != encr ) {
55
+
56
+ /* update the encrypt/decrypt direction */
57
+ if (!EVP_CipherInit_ex (aes -> ctx , NULL , NULL ,
58
+ NULL , NULL , encr )) {
59
+ ERR_clear_error ();
60
+ return false;
61
+ }
62
+
63
+ aes -> encr = encr ;
64
+ }
65
+
66
+ return true;
67
+ }
68
+
69
+
24
70
static void destructor (void * arg )
25
71
{
26
72
struct aes * st = arg ;
@@ -38,7 +84,7 @@ static void destructor(void *arg)
38
84
39
85
int aes_alloc (struct aes * * aesp , enum aes_mode mode ,
40
86
const uint8_t * key , size_t key_bits ,
41
- const uint8_t iv [ AES_BLOCK_SIZE ] )
87
+ const uint8_t * iv )
42
88
{
43
89
const EVP_CIPHER * cipher ;
44
90
struct aes * st ;
@@ -47,13 +93,17 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
47
93
if (!aesp || !key )
48
94
return EINVAL ;
49
95
50
- if (mode != AES_MODE_CTR )
96
+ cipher = aes_cipher (mode , key_bits );
97
+ if (!cipher )
51
98
return ENOTSUP ;
52
99
53
100
st = mem_zalloc (sizeof (* st ), destructor );
54
101
if (!st )
55
102
return ENOMEM ;
56
103
104
+ st -> mode = mode ;
105
+ st -> encr = true;
106
+
57
107
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
58
108
st -> ctx = EVP_CIPHER_CTX_new ();
59
109
if (!st -> ctx ) {
@@ -72,17 +122,6 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
72
122
EVP_CIPHER_CTX_init (st -> ctx );
73
123
#endif
74
124
75
- switch (key_bits ) {
76
-
77
- case 128 : cipher = EVP_aes_128_ctr (); break ;
78
- case 192 : cipher = EVP_aes_192_ctr (); break ;
79
- case 256 : cipher = EVP_aes_256_ctr (); break ;
80
- default :
81
- re_fprintf (stderr , "aes: unknown key: %zu bits\n" , key_bits );
82
- err = EINVAL ;
83
- goto out ;
84
- }
85
-
86
125
r = EVP_EncryptInit_ex (st -> ctx , cipher , NULL , key , iv );
87
126
if (!r ) {
88
127
ERR_clear_error ();
@@ -99,14 +138,14 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
99
138
}
100
139
101
140
102
- void aes_set_iv (struct aes * aes , const uint8_t iv [ AES_BLOCK_SIZE ] )
141
+ void aes_set_iv (struct aes * aes , const uint8_t * iv )
103
142
{
104
143
int r ;
105
144
106
145
if (!aes || !iv )
107
146
return ;
108
147
109
- r = EVP_EncryptInit_ex (aes -> ctx , NULL , NULL , NULL , iv );
148
+ r = EVP_CipherInit_ex (aes -> ctx , NULL , NULL , NULL , iv , -1 );
110
149
if (!r )
111
150
ERR_clear_error ();
112
151
}
@@ -116,9 +155,12 @@ int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len)
116
155
{
117
156
int c_len = (int )len ;
118
157
119
- if (!aes || !out || ! in )
158
+ if (!aes || !in )
120
159
return EINVAL ;
121
160
161
+ if (!set_crypt_dir (aes , true))
162
+ return EPROTO ;
163
+
122
164
if (!EVP_EncryptUpdate (aes -> ctx , out , & c_len , in , (int )len )) {
123
165
ERR_clear_error ();
124
166
return EPROTO ;
@@ -128,91 +170,98 @@ int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len)
128
170
}
129
171
130
172
131
- #else /* EVP_CIPH_CTR_MODE */
132
-
173
+ int aes_decr (struct aes * aes , uint8_t * out , const uint8_t * in , size_t len )
174
+ {
175
+ int c_len = (int )len ;
133
176
134
- struct aes {
135
- AES_KEY key ;
136
- uint8_t iv [AES_BLOCK_SIZE ];
137
- };
177
+ if (!aes || !in )
178
+ return EINVAL ;
138
179
180
+ if (!set_crypt_dir (aes , false))
181
+ return EPROTO ;
139
182
140
- static void destructor (void * arg )
141
- {
142
- struct aes * st = arg ;
183
+ if (!EVP_DecryptUpdate (aes -> ctx , out , & c_len , in , (int )len )) {
184
+ ERR_clear_error ();
185
+ return EPROTO ;
186
+ }
143
187
144
- memset ( & st -> key , 0 , sizeof ( st -> key )) ;
188
+ return 0 ;
145
189
}
146
190
147
191
148
- int aes_alloc (struct aes * * aesp , enum aes_mode mode ,
149
- const uint8_t * key , size_t key_bits ,
150
- const uint8_t iv [AES_BLOCK_SIZE ])
192
+ /**
193
+ * Get the authentication tag for an AEAD cipher (e.g. GCM)
194
+ *
195
+ * @param aes AES Context
196
+ * @param tag Authentication tag
197
+ * @param taglen Length of Authentication tag
198
+ *
199
+ * @return 0 if success, otherwise errorcode
200
+ */
201
+ int aes_get_authtag (struct aes * aes , uint8_t * tag , size_t taglen )
151
202
{
152
- struct aes * st ;
153
- int err = 0 , r ;
203
+ int tmplen ;
154
204
155
- if (!aesp || !key )
205
+ if (!aes || !tag || ! taglen )
156
206
return EINVAL ;
157
207
158
- if (mode != AES_MODE_CTR )
159
- return ENOTSUP ;
160
-
161
- st = mem_zalloc (sizeof (* st ), destructor );
162
- if (!st )
163
- return ENOMEM ;
208
+ switch (aes -> mode ) {
164
209
165
- r = AES_set_encrypt_key (key , (int )key_bits , & st -> key );
166
- if (r != 0 ) {
167
- err = EPROTO ;
168
- goto out ;
169
- }
170
- if (iv )
171
- memcpy (st -> iv , iv , sizeof (st -> iv ));
172
-
173
- out :
174
- if (err )
175
- mem_deref (st );
176
- else
177
- * aesp = st ;
178
-
179
- return err ;
180
- }
210
+ case AES_MODE_GCM :
211
+ if (!EVP_EncryptFinal_ex (aes -> ctx , NULL , & tmplen )) {
212
+ ERR_clear_error ();
213
+ return EPROTO ;
214
+ }
181
215
216
+ if (!EVP_CIPHER_CTX_ctrl (aes -> ctx , EVP_CTRL_GCM_GET_TAG ,
217
+ (int )taglen , tag )) {
218
+ ERR_clear_error ();
219
+ return EPROTO ;
220
+ }
182
221
183
- void aes_set_iv (struct aes * aes , const uint8_t iv [AES_BLOCK_SIZE ])
184
- {
185
- if (!aes )
186
- return ;
222
+ return 0 ;
187
223
188
- if (iv )
189
- memcpy (aes -> iv , iv , sizeof (aes -> iv ));
224
+ default :
225
+ return ENOTSUP ;
226
+ }
190
227
}
191
228
192
229
193
- int aes_encr (struct aes * aes , uint8_t * out , const uint8_t * in , size_t len )
230
+ /**
231
+ * Authenticate a decryption tag for an AEAD cipher (e.g. GCM)
232
+ *
233
+ * @param aes AES Context
234
+ * @param tag Authentication tag
235
+ * @param taglen Length of Authentication tag
236
+ *
237
+ * @return 0 if success, otherwise errorcode
238
+ *
239
+ * @retval EAUTH if authentication failed
240
+ */
241
+ int aes_authenticate (struct aes * aes , const uint8_t * tag , size_t taglen )
194
242
{
195
- unsigned char ec [AES_BLOCK_SIZE ] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
196
- unsigned int num = 0 ;
243
+ int tmplen ;
197
244
198
- if (!aes || !out || !in )
245
+ if (!aes || !tag || !taglen )
199
246
return EINVAL ;
200
247
201
- AES_ctr128_encrypt (in , out , len , & aes -> key , aes -> iv , ec , & num );
202
-
203
- return 0 ;
204
- }
248
+ switch (aes -> mode ) {
205
249
250
+ case AES_MODE_GCM :
251
+ if (!EVP_CIPHER_CTX_ctrl (aes -> ctx , EVP_CTRL_GCM_SET_TAG ,
252
+ (int )taglen , (void * )tag )) {
253
+ ERR_clear_error ();
254
+ return EPROTO ;
255
+ }
206
256
207
- #endif /* EVP_CIPH_CTR_MODE */
208
-
209
-
210
- /*
211
- * Common code:
212
- */
257
+ if (EVP_DecryptFinal_ex (aes -> ctx , NULL , & tmplen ) <= 0 ) {
258
+ ERR_clear_error ();
259
+ return EAUTH ;
260
+ }
213
261
262
+ return 0 ;
214
263
215
- int aes_decr ( struct aes * aes , uint8_t * out , const uint8_t * in , size_t len )
216
- {
217
- return aes_encr ( aes , out , in , len );
264
+ default :
265
+ return ENOTSUP ;
266
+ }
218
267
}
0 commit comments