xref: /minix3/minix/drivers/system/random/aes/rijndael_api.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /*	rijndael-api.c - Rijndael encryption programming interface.
2  *							Author: Kees J. Bot
3  *								3 Nov 2000
4  * Heavily based on the original API code by Antoon Bosselaers,
5  * Vincent Rijmen, and Paulo Barreto, but with a different interface.
6  *
7  * Read this code top to bottom, not all comments are repeated.
8  */
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 
14 #include "rijndael-alg.h"
15 #include "rijndael-api.h"
16 
17 /* Map a byte (?) address to a word address or vv. */
18 #define W(a)	((word32 *) (a))
19 #define B(a)	((word8 *) (a))
20 
21 #if STRICT_ALIGN
22 /* This machine checks alignment religiously.  (The code is not proper with
23  * respect to alignment.  We need a compiler that doesn't muck about with byte
24  * arrays that follow words in structs, and that places automatic variables
25  * at word boundaries if not odd-sized.  Most compilers are this nice.)
26  */
27 
28 #define aligned(a)		(((unsigned) (a) & 3) == 0)
29 #define aligned2(a1, a2)	aligned((unsigned) (a1) | (unsigned) (a2))
30 
blockcpy(void * dst,const void * src)31 static void blockcpy(void *dst, const void *src)
32 {
33     int i= 0;
34 
35     do {
36 	B(dst)[i+0] = B(src)[i+0];
37 	B(dst)[i+1] = B(src)[i+1];
38 	B(dst)[i+2] = B(src)[i+2];
39 	B(dst)[i+3] = B(src)[i+3];
40     } while ((i += 4) < 16);
41 }
42 
43 #else /* !STRICT_ALIGN */
44 /* This machine doesn't mind misaligned accesses much. */
45 
46 #define aligned(a)		((void) (a), 1)
47 #define aligned2(a1, a2)	((void) (a1), (void) (a2), 1)
48 
49 #if __GNUC__
50 __inline
51 #endif
blockcpy(void * dst,const void * src)52 static void blockcpy(void *dst, const void *src)
53 {
54     W(dst)[0] = W(src)[0];
55     W(dst)[1] = W(src)[1];
56     W(dst)[2] = W(src)[2];
57     W(dst)[3] = W(src)[3];
58 }
59 
60 #endif /* !STRICT_ALIGN */
61 
62 #define between(a, c, z)	((unsigned) (c) - (a) <= (unsigned) (z) - (a))
63 
rijndael_makekey(rd_keyinstance * key,size_t keylen,const void * keymaterial)64 int rijndael_makekey(rd_keyinstance *key,
65 	size_t keylen, const void *keymaterial)
66 {
67     word8 k[MAXKC][4];
68 
69     /* Initialize key schedule: */
70     if (keylen == RD_KEY_HEX) {
71 	const word8 *kp;
72 	int c, b;
73 
74 	kp= keymaterial;
75 	keylen= 0;
76 
77 	for (;;) {
78 	    c= *kp++;
79 	    if (between('0', c, '9')) b= (c - '0' + 0x0) << 4;
80 	    else
81 	    if (between('a', c, 'f')) b= (c - 'a' + 0xa) << 4;
82 	    else
83 	    if (between('A', c, 'F')) b= (c - 'A' + 0xA) << 4;
84 	    else break;
85 
86 	    c= *kp++;
87 	    if (between('0', c, '9')) b |= (c - '0' + 0x0);
88 	    else
89 	    if (between('a', c, 'f')) b |= (c - 'a' + 0xa);
90 	    else
91 	    if (between('A', c, 'F')) b |= (c - 'A' + 0xA);
92 	    else break;
93 
94 	    if (keylen >= 256/8) return RD_BAD_KEY_MAT;
95 	    k[keylen/4][keylen%4] = b;
96 	    keylen++;
97 	}
98 	if (c != 0) return RD_BAD_KEY_MAT;
99 
100 	if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
101 	    return RD_BAD_KEY_MAT;
102 	}
103     } else {
104 	if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
105 	    return RD_BAD_KEY_MAT;
106 	}
107 	memcpy(k, keymaterial, keylen);
108     }
109 
110     key->rounds= keylen * 8 / 32 + 6;
111 
112     rijndael_KeySched(k, key->encsched, key->rounds);
113     memcpy(key->decsched, key->encsched, sizeof(key->decsched));
114     rijndael_KeyEncToDec(key->decsched, key->rounds);
115 
116     return 0;
117 }
118 
rijndael_ecb_encrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * dummyIV)119 ssize_t rijndael_ecb_encrypt(rd_keyinstance *key,
120 	const void *input, void *output, size_t length, void *dummyIV)
121 {
122     /* Encrypt blocks of data in Electronic Codebook mode. */
123     const word8 *inp= input;
124     word8 *outp= output;
125     size_t i, nr_blocks, extra;
126     word32 in[4], out[4];
127     word8 t;
128 
129     /* Compute the number of whole blocks, and the extra bytes beyond the
130      * last block.  Those extra bytes, if any, are encrypted by stealing
131      * enough bytes from the previous encrypted block to make a whole block.
132      * This is done by encrypting the last block, exchanging the first few
133      * encrypted bytes with the extra bytes, and encrypting the last whole
134      * block again.
135      */
136     nr_blocks= length / 16;
137     if ((extra= (length % 16)) > 0) {
138 	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
139 	nr_blocks--;
140     }
141 
142     /* Encrypt a number of blocks. */
143     if (aligned2(inp, outp)) {
144 	for (i= 0; i < nr_blocks; i++) {
145 	    rijndael_Encrypt(inp, outp, key->encsched, key->rounds);
146 	    inp += 16;
147 	    outp += 16;
148 	}
149     } else {
150 	for (i= 0; i < nr_blocks; i++) {
151 	    blockcpy(in, inp);
152 	    rijndael_Encrypt(in, out, key->encsched, key->rounds);
153 	    blockcpy(outp, out);
154 	    inp += 16;
155 	    outp += 16;
156 	}
157     }
158 
159     /* Encrypt extra bytes by stealing from the last full block. */
160     if (extra > 0) {
161 	blockcpy(in, inp);
162 	rijndael_Encrypt(in, out, key->encsched, key->rounds);
163 	for (i= 0; i < extra; i++) {
164 	    t= B(out)[i];
165 	    B(out)[i] = inp[16 + i];
166 	    outp[16 + i] = t;
167 	}
168 	rijndael_Encrypt(out, out, key->encsched, key->rounds);
169 	blockcpy(outp, out);
170     }
171     return length;
172 }
173 
rijndael_ecb_decrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * dummyIV)174 ssize_t rijndael_ecb_decrypt(rd_keyinstance *key,
175 	const void *input, void *output, size_t length, void *dummyIV)
176 {
177     /* Decrypt blocks of data in Electronic Codebook mode. */
178     const word8 *inp= input;
179     word8 *outp= output;
180     size_t i, nr_blocks, extra;
181     word32 in[4], out[4];
182     word8 t;
183 
184     nr_blocks= length / 16;
185     if ((extra= (length % 16)) > 0) {
186 	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
187 	nr_blocks--;
188     }
189 
190     /* Decrypt a number of blocks. */
191     if (aligned2(inp, outp)) {
192 	for (i= 0; i < nr_blocks; i++) {
193 	    rijndael_Decrypt(inp, outp, key->decsched, key->rounds);
194 	    inp += 16;
195 	    outp += 16;
196 	}
197     } else {
198 	for (i= 0; i < nr_blocks; i++) {
199 	    blockcpy(in, inp);
200 	    rijndael_Decrypt(in, out, key->decsched, key->rounds);
201 	    blockcpy(outp, out);
202 	    inp += 16;
203 	    outp += 16;
204 	}
205     }
206 
207     /* Decrypt extra bytes that stole from the last full block. */
208     if (extra > 0) {
209 	blockcpy(in, inp);
210 	rijndael_Decrypt(in, out, key->decsched, key->rounds);
211 	for (i= 0; i < extra; i++) {
212 	    t= B(out)[i];
213 	    B(out)[i] = inp[16 + i];
214 	    outp[16 + i] = t;
215 	}
216 	rijndael_Decrypt(out, out, key->decsched, key->rounds);
217 	blockcpy(outp, out);
218     }
219     return length;
220 }
221 
rijndael_cbc_encrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)222 ssize_t rijndael_cbc_encrypt(rd_keyinstance *key,
223 	const void *input, void *output, size_t length, void *IV)
224 {
225     /* Encrypt blocks of data in Cypher Block Chaining mode. */
226     const word8 *inp= input;
227     word8 *outp= output;
228     size_t i, nr_blocks, extra;
229     word32 in[4], out[4], iv[4], *ivp;
230     word8 t;
231 
232     nr_blocks= length / 16;
233     if ((extra= (length % 16)) > 0) {
234 	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
235 	nr_blocks--;
236     }
237 
238     /* Each input block is first XORed with the previous encryption result.
239      * The "Initialization Vector" is used to XOR the first block with.
240      * When done the last crypted block is stored back as the new IV to be
241      * used for another call to this function.
242      */
243     ivp= aligned(IV) ? IV : (blockcpy(iv, IV), iv);
244 
245     if (aligned2(inp, outp)) {
246 	for (i= 0; i < nr_blocks; i++) {
247 	    in[0] = W(inp)[0] ^ ivp[0];
248 	    in[1] = W(inp)[1] ^ ivp[1];
249 	    in[2] = W(inp)[2] ^ ivp[2];
250 	    in[3] = W(inp)[3] ^ ivp[3];
251 	    rijndael_Encrypt(in, outp, key->encsched, key->rounds);
252 	    ivp= W(outp);
253 	    inp += 16;
254 	    outp += 16;
255 	}
256     } else {
257 	for (i= 0; i < nr_blocks; i++) {
258 	    blockcpy(in, inp);
259 	    in[0] ^= ivp[0];
260 	    in[1] ^= ivp[1];
261 	    in[2] ^= ivp[2];
262 	    in[3] ^= ivp[3];
263 	    rijndael_Encrypt(in, out, key->encsched, key->rounds);
264 	    blockcpy(outp, out);
265 	    ivp= out;
266 	    inp += 16;
267 	    outp += 16;
268 	}
269     }
270     if (extra > 0) {
271 	blockcpy(in, inp);
272 	in[0] ^= ivp[0];
273 	in[1] ^= ivp[1];
274 	in[2] ^= ivp[2];
275 	in[3] ^= ivp[3];
276 	rijndael_Encrypt(in, out, key->encsched, key->rounds);
277 	for (i= 0; i < extra; i++) {
278 	    t= B(out)[i];
279 	    B(out)[i] ^= inp[16 + i];
280 	    outp[16 + i] = t;
281 	}
282 	rijndael_Encrypt(out, out, key->encsched, key->rounds);
283 	blockcpy(outp, out);
284 	ivp= out;
285     }
286     blockcpy(IV, ivp);		/* Store last IV back. */
287     return length;
288 }
289 
rijndael_cbc_decrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)290 ssize_t rijndael_cbc_decrypt(rd_keyinstance *key,
291 	const void *input, void *output, size_t length, void *IV)
292 {
293     /* Decrypt blocks of data in Cypher Block Chaining mode. */
294     const word8 *inp= input;
295     word8 *outp= output;
296     size_t i, nr_blocks, extra;
297     word32 in[4], out[4], iv[4];
298     word8 t;
299 
300     nr_blocks= length / 16;
301     if ((extra= (length % 16)) > 0) {
302 	if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
303 	nr_blocks--;
304     }
305 
306     blockcpy(iv, IV);
307 
308     if (aligned2(inp, outp)) {
309 	for (i= 0; i < nr_blocks; i++) {
310 	    rijndael_Decrypt(inp, out, key->decsched, key->rounds);
311 	    out[0] ^= iv[0];
312 	    out[1] ^= iv[1];
313 	    out[2] ^= iv[2];
314 	    out[3] ^= iv[3];
315 	    iv[0] = W(inp)[0];
316 	    iv[1] = W(inp)[1];
317 	    iv[2] = W(inp)[2];
318 	    iv[3] = W(inp)[3];
319 	    W(outp)[0] = out[0];
320 	    W(outp)[1] = out[1];
321 	    W(outp)[2] = out[2];
322 	    W(outp)[3] = out[3];
323 	    inp += 16;
324 	    outp += 16;
325 	}
326     } else {
327 	for (i= 0; i < nr_blocks; i++) {
328 	    blockcpy(in, inp);
329 	    rijndael_Decrypt(in, out, key->decsched, key->rounds);
330 	    out[0] ^= iv[0];
331 	    out[1] ^= iv[1];
332 	    out[2] ^= iv[2];
333 	    out[3] ^= iv[3];
334 	    iv[0] = in[0];
335 	    iv[1] = in[1];
336 	    iv[2] = in[2];
337 	    iv[3] = in[3];
338 	    blockcpy(outp, out);
339 	    inp += 16;
340 	    outp += 16;
341 	}
342     }
343     if (extra > 0) {
344 	blockcpy(in, inp);
345 	blockcpy(IV, in);
346 	rijndael_Decrypt(in, out, key->decsched, key->rounds);
347 	for (i= 0; i < extra; i++) {
348 	    t= B(out)[i] ^ inp[16 + i];
349 	    B(out)[i] = inp[16 + i];
350 	    outp[16 + i] = t;
351 	}
352 	rijndael_Decrypt(out, out, key->decsched, key->rounds);
353 	out[0] ^= iv[0];
354 	out[1] ^= iv[1];
355 	out[2] ^= iv[2];
356 	out[3] ^= iv[3];
357 	blockcpy(outp, out);
358     } else {
359 	blockcpy(IV, iv);
360     }
361     return length;
362 }
363 
rijndael_cfb1_encrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)364 ssize_t rijndael_cfb1_encrypt(rd_keyinstance *key,
365 	const void *input, void *output, size_t length, void *IV)
366 {
367     /* Encrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
368     const word8 *inp= input;
369     word8 *outp= output;
370     word8 t;
371     size_t i;
372     int b;
373     word32 iv[4], civ[4];
374 
375     blockcpy(iv, IV);
376 
377     for (i= 0; i < length; i++) {
378 	t= *inp++;
379 	for (b= 0; b < 8; b++) {
380 	    rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
381 	    t ^= (B(civ)[0] & 0x80) >> b;
382 	    B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
383 	    B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
384 	    B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
385 	    B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
386 	    B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
387 	    B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
388 	    B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
389 	    B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
390 	    B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
391 	    B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
392 	    B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
393 	    B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
394 	    B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
395 	    B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
396 	    B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
397 	    B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
398 	}
399 	*outp++ = t;
400     }
401     blockcpy(IV, iv);
402     return length;
403 }
404 
rijndael_cfb1_decrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)405 ssize_t rijndael_cfb1_decrypt(rd_keyinstance *key,
406 	const void *input, void *output, size_t length, void *IV)
407 {
408     /* Decrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
409     const word8 *inp= input;
410     word8 *outp= output;
411     word8 t;
412     size_t i;
413     int b;
414     word32 iv[4], civ[4];
415 
416     blockcpy(iv, IV);
417 
418     for (i= 0; i < length; i++) {
419 	t= *inp++;
420 	for (b= 0; b < 8; b++) {
421 	    rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
422 	    B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
423 	    B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
424 	    B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
425 	    B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
426 	    B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
427 	    B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
428 	    B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
429 	    B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
430 	    B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
431 	    B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
432 	    B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
433 	    B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
434 	    B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
435 	    B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
436 	    B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
437 	    B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
438 	    t ^= (B(civ)[0] & 0x80) >> b;
439 	}
440 	*outp++ = t;
441     }
442     blockcpy(IV, iv);
443     return length;
444 }
445 
rijndael_cfb8_encrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)446 ssize_t rijndael_cfb8_encrypt(rd_keyinstance *key,
447 	const void *input, void *output, size_t length, void *IV)
448 {
449     /* Encrypt blocks of data in Cypher Feedback mode, 8 bits at a time. */
450     const word8 *inp= input;
451     word8 *outp= output;
452     word8 t;
453     size_t i;
454     word32 iv[4], civ[4];
455 
456     blockcpy(iv, IV);
457 
458     for (i= 0; i < length; i++) {
459 	t= *inp++;
460 	rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
461 	t ^= B(civ)[0];
462 	B(iv)[ 0] = B(iv)[ 1];
463 	B(iv)[ 1] = B(iv)[ 2];
464 	B(iv)[ 2] = B(iv)[ 3];
465 	B(iv)[ 3] = B(iv)[ 4];
466 	B(iv)[ 4] = B(iv)[ 5];
467 	B(iv)[ 5] = B(iv)[ 6];
468 	B(iv)[ 6] = B(iv)[ 7];
469 	B(iv)[ 7] = B(iv)[ 8];
470 	B(iv)[ 8] = B(iv)[ 9];
471 	B(iv)[ 9] = B(iv)[10];
472 	B(iv)[10] = B(iv)[11];
473 	B(iv)[11] = B(iv)[12];
474 	B(iv)[12] = B(iv)[13];
475 	B(iv)[13] = B(iv)[14];
476 	B(iv)[14] = B(iv)[15];
477 	B(iv)[15] = t;
478 	*outp++ = t;
479     }
480     blockcpy(IV, iv);
481     return length;
482 }
483 
rijndael_cfb8_decrypt(rd_keyinstance * key,const void * input,void * output,size_t length,void * IV)484 ssize_t rijndael_cfb8_decrypt(rd_keyinstance *key,
485 	const void *input, void *output, size_t length, void *IV)
486 {
487     /* Decrypt blocks of data in Cypher Feedback mode, 1 byte at a time. */
488     const word8 *inp= input;
489     word8 *outp= output;
490     word8 t;
491     size_t i;
492     word32 iv[4], civ[4];
493 
494     blockcpy(iv, IV);
495 
496     for (i= 0; i < length; i++) {
497 	t= *inp++;
498 	rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
499 	B(iv)[ 0] = B(iv)[ 1];
500 	B(iv)[ 1] = B(iv)[ 2];
501 	B(iv)[ 2] = B(iv)[ 3];
502 	B(iv)[ 3] = B(iv)[ 4];
503 	B(iv)[ 4] = B(iv)[ 5];
504 	B(iv)[ 5] = B(iv)[ 6];
505 	B(iv)[ 6] = B(iv)[ 7];
506 	B(iv)[ 7] = B(iv)[ 8];
507 	B(iv)[ 8] = B(iv)[ 9];
508 	B(iv)[ 9] = B(iv)[10];
509 	B(iv)[10] = B(iv)[11];
510 	B(iv)[11] = B(iv)[12];
511 	B(iv)[12] = B(iv)[13];
512 	B(iv)[13] = B(iv)[14];
513 	B(iv)[14] = B(iv)[15];
514 	B(iv)[15] = t;
515 	t ^= B(civ)[0];
516 	*outp++ = t;
517     }
518     blockcpy(IV, iv);
519     return length;
520 }
521 
rijndael_pad(void * input,size_t length)522 ssize_t rijndael_pad(void *input, size_t length)
523 {
524     /* Adds at most one block of RFC-2040 style padding to the input to make
525      * it a whole number of blocks for easier encryption.  To be used if the
526      * input may be less then one block in size, otherwise let the encryption
527      * routines use cypher stealing.  The input buffer should allow enough
528      * space for the padding.  The new length of the input is returned.
529      */
530     word8 *inp= input;
531     size_t padlen;
532 
533     /* Add padding up until the next block boundary. */
534     padlen= 16 - (length % 16);
535     memset(inp + length, padlen, padlen);
536     return length + padlen;
537 }
538 
rijndael_unpad(const void * input,size_t length)539 ssize_t rijndael_unpad(const void *input, size_t length)
540 {
541     /* Remove RFC-2040 style padding after decryption.  The true length of
542      * the input is returned, or the usual errors if the padding is incorrect.
543      */
544     const word8 *inp= input;
545     size_t i, padlen;
546 
547     if (length == 0 || (length % 16) != 0) return RD_BAD_BLOCK_LENGTH;
548     padlen = inp[length-1];
549     if (padlen <= 0 || padlen > 16) return RD_BAD_DATA;
550     for (i= 2; i <= padlen; i++) {
551 	if (inp[length-i] != padlen) return RD_BAD_DATA;
552     }
553     return length - padlen;
554 }
555 
556 #ifdef INTERMEDIATE_VALUE_KAT
557 
cipherEncryptUpdateRounds(rd_keyinstance * key,const void * input,void * output,int rounds)558 void cipherEncryptUpdateRounds(rd_keyinstance *key,
559 	const void *input, void *output, int rounds)
560 {
561     /* Encrypt a block only a specified number of rounds. */
562     word8 block[4][4];
563 
564     blockcpy(block, input);
565 
566     rijndaelEncryptRound(block, key->encsched, key->rounds, rounds);
567 
568     blockcpy(output, block);
569 }
570 
cipherDecryptUpdateRounds(rd_keyinstance * key,const void * input,void * output,int rounds)571 void cipherDecryptUpdateRounds(rd_keyinstance *key,
572 	const void *input, void *output, int rounds)
573 {
574     /* Decrypt a block only a specified number of rounds. */
575     word8 block[4][4];
576 
577     blockcpy(block, input);
578 
579     rijndaelDecryptRound(block, key->decsched, key->rounds, rounds);
580 
581     blockcpy(output, block);
582 }
583 #endif /* INTERMEDIATE_VALUE_KAT */
584 
585 /*
586  * $PchId: rijndael_api.c,v 1.2 2001/01/10 22:01:20 philip Exp $
587  */
588