mirror of https://github.com/ARMmbed/mbed-os.git
M467 Support crypto AES-CCM H/W with one-shot & cascade mode
parent
88a529180f
commit
a430d70c0d
|
@ -9,6 +9,7 @@ target_include_directories(mbed-mbedtls
|
||||||
./rsa
|
./rsa
|
||||||
./sha
|
./sha
|
||||||
./gcm
|
./gcm
|
||||||
|
./ccm
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(mbed-mbedtls
|
target_sources(mbed-mbedtls
|
||||||
|
@ -22,4 +23,5 @@ target_sources(mbed-mbedtls
|
||||||
sha/sha512_alt.c
|
sha/sha512_alt.c
|
||||||
sha/sha_alt_hw.c
|
sha/sha_alt_hw.c
|
||||||
gcm/gcm_alt.c
|
gcm/gcm_alt.c
|
||||||
|
ccm/ccm_alt.c
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,738 @@
|
||||||
|
/*
|
||||||
|
* NIST SP800-38C compliant CCM implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||||
|
* Copyright (c) 2022, Nuvoton Technology Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of CCM:
|
||||||
|
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||||
|
* RFC 3610 "Counter with CBC-MAC (CCM)"
|
||||||
|
*
|
||||||
|
* Related:
|
||||||
|
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_CCM_C)
|
||||||
|
|
||||||
|
#include "mbedtls/ccm.h"
|
||||||
|
#include "mbedtls/platform_util.h"
|
||||||
|
#include "mbedtls/error.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||||
|
#if defined(MBEDTLS_PLATFORM_C)
|
||||||
|
#include "mbedtls/platform.h"
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#define mbedtls_printf printf
|
||||||
|
#endif /* MBEDTLS_PLATFORM_C */
|
||||||
|
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_CCM_ALT)
|
||||||
|
|
||||||
|
#include "M460.h"
|
||||||
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
#include "nu_bitutil.h"
|
||||||
|
#include "crypto-misc.h"
|
||||||
|
|
||||||
|
#define CCM_VALIDATE_RET( cond ) \
|
||||||
|
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
|
||||||
|
#define CCM_VALIDATE( cond ) \
|
||||||
|
MBEDTLS_INTERNAL_VALIDATE( cond )
|
||||||
|
|
||||||
|
#define CCM_ENCRYPT 1
|
||||||
|
#define CCM_DECRYPT 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define CCM_MODE (AES_MODE_CCM << CRPT_AES_CTL_OPMODE_Pos)
|
||||||
|
#define START CRPT_AES_CTL_START_Msk
|
||||||
|
#define DMAEN CRPT_AES_CTL_DMAEN_Msk
|
||||||
|
#define DMALAST CRPT_AES_CTL_DMALAST_Msk
|
||||||
|
#define DMACC CRPT_AES_CTL_DMACSCAD_Msk
|
||||||
|
#define START CRPT_AES_CTL_START_Msk
|
||||||
|
#define FBIN CRPT_AES_CTL_FBIN_Msk
|
||||||
|
#define FBOUT CRPT_AES_CTL_FBOUT_Msk
|
||||||
|
|
||||||
|
|
||||||
|
#define Debug_CCM_Info(x) {}
|
||||||
|
//#define Debug_CCM_Info(x) { printf x; }
|
||||||
|
|
||||||
|
int32_t ToBigEndian(uint8_t *pbuf, uint32_t u32Size)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t u8Tmp;
|
||||||
|
uint32_t u32Tmp;
|
||||||
|
|
||||||
|
/* pbuf must be word alignment */
|
||||||
|
if((uint32_t)pbuf & 0x3)
|
||||||
|
{
|
||||||
|
printf("The buffer must be 32-bit alignment.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(u32Size >= 4)
|
||||||
|
{
|
||||||
|
u8Tmp = *pbuf;
|
||||||
|
*(pbuf) = *(pbuf + 3);
|
||||||
|
*(pbuf + 3) = u8Tmp;
|
||||||
|
|
||||||
|
u8Tmp = *(pbuf + 1);
|
||||||
|
*(pbuf + 1) = *(pbuf + 2);
|
||||||
|
*(pbuf + 2) = u8Tmp;
|
||||||
|
|
||||||
|
u32Size -= 4;
|
||||||
|
pbuf += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(u32Size > 0)
|
||||||
|
{
|
||||||
|
u32Tmp = 0;
|
||||||
|
for(i = 0; i < u32Size; i++)
|
||||||
|
{
|
||||||
|
u32Tmp |= *(pbuf + i) << (24 - i * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((uint32_t *)pbuf) = u32Tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
CCM input format must be block alignment. The block size is 16 bytes.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Block B0
|
||||||
|
Formatting of the Control Information and the Nonce
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
First block B_0:
|
||||||
|
0 .. 0 flags
|
||||||
|
1 .. iv_len nonce (aka iv)
|
||||||
|
iv_len+1 .. 15 length
|
||||||
|
|
||||||
|
|
||||||
|
flags:
|
||||||
|
With flags as (bits):
|
||||||
|
7 0
|
||||||
|
6 add present?
|
||||||
|
5 .. 3 (t - 2) / 2
|
||||||
|
2 .. 0 q - 1
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32_t CCMPacker(const uint8_t *iv, uint32_t ivlen, const uint8_t *A, uint32_t alen, const uint8_t *P, uint32_t plen, uint8_t *pbuf, uint32_t *psize, uint32_t tlen, int32_t enc)
|
||||||
|
{
|
||||||
|
uint32_t i, j;
|
||||||
|
uint32_t alen_aligned, plen_aligned;
|
||||||
|
uint32_t u32Offset = 0;
|
||||||
|
uint8_t u8Tmp;
|
||||||
|
uint32_t q = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* Flags in B0
|
||||||
|
*With flags as(bits) :
|
||||||
|
7 0
|
||||||
|
6 add present ?
|
||||||
|
5 .. 3 (t - 2) / 2
|
||||||
|
2 .. 0 q - 1, q = 15 - nlen
|
||||||
|
*/
|
||||||
|
if( tlen > 0 )
|
||||||
|
{
|
||||||
|
q = 15 - ivlen;
|
||||||
|
u8Tmp = (q - 1) | ((tlen - 2) / 2 << 3) | ((alen > 0) ? 0x40 : 0);
|
||||||
|
pbuf[0] = u8Tmp; // flags
|
||||||
|
for(i = 0; i < ivlen; i++) // N
|
||||||
|
pbuf[i + 1] = iv[i];
|
||||||
|
for(i = ivlen + 1, j = q - 1; i < 16; i++, j--) // Q
|
||||||
|
{
|
||||||
|
if(j >= 4)
|
||||||
|
pbuf[i] = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pbuf[i] = (plen >> j * 8) & 0xfful;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32Offset = 16;
|
||||||
|
}
|
||||||
|
/* Formatting addition data */
|
||||||
|
/* alen. It is limited to be smaller than 2^16-2^8 */
|
||||||
|
if(alen > 0)
|
||||||
|
{
|
||||||
|
pbuf[u32Offset] = (alen >> 8) & 0xfful;
|
||||||
|
pbuf[u32Offset + 1] = alen & 0xfful;
|
||||||
|
|
||||||
|
for(i = 0; i < alen; i++)
|
||||||
|
pbuf[u32Offset + i + 2] = A[i];
|
||||||
|
|
||||||
|
alen_aligned = ((alen + 2 + 15) / 16) * 16;
|
||||||
|
for(i = u32Offset + 2 + alen; i < alen_aligned; i++)
|
||||||
|
{
|
||||||
|
pbuf[i] = (enc) ? 0:0xff; // padding zero or 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
u32Offset += alen_aligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Formatting payload */
|
||||||
|
if( (plen > 0) && (P != 0x00))
|
||||||
|
{
|
||||||
|
plen_aligned = ((plen + 15) / 16) * 16;
|
||||||
|
for(i = 0; i < plen; i++)
|
||||||
|
{
|
||||||
|
pbuf[u32Offset + i] = P[i];
|
||||||
|
}
|
||||||
|
for(; i < plen_aligned; i++)
|
||||||
|
{
|
||||||
|
pbuf[u32Offset + i] = 0; // padding zero
|
||||||
|
}
|
||||||
|
|
||||||
|
u32Offset += plen_aligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Formatting Ctr0 */
|
||||||
|
if( ivlen > 0 )
|
||||||
|
{
|
||||||
|
pbuf[u32Offset] = q - 1; // Flags
|
||||||
|
for(i = 0; i < ivlen; i++) // N
|
||||||
|
{
|
||||||
|
pbuf[u32Offset + 1 + i] = iv[i];
|
||||||
|
}
|
||||||
|
for(; i < 16; i++)
|
||||||
|
{
|
||||||
|
pbuf[u32Offset + 1 + i] = 0; // padding zero to block alignment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*psize = u32Offset;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
static void DumpBuffHex(uint8_t *pucBuff, int nBytes)
|
||||||
|
{
|
||||||
|
int32_t i32Idx, i, len;
|
||||||
|
|
||||||
|
|
||||||
|
i32Idx = 0;
|
||||||
|
while(nBytes > 0)
|
||||||
|
{
|
||||||
|
printf("0x%04X ", i32Idx);
|
||||||
|
|
||||||
|
len = (nBytes < 16) ? nBytes : 16;
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
printf("%02x ", pucBuff[i32Idx + i]);
|
||||||
|
for(; i < 16; i++)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf(" ");
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if((pucBuff[i32Idx + i] >= 0x20) && (pucBuff[i32Idx + i] < 127))
|
||||||
|
printf("%c", pucBuff[i32Idx + i]);
|
||||||
|
else
|
||||||
|
printf(".");
|
||||||
|
nBytes--;
|
||||||
|
}
|
||||||
|
i32Idx += len;
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DumpBuffHex2(uint8_t *pucBuff, int nBytes)
|
||||||
|
{
|
||||||
|
int32_t i32Idx, i;
|
||||||
|
|
||||||
|
i32Idx = 0;
|
||||||
|
while(nBytes > 0)
|
||||||
|
{
|
||||||
|
printf("0x%04X ", i32Idx);
|
||||||
|
for(i = 0; i < 16; i += 4)
|
||||||
|
printf("%08x ", *((uint32_t *)&pucBuff[i32Idx + i]));
|
||||||
|
i32Idx += 16;
|
||||||
|
nBytes -= 16;
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t _CCM_OneShot(mbedtls_ccm_context *ctx, int32_t encDec, const uint8_t *iv, uint32_t ivlen, const uint8_t *A, uint32_t alen, const uint8_t *P, uint32_t plen, uint8_t *buf, uint8_t *tag, uint32_t tlen)
|
||||||
|
{
|
||||||
|
uint32_t size, plen_aligned;
|
||||||
|
const uint8_t* pIn;
|
||||||
|
uint8_t* pOut;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%lu, plen=%lu, ivlen=%lu, tlen=%lu\n", __FUNCTION__, alen, plen, ivlen, tlen));
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("key (%d):\n", (4 + 2*ctx->keySize)*4 );
|
||||||
|
DumpBuffHex(ctx->keys, (4 + 2*ctx->keySize)*4);
|
||||||
|
|
||||||
|
printf("N (%d):\n", ivlen);
|
||||||
|
DumpBuffHex(iv, ivlen);
|
||||||
|
|
||||||
|
printf("A (%d):\n", alen);
|
||||||
|
DumpBuffHex(A, alen);
|
||||||
|
|
||||||
|
printf("P (%d):\n", plen);
|
||||||
|
DumpBuffHex(P, plen);
|
||||||
|
|
||||||
|
printf("T len = %d\n", tlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Prepare the blocked buffer for CCM */
|
||||||
|
memset(ctx->ccm_buf, 0, MAX_CCM_BUF);
|
||||||
|
CCMPacker(iv, ivlen, A, alen, P, plen, ctx->ccm_buf, &size, tlen, encDec);
|
||||||
|
|
||||||
|
ToBigEndian(ctx->ccm_buf, size + 16);
|
||||||
|
|
||||||
|
plen_aligned = (plen & 0xful) ? ((plen + 15) / 16) * 16 : plen;
|
||||||
|
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
printf("input blocks (%d):\n", size);
|
||||||
|
DumpBuffHex2(ctx->ccm_buf, size);
|
||||||
|
|
||||||
|
printf("input key (%d):\n", size);
|
||||||
|
DumpBuffHex2(ctx->keys, (4 + 2*ctx->keySize)*4);
|
||||||
|
|
||||||
|
printf("input Ctr0:\n");
|
||||||
|
DumpBuffHex2(&(ctx->ccm_buf[size]), 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
AES_Open(CRPT, 0, encDec, ctx->opMode, ctx->keySize, AES_OUT_SWAP);
|
||||||
|
/* Set AES Key into H/W */
|
||||||
|
AES_SetKey(CRPT, 0, ctx->keys, ctx->keySize);
|
||||||
|
|
||||||
|
/* For ctr0 */
|
||||||
|
AES_SetInitVect(CRPT, 0, (uint32_t *)&ctx->ccm_buf[size]);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set bytes count of A */
|
||||||
|
CRPT->AES_GCM_ACNT[0] = size - plen_aligned;
|
||||||
|
CRPT->AES_GCM_ACNT[1] = 0;
|
||||||
|
CRPT->AES_GCM_PCNT[0] = plen;
|
||||||
|
CRPT->AES_GCM_PCNT[1] = 0;
|
||||||
|
|
||||||
|
pIn = ctx->ccm_buf;
|
||||||
|
pOut = ctx->out_buf;
|
||||||
|
AES_SetDMATransfer(CRPT, 0, (uint32_t)pIn, (uint32_t)pOut, size);
|
||||||
|
|
||||||
|
crypto_aes_prestart();
|
||||||
|
|
||||||
|
/* Start AES crypt */
|
||||||
|
AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT);
|
||||||
|
|
||||||
|
/* Waiting for AES calculation */
|
||||||
|
ret = crypto_aes_wait();
|
||||||
|
if( ret == false )
|
||||||
|
{
|
||||||
|
printf("###[WARN] AES CCM got NU_CRYPTO_DONE_ERR \n");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, ctx->out_buf, plen);
|
||||||
|
|
||||||
|
if(tlen > 16)
|
||||||
|
{
|
||||||
|
tlen = 16;
|
||||||
|
}
|
||||||
|
memcpy(tag, &ctx->out_buf[plen_aligned], tlen);
|
||||||
|
|
||||||
|
Debug_CCM_Info(("OneShot output blocks (%lu)(%lu):\n", size, plen));
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
DumpBuffHex2(buf, plen);
|
||||||
|
printf("OneShot output blocks Tag :\n");
|
||||||
|
DumpBuffHex2(&ctx->out_buf[plen_aligned], 16);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t AES_Run(mbedtls_ccm_context *ctx, uint32_t u32Option)
|
||||||
|
{
|
||||||
|
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
crypto_aes_prestart();
|
||||||
|
CRPT->AES_CTL = u32Option | START;
|
||||||
|
ret = crypto_aes_wait();
|
||||||
|
if( ret == false )
|
||||||
|
{
|
||||||
|
printf("###[WARN] AES CCM got NU_CRYPTO_DONE_ERR \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t _CCM_Cascade(mbedtls_ccm_context *ctx, int32_t encDec, const uint8_t *iv, uint32_t ivlen, const uint8_t *A, uint32_t alen, const uint8_t *P, uint32_t plen, uint8_t *buf, uint8_t *tag, uint32_t tlen)
|
||||||
|
{
|
||||||
|
uint32_t size, plen_aligned;
|
||||||
|
uint32_t u32OptBasic;
|
||||||
|
int32_t plen_cur;
|
||||||
|
int32_t len;
|
||||||
|
const uint8_t *pin;
|
||||||
|
uint8_t *pout;
|
||||||
|
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%lu, plen=%lu, ivlen=%lu, tlen=%lu\n", __FUNCTION__, alen, plen, ivlen, tlen));
|
||||||
|
/* Prepare the blocked buffer for CCM */
|
||||||
|
memset(ctx->ccm_buf, 0, MAX_CCM_BUF);
|
||||||
|
CCMPacker(iv, ivlen, A, alen, 0, plen, ctx->ccm_buf, &size, tlen, encDec);
|
||||||
|
|
||||||
|
ToBigEndian(ctx->ccm_buf, size + 16);
|
||||||
|
|
||||||
|
plen_aligned = (plen & 0xful) ? ((plen + 15) / 16) * 16 : plen;
|
||||||
|
|
||||||
|
|
||||||
|
AES_Open(CRPT, 0, encDec, ctx->opMode, ctx->keySize, AES_OUT_SWAP);
|
||||||
|
/* Set AES Key into H/W */
|
||||||
|
AES_SetKey(CRPT, 0, ctx->keys, ctx->keySize);
|
||||||
|
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
printf("input blocks (%d):\n", size);
|
||||||
|
DumpBuffHex2(ctx->ccm_buf, size);
|
||||||
|
printf("input Ctr0:\n");
|
||||||
|
DumpBuffHex2(&(ctx->ccm_buf[size]), 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For ctr0 */
|
||||||
|
AES_SetInitVect(CRPT, 0, (uint32_t *)&ctx->ccm_buf[size]);
|
||||||
|
|
||||||
|
/* Set bytes count of A */
|
||||||
|
CRPT->AES_GCM_ACNT[0] = size;
|
||||||
|
CRPT->AES_GCM_ACNT[1] = 0;
|
||||||
|
CRPT->AES_GCM_PCNT[0] = plen; //plen_aligned; /* set plen_aligned will get wrong tag @plen=24 */
|
||||||
|
CRPT->AES_GCM_PCNT[1] = 0;
|
||||||
|
|
||||||
|
AES_SetDMATransfer(CRPT, 0, (uint32_t)ctx->ccm_buf, (uint32_t)ctx->out_buf, size);
|
||||||
|
|
||||||
|
/* feedback buffer is necessary for cascade mode */
|
||||||
|
CRPT->AES_FBADDR = (uint32_t)ctx->fb_buf;;
|
||||||
|
|
||||||
|
u32OptBasic = CRPT->AES_CTL ;
|
||||||
|
|
||||||
|
AES_Run(ctx, u32OptBasic | CCM_MODE | FBOUT | DMAEN);
|
||||||
|
|
||||||
|
plen_cur = plen;
|
||||||
|
pin = P;
|
||||||
|
pout = buf;
|
||||||
|
while(plen_cur)
|
||||||
|
{
|
||||||
|
len = plen_cur;
|
||||||
|
if(len > CCM_PBLOCK_SIZE)
|
||||||
|
{
|
||||||
|
len = CCM_PBLOCK_SIZE;
|
||||||
|
}
|
||||||
|
plen_cur -= len;
|
||||||
|
|
||||||
|
/* Prepare the blocked buffer for CCM */
|
||||||
|
CCMPacker(0, 0, 0, 0, pin, len, ctx->ccm_buf, &size, 0, encDec);
|
||||||
|
|
||||||
|
ToBigEndian(ctx->ccm_buf, size);
|
||||||
|
|
||||||
|
AES_SetDMATransfer(CRPT, 0, (uint32_t)ctx->ccm_buf, (uint32_t)pout, size);
|
||||||
|
|
||||||
|
/* Start AES Eecrypt */
|
||||||
|
if(plen_cur)
|
||||||
|
{
|
||||||
|
/* casecade n */
|
||||||
|
AES_Run(ctx, u32OptBasic | CCM_MODE | FBIN | FBOUT | DMAEN | DMACC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* last cascade */
|
||||||
|
AES_SetDMATransfer(CRPT, 0, (uint32_t)ctx->ccm_buf, (uint32_t)ctx->out_buf, size);
|
||||||
|
AES_Run(ctx, u32OptBasic | CCM_MODE | FBIN | FBOUT | DMAEN | DMACC | DMALAST);
|
||||||
|
memcpy(pout, ctx->out_buf, len);
|
||||||
|
}
|
||||||
|
Debug_CCM_Info(("output blocks (%lu)(%lu):\n", size, len));
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
DumpBuffHex2(pout, len);
|
||||||
|
#endif
|
||||||
|
pin += len;
|
||||||
|
pout += size;
|
||||||
|
}
|
||||||
|
#ifdef NVT_CCM_DEBUG
|
||||||
|
printf("output blocks Tag :\n");
|
||||||
|
DumpBuffHex2(&ctx->out_buf[size], 16);
|
||||||
|
#endif
|
||||||
|
if(tlen > 16)
|
||||||
|
{
|
||||||
|
tlen = 16;
|
||||||
|
}
|
||||||
|
memcpy(tag, &ctx->out_buf[size], tlen);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t _CCM(mbedtls_ccm_context *ctx, int32_t encDec, const uint8_t *iv, uint32_t ivlen, const uint8_t *A, uint32_t alen, const uint8_t *P, uint32_t plen, uint8_t *buf, uint8_t *tag, uint32_t tlen)
|
||||||
|
{
|
||||||
|
uint32_t plen_aligned, alen_aligned;
|
||||||
|
int32_t ret;
|
||||||
|
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%lu, plen=%lu, ivlen=%lu, tlen=%lu\n", __FUNCTION__, alen, plen, ivlen, tlen));
|
||||||
|
|
||||||
|
if(ivlen > 16)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Formatting addition data: 2 bytes to store A's length */
|
||||||
|
alen_aligned = ((alen + 2 + 15) / 16) * 16;
|
||||||
|
plen_aligned = ((plen + 15) / 16) * 16;
|
||||||
|
|
||||||
|
/* Length of B0's formatting nonce (aka iv): 16 */
|
||||||
|
if( (16 + alen_aligned + plen_aligned ) < CCM_PBLOCK_SIZE )
|
||||||
|
{
|
||||||
|
ret = _CCM_OneShot(ctx, encDec, iv, ivlen, A, alen, P, plen, buf, tag, tlen);
|
||||||
|
} else {
|
||||||
|
ret = _CCM_Cascade(ctx, encDec, iv, ivlen, A, alen, P, plen, buf, tag, tlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize context
|
||||||
|
*/
|
||||||
|
void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
|
||||||
|
{
|
||||||
|
CCM_VALIDATE( ctx != NULL );
|
||||||
|
memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
|
||||||
|
|
||||||
|
ctx->opMode = AES_MODE_CCM;
|
||||||
|
/* Init crypto module */
|
||||||
|
crypto_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
|
||||||
|
mbedtls_cipher_id_t cipher,
|
||||||
|
const unsigned char *key,
|
||||||
|
unsigned int keybits )
|
||||||
|
{
|
||||||
|
int32_t klen;
|
||||||
|
|
||||||
|
CCM_VALIDATE_RET( ctx != NULL );
|
||||||
|
CCM_VALIDATE_RET( key != NULL );
|
||||||
|
CCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
|
||||||
|
|
||||||
|
|
||||||
|
klen = keybits / 8;
|
||||||
|
|
||||||
|
memcpy(ctx->keys, key, klen);
|
||||||
|
ToBigEndian((uint8_t *)ctx->keys, klen);
|
||||||
|
|
||||||
|
switch( keybits ) {
|
||||||
|
case 128:
|
||||||
|
ctx->keySize = AES_KEY_SIZE_128;
|
||||||
|
break;
|
||||||
|
case 192:
|
||||||
|
ctx->keySize = AES_KEY_SIZE_192;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
ctx->keySize = AES_KEY_SIZE_256;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free context
|
||||||
|
*/
|
||||||
|
void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
|
||||||
|
{
|
||||||
|
if( ctx == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Uninit crypto module */
|
||||||
|
crypto_uninit();
|
||||||
|
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authenticated encryption or decryption
|
||||||
|
*/
|
||||||
|
static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
unsigned char *tag, size_t tag_len )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check length requirements: SP800-38C A.1
|
||||||
|
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
|
||||||
|
* 'length' checked later (when writing it to the first block)
|
||||||
|
*
|
||||||
|
* Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
|
||||||
|
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||||
|
|
||||||
|
/* Also implies q is within bounds */
|
||||||
|
if( iv_len < 7 || iv_len > 13 )
|
||||||
|
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||||
|
|
||||||
|
if( add_len >= 0xFF00 )
|
||||||
|
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||||
|
|
||||||
|
|
||||||
|
ctx->opMode = AES_MODE_CCM;
|
||||||
|
ctx->encDec = mode;
|
||||||
|
|
||||||
|
|
||||||
|
/* Acquire ownership of AES H/W */
|
||||||
|
crypto_aes_acquire();
|
||||||
|
#if 1
|
||||||
|
/* Force AES free */
|
||||||
|
CRPT->AES_CTL = CRPT_AES_CTL_STOP_Msk;
|
||||||
|
#endif
|
||||||
|
AES_ENABLE_INT(CRPT);
|
||||||
|
|
||||||
|
ret = _CCM(ctx, mode, iv, iv_len, add, add_len, input, length, output, tag, tag_len);
|
||||||
|
|
||||||
|
/* Release ownership of AES H/W */
|
||||||
|
crypto_aes_release();
|
||||||
|
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authenticated encryption
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
unsigned char *tag, size_t tag_len )
|
||||||
|
{
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%u, plen=%u, ivlen=%u, tlen=%u\n", __FUNCTION__, add_len, length, iv_len, tag_len));
|
||||||
|
CCM_VALIDATE_RET( ctx != NULL );
|
||||||
|
CCM_VALIDATE_RET( iv != NULL );
|
||||||
|
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || input != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || output != NULL );
|
||||||
|
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
|
||||||
|
return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
|
||||||
|
add, add_len, input, output, tag, tag_len ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
unsigned char *tag, size_t tag_len )
|
||||||
|
{
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%u, plen=%u, ivlen=%u, tlen=%u\n", __FUNCTION__, add_len, length, iv_len, tag_len));
|
||||||
|
CCM_VALIDATE_RET( ctx != NULL );
|
||||||
|
CCM_VALIDATE_RET( iv != NULL );
|
||||||
|
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || input != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || output != NULL );
|
||||||
|
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
|
||||||
|
if( tag_len == 0 )
|
||||||
|
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||||
|
|
||||||
|
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
|
||||||
|
add_len, input, output, tag, tag_len ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authenticated decryption
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
const unsigned char *tag, size_t tag_len )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char check_tag[16];
|
||||||
|
unsigned char i;
|
||||||
|
int diff;
|
||||||
|
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%u, plen=%u, ivlen=%u, tlen=%u\n", __FUNCTION__, add_len, length, iv_len, tag_len));
|
||||||
|
CCM_VALIDATE_RET( ctx != NULL );
|
||||||
|
CCM_VALIDATE_RET( iv != NULL );
|
||||||
|
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || input != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || output != NULL );
|
||||||
|
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
|
||||||
|
|
||||||
|
if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
|
||||||
|
iv, iv_len, add, add_len,
|
||||||
|
input, output, check_tag, tag_len ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check tag in "constant-time" */
|
||||||
|
for( diff = 0, i = 0; i < tag_len; i++ )
|
||||||
|
diff |= tag[i] ^ check_tag[i];
|
||||||
|
|
||||||
|
if( diff != 0 )
|
||||||
|
{
|
||||||
|
mbedtls_platform_zeroize( output, length );
|
||||||
|
return( MBEDTLS_ERR_CCM_AUTH_FAILED );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
const unsigned char *tag, size_t tag_len )
|
||||||
|
{
|
||||||
|
Debug_CCM_Info(("## FUNC: %s, alen=%u, plen=%u, ivlen=%u, tlen=%u\n", __FUNCTION__, add_len, length, iv_len, tag_len));
|
||||||
|
CCM_VALIDATE_RET( ctx != NULL );
|
||||||
|
CCM_VALIDATE_RET( iv != NULL );
|
||||||
|
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || input != NULL );
|
||||||
|
CCM_VALIDATE_RET( length == 0 || output != NULL );
|
||||||
|
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
|
||||||
|
|
||||||
|
if( tag_len == 0 )
|
||||||
|
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||||
|
|
||||||
|
return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
|
||||||
|
add_len, input, output, tag, tag_len ) );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_CCM_ALT */
|
||||||
|
#endif /* MBEDTLS_CCM_C */
|
|
@ -0,0 +1,318 @@
|
||||||
|
/**
|
||||||
|
* \file ccm.h
|
||||||
|
*
|
||||||
|
* \brief This file provides an API for the CCM authenticated encryption
|
||||||
|
* mode for block ciphers.
|
||||||
|
*
|
||||||
|
* CCM combines Counter mode encryption with CBC-MAC authentication
|
||||||
|
* for 128-bit block ciphers.
|
||||||
|
*
|
||||||
|
* Input to CCM includes the following elements:
|
||||||
|
* <ul><li>Payload - data that is both authenticated and encrypted.</li>
|
||||||
|
* <li>Associated data (Adata) - data that is authenticated but not
|
||||||
|
* encrypted, For example, a header.</li>
|
||||||
|
* <li>Nonce - A unique value that is assigned to the payload and the
|
||||||
|
* associated data.</li></ul>
|
||||||
|
*
|
||||||
|
* Definition of CCM:
|
||||||
|
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||||
|
* RFC 3610 "Counter with CBC-MAC (CCM)"
|
||||||
|
*
|
||||||
|
* Related:
|
||||||
|
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
|
||||||
|
*
|
||||||
|
* Definition of CCM*:
|
||||||
|
* IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
|
||||||
|
* Integer representation is fixed most-significant-octet-first order and
|
||||||
|
* the representation of octets is most-significant-bit-first order. This is
|
||||||
|
* consistent with RFC 3610.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
|
||||||
|
* Copyright (c) 2022, Nuvoton Technology Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of Mbed TLS (https://tls.mbed.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MBEDTLS_CCM_ALT_H
|
||||||
|
#define MBEDTLS_CCM_ALT_H
|
||||||
|
|
||||||
|
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||||
|
#include "config.h"
|
||||||
|
#else
|
||||||
|
#include MBEDTLS_CONFIG_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mbed_toolchain.h"
|
||||||
|
#include "mbedtls/cipher.h"
|
||||||
|
#include "NuMicro.h"
|
||||||
|
|
||||||
|
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
|
||||||
|
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
|
||||||
|
|
||||||
|
/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
|
||||||
|
#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Regular implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
#define MAX_CCM_BUF 256
|
||||||
|
#define CCM_PBLOCK_SIZE MAX_CCM_BUF
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The CCM context-type definition. The CCM context is passed
|
||||||
|
* to the APIs called.
|
||||||
|
*/
|
||||||
|
typedef struct mbedtls_ccm_context
|
||||||
|
{
|
||||||
|
MBED_ALIGN(4) uint8_t ccm_buf[MAX_CCM_BUF + 16]; /* 16 bytes for ctr0 in packer */
|
||||||
|
MBED_ALIGN(4) uint8_t out_buf[MAX_CCM_BUF + 16]; /* 16 bytes for tag */
|
||||||
|
MBED_ALIGN(4) uint8_t fb_buf[72]; /* feedback buffer for GCM DMA */
|
||||||
|
uint32_t keySize;
|
||||||
|
uint32_t keys[8]; /* Cipher key */
|
||||||
|
uint32_t encDec; /* 0: decrypt, 1: encrypt */
|
||||||
|
uint32_t opMode; /* AES_MODE CCM */
|
||||||
|
|
||||||
|
}
|
||||||
|
mbedtls_ccm_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function initializes the specified CCM context,
|
||||||
|
* to make references valid, and prepare the context
|
||||||
|
* for mbedtls_ccm_setkey() or mbedtls_ccm_free().
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to initialize. This must not be \c NULL.
|
||||||
|
*/
|
||||||
|
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function initializes the CCM context set in the
|
||||||
|
* \p ctx parameter and sets the encryption key.
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to initialize. This must be an initialized
|
||||||
|
* context.
|
||||||
|
* \param cipher The 128-bit block cipher to use.
|
||||||
|
* \param key The encryption key. This must not be \c NULL.
|
||||||
|
* \param keybits The key size in bits. This must be acceptable by the cipher.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success.
|
||||||
|
* \return A CCM or cipher-specific error code on failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
|
||||||
|
mbedtls_cipher_id_t cipher,
|
||||||
|
const unsigned char *key,
|
||||||
|
unsigned int keybits );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function releases and clears the specified CCM context
|
||||||
|
* and underlying cipher sub-context.
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to clear. If this is \c NULL, the function
|
||||||
|
* has no effect. Otherwise, this must be initialized.
|
||||||
|
*/
|
||||||
|
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function encrypts a buffer using CCM.
|
||||||
|
*
|
||||||
|
* \note The tag is written to a separate buffer. To concatenate
|
||||||
|
* the \p tag with the \p output, as done in <em>RFC-3610:
|
||||||
|
* Counter with CBC-MAC (CCM)</em>, use
|
||||||
|
* \p tag = \p output + \p length, and make sure that the
|
||||||
|
* output buffer is at least \p length + \p tag_len wide.
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to use for encryption. This must be
|
||||||
|
* initialized and bound to a key.
|
||||||
|
* \param length The length of the input data in Bytes.
|
||||||
|
* \param iv The initialization vector (nonce). This must be a readable
|
||||||
|
* buffer of at least \p iv_len Bytes.
|
||||||
|
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
|
||||||
|
* or 13. The length L of the message length field is
|
||||||
|
* 15 - \p iv_len.
|
||||||
|
* \param add The additional data field. If \p add_len is greater than
|
||||||
|
* zero, \p add must be a readable buffer of at least that
|
||||||
|
* length.
|
||||||
|
* \param add_len The length of additional data in Bytes.
|
||||||
|
* This must be less than `2^16 - 2^8`.
|
||||||
|
* \param input The buffer holding the input data. If \p length is greater
|
||||||
|
* than zero, \p input must be a readable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param output The buffer holding the output data. If \p length is greater
|
||||||
|
* than zero, \p output must be a writable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param tag The buffer holding the authentication field. This must be a
|
||||||
|
* readable buffer of at least \p tag_len Bytes.
|
||||||
|
* \param tag_len The length of the authentication field to generate in Bytes:
|
||||||
|
* 4, 6, 8, 10, 12, 14 or 16.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success.
|
||||||
|
* \return A CCM or cipher-specific error code on failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
unsigned char *tag, size_t tag_len );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function encrypts a buffer using CCM*.
|
||||||
|
*
|
||||||
|
* \note The tag is written to a separate buffer. To concatenate
|
||||||
|
* the \p tag with the \p output, as done in <em>RFC-3610:
|
||||||
|
* Counter with CBC-MAC (CCM)</em>, use
|
||||||
|
* \p tag = \p output + \p length, and make sure that the
|
||||||
|
* output buffer is at least \p length + \p tag_len wide.
|
||||||
|
*
|
||||||
|
* \note When using this function in a variable tag length context,
|
||||||
|
* the tag length has to be encoded into the \p iv passed to
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to use for encryption. This must be
|
||||||
|
* initialized and bound to a key.
|
||||||
|
* \param length The length of the input data in Bytes.
|
||||||
|
* \param iv The initialization vector (nonce). This must be a readable
|
||||||
|
* buffer of at least \p iv_len Bytes.
|
||||||
|
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
|
||||||
|
* or 13. The length L of the message length field is
|
||||||
|
* 15 - \p iv_len.
|
||||||
|
* \param add The additional data field. This must be a readable buffer of
|
||||||
|
* at least \p add_len Bytes.
|
||||||
|
* \param add_len The length of additional data in Bytes.
|
||||||
|
* This must be less than 2^16 - 2^8.
|
||||||
|
* \param input The buffer holding the input data. If \p length is greater
|
||||||
|
* than zero, \p input must be a readable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param output The buffer holding the output data. If \p length is greater
|
||||||
|
* than zero, \p output must be a writable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param tag The buffer holding the authentication field. This must be a
|
||||||
|
* readable buffer of at least \p tag_len Bytes.
|
||||||
|
* \param tag_len The length of the authentication field to generate in Bytes:
|
||||||
|
* 0, 4, 6, 8, 10, 12, 14 or 16.
|
||||||
|
*
|
||||||
|
* \warning Passing \c 0 as \p tag_len means that the message is no
|
||||||
|
* longer authenticated.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success.
|
||||||
|
* \return A CCM or cipher-specific error code on failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
unsigned char *tag, size_t tag_len );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function performs a CCM authenticated decryption of a
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to use for decryption. This must be
|
||||||
|
* initialized and bound to a key.
|
||||||
|
* \param length The length of the input data in Bytes.
|
||||||
|
* \param iv The initialization vector (nonce). This must be a readable
|
||||||
|
* buffer of at least \p iv_len Bytes.
|
||||||
|
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
|
||||||
|
* or 13. The length L of the message length field is
|
||||||
|
* 15 - \p iv_len.
|
||||||
|
* \param add The additional data field. This must be a readable buffer
|
||||||
|
* of at least that \p add_len Bytes..
|
||||||
|
* \param add_len The length of additional data in Bytes.
|
||||||
|
* This must be less than 2^16 - 2^8.
|
||||||
|
* \param input The buffer holding the input data. If \p length is greater
|
||||||
|
* than zero, \p input must be a readable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param output The buffer holding the output data. If \p length is greater
|
||||||
|
* than zero, \p output must be a writable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param tag The buffer holding the authentication field. This must be a
|
||||||
|
* readable buffer of at least \p tag_len Bytes.
|
||||||
|
* \param tag_len The length of the authentication field to generate in Bytes:
|
||||||
|
* 4, 6, 8, 10, 12, 14 or 16.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success. This indicates that the message is authentic.
|
||||||
|
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
|
||||||
|
* \return A cipher-specific error code on calculation failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
const unsigned char *tag, size_t tag_len );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function performs a CCM* authenticated decryption of a
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* \note When using this function in a variable tag length context,
|
||||||
|
* the tag length has to be decoded from \p iv and passed to
|
||||||
|
* this function as \p tag_len. (\p tag needs to be adjusted
|
||||||
|
* accordingly.)
|
||||||
|
*
|
||||||
|
* \param ctx The CCM context to use for decryption. This must be
|
||||||
|
* initialized and bound to a key.
|
||||||
|
* \param length The length of the input data in Bytes.
|
||||||
|
* \param iv The initialization vector (nonce). This must be a readable
|
||||||
|
* buffer of at least \p iv_len Bytes.
|
||||||
|
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
|
||||||
|
* or 13. The length L of the message length field is
|
||||||
|
* 15 - \p iv_len.
|
||||||
|
* \param add The additional data field. This must be a readable buffer of
|
||||||
|
* at least that \p add_len Bytes.
|
||||||
|
* \param add_len The length of additional data in Bytes.
|
||||||
|
* This must be less than 2^16 - 2^8.
|
||||||
|
* \param input The buffer holding the input data. If \p length is greater
|
||||||
|
* than zero, \p input must be a readable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param output The buffer holding the output data. If \p length is greater
|
||||||
|
* than zero, \p output must be a writable buffer of at least
|
||||||
|
* that length.
|
||||||
|
* \param tag The buffer holding the authentication field. This must be a
|
||||||
|
* readable buffer of at least \p tag_len Bytes.
|
||||||
|
* \param tag_len The length of the authentication field in Bytes.
|
||||||
|
* 0, 4, 6, 8, 10, 12, 14 or 16.
|
||||||
|
*
|
||||||
|
* \warning Passing \c 0 as \p tag_len means that the message is nos
|
||||||
|
* longer authenticated.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success.
|
||||||
|
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
|
||||||
|
* \return A cipher-specific error code on calculation failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||||
|
const unsigned char *iv, size_t iv_len,
|
||||||
|
const unsigned char *add, size_t add_len,
|
||||||
|
const unsigned char *input, unsigned char *output,
|
||||||
|
const unsigned char *tag, size_t tag_len );
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||||
|
/**
|
||||||
|
* \brief The CCM checkup routine.
|
||||||
|
*
|
||||||
|
* \return \c 0 on success.
|
||||||
|
* \return \c 1 on failure.
|
||||||
|
*/
|
||||||
|
int mbedtls_ccm_self_test( int verbose );
|
||||||
|
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_CCM_ALT_H */
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#define MBEDTLS_AES_ALT
|
#define MBEDTLS_AES_ALT
|
||||||
#define MBEDTLS_GCM_ALT
|
#define MBEDTLS_GCM_ALT
|
||||||
|
#define MBEDTLS_CCM_ALT
|
||||||
|
|
||||||
#define MBEDTLS_ECP_INTERNAL_ALT
|
#define MBEDTLS_ECP_INTERNAL_ALT
|
||||||
/* Support for Weierstrass curves with Jacobi representation */
|
/* Support for Weierstrass curves with Jacobi representation */
|
||||||
|
|
Loading…
Reference in New Issue