Path: blob/master/libs/tomcrypt/src/encauth/ocb3/ocb3_init.c
8785 views
/* LibTomCrypt, modular cryptographic library -- Tom St Denis1*2* LibTomCrypt is a library that provides various cryptographic3* algorithms in a highly modular and flexible manner.4*5* The library is free for all purposes without any express6* guarantee it works.7*/89/**10@file ocb3_init.c11OCB implementation, initialize state, by Tom St Denis12*/13#include "tomcrypt.h"1415#ifdef LTC_OCB3_MODE1617static void _ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen)18{19int x, y, bottom;20int idx, shift;21unsigned char iNonce[MAXBLOCKSIZE];22unsigned char iKtop[MAXBLOCKSIZE];23unsigned char iStretch[MAXBLOCKSIZE+8];2425/* Nonce = zeros(127-bitlen(N)) || 1 || N */26zeromem(iNonce, sizeof(iNonce));27for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) {28iNonce[x] = nonce[noncelen-y-1];29}30iNonce[x] = 0x01;31iNonce[0] |= ((taglen*8) % 128) << 1;3233/* bottom = str2num(Nonce[123..128]) */34bottom = iNonce[ocb->block_len-1] & 0x3F;3536/* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */37iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0;38if ((cipher_descriptor[ocb->cipher].ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) {39zeromem(ocb->Offset_current, ocb->block_len);40return;41}4243/* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */44for (x = 0; x < ocb->block_len; x++) {45iStretch[x] = iKtop[x];46}47for (y = 0; y < 8; y++) {48iStretch[x+y] = iKtop[y] ^ iKtop[y+1];49}5051/* Offset_0 = Stretch[1+bottom..128+bottom] */52idx = bottom / 8;53shift = (bottom % 8);54for (x = 0; x < ocb->block_len; x++) {55ocb->Offset_current[x] = iStretch[idx+x] << shift;56if (shift > 0) {57ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift);58}59}60}6162static const struct {63int len;64unsigned char poly_mul[MAXBLOCKSIZE];65} polys[] = {66{678,68{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }69}, {7016,71{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }73}74};7576/**77Initialize an OCB context78@param ocb [out] The destination of the OCB state79@param cipher The index of the desired cipher80@param key The secret key81@param keylen The length of the secret key (octets)82@param nonce The session nonce83@param noncelen The length of the session nonce (octets, up to 15)84@param taglen The length of the tag (octets, up to 16)85@return CRYPT_OK if successful86*/87int ocb3_init(ocb3_state *ocb, int cipher,88const unsigned char *key, unsigned long keylen,89const unsigned char *nonce, unsigned long noncelen,90unsigned long taglen)91{92int poly, x, y, m, err;93unsigned char *previous, *current;9495LTC_ARGCHK(ocb != NULL);96LTC_ARGCHK(key != NULL);97LTC_ARGCHK(nonce != NULL);9899/* valid cipher? */100if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {101return err;102}103ocb->cipher = cipher;104105/* Valid Nonce?106* As of RFC7253: "string of no more than 120 bits" */107if (noncelen > (120/8)) {108return CRYPT_INVALID_ARG;109}110111/* The blockcipher must have a 128-bit blocksize */112if (cipher_descriptor[cipher].block_length != 16) {113return CRYPT_INVALID_ARG;114}115116/* The TAGLEN may be any value up to 128 (bits) */117if (taglen > 16) {118return CRYPT_INVALID_ARG;119}120ocb->tag_len = taglen;121122/* determine which polys to use */123ocb->block_len = cipher_descriptor[cipher].block_length;124x = (int)(sizeof(polys)/sizeof(polys[0]));125for (poly = 0; poly < x; poly++) {126if (polys[poly].len == ocb->block_len) {127break;128}129}130if (poly == x) {131return CRYPT_INVALID_ARG; /* block_len not found in polys */132}133if (polys[poly].len != ocb->block_len) {134return CRYPT_INVALID_ARG;135}136137/* schedule the key */138if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {139return err;140}141142/* L_* = ENCIPHER(K, zeros(128)) */143zeromem(ocb->L_star, ocb->block_len);144if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) {145return err;146}147148/* compute L_$, L_0, L_1, ... */149for (x = -1; x < 32; x++) {150if (x == -1) { /* gonna compute: L_$ = double(L_*) */151current = ocb->L_dollar;152previous = ocb->L_star;153}154else if (x == 0) { /* gonna compute: L_0 = double(L_$) */155current = ocb->L_[0];156previous = ocb->L_dollar;157}158else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */159current = ocb->L_[x];160previous = ocb->L_[x-1];161}162m = previous[0] >> 7;163for (y = 0; y < ocb->block_len-1; y++) {164current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255;165}166current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255;167if (m == 1) {168/* current[] = current[] XOR polys[poly].poly_mul[]*/169ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len);170}171}172173/* initialize ocb->Offset_current = Offset_0 */174_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen);175176/* initialize checksum to all zeros */177zeromem(ocb->checksum, ocb->block_len);178179/* set block index */180ocb->block_index = 1;181182/* initialize AAD related stuff */183ocb->ablock_index = 1;184ocb->adata_buffer_bytes = 0;185zeromem(ocb->aOffset_current, ocb->block_len);186zeromem(ocb->aSum_current, ocb->block_len);187188return CRYPT_OK;189}190191#endif192193194