Commit fec49ddc authored by David McGrew's avatar David McGrew

continuing merge from jesup, several minor fixes

parent 28b59156
/*
*
* Copyright (c) 2001-2003 Cisco Systems, Inc.
* Copyright (c) 2001-2005 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -70,6 +70,10 @@ kernel = crypto/kernel/crypto_kernel.o crypto/kernel/alloc.o \
cryptobj = $(ciphers) $(hashes) $(math) $(stat) $(kernel) $(replay)
aesicm = crypto/cipher/cipher.o crypto/cipher/aes.o crypto/cipher/aes_icm.o \
crypto/hash/auth.o crypto/kernel/alloc.o crypto/kernel/err.o \
crypto/math/datatypes.o crypto/replay/rdbx.o
aesicmobj = $(aesicm) $(rng)
# gdoi is the group domain of interpretation for isakmp, a group key
......@@ -176,7 +180,7 @@ install:
uninstall:
rm -rf /usr/local/include/srtp
rm -rf /usr/local/lib/libsrtp.a
if [ -f libaesicm.a ]; then rm -rf /usr/local/lib/libaesicm.a; fi
rm -rf /usr/local/lib/libaesicm.a
clean:
rm -rf $(cryptobj) $(srtpobj) $(cryptomath) $(table_apps) TAGS \
......
TODO List
1.4.1
- document which fields are in NBO/HBO, and check for consistency.
- move HAVE_U_LONG_LONG inside of datatypes.c, or some other
separate file
- re-write configure.in to make cross-compilation easier
- eliminate GENERIC_AESICM by generalizing the code a bit
Older comments
- add tests for key_limit_t datatype
- move octet_get_weight() from datatypes.c to math.c (any other
......@@ -10,11 +23,6 @@ Changes and additions planned
Make cipher and auth dealloc() functions zeroize the key-storage
areas before calling free().
Fix UST
- implement scatter/gather API
- SRTP using UST
- possibly add legacy SHA1 usage
Eliminate key_len from auth_init()
Doucument internal APIs (cipher, auth, srtp_protect, ...)
......@@ -23,18 +31,13 @@ Changes and additions planned
SRTP options not (yet) included in this libaray:
- the aes-f8-mode cipher
- HMAC-SHA-1
- the Master Key Index
- re-keying using the key derivation function (only the initial
use of the PRF has been implemented, as it's sufficient
for most uses)
INCOMPLETE ADDITIONS
Added DES and 3DES ICM.
PLANNED CHANGES
(OLD) PLANNED CHANGES
strip out test/lfsr.c
......@@ -61,6 +64,3 @@ PLANNED CHANGES
Consider eliminating low-level alloc functions in favor of len()
functions, so that there need not be multiple allocations within a
particular alloc() function.
Update test/stat-driver.c so that it tests the rand_source API.
Add a pseudorandom rand_source.
/*
* config_in.h
*
* template for header config file for Secure RTP and UST implementation
* template for header config file for Secure RTP and libcryptomodule
*
* David A. McGrew
* Cisco Systems, Inc.
......@@ -21,6 +21,10 @@
#define HAVE_MACHINE_TYPES_H 0
#define HAVE_SYS_INT_TYPES_H 0
/* check if an unsigned 64-bit integer is supported natively */
#define HAVE_U_LONG_LONG 0
/* check for microsoft integer definitions (e.g., cygwin) */
#define HAVE_MS_TYPES 1
......@@ -82,15 +86,15 @@
#define CPU_ALTIVEC 0
/*
* if /dev/random is available, then DEV_RANDOM == 1
* if /dev/urandom is available, then DEV_URANDOM == 1
*
* /dev/random is a (true) random number generator which is
* /dev/urandom is a (true) random number generator which is
* implemented in many modern operating systems
*/
#define DEV_RANDOM 0
#define DEV_URANDOM 0
/* check for stdlib.h - we use it for xalloc() and free() */
/* check for stdlib.h - we use it for alloc() and free() */
#define HAVE_STDLIB_H 0
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -30,7 +30,13 @@ AC_CHECK_HEADERS(sys/int_types.h)
AC_CHECK_HEADERS(syslog.h)
AC_CHECK_TYPE(uint16_t)
AC_CHECK_TYPES([int8,uint8,int16,uint16,int32,uint32,unit64])
AC_CHECK_TYPE(unsigned long long, HAVE_U_LONG_LONG=1, HAVE_U_LONG_LONG=0)
if test $HAVE_U_LONG_LONG = 1; then
AC_DEFINE(HAVE_U_LONG_LONG)
fi
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
......@@ -108,7 +114,7 @@ if test $GDOI = 1; then
AC_SUBST(GDOI_OBJS)
fi
AC_CONFIG_HEADER(include/config.h:config_in.h)
AC_CONFIG_HEADER(crypto/include/config.h:config_in.h)
AC_OUTPUT(Makefile)
......
# Makefile for libcryptokernel.a
# Makefile for libcryptomodule.a
#
# David A. McGrew
# Cisco Systems, Inc.
......@@ -27,6 +27,7 @@ p=00112233445566778899aabbccddeeff
c=69c4e0d86a7b0430d8cdb78070b4c55a
runtest: $(testapp)
test/env # print out information on the build environment
@echo "running libcryptomodule test applications..."
test `test/aes_calc $k $p` = $c
test/cipher_driver -v >/dev/null
......@@ -85,7 +86,7 @@ libcryptomodule.a: $(cryptobj)
testapp = test/cipher_driver test/datatypes_driver \
test/stat_driver test/sha1_driver test/kernel_driver \
test/aes_calc test/rand_gen
test/aes_calc test/rand_gen test/env
all: libcryptomodule.a $(testapp)
......
This diff is collapsed.
......@@ -220,13 +220,13 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c,
debug_print(mod_aes_cbc, "iv: %s",
v128_hex_string(&previous));
/*
* loop over ciphertext blocks, decrypting then exoring with state
* then writing plaintext to output
*/
while (bytes_to_encr > 0) {
/* set state to ciphertext input block */
for (i=0; i < 16; i++) {
state.octet[i] = *input++;
......@@ -234,7 +234,7 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c,
debug_print(mod_aes_cbc, "inblock: %s",
v128_hex_string(&state));
/* decrypt state */
aes_decrypt(&state, c->expanded_key);
......@@ -268,7 +268,7 @@ aes_cbc_nist_encrypt(aes_cbc_ctx_t *c,
int num_pad_bytes;
err_status_t status;
/*
/*
* determine the number of padding bytes that we need to add -
* this value is always between 1 and 16, inclusive.
*/
......@@ -320,7 +320,7 @@ aes_cbc_nist_decrypt(aes_cbc_ctx_t *c,
pad_end--;
num_pad_bytes++;
}
/* decrement data size */
*bytes_in_data -= num_pad_bytes;
......
......@@ -198,13 +198,27 @@ err_status_t
aes_icm_set_octet(aes_icm_ctx_t *c,
uint64_t octet_num) {
#if (HAVE_U_LONG_LONG == 0)
int tail_num = low32(octet_num) & 0x0f;
/* 64-bit right-shift 4 */
uint64_t block_num = make64(high32(octet_num) >> 4,
((high32(octet_num) & 0x0f)<<(32-4)) |
(low32(octet_num) >> 4));
#else
int tail_num = octet_num % 16;
uint64_t block_num = octet_num / 16;
#endif
/* set counter value */
/* FIX - There's no way this is correct */
c->counter.v64[0] = c->offset.v64[0];
#if (HAVE_U_LONG_LONG == 0)
c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
low32(c->offset.v64[0]) ^ low32(block_num));
#else
c->counter.v64[0] = c->offset.v64[0] ^ block_num;
#endif
debug_print(mod_aes_icm,
"set_octet: %s", v128_hex_string(&c->counter));
......@@ -213,7 +227,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c,
if (tail_num) {
v128_copy(&c->keystream_buffer, &c->counter);
aes_encrypt(&c->keystream_buffer, c->expanded_key);
c->bytes_in_buffer = 16;
c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s",
v128_hex_string(&c->counter));
......@@ -274,7 +288,7 @@ aes_icm_advance(aes_icm_ctx_t *c) {
/* fill buffer with new keystream */
v128_copy(&c->keystream_buffer, &c->counter);
aes_encrypt(&c->keystream_buffer, c->expanded_key);
c->bytes_in_buffer = 16;
c->bytes_in_buffer = sizeof(v128_t);
debug_print(mod_aes_icm, "counter: %s",
v128_hex_string(&c->counter));
......@@ -323,9 +337,11 @@ aes_icm_encrypt(aes_icm_ctx_t *c,
if (bytes_to_encr <= c->bytes_in_buffer) {
/* deal with odd case of small bytes_to_encr */
for (i = (16 - c->bytes_in_buffer);
i < (16 - c->bytes_in_buffer + bytes_to_encr); i++)
for (i = (sizeof(v128_t) - c->bytes_in_buffer);
i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
{
*buf++ ^= c->keystream_buffer.octet[i];
}
c->bytes_in_buffer -= bytes_to_encr;
......@@ -335,7 +351,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c,
} else {
/* encrypt bytes until the remaining data is 16-byte aligned */
for (i=(16 - c->bytes_in_buffer); i < 16; i++)
for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
*buf++ ^= c->keystream_buffer.octet[i];
bytes_to_encr -= c->bytes_in_buffer;
......@@ -344,7 +360,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c,
}
/* now loop over entire 16-byte blocks of keystream */
for (i=0; i < (bytes_to_encr/16); i++) {
for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
/* fill buffer with new keystream */
aes_icm_advance(c);
......@@ -401,7 +417,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c,
*buf++ ^= c->keystream_buffer.octet[i];
/* reset the keystream buffer size to right value */
c->bytes_in_buffer = 16 - i;
c->bytes_in_buffer = sizeof(v128_t) - i;
} else {
/* no tail, so just reset the keystream buffer size to zero */
......@@ -464,7 +480,7 @@ cipher_test_case_t aes_icm_test_case_0 = {
NULL /* pointer to next testcase */
};
/*
* note: the encrypt function is identical to the decrypt function
*/
......
......@@ -93,7 +93,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
debug_print(mod_cipher, "running self-test for cipher %s",
ct->description);
/*
* check to make sure that we have at least one test case, and
* return an error if we don't - we need to be paranoid here
......@@ -123,7 +123,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
cipher_dealloc(c);
return status;
}
/* copy plaintext into test buffer */
if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
cipher_dealloc(c);
......@@ -178,7 +178,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
cipher_dealloc(c);
return err_status_algo_fail;
}
/*
* test the decrypt function
*/
......@@ -257,7 +257,7 @@ cipher_type_self_test(const cipher_type_t *ct) {
test_case = test_case->next_test_case;
++case_num;
}
/* now run some random invertibility tests */
/* allocate cipher, using paramaters from the first test case */
......@@ -269,7 +269,8 @@ cipher_type_self_test(const cipher_type_t *ct) {
rand_source_init();
for (j=0; j < NUM_RAND_TESTS; j++) {
int length, plaintext_len;
unsigned length;
int plaintext_len;
octet_t key[MAX_KEY_LEN];
octet_t iv[MAX_KEY_LEN];
......
......@@ -171,7 +171,7 @@ hmac_update(hmac_ctx_t *state, const octet_t *message, int msg_octets) {
}
err_status_t
hmac_compute(hmac_ctx_t *state, const octet_t *message,
hmac_compute(hmac_ctx_t *state, const void *message,
int msg_octets, int tag_len, octet_t *result) {
uint32_t hash_value[5];
uint32_t H[5];
......
......@@ -69,14 +69,6 @@ aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key);
void
aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key);
/*
* gf2_8_shift(x) returns the next gf2_8 value in the cyclic
* representation of that field
*/
gf2_8
gf2_8_shift(octet_t input);
#if 0
/*
* internal functions
......
......@@ -18,8 +18,8 @@ typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
v128_t keystream_buffer; /* buffers bytes of keystream */
int bytes_in_buffer; /* number of unused bytes in buffer */
aes_expanded_key_t expanded_key; /* the cipher key */
int bytes_in_buffer; /* number of unused bytes in buffer */
} aes_icm_ctx_t;
......
/* include/config.h. Generated automatically by configure. */
/* crypto/include/config.h. Generated by configure. */
/*
* config.h
* config_in.h
*
* template for header config file for Secure RTP and UST implementation
* template for header config file for Secure RTP and libcryptomodule
*
* David A. McGrew
* Cisco Systems, Inc.
......@@ -14,38 +14,37 @@
/* if we're on a big endian machine, we need to define this */
#include <sys/types.h>
#if (BYTE_ORDER == BIG_ENDIAN)
#define WORDS_BIGENDIAN 1
#else
#define WORDS_BIGENDIAN 0
#endif
#define WORDS_BIGENDIAN 1
/* check for <stdint.h> or <machine/types.h> */
#define HAVE_STDINT_H 1
#define HAVE_STDINT_H 1
#define HAVE_MACHINE_TYPES_H 1
#define HAVE_SYS_INT_TYPES_H 0
/* check if an unsigned 64-bit integer is supported natively */
#define HAVE_U_LONG_LONG 1
/* check for microsoft integer definitions (e.g., cygwin) */
#define HAVE_MS_TYPES 1
/* if we don't have uio.h, we'll need to define struct iovec */
#define HAVE_SYS_UIO_H 1
#define HAVE_SYS_UIO_H 1
/* <unistd.h> is used by some test/ apps */
#define HAVE_UNISTD_H 1
#define HAVE_UNISTD_H 1
/* test apps should use inet_aton(), if it's available */
#define HAVE_INET_ATON 1
#define HAVE_INET_ATON 1
/* check if we have syslog functions */
#define HAVE_SYSLOG_H 1
#define HAVE_SYSLOG_H 1
/* check to see if the user has requested the use of syslog */
......@@ -57,15 +56,15 @@
/* define ERR_REPORTING_FILE to have messages sent to file */
#define ERR_REPORTING_FILE
#define ERR_REPORTING_FILE
/*
/*
* set ENABLE_DEBUGGING to 1 to compile in dynamic debugging system,
* set it to 0 to not compile in dynamic debugging (for a slight
* performance improvement)
*/
#define ENABLE_DEBUGGING 1
#define ENABLE_DEBUGGING 1
/* if we're going to use GDOI, define SRTP_GDOI to 1 */
......@@ -76,44 +75,33 @@
* Note that more than one type can be defined at once; this is so
* that special instructions and other optimizations can be handled
* independently.
*
*
* CPU_RISC RISC machines (assume slow byte access)
* CPU_CISC CISC machines (e.g. Intel)
*
*/
#if WORDS_BIGENDIAN
#define CPU_RISC 1
#else
#define CPU_CISC 1
#endif
/*
* define CPU_16 if cryptoalgorithms should use 16-bit operations -
* this is probably only the case on very low-end devices
* CPU_ALTIVEC Motorola's SIMD instruction set
*
*/
#define CPU_16 0
/*
* define CPU_ALTIVEC in order to use the G4/G5 processor's AltiVec
* SIMD instruction set where possible
*/
#define CPU_RISC 1
#define CPU_CISC 0
#define CPU_ALTIVEC 0
/*
* if /dev/random is available, then DEV_RANDOM == 1
* if /dev/urandom is available, then DEV_URANDOM == 1
*
* /dev/random is a (true) random number generator which is
* /dev/urandom is a (true) random number generator which is
* implemented in many modern operating systems
*/
#define DEV_RANDOM 0
#define DEV_URANDOM 1
/* check for stdlib.h - we use it for alloc() and free() */
#define HAVE_STDLIB_H 1
/* whether to use ismacryp code */
#define GENERIC_AESICM 1
#endif /* CONFIG_H */
......
......@@ -209,7 +209,7 @@ v128_right_shift(v128_t *x, int index);
(((x)->v64[0] == (y)->v64[0]) && ((x)->v64[1] == (y)->v64[1]))
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
#define _v128_xor_eq(z, x) \
( \
(z)->v32[0] ^= (x)->v32[0], \
......
......@@ -48,7 +48,9 @@
#include "config.h" /* check for ERR_REPORTING_SYSLOG */
#ifdef ERR_REPORTING_FILE
#include <stdio.h>
#endif
#include <stdarg.h>
......@@ -163,8 +165,8 @@ err_report(int priority, char *format, ...);
*/
typedef struct {
unsigned int on; /* 1 if debugging is on, 0 if it is off */
char *name; /* printable name for debug module */
int on; /* 1 if debugging is on, 0 if it is off */
char *name; /* printable name for debug module */
} debug_module_t;
#if ENABLE_DEBUGGING
......
......@@ -54,12 +54,18 @@ typedef octet_t gf2_8;
#define gf2_8_field_polynomial 0x1B
/*
* gf2_8_shift(x) returns the next gf2_8 value in the cyclic
* representation of that field
* gf2_8_shift(x) returns
*/
gf2_8
gf2_8_shift(octet_t input);
/*
* gf2_8_shift(z) returns the result of the GF(2^8) 'multiply by x'
* operation, using the field representation from AES; that is, the
* next gf2_8 value in the cyclic representation of that field. The
* value z should be an octet_t.
*/
#define gf2_8_shift(z) (((z) & 128) ? \
(((z) << 1) ^ gf2_8_field_polynomial) : ((z) << 1))
gf2_8
gf2_8_compute_inverse(gf2_8 x);
......
......@@ -70,7 +70,7 @@ err_status_t
hmac_update(hmac_ctx_t *state, const octet_t *message, int msg_octets);
err_status_t
hmac_compute(hmac_ctx_t *state, const octet_t *message,
hmac_compute(hmac_ctx_t *state, const void *message,
int msg_octets, int tag_len, octet_t *result);
......
......@@ -51,6 +51,10 @@
#include <stdlib.h> /* standard integers should be referenced here */
#ifndef HAVE_U_LONG_LONG
/* Used instead of #ifndef HAVE_UINT64 since we're going to define uint64_t */
#define NO_64BIT_MATH 1
#endif
/* use standard integer definitions, if they're available */
#if HAVE_STDINT_H
......@@ -74,7 +78,7 @@
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
typedef double uint64_t;
/* assert that sizeof(double) == 8 */
#else
......@@ -90,7 +94,7 @@ typedef unsigned long long int uint64_t;
typedef short int int16_t;
typedef int int32_t;
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
typedef double int64_t;
/* assert that sizeof(double) == 8 */
#else
......
......@@ -229,20 +229,32 @@ v128_right_shift(v128_t *x, int index);
(x)->v32[3] = ~(x)->v32[3] \
)
/* ok for NO_64BIT_MATH if it can compare uint64_t's (even as structures) */
#define _v128_is_eq(x, y) \
(((x)->v64[0] == (y)->v64[0]) && ((x)->v64[1] == (y)->v64[1]))
#if (HAVE_U_LONG_LONG == 0)
#define _v128_xor_eq(z, x) \
( \
(z)->v32[0] ^= (x)->v32[0], \
(z)->v32[1] ^= (x)->v32[1], \
(z)->v32[2] ^= (x)->v32[2], \
(z)->v32[3] ^= (x)->v32[3] \
)
#else
#define _v128_xor_eq(z, x) \
( \
(z)->v64[0] ^= (x)->v64[0], \
(z)->v64[1] ^= (x)->v64[1] \
)
#endif
#if 0
#define _v128_get_bit(x, bit) \
( \
(x->v32[3-((bit) >> 5)] >> ((bit) & 31)) & 1 \
(((x)->v32[3-((bit) >> 5)] >> ((bit) & 31)) & 1) \
)
#define _v128_set_bit(x, bit) \
......@@ -252,8 +264,9 @@ v128_right_shift(v128_t *x, int index);
#define _v128_clear_bit(x, bit) \
( \
(((x)->v32[(bit) >> 5]) &= ~((unsigned long)1 << ((bit) & 31))) \
(((x)->v32[3-((bit) >> 5])) &= ~((uint32_t)1 << ((bit) & 31))) \
)
#endif
#define _v128_set_bit_to(x, bit, value) \
( \
......@@ -287,6 +300,7 @@ v128_right_shift(v128_t *x, int index);
#endif /* OLD */
#if 0
#if WORDS_BIGENDIAN
#define _v128_add(z, x, y) { \
......@@ -327,7 +341,7 @@ v128_right_shift(v128_t *x, int index);
}
#endif /* WORDS_BIGENDIAN */
#endif
#ifdef DATATYPES_USE_MACROS /* little functions are really macros */
......
......@@ -48,7 +48,7 @@
err_status_t
key_limit_set(key_limit_t key, const xtd_seq_num_t s) {
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
if (high32(s) == 0 && low32(s) < soft_limit)
return err_status_bad_param;
#else
......@@ -77,7 +77,7 @@ key_limit_check(const key_limit_t key) {
key_event_t
key_limit_update(key_limit_t key) {
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
if (low32(key->num_left) == 0)
{
// carry
......@@ -101,7 +101,7 @@ key_limit_update(key_limit_t key) {
/* we just passed the soft limit, so change the state */
key->state = key_state_past_soft_limit;
}
#ifdef NO_64BIT_MATH
#if (HAVE_U_LONG_LONG == 0)
if (low32(key->num_left) == 0 && high32(key->num_left == 0))
#else
if (key->num_left < 1)
......
......@@ -413,25 +413,33 @@ octet_string_set_to_zero(octet_t *s, int len) {
inline uint32_t
bswap_32(uint32_t v) {
#ifdef WORDS_BIGENDIAN
/* assume that we're on a big-endian machine */
/* htonl() does nothing */
#else
#if CPU_CISC
#ifndef MIPSEL /* MIPSEL stands for MIPS Endian Little, but it's not x86,
* so ignore the assembly language */
/* assume that we're on an Intel x86 with x > 3 */
asm("bswap %0" : "=r" (v) : "0" (v));
#else
/* little-endian; we can use htonl() */
v = htonl(v);
#endif
#endif
/* assume that we're on a big-endian or non-intel machine */
return v;
}
inline uint64_t
bswap_64(uint64_t v) {
#ifdef WORDS_BIGENDIAN
/* assume that we're on a big-endian machine */
/* FIX? */
#else
#if CPU_CISC /* assume that we're on an Intel x86 with x > 3 */
#ifndef MIPSEL /* MIPSEL stands for MIPS Endian Little, but it's not x86,
* so ignore the assembly language */
v= (bswap_32(v >> 32)) | ((uint64_t)bswap_32((uint32_t)v)) << 32 ;
#else
v = make64(htonl(low32(v)),htonl(high32(v)));
#endif
#endif
#endif /* assume that we're on a big-endian or non-intel machine */
return v;
}
......
......@@ -48,18 +48,7 @@
#include "datatypes.h"
#include "gf2_8.h"
/*
* gf2_8_shift(x) returns the result of the GF(2^8) 'multiply by x'
* operation, using the field representation from AES.
*/
inline gf2_8
gf2_8_shift(gf2_8 input) {
if ((input & 128) == 0)
return input << 1;
else
return (input << 1) ^ gf2_8_field_polynomial;
}