mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
Linting and formatting of .c
and .h
with C/C++ IntelliSence
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "gcm.h"
|
||||
#include "gcm.h"
|
||||
|
||||
// mode : AES_ENCRYPT, AES_DECRYPT
|
||||
int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_length, const uint8_t *key, const size_t key_len, const uint8_t *iv, const size_t iv_len, const uint8_t *adata, size_t adata_len, uint8_t *atag, size_t atag_len);
|
||||
|
494
nfq/crypto/aes.c
494
nfq/crypto/aes.c
@@ -1,29 +1,29 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
*
|
||||
* 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 "aes.h"
|
||||
|
||||
static int aes_tables_inited = 0; // run-once flag for performing key
|
||||
// expasion table generation (see below)
|
||||
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
|
||||
@@ -37,175 +37,189 @@ static int aes_tables_inited = 0; // run-once flag for performing key
|
||||
* 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
|
||||
// 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
|
||||
#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 */
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
static uint32_t RCON[10]; // AES round constants
|
||||
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 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 ); }
|
||||
#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 ]; \
|
||||
}
|
||||
/*
|
||||
* 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 ]; \
|
||||
}
|
||||
#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++; }
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 i, x, y, z; // general purpose iteration and computation locals
|
||||
int pow[256];
|
||||
int log[256];
|
||||
|
||||
if (aes_tables_inited) return;
|
||||
if (aes_tables_inited)
|
||||
return;
|
||||
|
||||
// fill the 'pow' and 'log' tables over GF(2^8)
|
||||
for (i = 0, x = 1; i < 256; i++) {
|
||||
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++) {
|
||||
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
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
RSb[0x63] = 0x00;
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
for (i = 1; i < 256; i++) {
|
||||
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
|
||||
#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++) {
|
||||
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);
|
||||
((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
|
||||
#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);
|
||||
((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_tables_inited = 1; // flag that the tables have been generated
|
||||
} // to permit subsequent use of the AES cipher
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -218,25 +232,27 @@ void aes_init_keygen_tables(void)
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_set_encryption_key(aes_context *ctx,
|
||||
const uchar *key,
|
||||
uint keysize)
|
||||
const uchar *key,
|
||||
uint keysize)
|
||||
{
|
||||
uint i; // general purpose iteration local
|
||||
uint i; // general purpose iteration local
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
|
||||
for (i = 0; i < (keysize >> 2); i++) {
|
||||
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) {
|
||||
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);
|
||||
((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];
|
||||
@@ -245,12 +261,13 @@ int aes_set_encryption_key(aes_context *ctx,
|
||||
break;
|
||||
|
||||
case 12:
|
||||
for (i = 0; i < 8; i++, RK += 6) {
|
||||
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);
|
||||
((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];
|
||||
@@ -261,22 +278,23 @@ int aes_set_encryption_key(aes_context *ctx,
|
||||
break;
|
||||
|
||||
case 14:
|
||||
for (i = 0; i < 7; i++, RK += 8) {
|
||||
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);
|
||||
((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);
|
||||
((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];
|
||||
@@ -287,10 +305,10 @@ int aes_set_encryption_key(aes_context *ctx,
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -303,36 +321,38 @@ int aes_set_encryption_key(aes_context *ctx,
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_set_decryption_key(aes_context *ctx,
|
||||
const uchar *key,
|
||||
uint keysize)
|
||||
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
|
||||
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
|
||||
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);
|
||||
return (ret);
|
||||
|
||||
SK = cty.rk + cty.rounds * 4;
|
||||
|
||||
CPY128 // copy a 128-bit block from *SK to *RK
|
||||
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]] ^
|
||||
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);
|
||||
}
|
||||
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 */
|
||||
@@ -344,34 +364,42 @@ int aes_set_decryption_key(aes_context *ctx,
|
||||
* 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
|
||||
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.
|
||||
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
|
||||
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
|
||||
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);
|
||||
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));
|
||||
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));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -384,20 +412,24 @@ int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_cipher(aes_context *ctx,
|
||||
const uchar input[16],
|
||||
uchar output[16])
|
||||
const uchar input[16],
|
||||
uchar output[16])
|
||||
{
|
||||
int i;
|
||||
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
||||
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++;
|
||||
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 AES_DECRYPTION // whether AES decryption is supported
|
||||
|
||||
if (ctx->mode == DECRYPT)
|
||||
{
|
||||
@@ -409,29 +441,29 @@ int aes_cipher(aes_context *ctx,
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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 */
|
||||
{
|
||||
@@ -445,31 +477,31 @@ int aes_cipher(aes_context *ctx,
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
}
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
@@ -478,6 +510,6 @@ int aes_cipher(aes_context *ctx,
|
||||
PUT_UINT32_LE(X2, output, 8);
|
||||
PUT_UINT32_LE(X3, output, 12);
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
/* end of aes.c */
|
||||
|
@@ -1,35 +1,35 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
#define AES_DECRYPTION 0 // whether AES decryption is supported
|
||||
#define AES_DECRYPTION 0 // whether AES decryption is supported
|
||||
/******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define AES_ENCRYPT 1 // specify whether we're encrypting
|
||||
#define AES_DECRYPT 0 // or decrypting
|
||||
#define AES_ENCRYPT 1 // specify whether we're encrypting
|
||||
#define AES_DECRYPT 0 // or decrypting
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
@@ -38,41 +38,39 @@ typedef UINT32 uint32_t;
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
typedef unsigned char uchar; // add some convienent shorter types
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
404
nfq/crypto/gcm.c
404
nfq/crypto/gcm.c
@@ -1,26 +1,26 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
*
|
||||
* 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 "gcm.h"
|
||||
#include "aes.h"
|
||||
@@ -41,80 +41,79 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
/* 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).
|
||||
*/
|
||||
/*
|
||||
* 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 };
|
||||
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 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) ); }
|
||||
#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.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_MULT
|
||||
@@ -124,9 +123,9 @@ int gcm_initialize(void)
|
||||
* '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
|
||||
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;
|
||||
@@ -137,11 +136,13 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
|
||||
zh = ctx->HH[lo];
|
||||
zl = ctx->HL[lo];
|
||||
|
||||
for (i = 15; i >= 0; i--) {
|
||||
for (i = 15; i >= 0; i--)
|
||||
{
|
||||
lo = (uchar)(x[i] & 0x0f);
|
||||
hi = (uchar)(x[i] >> 4);
|
||||
|
||||
if (i != 15) {
|
||||
if (i != 15)
|
||||
{
|
||||
rem = (uchar)(zl & 0x0f);
|
||||
zl = (zh << 60) | (zl >> 4);
|
||||
zh = (zh >> 4);
|
||||
@@ -162,7 +163,6 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
|
||||
PUT_UINT32_BE(zl, output, 12);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_SETKEY
|
||||
@@ -172,26 +172,26 @@ static void gcm_mult(gcm_context *ctx, // pointer to established context
|
||||
*
|
||||
******************************************************************************/
|
||||
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)
|
||||
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
|
||||
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, AES_ENCRYPT, key, keysize)) != 0)
|
||||
return(ret);
|
||||
return (ret);
|
||||
if ((ret = aes_cipher(&ctx->aes_ctx, h, h)) != 0)
|
||||
return(ret);
|
||||
return (ret);
|
||||
|
||||
GET_UINT32_BE(hi, h, 0); // pack h as two 64-bit ints, big-endian
|
||||
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;
|
||||
|
||||
@@ -199,31 +199,33 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
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->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->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
|
||||
ctx->HL[0] = 0;
|
||||
|
||||
for (i = 4; i > 0; i >>= 1) {
|
||||
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) {
|
||||
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++) {
|
||||
for (j = 1; j < i; j++)
|
||||
{
|
||||
HiH[j] = vh ^ ctx->HH[j];
|
||||
HiL[j] = vl ^ ctx->HL[j];
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
|
||||
@@ -245,18 +247,18 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
* 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 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
|
||||
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
|
||||
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
|
||||
@@ -265,42 +267,48 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
ctx->len = 0;
|
||||
ctx->add_len = 0;
|
||||
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = AES_ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = AES_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)
|
||||
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
|
||||
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
|
||||
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) {
|
||||
while (iv_len > 0)
|
||||
{
|
||||
use_len = (iv_len < 16) ? iv_len : 16;
|
||||
for (i = 0; i < use_len; i++) ctx->y[i] ^= p[i];
|
||||
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];
|
||||
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);
|
||||
return (ret);
|
||||
|
||||
ctx->add_len = add_len;
|
||||
p = add;
|
||||
while (add_len > 0) {
|
||||
while (add_len > 0)
|
||||
{
|
||||
use_len = (add_len < 16) ? add_len : 16;
|
||||
for (i = 0; i < use_len; i++) ctx->buf[i] ^= p[i];
|
||||
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);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -314,48 +322,53 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
* 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 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
|
||||
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) {
|
||||
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;
|
||||
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);
|
||||
return (ret);
|
||||
|
||||
// encrypt or decrypt the input to the output
|
||||
if (ctx->mode == AES_ENCRYPT)
|
||||
{
|
||||
for (i = 0; i < use_len; i++) {
|
||||
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
|
||||
// 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
|
||||
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];
|
||||
@@ -364,13 +377,13 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
output[i] = (uchar)(ectr[i] ^ input[i]);
|
||||
}
|
||||
}
|
||||
gcm_mult(ctx, ctx->buf, ctx->buf); // perform a GHASH operation
|
||||
gcm_mult(ctx, ctx->buf, ctx->buf); // perform a GHASH operation
|
||||
|
||||
length -= use_len; // drop the remaining byte count to process
|
||||
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
|
||||
output += use_len; // bump our output pointer forward
|
||||
}
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -381,18 +394,20 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
* 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
|
||||
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 (tag_len != 0)
|
||||
memcpy(tag, ctx->base_ectr, tag_len);
|
||||
|
||||
if (orig_len || orig_add_len) {
|
||||
if (orig_len || orig_add_len)
|
||||
{
|
||||
memset(work_buf, 0x00, 16);
|
||||
|
||||
PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
|
||||
@@ -400,14 +415,15 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
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];
|
||||
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];
|
||||
for (i = 0; i < tag_len; i++)
|
||||
tag[i] ^= ctx->buf[i];
|
||||
}
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
@@ -426,29 +442,28 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
*
|
||||
******************************************************************************/
|
||||
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_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);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
@@ -462,37 +477,38 @@ int gcm_crypt_and_tag(
|
||||
*
|
||||
******************************************************************************/
|
||||
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_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
|
||||
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, AES_DECRYPT, iv, iv_len, add, add_len,
|
||||
input, output, length, check_tag, tag_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
|
||||
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);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
158
nfq/crypto/gcm.h
158
nfq/crypto/gcm.h
@@ -1,73 +1,70 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
||||
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
||||
|
||||
#include "aes.h" // gcm_context includes aes_context
|
||||
#include "aes.h" // gcm_context includes aes_context
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
typedef unsigned int size_t;// use the right type for length declarations
|
||||
typedef unsigned int size_t; // use the right type for length declarations
|
||||
typedef UINT32 uint32_t;
|
||||
typedef UINT64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -87,18 +84,17 @@ int gcm_setkey(gcm_context *ctx, // caller-provided context ptr
|
||||
*
|
||||
******************************************************************************/
|
||||
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_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
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -113,17 +109,16 @@ int gcm_crypt_and_tag(
|
||||
*
|
||||
******************************************************************************/
|
||||
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_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
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -133,13 +128,12 @@ int gcm_auth_decrypt(
|
||||
* 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)
|
||||
|
||||
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)
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -152,11 +146,10 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
* 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 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
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -166,10 +159,9 @@ int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
* 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
|
||||
|
||||
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
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@@ -15,54 +15,54 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.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.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* 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, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t 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);
|
||||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
|
||||
info_len, okm, okm_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -93,17 +93,19 @@ int hkdf(SHAversion whichSha,
|
||||
*
|
||||
*/
|
||||
int hkdfExtract(SHAversion whichSha,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
uint8_t prk[USHAMaxHashSize])
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
uint8_t prk[USHAMaxHashSize])
|
||||
{
|
||||
unsigned char nullSalt[USHAMaxHashSize];
|
||||
if (salt == 0) {
|
||||
if (salt == 0)
|
||||
{
|
||||
salt = nullSalt;
|
||||
salt_len = USHAHashSize(whichSha);
|
||||
memset(nullSalt, '\0', salt_len);
|
||||
}
|
||||
else if (salt_len < 0) {
|
||||
else if (salt_len < 0)
|
||||
{
|
||||
return shaBadParam;
|
||||
}
|
||||
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
|
||||
@@ -143,42 +145,51 @@ int hkdfExtract(SHAversion whichSha,
|
||||
*
|
||||
*/
|
||||
int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
{
|
||||
size_t hash_len, N;
|
||||
unsigned char T[USHAMaxHashSize];
|
||||
size_t Tlen, where, i;
|
||||
|
||||
if (info == 0) {
|
||||
if (info == 0)
|
||||
{
|
||||
info = (const unsigned char *)"";
|
||||
info_len = 0;
|
||||
}
|
||||
else if (info_len < 0) {
|
||||
else if (info_len < 0)
|
||||
{
|
||||
return shaBadParam;
|
||||
}
|
||||
if (okm_len <= 0) return shaBadParam;
|
||||
if (!okm) return shaBadParam;
|
||||
if (okm_len <= 0)
|
||||
return shaBadParam;
|
||||
if (!okm)
|
||||
return shaBadParam;
|
||||
|
||||
hash_len = USHAHashSize(whichSha);
|
||||
if (prk_len < hash_len) return shaBadParam;
|
||||
if (prk_len < hash_len)
|
||||
return shaBadParam;
|
||||
N = okm_len / hash_len;
|
||||
if ((okm_len % hash_len) != 0) N++;
|
||||
if (N > 255) return shaBadParam;
|
||||
if ((okm_len % hash_len) != 0)
|
||||
N++;
|
||||
if (N > 255)
|
||||
return shaBadParam;
|
||||
|
||||
Tlen = 0;
|
||||
where = 0;
|
||||
for (i = 1; i <= N; i++) {
|
||||
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;
|
||||
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));
|
||||
(i != N) ? hash_len : (okm_len - where));
|
||||
where += hash_len;
|
||||
Tlen = hash_len;
|
||||
}
|
||||
@@ -210,14 +221,16 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
*
|
||||
*/
|
||||
int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
|
||||
const unsigned char *salt, size_t salt_len)
|
||||
const unsigned char *salt, size_t salt_len)
|
||||
{
|
||||
unsigned char nullSalt[USHAMaxHashSize];
|
||||
if (!context) return shaNull;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
|
||||
context->whichSha = whichSha;
|
||||
context->hashSize = USHAHashSize(whichSha);
|
||||
if (salt == 0) {
|
||||
if (salt == 0)
|
||||
{
|
||||
salt = nullSalt;
|
||||
salt_len = context->hashSize;
|
||||
memset(nullSalt, '\0', salt_len);
|
||||
@@ -247,11 +260,14 @@ int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
|
||||
*
|
||||
*/
|
||||
int hkdfInput(HKDFContext *context, const unsigned char *ikm,
|
||||
size_t ikm_len)
|
||||
size_t ikm_len)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
if (context->Corrupted)
|
||||
return context->Corrupted;
|
||||
if (context->Computed)
|
||||
return context->Corrupted = shaStateError;
|
||||
return hmacInput(&context->hmacContext, ikm, ikm_len);
|
||||
}
|
||||
|
||||
@@ -276,11 +292,14 @@ int hkdfInput(HKDFContext *context, const unsigned char *ikm,
|
||||
* sha Error Code.
|
||||
*/
|
||||
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
|
||||
unsigned int ikm_bit_count)
|
||||
unsigned int ikm_bit_count)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -315,23 +334,27 @@ int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
|
||||
*
|
||||
*/
|
||||
int hkdfResult(HKDFContext *context,
|
||||
uint8_t prk[USHAMaxHashSize],
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
uint8_t prk[USHAMaxHashSize],
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t 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;
|
||||
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);
|
||||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
|
||||
info_len, okm, okm_len);
|
||||
context->Computed = 1;
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
|
@@ -14,44 +14,44 @@
|
||||
#include "sha.h"
|
||||
#include <stddef.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.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* 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, size_t length,
|
||||
const unsigned char *key, size_t key_len,
|
||||
uint8_t digest[USHAMaxHashSize])
|
||||
const unsigned char *message_array, size_t length,
|
||||
const unsigned char *key, size_t key_len,
|
||||
uint8_t digest[USHAMaxHashSize])
|
||||
{
|
||||
HMACContext context;
|
||||
return hmacReset(&context, whichSha, key, key_len) ||
|
||||
hmacInput(&context, message_array, length) ||
|
||||
hmacResult(&context, digest);
|
||||
hmacInput(&context, message_array, length) ||
|
||||
hmacResult(&context, digest);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -76,7 +76,7 @@ int hmac(SHAversion whichSha,
|
||||
*
|
||||
*/
|
||||
int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
const unsigned char *key, size_t key_len)
|
||||
const unsigned char *key, size_t key_len)
|
||||
{
|
||||
size_t i, blocksize, hashsize;
|
||||
int ret;
|
||||
@@ -87,7 +87,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
/* temporary buffer when keylen > blocksize */
|
||||
unsigned char tempkey[USHAMaxHashSize];
|
||||
|
||||
if (!context) return shaNull;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
context->Computed = 0;
|
||||
context->Corrupted = shaSuccess;
|
||||
|
||||
@@ -99,12 +100,14 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
* If key is longer than the hash blocksize,
|
||||
* reset it to key = HASH(key).
|
||||
*/
|
||||
if (key_len > blocksize) {
|
||||
if (key_len > blocksize)
|
||||
{
|
||||
USHAContext tcontext;
|
||||
int err = USHAReset(&tcontext, whichSha) ||
|
||||
USHAInput(&tcontext, key, key_len) ||
|
||||
USHAResult(&tcontext, tempkey);
|
||||
if (err != shaSuccess) return err;
|
||||
USHAInput(&tcontext, key, key_len) ||
|
||||
USHAResult(&tcontext, tempkey);
|
||||
if (err != shaSuccess)
|
||||
return err;
|
||||
|
||||
key = tempkey;
|
||||
key_len = hashsize;
|
||||
@@ -121,13 +124,15 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
* 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++) {
|
||||
/* 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++) {
|
||||
for (; i < blocksize; i++)
|
||||
{
|
||||
k_ipad[i] = 0x36;
|
||||
context->k_opad[i] = 0x5c;
|
||||
}
|
||||
@@ -135,8 +140,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
/* perform inner hash */
|
||||
/* init context for 1st pass */
|
||||
ret = USHAReset(&context->shaContext, whichSha) ||
|
||||
/* and start with inner pad */
|
||||
USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
/* and start with inner pad */
|
||||
USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
@@ -161,14 +166,17 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
*
|
||||
*/
|
||||
int hmacInput(HMACContext *context, const unsigned char *text,
|
||||
size_t text_len)
|
||||
size_t text_len)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
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);
|
||||
USHAInput(&context->shaContext, text, text_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,14 +199,17 @@ int hmacInput(HMACContext *context, const unsigned char *text,
|
||||
* sha Error Code.
|
||||
*/
|
||||
int hmacFinalBits(HMACContext *context,
|
||||
uint8_t bits, unsigned int bit_count)
|
||||
uint8_t bits, unsigned int bit_count)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
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);
|
||||
USHAFinalBits(&context->shaContext, bits, bit_count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -223,9 +234,12 @@ int hmacFinalBits(HMACContext *context,
|
||||
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;
|
||||
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.) */
|
||||
@@ -238,7 +252,7 @@ int hmacResult(HMACContext *context, uint8_t *digest)
|
||||
|
||||
/* start with outer pad */
|
||||
USHAInput(&context->shaContext, context->k_opad,
|
||||
context->blockSize) ||
|
||||
context->blockSize) ||
|
||||
|
||||
/* then results of 1st hash */
|
||||
USHAInput(&context->shaContext, digest, context->hashSize) ||
|
||||
|
@@ -10,16 +10,16 @@
|
||||
*/
|
||||
|
||||
#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)))
|
||||
#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)))
|
||||
#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))
|
||||
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
|
||||
|
161
nfq/crypto/sha.h
161
nfq/crypto/sha.h
@@ -85,12 +85,13 @@
|
||||
/*
|
||||
* All SHA functions return one of these values.
|
||||
*/
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
shaSuccess = 0,
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
shaStateError, /* called Input after FinalBits or Result */
|
||||
shaBadParam /* passed a bad parameter */
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
shaStateError, /* called Input after FinalBits or Result */
|
||||
shaBadParam /* passed a bad parameter */
|
||||
};
|
||||
#endif /* _SHA_enum_ */
|
||||
|
||||
@@ -98,41 +99,50 @@ enum {
|
||||
* These constants hold size information for each of the SHA
|
||||
* hashing operations
|
||||
*/
|
||||
enum {
|
||||
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
|
||||
enum
|
||||
{
|
||||
SHA1_Message_Block_Size = 64,
|
||||
SHA224_Message_Block_Size = 64,
|
||||
SHA256_Message_Block_Size = 64,
|
||||
USHA_Max_Message_Block_Size = SHA256_Message_Block_Size,
|
||||
|
||||
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
|
||||
SHA1HashSize = 20,
|
||||
SHA224HashSize = 28,
|
||||
SHA256HashSize = 32,
|
||||
USHAMaxHashSize = SHA256HashSize,
|
||||
|
||||
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
|
||||
SHA256HashSizeBits = 256, USHAMaxHashSizeBits = SHA256HashSizeBits
|
||||
SHA1HashSizeBits = 160,
|
||||
SHA224HashSizeBits = 224,
|
||||
SHA256HashSizeBits = 256,
|
||||
USHAMaxHashSizeBits = SHA256HashSizeBits
|
||||
};
|
||||
|
||||
/*
|
||||
* These constants are used in the USHA (Unified SHA) functions.
|
||||
*/
|
||||
typedef enum SHAversion {
|
||||
SHA224, SHA256
|
||||
typedef enum SHAversion
|
||||
{
|
||||
SHA224,
|
||||
SHA256
|
||||
} SHAversion;
|
||||
|
||||
/*
|
||||
* This structure will hold context information for the SHA-256
|
||||
* hashing operation.
|
||||
*/
|
||||
typedef struct SHA256Context {
|
||||
uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
|
||||
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 */
|
||||
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 */
|
||||
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 */
|
||||
int Computed; /* Is the hash computed? */
|
||||
int Corrupted; /* Cumulative corruption code */
|
||||
} SHA256Context;
|
||||
|
||||
/*
|
||||
@@ -145,10 +155,13 @@ typedef struct SHA256Context SHA224Context;
|
||||
* This structure holds context information for all SHA
|
||||
* hashing operations.
|
||||
*/
|
||||
typedef struct USHAContext {
|
||||
int whichSha; /* which SHA is being used */
|
||||
union {
|
||||
SHA224Context sha224Context; SHA256Context sha256Context;
|
||||
typedef struct USHAContext
|
||||
{
|
||||
int whichSha; /* which SHA is being used */
|
||||
union
|
||||
{
|
||||
SHA224Context sha224Context;
|
||||
SHA256Context sha256Context;
|
||||
} ctx;
|
||||
|
||||
} USHAContext;
|
||||
@@ -157,15 +170,16 @@ typedef struct 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 */
|
||||
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 */
|
||||
/* outer padding - key XORd with opad */
|
||||
int Computed; /* Is the MAC computed? */
|
||||
int Corrupted; /* Cumulative corruption code */
|
||||
|
||||
} HMACContext;
|
||||
|
||||
@@ -173,47 +187,47 @@ typedef struct 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 */
|
||||
typedef struct HKDFContext
|
||||
{
|
||||
int whichSha; /* which SHA is being used */
|
||||
HMACContext hmacContext;
|
||||
int hashSize; /* hash size of SHA being used */
|
||||
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 */
|
||||
/* pseudo-random key - output of hkdfInput */
|
||||
int Computed; /* Is the key material computed? */
|
||||
int Corrupted; /* Cumulative corruption code */
|
||||
} HKDFContext;
|
||||
|
||||
/*
|
||||
* Function Prototypes
|
||||
*/
|
||||
|
||||
|
||||
/* SHA-224 */
|
||||
int SHA224Reset(SHA224Context *);
|
||||
int SHA224Input(SHA224Context *, const uint8_t *bytes,
|
||||
unsigned int bytecount);
|
||||
unsigned int bytecount);
|
||||
int SHA224FinalBits(SHA224Context *, uint8_t bits,
|
||||
unsigned int bit_count);
|
||||
unsigned int bit_count);
|
||||
int SHA224Result(SHA224Context *,
|
||||
uint8_t Message_Digest[SHA224HashSize]);
|
||||
uint8_t Message_Digest[SHA224HashSize]);
|
||||
|
||||
/* SHA-256 */
|
||||
int SHA256Reset(SHA256Context *);
|
||||
int SHA256Input(SHA256Context *, const uint8_t *bytes,
|
||||
unsigned int bytecount);
|
||||
unsigned int bytecount);
|
||||
int SHA256FinalBits(SHA256Context *, uint8_t bits,
|
||||
unsigned int bit_count);
|
||||
unsigned int bit_count);
|
||||
int SHA256Result(SHA256Context *,
|
||||
uint8_t Message_Digest[SHA256HashSize]);
|
||||
uint8_t Message_Digest[SHA256HashSize]);
|
||||
|
||||
/* Unified SHA functions, chosen by whichSha */
|
||||
int USHAReset(USHAContext *context, SHAversion whichSha);
|
||||
int USHAInput(USHAContext *context,
|
||||
const uint8_t *bytes, unsigned int bytecount);
|
||||
const uint8_t *bytes, unsigned int bytecount);
|
||||
int USHAFinalBits(USHAContext *context,
|
||||
uint8_t bits, unsigned int bit_count);
|
||||
uint8_t bits, unsigned int bit_count);
|
||||
int USHAResult(USHAContext *context,
|
||||
uint8_t Message_Digest[USHAMaxHashSize]);
|
||||
uint8_t Message_Digest[USHAMaxHashSize]);
|
||||
int USHABlockSize(enum SHAversion whichSha);
|
||||
int USHAHashSize(enum SHAversion whichSha);
|
||||
|
||||
@@ -222,12 +236,12 @@ int USHAHashSize(enum SHAversion whichSha);
|
||||
* for all SHAs.
|
||||
* This interface allows a fixed-length text input to be used.
|
||||
*/
|
||||
int hmac(SHAversion whichSha, /* which SHA algorithm to use */
|
||||
const unsigned char *text, /* pointer to data stream */
|
||||
size_t text_len, /* length of data stream */
|
||||
const unsigned char *key, /* pointer to authentication key */
|
||||
size_t key_len, /* length of authentication key */
|
||||
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
|
||||
int hmac(SHAversion whichSha, /* which SHA algorithm to use */
|
||||
const unsigned char *text, /* pointer to data stream */
|
||||
size_t text_len, /* length of data stream */
|
||||
const unsigned char *key, /* pointer to authentication key */
|
||||
size_t key_len, /* length of authentication key */
|
||||
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
|
||||
|
||||
/*
|
||||
* HMAC Keyed-Hashing for Message Authentication, RFC 2104,
|
||||
@@ -235,31 +249,30 @@ int hmac(SHAversion whichSha, /* which SHA algorithm to use */
|
||||
* This interface allows any length of text input to be used.
|
||||
*/
|
||||
int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
const unsigned char *key, size_t key_len);
|
||||
const unsigned char *key, size_t key_len);
|
||||
int hmacInput(HMACContext *context, const unsigned char *text,
|
||||
size_t text_len);
|
||||
size_t text_len);
|
||||
int hmacFinalBits(HMACContext *context, uint8_t bits,
|
||||
unsigned int bit_count);
|
||||
unsigned int bit_count);
|
||||
int hmacResult(HMACContext *context,
|
||||
uint8_t digest[USHAMaxHashSize]);
|
||||
|
||||
uint8_t digest[USHAMaxHashSize]);
|
||||
|
||||
/*
|
||||
* HKDF HMAC-based Extract-and-Expand Key Derivation Function,
|
||||
* RFC 5869, for all SHAs.
|
||||
*/
|
||||
int hkdf(SHAversion whichSha,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[ ], size_t okm_len);
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[], size_t okm_len);
|
||||
|
||||
int hkdfExtract(SHAversion whichSha, const unsigned char *salt,
|
||||
size_t salt_len, const unsigned char *ikm,
|
||||
size_t ikm_len, uint8_t prk[USHAMaxHashSize]);
|
||||
int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
|
||||
size_t prk_len, const unsigned char *info,
|
||||
size_t info_len, uint8_t okm[ ], size_t okm_len);
|
||||
size_t salt_len, const unsigned char *ikm,
|
||||
size_t ikm_len, uint8_t prk[USHAMaxHashSize]);
|
||||
int hkdfExpand(SHAversion whichSha, const uint8_t prk[],
|
||||
size_t prk_len, const unsigned char *info,
|
||||
size_t info_len, uint8_t okm[], size_t okm_len);
|
||||
|
||||
/*
|
||||
* HKDF HMAC-based Extract-and-Expand Key Derivation Function,
|
||||
@@ -267,12 +280,12 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
|
||||
* This interface allows any length of text input to be used.
|
||||
*/
|
||||
int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
|
||||
const unsigned char *salt, size_t salt_len);
|
||||
const unsigned char *salt, size_t salt_len);
|
||||
int hkdfInput(HKDFContext *context, const unsigned char *ikm,
|
||||
size_t ikm_len);
|
||||
size_t ikm_len);
|
||||
int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
|
||||
unsigned int ikm_bit_count);
|
||||
unsigned int ikm_bit_count);
|
||||
int hkdfResult(HKDFContext *context,
|
||||
uint8_t prk[USHAMaxHashSize],
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[USHAMaxHashSize], size_t okm_len);
|
||||
uint8_t prk[USHAMaxHashSize],
|
||||
const unsigned char *info, size_t info_len,
|
||||
uint8_t okm[USHAMaxHashSize], size_t okm_len);
|
||||
|
@@ -44,54 +44,53 @@
|
||||
#include "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 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))
|
||||
#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 )
|
||||
#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);
|
||||
uint8_t Pad_Byte);
|
||||
static void SHA224_256PadMessage(SHA256Context *context,
|
||||
uint8_t Pad_Byte);
|
||||
uint8_t Pad_Byte);
|
||||
static int SHA224_256ResultN(SHA256Context *context,
|
||||
uint8_t Message_Digest[ ], int HashSize);
|
||||
uint8_t Message_Digest[], int HashSize);
|
||||
|
||||
/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
|
||||
static uint32_t SHA224_H0[SHA256HashSize/4] = {
|
||||
static uint32_t SHA224_H0[SHA256HashSize / 4] = {
|
||||
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
|
||||
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
|
||||
};
|
||||
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
|
||||
};
|
||||
static uint32_t SHA256_H0[SHA256HashSize / 4] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};
|
||||
|
||||
/*
|
||||
* SHA224Reset
|
||||
@@ -133,7 +132,7 @@ int SHA224Reset(SHA224Context *context)
|
||||
*
|
||||
*/
|
||||
int SHA224Input(SHA224Context *context, const uint8_t *message_array,
|
||||
unsigned int length)
|
||||
unsigned int length)
|
||||
{
|
||||
return SHA256Input(context, message_array, length);
|
||||
}
|
||||
@@ -183,7 +182,7 @@ int SHA224FinalBits(SHA224Context *context,
|
||||
* sha Error Code.
|
||||
*/
|
||||
int SHA224Result(SHA224Context *context,
|
||||
uint8_t Message_Digest[SHA224HashSize])
|
||||
uint8_t Message_Digest[SHA224HashSize])
|
||||
{
|
||||
return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
|
||||
}
|
||||
@@ -227,27 +226,32 @@ int SHA256Reset(SHA256Context *context)
|
||||
* sha Error Code.
|
||||
*/
|
||||
int SHA256Input(SHA256Context *context, const uint8_t *message_array,
|
||||
unsigned int length)
|
||||
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;
|
||||
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--) {
|
||||
while (length--)
|
||||
{
|
||||
context->Message_Block[context->Message_Block_Index++] =
|
||||
*message_array;
|
||||
*message_array;
|
||||
|
||||
if ((SHA224_256AddLength(context, 8) == shaSuccess) &&
|
||||
(context->Message_Block_Index == SHA256_Message_Block_Size))
|
||||
(context->Message_Block_Index == SHA256_Message_Block_Size))
|
||||
SHA224_256ProcessMessageBlock(context);
|
||||
|
||||
message_array++;
|
||||
}
|
||||
|
||||
return context->Corrupted;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -276,24 +280,26 @@ int SHA256FinalBits(SHA256Context *context,
|
||||
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
|
||||
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
|
||||
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
|
||||
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
|
||||
};
|
||||
/* 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
|
||||
};
|
||||
/* 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;
|
||||
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]));
|
||||
SHA224_256Finalize(context, (uint8_t)((message_bits & masks[length]) | markbit[length]));
|
||||
|
||||
return context->Corrupted;
|
||||
}
|
||||
@@ -341,10 +347,11 @@ int SHA256Result(SHA256Context *context,
|
||||
*/
|
||||
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
|
||||
context->Length_High = context->Length_Low = 0;
|
||||
context->Message_Block_Index = 0;
|
||||
context->Message_Block_Index = 0;
|
||||
|
||||
context->Intermediate_Hash[0] = H0[0];
|
||||
context->Intermediate_Hash[1] = H0[1];
|
||||
@@ -355,7 +362,7 @@ static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
|
||||
context->Intermediate_Hash[6] = H0[6];
|
||||
context->Intermediate_Hash[7] = H0[7];
|
||||
|
||||
context->Computed = 0;
|
||||
context->Computed = 0;
|
||||
context->Corrupted = shaSuccess;
|
||||
|
||||
return shaSuccess;
|
||||
@@ -396,12 +403,11 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
|
||||
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 */
|
||||
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
|
||||
@@ -412,8 +418,8 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
|
||||
(((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];
|
||||
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];
|
||||
@@ -424,9 +430,10 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
|
||||
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);
|
||||
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;
|
||||
@@ -468,14 +475,14 @@ static void SHA224_256ProcessMessageBlock(SHA256Context *context)
|
||||
* sha Error Code.
|
||||
*/
|
||||
static void SHA224_256Finalize(SHA256Context *context,
|
||||
uint8_t Pad_Byte)
|
||||
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_High = 0; /* and clear length */
|
||||
context->Length_Low = 0;
|
||||
context->Computed = 1;
|
||||
}
|
||||
@@ -505,7 +512,7 @@ static void SHA224_256Finalize(SHA256Context *context,
|
||||
* Nothing.
|
||||
*/
|
||||
static void SHA224_256PadMessage(SHA256Context *context,
|
||||
uint8_t Pad_Byte)
|
||||
uint8_t Pad_Byte)
|
||||
{
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
@@ -513,15 +520,17 @@ static void SHA224_256PadMessage(SHA256Context *context,
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
|
||||
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
|
||||
}
|
||||
else
|
||||
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
|
||||
|
||||
while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
|
||||
while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
|
||||
context->Message_Block[context->Message_Block_Index++] = 0;
|
||||
|
||||
/*
|
||||
@@ -561,21 +570,22 @@ static void SHA224_256PadMessage(SHA256Context *context,
|
||||
* sha Error Code.
|
||||
*/
|
||||
static int SHA224_256ResultN(SHA256Context *context,
|
||||
uint8_t Message_Digest[ ], int HashSize)
|
||||
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)
|
||||
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 ) ));
|
||||
Message_Digest[i] = (uint8_t)(context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
|
@@ -30,12 +30,17 @@
|
||||
*/
|
||||
int USHAReset(USHAContext *context, enum SHAversion whichSha)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
context->whichSha = whichSha;
|
||||
switch (whichSha) {
|
||||
case SHA224: return SHA224Reset((SHA224Context*)&context->ctx);
|
||||
case SHA256: return SHA256Reset((SHA256Context*)&context->ctx);
|
||||
default: return shaBadParam;
|
||||
switch (whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224Reset((SHA224Context *)&context->ctx);
|
||||
case SHA256:
|
||||
return SHA256Reset((SHA256Context *)&context->ctx);
|
||||
default:
|
||||
return shaBadParam;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,15 +67,18 @@ int USHAReset(USHAContext *context, enum SHAversion whichSha)
|
||||
int USHAInput(USHAContext *context,
|
||||
const uint8_t *bytes, unsigned int bytecount)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
switch (context->whichSha) {
|
||||
case SHA224:
|
||||
return SHA224Input((SHA224Context*)&context->ctx, bytes,
|
||||
bytecount);
|
||||
case SHA256:
|
||||
return SHA256Input((SHA256Context*)&context->ctx, bytes,
|
||||
bytecount);
|
||||
default: return shaBadParam;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
switch (context->whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224Input((SHA224Context *)&context->ctx, bytes,
|
||||
bytecount);
|
||||
case SHA256:
|
||||
return SHA256Input((SHA256Context *)&context->ctx, bytes,
|
||||
bytecount);
|
||||
default:
|
||||
return shaBadParam;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,15 +104,18 @@ int USHAInput(USHAContext *context,
|
||||
int USHAFinalBits(USHAContext *context,
|
||||
uint8_t bits, unsigned int bit_count)
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
switch (context->whichSha) {
|
||||
case SHA224:
|
||||
return SHA224FinalBits((SHA224Context*)&context->ctx, bits,
|
||||
bit_count);
|
||||
case SHA256:
|
||||
return SHA256FinalBits((SHA256Context*)&context->ctx, bits,
|
||||
bit_count);
|
||||
default: return shaBadParam;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
switch (context->whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224FinalBits((SHA224Context *)&context->ctx, bits,
|
||||
bit_count);
|
||||
case SHA256:
|
||||
return SHA256FinalBits((SHA256Context *)&context->ctx, bits,
|
||||
bit_count);
|
||||
default:
|
||||
return shaBadParam;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,15 +141,18 @@ int USHAFinalBits(USHAContext *context,
|
||||
int USHAResult(USHAContext *context,
|
||||
uint8_t Message_Digest[USHAMaxHashSize])
|
||||
{
|
||||
if (!context) return shaNull;
|
||||
switch (context->whichSha) {
|
||||
case SHA224:
|
||||
return SHA224Result((SHA224Context*)&context->ctx,
|
||||
Message_Digest);
|
||||
case SHA256:
|
||||
return SHA256Result((SHA256Context*)&context->ctx,
|
||||
Message_Digest);
|
||||
default: return shaBadParam;
|
||||
if (!context)
|
||||
return shaNull;
|
||||
switch (context->whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224Result((SHA224Context *)&context->ctx,
|
||||
Message_Digest);
|
||||
case SHA256:
|
||||
return SHA256Result((SHA256Context *)&context->ctx,
|
||||
Message_Digest);
|
||||
default:
|
||||
return shaBadParam;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,10 +173,13 @@ int USHAResult(USHAContext *context,
|
||||
*/
|
||||
int USHABlockSize(enum SHAversion whichSha)
|
||||
{
|
||||
switch (whichSha) {
|
||||
case SHA224: return SHA224_Message_Block_Size;
|
||||
default:
|
||||
case SHA256: return SHA256_Message_Block_Size;
|
||||
switch (whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224_Message_Block_Size;
|
||||
default:
|
||||
case SHA256:
|
||||
return SHA256_Message_Block_Size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,9 +200,12 @@ int USHABlockSize(enum SHAversion whichSha)
|
||||
*/
|
||||
int USHAHashSize(enum SHAversion whichSha)
|
||||
{
|
||||
switch (whichSha) {
|
||||
case SHA224: return SHA224HashSize;
|
||||
default:
|
||||
case SHA256: return SHA256HashSize;
|
||||
switch (whichSha)
|
||||
{
|
||||
case SHA224:
|
||||
return SHA224HashSize;
|
||||
default:
|
||||
case SHA256:
|
||||
return SHA256HashSize;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user