Add crypto files

This commit is contained in:
Vadim Vetrov 2024-09-21 22:13:32 +03:00
parent 1a88bffbd9
commit eaf64db8c3
No known key found for this signature in database
GPG Key ID: E8A308689D7A73A5
26 changed files with 4607 additions and 10 deletions

2
Kbuild
View File

@ -1,3 +1,3 @@
obj-m := kyoutubeUnblock.o
kyoutubeUnblock-objs := kytunblock.o mangle.o quic.o utils.o kargs.o tls.o getopt.o args.o
ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement
ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement -I$(src)/include

47
crypto/aes-gcm.c Normal file
View File

@ -0,0 +1,47 @@
//
// aes-gcm.c
// Pods
//
// Created by Markus Kosmal on 20/11/14.
//
//
#include "crypto/aes-gcm.h"
#include "crypto/gcm.h"
int aes_gcm_encrypt(unsigned char* output, const unsigned char* input, int input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len){
int ret = 0; // our return value
gcm_context ctx; // includes the AES context structure
size_t tag_len = 0;
unsigned char * tag_buf = NULL;
gcm_setkey( &ctx, key, (const uint)key_len );
ret = gcm_crypt_and_tag( &ctx, ENCRYPT, iv, iv_len, NULL, 0,
input, output, input_length, tag_buf, tag_len);
gcm_zero_ctx( &ctx );
return( ret );
}
int aes_gcm_decrypt(unsigned char* output, const unsigned char* input, int input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len){
int ret = 0; // our return value
gcm_context ctx; // includes the AES context structure
size_t tag_len = 0;
unsigned char * tag_buf = NULL;
gcm_setkey( &ctx, key, (const uint)key_len );
ret = gcm_crypt_and_tag( &ctx, DECRYPT, iv, iv_len, NULL, 0,
input, output, input_length, tag_buf, tag_len);
gcm_zero_ctx( &ctx );
return( ret );
}

483
crypto/aes.c Normal file
View File

@ -0,0 +1,483 @@
/******************************************************************************
*
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
*
* This is a simple and straightforward implementation of the AES Rijndael
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
* of this work was correctness & accuracy. It is written in 'C' without any
* particular focus upon optimization or speed. It should be endian (memory
* byte order) neutral since the few places that care are handled explicitly.
*
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
*
* It is intended for general purpose use, but was written in support of GRC's
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
*
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
*
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
*
*******************************************************************************/
#include "crypto/aes.h"
static int aes_tables_inited = 0; // run-once flag for performing key
// expasion table generation (see below)
/*
* The following static local tables must be filled-in before the first use of
* the GCM or AES ciphers. They are used for the AES key expansion/scheduling
* and once built are read-only and thread safe. The "gcm_initialize" function
* must be called once during system initialization to populate these arrays
* for subsequent use by the AES key scheduler. If they have not been built
* before attempted use, an error will be returned to the caller.
*
* NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since
* GCM uses AES in counter-mode, where the AES cipher output is XORed with
* the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
* decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
*/
// We always need our forward tables
static uchar FSb[256]; // Forward substitution box (FSb)
static uint32_t FT0[256]; // Forward key schedule assembly tables
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];
#if AES_DECRYPTION // We ONLY need reverse for decryption
static uchar RSb[256]; // Reverse substitution box (RSb)
static uint32_t RT0[256]; // Reverse key schedule assembly tables
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];
#endif /* AES_DECRYPTION */
static uint32_t RCON[10]; // AES round constants
/*
* Platform Endianness Neutralizing Load and Store Macro definitions
* AES wants platform-neutral Little Endian (LE) byte ordering
*/
#define GET_UINT32_LE(n,b,i) { \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); }
#define PUT_UINT32_LE(n,b,i) { \
(b)[(i) ] = (uchar) ( (n) ); \
(b)[(i) + 1] = (uchar) ( (n) >> 8 ); \
(b)[(i) + 2] = (uchar) ( (n) >> 16 ); \
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
/*
* AES forward and reverse encryption round processing macros
*/
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
}
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y2 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y0 >> 24 ) & 0xFF ]; \
}
/*
* These macros improve the readability of the key
* generation initialization code by collapsing
* repetitive common operations into logical pieces.
*/
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
#define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \
*RK++ = *SK++; *RK++ = *SK++; }
/******************************************************************************
*
* AES_INIT_KEYGEN_TABLES
*
* Fills the AES key expansion tables allocated above with their static
* data. This is not "per key" data, but static system-wide read-only
* table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once
* at system initialization to setup the tables for all subsequent use.
*
******************************************************************************/
void aes_init_keygen_tables( void )
{
int i, x, y, z; // general purpose iteration and computation locals
int pow[256];
int log[256];
if (aes_tables_inited) return;
// fill the 'pow' and 'log' tables over GF(2^8)
for( i = 0, x = 1; i < 256; i++ ) {
pow[i] = x;
log[x] = i;
x = ( x ^ XTIME( x ) ) & 0xFF;
}
// compute the round constants
for( i = 0, x = 1; i < 10; i++ ) {
RCON[i] = (uint32_t) x;
x = XTIME( x ) & 0xFF;
}
// fill the forward and reverse substitution boxes
FSb[0x00] = 0x63;
#if AES_DECRYPTION // whether AES decryption is supported
RSb[0x63] = 0x00;
#endif /* AES_DECRYPTION */
for( i = 1; i < 256; i++ ) {
x = y = pow[255 - log[i]];
MIX(x,y);
MIX(x,y);
MIX(x,y);
MIX(x,y);
FSb[i] = (uchar) ( x ^= 0x63 );
#if AES_DECRYPTION // whether AES decryption is supported
RSb[x] = (uchar) i;
#endif /* AES_DECRYPTION */
}
// generate the forward and reverse key expansion tables
for( i = 0; i < 256; i++ ) {
x = FSb[i];
y = XTIME( x ) & 0xFF;
z = ( y ^ x ) & 0xFF;
FT0[i] = ( (uint32_t) y ) ^ ( (uint32_t) x << 8 ) ^
( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 );
FT1[i] = ROTL8( FT0[i] );
FT2[i] = ROTL8( FT1[i] );
FT3[i] = ROTL8( FT2[i] );
#if AES_DECRYPTION // whether AES decryption is supported
x = RSb[i];
RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
( (uint32_t) MUL( 0x09, x ) << 8 ) ^
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
( (uint32_t) MUL( 0x0B, x ) << 24 );
RT1[i] = ROTL8( RT0[i] );
RT2[i] = ROTL8( RT1[i] );
RT3[i] = ROTL8( RT2[i] );
#endif /* AES_DECRYPTION */
}
aes_tables_inited = 1; // flag that the tables have been generated
} // to permit subsequent use of the AES cipher
/******************************************************************************
*
* AES_SET_ENCRYPTION_KEY
*
* This is called by 'aes_setkey' when we're establishing a key for
* subsequent encryption. We give it a pointer to the encryption
* context, a pointer to the key, and the key's length in bytes.
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
*
******************************************************************************/
int aes_set_encryption_key( aes_context *ctx,
const uchar *key,
uint keysize )
{
uint i; // general purpose iteration local
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
for( i = 0; i < (keysize >> 2); i++ ) {
GET_UINT32_LE( RK[i], key, i << 2 );
}
switch( ctx->rounds )
{
case 10:
for( i = 0; i < 10; i++, RK += 4 ) {
RK[4] = RK[0] ^ RCON[i] ^
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
RK[5] = RK[1] ^ RK[4];
RK[6] = RK[2] ^ RK[5];
RK[7] = RK[3] ^ RK[6];
}
break;
case 12:
for( i = 0; i < 8; i++, RK += 6 ) {
RK[6] = RK[0] ^ RCON[i] ^
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
RK[7] = RK[1] ^ RK[6];
RK[8] = RK[2] ^ RK[7];
RK[9] = RK[3] ^ RK[8];
RK[10] = RK[4] ^ RK[9];
RK[11] = RK[5] ^ RK[10];
}
break;
case 14:
for( i = 0; i < 7; i++, RK += 8 ) {
RK[8] = RK[0] ^ RCON[i] ^
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
RK[9] = RK[1] ^ RK[8];
RK[10] = RK[2] ^ RK[9];
RK[11] = RK[3] ^ RK[10];
RK[12] = RK[4] ^
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
RK[13] = RK[5] ^ RK[12];
RK[14] = RK[6] ^ RK[13];
RK[15] = RK[7] ^ RK[14];
}
break;
default:
return -1;
}
return( 0 );
}
#if AES_DECRYPTION // whether AES decryption is supported
/******************************************************************************
*
* AES_SET_DECRYPTION_KEY
*
* This is called by 'aes_setkey' when we're establishing a
* key for subsequent decryption. We give it a pointer to
* the encryption context, a pointer to the key, and the key's
* length in bits. Valid lengths are: 128, 192, or 256 bits.
*
******************************************************************************/
int aes_set_decryption_key( aes_context *ctx,
const uchar *key,
uint keysize )
{
int i, j;
aes_context cty; // a calling aes context for set_encryption_key
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
uint32_t *SK;
int ret;
cty.rounds = ctx->rounds; // initialize our local aes context
cty.rk = cty.buf; // round count and key buf pointer
if (( ret = aes_set_encryption_key( &cty, key, keysize )) != 0 )
return( ret );
SK = cty.rk + cty.rounds * 4;
CPY128 // copy a 128-bit block from *SK to *RK
for( i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8 ) {
for( j = 0; j < 4; j++, SK++ ) {
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
}
}
CPY128 // copy a 128-bit block from *SK to *RK
memset( &cty, 0, sizeof( aes_context ) ); // clear local aes context
return( 0 );
}
#endif /* AES_DECRYPTION */
/******************************************************************************
*
* AES_SETKEY
*
* Invoked to establish the key schedule for subsequent encryption/decryption
*
******************************************************************************/
int aes_setkey( aes_context *ctx, // AES context provided by our caller
int mode, // ENCRYPT or DECRYPT flag
const uchar *key, // pointer to the key
uint keysize ) // key length in bytes
{
// since table initialization is not thread safe, we could either add
// system-specific mutexes and init the AES key generation tables on
// demand, or ask the developer to simply call "gcm_initialize" once during
// application startup before threading begins. That's what we choose.
if( !aes_tables_inited ) return ( -1 ); // fail the call when not inited.
ctx->mode = mode; // capture the key type we're creating
ctx->rk = ctx->buf; // initialize our round key pointer
switch( keysize ) // set the rounds count based upon the keysize
{
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
default: return(-1);
}
#if AES_DECRYPTION
if( mode == DECRYPT ) // expand our key for encryption or decryption
return( aes_set_decryption_key( ctx, key, keysize ) );
else /* ENCRYPT */
#endif /* AES_DECRYPTION */
return( aes_set_encryption_key( ctx, key, keysize ) );
}
/******************************************************************************
*
* AES_CIPHER
*
* Perform AES encryption and decryption.
* The AES context will have been setup with the encryption mode
* and all keying information appropriate for the task.
*
******************************************************************************/
int aes_cipher( aes_context *ctx,
const uchar input[16],
uchar output[16] )
{
int i;
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
RK = ctx->rk;
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; // load our 128-bit
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; // input buffer in a storage
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; // memory endian-neutral way
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
#if AES_DECRYPTION // whether AES decryption is supported
if( ctx->mode == DECRYPT )
{
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
{
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
}
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
}
else /* ENCRYPT */
{
#endif /* AES_DECRYPTION */
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
{
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
}
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
#if AES_DECRYPTION // whether AES decryption is supported
}
#endif /* AES_DECRYPTION */
PUT_UINT32_LE( X0, output, 0 );
PUT_UINT32_LE( X1, output, 4 );
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
return( 0 );
}
/* end of aes.c */

