Skip to content

Commit 153abea

Browse files
Merge pull request #545 from anhu/aes_modes_cts
AES modes extravaganza. CTS
2 parents b179722 + 482ade5 commit 153abea

1 file changed

Lines changed: 265 additions & 0 deletions

File tree

crypto/aes-modes/aes-cts.c

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/* aes-cts.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-CTS Example
23+
* This example demonstrates:
24+
* - One-shot encryption using wc_AesCtsEncrypt()
25+
* - One-shot decryption using wc_AesCtsDecrypt()
26+
* Note: CTS (Ciphertext Stealing) allows encryption of data that is not
27+
* a multiple of the block size without padding expansion
28+
* Requires minimum 16 bytes input
29+
* Note: CTS streaming API (Update/Final) requires careful handling of
30+
* internal buffering and is not demonstrated in this example.
31+
*/
32+
33+
#include <stdio.h>
34+
#include <stdlib.h>
35+
#include <string.h>
36+
37+
#ifndef WOLFSSL_USER_SETTINGS
38+
#include <wolfssl/options.h>
39+
#endif
40+
#include <wolfssl/wolfcrypt/settings.h>
41+
#include <wolfssl/wolfcrypt/aes.h>
42+
#include <wolfssl/wolfcrypt/random.h>
43+
#include <wolfssl/wolfcrypt/error-crypt.h>
44+
45+
#if !defined(NO_AES) && defined(WOLFSSL_AES_CTS)
46+
47+
#define AES_KEY_SIZE AES_256_KEY_SIZE
48+
49+
static int read_file(const char* filename, byte** data, word32* dataSz)
50+
{
51+
FILE* fp;
52+
long fileSz;
53+
54+
fp = fopen(filename, "rb");
55+
if (fp == NULL) {
56+
printf("Error: Cannot open file %s\n", filename);
57+
return -1;
58+
}
59+
60+
fseek(fp, 0, SEEK_END);
61+
fileSz = ftell(fp);
62+
fseek(fp, 0, SEEK_SET);
63+
64+
*data = (byte*)malloc(fileSz);
65+
if (*data == NULL) {
66+
fclose(fp);
67+
printf("Error: Memory allocation failed\n");
68+
return -1;
69+
}
70+
71+
*dataSz = (word32)fread(*data, 1, fileSz, fp);
72+
fclose(fp);
73+
74+
return 0;
75+
}
76+
77+
static int write_file(const char* filename, const byte* data, word32 dataSz)
78+
{
79+
FILE* fp;
80+
81+
fp = fopen(filename, "wb");
82+
if (fp == NULL) {
83+
printf("Error: Cannot create file %s\n", filename);
84+
return -1;
85+
}
86+
87+
fwrite(data, 1, dataSz, fp);
88+
fclose(fp);
89+
90+
return 0;
91+
}
92+
93+
/* One-shot encryption */
94+
static int encrypt_file(const char* inFile, const char* outFile,
95+
const byte* key, word32 keySz)
96+
{
97+
WC_RNG rng;
98+
byte iv[AES_BLOCK_SIZE];
99+
byte* plaintext = NULL;
100+
byte* output = NULL;
101+
word32 plaintextSz;
102+
word32 outputSz;
103+
int ret;
104+
105+
ret = read_file(inFile, &plaintext, &plaintextSz);
106+
if (ret != 0) return ret;
107+
108+
/* CTS requires minimum 16 bytes */
109+
if (plaintextSz < AES_BLOCK_SIZE) {
110+
printf("Error: Input must be at least %d bytes for CTS\n",
111+
AES_BLOCK_SIZE);
112+
free(plaintext);
113+
return -1;
114+
}
115+
116+
/* Output: IV + ciphertext (same size as plaintext with CTS) */
117+
outputSz = AES_BLOCK_SIZE + plaintextSz;
118+
output = (byte*)malloc(outputSz);
119+
if (output == NULL) {
120+
free(plaintext);
121+
return -1;
122+
}
123+
124+
/* Generate random IV */
125+
ret = wc_InitRng(&rng);
126+
if (ret != 0) {
127+
free(plaintext);
128+
free(output);
129+
return ret;
130+
}
131+
132+
ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE);
133+
wc_FreeRng(&rng);
134+
if (ret != 0) {
135+
free(plaintext);
136+
free(output);
137+
return ret;
138+
}
139+
140+
/* One-shot encrypt */
141+
ret = wc_AesCtsEncrypt(key, keySz, output + AES_BLOCK_SIZE,
142+
plaintext, plaintextSz, iv);
143+
144+
if (ret != 0) {
145+
free(plaintext);
146+
free(output);
147+
return ret;
148+
}
149+
150+
/* Prepend IV to output */
151+
memcpy(output, iv, AES_BLOCK_SIZE);
152+
153+
ret = write_file(outFile, output, outputSz);
154+
155+
free(plaintext);
156+
free(output);
157+
158+
printf("AES-CTS encryption complete (one-shot)\n");
159+
return ret;
160+
}
161+
162+
/* One-shot decryption (CTS streaming API requires complex buffering) */
163+
static int decrypt_file(const char* inFile, const char* outFile,
164+
const byte* key, word32 keySz)
165+
{
166+
byte iv[AES_BLOCK_SIZE];
167+
byte* input = NULL;
168+
byte* plaintext = NULL;
169+
word32 inputSz;
170+
word32 ciphertextSz;
171+
int ret;
172+
173+
ret = read_file(inFile, &input, &inputSz);
174+
if (ret != 0) return ret;
175+
176+
if (inputSz < AES_BLOCK_SIZE * 2) {
177+
free(input);
178+
printf("Error: File too small\n");
179+
return -1;
180+
}
181+
182+
/* Extract IV from beginning */
183+
memcpy(iv, input, AES_BLOCK_SIZE);
184+
185+
ciphertextSz = inputSz - AES_BLOCK_SIZE;
186+
plaintext = (byte*)malloc(ciphertextSz);
187+
if (plaintext == NULL) {
188+
free(input);
189+
return -1;
190+
}
191+
192+
/* One-shot decrypt */
193+
ret = wc_AesCtsDecrypt(key, keySz, plaintext,
194+
input + AES_BLOCK_SIZE, ciphertextSz, iv);
195+
196+
if (ret != 0) {
197+
free(input);
198+
free(plaintext);
199+
return ret;
200+
}
201+
202+
ret = write_file(outFile, plaintext, ciphertextSz);
203+
204+
free(input);
205+
free(plaintext);
206+
207+
printf("AES-CTS decryption complete (one-shot, no streaming API "
208+
"available)\n");
209+
return ret;
210+
}
211+
212+
int main(int argc, char** argv)
213+
{
214+
byte key[AES_KEY_SIZE];
215+
int ret;
216+
217+
if (argc != 3) {
218+
printf("Usage: %s <input file> <output file>\n", argv[0]);
219+
printf("Encrypts input file (one-shot), then decrypts to output file "
220+
"(streaming)\n");
221+
printf("Note: Input must be at least 16 bytes\n");
222+
return 1;
223+
}
224+
225+
wolfCrypt_Init();
226+
227+
/* Use a fixed key for demonstration */
228+
memset(key, 0x10, AES_KEY_SIZE);
229+
230+
/* Encrypt to temporary file */
231+
ret = encrypt_file(argv[1], "temp_encrypted.bin", key, AES_KEY_SIZE);
232+
if (ret != 0) {
233+
printf("Encryption failed: %d\n", ret);
234+
wolfCrypt_Cleanup();
235+
return 1;
236+
}
237+
238+
/* Decrypt to output file */
239+
ret = decrypt_file("temp_encrypted.bin", argv[2], key, AES_KEY_SIZE);
240+
if (ret != 0) {
241+
printf("Decryption failed: %d\n", ret);
242+
wolfCrypt_Cleanup();
243+
return 1;
244+
}
245+
246+
/* Clean up temp file */
247+
remove("temp_encrypted.bin");
248+
249+
printf("Success! Decrypted file written to %s\n", argv[2]);
250+
251+
wolfCrypt_Cleanup();
252+
return 0;
253+
}
254+
255+
#else
256+
257+
int main(int argc, char** argv)
258+
{
259+
(void)argc;
260+
(void)argv;
261+
printf("AES-CTS not compiled in. Enable with WOLFSSL_AES_CTS\n");
262+
return 0;
263+
}
264+
265+
#endif

0 commit comments

Comments
 (0)