Skip to content

Commit 62476b1

Browse files
committed
Add minimal buffer encrypt and decrypt example for AES-GCM
1 parent f2dec15 commit 62476b1

File tree

3 files changed

+199
-2
lines changed

3 files changed

+199
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ crypto/aes/aescfb-file-encrypt
136136
crypto/aes/aesctr-file-encrypt
137137
crypto/aes/aesgcm-file-encrypt
138138
crypto/aes/aesgcm-oneshot
139+
crypto/aes/aesgcm-minimal
139140
crypto/camellia/camellia-encrypt
140141
crypto/pkcs12/pkcs12-create-example
141142
crypto/pkcs12/pkcs12-example

crypto/aes/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ CFLAGS=-Wall
33
WOLFSSL_INSTALL_DIR=/usr/local
44
LIBS=-L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl -lm
55

6-
all: aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt aesgcm-oneshot
6+
all: aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt aesgcm-oneshot aesgcm-minimal
77

88
aes-file-encrypt: aes-file-encrypt.o
99
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
@@ -20,7 +20,10 @@ aesgcm-file-encrypt: aesgcm-file-encrypt.o
2020
aesgcm-oneshot: aesgcm-oneshot.o
2121
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
2222

23+
aesgcm-minimal: aesgcm-minimal.o
24+
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
25+
2326
.PHONY: clean
2427

2528
clean:
26-
rm -f *.o aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt text* aesgcm-oneshot
29+
rm -f *.o aes-file-encrypt aescfb-file-encrypt aesctr-file-encrypt aesgcm-file-encrypt text* aesgcm-oneshot aesgcm-minimal