511
crypto/gcm.c Normal file
View File

@ -0,0 +1,511 @@
/******************************************************************************
*
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
*
* This is a simple and straightforward implementation of AES-GCM authenticated
* encryption. The focus of this work was correctness & accuracy. It is written
* in straight 'C' without any particular focus upon optimization or speed. It
* should be endian (memory byte order) neutral since the few places that care
* are handled explicitly.
*
* This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
*
* It is intended for general purpose use, but was written in support of GRC's
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
*
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/
* gcm/gcm-revised-spec.pdf
*
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
*
*******************************************************************************/
#include "crypto/gcm.h"
#include "crypto/aes.h"
/******************************************************************************
* ==== IMPLEMENTATION WARNING ====
*
* This code was developed for use within SQRL's fixed environmnent. Thus, it
* is somewhat less "general purpose" than it would be if it were designed as
* a general purpose AES-GCM library. Specifically, it bothers with almost NO
* error checking on parameter limits, buffer bounds, etc. It assumes that it
* is being invoked by its author or by someone who understands the values it
* expects to receive. Its behavior will be undefined otherwise.
*
* All functions that might fail are defined to return 'ints' to indicate a
* problem. Most do not do so now. But this allows for error propagation out
* of internal functions if robust error checking should ever be desired.
*
******************************************************************************/
/* Calculating the "GHASH"
*
* There are many ways of calculating the so-called GHASH in software, each with
* a traditional size vs performance tradeoff. The GHASH (Galois field hash) is
* an intriguing construction which takes two 128-bit strings (also the cipher's
* block size and the fundamental operation size for the system) and hashes them
* into a third 128-bit result.
*
* Many implementation solutions have been worked out that use large precomputed
* table lookups in place of more time consuming bit fiddling, and this approach
* can be scaled easily upward or downward as needed to change the time/space
* tradeoff. It's been studied extensively and there's a solid body of theory and
* practice. For example, without using any lookup tables an implementation
* might obtain 119 cycles per byte throughput, whereas using a simple, though
* large, key-specific 64 kbyte 8-bit lookup table the performance jumps to 13
* cycles per byte.
*
* And Intel's processors have, since 2010, included an instruction which does
* the entire 128x128->128 bit job in just several 64x64->128 bit pieces.
*
* Since SQRL is interactive, and only processing a few 128-bit blocks, I've
* settled upon a relatively slower but appealing small-table compromise which
* folds a bunch of not only time consuming but also bit twiddling into a simple
* 16-entry table which is attributed to Victor Shoup's 1996 work while at
* Bellcore: "On Fast and Provably Secure MessageAuthentication Based on
* Universal Hashing." See: http://www.shoup.net/papers/macs.pdf
* See, also section 4.1 of the "gcm-revised-spec" cited above.
*/
/*
* This 16-entry table of pre-computed constants is used by the
* GHASH multiplier to improve over a strictly table-free but
* significantly slower 128x128 bit multiple within GF(2^128).
*/
static const uint64_t last4[16] = {
0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 };
/*
* Platform Endianness Neutralizing Load and Store Macro definitions
* GCM wants platform-neutral Big Endian (BE) byte ordering
*/
#define GET_UINT32_BE(n,b,i) { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); }
#define PUT_UINT32_BE(n,b,i) { \
(b)[(i) ] = (uchar) ( (n) >> 24 ); \
(b)[(i) + 1] = (uchar) ( (n) >> 16 ); \
(b)[(i) + 2] = (uchar) ( (n) >> 8 ); \
(b)[(i) + 3] = (uchar) ( (n) ); }
/******************************************************************************
*
* GCM_INITIALIZE
*
* Must be called once to initialize the GCM library.
*
* At present, this only calls the AES keygen table generator, which expands
* the AES keying tables for use. This is NOT A THREAD-SAFE function, so it
* MUST be called during system initialization before a multi-threading
* environment is running.
*
******************************************************************************/
int gcm_initialize( void )
{
aes_init_keygen_tables();
return( 0 );
}
/******************************************************************************
*
* GCM_MULT
*
* Performs a GHASH operation on the 128-bit input vector 'x', setting
* the 128-bit output vector to 'x' times H using our precomputed tables.
* 'x' and 'output' are seen as elements of GCM's GF(2^128) Galois field.
*
******************************************************************************/
static void gcm_mult( gcm_context *ctx, // pointer to established context
const uchar x[16], // pointer to 128-bit input vector
uchar output[16] ) // pointer to 128-bit output vector
{
int i;
uchar lo, hi, rem;
uint64_t zh, zl;
lo = (uchar)( x[15] & 0x0f );
hi = (uchar)( x[15] >> 4 );
zh = ctx->HH[lo];
zl = ctx->HL[lo];
for( i = 15; i >= 0; i-- ) {
lo = (uchar) ( x[i] & 0x0f );
hi = (uchar) ( x[i] >> 4 );
if( i != 15 ) {
rem = (uchar) ( zl & 0x0f );
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[lo];
zl ^= ctx->HL[lo];
}
rem = (uchar) ( zl & 0x0f );
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[hi];
zl ^= ctx->HL[hi];
}
PUT_UINT32_BE( zh >> 32, output, 0 );
PUT_UINT32_BE( zh, output, 4 );
PUT_UINT32_BE( zl >> 32, output, 8 );
PUT_UINT32_BE( zl, output, 12 );
}
/******************************************************************************
*
* GCM_SETKEY
*
* This is called to set the AES-GCM key. It initializes the AES key
* and populates the gcm context's pre-calculated HTables.
*
******************************************************************************/
int gcm_setkey( gcm_context *ctx, // pointer to caller-provided gcm context
const uchar *key, // pointer to the AES encryption key
const uint keysize) // size in bytes (must be 16, 24, 32 for
// 128, 192 or 256-bit keys respectively)
{
int ret, i, j;
uint64_t hi, lo;
uint64_t vl, vh;
unsigned char h[16];
memset( ctx, 0, sizeof(gcm_context) ); // zero caller-provided GCM context
memset( h, 0, 16 ); // initialize the block to encrypt
// encrypt the null 128-bit block to generate a key-based value
// which is then used to initialize our GHASH lookup tables
if(( ret = aes_setkey( &ctx->aes_ctx, ENCRYPT, key, keysize )) != 0 )
return( ret );
if(( ret = aes_cipher( &ctx->aes_ctx, h, h )) != 0 )
return( ret );
GET_UINT32_BE( hi, h, 0 ); // pack h as two 64-bit ints, big-endian
GET_UINT32_BE( lo, h, 4 );
vh = (uint64_t) hi << 32 | lo;
GET_UINT32_BE( hi, h, 8 );
GET_UINT32_BE( lo, h, 12 );
vl = (uint64_t) hi << 32 | lo;
ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
ctx->HH[8] = vh;
ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
ctx->HL[0] = 0;
for( i = 4; i > 0; i >>= 1 ) {
uint32_t T = (uint32_t) ( vl & 1 ) * 0xe1000000U;
vl = ( vh << 63 ) | ( vl >> 1 );
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
ctx->HL[i] = vl;
ctx->HH[i] = vh;
}
for (i = 2; i < 16; i <<= 1 ) {
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
vh = *HiH;
vl = *HiL;
for( j = 1; j < i; j++ ) {
HiH[j] = vh ^ ctx->HH[j];
HiL[j] = vl ^ ctx->HL[j];
}
}
return( 0 );
}
/******************************************************************************
*
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
*
* SETKEY:
*
* START: Sets the Encryption/Decryption mode.
* Accepts the initialization vector and additional data.
*
* UPDATE: Encrypts or decrypts the plaintext or ciphertext.
*
* FINISH: Performs a final GHASH to generate the authentication tag.
*
******************************************************************************
*
* GCM_START
*
* Given a user-provided GCM context, this initializes it, sets the encryption
* mode, and preprocesses the initialization vector and additional AEAD data.
*
******************************************************************************/
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
int mode, // GCM_ENCRYPT or GCM_DECRYPT
const uchar *iv, // pointer to initialization vector
size_t iv_len, // IV length in bytes (should == 12)
const uchar *add, // ptr to additional AEAD data (NULL if none)
size_t add_len ) // length of additional AEAD data (bytes)
{
int ret; // our error return if the AES encrypt fails
uchar work_buf[16]; // XOR source built from provided IV if len != 16
const uchar *p; // general purpose array pointer
size_t use_len; // byte count to process, up to 16 bytes
size_t i; // local loop iterator
// since the context might be reused under the same key
// we zero the working buffers for this next new process
memset( ctx->y, 0x00, sizeof(ctx->y ) );
memset( ctx->buf, 0x00, sizeof(ctx->buf) );
ctx->len = 0;
ctx->add_len = 0;
ctx->mode = mode; // set the GCM encryption/decryption mode
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
if( iv_len == 12 ) { // GCM natively uses a 12-byte, 96-bit IV
memcpy( ctx->y, iv, iv_len ); // copy the IV to the top of the 'y' buff
ctx->y[15] = 1; // start "counting" from 1 (not 0)
}
else // if we don't have a 12-byte IV, we GHASH whatever we've been given
{
memset( work_buf, 0x00, 16 ); // clear the working buffer
PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); // place the IV into buffer
p = iv;
while( iv_len > 0 ) {
use_len = ( iv_len < 16 ) ? iv_len : 16;
for( i = 0; i < use_len; i++ ) ctx->y[i] ^= p[i];
gcm_mult( ctx, ctx->y, ctx->y );
iv_len -= use_len;
p += use_len;
}
for( i = 0; i < 16; i++ ) ctx->y[i] ^= work_buf[i];
gcm_mult( ctx, ctx->y, ctx->y );
}
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ctx->base_ectr ) ) != 0 )
return( ret );
ctx->add_len = add_len;
p = add;
while( add_len > 0 ) {
use_len = ( add_len < 16 ) ? add_len : 16;
for( i = 0; i < use_len; i++ ) ctx->buf[i] ^= p[i];
gcm_mult( ctx, ctx->buf, ctx->buf );
add_len -= use_len;
p += use_len;
}
return( 0 );
}
/******************************************************************************
*
* GCM_UPDATE
*
* This is called once or more to process bulk plaintext or ciphertext data.
* We give this some number of bytes of input and it returns the same number
* of output bytes. If called multiple times (which is fine) all but the final
* invocation MUST be called with length mod 16 == 0. (Only the final call can
* have a partial block length of < 128 bits.)
*
******************************************************************************/
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
size_t length, // length, in bytes, of data to process
const uchar *input, // pointer to source data
uchar *output ) // pointer to destination data
{
int ret; // our error return if the AES encrypt fails
uchar ectr[16]; // counter-mode cipher output for XORing
size_t use_len; // byte count to process, up to 16 bytes
size_t i; // local loop iterator
ctx->len += length; // bump the GCM context's running length count
while( length > 0 ) {
// clamp the length to process at 16 bytes
use_len = ( length < 16 ) ? length : 16;
// increment the context's 128-bit IV||Counter 'y' vector
for( i = 16; i > 12; i-- ) if( ++ctx->y[i - 1] != 0 ) break;
// encrypt the context's 'y' vector under the established key
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ectr ) ) != 0 )
return( ret );
// encrypt or decrypt the input to the output
if( ctx->mode == ENCRYPT )
{
for( i = 0; i < use_len; i++ ) {
// XOR the cipher's ouptut vector (ectr) with our input
output[i] = (uchar) ( ectr[i] ^ input[i] );
// now we mix in our data into the authentication hash.
// if we're ENcrypting we XOR in the post-XOR (output)
// results, but if we're DEcrypting we XOR in the input
// data
ctx->buf[i] ^= output[i];
}
}
else
{
for( i = 0; i < use_len; i++ ) {
// but if we're DEcrypting we XOR in the input data first,
// i.e. before saving to ouput data, otherwise if the input
// and output buffer are the same (inplace decryption) we
// would not get the correct auth tag
ctx->buf[i] ^= input[i];
// XOR the cipher's ouptut vector (ectr) with our input
output[i] = (uchar) ( ectr[i] ^ input[i] );
}
}
gcm_mult( ctx, ctx->buf, ctx->buf ); // perform a GHASH operation
length -= use_len; // drop the remaining byte count to process
input += use_len; // bump our input pointer forward
output += use_len; // bump our output pointer forward
}
return( 0 );
}
/******************************************************************************
*
* GCM_FINISH
*
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
* It performs the final GHASH to produce the resulting authentication TAG.
*
******************************************************************************/
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
uchar *tag, // pointer to buffer which receives the tag
size_t tag_len ) // length, in bytes, of the tag-receiving buf
{
uchar work_buf[16];
uint64_t orig_len = ctx->len * 8;
uint64_t orig_add_len = ctx->add_len * 8;
size_t i;
if( tag_len != 0 ) memcpy( tag, ctx->base_ectr, tag_len );
if( orig_len || orig_add_len ) {
memset( work_buf, 0x00, 16 );
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
for( i = 0; i < 16; i++ ) ctx->buf[i] ^= work_buf[i];
gcm_mult( ctx, ctx->buf, ctx->buf );
for( i = 0; i < tag_len; i++ ) tag[i] ^= ctx->buf[i];
}
return( 0 );
}
/******************************************************************************
*
* GCM_CRYPT_AND_TAG
*
* This either encrypts or decrypts the user-provided data and, either
* way, generates an authentication tag of the requested length. It must be
* called with a GCM context whose key has already been set with GCM_SETKEY.
*
* The user would typically call this explicitly to ENCRYPT a buffer of data
* and optional associated data, and produce its an authentication tag.
*
* To reverse the process the user would typically call the companion
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
* to perform its decryption and tag generation, which it then compares.
*
******************************************************************************/
int gcm_crypt_and_tag(
gcm_context *ctx, // gcm context with key already setup
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data
size_t add_len, // byte length of the additional AEAD data
const uchar *input, // pointer to the cipher data source
uchar *output, // pointer to the cipher data destination
size_t length, // byte length of the cipher data
uchar *tag, // pointer to the tag to be generated
size_t tag_len ) // byte length of the tag to be generated
{ /*
assuming that the caller has already invoked gcm_setkey to
prepare the gcm context with the keying material, we simply
invoke each of the three GCM sub-functions in turn...
*/
gcm_start ( ctx, mode, iv, iv_len, add, add_len );
gcm_update ( ctx, length, input, output );
gcm_finish ( ctx, tag, tag_len );
return( 0 );
}
/******************************************************************************
*
* GCM_AUTH_DECRYPT
*
* This DECRYPTS a user-provided data buffer with optional associated data.
* It then verifies a user-supplied authentication tag against the tag just
* re-created during decryption to verify that the data has not been altered.
*
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
* and authentication tag generation.
*
******************************************************************************/
int gcm_auth_decrypt(
gcm_context *ctx, // gcm context with key already setup
const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data
size_t add_len, // byte length of the additional AEAD data
const uchar *input, // pointer to the cipher data source
uchar *output, // pointer to the cipher data destination
size_t length, // byte length of the cipher data
const uchar *tag, // pointer to the tag to be authenticated
size_t tag_len ) // byte length of the tag <= 16
{
uchar check_tag[16]; // the tag generated and returned by decryption
int diff; // an ORed flag to detect authentication errors
size_t i; // our local iterator
/*
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
(which is an identical XORing to reverse the previous one)
and also to re-generate the matching authentication tag
*/
gcm_crypt_and_tag( ctx, DECRYPT, iv, iv_len, add, add_len,
input, output, length, check_tag, tag_len );
// now we verify the authentication tag in 'constant time'
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 ) { // see whether any bits differed?
memset( output, 0, length ); // if so... wipe the output data
return( GCM_AUTH_FAILURE ); // return GCM_AUTH_FAILURE
}
return( 0 );
}
/******************************************************************************
*
* GCM_ZERO_CTX
*
* The GCM context contains both the GCM context and the AES context.
* This includes keying and key-related material which is security-
* sensitive, so it MUST be zeroed after use. This function does that.
*
******************************************************************************/
void gcm_zero_ctx( gcm_context *ctx )
{
// zero the context originally provided to us
memset( ctx, 0, sizeof( gcm_context ) );
}

