source: rtems-libbsd/ipsec-tools/src/racoon/missing/crypto/rijndael/rijndael-api-fst.c @ b376ae1

55-freebsd-126-freebsd-12
Last change on this file since b376ae1 was b376ae1, checked in by Christian Mauderer <christian.mauderer@…>, on 05/03/18 at 12:15:11

ipsec-tools: Port libipsec, setkey and racoon.

Note that this replaces the libipsec from FreeBSD with the one provided
by ipsec-tools.

  • Property mode set to 100644
File size: 13.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $NetBSD: rijndael-api-fst.c,v 1.4 2006/09/09 16:22:36 manu Exp $        */
4
5/*      $KAME: rijndael-api-fst.c,v 1.8 2002/11/18 23:32:54 itojun Exp $        */
6
7/*
8 * rijndael-api-fst.c   v2.3   April '2000
9 *
10 * Optimised ANSI C code
11 *
12 * authors: v1.0: Antoon Bosselaers
13 *          v2.0: Vincent Rijmen
14 *          v2.1: Vincent Rijmen
15 *          v2.2: Vincent Rijmen
16 *          v2.3: Paulo Barreto
17 *          v2.4: Vincent Rijmen
18 *
19 * This code is placed in the public domain.
20 */
21
22#include "config.h"
23
24#include <sys/param.h>
25#include <sys/types.h>
26#ifdef _KERNEL
27#include <sys/time.h>
28#include <sys/systm.h>
29#else
30#include <string.h>
31#endif
32#include <crypto/rijndael/rijndael-alg-fst.h>
33#include <crypto/rijndael/rijndael-api-fst.h>
34#include <crypto/rijndael/rijndael_local.h>
35
36#include <err.h>
37#define bcopy(a, b, c) memcpy(b, a, c)
38#define bzero(a, b) memset(a, 0, b)
39#define panic(a) err(1, (a))
40
41int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
42        word8 k[MAXKC][4];
43        int i;
44        char *keyMat;
45       
46        if (key == NULL) {
47                return BAD_KEY_INSTANCE;
48        }
49
50        if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
51                key->direction = direction;
52        } else {
53                return BAD_KEY_DIR;
54        }
55
56        if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
57                key->keyLen = keyLen;
58        } else {
59                return BAD_KEY_MAT;
60        }
61
62        if (keyMaterial != NULL) {
63                bcopy(keyMaterial, key->keyMaterial, keyLen/8);
64        }
65
66        key->ROUNDS = keyLen/32 + 6;
67
68        /* initialize key schedule: */
69        keyMat = key->keyMaterial;
70        for (i = 0; i < key->keyLen/8; i++) {
71                k[i >> 2][i & 3] = (word8)keyMat[i];
72        }
73        rijndaelKeySched(k, key->keySched, key->ROUNDS);
74        if (direction == DIR_DECRYPT) {
75                rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
76        }
77
78        return TRUE;
79}
80
81int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
82        if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
83                cipher->mode = mode;
84        } else {
85                return BAD_CIPHER_MODE;
86        }
87        if (IV != NULL) {
88                bcopy(IV, cipher->IV, MAX_IV_SIZE);
89        } else {
90                bzero(cipher->IV, MAX_IV_SIZE);
91        }
92        return TRUE;
93}
94
95int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
96                BYTE *input, int inputLen, BYTE *outBuffer) {
97        int i, k, numBlocks;
98        word8 block[16], iv[4][4];
99
100        if (cipher == NULL ||
101                key == NULL ||
102                key->direction == DIR_DECRYPT) {
103                return BAD_CIPHER_STATE;
104        }
105        if (input == NULL || inputLen <= 0) {
106                return 0; /* nothing to do */
107        }
108
109        numBlocks = inputLen/128;
110       
111        switch (cipher->mode) {
112        case MODE_ECB:
113                for (i = numBlocks; i > 0; i--) {
114                        rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
115                        input += 16;
116                        outBuffer += 16;
117                }
118                break;
119               
120        case MODE_CBC:
121#if 1 /*STRICT_ALIGN*/
122                bcopy(cipher->IV, block, 16);
123                bcopy(input, iv, 16);
124                ((word32*)block)[0] ^= ((word32*)iv)[0];
125                ((word32*)block)[1] ^= ((word32*)iv)[1];
126                ((word32*)block)[2] ^= ((word32*)iv)[2];
127                ((word32*)block)[3] ^= ((word32*)iv)[3];
128#else
129                ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
130                ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
131                ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
132                ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
133#endif
134                rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
135                input += 16;
136                for (i = numBlocks - 1; i > 0; i--) {
137#if 1 /*STRICT_ALIGN*/
138                        bcopy(outBuffer, block, 16);
139                        bcopy(input, iv, 16);
140                        ((word32*)block)[0] ^= ((word32*)iv)[0];
141                        ((word32*)block)[1] ^= ((word32*)iv)[1];
142                        ((word32*)block)[2] ^= ((word32*)iv)[2];
143                        ((word32*)block)[3] ^= ((word32*)iv)[3];
144#else
145                        ((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
146                        ((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
147                        ((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
148                        ((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
149#endif
150                        outBuffer += 16;
151                        rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
152                        input += 16;
153                }
154                break;
155       
156        case MODE_CFB1:
157#if 1 /*STRICT_ALIGN*/
158                bcopy(cipher->IV, iv, 16);
159#else  /* !STRICT_ALIGN */
160                *((word32*)iv[0]) = *((word32*)(cipher->IV   ));
161                *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
162                *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
163                *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
164#endif /* ?STRICT_ALIGN */
165                for (i = numBlocks; i > 0; i--) {
166                        for (k = 0; k < 128; k++) {
167                                *((word32*) block    ) = *((word32*)iv[0]);
168                                *((word32*)(block+ 4)) = *((word32*)iv[1]);
169                                *((word32*)(block+ 8)) = *((word32*)iv[2]);
170                                *((word32*)(block+12)) = *((word32*)iv[3]);
171                                rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
172                                outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
173                                iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
174                                iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
175                                iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
176                                iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
177                                iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
178                                iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
179                                iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
180                                iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
181                                iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
182                                iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
183                                iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
184                                iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
185                                iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
186                                iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
187                                iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
188                                iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
189                        }
190                }
191                break;
192       
193        default:
194                return BAD_CIPHER_STATE;
195        }
196       
197        return 128*numBlocks;
198}
199
200/**
201 * Encrypt data partitioned in octets, using RFC 2040-like padding.
202 *
203 * @param   input           data to be encrypted (octet sequence)
204 * @param   inputOctets         input length in octets (not bits)
205 * @param   outBuffer       encrypted output data
206 *
207 * @return      length in octets (not bits) of the encrypted output buffer.
208 */
209int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
210                BYTE *input, int inputOctets, BYTE *outBuffer) {
211        int i, numBlocks, padLen;
212        word8 block[16], *iv, *cp;
213
214        if (cipher == NULL ||
215                key == NULL ||
216                key->direction == DIR_DECRYPT) {
217                return BAD_CIPHER_STATE;
218        }
219        if (input == NULL || inputOctets <= 0) {
220                return 0; /* nothing to do */
221        }
222
223        numBlocks = inputOctets/16;
224
225        switch (cipher->mode) {
226        case MODE_ECB:
227                for (i = numBlocks; i > 0; i--) {
228                        rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
229                        input += 16;
230                        outBuffer += 16;
231                }
232                padLen = 16 - (inputOctets - 16*numBlocks);
233                if (padLen <= 0 || padLen > 16)
234                        panic("rijndael_padEncrypt(ECB)");
235                bcopy(input, block, 16 - padLen);
236                for (cp = block + 16 - padLen; cp < block + 16; cp++)
237                        *cp = padLen;
238                rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
239                break;
240
241        case MODE_CBC:
242                iv = cipher->IV;
243                for (i = numBlocks; i > 0; i--) {
244                        ((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0];
245                        ((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1];
246                        ((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2];
247                        ((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3];
248                        rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
249                        iv = outBuffer;
250                        input += 16;
251                        outBuffer += 16;
252                }
253                padLen = 16 - (inputOctets - 16*numBlocks);
254                if (padLen <= 0 || padLen > 16)
255                        panic("rijndael_padEncrypt(CBC)");
256                for (i = 0; i < 16 - padLen; i++) {
257                        block[i] = input[i] ^ iv[i];
258                }
259                for (i = 16 - padLen; i < 16; i++) {
260                        block[i] = (BYTE)padLen ^ iv[i];
261                }
262                rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
263                break;
264
265        default:
266                return BAD_CIPHER_STATE;
267        }
268
269        return 16*(numBlocks + 1);
270}
271
272int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
273                BYTE *input, int inputLen, BYTE *outBuffer) {
274        int i, k, numBlocks;
275        word8 block[16], iv[4][4];
276
277        if (cipher == NULL ||
278                key == NULL ||
279                (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
280                return BAD_CIPHER_STATE;
281        }
282        if (input == NULL || inputLen <= 0) {
283                return 0; /* nothing to do */
284        }
285
286        numBlocks = inputLen/128;
287
288        switch (cipher->mode) {
289        case MODE_ECB:
290                for (i = numBlocks; i > 0; i--) {
291                        rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
292                        input += 16;
293                        outBuffer += 16;
294                }
295                break;
296               
297        case MODE_CBC:
298#if 1 /*STRICT_ALIGN */
299                bcopy(cipher->IV, iv, 16);
300#else
301                *((word32*)iv[0]) = *((word32*)(cipher->IV   ));
302                *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
303                *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
304                *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
305#endif
306                for (i = numBlocks; i > 0; i--) {
307                        rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
308                        ((word32*)block)[0] ^= *((word32*)iv[0]);
309                        ((word32*)block)[1] ^= *((word32*)iv[1]);
310                        ((word32*)block)[2] ^= *((word32*)iv[2]);
311                        ((word32*)block)[3] ^= *((word32*)iv[3]);
312#if 1 /*STRICT_ALIGN*/
313                        bcopy(input, iv, 16);
314                        bcopy(block, outBuffer, 16);
315#else
316                        *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
317                        *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
318                        *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
319                        *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
320#endif
321                        input += 16;
322                        outBuffer += 16;
323                }
324                break;
325       
326        case MODE_CFB1:
327#if 1 /*STRICT_ALIGN */
328                bcopy(cipher->IV, iv, 16);
329#else
330                *((word32*)iv[0]) = *((word32*)(cipher->IV));
331                *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
332                *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
333                *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
334#endif
335                for (i = numBlocks; i > 0; i--) {
336                        for (k = 0; k < 128; k++) {
337                                *((word32*) block    ) = *((word32*)iv[0]);
338                                *((word32*)(block+ 4)) = *((word32*)iv[1]);
339                                *((word32*)(block+ 8)) = *((word32*)iv[2]);
340                                *((word32*)(block+12)) = *((word32*)iv[3]);
341                                rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
342                                iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
343                                iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
344                                iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
345                                iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
346                                iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
347                                iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
348                                iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
349                                iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
350                                iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
351                                iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
352                                iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
353                                iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
354                                iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
355                                iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
356                                iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
357                                iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
358                                outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
359                        }
360                }
361                break;
362
363        default:
364                return BAD_CIPHER_STATE;
365        }
366       
367        return 128*numBlocks;
368}
369
370int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
371                BYTE *input, int inputOctets, BYTE *outBuffer) {
372        int i, numBlocks, padLen;
373        word8 block[16];
374        word32 iv[4];
375
376        if (cipher == NULL ||
377                key == NULL ||
378                key->direction == DIR_ENCRYPT) {
379                return BAD_CIPHER_STATE;
380        }
381        if (input == NULL || inputOctets <= 0) {
382                return 0; /* nothing to do */
383        }
384        if (inputOctets % 16 != 0) {
385                return BAD_DATA;
386        }
387
388        numBlocks = inputOctets/16;
389
390        switch (cipher->mode) {
391        case MODE_ECB:
392                /* all blocks but last */
393                for (i = numBlocks - 1; i > 0; i--) {
394                        rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
395                        input += 16;
396                        outBuffer += 16;
397                }
398                /* last block */
399                rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
400                padLen = block[15];
401                if (padLen >= 16) {
402                        return BAD_DATA;
403                }
404                for (i = 16 - padLen; i < 16; i++) {
405                        if (block[i] != padLen) {
406                                return BAD_DATA;
407                        }
408                }
409                bcopy(block, outBuffer, 16 - padLen);
410                break;
411               
412        case MODE_CBC:
413                bcopy(cipher->IV, iv, 16);
414                /* all blocks but last */
415                for (i = numBlocks - 1; i > 0; i--) {
416                        rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
417                        ((word32*)block)[0] ^= iv[0];
418                        ((word32*)block)[1] ^= iv[1];
419                        ((word32*)block)[2] ^= iv[2];
420                        ((word32*)block)[3] ^= iv[3];
421                        bcopy(input, iv, 16);
422                        bcopy(block, outBuffer, 16);
423                        input += 16;
424                        outBuffer += 16;
425                }
426                /* last block */
427                rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
428                ((word32*)block)[0] ^= iv[0];
429                ((word32*)block)[1] ^= iv[1];
430                ((word32*)block)[2] ^= iv[2];
431                ((word32*)block)[3] ^= iv[3];
432                padLen = block[15];
433                if (padLen <= 0 || padLen > 16) {
434                        return BAD_DATA;
435                }
436                for (i = 16 - padLen; i < 16; i++) {
437                        if (block[i] != padLen) {
438                                return BAD_DATA;
439                        }
440                }
441                bcopy(block, outBuffer, 16 - padLen);
442                break;
443       
444        default:
445                return BAD_CIPHER_STATE;
446        }
447       
448        return 16*numBlocks - padLen;
449}
450
451#ifdef INTERMEDIATE_VALUE_KAT
452/**
453 *      cipherUpdateRounds:
454 *
455 *      Encrypts/Decrypts exactly one full block a specified number of rounds.
456 *      Only used in the Intermediate Value Known Answer Test. 
457 *
458 *      Returns:
459 *              TRUE - on success
460 *              BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
461 */
462int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
463                BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
464        int j;
465        word8 block[4][4];
466
467        if (cipher == NULL || key == NULL) {
468                return BAD_CIPHER_STATE;
469        }
470
471        for (j = 3; j >= 0; j--) {
472                /* parse input stream into rectangular array */
473                *((word32*)block[j]) = *((word32*)(input+4*j));
474        }
475
476        switch (key->direction) {
477        case DIR_ENCRYPT:
478                rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
479                break;
480               
481        case DIR_DECRYPT:
482                rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
483                break;
484               
485        default:
486                return BAD_KEY_DIR;
487        }
488
489        for (j = 3; j >= 0; j--) {
490                /* parse rectangular array into output ciphertext bytes */
491                *((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
492        }
493       
494        return TRUE;
495}
496#endif /* INTERMEDIATE_VALUE_KAT */
Note: See TracBrowser for help on using the repository browser.