1
0
mirror of https://github.com/biergaizi/codecrypt synced 2024-06-16 11:58:16 +00:00
codecrypt/src/cubehash_impl.h
Tom Li 29f7826b1e
cubehash_impl.h: finalize without an incomplete block.
Currently, process_final_incomplete_block() will perform the round
R calculation with the remaining data, then finalize CubeHash. It
is not possible to finalize CubeHash if there's no incomplete block.

Here, we define the call of process_final_incomplete_block(NULL, 0)
as a way to directly finalize CubeHash when input is a multiple of
block size and there is no remaining data for round R.

Also, in this case, any call of process_final_incomplete_block(),
but only with a single NULL pointer, or only with n == 0, is an
indication of bug. We assert both to be zero/nonzero.

Signed-off-by: Tom Li <tomli@tomli.me>
2019-01-03 21:18:21 +08:00

141 lines
3.4 KiB
C++

/*
* This file is part of Codecrypt.
*
* Copyright (C) 2013-2016 Mirek Kratochvil <exa.exa@gmail.com>
*
* Codecrypt is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Codecrypt is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Codecrypt. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ccr_cubehash_impl_h_
#define _ccr_cubehash_impl_h_
#include "types.h"
#include <cassert>
#include <stdint.h>
#define ROT(a,b,n) (((a) << (b)) | ((a) >> (n - b)))
#define i16(cmd) for(i=0;i<16;++i) cmd;
template < int I, //initialization rounds
int R, //rounds
int B, //input block size, less or equal 128
int F, //finalization rounds
int H > //output hash size in *bytes*, not bits! less or equal 128.
class cubehash_state
{
uint32_t X[32]; //the state
inline void rounds (uint n) {
int i;
uint32_t T[16];
for (; n; --n) {
i16 (X[i + 16] += X[i]);
i16 (T[i ^ 8] = X[i]);
i16 (X[i] = ROT (T[i], 7, 32));
i16 (X[i] ^= X[i + 16]);
i16 (T[i ^ 2] = X[i + 16]);
i16 (X[i + 16] = T[i]);
i16 (X[i + 16] += X[i]);
i16 (T[i ^ 4] = X[i]);
i16 (X[i] = ROT (T[i], 11, 32));
i16 (X[i] ^= X[i + 16]);
i16 (T[i ^ 1] = X[i + 16]);
i16 (X[i + 16] = T[i]);
}
}
public:
inline void init() {
static bool iv_init = false;
static uint32_t IV[32];
int i;
if (iv_init) {
for (i = 0; i < 32; ++i) X[i] = IV[i];
return;
}
X[0] = H;
X[1] = B;
X[2] = R;
for (i = 3; i < 32; ++i) X[i] = 0;
rounds (I);
for (i = 0; i < 32; ++i) IV[i] = X[i];
iv_init = true;
}
void process_block (const byte*data) {
int i;
for (i = 0; i + 4 <= B; i += 4)
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ //allow a small speedup for LE architectures
X[i / 4] ^= * (uint32_t*) &data[i];
#else
X[i / 4] ^= (uint32_t) data[i]
| ( (uint32_t) data[i + 1]) << 8
| ( (uint32_t) data[i + 2]) << 16
| ( (uint32_t) data[i + 3]) << 24;
#endif
for (; i < B; ++i)
X[i / 4] ^= ( (uint32_t) (data[i])) << ( (i % 4) * 8);
rounds (R);
}
void process_final_incomplete_block (const byte*data, int n) {
int i;
if (data == NULL && n == 0) {
//empty block, finalize
X[31] ^= 1;
rounds (F);
return;
}
assert(data != NULL && n != 0); // if only one is NULL/0, it's a bug
for (i = 0; i + 4 <= n; i += 4)
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
X[i / 4] ^= * (uint32_t*) &data[i];
#else
X[i / 4] ^= (uint32_t) data[i]
| ( (uint32_t) data[i + 1]) << 8
| ( (uint32_t) data[i + 2]) << 16
| ( (uint32_t) data[i + 3]) << 24;
#endif
for (; i < n; ++i)
X[i / 4] ^= ( (uint32_t) (data[i])) << ( (i % 4) * 8);
//i==n, n<128 (!)
X[i / 4] ^= ( (uint32_t) 0x80) << ( (i % 4) * 8);
rounds (R);
//finalize
X[31] ^= 1;
rounds (F);
}
void get_hash (byte*out) {
for (int i = 0; i < H; ++i)
out[i] = (X[i / 4] >> ( (i % 4) * 8)) & 0xff;
}
};
#endif