335
crypto/hkdf.c Normal file
View File

@ -0,0 +1,335 @@
/**************************** hkdf.c ***************************/
/***************** See RFC 6234 for details. *******************/
/* Copyright (c) 2011 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */
/*
* Description:
* This file implements the HKDF algorithm (HMAC-based
* Extract-and-Expand Key Derivation Function, RFC 5869),
* expressed in terms of the various SHA algorithms.
*/
#include "crypto/sha.h"
#warning "May fail on kernel module"
#include "types.h"
/*
* hkdf
*
* Description:
* This function will generate keying material using HKDF.
*
* Parameters:
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt[ ]: [in]
* The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros.
* salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.)
* ikm[ ]: [in]
* Input keying material.
* ikm_len: [in]
* The length of the input keying material.
* info[ ]: [in]
* The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored.
* info_len: [in]
* The length of the optional context and application specific
* information. (Ignored if info == NULL.)
* okm[ ]: [out]
* Where the HKDF is to be stored.
* okm_len: [in]
* The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha)
*
* Notes:
* Calls hkdfExtract() and hkdfExpand().
*
* Returns:
* sha Error Code.
*
*/
int hkdf(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
{
uint8_t prk[USHAMaxHashSize];
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
info_len, okm, okm_len);
}
/*
* hkdfExtract
*
* Description:
* This function will perform HKDF extraction.
*
* Parameters:
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt[ ]: [in]
* The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros.
* salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.)
* ikm[ ]: [in]
* Input keying material.
* ikm_len: [in]
* The length of the input keying material.
* prk[ ]: [out]
* Array where the HKDF extraction is to be stored.
* Must be larger than USHAHashSize(whichSha);
*
* Returns:
* sha Error Code.
*
*/
int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
uint8_t prk[USHAMaxHashSize])
{
unsigned char nullSalt[USHAMaxHashSize];
if (salt == 0) {
salt = nullSalt;
salt_len = USHAHashSize(whichSha);
memset(nullSalt, '\0', salt_len);
} else if (salt_len < 0) {
return shaBadParam;
}
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
}
/*
* hkdfExpand
*
* Description:
* This function will perform HKDF expansion.
*
* Parameters:
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* prk[ ]: [in]
* The pseudo-random key to be expanded; either obtained
* directly from a cryptographically strong, uniformly
* distributed pseudo-random number generator, or as the
* output from hkdfExtract().
* prk_len: [in]
* The length of the pseudo-random key in prk;
* should at least be equal to USHAHashSize(whichSHA).
* info[ ]: [in]
* The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored.
* info_len: [in]
* The length of the optional context and application specific
* information. (Ignored if info == NULL.)
* okm[ ]: [out]
* Where the HKDF is to be stored.
* okm_len: [in]
* The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha)
*
* Returns:
* sha Error Code.
*
*/
int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
{
int hash_len, N;
unsigned char T[USHAMaxHashSize];
int Tlen, where, i;
if (info == 0) {
info = (const unsigned char *)"";
info_len = 0;
} else if (info_len < 0) {
return shaBadParam;
}
if (okm_len <= 0) return shaBadParam;
if (!okm) return shaBadParam;
hash_len = USHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam;
N = okm_len / hash_len;
if ((okm_len % hash_len) != 0) N++;
if (N > 255) return shaBadParam;
Tlen = 0;
where = 0;
for (i = 1; i <= N; i++) {
HMACContext context;
unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
hmacInput(&context, T, Tlen) ||
hmacInput(&context, info, info_len) ||
hmacInput(&context, &c, 1) ||
hmacResult(&context, T);
if (ret != shaSuccess) return ret;
memcpy(okm + where, T,
(i != N) ? hash_len : (okm_len - where));
where += hash_len;
Tlen = hash_len;
}
return shaSuccess;
}
/*
* hkdfReset
*
* Description:
* This function will initialize the hkdfContext in preparation
* for key derivation using the modular HKDF interface for
* arbitrary length inputs.
*
* Parameters:
* context: [in/out]
* The context to reset.
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* salt[ ]: [in]
* The optional salt value (a non-secret random value);
* if not provided (salt == NULL), it is set internally
* to a string of HashLen(whichSha) zeros.
* salt_len: [in]
* The length of the salt value. (Ignored if salt == NULL.)
*
* Returns:
* sha Error Code.
*
*/
int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len)
{
unsigned char nullSalt[USHAMaxHashSize];
if (!context) return shaNull;
context->whichSha = whichSha;
context->hashSize = USHAHashSize(whichSha);
if (salt == 0) {
salt = nullSalt;
salt_len = context->hashSize;
memset(nullSalt, '\0', salt_len);
}
return hmacReset(&context->hmacContext, whichSha, salt, salt_len);
}
/*
* hkdfInput
*
* Description:
* This function accepts an array of octets as the next portion
* of the input keying material. It may be called multiple times.
*
* Parameters:
* context: [in/out]
* The HKDF context to update.
* ikm[ ]: [in]
* An array of octets representing the next portion of
* the input keying material.
* ikm_len: [in]
* The length of ikm.
*
* Returns:
* sha Error Code.
*
*/
int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
return hmacInput(&context->hmacContext, ikm, ikm_len);
}
/*
* hkdfFinalBits
*
* Description:
* This function will add in any final bits of the
* input keying material.
*
* Parameters:
* context: [in/out]
* The HKDF context to update
* ikm_bits: [in]
* The final bits of the input keying material, in the upper
* portion of the byte. (Use 0b###00000 instead of 0b00000###
* to input the three bits ###.)
* ikm_bit_count: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
return hmacFinalBits(&context->hmacContext, ikm_bits, ikm_bit_count);
}
/*
* hkdfResult
*
* Description:
* This function will finish the HKDF extraction and perform the
* final HKDF expansion.
*
* Parameters:
* context: [in/out]
* The HKDF context to use to calculate the HKDF hash.
* prk[ ]: [out]
* An optional location to store the HKDF extraction.
* Either NULL, or pointer to a buffer that must be
* larger than USHAHashSize(whichSha);
* info[ ]: [in]
* The optional context and application specific information.
* If info == NULL or a zero-length string, it is ignored.
* info_len: [in]
* The length of the optional context and application specific
* information. (Ignored if info == NULL.)
* okm[ ]: [out]
* Where the HKDF is to be stored.
* okm_len: [in]
* The length of the buffer to hold okm.
* okm_len must be <= 255 * USHABlockSize(whichSha)
*
* Returns:
* sha Error Code.
*
*/
int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len,
uint8_t okm[], int okm_len)
{
uint8_t prkbuf[USHAMaxHashSize];
int ret;
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (!okm) return context->Corrupted = shaBadParam;
if (!prk) prk = prkbuf;
ret = hmacResult(&context->hmacContext, prk) ||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
info_len, okm, okm_len);
context->Computed = 1;
return context->Corrupted = ret;
}

