⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gcm.c

📁 加密认证联合模式的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 ---------------------------------------------------------------------------
 Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved.

 LICENSE TERMS

 The free distribution and use of this software in both source and binary
 form is allowed (with or without changes) provided that:

   1. distributions of this source code include the above copyright
      notice, this list of conditions and the following disclaimer;

   2. distributions in binary form include the above copyright
      notice, this list of conditions and the following disclaimer
      in the documentation and/or other associated materials;

   3. the copyright holder's name is not used to endorse products
      built using this software without specific written permission.

 ALTERNATIVELY, provided that this notice is retained in full, this product
 may be distributed under the terms of the GNU General Public License (GPL),
 in which case the provisions of the GPL apply INSTEAD OF those given above.

 DISCLAIMER

 This software is provided 'as is' with no explicit or implied warranties
 in respect of its properties, including, but not limited to, correctness
 and/or fitness for purpose.
 ---------------------------------------------------------------------------
 Issue Date: 13/06/2006

 My thanks to John Viega and David McGrew for their support in developing
 this code and to David for testing it on a big-endain system.
*/

#include "gcm.h"
#include "mode_hdr.h"

#if defined(__cplusplus)
extern "C"
{
#endif

#define BLOCK_SIZE      GCM_BLOCK_SIZE      /* block length                 */
#define BLK_ADR_MASK    (BLOCK_SIZE - 1)    /* mask for 'in block' address  */
#define CTR_POS         12

#define inc_ctr(x)  \
    {   int i = BLOCK_SIZE; while(i-- > CTR_POS && !++(ui8_ptr(x)[i])) ; }

ret_type gcm_init_and_key(                      /* initialise mode and set key  */
            const unsigned char key[],          /* the key value                */
            unsigned long key_len,              /* and its length in bytes      */
            gcm_ctx ctx[1])                     /* the mode context             */
{
    memset(ctx->ghash_h, 0, sizeof(ctx->ghash_h));

    /* set the AES key                          */
    aes_encrypt_key(key, key_len, ctx->aes);

    /* compute E(0) (for the hash function)     */
    aes_encrypt(ui8_ptr(ctx->ghash_h), ui8_ptr(ctx->ghash_h), ctx->aes);

#if defined( TABLES_64K )
    init_64k_table(ui8_ptr(ctx->ghash_h), ctx->gf_t64k);
#elif defined( TABLES_8K )
    init_8k_table(ui8_ptr(ctx->ghash_h), ctx->gf_t8k);
#elif defined( TABLES_4K )
    init_4k_table(ui8_ptr(ctx->ghash_h), ctx->gf_t4k);
#elif defined( TABLES_256 )
    init_256_table(ui8_ptr(ctx->ghash_h), ctx->gf_t256);
#endif
    return RETURN_OK;
}

#if defined( TABLES_64K )
#define gf_mul_hh(a, ctx, scr)  gf_mul_64k(a, ctx->gf_t64k, scr)
#elif defined( TABLES_8K )
#define gf_mul_hh(a, ctx, scr)  gf_mul_8k(a, ctx->gf_t8k, scr)
#elif defined( TABLES_4K )
#define gf_mul_hh(a, ctx, scr)  gf_mul_4k(a, ctx->gf_t4k, scr)
#elif defined( TABLES_256 )
#define gf_mul_hh(a, ctx, scr)  gf_mul_256(a, ctx->gf_t256, scr)
#else
#define gf_mul_hh(a, ctx, scr)  gf_mul(a, ui8_ptr(ctx->ghash_h))
#endif

ret_type gcm_init_message(                      /* initialise a new message     */
            const unsigned char iv[],           /* the initialisation vector    */
            unsigned long iv_len,               /* and its length in bytes      */
            gcm_ctx ctx[1])                     /* the mode context             */
{   uint_32t i, n_pos = 0, scratch[GF_BYTE_LEN >> 2];
    uint_8t *p;

    memset(ctx->ctr_val, 0, BLOCK_SIZE);
    if(iv_len == CTR_POS)
    {
        memcpy(ctx->ctr_val, iv, CTR_POS); ui8_ptr(ctx->ctr_val)[15] = 0x01;
    }
    else
    {   n_pos = iv_len;
        while(n_pos >= BLOCK_SIZE)
        {
            xor_block_aligned(ctx->ctr_val, iv);
            n_pos -= BLOCK_SIZE;
            iv += BLOCK_SIZE;
            gf_mul_hh(ui8_ptr(ctx->ctr_val), ctx, scratch);
        }

        if(n_pos)
        {
            p = ui8_ptr(ctx->ctr_val);
            while(n_pos-- > 0)
                *p++ ^= *iv++;
            gf_mul_hh(ui8_ptr(ctx->ctr_val), ctx, scratch);
        }
        n_pos = (iv_len << 3);
        for(i = BLOCK_SIZE - 1; n_pos; --i, n_pos >>= 8)
            ui8_ptr(ctx->ctr_val)[i] ^= (unsigned char)n_pos;
        gf_mul_hh(ui8_ptr(ctx->ctr_val), ctx, scratch);
    }

    ctx->y0_val = *ui32_ptr(ui8_ptr(ctx->ctr_val) + CTR_POS);
    inc_ctr(ctx->ctr_val);
    memset(ctx->hdr_ghv, 0, BLOCK_SIZE);
    memset(ctx->txt_ghv, 0, BLOCK_SIZE);
    ctx->hdr_cnt = 0;
    ctx->txt_ccnt = ctx->txt_acnt = 0;
    return RETURN_OK;
}

ret_type gcm_auth_header(                       /* authenticate the header      */
            const unsigned char hdr[],          /* the header buffer            */
            unsigned long hdr_len,              /* and its length in bytes      */
            gcm_ctx ctx[1])                     /* the mode context             */
{   uint_32t cnt = 0, b_pos = (uint_32t)ctx->hdr_cnt & BLK_ADR_MASK;
    uint_32t scratch[GF_BYTE_LEN >> 2];

    if(!hdr_len)
        return RETURN_OK;

    if(ctx->hdr_cnt && b_pos == 0)
        gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);

    while(cnt < hdr_len && (b_pos & BUF_ADRMASK))
        ui8_ptr(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];
    
    if(!(b_pos & BUF_ADRMASK) && !((hdr + cnt - ui8_ptr(ctx->hdr_ghv)) & BUF_ADRMASK))
    {
        while(cnt + BUF_INC <= hdr_len && b_pos <= BLOCK_SIZE - BUF_INC)
        {
            *unit_ptr(ui8_ptr(ctx->hdr_ghv) + b_pos) ^= *unit_ptr(hdr + cnt);
            cnt += BUF_INC; b_pos += BUF_INC;
        }
        
        while(cnt + BLOCK_SIZE <= hdr_len)
        {
            gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);
            xor_block_aligned(ctx->hdr_ghv, hdr + cnt);
            cnt += BLOCK_SIZE;
        }
    }
    else
    {
        while(cnt < hdr_len && b_pos < BLOCK_SIZE)
            ui8_ptr(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];

        while(cnt + BLOCK_SIZE <= hdr_len)
        {
            gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);
            xor_block(ctx->hdr_ghv, hdr + cnt);
            cnt += BLOCK_SIZE;
        }
    }

    while(cnt < hdr_len)
    {
        if(b_pos == BLOCK_SIZE)
        {
            gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);
            b_pos = 0;
        }
        ui8_ptr(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];
    }

    ctx->hdr_cnt += cnt;
    return RETURN_OK;
}

