1 unit AES_CBC;
2
3 (*************************************************************************
4
5 DESCRIPTION : AES CBC functions
6
7 REQUIREMENTS : TP5-7, D1-D7/D9-D10/D12, FPC, VP
8
9 EXTERNAL DATA : ---
10
11 MEMORY USAGE : ---
12
13 DISPLAY MODE : ---
14
15 REFERENCES : [3] http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
16 [1] http://csrc.nist.gov/fips/fips-197.pdf
17 [4] Cipher text stealing: Schneier, Applied Cryptography 2.ed, ch.9.3
18
19
20 Version Date Author Modification
21 ------- -------- ------- ------------------------------------------
22 0.10 20.09.03 we initial version
23 0.20 21.09.03 we Cipher text stealing
24 0.21 21.09.03 we with Flag, functions, error codes
25 0.22 27.09.03 we FPC/go32v2
26 0.23 03.10.03 we 3-para encr/decr
27 0.24 03.10.03 we Fix overwrite source bug for decrypt
28 0.25 05.10.03 we STD.INC, TP5-6
29 0.26 12.06.04 we uses BLKSIZE constant
30 0.27 12.06.04 we check for nil pointers
31 0.28 02.07.04 we {$ifdef DLL} stdcall; {$endif}
32 0.29 30.11.04 we AES_XorBlock, AESBLKSIZE
33 0.30 01.12.04 we No more processing after short block
34 0.31 09.07.06 we Checked: D9-D10
35 0.34 16.11.08 we Use Ptr2Inc from BTypes
36 0.35 27.07.10 we Longint ILen in AES_CBC_En/Decrypt
37 **************************************************************************)
38
39
40 (*-------------------------------------------------------------------------
41 (C) Copyright 2002-2010 Wolfgang Ehrhardt
42
43 This software is provided 'as-is', without any express or implied warranty.
44 In no event will the authors be held liable for any damages arising from
45 the use of this software.
46
47 Permission is granted to anyone to use this software for any purpose,
48 including commercial applications, and to alter it and redistribute it
49 freely, subject to the following restrictions:
50
51 1. The origin of this software must not be misrepresented; you must not
52 claim that you wrote the original software. If you use this software in
53 a product, an acknowledgment in the product documentation would be
54 appreciated but is not required.
55
56 2. Altered source versions must be plainly marked as such, and must not be
57 misrepresented as being the original software.
58
59 3. This notice may not be removed or altered from any source distribution.
60 ----------------------------------------------------------------------------*)
61
62 {$i STD.INC}
63
64 interface
65
66
67 uses
68 BTypes, AES_Type, AES_Base, AES_Encr, AES_Decr;
69
70 {$ifdef CONST}
71
AES_CBC_Init_Encrnull72 function AES_CBC_Init_Encr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
73 {-AES key expansion, error if invalid key size, encrypt IV}
74 {$ifdef DLL} stdcall; {$endif}
75
AES_CBC_Init_Decrnull76 function AES_CBC_Init_Decr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
77 {-AES key expansion, error if invalid key size, encrypt IV}
78 {$ifdef DLL} stdcall; {$endif}
79
80 {$else}
81
AES_CBC_Init_Encrnull82 function AES_CBC_Init_Encr(var Key; KeyBits: word; var IV: TAESBlock; var ctx: TAESContext): integer;
83 {-AES key expansion, error if invalid key size, encrypt IV}
84
AES_CBC_Init_Decrnull85 function AES_CBC_Init_Decr(var Key; KeyBits: word; var IV: TAESBlock; var ctx: TAESContext): integer;
86 {-AES key expansion, error if invalid key size, encrypt IV}
87
88 {$endif}
89
90
AES_CBC_Encryptnull91 function AES_CBC_Encrypt(ptp, ctp: Pointer; ILen: longint; var ctx: TAESContext): integer;
92 {-Encrypt ILen bytes from ptp^ to ctp^ in CBC mode}
93 {$ifdef DLL} stdcall; {$endif}
94
AES_CBC_Decryptnull95 function AES_CBC_Decrypt(ctp, ptp: Pointer; ILen: longint; var ctx: TAESContext): integer;
96 {-Decrypt ILen bytes from ctp^ to ptp^ in CBC mode}
97 {$ifdef DLL} stdcall; {$endif}
98
99
100 implementation
101
102
103 {---------------------------------------------------------------------------}
104 {$ifdef CONST}
AES_CBC_Init_Encrnull105 function AES_CBC_Init_Encr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
106 {$else}
AES_CBC_Init_Encrnull107 function AES_CBC_Init_Encr(var Key; KeyBits: word; var IV: TAESBlock; var ctx: TAESContext): integer;
108 {$endif}
109 {-AES key expansion, error if invalid key size, encrypt IV}
110 begin
111 {-AES key expansion, error if invalid key size}
112 AES_CBC_Init_Encr := AES_Init_Encr(Key, KeyBits, ctx);
113 ctx.IV := IV;
114 end;
115
116
117 {---------------------------------------------------------------------------}
118 {$ifdef CONST}
AES_CBC_Init_Decrnull119 function AES_CBC_Init_Decr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
120 {$else}
AES_CBC_Init_Decrnull121 function AES_CBC_Init_Decr(var Key; KeyBits: word; var IV: TAESBlock; var ctx: TAESContext): integer;
122 {$endif}
123 {-AES key expansion, error if invalid key size, encrypt IV}
124 begin
125 {-AES key expansion, error if invalid key size}
126 AES_CBC_Init_Decr := AES_Init_Decr(Key, KeyBits, ctx);
127 ctx.IV := IV;
128 end;
129
130
131 {---------------------------------------------------------------------------}
AES_CBC_Encryptnull132 function AES_CBC_Encrypt(ptp, ctp: Pointer; ILen: longint; var ctx: TAESContext): integer;
133 {-Encrypt ILen bytes from ptp^ to ctp^ in CBC mode}
134 var
135 i,n: longint;
136 m: word;
137 begin
138
139 AES_CBC_Encrypt := 0;
140 if ILen<0 then ILen := 0;
141
142 if ctx.Decrypt<>0 then begin
143 AES_CBC_Encrypt := AES_Err_Invalid_Mode;
144 exit;
145 end;
146
147 if (ptp=nil) or (ctp=nil) then begin
148 if ILen>0 then begin
149 AES_CBC_Encrypt := AES_Err_NIL_Pointer;
150 exit;
151 end;
152 end;
153
154 {$ifdef BIT16}
155 if (ofs(ptp^)+ILen>$FFFF) or (ofs(ctp^)+ILen>$FFFF) then begin
156 AES_CBC_Encrypt := AES_Err_Invalid_16Bit_Length;
157 exit;
158 end;
159 {$endif}
160
161 n := ILen div AESBLKSIZE; {Full blocks}
162 m := ILen mod AESBLKSIZE; {Remaining bytes in short block}
163 if m<>0 then begin
164 if n=0 then begin
165 AES_CBC_Encrypt := AES_Err_Invalid_Length;
166 exit;
167 end;
168 dec(n); {CTS: special treatment of last TWO blocks}
169 end;
170
171 {Short block must be last, no more processing allowed}
172 if ctx.Flag and 1 <> 0 then begin
173 AES_CBC_Encrypt := AES_Err_Data_After_Short_Block;
174 exit;
175 end;
176
177 with ctx do begin
178 for i:=1 to n do begin
179 {ct[i] = encr(ct[i-1] xor pt[i]), cf. [3] 6.2}
180 AES_XorBlock(PAESBlock(ptp)^, IV, IV);
181 AES_Encrypt(ctx, IV, IV);
182 PAESBlock(ctp)^ := IV;
183 inc(Ptr2Inc(ptp),AESBLKSIZE);
184 inc(Ptr2Inc(ctp),AESBLKSIZE);
185 end;
186 if m<>0 then begin
187 {Cipher text stealing}
188 AES_XorBlock(PAESBlock(ptp)^, IV, IV);
189 AES_Encrypt(ctx, IV, IV);
190 buf := IV;
191 inc(Ptr2Inc(ptp),AESBLKSIZE);
192 for i:=0 to m-1 do IV[i] := IV[i] xor PAESBlock(ptp)^[i];
193 AES_Encrypt(ctx, IV, PAESBlock(ctp)^);
194 inc(Ptr2Inc(ctp),AESBLKSIZE);
195 move(buf,PAESBlock(ctp)^,m);
196 {Set short block flag}
197 Flag := Flag or 1;
198 end;
199 end;
200 end;
201
202
203 {---------------------------------------------------------------------------}
AES_CBC_Decryptnull204 function AES_CBC_Decrypt(ctp, ptp: Pointer; ILen: longint; var ctx: TAESContext): integer;
205 {-Decrypt ILen bytes from ctp^ to ptp^ in CBC mode}
206 var
207 i,n: longint;
208 m: word;
209 tmp: TAESBlock;
210 begin
211
212 AES_CBC_Decrypt := 0;
213 if ILen<0 then ILen := 0;
214
215 if ctx.Decrypt=0 then begin
216 AES_CBC_Decrypt := AES_Err_Invalid_Mode;
217 exit;
218 end;
219
220 if (ptp=nil) or (ctp=nil) then begin
221 if ILen>0 then begin
222 AES_CBC_Decrypt := AES_Err_NIL_Pointer;
223 exit;
224 end;
225 end;
226
227 {$ifdef BIT16}
228 if (ofs(ptp^)+ILen>$FFFF) or (ofs(ctp^)+ILen>$FFFF) then begin
229 AES_CBC_Decrypt := AES_Err_Invalid_16Bit_Length;
230 exit;
231 end;
232 {$endif}
233
234 n := ILen div AESBLKSIZE; {Full blocks}
235 m := ILen mod AESBLKSIZE; {Remaining bytes in short block}
236 if m<>0 then begin
237 if n=0 then begin
238 AES_CBC_Decrypt := AES_Err_Invalid_Length;
239 exit;
240 end;
241 dec(n); {CTS: special treatment of last TWO blocks}
242 end;
243
244 {Short block must be last, no more processing allowed}
245 if ctx.Flag and 1 <> 0 then begin
246 AES_CBC_Decrypt := AES_Err_Data_After_Short_Block;
247 exit;
248 end;
249
250 with ctx do begin
251 for i:=1 to n do begin
252 {pt[i] = decr(ct[i]) xor ct[i-1]), cf. [3] 6.2}
253 buf := IV;
254 IV := PAESBlock(ctp)^;
255 AES_Decrypt(ctx, IV, PAESBlock(ptp)^);
256 AES_XorBlock(PAESBlock(ptp)^, buf, PAESBlock(ptp)^);
257 inc(Ptr2Inc(ptp),AESBLKSIZE);
258 inc(Ptr2Inc(ctp),AESBLKSIZE);
259 end;
260 if m<>0 then begin
261 {Cipher text stealing, L=ILen (Schneier's n)}
262 buf := IV; {C(L-2)}
263 AES_Decrypt(ctx, PAESBlock(ctp)^, IV);
264 inc(Ptr2Inc(ctp),AESBLKSIZE);
265 fillchar(tmp,sizeof(tmp),0);
266 move(PAESBlock(ctp)^,tmp,m); {c[L]|0}
267 AES_XorBlock(tmp,IV,IV);
268 tmp := IV;
269 move(PAESBlock(ctp)^,tmp,m); {c[L]| C'}
270 AES_Decrypt(ctx,tmp,tmp);
271 AES_XorBlock(tmp, buf, PAESBlock(ptp)^);
272 inc(Ptr2Inc(ptp),AESBLKSIZE);
273 move(IV,PAESBlock(ptp)^,m);
274 {Set short block flag}
275 Flag := Flag or 1;
276 end;
277 end;
278 end;
279
280 end.
281