246
crypto/hmac.c Normal file
View File

@ -0,0 +1,246 @@
/**************************** hmac.c ***************************/
/***************** See RFC 6234 for details. *******************/
/* Copyright (c) 2011 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */
/*
* Description:
* This file implements the HMAC algorithm (Keyed-Hashing for
* Message Authentication, [RFC 2104]), expressed in terms of
* the various SHA algorithms.
*/
#include "crypto/sha.h"
/*
* hmac
*
* Description:
* This function will compute an HMAC message digest.
*
* Parameters:
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* message_array[ ]: [in]
* An array of octets representing the message.
* Note: in RFC 2104, this parameter is known
* as 'text'.
* length: [in]
* The length of the message in message_array.
* key[ ]: [in]
* The secret shared key.
* key_len: [in]
* The length of the secret shared key.
* digest[ ]: [out]
* Where the digest is to be returned.
* NOTE: The length of the digest is determined by
* the value of whichSha.
*
* Returns:
* sha Error Code.
*
*/
int hmac(SHAversion whichSha,
const unsigned char *message_array, int length,
const unsigned char *key, int key_len,
uint8_t digest[USHAMaxHashSize])
{
HMACContext context;
return hmacReset(&context, whichSha, key, key_len) ||
hmacInput(&context, message_array, length) ||
hmacResult(&context, digest);
}
/*
* hmacReset
*
* Description:
* This function will initialize the hmacContext in preparation
* for computing a new HMAC message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
* whichSha: [in]
* One of SHA1, SHA224, SHA256, SHA384, SHA512
* key[ ]: [in]
* The secret shared key.
* key_len: [in]
* The length of the secret shared key.
*
* Returns:
* sha Error Code.
*
*/
int hmacReset(HMACContext *context, enum SHAversion whichSha,
const unsigned char *key, int key_len)
{
int i, blocksize, hashsize, ret;
/* inner padding - key XORd with ipad */
unsigned char k_ipad[USHA_Max_Message_Block_Size];
/* temporary buffer when keylen > blocksize */
unsigned char tempkey[USHAMaxHashSize];
if (!context) return shaNull;
context->Computed = 0;
context->Corrupted = shaSuccess;
blocksize = context->blockSize = USHABlockSize(whichSha);
hashsize = context->hashSize = USHAHashSize(whichSha);
context->whichSha = whichSha;
/*
* If key is longer than the hash blocksize,
* reset it to key = HASH(key).
*/
if (key_len > blocksize) {
USHAContext tcontext;
int err = USHAReset(&tcontext, whichSha) ||
USHAInput(&tcontext, key, key_len) ||
USHAResult(&tcontext, tempkey);
if (err != shaSuccess) return err;
key = tempkey;
key_len = hashsize;
}
/*
* The HMAC transform looks like:
*
* SHA(K XOR opad, SHA(K XOR ipad, text))
*
* where K is an n byte key, 0-padded to a total of blocksize bytes,
* ipad is the byte 0x36 repeated blocksize times,
* opad is the byte 0x5c repeated blocksize times,
* and text is the data being protected.
*/
/* store key into the pads, XOR'd with ipad and opad values */
for (i = 0; i < key_len; i++) {
k_ipad[i] = key[i] ^ 0x36;
context->k_opad[i] = key[i] ^ 0x5c;
}
/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
for ( ; i < blocksize; i++) {
k_ipad[i] = 0x36;
context->k_opad[i] = 0x5c;
}
/* perform inner hash */
/* init context for 1st pass */
ret = USHAReset(&context->shaContext, whichSha) ||
/* and start with inner pad */
USHAInput(&context->shaContext, k_ipad, blocksize);
return context->Corrupted = ret;
}
/*
* hmacInput
*
* Description:
* This function accepts an array of octets as the next portion
* of the message. It may be called multiple times.
*
* Parameters:
* context: [in/out]
* The HMAC context to update.
* text[ ]: [in]
* An array of octets representing the next portion of
* the message.
* text_len: [in]
* The length of the message in text.
*
* Returns:
* sha Error Code.
*
*/
int hmacInput(HMACContext *context, const unsigned char *text,
int text_len)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
/* then text of datagram */
return context->Corrupted =
USHAInput(&context->shaContext, text, text_len);
}
/*
* hmacFinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The HMAC context to update.
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int hmacFinalBits(HMACContext *context,
uint8_t bits, unsigned int bit_count)
{
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
/* then final bits of datagram */
return context->Corrupted =
USHAFinalBits(&context->shaContext, bits, bit_count);
}
/*
* hmacResult
*
* Description:
* This function will return the N-byte message digest into the
* Message_Digest array provided by the caller.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the HMAC hash.
* digest[ ]: [out]
* Where the digest is returned.
* NOTE 2: The length of the hash is determined by the value of
* whichSha that was passed to hmacReset().
*
* Returns:
* sha Error Code.
*
*/
int hmacResult(HMACContext *context, uint8_t *digest)
{
int ret;
if (!context) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
/* finish up 1st pass */
/* (Use digest here as a temporary buffer.) */
ret =
USHAResult(&context->shaContext, digest) ||
/* perform outer SHA */
/* init context for 2nd pass */
USHAReset(&context->shaContext, context->whichSha) ||
/* start with outer pad */
USHAInput(&context->shaContext, context->k_opad,
context->blockSize) ||
/* then results of 1st hash */
USHAInput(&context->shaContext, digest, context->hashSize) ||
/* finish up 2nd pass */
USHAResult(&context->shaContext, digest);
context->Computed = 1;
return context->Corrupted = ret;
}

