📄 pgpaes.c
字号:
/*
* Optimised ANSI C code for the AES cipher AKA Rijndael
* authors: v1.0: Antoon Bosselaers
* v2.0: Vincent Rijmen
* Formatted for PGP.
* $Id: pgpAES.c,v 1.9 2001/10/05 23:55:00 hal Exp $
*/
#include "pgpSDKBuildFlags.h"
#ifndef PGP_AES
#error you must define PGP_AES one way or the other
#endif
#if PGP_AES /* [ */
#include "pgpConfig.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpAES.h"
#include "pgpMem.h"
#include "pgpUsuals.h"
#include <stdio.h>
#include <stdlib.h>
#define MAXKC (256/32)
#define MAXROUNDS 14
typedef unsigned char word8;
typedef unsigned short word16;
typedef unsigned int word32;
static int rijndaelKeySched (word8 k[MAXKC][4], int keyBits,
word8 rk[MAXROUNDS+1][4][4], int rounds);
static int rijndaelEncrypt (word8 a[16], word8 b[16],
word8 rk[MAXROUNDS+1][4][4], int rounds);
static int rijndaelKeyEnctoDec (int keyBits, word8 W[MAXROUNDS+1][4][4],
int rounds);
static int rijndaelKeyDectoEnc (int keyBits, word8 W[MAXROUNDS+1][4][4],
int rounds);
static int rijndaelDecrypt (word8 a[16], word8 b[16],
word8 rk[MAXROUNDS+1][4][4], int rounds);
#if PGP_UNIX_SOLARIS
/* Hosts which can't dereference arbitrary pointers as word32s */
#define AES_WORD_ALIGNMENT 1
#else
#define AES_WORD_ALIGNMENT 0
#endif
#define SC ((BC - 4) >> 1)
#include "pgpAESboxes.h"
#if ! PGP_OSX /* These do not appear to be used. */
static word8 shifts[3][4][2] = {
{ { 0, 0 },
{ 1, 3 },
{ 2, 2 },
{ 3, 1 } },
{ { 0, 0 },
{ 1, 5 },
{ 2, 4 },
{ 3, 3 } },
{ { 0, 0 },
{ 1, 7 },
{ 3, 5 },
{ 4, 4 } }
};
#endif
static word8 mul(word8 a, word8 b) {
/* multiply two elements of GF(2^m)
* needed for MixColumn and InvMixColumn
*/
if (a && b)
return Alogtable[(Logtable[a] + Logtable[b])%255];
else
return 0;
}
#if ! PGP_OSX /* These do not appear to be used */
static void KeyAddition(word8 a[4][4], word8 rk[4][4], word8 BC) {
/* Exor corresponding text input and round key input bytes
*/
int i, j;
for(i = 0; i < BC; i++)
for(j = 0; j < 4; j++)
a[i][j] ^= rk[i][j];
}
static void ShiftRow(word8 a[4][4], word8 d, word8 BC) {
/* Row 0 remains unchanged
* The other three rows are shifted a variable amount
*/
word8 tmp[4];
int i, j;
for(i = 1; i < 4; i++) {
for(j = 0; j < BC; j++)
tmp[j] = a[(j + shifts[SC][i][d]) % BC][i];
for(j = 0; j < BC; j++)
a[j][i] = tmp[j];
}
}
static void Substitution(word8 a[4][4], word8 box[256], word8 BC) {
/* Replace every byte of the input by the byte at that place
* in the nonlinear S-box
*/
int i, j;
for(i = 0; i < BC; i++)
for(j = 0; j < 4; j++)
a[i][j] = box[a[i][j]] ;
}
#endif
static void MixColumn(word8 a[4][4], word8 BC) {
/* Mix the four bytes of every column in a linear way
*/
word8 b[4][4];
int i, j;
for(j = 0; j < BC; j++)
for(i = 0; i < 4; i++)
b[j][i] = mul(2,a[j][i])
^ mul(3,a[j][(i + 1) % 4])
^ a[j][(i + 2) % 4]
^ a[j][(i + 3) % 4];
for(i = 0; i < 4; i++)
for(j = 0; j < BC; j++)
a[j][i] = b[j][i];
}
static void InvMixColumn(word8 a[4][4], word8 BC) {
/* Mix the four bytes of every column in a linear way
* This is the opposite operation of Mixcolumn
*/
int j;
for(j = 0; j < BC; j++)
*((word32*)a[j]) = *((word32*)U1[a[j][0]])
^ *((word32*)U2[a[j][1]])
^ *((word32*)U3[a[j][2]])
^ *((word32*)U4[a[j][3]]);
}
int rijndaelKeySched (word8 k[MAXKC][4], int keyBits,
word8 W[MAXROUNDS+1][4][4], int rounds)
{
/* Calculate the necessary round keys
* The number of calculations depends on keyBits and blockBits
*/
int j, r, t, rconpointer = 0;
word8 tk[MAXKC][4];
int KC = rounds - 6;
(void) keyBits; /* Silence compiler warnings */
/*
* Copy to tk array without requiring k to have word32 safe alignment
for(j = KC-1; j >= 0; j--)
*((word32*)tk[j]) = *((word32*)k[j]);
*/
pgpCopyMemory( k, tk, KC*4 );
r = 0;
t = 0;
/* copy values into round key array */
for(j = 0; (j < KC) && (r < (rounds+1)); ) {
for (; (j < KC) && (t < 4); j++, t++)
*((word32*)W[r][t]) = *((word32*)tk[j]);
if (t == 4) {
r++;
t = 0;
}
}
while (r < (rounds+1)) { /* while not enough round key material calculated */
/* calculate new values */
tk[0][0] ^= S[tk[KC-1][1]];
tk[0][1] ^= S[tk[KC-1][2]];
tk[0][2] ^= S[tk[KC-1][3]];
tk[0][3] ^= S[tk[KC-1][0]];
tk[0][0] ^= rcon[rconpointer++];
if (KC != 8)
for(j = 1; j < KC; j++)
*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
else {
for(j = 1; j < KC/2; j++)
*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
for(j = KC/2 + 1; j < KC; j++)
*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
}
/* copy values into round key array */
for(j = 0; (j < KC) && (r < (rounds+1)); ) {
for (; (j < KC) && (t < 4); j++, t++)
*((word32*)W[r][t]) = *((word32*)tk[j]);
if (t == 4) {
r++;
t = 0;
}
}
}
return 0;
}
static int rijndaelKeyEnctoDec (int keyBits, word8 W[MAXROUNDS+1][4][4],
int rounds)
{
int r;
(void) keyBits; /* Silence compiler warnings */
for (r = 1; r < rounds; r++) {
InvMixColumn(W[r], 4);
}
return 0;
}
static int rijndaelKeyDectoEnc (int keyBits, word8 W[MAXROUNDS+1][4][4],
int rounds)
{
int r;
(void) keyBits; /* Silence compiler warnings */
for (r = 1; r < rounds; r++) {
MixColumn(W[r], 4);
}
return 0;
}
/* rk is word32 aligned, but in and out may not be */
static int rijndaelEncrypt (word8 in[16], word8 out[16],
word8 rk[MAXROUNDS+1][4][4], int rounds)
{
/* Encryption of one block.
*/
int r;
#if AES_WORD_ALIGNMENT
word32 dummy;
word8 a[16], b[16];
#else
word8 *a, *b;
#endif
word8 temp[4][4];
#if AES_WORD_ALIGNMENT
pgpCopyMemory( in, a, sizeof(a) );
#else
a = in;
b = out;
#endif
*((word32*)temp[0]) = *((word32*)a) ^ *((word32*)rk[0][0]);
*((word32*)temp[1]) = *((word32*)(a+4)) ^ *((word32*)rk[0][1]);
*((word32*)temp[2]) = *((word32*)(a+8)) ^ *((word32*)rk[0][2]);
*((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
*((word32*)b) = *((word32*)T1[temp[0][0]])
^ *((word32*)T2[temp[1][1]])
^ *((word32*)T3[temp[2][2]])
^ *((word32*)T4[temp[3][3]]);
*((word32*)(b+4)) = *((word32*)T1[temp[1][0]])
^ *((word32*)T2[temp[2][1]])
^ *((word32*)T3[temp[3][2]])
^ *((word32*)T4[temp[0][3]]);
*((word32*)(b+8)) = *((word32*)T1[temp[2][0]])
^ *((word32*)T2[temp[3][1]])
^ *((word32*)T3[temp[0][2]])
^ *((word32*)T4[temp[1][3]]);
*((word32*)(b+12)) = *((word32*)T1[temp[3][0]])
^ *((word32*)T2[temp[0][1]])
^ *((word32*)T3[temp[1][2]])
^ *((word32*)T4[temp[2][3]]);
for(r = 1; r < rounds-1; r++) {
*((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[r][0]);
*((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[r][1]);
*((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[r][2]);
*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
*((word32*)b) = *((word32*)T1[temp[0][0]])
^ *((word32*)T2[temp[1][1]])
^ *((word32*)T3[temp[2][2]])
^ *((word32*)T4[temp[3][3]]);
*((word32*)(b+4)) = *((word32*)T1[temp[1][0]])
^ *((word32*)T2[temp[2][1]])
^ *((word32*)T3[temp[3][2]])
^ *((word32*)T4[temp[0][3]]);
*((word32*)(b+8)) = *((word32*)T1[temp[2][0]])
^ *((word32*)T2[temp[3][1]])
^ *((word32*)T3[temp[0][2]])
^ *((word32*)T4[temp[1][3]]);
*((word32*)(b+12)) = *((word32*)T1[temp[3][0]])
^ *((word32*)T2[temp[0][1]])
^ *((word32*)T3[temp[1][2]])
^ *((word32*)T4[temp[2][3]]);
}
/* last round is special */
*((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[rounds-1][0]);
*((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[rounds-1][1]);
*((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[rounds-1][2]);
*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[rounds-1][3]);
b[0] = T1[temp[0][0]][1];
b[1] = T1[temp[1][1]][1];
b[2] = T1[temp[2][2]][1];
b[3] = T1[temp[3][3]][1];
b[4] = T1[temp[1][0]][1];
b[5] = T1[temp[2][1]][1];
b[6] = T1[temp[3][2]][1];
b[7] = T1[temp[0][3]][1];
b[8] = T1[temp[2][0]][1];
b[9] = T1[temp[3][1]][1];
b[10] = T1[temp[0][2]][1];
b[11] = T1[temp[1][3]][1];
b[12] = T1[temp[3][0]][1];
b[13] = T1[temp[0][1]][1];
b[14] = T1[temp[1][2]][1];
b[15] = T1[temp[2][3]][1];
*((word32*)b) ^= *((word32*)rk[rounds][0]);
*((word32*)(b+4)) ^= *((word32*)rk[rounds][1]);
*((word32*)(b+8)) ^= *((word32*)rk[rounds][2]);
*((word32*)(b+12)) ^= *((word32*)rk[rounds][3]);
#if AES_WORD_ALIGNMENT
pgpCopyMemory( b, out, sizeof(b) );
#endif
return 0;
}
/* rk is word32 aligned, but in and out may not be */
static int rijndaelDecrypt (word8 in[16], word8 out[16],
word8 rk[MAXROUNDS+1][4][4], int rounds)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -