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

📄 ccm.c

📁 加密认证联合模式的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:

    if(ctx->cnt == ctx->hdr_lim)
    {
        ctx->state = MSG_STATE;
        ctx->cnt = 0;
        ctx->txt_acnt = 0;
    }

    return RETURN_OK;
}

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

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

    if(ctx->state == AUTH_STATE)
        return (ctx->state = CCM_AUTH_LENGTH_ERROR);

    if(ctx->txt_acnt + data_len > ctx->msg_len)
        return (ctx->state = CCM_MSG_LENGTH_ERROR);

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

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

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

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

    while(cnt < data_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++] ^= data[cnt++];
    }

    if(b_pos == BLOCK_SIZE)
        aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);

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

ret_type ccm_crypt_data(                        /* encrypt or decrypt data      */
            unsigned char data[],               /* the data buffer              */
            unsigned long data_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(ctx->state < 0)
        return ctx->state;

    if(ctx->state == AUTH_STATE)
        return (ctx->state = CCM_AUTH_LENGTH_ERROR);

    if(ctx->cnt + data_len > ctx->msg_len)
        return (ctx->state = CCM_MSG_LENGTH_ERROR);

    if(!data_len)
        return RETURN_OK;

    if(b_pos == 0)
    {
        aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
        inc_ctr(ctx->ctr_val);
    }

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

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

        while(cnt + BLOCK_SIZE <= data_len)
        {
            aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
            inc_ctr(ctx->ctr_val);
            xor_block_aligned(data + cnt, ctx->enc_ctr);
            cnt += BLOCK_SIZE;
        }
    }
    else
    {
        while(cnt < data_len && b_pos < BLOCK_SIZE)
            data[cnt++] ^= ui8_ptr(ctx->enc_ctr)[b_pos++];

        while(cnt + BLOCK_SIZE <= data_len)
        {
            aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
            inc_ctr(ctx->ctr_val);
            xor_block(data + cnt, ctx->enc_ctr);
            cnt += BLOCK_SIZE;
        }
    }

    while(cnt < data_len)
    {
        if(b_pos == BLOCK_SIZE)
        {
            aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
            inc_ctr(ctx->ctr_val);
            b_pos = 0;
        }
        data[cnt++] ^= ui8_ptr(ctx->enc_ctr)[b_pos++];
    }

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

ret_type ccm_compute_tag(                       /* compute authentication tag   */
            unsigned char tag[],                /* the buffer for the tag       */
            unsigned long tag_len,              /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{   uint_32t cnt, pos;

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

    if(   tag_len != ctx->tag_len
       || ctx->state == INIT_STATE && ctx->hdr_lim
       || ctx->state == AUTH_STATE)
        return (ctx->state = CCM_AUTH_LENGTH_ERROR);

    if(ctx->txt_acnt != ctx->cnt && ctx->cnt > 0)
        return RETURN_ERROR;

    if(   ctx->cnt < ctx->msg_len
       || ctx->cnt + tag_len > ctx->msg_len + ctx->tag_len)
        return (ctx->state = CCM_MSG_LENGTH_ERROR);

    /* if at the start of the authentication field  */
    if(tag_len > 0 && ctx->cnt == ctx->msg_len)
    {
        if(ctx->cnt & BLK_ADR_MASK)
            aes_encrypt(ui8_ptr(ctx->cbc_buf), ui8_ptr(ctx->cbc_buf), ctx->aes);
        set_ctr(ctx, 0);
        aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
    }

    cnt = 0;
    pos = (uint_32t)(ctx->cnt - ctx->msg_len);
    while(cnt < tag_len)
    {
        tag[cnt++] = ui8_ptr(ctx->cbc_buf)[pos] ^ ui8_ptr(ctx->enc_ctr)[pos];
        ++pos;
    }

    return (ctx->cnt == ctx->txt_acnt ? RETURN_OK : RETURN_WARN);
}

ret_type ccm_end(                               /* clean up and end operation   */
            ccm_ctx ctx[1])                     /* the mode context             */
{
    memset(ctx, 0, sizeof(ccm_ctx));
    return RETURN_OK;
}

ret_type ccm_encrypt(                           /* authenticate & encrypt data  */
            unsigned char data[],               /* the data buffer              */
            unsigned long data_len,             /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{

    ccm_auth_data(data, data_len, ctx);
    ccm_crypt_data(data, data_len, ctx);
    return RETURN_OK;
}

ret_type ccm_decrypt(                           /* decrypt & authenticate data  */
            unsigned char data[],               /* the data buffer              */
            unsigned long data_len,             /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{
    ccm_crypt_data(data, data_len, ctx);
    ccm_auth_data(data, data_len, ctx);
    return RETURN_OK;
}

ret_type ccm_encrypt_message(                   /* encrypt an entire message    */
            const unsigned char iv[],           /* the initialisation vector    */
            unsigned long iv_len,               /* and its length in bytes      */
            const unsigned char hdr[],          /* the header buffer            */
            unsigned long hdr_len,              /* and its length in bytes      */
            unsigned char msg[],                /* the message buffer           */
            unsigned long msg_len,              /* and its length in bytes      */
            unsigned char tag[],                /* the buffer for the tag       */
            unsigned long tag_len,              /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{
    ccm_init_message(iv, iv_len, hdr_len, msg_len, tag_len, ctx);
    ccm_auth_header(hdr, hdr_len, ctx);
    ccm_encrypt(msg, msg_len, ctx);
    return ccm_compute_tag(tag, tag_len, ctx) ? RETURN_ERROR : RETURN_OK;
}

ret_type ccm_decrypt_message(                   /* decrypt an entire message    */
            const unsigned char iv[],           /* the initialisation vector    */
            unsigned long iv_len,               /* and its length in bytes      */
            const unsigned char hdr[],          /* the header buffer            */
            unsigned long hdr_len,              /* and its length in bytes      */
            unsigned char msg[],                /* the message buffer           */
            unsigned long msg_len,              /* and its length in bytes      */
            const unsigned char tag[],          /* the buffer for the tag       */
            unsigned long tag_len,              /* and its length in bytes      */
            ccm_ctx ctx[1])                     /* the mode context             */
{   uint_8t local_tag[BLOCK_SIZE];
    ret_type rr;

    ccm_init_message(iv, iv_len, hdr_len, msg_len, tag_len, ctx);
    ccm_auth_header(hdr, hdr_len, ctx);
    ccm_decrypt(msg, msg_len, ctx);
    rr = ccm_compute_tag(local_tag, tag_len, ctx);
    return (rr != RETURN_OK || memcmp(tag, local_tag, tag_len)) ? RETURN_ERROR : RETURN_OK;
}

#if defined(__cplusplus)
}
#endif

⌨️ 快捷键说明

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