415
crypto/sha1.c Normal file
View File

@ -0,0 +1,415 @@
/**************************** sha1.c ***************************/
/***************** See RFC 6234 for details. *******************/
/* Copyright (c) 2011 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */
/*
* Description:
* This file implements the Secure Hash Algorithm SHA-1
* as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-3/fips180-3_final.pdf
*
* The SHA-1 algorithm produces a 160-bit message digest for a
* given data stream that can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code
* uses <stdint.h> (included via "sha.h") to define 32- and
* 8-bit unsigned integer types. If your C compiler does
* not support 32-bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits
* long. This implementation uses SHA1Input() to hash the bits
* that are a multiple of the size of an 8-bit octet, and then
* optionally uses SHA1FinalBits() to hash the final few bits of
* the input.
*/
#include "crypto/sha.h"
#include "crypto/sha-private.h"
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1_ROTL(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/*
* Add "length" to the length.
* Set Corrupted when overflow has occurred.
*/
static uint32_t addTemp;
#define SHA1AddLength(context, length) \
(addTemp = (context)->Length_Low, \
(context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong \
: (context)->Corrupted )
/* Local Function Prototypes */
static void SHA1ProcessMessageBlock(SHA1Context *context);
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte);
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte);
/*
* SHA1Reset
*
* Description:
* This function will initialize the SHA1Context in preparation
* for computing a new SHA1 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Reset(SHA1Context *context)
{
if (!context) return shaNull;
context->Length_High = context->Length_Low = 0;
context->Message_Block_Index = 0;
/* Initial Hash Values: FIPS 180-3 section 5.3.1 */
context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = shaSuccess;
return shaSuccess;
}
/*
* SHA1Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_array[ ]: [in]
* An array of octets representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Input(SHA1Context *context,
const uint8_t *message_array, unsigned length)
{
if (!context) return shaNull;
if (!length) return shaSuccess;
if (!message_array) return shaNull;
if (context->Computed) return context->Corrupted = shaStateError;
if (context->Corrupted) return context->Corrupted;
while (length--) {
context->Message_Block[context->Message_Block_Index++] =
*message_array;
if ((SHA1AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA1_Message_Block_Size))
SHA1ProcessMessageBlock(context);
message_array++;
}
return context->Corrupted;
}
/*
* SHA1FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int SHA1FinalBits(SHA1Context *context, uint8_t message_bits,
unsigned int length)
{
static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
};
static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
};
if (!context) return shaNull;
if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (length >= 8) return context->Corrupted = shaBadParam;
SHA1AddLength(context, length);
SHA1Finalize(context,
(uint8_t) ((message_bits & masks[length]) | markbit[length]));
return context->Corrupted;
}
/*
* SHA1Result
*
* Description:
* This function will return the 160-bit message digest
* into the Message_Digest array provided by the caller.
* NOTE:
* The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 19.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA-1 hash.
* Message_Digest[ ]: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Result(SHA1Context *context,
uint8_t Message_Digest[SHA1HashSize])
{
int i;
if (!context) return shaNull;
if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (!context->Computed)
SHA1Finalize(context, 0x80);
for (i = 0; i < SHA1HashSize; ++i)
Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2]
>> (8 * ( 3 - ( i & 0x03 ) )));
return shaSuccess;
}
/*
* SHA1ProcessMessageBlock
*
* Description:
* This helper function will process the next 512 bits of the
* message stored in the Message_Block array.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the Secure Hash Standard.
*/
static void SHA1ProcessMessageBlock(SHA1Context *context)
{
/* Constants defined in FIPS 180-3, section 4.2.1 */
const uint32_t K[4] = {
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = 0; t < 16; t++) {
W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24;
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16;
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8;
W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]);
}
for (t = 16; t < 80; t++)
W[t] = SHA1_ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
for (t = 0; t < 20; t++) {
temp = SHA1_ROTL(5,A) + SHA_Ch(B, C, D) + E + W[t] + K[0];
E = D;
D = C;
C = SHA1_ROTL(30,B);
B = A;
A = temp;
}
for (t = 20; t < 40; t++) {
temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
E = D;
D = C;
C = SHA1_ROTL(30,B);
B = A;
A = temp;
}
for (t = 40; t < 60; t++) {
temp = SHA1_ROTL(5,A) + SHA_Maj(B, C, D) + E + W[t] + K[2];
E = D;
D = C;
C = SHA1_ROTL(30,B);
B = A;
A = temp;
}
for (t = 60; t < 80; t++) {
temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[3];
E = D;
D = C;
C = SHA1_ROTL(30,B);
B = A;
A = temp;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0;
}
/*
* SHA1Finalize
*
* Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*
*/
static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
{
int i;
SHA1PadMessage(context, Pad_Byte);
/* message may be sensitive, clear it out */
for (i = 0; i < SHA1_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_High = 0; /* and clear length */
context->Length_Low = 0;
context->Computed = 1;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 512 bits. The first padding bit must be a '1'.
* The last 64 bits represent the length of the original message.
* All bits in between should be 0. This helper function will pad
* the message according to those rules by filling the Message_Block
* array accordingly. When it returns, it can be assumed that the
* message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad.
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA1_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
context->Message_Block[59] = (uint8_t) (context->Length_High);
context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t) (context->Length_Low);
SHA1ProcessMessageBlock(context);
}

580
crypto/sha224-256.c Normal file
View File

