diff --git a/audit/chacha20.c b/audit/chacha20.c deleted file mode 100644 index 5358ca4..0000000 --- a/audit/chacha20.c +++ /dev/null @@ -1,343 +0,0 @@ -/* =================================================================== - * - * Copyright (c) 2014, Legrandin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * =================================================================== - */ - -#include "common.h" -#include "endianess.h" - -FAKE_INIT(chacha20) - -#define KEY_SIZE 32 - -typedef struct { - /** Initial state for the next iteration **/ - uint32_t h[16]; - size_t nonceSize; /** in bytes **/ - - /** How many bytes at the beginning of the key stream - * have already been used. - */ - unsigned usedKeyStream; - - uint8_t keyStream[sizeof(uint32_t)*16]; -} stream_state; - -#define ROTL(q, n) (((q) << (n)) | ((q) >> (32 - (n)))) - -#define QR(a, b, c, d) {\ - a+=b; d^=a; d=ROTL(d,16); \ - c+=d; b^=c; b=ROTL(b,12); \ - a+=b; d^=a; d=ROTL(d,8); \ - c+=d; b^=c; b=ROTL(b,7); \ -} - -EXPORT_SYM int chacha20_init(stream_state **pState, - const uint8_t *key, - size_t keySize, - const uint8_t *nonce, - size_t nonceSize) -{ - stream_state *hs; - unsigned i; - - if (NULL == pState || NULL == nonce) - return ERR_NULL; - - if (NULL == key || keySize != KEY_SIZE) - return ERR_KEY_SIZE; - - if (nonceSize != 8 && nonceSize != 12 && nonceSize != 16) - return ERR_NONCE_SIZE; - - *pState = hs = (stream_state*) calloc(1, sizeof(stream_state)); - if (NULL == hs) - return ERR_MEMORY; - - hs->h[0] = 0x61707865; - hs->h[1] = 0x3320646e; - hs->h[2] = 0x79622d32; - hs->h[3] = 0x6b206574; - - /** Move 256-bit/32-byte key into h[4..11] **/ - for (i=0; i<32/4; i++) { - hs->h[4+i] = LOAD_U32_LITTLE(key + 4*i); - } - - switch (nonceSize) { - case 8: { - /* - cccccccc cccccccc cccccccc cccccccc - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - bbbbbbbb BBBBBBBB nnnnnnnn nnnnnnnn - - c=constant k=key b=blockcount(low) B=blockcount(high) n=nonce - */ - - /** h[12] remains 0 (offset) **/ - /** h[13] remains 0 (offset) **/ - hs->h[14] = LOAD_U32_LITTLE(nonce + 0); - hs->h[15] = LOAD_U32_LITTLE(nonce + 4); - break; - } - case 12: { - /* - cccccccc cccccccc cccccccc cccccccc - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - bbbbbbbb nnnnnnnn nnnnnnnn nnnnnnnn - - c=constant k=key b=blockcount n=nonce - */ - - /** h[12] remains 0 (offset) **/ - hs->h[13] = LOAD_U32_LITTLE(nonce + 0); - hs->h[14] = LOAD_U32_LITTLE(nonce + 4); - hs->h[15] = LOAD_U32_LITTLE(nonce + 8); - break; - } - case 16: { - /* - cccccccc cccccccc cccccccc cccccccc - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk - nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn - - c=constant k=key n=nonce - */ - - hs->h[12] = LOAD_U32_LITTLE(nonce + 0); - hs->h[13] = LOAD_U32_LITTLE(nonce + 4); - hs->h[14] = LOAD_U32_LITTLE(nonce + 8); - hs->h[15] = LOAD_U32_LITTLE(nonce + 12); - break; - } - default: - return ERR_NONCE_SIZE; - } - - hs->nonceSize = nonceSize; - hs->usedKeyStream = sizeof hs->keyStream; - - return 0; -} - -EXPORT_SYM int chacha20_destroy(stream_state *state) -{ - if (NULL == state) - return ERR_NULL; - free(state); - return 0; -} - -static int chacha20_core(stream_state *state, uint32_t h[16]) -{ - unsigned i; - - memcpy(h, state->h, sizeof state->h); - - for (i=0; i<10; i++) { - /** Column round **/ - QR(h[0], h[4], h[ 8], h[12]); - QR(h[1], h[5], h[ 9], h[13]); - QR(h[2], h[6], h[10], h[14]); - QR(h[3], h[7], h[11], h[15]); - /** Diagonal round **/ - QR(h[0], h[5], h[10], h[15]); - QR(h[1], h[6], h[11], h[12]); - QR(h[2], h[7], h[ 8], h[13]); - QR(h[3], h[4], h[ 9], h[14]); - } - - for (i=0; i<16; i++) { - uint32_t sum; - - sum = h[i] + state->h[i]; - STORE_U32_LITTLE(state->keyStream + 4*i, sum); - } - - state->usedKeyStream = 0; - - switch (state->nonceSize) { - case 8: { - /** Nonce is 64 bits, counter is two words **/ - if (++state->h[12] == 0) { - if (++state->h[13] == 0) { - return ERR_MAX_DATA; - } - } - break; - } - case 12: { - /** Nonce is 96 bits, counter is one word **/ - if (++state->h[12] == 0) { - return ERR_MAX_DATA; - } - break; - } - case 16: { - /** Nonce is 192 bits, there is no counter as this is intended - * to be run once only (HChaCha20) **/ - break; - } - } - - return 0; -} - -EXPORT_SYM int chacha20_encrypt(stream_state *state, - const uint8_t in[], - uint8_t out[], - size_t len) -{ - if (NULL == state || NULL == in || NULL == out) - return ERR_NULL; - - if ((state->nonceSize != 8) && (state->nonceSize != 12)) - return ERR_NONCE_SIZE; - - while (len>0) { - unsigned keyStreamToUse; - unsigned i; - uint32_t h[16]; - - if (state->usedKeyStream == sizeof state->keyStream) { - int result; - - result = chacha20_core(state, h); - if (result) - return result; - } - - keyStreamToUse = (unsigned)MIN(len, sizeof state->keyStream - state->usedKeyStream); - for (i=0; ikeyStream[i + state->usedKeyStream]; - - len -= keyStreamToUse; - state->usedKeyStream += keyStreamToUse; - } - - return 0; -} - -EXPORT_SYM int chacha20_seek(stream_state *state, - unsigned long block_high, - unsigned long block_low, - unsigned offset) -{ - int result; - uint32_t h[16]; - - if (NULL == state) - return ERR_NULL; - - if ((state->nonceSize != 8) && (state->nonceSize != 12)) - return ERR_NONCE_SIZE; - - if (offset >= sizeof state->keyStream) - return ERR_MAX_OFFSET; - - if (state->nonceSize == 8) { - /** Nonce is 64 bits, counter is two words **/ - state->h[12] = (uint32_t)block_low; - state->h[13] = (uint32_t)block_high; - } else { - /** Nonce is 96 bits, counter is one word **/ - if (block_high > 0) { - return ERR_MAX_OFFSET; - } - state->h[12] = (uint32_t)block_low; - } - - result = chacha20_core(state, h); - if (result) - return result; - - state->usedKeyStream = offset; - - return 0; -} - -/* - * Based on https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - */ -EXPORT_SYM int hchacha20(const uint8_t key[KEY_SIZE], - const uint8_t nonce16[16], /* First 16 bytes of the 24 byte nonce */ - uint8_t subkey[KEY_SIZE]) -{ - stream_state *pState; - uint32_t h[16]; - - if (NULL == key || NULL == nonce16 || NULL == subkey) { - return ERR_NULL; - } - - chacha20_init(&pState, key, KEY_SIZE, nonce16, 16); - if (NULL == pState) - return ERR_MEMORY; - - chacha20_core(pState, h); - /* We only keep first and last row from the new state */ - STORE_U32_LITTLE(subkey + 0, h[0]); - STORE_U32_LITTLE(subkey + 4, h[1]); - STORE_U32_LITTLE(subkey + 8, h[2]); - STORE_U32_LITTLE(subkey + 12, h[3]); - STORE_U32_LITTLE(subkey + 16, h[12]); - STORE_U32_LITTLE(subkey + 20, h[13]); - STORE_U32_LITTLE(subkey + 24, h[14]); - STORE_U32_LITTLE(subkey + 28, h[15]); - chacha20_destroy(pState); - - return 0; -} - -#ifdef PROFILE -int main(void) -{ - const unsigned data_size = 1024*1024; - const uint8_t key[32] = "12345678901234561234567890123456"; - const uint8_t nonce[8] = "12345678"; - stream_state *state; - uint8_t *data; - - data = malloc(data_size); - for (int i=0; i