📄 gcm.c
字号:
}
else
{
while(cnt < data_len && b_pos < BLOCK_SIZE)
ui8_ptr(ctx->txt_ghv)[b_pos++] ^= data[cnt++];
while(cnt + BLOCK_SIZE <= data_len)
{
gf_mul_hh(ui8_ptr(ctx->txt_ghv), ctx, scratch);
xor_block(ctx->txt_ghv, data + cnt);
cnt += BLOCK_SIZE;
}
}
while(cnt < data_len)
{
if(b_pos == BLOCK_SIZE)
{
gf_mul_hh(ui8_ptr(ctx->txt_ghv), ctx, scratch);
b_pos = 0;
}
ui8_ptr(ctx->txt_ghv)[b_pos++] ^= data[cnt++];
}
ctx->txt_acnt += cnt;
return RETURN_OK;
}
ret_type gcm_crypt_data( /* encrypt or decrypt data */
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_ccnt & BLK_ADR_MASK);
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->txt_ccnt += cnt;
return RETURN_OK;
}
ret_type gcm_compute_tag( /* compute authentication tag */
unsigned char tag[], /* the buffer for the tag */
unsigned long tag_len, /* and its length in bytes */
gcm_ctx ctx[1]) /* the mode context */
{ uint_32t i, ln, scratch[GF_BYTE_LEN >> 2];
uint_8t tbuf[BLOCK_SIZE];
if(ctx->txt_acnt != ctx->txt_ccnt && ctx->txt_ccnt > 0)
return RETURN_ERROR;
gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);
gf_mul_hh(ui8_ptr(ctx->txt_ghv), ctx, scratch);
#if 1 /* alternative versions of the exponentiation operation */
if(ctx->hdr_cnt && (ln = (uint_32t)((ctx->txt_acnt + BLOCK_SIZE - 1) / BLOCK_SIZE)))
{
memcpy(tbuf, ctx->ghash_h, BLOCK_SIZE);
for( ; ; )
{
if(ln & 1) gf_mul(ui8_ptr(ctx->hdr_ghv), tbuf);
if(!(ln >>= 1)) break;
gf_mul(tbuf, tbuf);
}
}
#else /* this one seems slower on x86 and x86_64 :-( */
if(ctx->hdr_cnt && (ln = (uint_32t)((ctx->txt_acnt + BLOCK_SIZE - 1) / BLOCK_SIZE)))
{
i = ln | ln >> 1; i |= i >> 2; i |= i >> 4;
i |= i >> 8; i |= i >> 16; i = i & ~(i >> 1);
memset(tbuf, 0, BLOCK_SIZE);
tbuf[0] = 0x80;
while(i)
{
gf_mul(tbuf, tbuf);
if(i & ln)
gf_mul_hh(tbuf, ctx, scratch);
i >>= 1;
}
gf_mul(ui8_ptr(ctx->hdr_ghv), tbuf);
}
#endif
i = BLOCK_SIZE; ln = (uint_32t)(ctx->txt_acnt << 3);
while(i-- > 0)
{
ui8_ptr(ctx->hdr_ghv)[i] ^= ui8_ptr(ctx->txt_ghv)[i] ^ (unsigned char)ln;
ln = (i == 8 ? (uint_32t)(ctx->hdr_cnt << 3) : ln >> 8);
}
gf_mul_hh(ui8_ptr(ctx->hdr_ghv), ctx, scratch);
*ui32_ptr(ui8_ptr(ctx->ctr_val) + CTR_POS) = ctx->y0_val;
aes_encrypt(ui8_ptr(ctx->ctr_val), ui8_ptr(ctx->enc_ctr), ctx->aes);
for(i = 0; i < (unsigned int)tag_len; ++i)
tag[i] = ui8_ptr(ctx->hdr_ghv)[i] ^ ui8_ptr(ctx->enc_ctr)[i];
return (ctx->txt_ccnt == ctx->txt_acnt ? RETURN_OK : RETURN_WARN);
}
ret_type gcm_end( /* clean up and end operation */
gcm_ctx ctx[1]) /* the mode context */
{
memset(ctx, 0, sizeof(gcm_ctx));
return RETURN_OK;
}
ret_type gcm_encrypt( /* encrypt & authenticate data */
unsigned char data[], /* the data buffer */
unsigned long data_len, /* and its length in bytes */
gcm_ctx ctx[1]) /* the mode context */
{
gcm_crypt_data(data, data_len, ctx);
gcm_auth_data(data, data_len, ctx);
return RETURN_OK;
}
ret_type gcm_decrypt( /* authenticate & decrypt data */
unsigned char data[], /* the data buffer */
unsigned long data_len, /* and its length in bytes */
gcm_ctx ctx[1]) /* the mode context */
{
gcm_auth_data(data, data_len, ctx);
gcm_crypt_data(data, data_len, ctx);
return RETURN_OK;
}
ret_type gcm_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 */
gcm_ctx ctx[1]) /* the mode context */
{
gcm_init_message(iv, iv_len, ctx);
gcm_auth_header(hdr, hdr_len, ctx);
gcm_encrypt(msg, msg_len, ctx);
return gcm_compute_tag(tag, tag_len, ctx) ? RETURN_ERROR : RETURN_OK;
}
ret_type gcm_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 */
gcm_ctx ctx[1]) /* the mode context */
{ uint_8t local_tag[BLOCK_SIZE];
ret_type rr;
gcm_init_message(iv, iv_len, ctx);
gcm_auth_header(hdr, hdr_len, ctx);
gcm_decrypt(msg, msg_len, ctx);
rr = gcm_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 + -