VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/GfMul.h
blob: bc1ab43561dd3b6e2d3c7d8e5eecd049ff3dd471 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 ---------------------------------------------------------------------------
 Copyright (c) 2003, Dr Brian Gladman, Worcester, UK.   All rights reserved.

 LICENSE TERMS

 The free distribution and use of this software is allowed (with or without
 changes) provided that:

  1. source code distributions include the above copyright notice, this
     list of conditions and the following disclaimer;

  2. binary distributions include the above copyright notice, this list
     of conditions and the following disclaimer in their documentation;

  3. the name of the copyright holder is not used to endorse products
     built using this software without specific written permission.

 DISCLAIMER

 This software is provided 'as is' with no explicit or implied warranties
 in respect of its properties, including, but not limited to, correctness
 and/or fitness for purpose.
 ---------------------------------------------------------------------------
 Issue Date: 31/01/2004
*/

/* Adapted for TrueCrypt */

#ifndef _GCM_H
#define _GCM_H

#include "Tcdefs.h"

#if defined(__cplusplus)
extern "C"
{
#endif

#define CBLK_LEN   16  /* encryption block length */
#define CBLK_LEN8  8

typedef struct
{
    unsigned __int32 gf_t8k[CBLK_LEN * 2][16][CBLK_LEN / 4];
} GfCtx8k;

typedef struct
{
		unsigned __int32 gf_t4k[CBLK_LEN8 * 2][16][CBLK_LEN / 4];
} GfCtx4k64;

typedef struct
{
	/* union not used to support faster mounting */
    unsigned __int32 gf_t128[CBLK_LEN * 2 / 2][16][CBLK_LEN / 4];
    unsigned __int32 gf_t64[CBLK_LEN8 * 2][16][CBLK_LEN8 / 4];
} GfCtx;

typedef int  ret_type;

void GfMul128 (void *a, const void* b);
void GfMul128Tab(unsigned char a[16], GfCtx8k *ctx);
int Gf128Tab64Init (unsigned __int8 *a, GfCtx *ctx);
void Gf128MulBy64Tab (unsigned __int8 a[8], unsigned __int8 p[16], GfCtx *ctx);
void MirrorBits128 (unsigned __int8 *a);
void MirrorBits64 (unsigned __int8 *a);
BOOL GfMulSelfTest ();

#if defined(__cplusplus)
}
#endif

