mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-16 04:24:45 -07:00
Format
This commit is contained in:
387
applications/external/esubghz_chat/crypto/gcm.c
vendored
387
applications/external/esubghz_chat/crypto/gcm.c
vendored
@@ -76,25 +76,40 @@
|
||||
* 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 };
|
||||
0x0000,
|
||||
0x1c20,
|
||||
0x3840,
|
||||
0x2460,
|
||||
0x7080,
|
||||
0x6ca0,
|
||||
0x48c0,
|
||||
0x54e0,
|
||||
0xe100,
|
||||
0xfd20,
|
||||
0xd940,
|
||||
0xc560,
|
||||
0x9180,
|
||||
0x8da0,
|
||||
0xa9c0,
|
||||
0xb5e0};
|
||||
|
||||
/*
|
||||
* Platform Endianness Neutralizing Load and Store Macro definitions
|
||||
* GCM wants platform-neutral Big Endian (BE) byte ordering
|
||||
*/
|
||||
#define GET_UINT32_BE(n,b,i) { \
|
||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] ); }
|
||||
|
||||
#define PUT_UINT32_BE(n,b,i) { \
|
||||
(b)[(i) ] = (uchar) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (uchar) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (uchar) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (uchar) ( (n) ); }
|
||||
#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)); \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@@ -108,13 +123,11 @@ static const uint64_t last4[16] = {
|
||||
* environment is running.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_initialize( void )
|
||||
{
|
||||
int gcm_initialize(void) {
|
||||
aes_init_keygen_tables();
|
||||
return( 0 );
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_MULT
|
||||
@@ -124,45 +137,45 @@ 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;
|
||||
uint64_t zh, zl;
|
||||
|
||||
lo = (uchar)( x[15] & 0x0f );
|
||||
hi = (uchar)( x[15] >> 4 );
|
||||
lo = (uchar)(x[15] & 0x0f);
|
||||
hi = (uchar)(x[15] >> 4);
|
||||
zh = ctx->HH[lo];
|
||||
zl = ctx->HL[lo];
|
||||
|
||||
for( i = 15; i >= 0; i-- ) {
|
||||
lo = (uchar) ( x[i] & 0x0f );
|
||||
hi = (uchar) ( x[i] >> 4 );
|
||||
for(i = 15; i >= 0; i--) {
|
||||
lo = (uchar)(x[i] & 0x0f);
|
||||
hi = (uchar)(x[i] >> 4);
|
||||
|
||||
if( i != 15 ) {
|
||||
rem = (uchar) ( zl & 0x0f );
|
||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
||||
zh = ( zh >> 4 );
|
||||
zh ^= (uint64_t) last4[rem] << 48;
|
||||
if(i != 15) {
|
||||
rem = (uchar)(zl & 0x0f);
|
||||
zl = (zh << 60) | (zl >> 4);
|
||||
zh = (zh >> 4);
|
||||
zh ^= (uint64_t)last4[rem] << 48;
|
||||
zh ^= ctx->HH[lo];
|
||||
zl ^= ctx->HL[lo];
|
||||
}
|
||||
rem = (uchar) ( zl & 0x0f );
|
||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
||||
zh = ( zh >> 4 );
|
||||
zh ^= (uint64_t) last4[rem] << 48;
|
||||
rem = (uchar)(zl & 0x0f);
|
||||
zl = (zh << 60) | (zl >> 4);
|
||||
zh = (zh >> 4);
|
||||
zh ^= (uint64_t)last4[rem] << 48;
|
||||
zh ^= ctx->HH[hi];
|
||||
zl ^= ctx->HL[hi];
|
||||
}
|
||||
PUT_UINT32_BE( zh >> 32, output, 0 );
|
||||
PUT_UINT32_BE( zh, output, 4 );
|
||||
PUT_UINT32_BE( zl >> 32, output, 8 );
|
||||
PUT_UINT32_BE( zl, output, 12 );
|
||||
PUT_UINT32_BE(zh >> 32, output, 0);
|
||||
PUT_UINT32_BE(zh, output, 4);
|
||||
PUT_UINT32_BE(zl >> 32, output, 8);
|
||||
PUT_UINT32_BE(zl, output, 12);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_SETKEY
|
||||
@@ -171,59 +184,57 @@ static void gcm_mult( gcm_context *ctx, // pointer to established context
|
||||
* and populates the gcm context's pre-calculated HTables.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_setkey( gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
const uchar *key, // pointer to the AES encryption key
|
||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
int gcm_setkey(
|
||||
gcm_context* ctx, // pointer to caller-provided gcm context
|
||||
const uchar* key, // pointer to the AES encryption key
|
||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
{
|
||||
int ret, i, j;
|
||||
uint64_t hi, lo;
|
||||
uint64_t vl, vh;
|
||||
unsigned char h[16];
|
||||
|
||||
memset( ctx, 0, sizeof(gcm_context) ); // zero caller-provided GCM context
|
||||
memset( h, 0, 16 ); // initialize the block to encrypt
|
||||
memset(ctx, 0, sizeof(gcm_context)); // zero caller-provided GCM context
|
||||
memset(h, 0, 16); // initialize the block to encrypt
|
||||
|
||||
// encrypt the null 128-bit block to generate a key-based value
|
||||
// which is then used to initialize our GHASH lookup tables
|
||||
if(( ret = aes_setkey( &ctx->aes_ctx, ENCRYPT, key, keysize )) != 0 )
|
||||
return( ret );
|
||||
if(( ret = aes_cipher( &ctx->aes_ctx, h, h )) != 0 )
|
||||
return( ret );
|
||||
if((ret = aes_setkey(&ctx->aes_ctx, ENCRYPT, key, keysize)) != 0) return (ret);
|
||||
if((ret = aes_cipher(&ctx->aes_ctx, h, h)) != 0) return (ret);
|
||||
|
||||
GET_UINT32_BE( hi, h, 0 ); // pack h as two 64-bit ints, big-endian
|
||||
GET_UINT32_BE( lo, h, 4 );
|
||||
vh = (uint64_t) hi << 32 | lo;
|
||||
GET_UINT32_BE(hi, h, 0); // pack h as two 64-bit ints, big-endian
|
||||
GET_UINT32_BE(lo, h, 4);
|
||||
vh = (uint64_t)hi << 32 | lo;
|
||||
|
||||
GET_UINT32_BE( hi, h, 8 );
|
||||
GET_UINT32_BE( lo, h, 12 );
|
||||
vl = (uint64_t) hi << 32 | lo;
|
||||
GET_UINT32_BE(hi, h, 8);
|
||||
GET_UINT32_BE(lo, h, 12);
|
||||
vl = (uint64_t)hi << 32 | lo;
|
||||
|
||||
ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
|
||||
ctx->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 ) {
|
||||
uint32_t T = (uint32_t) ( vl & 1 ) * 0xe1000000U;
|
||||
vl = ( vh << 63 ) | ( vl >> 1 );
|
||||
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
|
||||
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,62 +256,61 @@ 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
|
||||
memset( ctx->y, 0x00, sizeof(ctx->y ) );
|
||||
memset( ctx->buf, 0x00, sizeof(ctx->buf) );
|
||||
memset(ctx->y, 0x00, sizeof(ctx->y));
|
||||
memset(ctx->buf, 0x00, sizeof(ctx->buf));
|
||||
ctx->len = 0;
|
||||
ctx->add_len = 0;
|
||||
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||
|
||||
if( iv_len == 12 ) { // GCM natively uses a 12-byte, 96-bit IV
|
||||
memcpy( ctx->y, iv, iv_len ); // copy the IV to the top of the 'y' buff
|
||||
ctx->y[15] = 1; // start "counting" from 1 (not 0)
|
||||
}
|
||||
else // if we don't have a 12-byte IV, we GHASH whatever we've been given
|
||||
{
|
||||
memset( work_buf, 0x00, 16 ); // clear the working buffer
|
||||
PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); // place the IV into buffer
|
||||
if(iv_len == 12) { // GCM natively uses a 12-byte, 96-bit IV
|
||||
memcpy(ctx->y, iv, iv_len); // copy the IV to the top of the 'y' buff
|
||||
ctx->y[15] = 1; // start "counting" from 1 (not 0)
|
||||
} else // if we don't have a 12-byte IV, we GHASH whatever we've been given
|
||||
{
|
||||
memset(work_buf, 0x00, 16); // clear the working buffer
|
||||
PUT_UINT32_BE(iv_len * 8, work_buf, 12); // place the IV into buffer
|
||||
|
||||
p = iv;
|
||||
while( iv_len > 0 ) {
|
||||
use_len = ( iv_len < 16 ) ? iv_len : 16;
|
||||
for( i = 0; i < use_len; i++ ) ctx->y[i] ^= p[i];
|
||||
gcm_mult( ctx, ctx->y, ctx->y );
|
||||
while(iv_len > 0) {
|
||||
use_len = (iv_len < 16) ? iv_len : 16;
|
||||
for(i = 0; i < use_len; i++) ctx->y[i] ^= p[i];
|
||||
gcm_mult(ctx, ctx->y, ctx->y);
|
||||
iv_len -= use_len;
|
||||
p += use_len;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) ctx->y[i] ^= work_buf[i];
|
||||
gcm_mult( ctx, ctx->y, ctx->y );
|
||||
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 );
|
||||
if((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0) return (ret);
|
||||
|
||||
ctx->add_len = add_len;
|
||||
p = add;
|
||||
while( add_len > 0 ) {
|
||||
use_len = ( add_len < 16 ) ? add_len : 16;
|
||||
for( i = 0; i < use_len; i++ ) ctx->buf[i] ^= p[i];
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
while(add_len > 0) {
|
||||
use_len = (add_len < 16) ? add_len : 16;
|
||||
for(i = 0; i < use_len; i++) ctx->buf[i] ^= p[i];
|
||||
gcm_mult(ctx, ctx->buf, ctx->buf);
|
||||
add_len -= use_len;
|
||||
p += use_len;
|
||||
}
|
||||
return( 0 );
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -314,63 +324,61 @@ 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;
|
||||
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 );
|
||||
if((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ectr)) != 0) return (ret);
|
||||
|
||||
// encrypt or decrypt the input to the output
|
||||
if( ctx->mode == ENCRYPT )
|
||||
{
|
||||
for( i = 0; i < use_len; i++ ) {
|
||||
if(ctx->mode == ENCRYPT) {
|
||||
for(i = 0; i < use_len; i++) {
|
||||
// XOR the cipher's ouptut vector (ectr) with our input
|
||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
||||
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
|
||||
} else {
|
||||
for(i = 0; i < use_len; i++) {
|
||||
// but if we're DEcrypting we XOR in the input data first,
|
||||
// i.e. before saving to ouput data, otherwise if the input
|
||||
// and output buffer are the same (inplace decryption) we
|
||||
// would not get the correct auth tag
|
||||
|
||||
ctx->buf[i] ^= input[i];
|
||||
ctx->buf[i] ^= input[i];
|
||||
|
||||
// XOR the cipher's ouptut vector (ectr) with our input
|
||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
||||
}
|
||||
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
|
||||
input += use_len; // bump our input pointer forward
|
||||
output += use_len; // bump our output pointer forward
|
||||
length -= use_len; // drop the remaining byte count to process
|
||||
input += use_len; // bump our input pointer forward
|
||||
output += use_len; // bump our output pointer forward
|
||||
}
|
||||
return( 0 );
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -381,33 +389,33 @@ 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_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 ) {
|
||||
memset( work_buf, 0x00, 16 );
|
||||
if(orig_len || orig_add_len) {
|
||||
memset(work_buf, 0x00, 16);
|
||||
|
||||
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
|
||||
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
|
||||
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
|
||||
PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
|
||||
PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
|
||||
PUT_UINT32_BE((orig_add_len), work_buf, 4);
|
||||
PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
|
||||
PUT_UINT32_BE((orig_len), work_buf, 12);
|
||||
|
||||
for( i = 0; i < 16; i++ ) ctx->buf[i] ^= work_buf[i];
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
for( i = 0; i < tag_len; i++ ) tag[i] ^= ctx->buf[i];
|
||||
for(i = 0; i < 16; i++) ctx->buf[i] ^= work_buf[i];
|
||||
gcm_mult(ctx, ctx->buf, ctx->buf);
|
||||
for(i = 0; i < tag_len; i++) tag[i] ^= ctx->buf[i];
|
||||
}
|
||||
return( 0 );
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
@@ -426,29 +434,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
|
||||
{ /*
|
||||
gcm_context* ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
|
||||
const uchar* iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar* add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar* input, // pointer to the cipher data source
|
||||
uchar* output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
uchar* tag, // pointer to the tag to be generated
|
||||
size_t tag_len) // byte length of the tag to be generated
|
||||
{ /*
|
||||
assuming that the caller has already invoked gcm_setkey to
|
||||
prepare the gcm context with the keying material, we simply
|
||||
invoke each of the three GCM sub-functions in turn...
|
||||
*/
|
||||
gcm_start ( ctx, mode, iv, iv_len, add, add_len );
|
||||
gcm_update ( ctx, length, input, output );
|
||||
gcm_finish ( ctx, tag, tag_len );
|
||||
return( 0 );
|
||||
gcm_start(ctx, mode, iv, iv_len, add, add_len);
|
||||
gcm_update(ctx, length, input, output);
|
||||
gcm_finish(ctx, tag, tag_len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
@@ -462,37 +469,36 @@ 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, DECRYPT, iv, iv_len, add, add_len,
|
||||
input, output, length, check_tag, tag_len );
|
||||
gcm_crypt_and_tag(
|
||||
ctx, DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len);
|
||||
|
||||
// now we verify the authentication tag in 'constant time'
|
||||
for( diff = 0, i = 0; i < tag_len; i++ )
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
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);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -504,8 +510,7 @@ int gcm_auth_decrypt(
|
||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||
*
|
||||
******************************************************************************/
|
||||
void gcm_zero_ctx( gcm_context *ctx )
|
||||
{
|
||||
void gcm_zero_ctx(gcm_context* ctx) {
|
||||
// zero the context originally provided to us
|
||||
memset( ctx, 0, sizeof( gcm_context ) );
|
||||
memset(ctx, 0, sizeof(gcm_context));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user