@ -0,0 +1,580 @@
/************************* sha224-256.c ************************/
/***************** See RFC 6234 for details. *******************/
/* Copyright (c) 2011 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */
/*
* Description:
* This file implements the Secure Hash Algorithms SHA-224 and
* SHA-256 as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-3/fips180-3_final.pdf
*
* The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
* message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given
* message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-224 and SHA-256 are defined in terms of 32-bit "words".
* This code uses <stdint.h> (included via "sha.h") to define 32-
* and 8-bit unsigned integer types. If your C compiler does not
* support 32-bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-224 and SHA-256 are designed to work with messages less
* than 2^64 bits long. This implementation uses SHA224/256Input()
* to hash the bits that are a multiple of the size of an 8-bit
* octet, and then optionally uses SHA224/256FinalBits()
* to hash the final few bits of the input.
*/
#include "crypto/sha.h"
#include "crypto/sha-private.h"
/* Define the SHA shift, rotate left, and rotate right macros */
#define SHA256_SHR(bits,word) ((word) >> (bits))
#define SHA256_ROTL(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
#define SHA256_ROTR(bits,word) \
(((word) >> (bits)) | ((word) << (32-(bits))))
/* Define the SHA SIGMA and sigma macros */
#define SHA256_SIGMA0(word) \
(SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
#define SHA256_SIGMA1(word) \
(SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
#define SHA256_sigma0(word) \
(SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
#define SHA256_sigma1(word) \
(SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
/*
* Add "length" to the length.
* Set Corrupted when overflow has occurred.
*/
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong : \
(context)->Corrupted )
/* Local Function Prototypes */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
static void SHA224_256ProcessMessageBlock(SHA256Context *context);
static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte);
static void SHA224_256PadMessage(SHA256Context *context,
uint8_t Pad_Byte);
static int SHA224_256ResultN(SHA256Context *context,
uint8_t Message_Digest[ ], int HashSize);
/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
static uint32_t SHA224_H0[SHA256HashSize/4] = {
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
};
/* Initial Hash Values: FIPS 180-3 section 5.3.3 */
static uint32_t SHA256_H0[SHA256HashSize/4] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
/*
* SHA224Reset
*
* Description:
* This function will initialize the SHA224Context in preparation
* for computing a new SHA224 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int SHA224Reset(SHA224Context *context)
{
return SHA224_256Reset(context, SHA224_H0);
}
/*
* SHA224Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_array[ ]: [in]
* An array of octets representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array.
*
* Returns:
* sha Error Code.
*
*/
int SHA224Input(SHA224Context *context, const uint8_t *message_array,
unsigned int length)
{
return SHA256Input(context, message_array, length);
}
/*
* SHA224FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int SHA224FinalBits(SHA224Context *context,
uint8_t message_bits, unsigned int length)
{
return SHA256FinalBits(context, message_bits, length);
}
/*
* SHA224Result
*
* Description:
* This function will return the 224-bit message digest
* into the Message_Digest array provided by the caller.
* NOTE:
* The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 27.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest[ ]: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int SHA224Result(SHA224Context *context,
uint8_t Message_Digest[SHA224HashSize])
{
return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
}
/*
* SHA256Reset
*
* Description:
* This function will initialize the SHA256Context in preparation
* for computing a new SHA256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int SHA256Reset(SHA256Context *context)
{
return SHA224_256Reset(context, SHA256_H0);
}
/*
* SHA256Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_array[ ]: [in]
* An array of octets representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array.
*
* Returns:
* sha Error Code.
*/
int SHA256Input(SHA256Context *context, const uint8_t *message_array,
unsigned int length)
{
if (!context) return shaNull;
if (!length) return shaSuccess;
if (!message_array) return shaNull;
if (context->Computed) return context->Corrupted = shaStateError;
if (context->Corrupted) return context->Corrupted;
while (length--) {
context->Message_Block[context->Message_Block_Index++] =
*message_array;
if ((SHA224_256AddLength(context, 8) == shaSuccess) &&
(context->Message_Block_Index == SHA256_Message_Block_Size))
SHA224_256ProcessMessageBlock(context);
message_array++;
}
return context->Corrupted;
}
/*
* SHA256FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int SHA256FinalBits(SHA256Context *context,
uint8_t message_bits, unsigned int length)
{
static uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
};
static uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
};
if (!context) return shaNull;
if (!length) return shaSuccess;
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
if (length >= 8) return context->Corrupted = shaBadParam;
SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length]));
return context->Corrupted;
}
/*
* SHA256Result
*
* Description:
* This function will return the 256-bit message digest
* into the Message_Digest array provided by the caller.
* NOTE:
* The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 31.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest[ ]: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int SHA256Result(SHA256Context *context,
uint8_t Message_Digest[SHA256HashSize])
{
return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
}
/*
* SHA224_256Reset
*
* Description:
* This helper function will initialize the SHA256Context in
* preparation for computing a new SHA-224 or SHA-256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
* H0[ ]: [in]
* The initial hash value array to use.
*
* Returns:
* sha Error Code.
*/
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
{
if (!context) return shaNull;
context->Length_High = context->Length_Low = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = H0[0];
context->Intermediate_Hash[1] = H0[1];
context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7];
context->Computed = 0;
context->Corrupted = shaSuccess;
return shaSuccess;
}
/*
* SHA224_256ProcessMessageBlock
*
* Description:
* This helper function will process the next 512 bits of the
* message stored in the Message_Block array.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the Secure Hash Standard.
*/
static void SHA224_256ProcessMessageBlock(SHA256Context *context)
{
/* Constants defined in FIPS 180-3, section 4.2.2 */
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
int t, t4; /* Loop counter */
uint32_t temp1, temp2; /* Temporary word value */
uint32_t W[64]; /* Word sequence */
uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = t4 = 0; t < 16; t++, t4 += 4)
W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
(((uint32_t)context->Message_Block[t4 + 1]) << 16) |
(((uint32_t)context->Message_Block[t4 + 2]) << 8) |
(((uint32_t)context->Message_Block[t4 + 3]));
for (t = 16; t < 64; t++)
W[t] = SHA256_sigma1(W[t-2]) + W[t-7] +
SHA256_sigma0(W[t-15]) + W[t-16];
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
F = context->Intermediate_Hash[5];
G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7];
for (t = 0; t < 64; t++) {
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C);
H = G;
G = F;
F = E;
E = D + temp1;
D = C;
C = B;
B = A;
A = temp1 + temp2;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H;
context->Message_Block_Index = 0;
}
/*
* SHA224_256Finalize
*
* Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*/
static void SHA224_256Finalize(SHA256Context *context,
uint8_t Pad_Byte)
{
int i;
SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_High = 0; /* and clear length */
context->Length_Low = 0;
context->Computed = 1;
}
/*
* SHA224_256PadMessage
*
* Description:
* According to the standard, the message must be padded to the next
* even multiple of 512 bits. The first padding bit must be a '1'.
* The last 64 bits represent the length of the original message.
* All bits in between should be 0. This helper function will pad
* the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad.
* Pad_Byte: [in]
* The last byte to add to the message block before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void SHA224_256PadMessage(SHA256Context *context,
uint8_t Pad_Byte)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
} else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context);
}
/*
* SHA224_256ResultN
*
* Description:
* This helper function will return the 224-bit or 256-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE:
* The first octet of hash is stored in the element with index 0,
* the last octet of hash in the element with index 27/31.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest[ ]: [out]
* Where the digest is returned.
* HashSize: [in]
* The size of the hash, either 28 or 32.
*
* Returns:
* sha Error Code.
*/
static int SHA224_256ResultN(SHA256Context *context,
uint8_t Message_Digest[ ], int HashSize)
{
int i;
if (!context) return shaNull;
if (!Message_Digest) return shaNull;
if (context->Corrupted) return context->Corrupted;
if (!context->Computed)
SHA224_256Finalize(context, 0x80);
for (i = 0; i < HashSize; ++i)
Message_Digest[i] = (uint8_t)
(context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
return shaSuccess;
}

1032
crypto/sha384-512.c Normal file

File diff suppressed because it is too large Load Diff

288
crypto/usha.c Normal file
View File

@ -0,0 +1,288 @@
/**************************** usha.c ***************************/
/***************** See RFC 6234 for details. *******************/
/* Copyright (c) 2011 IETF Trust and the persons identified as */
/* authors of the code. All rights reserved. */
/* See sha.h for terms of use and redistribution. */
/*
* Description:
* This file implements a unified interface to the SHA algorithms.
*/
#include "crypto/sha.h"
/*
* USHAReset
*
* Description:
* This function will initialize the SHA Context in preparation
* for computing a new SHA message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
* whichSha: [in]
* Selects which SHA reset to call
*
* Returns:
* sha Error Code.
*
*/
int USHAReset(USHAContext *context, enum SHAversion whichSha)
{
if (!context) return shaNull;
context->whichSha = whichSha;
switch (whichSha) {
case SHA1: return SHA1Reset((SHA1Context*)&context->ctx);
case SHA224: return SHA224Reset((SHA224Context*)&context->ctx);
case SHA256: return SHA256Reset((SHA256Context*)&context->ctx);
case SHA384: return SHA384Reset((SHA384Context*)&context->ctx);
case SHA512: return SHA512Reset((SHA512Context*)&context->ctx);
default: return shaBadParam;
}
}
/*
* USHAInput
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_array: [in]
* An array of octets representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array.
*
* Returns:
* sha Error Code.
*
*/
int USHAInput(USHAContext *context,
const uint8_t *bytes, unsigned int bytecount)
{
if (!context) return shaNull;
switch (context->whichSha) {
case SHA1:
return SHA1Input((SHA1Context*)&context->ctx, bytes,
bytecount);
case SHA224:
return SHA224Input((SHA224Context*)&context->ctx, bytes,
bytecount);
case SHA256:
return SHA256Input((SHA256Context*)&context->ctx, bytes,
bytecount);
case SHA384:
return SHA384Input((SHA384Context*)&context->ctx, bytes,
bytecount);
case SHA512:
return SHA512Input((SHA512Context*)&context->ctx, bytes,
bytecount);
default: return shaBadParam;
}
}
/*
* USHAFinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update.
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count)
{
if (!context) return shaNull;
switch (context->whichSha) {
case SHA1:
return SHA1FinalBits((SHA1Context*)&context->ctx, bits,
bit_count);
case SHA224:
return SHA224FinalBits((SHA224Context*)&context->ctx, bits,
bit_count);
case SHA256:
return SHA256FinalBits((SHA256Context*)&context->ctx, bits,
bit_count);
case SHA384:
return SHA384FinalBits((SHA384Context*)&context->ctx, bits,
bit_count);
case SHA512:
return SHA512FinalBits((SHA512Context*)&context->ctx, bits,
bit_count);
default: return shaBadParam;
}
}
/*
* USHAResult
*
* Description:
* This function will return the message digest of the appropriate
* bit size, as returned by USHAHashSizeBits(whichSHA) for the
* 'whichSHA' value used in the preceeding call to USHAReset,
* into the Message_Digest array provided by the caller.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA-1 hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*
*/
int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize])
{
if (!context) return shaNull;
switch (context->whichSha) {
case SHA1:
return SHA1Result((SHA1Context*)&context->ctx, Message_Digest);
case SHA224:
return SHA224Result((SHA224Context*)&context->ctx,
Message_Digest);
case SHA256:
return SHA256Result((SHA256Context*)&context->ctx,
Message_Digest);
case SHA384:
return SHA384Result((SHA384Context*)&context->ctx,
Message_Digest);
case SHA512:
return SHA512Result((SHA512Context*)&context->ctx,
Message_Digest);
default: return shaBadParam;
}
}
/*
* USHABlockSize
*
* Description:
* This function will return the blocksize for the given SHA
* algorithm.
*
* Parameters:
* whichSha:
* which SHA algorithm to query
*
* Returns:
* block size
*
*/
int USHABlockSize(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA1: return SHA1_Message_Block_Size;
case SHA224: return SHA224_Message_Block_Size;
case SHA256: return SHA256_Message_Block_Size;
case SHA384: return SHA384_Message_Block_Size;
default:
case SHA512: return SHA512_Message_Block_Size;
}
}
/*
* USHAHashSize
*
* Description:
* This function will return the hashsize for the given SHA
* algorithm.
*
* Parameters:
* whichSha:
* which SHA algorithm to query
*
* Returns:
* hash size
*
*/
int USHAHashSize(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA1: return SHA1HashSize;
case SHA224: return SHA224HashSize;
case SHA256: return SHA256HashSize;
case SHA384: return SHA384HashSize;
default:
case SHA512: return SHA512HashSize;
}
}
/*
* USHAHashSizeBits
*
* Description:
* This function will return the hashsize for the given SHA
* algorithm, expressed in bits.
*
* Parameters:
* whichSha:
* which SHA algorithm to query
*
* Returns:
* hash size in bits
*
*/
int USHAHashSizeBits(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA1: return SHA1HashSizeBits;
case SHA224: return SHA224HashSizeBits;
case SHA256: return SHA256HashSizeBits;
case SHA384: return SHA384HashSizeBits;
default:
case SHA512: return SHA512HashSizeBits;
}
}
/*
* USHAHashName
*
* Description:
* This function will return the name of the given SHA algorithm
* as a string.
*
* Parameters:
* whichSha:
* which SHA algorithm to query
*
* Returns:
* character string with the name in it
*
*/
const char *USHAHashName(enum SHAversion whichSha)
{
switch (whichSha) {
case SHA1: return "SHA1";
case SHA224: return "SHA224";
case SHA256: return "SHA256";
case SHA384: return "SHA384";
default:
case SHA512: return "SHA512";
}
}

18
include/crypto/aes-gcm.h Normal file
View File

@ -0,0 +1,18 @@
//
// aes-gcm.h
// MKo
//
// Created by Markus Kosmal on 20/11/14.
//
//
#ifndef mko_aes_gcm_h
#define mko_aes_gcm_h
#include "types.h"
int aes_gcm_encrypt(unsigned char* output, const unsigned char* input, int input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len);
int aes_gcm_decrypt(unsigned char* output, const unsigned char* input, int input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len);
#endif

74
include/crypto/aes.h Normal file
View File

