📄 rijndael_api.c
字号:
/* rijndael-api.c - Rijndael encryption programming interface. * Author: Kees J. Bot * 3 Nov 2000 * Heavily based on the original API code by Antoon Bosselaers, * Vincent Rijmen, and Paulo Barreto, but with a different interface. * * Read this code top to bottom, not all comments are repeated. */#include <stdlib.h>#include <string.h>#include <sys/types.h>#include "rijndael-alg.h"#include "rijndael-api.h"/* Map a byte (?) address to a word address or vv. */#define W(a) ((word32 *) (a))#define B(a) ((word8 *) (a))#if STRICT_ALIGN/* This machine checks alignment religiously. (The code is not proper with * respect to alignment. We need a compiler that doesn't muck about with byte * arrays that follow words in structs, and that places automatic variables * at word boundaries if not odd-sized. Most compilers are this nice.) */#define aligned(a) (((unsigned) (a) & 3) == 0)#define aligned2(a1, a2) aligned((unsigned) (a1) | (unsigned) (a2))static void blockcpy(void *dst, const void *src){ int i= 0; do { B(dst)[i+0] = B(src)[i+0]; B(dst)[i+1] = B(src)[i+1]; B(dst)[i+2] = B(src)[i+2]; B(dst)[i+3] = B(src)[i+3]; } while ((i += 4) < 16);}#else /* !STRICT_ALIGN *//* This machine doesn't mind misaligned accesses much. */#define aligned(a) ((void) (a), 1)#define aligned2(a1, a2) ((void) (a1), (void) (a2), 1)#if __GNUC____inline#endifstatic void blockcpy(void *dst, const void *src){ W(dst)[0] = W(src)[0]; W(dst)[1] = W(src)[1]; W(dst)[2] = W(src)[2]; W(dst)[3] = W(src)[3];}#endif /* !STRICT_ALIGN */#define between(a, c, z) ((unsigned) (c) - (a) <= (unsigned) (z) - (a))int rijndael_makekey(rd_keyinstance *key, size_t keylen, const void *keymaterial){ word8 k[MAXKC][4]; /* Initialize key schedule: */ if (keylen == RD_KEY_HEX) { const word8 *kp; int c, b; kp= keymaterial; keylen= 0; for (;;) { c= *kp++; if (between('0', c, '9')) b= (c - '0' + 0x0) << 4; else if (between('a', c, 'f')) b= (c - 'a' + 0xa) << 4; else if (between('A', c, 'F')) b= (c - 'A' + 0xA) << 4; else break; c= *kp++; if (between('0', c, '9')) b |= (c - '0' + 0x0); else if (between('a', c, 'f')) b |= (c - 'a' + 0xa); else if (between('A', c, 'F')) b |= (c - 'A' + 0xA); else break; if (keylen >= 256/8) return RD_BAD_KEY_MAT; B(k)[keylen++] = b; } if (c != 0) return RD_BAD_KEY_MAT; if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) { return RD_BAD_KEY_MAT; } } else { if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) { return RD_BAD_KEY_MAT; } memcpy(k, keymaterial, keylen); } key->rounds= keylen * 8 / 32 + 6; rijndael_KeySched(k, key->encsched, key->rounds); memcpy(key->decsched, key->encsched, sizeof(key->decsched)); rijndael_KeyEncToDec(key->decsched, key->rounds); return 0;}ssize_t rijndael_ecb_encrypt(rd_keyinstance *key, const void *input, void *output, size_t length, void *dummyIV){ /* Encrypt blocks of data in Electronic Codebook mode. */ const word8 *inp= input; word8 *outp= output; size_t i, nr_blocks, extra; word32 in[4], out[4]; word8 t; /* Compute the number of whole blocks, and the extra bytes beyond the * last block. Those extra bytes, if any, are encrypted by stealing * enough bytes from the previous encrypted block to make a whole block. * This is done by encrypting the last block, exchanging the first few * encrypted bytes with the extra bytes, and encrypting the last whole * block again. */ nr_blocks= length / 16; if ((extra= (length % 16)) > 0) { if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH; nr_blocks--; } /* Encrypt a number of blocks. */ if (aligned2(inp, outp)) { for (i= 0; i < nr_blocks; i++) { rijndael_Encrypt(inp, outp, key->encsched, key->rounds); inp += 16; outp += 16; } } else { for (i= 0; i < nr_blocks; i++) { blockcpy(in, inp); rijndael_Encrypt(in, out, key->encsched, key->rounds); blockcpy(outp, out); inp += 16; outp += 16; } } /* Encrypt extra bytes by stealing from the last full block. */ if (extra > 0) { blockcpy(in, inp); rijndael_Encrypt(in, out, key->encsched, key->rounds); for (i= 0; i < extra; i++) { t= B(out)[i]; B(out)[i] = inp[16 + i]; outp[16 + i] = t; } rijndael_Encrypt(out, out, key->encsched, key->rounds); blockcpy(outp, out); } return length;}ssize_t rijndael_ecb_decrypt(rd_keyinstance *key, const void *input, void *output, size_t length, void *dummyIV){ /* Decrypt blocks of data in Electronic Codebook mode. */ const word8 *inp= input; word8 *outp= output; size_t i, nr_blocks, extra; word32 in[4], out[4]; word8 t; nr_blocks= length / 16; if ((extra= (length % 16)) > 0) { if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH; nr_blocks--; } /* Decrypt a number of blocks. */ if (aligned2(inp, outp)) { for (i= 0; i < nr_blocks; i++) { rijndael_Decrypt(inp, outp, key->decsched, key->rounds); inp += 16; outp += 16; } } else { for (i= 0; i < nr_blocks; i++) { blockcpy(in, inp); rijndael_Decrypt(in, out, key->decsched, key->rounds); blockcpy(outp, out); inp += 16; outp += 16; } } /* Decrypt extra bytes that stole from the last full block. */ if (extra > 0) { blockcpy(in, inp); rijndael_Decrypt(in, out, key->decsched, key->rounds); for (i= 0; i < extra; i++) { t= B(out)[i]; B(out)[i] = inp[16 + i]; outp[16 + i] = t; } rijndael_Decrypt(out, out, key->decsched, key->rounds); blockcpy(outp, out); } return length;}ssize_t rijndael_cbc_encrypt(rd_keyinstance *key, const void *input, void *output, size_t length, void *IV){ /* Encrypt blocks of data in Cypher Block Chaining mode. */ const word8 *inp= input; word8 *outp= output; size_t i, nr_blocks, extra; word32 in[4], out[4], iv[4], *ivp; word8 t; nr_blocks= length / 16; if ((extra= (length % 16)) > 0) { if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH; nr_blocks--; } /* Each input block is first XORed with the previous encryption result. * The "Initialization Vector" is used to XOR the first block with. * When done the last crypted block is stored back as the new IV to be * used for another call to this function. */ ivp= aligned(IV) ? IV : (blockcpy(iv, IV), iv); if (aligned2(inp, outp)) { for (i= 0; i < nr_blocks; i++) { in[0] = W(inp)[0] ^ ivp[0]; in[1] = W(inp)[1] ^ ivp[1]; in[2] = W(inp)[2] ^ ivp[2]; in[3] = W(inp)[3] ^ ivp[3]; rijndael_Encrypt(in, outp, key->encsched, key->rounds); ivp= W(outp); inp += 16; outp += 16; } } else { for (i= 0; i < nr_blocks; i++) { blockcpy(in, inp); in[0] ^= ivp[0]; in[1] ^= ivp[1]; in[2] ^= ivp[2]; in[3] ^= ivp[3]; rijndael_Encrypt(in, out, key->encsched, key->rounds); blockcpy(outp, out); ivp= out; inp += 16; outp += 16; } } if (extra > 0) { blockcpy(in, inp); in[0] ^= ivp[0]; in[1] ^= ivp[1]; in[2] ^= ivp[2]; in[3] ^= ivp[3]; rijndael_Encrypt(in, out, key->encsched, key->rounds); for (i= 0; i < extra; i++) { t= B(out)[i]; B(out)[i] ^= inp[16 + i]; outp[16 + i] = t; } rijndael_Encrypt(out, out, key->encsched, key->rounds); blockcpy(outp, out); ivp= out; } blockcpy(IV, ivp); /* Store last IV back. */ return length;}ssize_t rijndael_cbc_decrypt(rd_keyinstance *key, const void *input, void *output, size_t length, void *IV){ /* Decrypt blocks of data in Cypher Block Chaining mode. */ const word8 *inp= input; word8 *outp= output;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -