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

📄 ccm.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/10/2006

 My thanks to Colin Sinclair for finding an error and suggesting a number
 of improvements to this code
*/

#include "ccm.h"
#include "mode_hdr.h"

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

#define BLOCK_SIZE      AES_BLOCK_SIZE      /* block length                 */
#define BLK_ADR_MASK    (BLOCK_SIZE - 1)    /* mask for 'in block' address  */
#define INIT_STATE      10
#define AUTH_STATE      11
#define MSG_STATE       12

#define ctr_len(x)      (((*(uint_8t*)(x)) & 0x07) + 1)

#define clr_ctr(x,l)    memset((uint_8t*)(x) + BLOCK_SIZE - (l), 0, (l))

#define set_ctr(x,v)                                \
    {   uint_8t *_p = (uint_8t*)(x) + BLOCK_SIZE;   \
        length_t _t = (v), _l = ctr_len(x);         \
        do                                          \
        {    *--_p = (uint_8t)_t; _t >>= 8; }       \
        while(--_l);                                \
    }

#define inc_ctr(x)                                  \
    {   uint_8t *_p = (uint_8t*)(x) + BLOCK_SIZE;   \
        length_t _l = ctr_len(x);                   \
        while(_l-- && ++(*--_p) == 0) ;             \
    }

#ifdef LONG_MESSAGES

#  define mlen_len(x)                   \
    (((x) & 0xff00000000000000) ? 7 :   \
     ((x) & 0xffff000000000000) ? 6 :   \
     ((x) & 0xffffff0000000000) ? 5 :   \
     ((x) & 0xffffffff00000000) ? 4 :   \
     ((x) & 0xffffffffff000000) ? 3 :   \
     ((x) & 0xffffffffffff0000) ? 2 : 1)

#else
#  define mlen_len(x) (((x) & 0xff000000) ? 3 : ((x) & 0xffff0000) ? 2 : 1)
#endif