crypto/aes/aesgcm-minimal.c

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/* aesgcm-minimal.c
2+
*
3+
* Copyright (C) 2006-2026 wolfSSL Inc.
4+
*
5+
* This file is part of wolfSSL.
6+
*
7+
* wolfSSL is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfSSL is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
#ifndef WOLFSSL_USER_SETTINGS
23+
#include <wolfssl/options.h>
24+
#endif
25+
#include <wolfssl/wolfcrypt/aes.h>
26+
#include <wolfssl/wolfcrypt/error-crypt.h>
27+
#include <wolfssl/wolfcrypt/random.h>
28+
29+
#include <stdio.h>
30+
#include <string.h>
31+
32+
#define KEY_SZ AES_256_KEY_SIZE
33+
#define NONCE_SZ GCM_NONCE_MID_SZ
34+
#define TAG_SZ AES_BLOCK_SIZE
35+
36+
/* Optional setup path: seed wolfSSL RNG via RDSEED when available. */
37+
#if defined(__x86_64__)
38+
#define RDSEED_ENABLED 1
39+
#endif
40+
41+
#if defined(WC_RNG_SEED_CB) && defined(RDSEED_ENABLED)
42+
#include <immintrin.h>
43+
44+
/* wc_RngSeed_Cb: feed wolfSSL DRBG seed using RDSEED. */
45+
__attribute__((target("rdseed")))
46+
static int RdseedSeedCb(OS_Seed* os, byte* seed, word32 sz)
47+
{
48+
word32 i = 0;
49+
(void)os;
50+
51+
while (i < sz) {
52+
unsigned long long v = 0;
53+
int ok = 0;
54+
int tries;
55+
word32 n;
56+
57+
for (tries = 0; tries < 16; tries++) {
58+
if (_rdseed64_step(&v)) {
59+
ok = 1;
60+
break;
61+
}
62+
}
63+
if (!ok) {
64+
return RNG_FAILURE_E;
65+
}
66+
67+
n = (sz - i < (word32)sizeof(v)) ? (sz - i) : (word32)sizeof(v);
68+
memcpy(seed + i, &v, n);
69+
i += n;
70+
}
71+
return 0;
72+
}
73+
#endif
74+
75+
static int GenerateKeyAndIv(byte* key, byte* iv)
76+
{
77+
WC_RNG rng;
78+
int ret;
79+
80+
/* Setup: initialize RNG and (optionally) override seed source. */
81+
#if defined(WC_RNG_SEED_CB) && defined(RDSEED_ENABLED)
82+
wc_SetSeed_Cb(RdseedSeedCb);
83+
ret = wc_InitRng(&rng);
84+
wc_SetSeed_Cb(NULL);
85+
#else
86+
ret = wc_InitRng(&rng);
87+
#endif
88+
if (ret != 0) {
89+
return ret;
90+
}
91+
92+
ret = wc_RNG_GenerateBlock(&rng, key, KEY_SZ);
93+
if (ret == 0) {
94+
ret = wc_RNG_GenerateBlock(&rng, iv, NONCE_SZ);
95+
}
96+
wc_FreeRng(&rng);
97+
return ret;
98+
}
99+
100+
static int Encrypt(const byte* key, const byte* iv, const byte* plaintext,
101+
word32 plaintextSz, byte* ciphertext, byte* tag, const byte* aad,
102+
word32 aadSz)
103+
{
104+
int ret;
105+
Aes aes;
106+
107+
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
108+
if (ret == 0) {
109+
ret = wc_AesGcmSetKey(&aes, key, KEY_SZ);
110+
}
111+
if (ret == 0) {
112+
ret = wc_AesGcmEncrypt(&aes, ciphertext, plaintext, plaintextSz, iv,
113+
NONCE_SZ, tag, TAG_SZ, aad, aadSz);
114+
}
115+
wc_AesFree(&aes);
116+
return ret;
117+
}
118+
119+
static int Decrypt(const byte* key, const byte* iv, const byte* ciphertext,
120+
word32 ciphertextSz, byte* plaintext, const byte* tag, const byte* aad,
121+
word32 aadSz)
122+
{
123+
int ret;
124+
Aes aes;
125+
126+
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
127+
if (ret == 0) {
128+
ret = wc_AesGcmSetKey(&aes, key, KEY_SZ);
129+
}
130+
if (ret == 0) {
131+
ret = wc_AesGcmDecrypt(&aes, plaintext, ciphertext, ciphertextSz, iv,
132+
NONCE_SZ, tag, TAG_SZ, aad, aadSz);
133+
}
134+
wc_AesFree(&aes);
135+
return ret;
136+
}
137+
138+
void print_hex(const char* label, const byte* data, word32 sz)
139+
{
140+
printf("%s: ", label);
141+
for (word32 i = 0; i < sz; i++) {
142+
printf("%02x", data[i]);
143+
}
144+
printf("\n");
145+
}
146+
147+
int main(void)
148+
{
149+
/* Setup/example data and buffers. */
150+
byte key[KEY_SZ];
151+
const byte aad[] = "example-aad";
152+
const byte plaintext[] = "single block msg";
153+
byte decrypted[sizeof(plaintext)];
154+
byte iv[NONCE_SZ];
155+
byte ciphertext[sizeof(plaintext)];
156+
byte tag[TAG_SZ];
157+
int ret;
158+
159+
ret = GenerateKeyAndIv(key, iv);
160+
if (ret != 0) {
161+
printf("Key/IV generation failed: %d\n", ret);
162+
return 1;
163+
}
164+
print_hex("Plaintext", plaintext, sizeof(plaintext));
165+
print_hex(" Key", key, sizeof(key));
166+
print_hex(" IV", iv, sizeof(iv));
167+
168+
/* Encrypt with key + IV (+ optional AAD) to get tag. */
169+
ret = Encrypt(key, iv, plaintext, sizeof(plaintext), ciphertext, tag, aad,
170+
(word32)(sizeof(aad) - 1));
171+
if (ret != 0) {
172+
printf("Encryption failed: %d\n", ret);
173+
return 1;
174+
}
175+
print_hex("Ciphertext", ciphertext, sizeof(ciphertext));
176+
print_hex(" Auth Tag", tag, sizeof(tag));
177+
178+
/* Decrypt with the same key/IV/AAD and received tag. */
179+
ret = Decrypt(key, iv, ciphertext, sizeof(ciphertext), decrypted, tag, aad,
180+
(word32)(sizeof(aad) - 1));
181+
if (ret != 0) {
182+
printf("Decryption failed: %d\n", ret);
183+
return 1;
184+
}
185+
186+
if (memcmp(plaintext, decrypted, sizeof(plaintext)) != 0) {
187+
printf("Round-trip mismatch\n");
188+
return 1;
189+
}
190+
print_hex("Decrypted", decrypted, sizeof(decrypted));
191+
192+
return 0;
193+
}

0 commit comments

Comments
 (0)