@ -0,0 +1,74 @@
/******************************************************************************
*
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
*
* This is a simple and straightforward implementation of the AES Rijndael
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
* of this work was correctness & accuracy. It is written in 'C' without any
* particular focus upon optimization or speed. It should be endian (memory
* byte order) neutral since the few places that care are handled explicitly.
*
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
*
* It is intended for general purpose use, but was written in support of GRC's
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
*
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
*
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
*
*******************************************************************************/
#ifndef AES_HEADER
#define AES_HEADER
/******************************************************************************/
#define AES_DECRYPTION 0 // whether AES decryption is supported
/******************************************************************************/
#include "types.h"
#define ENCRYPT 1 // specify whether we're encrypting
#define DECRYPT 0 // or decrypting
typedef unsigned char uchar; // add some convienent shorter types
typedef unsigned int uint;
/******************************************************************************
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
******************************************************************************/
void aes_init_keygen_tables( void );
/******************************************************************************
* AES_CONTEXT : cipher context / holds inter-call data
******************************************************************************/
typedef struct {
int mode; // 1 for Encryption, 0 for Decryption
int rounds; // keysize-based rounds count
uint32_t *rk; // pointer to current round key
uint32_t buf[68]; // key expansion buffer
} aes_context;
/******************************************************************************
* AES_SETKEY : called to expand the key for encryption or decryption
******************************************************************************/
int aes_setkey( aes_context *ctx, // pointer to context
int mode, // 1 or 0 for Encrypt/Decrypt
const uchar *key, // AES input key
uint keysize ); // size in bytes (must be 16, 24, 32 for
// 128, 192 or 256-bit keys respectively)
// returns 0 for success
/******************************************************************************
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
******************************************************************************/
int aes_cipher( aes_context *ctx, // pointer to context
const uchar input[16], // 128-bit block to en/decipher
uchar output[16] ); // 128-bit output result block
// returns 0 for success
#endif /* AES_HEADER */

178
include/crypto/gcm.h Normal file
View File

@ -0,0 +1,178 @@
/******************************************************************************
*
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
*
* This is a simple and straightforward implementation of AES-GCM authenticated
* encryption. The focus of this work was correctness & accuracy. It is written
* in straight 'C' without any particular focus upon optimization or speed. It
* should be endian (memory byte order) neutral since the few places that care
* are handled explicitly.
*
* This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
*
* It is intended for general purpose use, but was written in support of GRC's
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
*
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \
* gcm/gcm-revised-spec.pdf
*
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
*
*******************************************************************************/
#ifndef GCM_HEADER
#define GCM_HEADER
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
#include "crypto/aes.h" // gcm_context includes aes_context
#include "types.h"
/******************************************************************************
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
******************************************************************************/
typedef struct {
int mode; // cipher direction: encrypt/decrypt
uint64_t len; // cipher data length processed so far
uint64_t add_len; // total add data length
uint64_t HL[16]; // precalculated lo-half HTable
uint64_t HH[16]; // precalculated hi-half HTable
uchar base_ectr[16]; // first counter-mode cipher output for tag
uchar y[16]; // the current cipher-input IV|Counter value
uchar buf[16]; // buf working value
aes_context aes_ctx; // cipher context used
} gcm_context;
/******************************************************************************
* GCM_CONTEXT : MUST be called once before ANY use of this library
******************************************************************************/
int gcm_initialize( void );
/******************************************************************************
* GCM_SETKEY : sets the GCM (and AES) keying material for use
******************************************************************************/
int gcm_setkey( gcm_context *ctx, // caller-provided context ptr
const uchar *key, // pointer to cipher key
const uint keysize // size in bytes (must be 16, 24, 32 for
// 128, 192 or 256-bit keys respectively)
); // returns 0 for success
/******************************************************************************
*
* GCM_CRYPT_AND_TAG
*
* This either encrypts or decrypts the user-provided data and, either
* way, generates an authentication tag of the requested length. It must be
* called with a GCM context whose key has already been set with GCM_SETKEY.
*
* The user would typically call this explicitly to ENCRYPT a buffer of data
* and optional associated data, and produce its an authentication tag.
*
* To reverse the process the user would typically call the companion
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
* to perform its decryption and tag generation, which it then compares.
*
******************************************************************************/
int gcm_crypt_and_tag(
gcm_context *ctx, // gcm context with key already setup
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data
size_t add_len, // byte length of the additional AEAD data
const uchar *input, // pointer to the cipher data source
uchar *output, // pointer to the cipher data destination
size_t length, // byte length of the cipher data
uchar *tag, // pointer to the tag to be generated
size_t tag_len ); // byte length of the tag to be generated
/******************************************************************************
*
* GCM_AUTH_DECRYPT
*
* This DECRYPTS a user-provided data buffer with optional associated data.
* It then verifies a user-supplied authentication tag against the tag just
* re-created during decryption to verify that the data has not been altered.
*
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
* and authentication tag generation.
*
******************************************************************************/
int gcm_auth_decrypt(
gcm_context *ctx, // gcm context with key already setup
const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data
size_t add_len, // byte length of the additional AEAD data
const uchar *input, // pointer to the cipher data source
uchar *output, // pointer to the cipher data destination
size_t length, // byte length of the cipher data
const uchar *tag, // pointer to the tag to be authenticated
size_t tag_len ); // byte length of the tag <= 16
/******************************************************************************
*
* GCM_START
*
* Given a user-provided GCM context, this initializes it, sets the encryption
* mode, and preprocesses the initialization vector and additional AEAD data.
*
******************************************************************************/
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
int mode, // ENCRYPT (1) or DECRYPT (0)
const uchar *iv, // pointer to initialization vector
size_t iv_len, // IV length in bytes (should == 12)
const uchar *add, // pointer to additional AEAD data (NULL if none)
size_t add_len ); // length of additional AEAD data (bytes)
/******************************************************************************
*
* GCM_UPDATE
*
* This is called once or more to process bulk plaintext or ciphertext data.
* We give this some number of bytes of input and it returns the same number
* of output bytes. If called multiple times (which is fine) all but the final
* invocation MUST be called with length mod 16 == 0. (Only the final call can
* have a partial block length of < 128 bits.)
*
******************************************************************************/
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
size_t length, // length, in bytes, of data to process
const uchar *input, // pointer to source data
uchar *output ); // pointer to destination data
/******************************************************************************
*
* GCM_FINISH
*
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
* It performs the final GHASH to produce the resulting authentication TAG.
*
******************************************************************************/
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
size_t tag_len ); // length, in bytes, of the tag-receiving buf
/******************************************************************************
*
* GCM_ZERO_CTX
*
* The GCM context contains both the GCM context and the AES context.
* This includes keying and key-related material which is security-
* sensitive, so it MUST be zeroed after use. This function does that.
*
******************************************************************************/
void gcm_zero_ctx( gcm_context *ctx );
#endif /* GCM_HEADER */

View File

@ -0,0 +1,28 @@
/************************ sha-private.h ************************/
/***************** See RFC 6234 for details. *******************/
#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H
/*
* These definitions are defined in FIPS 180-3, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2, and 4.1.3.
*
* The definitions used in FIPS 180-3 are as follows:
*/
#ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* USE_MODIFIED_MACROS */
/*
* The following definitions are equivalent and potentially faster.
*/
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#endif /* _SHA_PRIVATE__H */

356
include/crypto/sha.h Normal file
View File

