Skip to content

Commit 1d0c480

Browse files
committed
AES modes extravaganza. ofb, siv, xts
1 parent 123d562 commit 1d0c480

3 files changed

Lines changed: 973 additions & 0 deletions

File tree

crypto/aes-modes/aes-ofb.c

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
/* aes-ofb.c
2+
*
3+
* Copyright (C) 2006-2025 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+
/* AES-OFB Example
23+
* This example demonstrates:
24+
* - One-shot encryption using wc_AesOfbEncrypt()
25+
* - Streaming decryption using wc_AesOfbDecrypt() in chunks
26+
* Note: OFB mode inherently supports streaming (no padding required)
27+
*/
28+
29+
#include <stdio.h>
30+
#include <stdlib.h>
31+
#include <string.h>
32+
33+
#ifndef WOLFSSL_USER_SETTINGS
34+
#include <wolfssl/options.h>
35+
#endif
36+
#include <wolfssl/wolfcrypt/settings.h>
37+
#include <wolfssl/wolfcrypt/aes.h>
38+
#include <wolfssl/wolfcrypt/random.h>
39+
#include <wolfssl/wolfcrypt/error-crypt.h>
40+
41+
#if !defined(NO_AES) && defined(WOLFSSL_AES_OFB)
42+
43+
#define AES_KEY_SIZE AES_256_KEY_SIZE
44+
45+
/* Small chunk size to demonstrate streaming */
46+
#define CHUNK_SIZE 64
47+
48+
static int read_file(const char* filename, byte** data, word32* dataSz)
49+
{
50+
FILE* fp;
51+
long fileSz;
52+
53+
fp = fopen(filename, "rb");
54+
if (fp == NULL) {
55+
printf("Error: Cannot open file %s\n", filename);
56+
return -1;
57+
}
58+
59+
fseek(fp, 0, SEEK_END);
60+
fileSz = ftell(fp);
61+
fseek(fp, 0, SEEK_SET);
62+
63+
*data = (byte*)malloc(fileSz);
64+
if (*data == NULL) {
65+
fclose(fp);
66+
printf("Error: Memory allocation failed\n");
67+
return -1;
68+
}
69+
70+
*dataSz = (word32)fread(*data, 1, fileSz, fp);
71+
fclose(fp);
72+
73+
return 0;
74+
}
75+
76+
static int write_file(const char* filename, const byte* data, word32 dataSz)
77+
{
78+
FILE* fp;
79+
80+
fp = fopen(filename, "wb");
81+
if (fp == NULL) {
82+
printf("Error: Cannot create file %s\n", filename);
83+
return -1;
84+
}
85+
86+
fwrite(data, 1, dataSz, fp);
87+
fclose(fp);
88+
89+
return 0;
90+
}
91+
92+
/* One-shot encryption */
93+
static int encrypt_file(const char* inFile, const char* outFile,
94+
const byte* key, word32 keySz)
95+
{
96+
Aes aes;
97+
WC_RNG rng;
98+
byte iv[AES_BLOCK_SIZE];
99+
byte* plaintext = NULL;
100+
byte* ciphertext = NULL;
101+
word32 plaintextSz;
102+
int ret;
103+
104+
ret = read_file(inFile, &plaintext, &plaintextSz);
105+
if (ret != 0) return ret;
106+
107+
/* IV + ciphertext */
108+
ciphertext = (byte*)malloc(plaintextSz + AES_BLOCK_SIZE);
109+
if (ciphertext == NULL) {
110+
free(plaintext);
111+
return -1;
112+
}
113+
114+
/* Generate random IV */
115+
ret = wc_InitRng(&rng);
116+
if (ret != 0) {
117+
free(plaintext);
118+
free(ciphertext);
119+
return ret;
120+
}
121+
122+
ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE);
123+
wc_FreeRng(&rng);
124+
if (ret != 0) {
125+
free(plaintext);
126+
free(ciphertext);
127+
return ret;
128+
}
129+
130+
/* Initialize AES */
131+
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
132+
if (ret != 0) {
133+
free(plaintext);
134+
free(ciphertext);
135+
return ret;
136+
}
137+
138+
ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION);
139+
if (ret != 0) {
140+
wc_AesFree(&aes);
141+
free(plaintext);
142+
free(ciphertext);
143+
return ret;
144+
}
145+
146+
/* One-shot encrypt */
147+
ret = wc_AesOfbEncrypt(&aes, ciphertext + AES_BLOCK_SIZE, plaintext,
148+
plaintextSz);
149+
wc_AesFree(&aes);
150+
151+
if (ret != 0) {
152+
free(plaintext);
153+
free(ciphertext);
154+
return ret;
155+
}
156+
157+
/* Prepend IV to output */
158+
memcpy(ciphertext, iv, AES_BLOCK_SIZE);
159+
160+
ret = write_file(outFile, ciphertext, plaintextSz + AES_BLOCK_SIZE);
161+
162+
free(plaintext);
163+
free(ciphertext);
164+
165+
printf("AES-OFB encryption complete (one-shot)\n");
166+
return ret;
167+
}
168+
169+
/* Streaming decryption - process in chunks */
170+
static int decrypt_file(const char* inFile, const char* outFile,
171+
const byte* key, word32 keySz)
172+
{
173+
Aes aes;
174+
byte iv[AES_BLOCK_SIZE];
175+
byte* ciphertext = NULL;
176+
byte* plaintext = NULL;
177+
word32 ciphertextSz;
178+
word32 plaintextSz;
179+
word32 offset;
180+
word32 chunkSz;
181+
int ret;
182+
183+
ret = read_file(inFile, &ciphertext, &ciphertextSz);
184+
if (ret != 0) return ret;
185+
186+
if (ciphertextSz < AES_BLOCK_SIZE) {
187+
free(ciphertext);
188+
printf("Error: File too small\n");
189+
return -1;
190+
}
191+
192+
/* Extract IV from beginning */
193+
memcpy(iv, ciphertext, AES_BLOCK_SIZE);
194+
195+
plaintextSz = ciphertextSz - AES_BLOCK_SIZE;
196+
plaintext = (byte*)malloc(plaintextSz);
197+
if (plaintext == NULL) {
198+
free(ciphertext);
199+
return -1;
200+
}
201+
202+
/* Initialize AES */
203+
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
204+
if (ret != 0) {
205+
free(ciphertext);
206+
free(plaintext);
207+
return ret;
208+
}
209+
210+
ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION);
211+
if (ret != 0) {
212+
wc_AesFree(&aes);
213+
free(ciphertext);
214+
free(plaintext);
215+
return ret;
216+
}
217+
218+
/* Streaming decrypt - process in chunks */
219+
printf("AES-OFB streaming decryption:\n");
220+
offset = 0;
221+
while (offset < plaintextSz) {
222+
chunkSz = plaintextSz - offset;
223+
if (chunkSz > CHUNK_SIZE) {
224+
chunkSz = CHUNK_SIZE;
225+
}
226+
227+
ret = wc_AesOfbDecrypt(&aes, plaintext + offset,
228+
ciphertext + AES_BLOCK_SIZE + offset, chunkSz);
229+
if (ret != 0) {
230+
wc_AesFree(&aes);
231+
free(ciphertext);
232+
free(plaintext);
233+
return ret;
234+
}
235+
236+
printf(" Decrypted chunk: offset=%u, size=%u\n", offset, chunkSz);
237+
offset += chunkSz;
238+
}
239+
240+
wc_AesFree(&aes);
241+
242+
ret = write_file(outFile, plaintext, plaintextSz);
243+
244+
free(ciphertext);
245+
free(plaintext);
246+
247+
printf("AES-OFB decryption complete (streaming)\n");
248+
return ret;
249+
}
250+
251+
int main(int argc, char** argv)
252+
{
253+
byte key[AES_KEY_SIZE];
254+
int ret;
255+
256+
if (argc != 3) {
257+
printf("Usage: %s <input file> <output file>\n", argv[0]);
258+
printf("Encrypts input file (one-shot), then decrypts to output file "
259+
"(streaming)\n");
260+
return 1;
261+
}
262+
263+
wolfCrypt_Init();
264+
265+
/* Use a fixed key for demonstration */
266+
memset(key, 0x05, AES_KEY_SIZE);
267+
268+
/* Encrypt to temporary file */
269+
ret = encrypt_file(argv[1], "temp_encrypted.bin", key, AES_KEY_SIZE);
270+
if (ret != 0) {
271+
printf("Encryption failed: %d\n", ret);
272+
wolfCrypt_Cleanup();
273+
return 1;
274+
}
275+
276+
/* Decrypt to output file */
277+
ret = decrypt_file("temp_encrypted.bin", argv[2], key, AES_KEY_SIZE);
278+
if (ret != 0) {
279+
printf("Decryption failed: %d\n", ret);
280+
wolfCrypt_Cleanup();
281+
return 1;
282+
}
283+
284+
/* Clean up temp file */
285+
remove("temp_encrypted.bin");
286+
287+
printf("Success! Decrypted file written to %s\n", argv[2]);
288+
289+
wolfCrypt_Cleanup();
290+
return 0;
291+
}
292+
293+
#else
294+
295+
int main(int argc, char** argv)
296+
{
297+
(void)argc;
298+
(void)argv;
299+
printf("AES-OFB not compiled in. Enable with WOLFSSL_AES_OFB\n");
300+
return 0;
301+
}
302+
303+
#endif

0 commit comments

Comments
 (0)