ret_type gcm_auth_data(                         /* authenticate ciphertext data */
            const unsigned char data[],         /* the data buffer              */
            unsigned long data_len,             /* and its length in bytes      */
            gcm_ctx ctx[1])                     /* the mode context             */
{   uint_32t cnt = 0, b_pos = (uint_32t)(ctx->txt_acnt & BLK_ADR_MASK);
    uint_32t scratch[GF_BYTE_LEN >> 2];

    if(!data_len)
        return RETURN_OK;

    if(ctx->txt_acnt && b_pos == 0)
        gf_mul_hh(ui8_ptr(ctx->txt_ghv), ctx, scratch);

    while(cnt < data_len && (b_pos & BUF_ADRMASK))
        ui8_ptr(ctx->txt_ghv)[b_pos++] ^= data[cnt++];

    if(!(b_pos & BUF_ADRMASK) && !((data + cnt - ui8_ptr(ctx->txt_ghv)) & BUF_ADRMASK))
    {
        while(cnt + BUF_INC <= data_len && b_pos <= BLOCK_SIZE - BUF_INC)
        {
            *unit_ptr(ui8_ptr(ctx->txt_ghv) + b_pos) ^= *unit_ptr(data + cnt);
            cnt += BUF_INC; b_pos += BUF_INC;
        }

        while(cnt + BLOCK_SIZE <= data_len)
        {
            gf_mul_hh(ui8_ptr(ctx->txt_ghv), ctx, scratch);
            xor_block_aligned(ctx->txt_ghv, data + cnt);
            cnt += BLOCK_SIZE;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -