aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorareviu <areviu.info@gmail.com>2017-11-11 20:07:22 +0000
committerareviu <areviu.info@gmail.com>2017-11-11 20:07:22 +0000
commitb487618ca56c2badd6b529a74d9e48969dec48ac (patch)
treec08e9844d907e981527ed3b92ff5ed6c707dc4de /os/hal
parent7c499f04330b0a471dd9775c040c0fab5ed23230 (diff)
downloadChibiOS-b487618ca56c2badd6b529a74d9e48969dec48ac.tar.gz
ChibiOS-b487618ca56c2badd6b529a74d9e48969dec48ac.tar.bz2
ChibiOS-b487618ca56c2badd6b529a74d9e48969dec48ac.zip
added crypto aes and des polling mode
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10983 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk9
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c235
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.h29
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c193
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.h54
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c250
-rw-r--r--os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.h61
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c1089
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h299
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/platform.mk4
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h60
11 files changed, 2282 insertions, 1 deletions
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk b/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk
new file mode 100644
index 000000000..120be44b7
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/driver.mk
@@ -0,0 +1,9 @@
+PLATFORMSRC +=$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c \
+ $(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c \
+ $(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
+
+
+
+PLATFORMINC +=$(CHIBIOS)/os/hal/ports/SAMA/LLD/CRYPTOv1
+
+
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c
new file mode 100644
index 000000000..563269d42
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.c
@@ -0,0 +1,235 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#include "hal.h"
+#include "sama_crypto_lld.h"
+
+
+
+
+
+void sama_aes_lld_write_key(const uint32_t * key, const uint32_t * vectors,
+ uint32_t len) {
+
+ AES->AES_KEYWR[0] = key[0];
+ AES->AES_KEYWR[1] = key[1];
+ AES->AES_KEYWR[2] = key[2];
+ AES->AES_KEYWR[3] = key[3];
+
+ if (len >= 24) {
+ AES->AES_KEYWR[4] = key[4];
+ AES->AES_KEYWR[5] = key[5];
+ }
+
+ else {
+ AES->AES_KEYWR[4] = 0;
+ AES->AES_KEYWR[5] = 0;
+ AES->AES_KEYWR[6] = 0;
+ AES->AES_KEYWR[7] = 0;
+ }
+
+ if (len == 32) {
+ AES->AES_KEYWR[6] = key[6];
+ AES->AES_KEYWR[7] = key[7];
+ }
+
+ if (vectors != NULL) {
+ AES->AES_IVR[0] = vectors[0];
+ AES->AES_IVR[1] = vectors[1];
+ AES->AES_IVR[2] = vectors[2];
+ AES->AES_IVR[3] = vectors[3];
+ }
+
+ else {
+ AES->AES_IVR[0] = 0;
+ AES->AES_IVR[1] = 0;
+ AES->AES_IVR[2] = 0;
+ AES->AES_IVR[3] = 0;
+ }
+
+}
+
+cryerror_t sama_aes_lld_set_key_size(size_t size) {
+
+ uint32_t key_size = AES_MR_KEYSIZE_AES128;
+
+ if (size == 16)
+ key_size = AES_MR_KEYSIZE_AES128;
+ else if (size == 24)
+ key_size = AES_MR_KEYSIZE_AES192;
+ else if (size == 32)
+ key_size = AES_MR_KEYSIZE_AES256;
+ else
+ return CRY_ERR_INV_KEY_SIZE;
+ //set key size
+ AES->AES_MR |= (( AES_MR_KEYSIZE_Msk & (key_size)) | AES_MR_CKEY_PASSWD);
+
+ return CRY_NOERROR;
+}
+
+void sama_aes_lld_set_input(uint32_t* data) {
+ uint8_t i;
+ uint8_t size = 4;
+
+ if ((AES->AES_MR & AES_MR_OPMOD_Msk) == AES_MR_OPMOD_CFB) {
+ if ((AES->AES_MR & AES_MR_CFBS_Msk) ==
+ AES_MR_CFBS_SIZE_128BIT)
+ size = 4;
+ else if ((AES->AES_MR & AES_MR_CFBS_Msk) ==
+ AES_MR_CFBS_SIZE_64BIT)
+ size = 2;
+ else
+ size = 1;
+ }
+
+ for (i = 0; i < size; i++) {
+ AES->AES_IDATAR[i] = data[i];
+ }
+
+}
+
+void sama_aes_lld_get_output(uint32_t* data) {
+ uint8_t i;
+
+ for (i = 0; i < 4; i++) {
+ data[i] = (AES->AES_ODATAR[i]);
+ }
+}
+
+cryerror_t sama_aes_lld_process_polling(CRYDriver *cryp, aesparams *params,
+ const uint8_t *in, uint8_t *out, size_t indata_len) {
+ uint32_t i;
+ cryerror_t ret;
+
+//AES soft reset
+ AES->AES_CR = AES_CR_SWRST;
+
+//AES set op mode
+ AES->AES_MR |= ((AES_MR_OPMOD_Msk & (params->mode)) | AES_MR_CKEY_PASSWD);
+
+//AES set key size
+ ret = sama_aes_lld_set_key_size(cryp->key0_size);
+
+ if (ret == CRY_NOERROR) {
+
+ AES->AES_MR |= (AES_MR_CFBS(cryp->config->cfbs) | AES_MR_CKEY_PASSWD);
+
+ sama_aes_lld_write_key(key0_buffer,( const uint32_t *) params->iv, cryp->key0_size);
+
+ if (params->encrypt)
+ AES->AES_MR |= AES_MR_CIPHER;
+ else
+ AES->AES_MR &= ~AES_MR_CIPHER;
+
+ AES->AES_MR |= (((AES_MR_SMOD_Msk & (AES_MR_SMOD_MANUAL_START)))
+ | AES_MR_CKEY_PASSWD);
+
+//Enable aes interrupt
+ AES->AES_IER = AES_IER_DATRDY;
+
+ for (i = 0; i < indata_len; i += params->block_size) {
+
+ sama_aes_lld_set_input((uint32_t *) ((in) + i));
+
+ AES->AES_CR = AES_CR_START;
+
+ while ((AES->AES_ISR & AES_ISR_DATRDY) != AES_ISR_DATRDY)
+ ;
+
+ sama_aes_lld_get_output((uint32_t *) ((out) + i));
+ }
+
+ }
+
+ return CRY_NOERROR;
+
+}
+
+cryerror_t sama_aes_lld_process_dma(CRYDriver *cryp, aesparams *params,
+ const uint8_t *in, uint8_t *out, size_t indata_len) {
+
+ osalDbgAssert(cryp->thread == NULL, "already waiting");
+
+ //set chunk size
+ cryp->dmachunksize = DMA_CHUNK_SIZE_4;
+
+ if ((cryp->config->cfbs != AES_CFBS_128))
+ cryp->dmachunksize = DMA_CHUNK_SIZE_1;
+
+ //set dma with
+ cryp->dmawith = DMA_DATA_WIDTH_WORD;
+
+ if (cryp->config->cfbs == AES_CFBS_16)
+ cryp->dmawith = DMA_DATA_WIDTH_HALF_WORD;
+ if (cryp->config->cfbs == AES_CFBS_8)
+ cryp->dmawith = DMA_DATA_WIDTH_BYTE;
+
+ cryp->rxdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM | XDMAC_CC_CSIZE(cryp->dmachunksize) |
+ XDMAC_CC_DWIDTH(cryp->dmawith) |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_AES_RX);
+
+ cryp->txdmamode = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_PROT_SEC |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER | XDMAC_CC_CSIZE(cryp->dmachunksize) |
+ XDMAC_CC_DWIDTH(cryp->dmawith) |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_AES_TX);
+
+ /* Writing channel */
+ dmaChannelSetSource(cryp->dmatx, in);
+ dmaChannelSetDestination(cryp->dmatx, AES->AES_IDATAR);
+ dmaChannelSetTransactionSize(cryp->dmatx, ( indata_len / DMA_DATA_WIDTH_TO_BYTE(cryp->dmawith)));
+
+
+ /* Reading channel */
+ dmaChannelSetSource(cryp->dmarx, AES->AES_ODATAR);
+ dmaChannelSetDestination(cryp->dmarx, out);
+ dmaChannelSetTransactionSize(cryp->dmarx, ( indata_len / DMA_DATA_WIDTH_TO_BYTE(cryp->dmawith)));
+
+ if (params->encrypt)
+ AES->AES_MR |= AES_MR_CIPHER;
+ else
+ AES->AES_MR &= ~AES_MR_CIPHER;
+
+ AES->AES_MR |= (((AES_MR_SMOD_Msk & (AES_MR_SMOD_IDATAR0_START)))
+ | AES_MR_CKEY_PASSWD);
+
+ //Enable aes interrupt
+ AES->AES_IER = AES_IER_DATRDY;
+
+ osalSysLock();
+
+ dmaChannelEnable(cryp->dmarx);
+ dmaChannelEnable(cryp->dmatx);
+
+ osalThreadSuspendS(&cryp->thread);
+
+ osalSysUnlock();
+
+ return CRY_NOERROR;
+
+}
+
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.h b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.h
new file mode 100644
index 000000000..3df2d28e1
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_aes_lld.h
@@ -0,0 +1,29 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#ifndef CRYPTOLIB_LLD_SAMA_AES_H_
+#define CRYPTOLIB_LLD_SAMA_AES_H_
+
+extern void sama_aes_lld_write_key(const uint32_t * key, const uint32_t * vectors,uint32_t len);
+extern cryerror_t sama_aes_lld_set_key_size(size_t size);
+extern cryerror_t sama_aes_lld_process_polling(CRYDriver *cryp,aesparams *params,const uint8_t *in,uint8_t *out,size_t indata_len);
+extern cryerror_t sama_aes_lld_process_dma(CRYDriver *cryp,aesparams *params,const uint8_t *in,uint8_t *out,size_t indata_len);
+
+extern void sama_aes_lld_set_input(uint32_t* data);
+extern void sama_aes_lld_get_output(uint32_t* data);
+
+
+
+#endif /* CRYPTOLIB_LLD_SAMA_AES_H_ */
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c
new file mode 100644
index 000000000..8375dab67
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.c
@@ -0,0 +1,193 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#include "hal.h"
+#include "sama_crypto_lld.h"
+
+#define KEY0_BUFFER_SIZE_W HAL_CRY_MAX_KEY_SIZE/4
+
+uint32_t key0_buffer[KEY0_BUFFER_SIZE_W];
+
+#if defined(SAMA_DMA_REQUIRED)
+static void crypto_lld_serve_read_interrupt(CRYDriver *cryp, uint32_t flags);
+static void crypto_lld_serve_write_interrupt(CRYDriver *cryp, uint32_t flags);
+#endif
+
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] cryp pointer to the @p CRYDRiver object
+ *
+ * @notapi
+ */
+#define _cry_wakeup_isr(cryp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&cryp->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+
+
+/**
+ * @brief Common ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _cry_isr_code(cryp) { \
+ _cry_wakeup_isr(cryp); \
+}
+
+void samaCryptoDriverInit(CRYDriver *cryp) {
+ cryp->enabledPer = 0;
+ cryp->thread = NULL;
+}
+
+void samaCryptoDriverStart(CRYDriver *cryp) {
+
+
+ samaClearKeyBuffer();
+
+ if (cryp->config->transfer_mode == TRANSFER_DMA)
+ {
+#if defined(SAMA_DMA_REQUIRED)
+ cryp->dmarx = dmaChannelAllocate(SAMA_CRY_CRYD1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t) crypto_lld_serve_read_interrupt, (void *) cryp);
+ osalDbgAssert(cryp->dmarx != NULL, "no channel allocated");
+
+ cryp->dmatx = dmaChannelAllocate(SAMA_CRY_CRYD1_DMA_IRQ_PRIORITY,
+ (sama_dmaisr_t) crypto_lld_serve_write_interrupt, (void *) cryp);
+ osalDbgAssert(cryp->dmatx != NULL, "no channel allocated");
+#endif
+ }
+
+}
+
+void samaCryptoDriverStop(CRYDriver *cryp) {
+ samaCryptoDriverDisable(cryp);
+}
+
+
+/**
+ * write key into internal buffer
+ */
+cryerror_t samaCryptoDriverWriteTransientKey(const uint8_t *keyp,size_t size)
+{
+ uint8_t *p = (uint8_t *)key0_buffer;
+
+ if (size <= HAL_CRY_MAX_KEY_SIZE)
+ {
+ samaClearKeyBuffer();
+
+ for (size_t i=0;i<size;i++)
+ {
+ p[i] = keyp[i];
+ }
+ }
+ else
+ {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+
+ return CRY_NOERROR;
+}
+
+
+void samaClearKeyBuffer(void)
+{
+ for (size_t i=0;i<KEY0_BUFFER_SIZE_W;i++)
+ {
+ key0_buffer[i] = 0;
+ }
+}
+
+void samaCryptoDriverDisable(CRYDriver *cryp)
+{
+ if ((cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer &= ~AES_PER;
+ pmcDisableAES();
+ }
+ if ((cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer &= ~TDES_PER;
+ pmcDisableDES();
+ }
+ if ((cryp->enabledPer & SHA_PER)) {
+ cryp->enabledPer &= ~SHA_PER;
+ pmcDisableSHA();
+ }
+ if ((cryp->enabledPer & TRNG_PER)) {
+ cryp->enabledPer &= ~TRNG_PER;
+ pmcDisableTRNG();
+ }
+}
+
+#if defined(SAMA_DMA_REQUIRED)
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void crypto_lld_serve_read_interrupt(CRYDriver *cryp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ #if defined(SAMA_CRY_DMA_ERROR_HOOK)
+ if ((flags & (XDMAC_CIS_RBEIS | XDMAC_CIS_ROIS)) != 0) {
+ SAMA_CRY_DMA_ERROR_HOOK(cryp);
+ }
+#else
+ (void)flags;
+#endif
+
+ /* Stop everything.*/
+
+ dmaChannelDisable(cryp->dmatx);
+ dmaChannelDisable(cryp->dmarx);
+ /* Portable CRY ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _cry_isr_code(cryp);
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void crypto_lld_serve_write_interrupt(CRYDriver *cryp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+
+#if defined(SAMA_CRY_DMA_ERROR_HOOK)
+ (void)cryp;
+ if ((flags & (XDMAC_CIS_WBEIS | XDMAC_CIS_ROIS)) != 0) {
+ SAMA_CRY_DMA_ERROR_HOOK(cryp);
+ }
+#else
+ (void)cryp;
+ (void)flags;
+#endif
+
+
+}
+
+#endif
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.h b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.h
new file mode 100644
index 000000000..734fad25b
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_crypto_lld.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#ifndef SAMA_CRYPTO_LLD_H_
+#define SAMA_CRYPTO_LLD_H_
+
+extern void samaCryptoDriverInit(CRYDriver *cryp);
+extern void samaCryptoDriverStart(CRYDriver *cryp);
+extern void samaCryptoDriverStop(CRYDriver *cryp);
+extern cryerror_t samaCryptoDriverWriteTransientKey(const uint8_t *keyp,size_t size);
+extern void samaCryptoDriverDisable(CRYDriver *cryp);
+extern void samaClearKeyBuffer(void);
+
+#define AES_PER 0x01
+#define TRNG_PER 0x02
+#define SHA_PER 0x04
+#define TDES_PER 0x08
+
+#define DMA_DATA_WIDTH_BYTE 0
+#define DMA_DATA_WIDTH_HALF_WORD 1
+#define DMA_DATA_WIDTH_WORD 2
+#define DMA_DATA_WIDTH_DWORD 3
+
+#define DMA_CHUNK_SIZE_1 0
+#define DMA_CHUNK_SIZE_2 1
+#define DMA_CHUNK_SIZE_4 2
+#define DMA_CHUNK_SIZE_8 3
+#define DMA_CHUNK_SIZE_16 4
+
+#define DMA_DATA_WIDTH_TO_BYTE(w) (1 << w)
+
+
+
+extern uint32_t key0_buffer[HAL_CRY_MAX_KEY_SIZE/4];
+
+
+
+#include "sama_aes_lld.h"
+#include "sama_tdes_lld.h"
+
+
+#endif //SAMA_CRYPTO_LLD_H_
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
new file mode 100644
index 000000000..2e804cf8e
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.c
@@ -0,0 +1,250 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#include "hal.h"
+#include "sama_crypto_lld.h"
+#include "sama_tdes_lld.h"
+
+enum tdesd_key_mode_t {
+ TDES_KEY_THREE = 0, TDES_KEY_TWO
+};
+
+void tdes_set_input(uint32_t* data0, uint32_t* data1) {
+ TDES->TDES_IDATAR[0] = *data0;
+ if (data1)
+ TDES->TDES_IDATAR[1] = *data1;
+}
+
+void tdes_get_output(uint32_t *data0, uint32_t *data1) {
+ *data0 = TDES->TDES_ODATAR[0];
+ if (data1)
+ *data1 = TDES->TDES_ODATAR[1];
+}
+
+cryerror_t sama_tdes_lld_polling(CRYDriver *cryp, tdes_config_t *params,
+ bool encrypt, const uint8_t *data, size_t data_len, uint8_t * out,
+ const uint8_t *iv) {
+
+ uint32_t mode = 0;
+ uint32_t i;
+ uint8_t size = 8;
+ uint32_t *vectors = (uint32_t *) iv;
+ //soft reset
+ TDES->TDES_CR = TDES_CR_SWRST;
+ //configure
+ if (encrypt)
+ mode |= TDES_MR_CIPHER_ENCRYPT;
+ else
+ mode |= TDES_MR_CIPHER_DECRYPT;
+
+ if (cryp->key0_size == 16)
+ mode |= (TDES_KEY_TWO << 4);
+ else
+ mode |= (TDES_KEY_THREE << 4);
+
+ mode |= TDES_MR_TDESMOD(params->algo);
+
+ mode |= TDES_MR_SMOD_MANUAL_START;
+
+ mode |= TDES_MR_OPMOD(params->mode);
+
+ if (cryp->config != NULL) {
+ mode |= TDES_MR_CFBS(cryp->config->cfbs);
+
+ if (params->mode == TDES_MODE_CFB) {
+ if (cryp->config->cfbs == TDES_CFBS_32)
+ size = 4;
+ else if (cryp->config->cfbs == TDES_CFBS_16)
+ size = 2;
+ else if (cryp->config->cfbs == TDES_CFBS_8)
+ size = 1;
+ }
+
+ }
+
+ TDES->TDES_MR = mode;
+
+ //write keys
+ /* Write the 64-bit key(s) in the different Key Word Registers,
+ * depending on whether one, two or three keys are required. */
+
+ TDES->TDES_KEY1WR[0] = key0_buffer[0];
+ TDES->TDES_KEY1WR[1] = key0_buffer[1];
+
+ if (cryp->key0_size > 8) {
+ TDES->TDES_KEY2WR[0] = key0_buffer[2];
+ TDES->TDES_KEY2WR[1] = key0_buffer[3];
+ } else {
+ TDES->TDES_KEY2WR[0] = 0x0;
+ TDES->TDES_KEY2WR[1] = 0x0;
+ }
+ if (cryp->key0_size > 16) {
+ TDES->TDES_KEY3WR[0] = key0_buffer[4];
+ TDES->TDES_KEY3WR[1] = key0_buffer[5];
+ } else {
+ TDES->TDES_KEY3WR[0] = 0x0;
+ TDES->TDES_KEY3WR[1] = 0x0;
+ }
+ /* The Initialization Vector Registers apply to all modes except ECB. */
+ if (params->mode != TDES_MODE_ECB && vectors != NULL) {
+ TDES->TDES_IVR[0] = vectors[0];
+ TDES->TDES_IVR[1] = vectors[1];
+ }
+ if (params->algo == TDES_ALGO_XTEA) {
+ TDES->TDES_XTEA_RNDR = TDES_XTEA_RNDR_XTEA_RNDS(32);
+ }
+
+ /* Iterate per 64-bit data block */
+ for (i = 0; i < data_len; i += size) {
+ if (size == 8)
+ tdes_set_input((uint32_t *) ((data) + i),
+ (uint32_t *) ((data) + i + 4));
+ else
+ tdes_set_input((uint32_t *) ((data) + i), NULL);
+
+ //Start TDES
+ TDES->TDES_CR = TDES_CR_START;
+
+ //check status
+ while ((TDES->TDES_ISR & TDES_ISR_DATRDY) != TDES_ISR_DATRDY)
+ ;
+
+ if (size == 8)
+ tdes_get_output((uint32_t *) ((out) + i),
+ (uint32_t *) ((out) + i + 4));
+ else
+ tdes_get_output((uint32_t *) ((out) + i), NULL);
+ }
+
+ return CRY_NOERROR;
+}
+
+cryerror_t sama_tdes_lld_dma(CRYDriver *cryp, tdes_config_t *params,
+ bool encrypt, const uint8_t *data, size_t data_len, uint8_t * out,
+ const uint8_t *iv) {
+
+
+ uint32_t mode = 0;
+ uint32_t *vectors = (uint32_t *) iv;
+
+ cryp->dmachunksize = DMA_CHUNK_SIZE_1;
+ cryp->dmawith = 4;
+ if ((params->mode == TDES_MODE_CFB)) {
+ if (cryp->config->cfbs == TDES_CFBS_16)
+ cryp->dmawith = DMA_DATA_WIDTH_HALF_WORD;
+ if (cryp->config->cfbs == TDES_CFBS_8)
+ cryp->dmawith = DMA_DATA_WIDTH_BYTE;
+ }
+ cryp->rxdmamode =
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE(cryp->dmachunksize) |
+ XDMAC_CC_DWIDTH(cryp->dmawith) |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(PERID_TDES_RX);
+
+ cryp->txdmamode =
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE(cryp->dmachunksize) |
+ XDMAC_CC_DWIDTH(cryp->dmawith) |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(PERID_TDES_TX);
+
+ dmaChannelSetMode(cryp->dmarx, cryp->rxdmamode);
+ dmaChannelSetMode(cryp->dmatx, cryp->txdmamode);
+
+ /* Writing channel */
+ dmaChannelSetSource(cryp->dmatx, data);
+ dmaChannelSetDestination(cryp->dmatx, TDES->TDES_IDATAR);
+ dmaChannelSetTransactionSize(cryp->dmatx, ( data_len / DMA_DATA_WIDTH_TO_BYTE(cryp->dmawith)) );
+
+ // ( data_len / DMA_DATA_WIDTH_TO_BYTE(cryp->dmawith))
+
+ /* Reading channel */
+ dmaChannelSetSource(cryp->dmarx, TDES->TDES_ODATAR);
+ dmaChannelSetDestination(cryp->dmarx, out);
+ dmaChannelSetTransactionSize(cryp->dmarx, ( data_len / DMA_DATA_WIDTH_TO_BYTE(cryp->dmawith)) );
+
+
+ //soft reset
+ TDES->TDES_CR = TDES_CR_SWRST;
+ //configure
+ if (encrypt)
+ mode |= TDES_MR_CIPHER_ENCRYPT;
+ else
+ mode |= TDES_MR_CIPHER_DECRYPT;
+
+ if (cryp->key0_size == 16)
+ mode |= (TDES_KEY_TWO << 4);
+ else
+ mode |= (TDES_KEY_THREE << 4);
+
+ mode |= TDES_MR_TDESMOD(params->algo);
+
+ mode |= TDES_MR_SMOD(2);
+
+ mode |= TDES_MR_OPMOD(params->mode);
+
+ TDES->TDES_MR = mode;
+
+ //write keys
+ /* Write the 64-bit key(s) in the different Key Word Registers,
+ * depending on whether one, two or three keys are required. */
+
+ TDES->TDES_KEY1WR[0] = key0_buffer[0];
+ TDES->TDES_KEY1WR[1] = key0_buffer[1];
+
+ if (cryp->key0_size > 8) {
+ TDES->TDES_KEY2WR[0] = key0_buffer[2];
+ TDES->TDES_KEY2WR[1] = key0_buffer[3];
+ } else {
+ TDES->TDES_KEY2WR[0] = 0x0;
+ TDES->TDES_KEY2WR[1] = 0x0;
+ }
+ if (cryp->key0_size > 16) {
+ TDES->TDES_KEY3WR[0] = key0_buffer[4];
+ TDES->TDES_KEY3WR[1] = key0_buffer[5];
+ } else {
+ TDES->TDES_KEY3WR[0] = 0x0;
+ TDES->TDES_KEY3WR[1] = 0x0;
+ }
+ /* The Initialization Vector Registers apply to all modes except ECB. */
+ if (params->mode != TDES_MODE_ECB && vectors != NULL) {
+ TDES->TDES_IVR[0] = vectors[0];
+ TDES->TDES_IVR[1] = vectors[1];
+ }
+ if (params->algo == TDES_ALGO_XTEA) {
+ TDES->TDES_XTEA_RNDR = TDES_XTEA_RNDR_XTEA_RNDS(32);
+ }
+
+
+ osalSysLock();
+
+ dmaChannelEnable(cryp->dmarx);
+ dmaChannelEnable(cryp->dmatx);
+
+
+ osalThreadSuspendS(&cryp->thread);
+ osalSysUnlock();
+
+
+ return CRY_NOERROR;
+}
+
diff --git a/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.h b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.h
new file mode 100644
index 000000000..bc48f02b1
--- /dev/null
+++ b/os/hal/ports/SAMA/LLD/CRYPTOv1/sama_tdes_lld.h
@@ -0,0 +1,61 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+#ifndef CRYPTOLIB_LLD_TDES_H_
+#define CRYPTOLIB_LLD_TDES_H_
+
+
+
+typedef enum {
+ TDES_MODE_ECB = 0,
+ TDES_MODE_CBC,
+ TDES_MODE_OFB,
+ TDES_MODE_CFB
+}tdes_mode_t;
+
+
+
+typedef enum {
+ TDES_CFBS_64 = 0,
+ TDES_CFBS_32,
+ TDES_CFBS_16,
+ TDES_CFBS_8
+}tdes_cipher_size_t;
+
+typedef struct {
+ tdes_algo_t algo;
+ tdes_mode_t mode;
+}tdes_config_t;
+
+
+extern void sama_tdes_lld_init(CRYDriver *cryp);
+
+extern cryerror_t sama_tdes_lld_polling(CRYDriver *cryp,
+ tdes_config_t *params,
+ bool encrypt,
+ const uint8_t *data,
+ size_t data_len,
+ uint8_t *out,
+ const uint8_t *iv);
+extern cryerror_t sama_tdes_lld_dma(CRYDriver *cryp,
+ tdes_config_t *params,
+ bool encrypt,
+ const uint8_t *data,
+ size_t data_len,
+ uint8_t *out,
+ const uint8_t *iv);
+
+
+#endif /* CRYPTOLIB_LLD_TDES_H_ */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
new file mode 100644
index 000000000..7665f9204
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
@@ -0,0 +1,1089 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+ */
+
+/**
+ * @file hal_crypto_lld.c
+ * @brief PLATFORM cryptographic subsystem low level driver source.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+#include <string.h>
+#include "hal.h"
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+#include "sama_crypto_lld.h"
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+
+/** @brief CRY1 driver identifier.*/
+#if PLATFORM_CRY_USE_CRY1 || defined(__DOXYGEN__)
+CRYDriver CRYD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level crypto driver initialization.
+ *
+ * @notapi
+ */
+void cry_lld_init(void) {
+#if PLATFORM_CRY_USE_CRY1 == TRUE
+ cryObjectInit(&CRYD1);
+ samaCryptoDriverInit(&CRYD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_start(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_STOP) {
+#if PLATFORM_CRY_USE_CRY1
+ if (&CRYD1 == cryp) {
+ samaCryptoDriverStart(&CRYD1);
+ }
+#endif /* PLATFORM_CRY_USE_CRY1 */
+ }
+}
+
+/**
+ * @brief Deactivates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_stop(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_READY) {
+#if PLATFORM_CRY_USE_CRY1
+ if (&CRYD1 == cryp) {
+ samaCryptoDriverStop(&CRYD1);
+ }
+#endif /* PLATFORM_CRY_USE_CRY1 */
+
+ }
+}
+
+/**
+ * @brief Initializes the transient key for a specific algorithm.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the specified algorithm is unknown or
+ * unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_loadkey(CRYDriver *cryp, cryalgorithm_t algorithm,
+ size_t size, const uint8_t *keyp) {
+
+ (void)(cryp);
+ (void)(algorithm);
+ return samaCryptoDriverWriteTransientKey(keyp, size);
+
+}
+
+/**
+ * @brief Encryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp, crykey_t key_id,
+ const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES();
+ }
+
+ params.encrypt = 1;
+ params.block_size = 16;
+ params.mode = 0;
+ params.iv = NULL;
+
+
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, 16);
+
+
+ return ret;
+}
+
+/**
+ * @brief Decryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] in buffer containing the input cyphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp, crykey_t key_id,
+ const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES();
+ }
+
+ params.encrypt = 0;
+ params.block_size = 16;
+ params.mode = 0;
+ params.iv = NULL;
+
+
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, 16);
+
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using AES-ECB.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES();
+ }
+
+ params.encrypt = 1;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_ECB;
+ params.iv = NULL;
+
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using AES-ECB.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES();
+ }
+
+ params.encrypt = 0;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_ECB;
+
+
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using AES-CBC.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+ params.encrypt = 1;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_CBC;
+ params.iv = iv;
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using AES-CBC.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+
+ params.encrypt = 0;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_CBC;
+ params.iv = iv;
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using AES-CFB.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+ params.encrypt = 1;
+ params.block_size = 16;
+ switch (cryp->config->cfbs) {
+ case AES_CFBS_128:
+ params.block_size = 16;
+ break;
+ case AES_CFBS_64:
+ params.block_size = 8;
+ break;
+ case AES_CFBS_32:
+ params.block_size = 4;
+ break;
+ case AES_CFBS_16:
+ params.block_size = 2;
+ break;
+ case AES_CFBS_8:
+ params.block_size = 1;
+ break;
+ }
+ params.mode = AES_MR_OPMOD_CFB;
+ params.iv = iv;
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using AES-CFB.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of the selected key size
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+
+ params.encrypt = 0;
+ params.block_size = 16;
+ switch (cryp->config->cfbs) {
+ case AES_CFBS_128:
+ params.block_size = 16;
+ break;
+ case AES_CFBS_64:
+ params.block_size = 8;
+ break;
+ case AES_CFBS_32:
+ params.block_size = 4;
+ break;
+ case AES_CFBS_16:
+ params.block_size = 2;
+ break;
+ case AES_CFBS_8:
+ params.block_size = 1;
+ break;
+ }
+ params.mode = AES_MR_OPMOD_CFB;
+ params.iv = iv;
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using AES-CTR.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+
+ params.encrypt = 1;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_CTR;
+ params.iv = iv;
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+
+
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using AES-CTR.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input cyphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ aesparams params;
+ if (key_id != 0)
+ return CRY_ERR_INV_KEY_ID;
+
+ if (!(cryp->enabledPer & AES_PER)) {
+ cryp->enabledPer |= AES_PER;
+ pmcEnableAES()
+ ;
+ }
+
+ params.encrypt = 0;
+ params.block_size = 16;
+ params.mode = AES_MR_OPMOD_CTR;
+ params.iv = iv;
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_aes_lld_process_polling(cryp, &params, in, out, size);
+ else
+ ret = sama_aes_lld_process_dma(cryp, &params, in, out, size);
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using AES-GCM.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the text buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @param[in] aadsize size of the authentication data, this number must be a
+ * multiple of 16
+ * @param[in] aad buffer containing the authentication data
+ * @param[in] authtag 128 bits buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv,
+ size_t aadsize,
+ const uint8_t *aad,
+ uint8_t *authtag) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+ (void)aadsize;
+ (void)aad;
+ (void)authtag;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-GCM.
+ * @note The function operates on data buffers whose lenght is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the text buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer for the output cyphertext
+ * @param[out] out buffer containing the input plaintext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @param[in] aadsize size of the authentication data, this number must be a
+ * multiple of 16
+ * @param[in] aad buffer containing the authentication data
+ * @param[in] authtag 128 bits buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv,
+ size_t aadsize,
+ const uint8_t *aad,
+ uint8_t *authtag) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+ (void)aadsize;
+ (void)aad;
+ (void)authtag;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+
+/**
+ * @brief Encryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp, crykey_t key_id,
+ const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+
+ if ( ( cryp->config->tdes_algo == TDES_ALGO_SINGLE && cryp->key0_size != 8 ) ||
+ ( cryp->config->tdes_algo == TDES_ALGO_TRIPLE && cryp->key0_size != 24 ) )
+ return CRY_ERR_INV_KEY_SIZE;
+
+ tdes_config_t params = { cryp->config->tdes_algo,
+ 0
+ };
+
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES();
+ }
+
+ ret = sama_tdes_lld_polling(cryp,&params, true, in,
+ 8, out,NULL);
+
+ return ret;
+}
+
+/**
+ * @brief Decryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] in buffer containing the input cyphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp, crykey_t key_id,
+ const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ tdes_config_t params = { cryp->config->tdes_algo,
+ 0
+ };
+ if(key_id != 0 )
+ return CRY_ERR_INV_KEY_ID;
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES();
+ }
+
+ ret = sama_tdes_lld_polling(cryp,&params, false, in,
+ 8, out,NULL);
+
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ tdes_config_t params = { cryp->config->tdes_algo, TDES_MODE_ECB };
+ if (key_id != 0)
+ return CRY_ERR_INV_KEY_ID;
+
+ if (cryp->key0_size != 16 && cryp->key0_size != 24) {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES()
+ ;
+ }
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_tdes_lld_polling(cryp, &params, true, in, size, out, NULL);
+ else
+ ret = sama_tdes_lld_dma(cryp, &params, true, in, size, out, NULL);
+
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input cyphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out) {
+
+ cryerror_t ret = CRY_NOERROR;
+ tdes_config_t params = { cryp->config->tdes_algo, TDES_MODE_ECB };
+ if (key_id != 0)
+ return CRY_ERR_INV_KEY_ID;
+
+ if (cryp->key0_size != 16 && cryp->key0_size != 24) {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES()
+ ;
+ }
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_tdes_lld_polling(cryp, &params, false, in, size, out, NULL);
+ else
+ ret = sama_tdes_lld_dma(cryp, &params, false, in, size, out, NULL);
+
+ return ret;
+}
+
+/**
+ * @brief Encryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output cyphertext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+
+ cryerror_t ret = CRY_NOERROR;
+ tdes_config_t params = { cryp->config->tdes_algo, TDES_MODE_CBC };
+ if (key_id != 0)
+ return CRY_ERR_INV_KEY_ID;
+
+ if (cryp->key0_size != 16 && cryp->key0_size != 24) {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES()
+ ;
+ }
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_tdes_lld_polling(cryp, &params, true, in, size, out, iv);
+ else
+ ret = sama_tdes_lld_dma(cryp, &params, true, in, size, out, iv);
+ return ret;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is the
+ * transient key, other values are keys stored in an
+ * unspecified way
+ * @param[in] size size of the plaintext buffer, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input cyphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp, crykey_t key_id,
+ size_t size, const uint8_t *in, uint8_t *out, const uint8_t *iv) {
+
+ cryerror_t ret = CRY_NOERROR;
+ tdes_config_t params = { cryp->config->tdes_algo, TDES_MODE_CBC };
+ if (key_id != 0)
+ return CRY_ERR_INV_KEY_ID;
+
+ if (cryp->key0_size != 16 && cryp->key0_size != 24) {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+
+ if (!(cryp->enabledPer & TDES_PER)) {
+ cryp->enabledPer |= TDES_PER;
+ pmcEnableDES()
+ ;
+ }
+
+ if (cryp->config->transfer_mode == TRANSFER_POLLING)
+ ret = sama_tdes_lld_polling(cryp, &params, false, in, size, out, iv);
+ else
+ ret = sama_tdes_lld_dma(cryp, &params, false, in, size, out, iv);
+
+ return ret;
+}
+
+
+
+#endif /* HAL_USE_CRY == TRUE */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h
new file mode 100644
index 000000000..135ac600c
--- /dev/null
+++ b/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.h
@@ -0,0 +1,299 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ 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.
+*/
+
+/**
+ * @file hal_cry_lld.h
+ * @brief PLATFORM cryptographic subsystem low level driver header.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#ifndef HAL_CRYPTO_LLD_H
+#define HAL_CRYPTO_LLD_H
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Driver capability switches
+ * @{
+ */
+#define CRY_LLD_SUPPORTS_AES TRUE
+#define CRY_LLD_SUPPORTS_AES_ECB TRUE
+#define CRY_LLD_SUPPORTS_AES_CBC TRUE
+#define CRY_LLD_SUPPORTS_AES_CFB TRUE
+#define CRY_LLD_SUPPORTS_AES_CTR TRUE
+#define CRY_LLD_SUPPORTS_AES_GCM TRUE
+#define CRY_LLD_SUPPORTS_DES TRUE
+#define CRY_LLD_SUPPORTS_DES_ECB TRUE
+#define CRY_LLD_SUPPORTS_DES_CBC TRUE
+/** @{ */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief CRY1 driver enable switch.
+ * @details If set to @p TRUE the support for CRY1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_CRY_USE_CRY1) || defined(__DOXYGEN__)
+#define PLATFORM_CRY_USE_CRY1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+typedef struct
+{
+ uint32_t encrypt;
+ uint32_t block_size;
+ uint32_t mode;
+ const uint8_t *iv;
+}aesparams;
+
+typedef enum {
+ TRANSFER_DMA = 0,
+ TRANSFER_POLLING,
+}crytransfermode_t;
+
+typedef enum {
+ AES_CFBS_128 = 0,
+ AES_CFBS_64,
+ AES_CFBS_32,
+ AES_CFBS_16,
+ AES_CFBS_8
+}aesciphersize_t;
+
+
+/**
+ * @brief CRY key identifier type.
+ */
+typedef uint32_t crykey_t;
+
+/**
+ * @brief Type of a structure representing an CRY driver.
+ */
+typedef struct CRYDriver CRYDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+
+
+typedef enum {
+ TDES_ALGO_SINGLE = 0,
+ TDES_ALGO_TRIPLE,
+ TDES_ALGO_XTEA
+}tdes_algo_t;
+
+typedef struct {
+
+ crytransfermode_t transfer_mode;
+ uint32_t cfbs;
+ tdes_algo_t tdes_algo;
+
+} CRYConfig;
+
+#define CRY_DRIVER_EXT_FIELDS thread_reference_t thread; \
+ sama_dma_channel_t *dmarx; \
+ sama_dma_channel_t *dmatx; \
+ uint32_t rxdmamode; \
+ uint32_t txdmamode; \
+ uint8_t dmawith; \
+ uint8_t dmachunksize; \
+ uint8_t enabledPer;
+/**
+ * @brief Structure representing an CRY driver.
+ */
+struct CRYDriver {
+ /**
+ * @brief Driver state.
+ */
+ crystate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CRYConfig *config;
+ /**
+ * @brief Algorithm type of transient key.
+ */
+ cryalgorithm_t key0_type;
+ /**
+ * @brief Size of transient key.
+ */
+ size_t key0_size;
+#if (HAL_CRY_USE_FALLBACK == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Key buffer for the fall-back implementation.
+ */
+ uint8_t key0_buffer[HAL_CRY_MAX_KEY_SIZE];
+#endif
+#if defined(CRY_DRIVER_EXT_FIELDS)
+ CRY_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_CRY_USE_CRY1 == TRUE) && !defined(__DOXYGEN__)
+extern CRYDriver CRYD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void cry_lld_init(void);
+ void cry_lld_start(CRYDriver *cryp);
+ void cry_lld_stop(CRYDriver *cryp);
+ cryerror_t cry_lld_loadkey(CRYDriver *cryp,
+ cryalgorithm_t algorithm,
+ size_t size,
+ const uint8_t *keyp);
+ cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv,
+ size_t aadsize,
+ const uint8_t *aad,
+ uint8_t *authtag);
+ cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv,
+ size_t aadsize,
+ const uint8_t *aad,
+ uint8_t *authtag);
+ cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CRY == TRUE */
+
+#endif /* HAL_CRYPTO_LLD_H */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/platform.mk b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
index 59fda14fc..6f826f1cf 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/platform.mk
+++ b/os/hal/ports/SAMA/SAMA5D2x/platform.mk
@@ -5,7 +5,8 @@ PLATFORMSRC := $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_lld.c \
$(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/aic.c \
$(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_matrix.c \
$(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/sama_cache.c \
- $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_tc_lld.c
+ $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_tc_lld.c \
+ $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x/hal_crypto_lld.c
# Required include directories.
PLATFORMINC := $(CHIBIOS)/os/hal/ports/SAMA/SAMA5D2x
@@ -29,3 +30,4 @@ include $(CHIBIOS)/os/hal/ports/SAMA/LLD/PIOv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/SPIv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/RTCv1/driver.mk
include $(CHIBIOS)/os/hal/ports/SAMA/LLD/USARTv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/SAMA/LLD/Cryptov1/driver.mk
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h b/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
index 8c010a6d8..39354054e 100644
--- a/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
+++ b/os/hal/ports/SAMA/SAMA5D2x/sama_pmc.h
@@ -408,8 +408,68 @@
*/
#define pmcDisableTC1() pmcDisablePidHigh(ID_TC1_MSK)
+
+/**
+ * @brief Enables the AES peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableAES() pmcEnablePidLow(ID_AES_MSK)
+
+/**
+ * @brief Disables the AES peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableAES() pmcDisablePidLow(ID_AES_MSK)
+
+/**
+ * @brief Enables the TRNG peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableTRNG() pmcEnablePidHigh(ID_TRNG_MSK)
+/**
+ * @brief Disables the TRNG peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableTRNG() pmcDisablePidHigh(ID_TRNG_MSK)
+
+/**
+ * @brief Enables the DES peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableDES() pmcEnablePidLow(ID_TDES_MSK)
+/**
+ * @brief Disables the DES peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableDES() pmcDisablePidLow(ID_TDES_MSK)
+
+/**
+ * @brief Enables the SHA peripheral clock.
+ *
+ * @api
+ */
+#define pmcEnableSHA() pmcEnablePidLow(ID_SHA_MSK)
+/**
+ * @brief Disables the SHA peripheral clock.
+ *
+ * @api
+ */
+#define pmcDisableSHA() pmcDisablePidLow(ID_SHA_MSK)
+
+
/** @} */
+
+
+
+
+
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/