580 lines
20 KiB
C
580 lines
20 KiB
C
/**
|
|
* @file ske_gcm.c
|
|
* @brief Semidrive CRYPTO ske gcm source file.
|
|
*
|
|
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <ske_gcm.h>
|
|
#ifdef SUPPORT_SKE_MODE_GCM
|
|
|
|
/* function: ske_hp gcm mode init config
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* crypto --------------------- input, encrypting or decrypting
|
|
* key ------------------------ input, key in bytes, key of AES(128/192/256)
|
|
* or SM4 sp_key_idx ----------------- input, index of secure port key,
|
|
* (sp_key_idx & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is
|
|
* 1, that means using low 128bit of the 256bit key iv -------------------------
|
|
* input, iv in bytes iv_bytes ------------------- input, byte length of iv, now
|
|
* only 12 bytes supported aad_bytes ------------------ input, byte length of
|
|
* aad, it could be any value, including 0 c_bytes -------------------- input,
|
|
* byte length of plaintext/ciphertext, it could be any value, including 0
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. this function is for CPU style
|
|
* 2. only AES(128/192/256) and SM4 are supported for GCM mode
|
|
* 3. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 4. iv must be 12 bytes here
|
|
* 5. aad_bytes and c_bytes could not be zero at the same time
|
|
*/
|
|
uint32_t ske_hp_gcm_init(ske_gcm_ctx_t *ctx, SKE_ALG alg, SKE_CRYPTO crypto,
|
|
uint8_t *key, uint16_t sp_key_idx, uint8_t *iv,
|
|
uint32_t iv_bytes, uint32_t aad_bytes,
|
|
uint32_t c_bytes)
|
|
{
|
|
uint32_t tmp[4];
|
|
|
|
if (NULL == ctx || NULL == iv) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (12 != iv_bytes) {
|
|
return SKE_INPUT_INVALID;
|
|
} else if ((0 == aad_bytes) && (0 == c_bytes)) {
|
|
return SKE_INPUT_INVALID;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_cpu_mode();
|
|
|
|
memcpy_(tmp, iv, iv_bytes);
|
|
tmp[3] = 0;
|
|
|
|
ctx->aad_bytes = aad_bytes;
|
|
ske_hp_set_aad_len_uint32(aad_bytes);
|
|
|
|
ctx->c_bytes = c_bytes;
|
|
ske_hp_set_c_len_uint32(c_bytes);
|
|
|
|
ctx->current_bytes = 0;
|
|
ctx->crypto = crypto;
|
|
|
|
return ske_hp_init_internal(ctx->ske_gcm_ctx, alg, SKE_MODE_GCM, crypto,
|
|
key, sp_key_idx, (uint8_t *)tmp);
|
|
}
|
|
|
|
/* function: ske_hp gcm mode input aad
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* aad ------------------------ input, aad, its length is ctx->aad_bytes,
|
|
* please make sure aad here is integral return: SKE_SUCCESS(success),
|
|
* other(error) caution:
|
|
* 1. this function must be called after calling ske_hp_gcm_init()
|
|
* 2. if there is no aad, this function could be omitted
|
|
*/
|
|
uint32_t ske_hp_gcm_aad(ske_gcm_ctx_t *ctx, uint8_t *aad)
|
|
{
|
|
uint32_t blocks_bytes, remainder_bytes;
|
|
uint32_t ret;
|
|
|
|
if (NULL == ctx || (NULL == aad && ctx->aad_bytes != 0)) {
|
|
return SKE_BUFFER_NULL;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
blocks_bytes = (ctx->aad_bytes) & (~0x0F);
|
|
remainder_bytes = (ctx->aad_bytes) & 0x0F;
|
|
|
|
if (remainder_bytes) {
|
|
ret =
|
|
ske_hp_update_blocks_no_output(ctx->ske_gcm_ctx, aad, blocks_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
memcpy_(ctx->buf, aad + blocks_bytes, remainder_bytes);
|
|
memset_(ctx->buf + remainder_bytes, 0, 16 - remainder_bytes);
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_gcm_ctx, ctx->buf, 16);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
} else {
|
|
if (blocks_bytes) {
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_gcm_ctx, aad,
|
|
blocks_bytes - 16);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_gcm_ctx,
|
|
aad + blocks_bytes - 16, 16);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
} else {
|
|
;
|
|
}
|
|
}
|
|
|
|
ske_hp_set_last_block(0);
|
|
|
|
ctx->current_bytes = 0;
|
|
|
|
return SKE_SUCCESS;
|
|
}
|
|
|
|
/* function: ske_hp gcm mode input plaintext/ciphertext
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* in ------------------------- input, plaintext or ciphertext
|
|
* out ------------------------ output, ciphertext or plaintext
|
|
* bytes ---------------------- input, byte length of input or output
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. this function must be called after calling ske_hp_gcm_aad()
|
|
* 2. if there is no plaintext/ciphertext, this function could be omitted
|
|
* 3. to save memory, in and out could be the same buffer, in this case, the
|
|
* output will cover the input.
|
|
* 4. if plaintext/ciphertext is too long, you could divide it by block(16
|
|
* bytes), and if bytes is not a multiple of 16, please make sure the last
|
|
* section contains the tail, then call this function to input the sections
|
|
* respectively. for example, if bytes is 65, the input could be divided into 3
|
|
* sections with byte length 48,16,1 respectively.
|
|
*/
|
|
uint32_t ske_hp_gcm_update(ske_gcm_ctx_t *ctx, uint8_t *in, uint8_t *out,
|
|
uint32_t bytes)
|
|
{
|
|
uint32_t blocks_bytes, remainder_bytes;
|
|
uint32_t ret;
|
|
|
|
if (NULL == ctx || NULL == in || NULL == out) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (0 == bytes) {
|
|
return SKE_SUCCESS;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
if (ctx->current_bytes + bytes > ctx->c_bytes) {
|
|
return SKE_INPUT_INVALID;
|
|
} else if (ctx->current_bytes + bytes == ctx->c_bytes) {
|
|
blocks_bytes = bytes & (~0x0F);
|
|
remainder_bytes = bytes & 0x0F;
|
|
|
|
if (0 == remainder_bytes) {
|
|
if (blocks_bytes) {
|
|
blocks_bytes -= 16;
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_gcm_ctx, in, out,
|
|
blocks_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_gcm_ctx,
|
|
in + blocks_bytes,
|
|
out + blocks_bytes, 16);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
} else {
|
|
;
|
|
}
|
|
} else {
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_gcm_ctx, in, out,
|
|
blocks_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
memcpy_(ctx->buf, in + blocks_bytes, remainder_bytes);
|
|
memset_(ctx->buf + remainder_bytes, 0, 16 - remainder_bytes);
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_gcm_ctx, ctx->buf,
|
|
ctx->buf, 16);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
memcpy_(out + blocks_bytes, ctx->buf, remainder_bytes);
|
|
}
|
|
} else {
|
|
if (bytes & (16 - 1)) {
|
|
return SKE_INPUT_INVALID;
|
|
} else {
|
|
ret =
|
|
ske_hp_update_blocks_internal(ctx->ske_gcm_ctx, in, out, bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ctx->current_bytes += bytes;
|
|
}
|
|
}
|
|
|
|
return SKE_SUCCESS;
|
|
}
|
|
|
|
/* function: ske_hp gcm mode finish
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* tag ------------------------ input(for decryption), output(for
|
|
* encryption) tag_bytes ------------------ input, byte length of tag. return:
|
|
* SKE_SUCCESS(success), other(error) caution:
|
|
* 1. this function must be called after calling ske_hp_gcm_update()
|
|
* 2. tag_bytes could be 0, but not bigger than SKE_HP_GCM_MAX_BYTES
|
|
* 3. for encryption, tag is output; and for decryption, tag is input, if
|
|
* returns SKE_SUCCESS that means certification passed, otherwise not.
|
|
*/
|
|
uint32_t ske_hp_gcm_final(ske_gcm_ctx_t *ctx, uint8_t *tag, uint32_t tag_bytes)
|
|
{
|
|
uint32_t ret;
|
|
|
|
if (NULL == ctx || NULL == tag) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (tag_bytes > SKE_HP_GCM_MAX_BYTES) {
|
|
return SKE_INPUT_INVALID;
|
|
}
|
|
|
|
ret = ske_hp_wait_till_output();
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_simple_get_output_block((uint32_t *)ctx->buf,
|
|
ctx->ske_gcm_ctx->block_words);
|
|
|
|
if (SKE_CRYPTO_ENCRYPT == ctx->crypto) {
|
|
memcpy_(tag, ctx->buf, tag_bytes);
|
|
ret = SKE_SUCCESS;
|
|
} else {
|
|
ret = memcmp_(tag, ctx->buf, tag_bytes);
|
|
}
|
|
|
|
memset_(ctx, 0, sizeof(ske_gcm_ctx_t));
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* function: ske_hp gcm mode encrypt/decrypt(one-off style)
|
|
* parameters:
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* crypto --------------------- input, encrypting or decrypting
|
|
* key ------------------------ input, key in bytes, key of AES(128/192/256)
|
|
* or SM4 sp_key_idx ----------------- input, index of secure port key,
|
|
* (sp_key_idx & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is
|
|
* 1, that means using low 128bit of the 256bit key iv -------------------------
|
|
* input, iv in bytes iv_bytes ------------------- input, byte length of iv, now
|
|
* only 12 bytes supported aad ------------------------ input, aad, please make
|
|
* sure aad here is integral aad_bytes ------------------ input, byte length of
|
|
* aad, it could be any value, including 0 c_bytes -------------------- input,
|
|
* byte length of plaintext/ciphertext, it could be any value, including 0 in
|
|
* ------------------------- input, plaintext or ciphertext out
|
|
* ------------------------ output, ciphertext or plaintext tag
|
|
* ------------------------ input(for decryption), output(for encryption)
|
|
* tag_bytes ------------------ input, byte length of tag.
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. this function is for CPU style
|
|
* 2. only AES(128/192/256) and SM4 are supported for GCM mode
|
|
* 3. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 4. iv must be 12 bytes here
|
|
* 5. aad_bytes and c_bytes could not be zero at the same time
|
|
* 6. to save memory, in and out could be the same buffer, in this case, the
|
|
* output will cover the input.
|
|
* 7. tag_bytes could be 0, but not bigger than SKE_HP_GCM_MAX_BYTES
|
|
* 8. for encryption, tag is output; and for decryption, tag is input, if
|
|
* returns SKE_SUCCESS that means certification passed, otherwise not.
|
|
*/
|
|
uint32_t ske_hp_gcm_crypto(SKE_ALG alg, SKE_CRYPTO crypto, uint8_t *key,
|
|
uint16_t sp_key_idx, uint8_t *iv, uint32_t iv_bytes,
|
|
uint8_t *aad, uint32_t aad_bytes, uint8_t *in,
|
|
uint8_t *out, uint32_t c_bytes, uint8_t *tag,
|
|
uint32_t tag_bytes)
|
|
{
|
|
ske_gcm_ctx_t ctx[1];
|
|
uint32_t ret;
|
|
|
|
ret = ske_hp_gcm_init(ctx, alg, crypto, key, sp_key_idx, iv, iv_bytes,
|
|
aad_bytes, c_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
ret = ske_hp_gcm_aad(ctx, aad);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
ret = ske_hp_gcm_update(ctx, in, out, c_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
return ske_hp_gcm_final(ctx, tag, tag_bytes);
|
|
}
|
|
|
|
#ifdef SKE_HP_DMA_FUNCTION
|
|
|
|
/* function: ske_hp dma gcm mode init config
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* crypto --------------------- input, encrypting or decrypting
|
|
* key ------------------------ input, key in bytes, key of AES(128/192/256)
|
|
* or SM4 sp_key_idx ----------------- input, index of secure port key,
|
|
* (sp_key_idx & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is
|
|
* 1, that means using low 128bit of the 256bit key iv -------------------------
|
|
* input, iv in bytes iv_bytes ------------------- input, byte length of iv, now
|
|
* only 12 bytes supported aad_bytes ------------------ input, byte length of
|
|
* aad, it could be any value, including 0 c_bytes -------------------- input,
|
|
* byte length of plaintext/ciphertext, it could be any value, including 0
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. this function is for DMA style
|
|
* 2. only AES(128/192/256) and SM4 are supported for GCM mode
|
|
* 3. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 4. iv must be 12 bytes here
|
|
* 5. aad_bytes and c_bytes could not be zero at the same time
|
|
*/
|
|
uint32_t ske_hp_dma_gcm_init(ske_gcm_ctx_t *ctx, SKE_ALG alg, SKE_CRYPTO crypto,
|
|
uint8_t *key, uint16_t sp_key_idx, uint8_t *iv,
|
|
uint32_t iv_bytes, uint32_t aad_bytes,
|
|
uint32_t c_bytes)
|
|
{
|
|
uint32_t tmp[4];
|
|
|
|
if (NULL == ctx || NULL == iv) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (12 != iv_bytes) {
|
|
return SKE_INPUT_INVALID;
|
|
} else if ((0 == aad_bytes) && (0 == c_bytes)) {
|
|
return SKE_INPUT_INVALID;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_dma_mode();
|
|
|
|
memcpy_(tmp, iv, iv_bytes);
|
|
tmp[3] = 0;
|
|
|
|
ctx->aad_bytes = aad_bytes;
|
|
ske_hp_set_aad_len_uint32(aad_bytes);
|
|
|
|
ctx->c_bytes = c_bytes;
|
|
ske_hp_set_c_len_uint32(c_bytes);
|
|
|
|
ctx->current_bytes = 0;
|
|
ctx->crypto = crypto;
|
|
|
|
return ske_hp_init_internal(ctx->ske_gcm_ctx, alg, SKE_MODE_GCM, crypto,
|
|
key, sp_key_idx, (uint8_t *)tmp);
|
|
}
|
|
|
|
/* function: ske_hp dma gcm mode input aad+plaintext/ciphertext, get
|
|
* ciphertext/plaintext+tag parameters: ctx ------------------------ input,
|
|
* ske_gcm_ctx_t context pointer in ------------------------- input,
|
|
* aad+plaintext/ciphertext out ------------------------ output,
|
|
* ciphertext/plaintext+tag tag_bytes ------------------ input, byte length of
|
|
* tag. return: SKE_SUCCESS(success), other(error) caution:
|
|
* 1. this function must be called after calling ske_hp_dma_gcm_init()
|
|
* 2. aad must be blocks, if not, please pad it with 0
|
|
* 3. plaintext/ciphertext must be blocks without padding 0
|
|
* 4. the output will be blocks too, and the last block is tag with padding
|
|
* 0 if necessary
|
|
* 5. please make sure aad+plaintext/ciphertext is integral
|
|
* 6. to save memory, in and out could be the same buffer, in this case, the
|
|
* output will cover the input.
|
|
*/
|
|
uint32_t ske_hp_dma_gcm_update_blocks(ske_gcm_ctx_t *ctx, uint32_t *in,
|
|
uint32_t *out, uint32_t tag_bytes)
|
|
{
|
|
uint32_t aad_blocks_words;
|
|
uint32_t c_blocks_words;
|
|
uint32_t c_bytes, i, ret;
|
|
|
|
if (NULL == ctx || NULL == in || NULL == out) {
|
|
return SKE_BUFFER_NULL;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
aad_blocks_words = ((ctx->aad_bytes + 15) / 16) * 4;
|
|
c_blocks_words = ((ctx->c_bytes + 15) / 16) * 4;
|
|
c_bytes = ctx->c_bytes;
|
|
|
|
ske_hp_set_last_block(1);
|
|
ret = ske_hp_dma_operate(ctx->ske_gcm_ctx, in, out,
|
|
aad_blocks_words + c_blocks_words,
|
|
c_blocks_words + 4);
|
|
|
|
if ((SKE_SUCCESS == ret)) {
|
|
/*get MSB(tag) of tag_bytes*/
|
|
if (c_bytes & 0x0F) {
|
|
i = (ctx->c_bytes) / 4;
|
|
c_bytes &= 0x03;
|
|
|
|
if (c_bytes) {
|
|
#ifdef SKE_HP_CPU_BIG_ENDIAN
|
|
out[i] &= (1 << (32 - c_bytes * 8)) - 1;
|
|
#else
|
|
out[i] &= (1 << (c_bytes * 8)) - 1;
|
|
#endif
|
|
i++;
|
|
}
|
|
|
|
while (i < c_blocks_words) {
|
|
out[i++] = 0;
|
|
}
|
|
}
|
|
|
|
out += c_blocks_words;
|
|
|
|
if (16 != tag_bytes) {
|
|
|
|
i = tag_bytes / 4;
|
|
tag_bytes &= 3;
|
|
|
|
if (tag_bytes) {
|
|
#ifdef SKE_HP_CPU_BIG_ENDIAN
|
|
out[i] &= (1 << (32 - tag_bytes * 8)) - 1;
|
|
#else
|
|
out[i] &= (1 << (tag_bytes * 8)) - 1;
|
|
#endif
|
|
i++;
|
|
}
|
|
|
|
while (i < 4) {
|
|
out[i++] = 0;
|
|
}
|
|
}
|
|
} else {
|
|
;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* function: ske_hp dma gcm mode finish
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_gcm_ctx_t context pointer
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. this function is optional
|
|
*/
|
|
uint32_t ske_hp_dma_gcm_final(ske_gcm_ctx_t *ctx)
|
|
{
|
|
if (NULL == ctx) {
|
|
return SKE_BUFFER_NULL;
|
|
}
|
|
|
|
memset_(ctx, 0, sizeof(ske_gcm_ctx_t));
|
|
|
|
return SKE_SUCCESS;
|
|
}
|
|
|
|
/* function: ske_hp dma gcm mode encrypt/decrypt(one-off style)
|
|
* parameters:
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* crypto --------------------- input, encrypting or decrypting
|
|
* key ------------------------ input, key in bytes, key of AES(128/192/256)
|
|
* or SM4 sp_key_idx ----------------- input, index of secure port key,
|
|
* (sp_key_idx & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is
|
|
* 1, that means using low 128bit of the 256bit key iv -------------------------
|
|
* input, iv in bytes iv_bytes ------------------- input, byte length of iv, now
|
|
* only 12 bytes supported aad_bytes ------------------ input, byte length of
|
|
* aad, it could be any value, including 0 in ------------------------- input,
|
|
* aad+plaintext/ciphertext out ------------------------ output,
|
|
* ciphertext/plaintext+tag c_bytes -------------------- input, byte length of
|
|
* plaintext/ciphertext, it could be any value, including 0 tag_bytes
|
|
* ------------------ input, byte length of tag. return: SKE_SUCCESS(success),
|
|
* other(error) caution:
|
|
* 1. this function is for DMA style
|
|
* 2. only AES(128/192/256) and SM4 are supported for GCM mode
|
|
* 3. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 4. iv must be 12 bytes here
|
|
* 5. aad_bytes and c_bytes could not be zero at the same time
|
|
* 6. aad must be blocks, if not, please pad it with 0
|
|
* 7. plaintext/ciphertext must be blocks without padding 0
|
|
* 8. the output will be blocks too, and the last block is tag with padding
|
|
* 0 if necessary
|
|
* 9. please make sure aad+plaintext/ciphertext is integral
|
|
* 10. to save memory, in and out could be the same buffer, in this case,
|
|
* the output will cover the input.
|
|
*/
|
|
uint32_t ske_hp_dma_gcm_crypto(SKE_ALG alg, SKE_CRYPTO crypto, uint8_t *key,
|
|
uint16_t sp_key_idx, uint8_t *iv,
|
|
uint32_t iv_bytes, uint32_t aad_bytes,
|
|
uint32_t *in, uint32_t *out, uint32_t c_bytes,
|
|
uint32_t tag_bytes)
|
|
{
|
|
ske_gcm_ctx_t ctx[1];
|
|
uint32_t ret;
|
|
|
|
ret = ske_hp_dma_gcm_init(ctx, alg, crypto, key, sp_key_idx, iv, iv_bytes,
|
|
aad_bytes, c_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
ret = ske_hp_dma_gcm_update_blocks(ctx, in, out, tag_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
}
|
|
|
|
return ske_hp_dma_gcm_final(ctx);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|