#endif
(DCS), Alex Kolotnikov This program and the accompanying materials are licensed and made available under the terms and conditions of the Apache License, Version 2.0. The full text of the license may be found at https://opensource.org/licenses/Apache-2.0 Dynamic SBOX idea is from GostCrypt project. Copyright (c) 2008-2011 TrueCrypt Developers Association **/ #include "GostCipher.h" #include "Streebog.h" #include "common\Tcdefs.h" #include "cpu.h" #if defined(CIPHER_GOST89) // Crypto Pro byte S_CryptoPro[8][16] = { {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC}, {0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB}, {0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3}, {0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5}, {0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3}, {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD}, {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8}, {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF} }; // TC26 byte S_TC26[8][16] = { { 0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1 }, { 0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf }, { 0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0 }, { 0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb }, { 0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc }, { 0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0 }, { 0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7 }, { 0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2 }, }; void gost_prepare_kds(gost_kds* kds) { uint32 i; // Build substitution tables. for (i = 0; i < 256; ++i) { uint32 p; p = kds->sbox[7][i >> 4] << 4 | kds->sbox[6][i & 15]; p = p << 24; p = p << 11 | p >> 21; kds->sbox_cvt[i] = p; // S87 p = kds->sbox[5][i >> 4] << 4 | kds->sbox[4][i & 15]; p = p << 16; p = p << 11 | p >> 21; kds->sbox_cvt[256 + i] = p; // S65 p = kds->sbox[3][i >> 4] << 4 | kds->sbox[2][i & 15]; p = p << 8; p = p << 11 | p >> 21; kds->sbox_cvt[256 * 2 + i] = p; // S43 p = kds->sbox[1][i >> 4] << 4 | kds->sbox[0][i & 15]; p = p << 11 | p >> 21; kds->sbox_cvt[256 * 3 + i] = p; // S21 } } #ifdef GOST_DYNAMIC_SBOXES static void xor_s_box(byte s_box[8][16], byte *seed) { int i; for (i = 0; i < 16; i++) { s_box[0][i] ^= (seed[ (i * 4) + 0 ] ) & 0xF; s_box[1][i] ^= (seed[ (i * 4) + 0 ]>>4) & 0xF; s_box[2][i] ^= (seed[ (i * 4) + 1 ] ) & 0xF; s_box[3][i] ^= (seed[ (i * 4) + 1 ]>>4) & 0xF; s_box[4][i] ^= (seed[ (i * 4) + 2 ] ) & 0xF; s_box[5][i] ^= (seed[ (i * 4) + 2 ]>>4) & 0xF; s_box[6][i] ^= (seed[ (i * 4) + 3 ] ) & 0xF; s_box[7][i] ^= (seed[ (i * 4) + 3 ]>>4) & 0xF; } } #endif void gost_set_key(const byte *key, gost_kds *ks) { #ifdef GOST_DYNAMIC_SBOXES STREEBOG_CTX sctx; byte sbox_seed[64]; #if defined (DEVICE_DRIVER) && !defined (_WIN64) KFLOATING_SAVE floatingPointState; NTSTATUS saveStatus = STATUS_SUCCESS; if (HasSSE2() || HasSSE41()) saveStatus = KeSaveFloatingPointState (&floatingPointState); #endif #endif memcpy(ks->key, key, GOST_KEYSIZE); memcpy(ks->sbox, S_TC26, sizeof(ks->sbox)); #ifdef GOST_DYNAMIC_SBOXES //Generate pseudorandom data based on the key STREEBOG_init(&sctx); STREEBOG_add(&sctx, key, 32); STREEBOG_finalize(&sctx, sbox_seed); #if defined (DEVICE_DRIVER) && !defined (_WIN64) if (NT_SUCCESS (saveStatus) && (HasSSE2() || HasSSE41())) KeRestoreFloatingPointState (&floatingPointState); #endif xor_s_box(ks->sbox, sbox_seed); #endif gost_prepare_kds(ks); } static uint32 f(uint32 v, uint32* sbox){ byte* x =(byte*) &v; /* Do substitutions */ return sbox[x[3]] | sbox[256 + x[2]] | sbox[256*2 + x[1]] | sbox[256*3 + x[0]]; } void gost_encrypt_block(uint64 in_, uint64* out_, gost_kds* kds) { uint32* in = (uint32*)&in_; uint32* out = (uint32*)out_; uint32* key = (uint32*)kds->key; uint32* sbox = kds->sbox_cvt; // As named in the GOST uint32 n1 = in[0]; uint32 n2 = in[1]; n2 ^= f(n1+key[0], sbox); n1 ^= f(n2+key[1], sbox); n2 ^= f(n1+key[2], sbox); n1 ^= f(n2+key[3], sbox); n2 ^= f(n1+key[4], sbox); n1 ^= f(n2+key[5], sbox); n2 ^= f(n1+key[6], sbox); n1 ^= f(n2+key[7], sbox); n2 ^= f(n1+key[0], sbox); n1 ^= f(n2+key[1], sbox); n2 ^= f(n1+key[2], sbox); n1 ^= f(n2+key[3], sbox); n2 ^= f(n1+key[4], sbox); n1 ^= f(n2+key[5], sbox); n2 ^= f(n1+key[6], sbox); n1 ^= f(n2+key[7], sbox); n2 ^= f(n1+key[0], sbox); n1 ^= f(n2+key[1], sbox); n2 ^= f(n1+key[2], sbox); n1 ^= f(n2+key[3], sbox); n2 ^= f(n1+key[4], sbox); n1 ^= f(n2+key[5], sbox); n2 ^= f(n1+key[6], sbox); n1 ^= f(n2+key[7], sbox); n2 ^= f(n1+key[7], sbox); n1 ^= f(n2+key[6], sbox); n2 ^= f(n1+key[5], sbox); n1 ^= f(n2+key[4], sbox); n2 ^= f(n1+key[3], sbox); n1 ^= f(n2+key[2], sbox); n2 ^= f(n1+key[1], sbox); n1 ^= f(n2+key[0], sbox); // There is no swap after the last round out[0] = n2; out[1] = n1; } void gost_decrypt_block(uint64 in_, uint64* out_, gost_kds* kds) { uint32* in = (uint32*)&in_; uint32* out = (uint32*)out_; uint32* key = (uint32*)kds->key; uint32* sbox = kds->sbox_cvt; // As named in the GOST uint32 n1 = in[0]; uint32 n2 = in[1]; n2 ^= f(n1+key[0], sbox); n1 ^= f(n2+key[1], sbox); n2 ^= f(n1+key[2], sbox); n1 ^= f(n2+key[3], sbox); n2 ^= f(n1+key[4], sbox); n1 ^= f(n2+key[5], sbox); n2 ^= f(n1+key[6], sbox); n1 ^= f(n2+key[7], sbox); n2 ^= f(n1+key[7], sbox); n1 ^= f(n2+key[6], sbox); n2 ^= f(n1+key[5], sbox); n1 ^= f(n2+key[4], sbox); n2 ^= f(n1+key[3], sbox); n1 ^= f(n2+key[2], sbox); n2 ^= f(n1+key[1], sbox); n1 ^= f(n2+key[0], sbox); n2 ^= f(n1+key[7], sbox); n1 ^= f(n2+key[6], sbox); n2 ^= f(n1+key[5], sbox); n1 ^= f(n2+key[4], sbox); n2 ^= f(n1+key[3], sbox); n1 ^= f(n2+key[2], sbox); n2 ^= f(n1+key[1], sbox); n1 ^= f(n2+key[0], sbox); n2 ^= f(n1+key[7], sbox); n1 ^= f(n2+key[6], sbox); n2 ^= f(n1+key[5], sbox); n1 ^= f(n2+key[4], sbox); n2 ^= f(n1+key[3], sbox); n1 ^= f(n2+key[2], sbox); n2 ^= f(n1+key[1], sbox); n1 ^= f(n2+key[0], sbox); out[0] = n2; out[1] = n1; } #if defined(_M_AMD64) void gost_encrypt_128_CBC_asm(const byte *in, byte *out, gost_kds *ks, uint64 count); void gost_decrypt_128_CBC_asm(const byte *in, byte *out, gost_kds *ks, uint64 count); #endif void gost_encrypt(const byte *in, byte *out, gost_kds *ks, int count) { #if defined(_M_AMD64) gost_encrypt_128_CBC_asm(in, out, ks, (uint64)count); #else while (count > 0) { // encrypt two blocks in CBC mode gost_encrypt_block(*((uint64*)in), (uint64*)out, ks); *((gst_udword*)(out + 8)) = *((gst_udword*)(in + 8)) ^ *((gst_udword*)(out)); *((gst_udword*)(out + 12)) = *((gst_udword*)(in + 12)) ^ *((gst_udword*)(out + 4)); gost_encrypt_block(*((uint64*)(out + 8)), (uint64*)(out + 8), ks); count--; in += 16; out += 16; } #endif } void gost_decrypt(const byte *in, byte *out, gost_kds *ks, int count) { #if defined(_M_AMD64) gost_decrypt_128_CBC_asm(in, out, ks, (uint64)count); #else while (count > 0) { // decrypt two blocks in CBC mode gost_decrypt_block(*((uint64*)(in + 8)), (uint64*)(out + 8), ks); *((gst_udword*)(out + 8)) ^= *((gst_udword*)(in));; *((gst_udword*)(out + 12)) ^= *((gst_udword*)(in + 4));; gost_decrypt_block(*((uint64*)(in)), (uint64*)(out), ks); count--; in += 16; out += 16; } #endif } #endif