Skip to content

Commit b42724a

Browse files
alfredhrichaas
authored andcommitted
aes: add support for GCM Galois Counter Mode (creytiv#106)
* aes: add support for GCM Galois Counter Mode (AEAD) * add tag functions * variable length IV * set crypt direction * remove usage of old AES api * aes: set IV using EVP_CipherInit_ex
1 parent 6241871 commit b42724a

File tree

4 files changed

+177
-85
lines changed

4 files changed

+177
-85
lines changed

include/re_aes.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111

1212
/** AES mode */
1313
enum aes_mode {
14-
AES_MODE_CTR /**< AES Counter mode (CTR) */
14+
AES_MODE_CTR, /**< AES Counter mode (CTR) */
15+
AES_MODE_GCM, /**< AES Galois Counter Mode (GCM) */
1516
};
1617

1718
struct aes;
1819

1920
int aes_alloc(struct aes **stp, enum aes_mode mode,
2021
const uint8_t *key, size_t key_bits,
21-
const uint8_t iv[AES_BLOCK_SIZE]);
22-
void aes_set_iv(struct aes *aes, const uint8_t iv[AES_BLOCK_SIZE]);
22+
const uint8_t *iv);
23+
void aes_set_iv(struct aes *aes, const uint8_t *iv);
2324
int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len);
2425
int aes_decr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len);
26+
int aes_get_authtag(struct aes *aes, uint8_t *tag, size_t taglen);
27+
int aes_authenticate(struct aes *aes, const uint8_t *tag, size_t taglen);

src/aes/apple/aes.c

+22-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static void destructor(void *arg)
3030