@ -0,0 +1,356 @@
/**************************** sha.h ****************************/
/***************** See RFC 6234 for details. *******************/
/*
Copyright (c) 2011 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
- Redistributions of source code must retain the above
copyright notice, this list of conditions and
the following disclaimer.
- 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.
- Neither the name of Internet Society, IETF or IETF Trust, nor
the names of specific contributors, may be used to endorse or
promote products derived from this software without specific
prior written permission.
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 OWNER 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.
*/
#ifndef _SHA_H_
#define _SHA_H_
/*
* Description:
* This file implements the Secure Hash Algorithms
* as defined in the U.S. National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-3 published in October 2008
* and formerly defined in its predecessors, FIPS PUB 180-1
* and FIP PUB 180-2.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-3/fips180-3_final.pdf
*
* The five hashes are defined in these sizes:
* SHA-1 20 byte / 160 bit
* SHA-224 28 byte / 224 bit
* SHA-256 32 byte / 256 bit
* SHA-384 48 byte / 384 bit
* SHA-512 64 byte / 512 bit
*
* Compilation Note:
* These files may be compiled with two options:
* USE_32BIT_ONLY - use 32-bit arithmetic only, for systems
* without 64-bit integers
*
* USE_MODIFIED_MACROS - use alternate form of the SHA_Ch()
* and SHA_Maj() macros that are equivalent
* and potentially faster on many systems
*
*/
#include "types.h"
/*
* If you do not have the ISO standard stdint.h header file, then you
* must typedef the following:
* name meaning
* uint64_t unsigned 64-bit integer
* uint32_t unsigned 32-bit integer
* uint8_t unsigned 8-bit integer (i.e., unsigned char)
* int_least16_t integer of >= 16 bits
*
* See stdint-example.h
*/
#ifndef _SHA_enum_
#define _SHA_enum_
/*
* All SHA functions return one of these values.
*/
enum {
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError, /* called Input after FinalBits or Result */
shaBadParam /* passed a bad parameter */
};
#endif /* _SHA_enum_ */
/*
* These constants hold size information for each of the SHA
* hashing operations
*/
enum {
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
SHA512_Message_Block_Size = 128,
USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
SHA384HashSize = 48, SHA512HashSize = 64,
USHAMaxHashSize = SHA512HashSize,
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
};
/*
* These constants are used in the USHA (Unified SHA) functions.
*/
typedef enum SHAversion {
SHA1, SHA224, SHA256, SHA384, SHA512
} SHAversion;
/*
* This structure will hold context information for the SHA-1
* hashing operation.
*/
typedef struct SHA1Context {
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_High; /* Message length in bits */
uint32_t Length_Low; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA1_Message_Block_Size];
int Computed; /* Is the hash computed? */
int Corrupted; /* Cumulative corruption code */
} SHA1Context;
/*
* This structure will hold context information for the SHA-256
* hashing operation.
*/
typedef struct SHA256Context {
uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
uint32_t Length_High; /* Message length in bits */
uint32_t Length_Low; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA256_Message_Block_Size];
int Computed; /* Is the hash computed? */
int Corrupted; /* Cumulative corruption code */
} SHA256Context;
/*
* This structure will hold context information for the SHA-512
* hashing operation.
*/
typedef struct SHA512Context {
#ifdef USE_32BIT_ONLY
uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */
uint32_t Length[4]; /* Message length in bits */
#else /* !USE_32BIT_ONLY */
uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
uint64_t Length_High, Length_Low; /* Message length in bits */
#endif /* USE_32BIT_ONLY */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 1024-bit message blocks */
uint8_t Message_Block[SHA512_Message_Block_Size];
int Computed; /* Is the hash computed?*/
int Corrupted; /* Cumulative corruption code */
} SHA512Context;
/*
* This structure will hold context information for the SHA-224
* hashing operation. It uses the SHA-256 structure for computation.
*/
typedef struct SHA256Context SHA224Context;
/*
* This structure will hold context information for the SHA-384
* hashing operation. It uses the SHA-512 structure for computation.
*/
typedef struct SHA512Context SHA384Context;
/*
* This structure holds context information for all SHA
* hashing operations.
*/
typedef struct USHAContext {
int whichSha; /* which SHA is being used */
union {
SHA1Context sha1Context;
SHA224Context sha224Context; SHA256Context sha256Context;
SHA384Context sha384Context; SHA512Context sha512Context;
} ctx;
} USHAContext;
/*
* This structure will hold context information for the HMAC
* keyed-hashing operation.
*/
typedef struct HMACContext {
int whichSha; /* which SHA is being used */
int hashSize; /* hash size of SHA being used */
int blockSize; /* block size of SHA being used */
USHAContext shaContext; /* SHA context */
unsigned char k_opad[USHA_Max_Message_Block_Size];
/* outer padding - key XORd with opad */
int Computed; /* Is the MAC computed? */
int Corrupted; /* Cumulative corruption code */
} HMACContext;
/*
* This structure will hold context information for the HKDF
* extract-and-expand Key Derivation Functions.
*/
typedef struct HKDFContext {
int whichSha; /* which SHA is being used */
HMACContext hmacContext;
int hashSize; /* hash size of SHA being used */
unsigned char prk[USHAMaxHashSize];
/* pseudo-random key - output of hkdfInput */
int Computed; /* Is the key material computed? */
int Corrupted; /* Cumulative corruption code */
} HKDFContext;
/*
* Function Prototypes
*/
/* SHA-1 */
extern int SHA1Reset(SHA1Context *);
extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
unsigned int bytecount);
extern int SHA1FinalBits(SHA1Context *, uint8_t bits,
unsigned int bit_count);
extern int SHA1Result(SHA1Context *,
uint8_t Message_Digest[SHA1HashSize]);
/* SHA-224 */
extern int SHA224Reset(SHA224Context *);
extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
unsigned int bytecount);
extern int SHA224FinalBits(SHA224Context *, uint8_t bits,
unsigned int bit_count);
extern int SHA224Result(SHA224Context *,
uint8_t Message_Digest[SHA224HashSize]);
/* SHA-256 */
extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
unsigned int bytecount);
extern int SHA256FinalBits(SHA256Context *, uint8_t bits,
unsigned int bit_count);
extern int SHA256Result(SHA256Context *,
uint8_t Message_Digest[SHA256HashSize]);
/* SHA-384 */
extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
unsigned int bytecount);
extern int SHA384FinalBits(SHA384Context *, uint8_t bits,
unsigned int bit_count);
extern int SHA384Result(SHA384Context *,
uint8_t Message_Digest[SHA384HashSize]);
/* SHA-512 */
extern int SHA512Reset(SHA512Context *);
extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
unsigned int bytecount);
extern int SHA512FinalBits(SHA512Context *, uint8_t bits,
unsigned int bit_count);
extern int SHA512Result(SHA512Context *,
uint8_t Message_Digest[SHA512HashSize]);
/* Unified SHA functions, chosen by whichSha */
extern int USHAReset(USHAContext *context, SHAversion whichSha);
extern int USHAInput(USHAContext *context,
const uint8_t *bytes, unsigned int bytecount);
extern int USHAFinalBits(USHAContext *context,
uint8_t bits, unsigned int bit_count);
extern int USHAResult(USHAContext *context,
uint8_t Message_Digest[USHAMaxHashSize]);
extern int USHABlockSize(enum SHAversion whichSha);
extern int USHAHashSize(enum SHAversion whichSha);
extern int USHAHashSizeBits(enum SHAversion whichSha);
extern const char *USHAHashName(enum SHAversion whichSha);
/*
* HMAC Keyed-Hashing for Message Authentication, RFC 2104,
* for all SHAs.
* This interface allows a fixed-length text input to be used.
*/
extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
const unsigned char *text, /* pointer to data stream */
int text_len, /* length of data stream */
const unsigned char *key, /* pointer to authentication key */
int key_len, /* length of authentication key */
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
/*
* HMAC Keyed-Hashing for Message Authentication, RFC 2104,
* for all SHAs.
* This interface allows any length of text input to be used.
*/
extern int hmacReset(HMACContext *context, enum SHAversion whichSha,
const unsigned char *key, int key_len);
extern int hmacInput(HMACContext *context, const unsigned char *text,
int text_len);
extern int hmacFinalBits(HMACContext *context, uint8_t bits,
unsigned int bit_count);
extern int hmacResult(HMACContext *context,
uint8_t digest[USHAMaxHashSize]);
/*
* HKDF HMAC-based Extract-and-Expand Key Derivation Function,
* RFC 5869, for all SHAs.
*/
extern int hkdf(SHAversion whichSha, const unsigned char *salt,
int salt_len, const unsigned char *ikm, int ikm_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len);
extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt,
int salt_len, const unsigned char *ikm,
int ikm_len, uint8_t prk[USHAMaxHashSize]);
extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
int prk_len, const unsigned char *info,
int info_len, uint8_t okm[ ], int okm_len);
/*
* HKDF HMAC-based Extract-and-Expand Key Derivation Function,
* RFC 5869, for all SHAs.
* This interface allows any length of text input to be used.
*/
extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
const unsigned char *salt, int salt_len);
extern int hkdfInput(HKDFContext *context, const unsigned char *ikm,
int ikm_len);
extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
unsigned int ikm_bit_count);
extern int hkdfResult(HKDFContext *context,
uint8_t prk[USHAMaxHashSize],
const unsigned char *info, int info_len,
uint8_t okm[USHAMaxHashSize], int okm_len);
#endif /* _SHA_H_ */

View File

@ -8,6 +8,18 @@
#include <linux/string.h> // IWYU pragma: export
#include <linux/types.h>
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __s8 int8_t;
typedef __s16 int16_t;
typedef __s32 int32_t;
typedef __s64 int64_t;
typedef __s32 int_least32_t; /* integer of >= 32 bits */
typedef __s16 int_least16_t; /* integer of >= 16 bits */
#else /* USER_SPACE */
#include <errno.h> // IWYU pragma: export

View File

@ -4,6 +4,7 @@ USE_SYS_LIBS := no
#Userspace app makes here
BUILD_DIR := $(CURDIR)/build
DEPSDIR := $(BUILD_DIR)/deps
INCLUDE_DIR := $(CURDIR)/include
CC:=gcc
CCLD:=$(CC)
@ -15,7 +16,7 @@ ifeq ($(USE_SYS_LIBS), no)
REQ = $(LIBNETFILTER_QUEUE) $(LIBMNL) $(LIBCRYPTO)
endif
override CFLAGS += -DPKG_VERSION=\"$(PKG_FULLVERSION)\" -Wall -Wpedantic -Wno-unused-variable -std=gnu99
override CFLAGS += -DPKG_VERSION=\"$(PKG_FULLVERSION)\" -I$(INCLUDE_DIR) -Wall -Wpedantic -Wno-unused-variable -std=gnu99
LIBNFNETLINK_CFLAGS := -I$(DEPSDIR)/include
LIBNFNETLINK_LIBS := -L$(DEPSDIR)/lib
@ -37,7 +38,6 @@ OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
LIBNFNETLINK := $(DEPSDIR)/lib/libnfnetlink.la
LIBMNL := $(DEPSDIR)/lib/libmnl.la
LIBNETFILTER_QUEUE := $(DEPSDIR)/lib/libnetfilter_queue.la
#LIBCRYPTO := $(DEPSDIR)/lib64/libcrypto.a
.PHONY: default all dev dev_attrs prepare_dirs
default: all
@ -56,11 +56,6 @@ prepare_dirs:
mkdir -p $(BUILD_DIR)
mkdir -p $(DEPSDIR)
$(LIBCRYPTO):
cd deps/openssl && ./Configure --prefix=$(DEPSDIR) $(if $(CROSS_COMPILE_PLATFORM),--cross-compile-prefix=$(CROSS_COMPILE_PLATFORM)-,) --no-shared
$(MAKE) -C deps/openssl
$(MAKE) install_sw -C deps/openssl
$(LIBNFNETLINK):
cd deps/libnfnetlink && ./autogen.sh && ./configure --prefix=$(DEPSDIR) $(if $(CROSS_COMPILE_PLATFORM),--host=$(CROSS_COMPILE_PLATFORM),) --enable-static --disable-shared
$(MAKE) -C deps/libnfnetlink
@ -80,7 +75,7 @@ $(APP): $(OBJS) $(REQ)
@echo 'CCLD $(APP)'
$(CCLD) $(OBJS) -o $(APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread
$(BUILD_DIR)/%.o: %.c $(REQ) config.h
$(BUILD_DIR)/%.o: %.c $(REQ) $(INCLUDE_DIR)/config.h
@echo 'CC $@'
$(CC) -c $(CFLAGS) $(LDFLAGS) $< -o $@
@ -106,5 +101,4 @@ ifeq ($(USE_SYS_LIBS), no)
$(MAKE) distclean -C deps/libnetfilter_queue || true
$(MAKE) distclean -C deps/libmnl || true
$(MAKE) distclean -C deps/libnfnetlink || true
#$(MAKE) distclean -C deps/openssl || true
endif