ret_type ccm_init_and_key(                      /* initialise mode and set key  */
            const unsigned char key[],          /* the key value                */
            unsigned long key_len,              /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{
    ctx->state = CCM_OK;
    if(key_len != 16 && key_len != 24 && key_len != 32)
        ctx->state = CCM_BAD_KEY;
    aes_encrypt_key(key, (int)key_len, ctx->aes);
    return RETURN_OK;
}

ret_type ccm_init_message(                      /* initialise for a new message */
            const unsigned char iv[],           /* the initialisation vector    */
            unsigned long iv_len,               /* the nonce length             */
            length_t hdr_len,                   /* the associated data length   */
            length_t msg_len,                   /* message data length          */
            unsigned long tag_len,              /* authentication field length  */
            ccm_ctx ctx[1])                     /* the mode context             */
{   uint_32t cnt;

    ctx->state = CCM_OK;

    if(tag_len < 2 || tag_len > 16 || (tag_len & 1))
        ctx->state = CCM_BAD_AUTH_FIELD_LENGTH;
    else if(iv_len && iv_len < 7 || iv_len > 13)
        ctx->state = CCM_BAD_NONCE_LENGTH;
    if(ctx->state)
        return ctx->state;

    ctx->iv_len = iv_len;
    ctx->hdr_len = hdr_len;
    ctx->msg_len = msg_len;
    ctx->tag_len = tag_len;
    ctx->cnt = 0;
    ctx->txt_acnt = 0;
    ctx->hdr_lim = hdr_len;

    ui8_ptr(ctx->ctr_val)[0] =
        (uint_8t)(iv_len ? BLOCK_SIZE - 2 - iv_len : mlen_len(ctx->msg_len));

    /* move the iv into the block    */
    for(cnt = 1; cnt < (uint_32t)BLOCK_SIZE - ui8_ptr(ctx->ctr_val)[0] - 1; ++cnt)
        ui8_ptr(ctx->ctr_val)[cnt] = iv[cnt - 1];

    clr_ctr(ctx->ctr_val, ui8_ptr(ctx->ctr_val)[0] + 1);    /* clear the counter value  */
    memcpy(ctx->cbc_buf, ctx->ctr_val, BLOCK_SIZE);         /* copy block to CBC buffer */
    ui8_ptr(ctx->ctr_val)[BLOCK_SIZE - 1] = 1;              /* set initial counter      */
    set_ctr(ctx->cbc_buf, ctx->msg_len);                    /* store the message length */

    ui8_ptr(ctx->cbc_buf)[0] |= (ctx->hdr_lim ? 0x40 : 0) + ((ctx->tag_len - 2) << 2);
                                                            /* encrypt the cbc block    */
    aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);

    if(ctx->hdr_len)
    {   /* encode the length field if there is some associated data */

        if(ctx->hdr_len < 65536 - 256)
        {
            ui8_ptr(ctx->cbc_buf)[0] ^= (uint_8t)(ctx->hdr_lim >> 8);
            ui8_ptr(ctx->cbc_buf)[1] ^= (uint_8t) ctx->hdr_lim;
            ctx->cnt = 2;
        }
#ifndef LONG_MESSAGES
        else
        {
            ctx->state = CCM_AUTH_LENGTH_ERROR;
            return ctx->state;
        }
#else
        else if(ctx->hdr_len < 0x0000000100000000)
        {
            ui8_ptr(ctx->cbc_buf)[0] ^= 0xff;
            ui8_ptr(ctx->cbc_buf)[1] ^= 0xfe;
            ui8_ptr(ctx->cbc_buf)[2] ^= (uint_8t)(ctx->hdr_lim >> 24);
            ui8_ptr(ctx->cbc_buf)[3] ^= (uint_8t)(ctx->hdr_lim >> 16);
            ui8_ptr(ctx->cbc_buf)[4] ^= (uint_8t)(ctx->hdr_lim >>  8);
            ui8_ptr(ctx->cbc_buf)[5] ^= (uint_8t) ctx->hdr_lim;
            ctx->cnt = 6;
        }
        else
        {
            ui8_ptr(ctx->cbc_buf)[0] ^= 0xff;
            ui8_ptr(ctx->cbc_buf)[1] ^= 0xff;
            ui8_ptr(ctx->cbc_buf)[2] ^= (uint_8t)(ctx->hdr_lim >> 56);
            ui8_ptr(ctx->cbc_buf)[3] ^= (uint_8t)(ctx->hdr_lim >> 48);
            ui8_ptr(ctx->cbc_buf)[4] ^= (uint_8t)(ctx->hdr_lim >> 40);
            ui8_ptr(ctx->cbc_buf)[5] ^= (uint_8t)(ctx->hdr_lim >> 32);
            ui8_ptr(ctx->cbc_buf)[6] ^= (uint_8t)(ctx->hdr_lim >> 24);
            ui8_ptr(ctx->cbc_buf)[7] ^= (uint_8t)(ctx->hdr_lim >> 16);
            ui8_ptr(ctx->cbc_buf)[8] ^= (uint_8t)(ctx->hdr_lim >>  8);
            ui8_ptr(ctx->cbc_buf)[9] ^= (uint_8t) ctx->hdr_lim;
            ctx->cnt = 10;
        }
#endif
        ctx->hdr_lim += ctx->cnt;
        ctx->state = AUTH_STATE;
    }
    else    /* there is no associated data  */
    {
        ctx->cnt = 0;
        ctx->state = MSG_STATE;
    }

    ctx->hdr_lim = ctx->hdr_len + ctx->cnt;
    ctx->txt_acnt = ctx->cnt;

    return RETURN_OK;
}

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

    if(!hdr_len)
        return RETURN_OK;

    if(ctx->state < 0)
        return ctx->state;

    if(ctx->state != AUTH_STATE)
        return (ctx->state = CCM_BAD_AUTH_CALL);

    if(ctx->cnt + hdr_len > ctx->hdr_lim)
        return (ctx->state = CCM_AUTH_LENGTH_ERROR);

    while(cnt < hdr_len && (b_pos & BUF_ADRMASK))
        ui8_ptr(ctx->cbc_buf)[b_pos++] ^= hdr[cnt++];

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

        while(cnt + BLOCK_SIZE <= hdr_len)
        {
            aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);
            xor_block_aligned(ctx->cbc_buf, hdr + cnt);
            cnt += BLOCK_SIZE;
        }
    }
    else
    {
        while(cnt < hdr_len && b_pos < BLOCK_SIZE)
            ui8_ptr(ctx->cbc_buf)[b_pos++] ^= hdr[cnt++];

        while(cnt + BLOCK_SIZE <= hdr_len)
        {
            aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);
            xor_block(ctx->cbc_buf, hdr + cnt);
            cnt += BLOCK_SIZE;
        }
    }

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

    }

    ctx->cnt += cnt;
    if(b_pos == BLOCK_SIZE || ctx->cnt == ctx->hdr_lim)
        aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);

⌨️ 快捷键说明

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