Path: blob/main/sys/crypto/rijndael/rijndael-api-fst.c
39482 views
/* $KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $ */12/*3* rijndael-api-fst.c v2.3 April '20004*5* Optimised ANSI C code6*7* authors: v1.0: Antoon Bosselaers8* v2.0: Vincent Rijmen9* v2.1: Vincent Rijmen10* v2.2: Vincent Rijmen11* v2.3: Paulo Barreto12* v2.4: Vincent Rijmen13*14* This code is placed in the public domain.15*/1617#include <sys/param.h>18#ifdef _KERNEL19#include <sys/systm.h>20#else21#include <string.h>22#endif2324#include <crypto/rijndael/rijndael_local.h>25#include <crypto/rijndael/rijndael-api-fst.h>2627#ifndef TRUE28#define TRUE 129#endif3031typedef uint8_t BYTE;3233int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,34const char *keyMaterial) {3536if (key == NULL) {37return BAD_KEY_INSTANCE;38}3940if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {41key->direction = direction;42} else {43return BAD_KEY_DIR;44}4546if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {47key->keyLen = keyLen;48} else {49return BAD_KEY_MAT;50}5152if (keyMaterial != NULL) {53memcpy(key->keyMaterial, keyMaterial, keyLen/8);54}5556/* initialize key schedule: */57if (direction == DIR_ENCRYPT) {58key->Nr = rijndaelKeySetupEnc(key->rk, key->keyMaterial, keyLen);59} else {60key->Nr = rijndaelKeySetupDec(key->rk, key->keyMaterial, keyLen);61}62rijndaelKeySetupEnc(key->ek, key->keyMaterial, keyLen);63return TRUE;64}6566int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {67if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {68cipher->mode = mode;69} else {70return BAD_CIPHER_MODE;71}72if (IV != NULL) {73memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);74} else {75memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);76}77return TRUE;78}7980int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,81const BYTE *input, int inputLen, BYTE *outBuffer) {82int i, k, numBlocks;83uint8_t block[16], iv[4][4];8485if (cipher == NULL ||86key == NULL ||87key->direction == DIR_DECRYPT) {88return BAD_CIPHER_STATE;89}90if (input == NULL || inputLen <= 0) {91return 0; /* nothing to do */92}9394numBlocks = inputLen/128;9596switch (cipher->mode) {97case MODE_ECB:98for (i = numBlocks; i > 0; i--) {99rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);100input += 16;101outBuffer += 16;102}103break;104105case MODE_CBC:106#if 1 /*STRICT_ALIGN*/107memcpy(block, cipher->IV, 16);108memcpy(iv, input, 16);109((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];110((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];111((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];112((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];113#else114((uint32_t*)block)[0] = ((uint32_t*)cipher->IV)[0] ^ ((uint32_t*)input)[0];115((uint32_t*)block)[1] = ((uint32_t*)cipher->IV)[1] ^ ((uint32_t*)input)[1];116((uint32_t*)block)[2] = ((uint32_t*)cipher->IV)[2] ^ ((uint32_t*)input)[2];117((uint32_t*)block)[3] = ((uint32_t*)cipher->IV)[3] ^ ((uint32_t*)input)[3];118#endif119rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);120input += 16;121for (i = numBlocks - 1; i > 0; i--) {122#if 1 /*STRICT_ALIGN*/123memcpy(block, outBuffer, 16);124memcpy(iv, input, 16);125((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];126((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];127((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];128((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];129#else130((uint32_t*)block)[0] = ((uint32_t*)outBuffer)[0] ^ ((uint32_t*)input)[0];131((uint32_t*)block)[1] = ((uint32_t*)outBuffer)[1] ^ ((uint32_t*)input)[1];132((uint32_t*)block)[2] = ((uint32_t*)outBuffer)[2] ^ ((uint32_t*)input)[2];133((uint32_t*)block)[3] = ((uint32_t*)outBuffer)[3] ^ ((uint32_t*)input)[3];134#endif135outBuffer += 16;136rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);137input += 16;138}139break;140141case MODE_CFB1:142#if 1 /*STRICT_ALIGN*/143memcpy(iv, cipher->IV, 16);144#else /* !STRICT_ALIGN */145*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV ));146*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));147*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));148*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));149#endif /* ?STRICT_ALIGN */150for (i = numBlocks; i > 0; i--) {151for (k = 0; k < 128; k++) {152*((uint32_t*) block ) = *((uint32_t*)iv[0]);153*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);154*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);155*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);156rijndaelEncrypt(key->ek, key->Nr, block,157block);158outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);159iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);160iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);161iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);162iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);163iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);164iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);165iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);166iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);167iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);168iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);169iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);170iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);171iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);172iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);173iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);174iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);175}176}177break;178179default:180return BAD_CIPHER_STATE;181}182183explicit_bzero(block, sizeof(block));184return 128*numBlocks;185}186187/**188* Encrypt data partitioned in octets, using RFC 2040-like padding.189*190* @param input data to be encrypted (octet sequence)191* @param inputOctets input length in octets (not bits)192* @param outBuffer encrypted output data193*194* @return length in octets (not bits) of the encrypted output buffer.195*/196int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,197const BYTE *input, int inputOctets, BYTE *outBuffer) {198int i, numBlocks, padLen;199uint8_t block[16], *iv, *cp;200201if (cipher == NULL ||202key == NULL ||203key->direction == DIR_DECRYPT) {204return BAD_CIPHER_STATE;205}206if (input == NULL || inputOctets <= 0) {207return 0; /* nothing to do */208}209210numBlocks = inputOctets/16;211212switch (cipher->mode) {213case MODE_ECB:214for (i = numBlocks; i > 0; i--) {215rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);216input += 16;217outBuffer += 16;218}219padLen = 16 - (inputOctets - 16*numBlocks);220if (padLen <= 0 || padLen > 16)221return BAD_CIPHER_STATE;222memcpy(block, input, 16 - padLen);223for (cp = block + 16 - padLen; cp < block + 16; cp++)224*cp = padLen;225rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);226break;227228case MODE_CBC:229iv = cipher->IV;230for (i = numBlocks; i > 0; i--) {231((uint32_t*)block)[0] = ((const uint32_t*)input)[0] ^ ((uint32_t*)iv)[0];232((uint32_t*)block)[1] = ((const uint32_t*)input)[1] ^ ((uint32_t*)iv)[1];233((uint32_t*)block)[2] = ((const uint32_t*)input)[2] ^ ((uint32_t*)iv)[2];234((uint32_t*)block)[3] = ((const uint32_t*)input)[3] ^ ((uint32_t*)iv)[3];235rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);236iv = outBuffer;237input += 16;238outBuffer += 16;239}240padLen = 16 - (inputOctets - 16*numBlocks);241if (padLen <= 0 || padLen > 16)242return BAD_CIPHER_STATE;243for (i = 0; i < 16 - padLen; i++) {244block[i] = input[i] ^ iv[i];245}246for (i = 16 - padLen; i < 16; i++) {247block[i] = (BYTE)padLen ^ iv[i];248}249rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);250break;251252default:253return BAD_CIPHER_STATE;254}255256explicit_bzero(block, sizeof(block));257return 16*(numBlocks + 1);258}259260int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,261const BYTE *input, int inputLen, BYTE *outBuffer) {262int i, k, numBlocks;263uint8_t block[16], iv[4][4];264265if (cipher == NULL ||266key == NULL ||267(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {268return BAD_CIPHER_STATE;269}270if (input == NULL || inputLen <= 0) {271return 0; /* nothing to do */272}273274numBlocks = inputLen/128;275276switch (cipher->mode) {277case MODE_ECB:278for (i = numBlocks; i > 0; i--) {279rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);280input += 16;281outBuffer += 16;282}283break;284285case MODE_CBC:286#if 1 /*STRICT_ALIGN */287memcpy(iv, cipher->IV, 16);288#else289*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV ));290*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));291*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));292*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));293#endif294for (i = numBlocks; i > 0; i--) {295rijndaelDecrypt(key->rk, key->Nr, input, block);296((uint32_t*)block)[0] ^= *((uint32_t*)iv[0]);297((uint32_t*)block)[1] ^= *((uint32_t*)iv[1]);298((uint32_t*)block)[2] ^= *((uint32_t*)iv[2]);299((uint32_t*)block)[3] ^= *((uint32_t*)iv[3]);300#if 1 /*STRICT_ALIGN*/301memcpy(iv, input, 16);302memcpy(outBuffer, block, 16);303#else304*((uint32_t*)iv[0]) = ((uint32_t*)input)[0]; ((uint32_t*)outBuffer)[0] = ((uint32_t*)block)[0];305*((uint32_t*)iv[1]) = ((uint32_t*)input)[1]; ((uint32_t*)outBuffer)[1] = ((uint32_t*)block)[1];306*((uint32_t*)iv[2]) = ((uint32_t*)input)[2]; ((uint32_t*)outBuffer)[2] = ((uint32_t*)block)[2];307*((uint32_t*)iv[3]) = ((uint32_t*)input)[3]; ((uint32_t*)outBuffer)[3] = ((uint32_t*)block)[3];308#endif309input += 16;310outBuffer += 16;311}312break;313314case MODE_CFB1:315#if 1 /*STRICT_ALIGN */316memcpy(iv, cipher->IV, 16);317#else318*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV));319*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));320*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));321*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));322#endif323for (i = numBlocks; i > 0; i--) {324for (k = 0; k < 128; k++) {325*((uint32_t*) block ) = *((uint32_t*)iv[0]);326*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);327*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);328*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);329rijndaelEncrypt(key->ek, key->Nr, block,330block);331iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);332iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);333iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);334iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);335iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);336iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);337iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);338iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);339iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);340iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);341iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);342iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);343iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);344iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);345iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);346iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);347outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);348}349}350break;351352default:353return BAD_CIPHER_STATE;354}355356explicit_bzero(block, sizeof(block));357return 128*numBlocks;358}359360int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,361const BYTE *input, int inputOctets, BYTE *outBuffer) {362int i, numBlocks, padLen, rval;363uint8_t block[16];364uint32_t iv[4];365366if (cipher == NULL ||367key == NULL ||368key->direction == DIR_ENCRYPT) {369return BAD_CIPHER_STATE;370}371if (input == NULL || inputOctets <= 0) {372return 0; /* nothing to do */373}374if (inputOctets % 16 != 0) {375return BAD_DATA;376}377378numBlocks = inputOctets/16;379380switch (cipher->mode) {381case MODE_ECB:382/* all blocks but last */383for (i = numBlocks - 1; i > 0; i--) {384rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);385input += 16;386outBuffer += 16;387}388/* last block */389rijndaelDecrypt(key->rk, key->Nr, input, block);390padLen = block[15];391if (padLen >= 16) {392rval = BAD_DATA;393goto out;394}395for (i = 16 - padLen; i < 16; i++) {396if (block[i] != padLen) {397rval = BAD_DATA;398goto out;399}400}401memcpy(outBuffer, block, 16 - padLen);402break;403404case MODE_CBC:405memcpy(iv, cipher->IV, 16);406/* all blocks but last */407for (i = numBlocks - 1; i > 0; i--) {408rijndaelDecrypt(key->rk, key->Nr, input, block);409((uint32_t*)block)[0] ^= iv[0];410((uint32_t*)block)[1] ^= iv[1];411((uint32_t*)block)[2] ^= iv[2];412((uint32_t*)block)[3] ^= iv[3];413memcpy(iv, input, 16);414memcpy(outBuffer, block, 16);415input += 16;416outBuffer += 16;417}418/* last block */419rijndaelDecrypt(key->rk, key->Nr, input, block);420((uint32_t*)block)[0] ^= iv[0];421((uint32_t*)block)[1] ^= iv[1];422((uint32_t*)block)[2] ^= iv[2];423((uint32_t*)block)[3] ^= iv[3];424padLen = block[15];425if (padLen <= 0 || padLen > 16) {426rval = BAD_DATA;427goto out;428}429for (i = 16 - padLen; i < 16; i++) {430if (block[i] != padLen) {431rval = BAD_DATA;432goto out;433}434}435memcpy(outBuffer, block, 16 - padLen);436break;437438default:439return BAD_CIPHER_STATE;440}441442rval = 16*numBlocks - padLen;443444out:445explicit_bzero(block, sizeof(block));446return rval;447}448449450