3131
int aes_alloc(struct aes **stp, enum aes_mode mode,
3232
const uint8_t *key, size_t key_bits,
33-
const uint8_t iv[AES_BLOCK_SIZE])
33+
const uint8_t *iv)
3434
{
3535
struct aes *st;
3636
size_t key_bytes = key_bits / 8;
@@ -75,7 +75,7 @@ int aes_alloc(struct aes **stp, enum aes_mode mode,
7575
}
7676

7777

78-
void aes_set_iv(struct aes *st, const uint8_t iv[AES_BLOCK_SIZE])
78+
void aes_set_iv(struct aes *st, const uint8_t *iv)
7979
{
8080
CCCryptorStatus status;
8181

@@ -123,3 +123,23 @@ int aes_decr(struct aes *st, uint8_t *out, const uint8_t *in, size_t len)
123123
{
124124
return aes_encr(st, out, in, len);
125125
}
126+
127+
128+
int aes_get_authtag(struct aes *aes, uint8_t *tag, size_t taglen)
129+
{
130+
(void)aes;
131+
(void)tag;
132+
(void)taglen;
133+
134+
return ENOSYS;
135+
}
136+
137+
138+
int aes_authenticate(struct aes *aes, const uint8_t *tag, size_t taglen)
139+
{
140+
(void)aes;
141+
(void)tag;
142+
(void)taglen;
143+
144+
return ENOSYS;
145+
}

src/aes/openssl/aes.c

+129-80
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,60 @@
1313
#include <re_aes.h>
1414

1515

16-
#ifdef EVP_CIPH_CTR_MODE
17-
18-
1916
struct aes {
2017
EVP_CIPHER_CTX *ctx;
18+
enum aes_mode mode;
19+
bool encr;
2120
};
2221

2322

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+
2470
static void destructor(void *arg)
2571
{
2672
struct aes *st = arg;
@@ -38,7 +84,7 @@ static void destructor(void *arg)
3884

3985
int aes_alloc(struct aes **aesp, enum aes_mode mode,
4086
const uint8_t *key, size_t key_bits,
41-
const uint8_t iv[AES_BLOCK_SIZE])
87+
const uint8_t *iv)
4288
{
4389
const EVP_CIPHER *cipher;
4490
struct aes *st;
@@ -47,13 +93,17 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
4793
if (!aesp || !key)
4894
return EINVAL;
4995

50-
if (mode != AES_MODE_CTR)
96+
cipher = aes_cipher(mode, key_bits);
97+
if (!cipher)
5198
return ENOTSUP;
5299

53100
st = mem_zalloc(sizeof(*st), destructor);
54101
if (!st)
55102
return ENOMEM;
56103

104+
st->mode = mode;
105+
st->encr = true;
106+
57107
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
58108
st->ctx = EVP_CIPHER_CTX_new();
59109
if (!st->ctx) {
@@ -72,17 +122,6 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
72122
EVP_CIPHER_CTX_init(st->ctx);
73123
#endif
74124

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-
86125
r = EVP_EncryptInit_ex(st->ctx, cipher, NULL, key, iv);
87126
if (!r) {
88127
ERR_clear_error();
@@ -99,14 +138,14 @@ int aes_alloc(struct aes **aesp, enum aes_mode mode,
99138
}
100139

101140

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)
103142
{
104143
int r;
105144

106145
if (!aes || !iv)
107146
return;
108147

109-
r = EVP_EncryptInit_ex(aes->ctx, NULL, NULL, NULL, iv);
148+
r = EVP_CipherInit_ex(aes->ctx, NULL, NULL, NULL, iv, -1);
110149
if (!r)
111150
ERR_clear_error();
112151
}
@@ -116,9 +155,12 @@ int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len)
116155
{
117156
int c_len = (int)len;
118157

119-
if (!aes || !out || !in)
158+
if (!aes || !in)
120159
return EINVAL;
121160

161+
if (!set_crypt_dir(aes, true))
162+
return EPROTO;
163+
122164
if (!EVP_EncryptUpdate(aes->ctx, out, &c_len, in, (int)len)) {
123165
ERR_clear_error();
124166
return EPROTO;
@@ -128,91 +170,98 @@ int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len)
128170
}
129171

130172

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;
133176

134-
struct aes {
135-
AES_KEY key;
136-
uint8_t iv[AES_BLOCK_SIZE];
137-
};
177+
if (!aes || !in)
178+
return EINVAL;
138179

180+
if (!set_crypt_dir(aes, false))
181+
return EPROTO;
139182

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+
}
143187

144-
memset(&st->key, 0, sizeof(st->key));
188+
return 0;
145189
}
146190

147191

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)
151202
{
152-
struct aes *st;
153-
int err = 0, r;
203+
int tmplen;
154204

155-
if (!aesp || !key)
205+
if (!aes || !tag || !taglen)
156206
return EINVAL;
157207

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) {
164209

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+
}
181215

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+
}
182221

183-
void aes_set_iv(struct aes *aes, const uint8_t iv[AES_BLOCK_SIZE])
184-
{
185-
if (!aes)
186-
return;
222+
return 0;
187223

188-
if (iv)
189-
memcpy(aes->iv, iv, sizeof(aes->iv));
224+
default:
225+
return ENOTSUP;
226+
}
190227
}
191228

192229

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)
194242
{
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;
197244

198-
if (!aes || !out || !in)
245+
if (!aes || !tag || !taglen)
199246
return EINVAL;
200247

201-
AES_ctr128_encrypt(in, out, len, &aes->key, aes->iv, ec, &num);
202-
203-
return 0;
204-
}
248+
switch (aes->mode) {
205249

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+
}
206256

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+
}
213261

262+
return 0;
214263

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+
}
218267
}

src/aes/stub.c

+20
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,23 @@ int aes_decr(struct aes *st, uint8_t *out, const uint8_t *in, size_t len)
4545
(void)len;
4646
return ENOSYS;
4747
}
48+
49+
50+
int aes_get_authtag(struct aes *aes, uint8_t *tag, size_t taglen)
51+
{
52+
(void)aes;
53+
(void)tag;
54+
(void)taglen;
55+
56+
return ENOSYS;
57+
}
58+
59+
60+
int aes_authenticate(struct aes *aes, const uint8_t *tag, size_t taglen)
61+
{
62+
(void)aes;
63+
(void)tag;
64+
(void)taglen;
65+
66+
return ENOSYS;
67+
}

0 commit comments

Comments
 (0)