/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ /* * rijndaelApi.c - AES API layer * * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto * and Vincent Rijmen */ #include #include #include "rijndael-alg-ref.h" #include "rijndaelApi.h" #ifdef ALTIVEC_ENABLE /* this goes somewhere else and gets init'd by the plugin object.... */ /* as of 4/11/2001, the vectorized routines do NOT work */ int gHasAltivec = 0; #endif int doAES128 = 1; #define CBC_DEBUG 0 #if CBC_DEBUG static void dumpChainBuf(cipherInstance *cipher, char *op) { int t,j; int columns = cipher->blockLen / 32; printf("chainBuf %s: ", op); for (j = 0; j < columns; j++) { for(t = 0; t < 4; t++) { printf("%02x ", cipher->chainBlock[t][j]); } } printf("\n"); } #else #define dumpChainBuf(c, o) #endif int makeKey( keyInstance *key, int keyLen, // in BITS int blockLen, // in BITS word8 *keyMaterial, int enable128Opt) { unsigned keyBytes; unsigned i; if (key == NULL) { return BAD_KEY_INSTANCE; } if(keyMaterial == NULL) { return BAD_KEY_MAT; } if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { key->keyLen = keyLen; } else { return BAD_KEY_MAT; } key->blockLen = blockLen; key->columns = blockLen / 32; /* initialize key schedule */ #if !GLADMAN_AES_128_ENABLE if(enable128Opt && (keyLen == MIN_AES_KEY_BITS) && (blockLen == MIN_AES_BLOCK_BITS)) { /* optimized, 128 bit key and block size */ word8 k[4][KC_128_OPT] __attribute__((aligned(4))); for(i = 0; i < (MIN_AES_KEY_BITS/8); i++) { /* speed this up */ k[i % 4][i / 4] = keyMaterial[i]; } rijndaelKeySched128 (k, key->keySched); memset(k, 0, 4 * KC_128_OPT); } else #endif /* !GLADMAN_AES_128_ENABLE */ { /* general case */ word8 k[4][MAXKC]; keyBytes = keyLen / 8; for(i = 0; i < keyBytes; i++) { k[i % 4][i / 4] = keyMaterial[i]; } rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched); memset(k, 0, 4 * MAXKC); } return TRUE; } /* * Simplified single-block encrypt/decrypt. */ #define AES_CONSISTENCY_CHECK 1 int rijndaelBlockEncrypt( keyInstance *key, word8 *input, word8 *outBuffer) { int j, t; word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here #if AES_CONSISTENCY_CHECK if (key == NULL || (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { return BAD_KEY_INSTANCE; } #endif /* AES_CONSISTENCY_CHECK */ #if defined(__ppc__) && defined(ALTIVEC_ENABLE) if(gHasAltivec && (key->blockLen == 128)) { vBlockEncrypt128(key, input, outBuffer); return 128; } #endif for (j = 0; j < key->columns; j++) { for(t = 0; t < 4; t++) /* parse input stream into rectangular array */ localBlock[t][j] = input[4*j+t]; } rijndaelEncrypt (localBlock, key->keyLen, key->blockLen, key->keySched); for (j = 0; j < key->columns; j++) { /* parse rectangular array into output ciphertext bytes */ for(t = 0; t < 4; t++) outBuffer[4*j+t] = (word8) localBlock[t][j]; } memset(localBlock, 0, 4 * MAXBC); return key->blockLen; } int rijndaelBlockDecrypt( keyInstance *key, word8 *input, word8 *outBuffer) { int j, t; word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here #if AES_CONSISTENCY_CHECK if (key == NULL || (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { return BAD_KEY_INSTANCE; } #endif /* AES_CONSISTENCY_CHECK */ #if defined(__ppc__) && defined(ALTIVEC_ENABLE) if(gHasAltivec && (cipher->blockLen == 128)) { vBlockDecrypt128(key, input, outBuffer); return 128; } #endif for (j = 0; j < key->columns; j++) { for(t = 0; t < 4; t++) /* parse input stream into rectangular array */ localBlock[t][j] = input[4*j+t]; } rijndaelDecrypt (localBlock, key->keyLen, key->blockLen, key->keySched); for (j = 0; j < key->columns; j++) { /* parse rectangular array into output ciphertext bytes */ for(t = 0; t < 4; t++) outBuffer[4*j+t] = (word8) localBlock[t][j]; } memset(localBlock, 0, 4 * MAXBC); return key->blockLen; } #if !GLADMAN_AES_128_ENABLE /* * Optimized routines for 128 bit block and 128 bit key. */ int rijndaelBlockEncrypt128( keyInstance *key, word8 *input, word8 *outBuffer) { int j; word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); word8 *row0 = localBlock[0]; word8 *row1 = localBlock[1]; word8 *row2 = localBlock[2]; word8 *row3 = localBlock[3]; /* parse input stream into rectangular array */ for (j = 0; j < BC_128_OPT; j++) { *row0++ = *input++; *row1++ = *input++; *row2++ = *input++; *row3++ = *input++; } rijndaelEncrypt128 (localBlock, key->keySched); /* parse rectangular array into output ciphertext bytes */ row0 = localBlock[0]; row1 = localBlock[1]; row2 = localBlock[2]; row3 = localBlock[3]; for (j = 0; j < BC_128_OPT; j++) { *outBuffer++ = *row0++; *outBuffer++ = *row1++; *outBuffer++ = *row2++; *outBuffer++ = *row3++; } memset(localBlock, 0, 4*BC_128_OPT); return MIN_AES_BLOCK_BITS; } int rijndaelBlockDecrypt128( keyInstance *key, word8 *input, word8 *outBuffer) { int j; word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); word8 *row0 = localBlock[0]; word8 *row1 = localBlock[1]; word8 *row2 = localBlock[2]; word8 *row3 = localBlock[3]; /* parse input stream into rectangular array */ for (j = 0; j < BC_128_OPT; j++) { *row0++ = *input++; *row1++ = *input++; *row2++ = *input++; *row3++ = *input++; } rijndaelDecrypt128 (localBlock, key->keySched); /* parse rectangular array into output ciphertext bytes */ row0 = localBlock[0]; row1 = localBlock[1]; row2 = localBlock[2]; row3 = localBlock[3]; for (j = 0; j < BC_128_OPT; j++) { *outBuffer++ = *row0++; *outBuffer++ = *row1++; *outBuffer++ = *row2++; *outBuffer++ = *row3++; } memset(localBlock, 0, 4*BC_128_OPT); return MIN_AES_BLOCK_BITS; } #endif /* !GLADMAN_AES_128_ENABLE */