1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00
trezor-firmware/crypto/aes/gf128mul.h

216 lines
6.7 KiB
C
Raw Permalink Normal View History

/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 11/01/2011
I am grateful for the work done by Mark Rodenkirch and Jason Papadopoulos
in helping to remove a bug in the operation of this code on big endian
systems when fast buffer operations are enabled.
---------------------------------------------------------------------------
An implementation of field multiplication in the Galois Field GF(2^128)
A polynomial representation is used for the field with the coefficients
held in bit sequences in which the bit numbers are the powers of x that
a bit represents. The field polynomial used is (x^128+x^7+x^2+x+1).
The obvious way of representing field elements in a computer system is
to map 'x' in the field to the binary integer '2'. But this was way too
obvious for cryptographers!
Here bytes are numbered in their memory order and bits within bytes are
numbered according to their integer numeric significance (that is as is
now normal with bit 0 representing unity). The term 'little endian'
will then used to describe mappings where numeric (power of 2) or field
(power of x) significance increases with increasing bit or byte numbers
with 'big endian' being used to describe the inverse situation.
The GF bit sequence can then be mapped onto 8-bit bytes in computer
memory in one of four simple ways:
A mapping in which x maps to the integer 2 in little endian
form for both bytes and bits within bytes:
LL: bit for x^n ==> bit for 2^(n % 8) in byte[n / 8]
A mapping in which x maps to the integer 2 in big endian form
for both bytes and bits within bytes:
BL: bit for x^n ==> bit for 2^(n % 8) in byte[15 - n / 8]
A little endian mapping for bytes but with the bits within
bytes in reverse order (big endian bytes):
LB: bit for x^n ==> bit for 2^(7 - n % 8) in byte[n / 8]
A big endian mapping for bytes but with the bits within
bytes in reverse order (big endian bytes):
BB: bit for x^n ==> bit for 2^(7 - n % 8) in byte[15 - n / 8]
128-bit field elements are represented by 16 byte buffers but for
processing efficiency reasons it is often desirable to process arrays
of bytes using longer types such as, for example, unsigned long values.
The type used for representing these buffers will be called a 'gf_unit'
and the buffer itself will be referred to as a 'gf_t' type.
THe field multiplier is based on the assumption that one of the two
field elements involved in multiplication will change only relatively
infrequently, making it worthwhile to precompute tables to speed up
multiplication by this value.
*/
#ifndef _GF128MUL_H
#define _GF128MUL_H
#include <stdlib.h>
#include <string.h>
#include "brg_endian.h"
/* USER DEFINABLE OPTIONS */
/* UNIT_BITS sets the size of variables used to process 16 byte buffers
when the buffer alignment allows this. When buffers are processed
in bytes, 16 individual operations are invoolved. But if, say, such
a buffer is divided into 4 32 bit variables, it can then be processed
in 4 operations, making the code typically much faster. In general
it will pay to use the longest natively supported size, which will
probably be 32 or 64 bits in 32 and 64 bit systems respectively.
*/
#if defined( UNIT_BITS )
# undef UNIT_BITS
#endif
#if !defined( UNIT_BITS )
# if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN
# if 0
# define UNIT_BITS 8
# elif 0
# define UNIT_BITS 32
# elif 1
# define UNIT_BITS 64
# endif
# elif defined( _WIN64 )
# define UNIT_BITS 64
# else
# define UNIT_BITS 32
# endif
#endif
#if UNIT_BITS == 64 && !defined( NEED_UINT_64T )
# define NEED_UINT_64T
#endif
#include "mode_hdr.h"
/* Choose the Galois Field representation to use (see above) */
#if 0
# define GF_MODE_LL
#elif 0
# define GF_MODE_BL
#elif 1
# define GF_MODE_LB /* the representation used by GCM */
#elif 0
# define GF_MODE_BB
#else
# error mode is not defined
#endif
/* Table sizes for GF(128) Multiply. Normally larger tables give
higher speed but cache loading might change this. Normally only
one table size (or none at all) will be specified here
*/
#if 0
# define TABLES_64K
#endif
#if 0
# define TABLES_8K
#endif
#if 0
# define TABLES_4K
#endif
#if 0
# define TABLES_256
#endif
/* END OF USER DEFINABLE OPTIONS */
#if !(defined( TABLES_64K ) || defined( TABLES_8K ) \
|| defined( TABLES_4K ) || defined( TABLES_256 ))
# define NO_TABLES
#endif
#if defined(__cplusplus)
extern "C"
{
#endif
#define GF_BYTE_LEN 16
#define GF_UNIT_LEN (GF_BYTE_LEN / (UNIT_BITS >> 3))
UNIT_TYPEDEF(gf_unit_t, UNIT_BITS);
BUFR_TYPEDEF(gf_t, UNIT_BITS, GF_BYTE_LEN);
/* Code for conversion between the four different galois field representations
is optionally available using gf_convert.c
*/
typedef enum { REVERSE_NONE = 0, REVERSE_BITS = 1, REVERSE_BYTES = 2 } transform;
void convert_representation(gf_t dest, const gf_t source, transform rev);
void gf_mul(gf_t a, const gf_t b); /* slow field multiply */
/* types and calls for 64k table driven field multiplier */
typedef gf_t gf_t64k_a[16][256];
typedef gf_t (*gf_t64k_t)[256];
void init_64k_table(const gf_t g, gf_t64k_t t);
void gf_mul_64k(gf_t a, const gf_t64k_t t, void *r);
/* types and calls for 8k table driven field multiplier */
typedef gf_t gf_t8k_a[32][16];
typedef gf_t (*gf_t8k_t)[16];
void init_8k_table(const gf_t g, gf_t8k_t t);
void gf_mul_8k(gf_t a, const gf_t8k_t t, gf_t r);
/* types and calls for 8k table driven field multiplier */
typedef gf_t gf_t4k_a[256];
typedef gf_t (*gf_t4k_t);
void init_4k_table(const gf_t g, gf_t4k_t t);
void gf_mul_4k(gf_t a, const gf_t4k_t t, gf_t r);
/* types and calls for 8k table driven field multiplier */
typedef gf_t gf_t256_a[16];
typedef gf_t (*gf_t256_t);
void init_256_table(const gf_t g, gf_t256_t t);
void gf_mul_256(gf_t a, const gf_t256_t t, gf_t r);
#if defined(__cplusplus)
}
#endif
#endif