#include "PMAC.h"
#include<iostream>
#include<fstream>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
using namespace std;
#if (INT_MAX != 0x7fffffff)
#error -- Assumes 4-byte int
#endif
/*
* This implementation precomputes L(-1), L(0), L(1), L(PRE_COMP_BLOCKS),
* where L(0) = L and L(-1) = L/x and L(i) = x*L(i) for i>0.
* Normally, one would select PRE_COMP_BLOCKS to be a small number
* (like 0-6) and compute any larger L(i) values "on the fly", when they
* are needed. This saves space in _keystruct and needn't adversely
* impact running time. But in this implementation, to keep things as
* simple as possible, we compute all the L(i)-values we might ever see.
*/
#define PRE_COMP_BLOCKS 31 /* Must be between 0 and 31 */
#define AES_ROUNDS (AES_KEY_BITLEN / 32 + 6)
typedef unsigned char block[16];
struct _keystruct {
unsigned rek[4*(AES_ROUNDS+1)]; /* AES encryption key */
unsigned rdk[4*(AES_ROUNDS+1)]; /* AES decryption key */
unsigned tag_len; /* Sizeof tags to generate/validate */
block L[PRE_COMP_BLOCKS+1]; /* Precomputed L(i) values, L[0] = L */
block L_inv; /* Precomputed L/x value */
};
/*************************************************************************
* xor_block
*************************************************************************/
static void
xor_block(void *dst, void *src1, void *src2)
/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */
{
((unsigned *)dst)[0] = ((unsigned *)src1)[0] ^ ((unsigned *)src2)[0];
((unsigned *)dst)[1] = ((unsigned *)src1)[1] ^ ((unsigned *)src2)[1];
((unsigned *)dst)[2] = ((unsigned *)src1)[2] ^ ((unsigned *)src2)[2];
((unsigned *)dst)[3] = ((unsigned *)src1)[3] ^ ((unsigned *)src2)[3];
}
/*************************************************************************
* shift_left
*************************************************************************/
static void
shift_left(unsigned char *x)
/* 128-bit shift-left by 1 bit: *x <<= 1. */
{
int i;
for (i = 0; i < 15; i++) {
x[i] = (x[i] << 1) | (x[i+1] & 0x80 ? 1 : 0);
}
x[15] = (x[15] << 1);
}
/*************************************************************************
* shift_right
*************************************************************************/
static void
shift_right(unsigned char *x)
/* 128-bit shift-right by 1 bit: *x >>= 1 */
{
int i;
for (i = 15; i > 0; i--) {
x[i] = (x[i] >> 1) | (x[i-1] & 1 ? 0x80u : 0);
}
x[0] = (x[0] >> 1);
}
/*************************************************************************
* ntz
*************************************************************************/
static int
ntz(unsigned i)
/* Count the number of trailing zeroes in integer i. */
{
#if (_MSC_VER && _M_IX86) /* Only non-C sop */
__asm bsf eax, i
#elif (__GNUC__ && __i386__)
int rval;
asm volatile("bsf %1, %0" : "=r" (rval) : "g" (i));
return rval;
#else
int rval = 0;
while ((i & 1) == 0) {
i >>= 1;
rval++;
}
return rval;
#endif
}
/*************************************************************************
* ocb_aes_init
*************************************************************************/
keystruct * /* Init'd keystruct or NULL */
ocb_aes_init(void *enc_key, /* AES key */
unsigned tag_len, /* Length of tags to be used */
keystruct *key) /* OCB key structure. NULL means */
/* Allocate/init new, non-NULL */
/* means init existing structure */
{
unsigned char tmp[16] = {0,};
unsigned first_bit, last_bit, i;
if (key == NULL)
key = (keystruct *)malloc(sizeof(keystruct));
if (key != NULL) {
memset(key, 0, sizeof(keystruct));
/* Initialize AES keys. (Note that if one is only going to
encrypt, key->rdk can be eliminated */
rijndaelKeySetupEnc(key->rek, (unsigned char *)enc_key,
AES_KEY_BITLEN);
rijndaelKeySetupDec(key->rdk, (unsigned char *)enc_key,
AES_KEY_BITLEN);
/* Precompute L[i]-values. L[0] is synonym of L */
rijndaelEncrypt (key->rek, AES_ROUNDS, tmp, tmp);
for (i = 0; i <= PRE_COMP_BLOCKS; i++) {
memcpy(key->L + i, tmp, 16); /* Copy tmp to L[i] */
first_bit = tmp[0] & 0x80u; /* and multiply tmp by x */
shift_left(tmp);
if (first_bit)
tmp[15] ^= 0x87;
}
/* Precompute L_inv = L . x^{-1} */
memcpy(tmp, key->L, 16);
last_bit = tmp[15] & 0x01;
shift_right(tmp);
if (last_bit) {
tmp[0] ^= 0x80;
tmp[15] ^= 0x43;
}
memcpy(key->L_inv, tmp, 16);
/* Set tag length used for this session */
key->tag_len = tag_len;
}
return key;
}
/*************************************************************************
* pmac_aes -- move to a separate file when everything final
*************************************************************************/
void
pmac_aes (keystruct *key, /* Initialized key struct */
void *in, /* Buffer for (incoming) message */
unsigned in_len, /* Byte length of message */
void *tag) /* 16-byte buffer for generated tag */
{
unsigned i; /* Block counter */
unsigned char tmp[16]; /* temporary buffer */
block *in_blk; /* Block-typed alias to in */
block Offset; /* Offset (Z[i]) for current block */
block checksum; /* Checksum for computing tag */
/*
* Initializations
*/
i = 1; /* Start with first block */
in_blk = (block *)in - 1; /* Offset so in_blk[1] is first block. */
memset(checksum, 0, 16); /* Initlize the checksum and */
memset(Offset, 0, 16); /* current Offset to the zero block */
/*
* Process blocks 1 .. m-1.
*/
while (in_len > 16) {
/* Update Offset (Z[i] from Z[i-1]) */
xor_block(Offset, key->L + ntz(i), Offset);
xor_block(tmp, Offset, in_blk + i); /* xor input block with Z[i] */
rijndaelEncrypt(key->rek, AES_ROUNDS, tmp, tmp);
xor_block(checksum, checksum, tmp); /* Update checksum */
in_len -= 16; /* and the loop variables */
i++;
}
/*
* Process block m
*/
if (in_len == 16) { /* full final block */
xor_block(checksum, checksum, in_blk + i);
xor_block(checksum, checksum, key->L_inv);
} else { /* short final block */
memset(tmp, 0, 16);
memcpy(tmp, in_blk + i, in_len);
tmp[in_len] = 0x80;
xor_block(checksum, checksum, tmp);
}
rijndaelEncrypt(key->rek, AES_ROUNDS, checksum, (unsigned char *)tag);
}
static const u32 Te0[256] = {
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
0xeffafa15U, 0xb25959ebU, 0x8e4
评论0