aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/SAMA/LLD/CRYPTOv1
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/ports/SAMA/LLD/CRYPTOv1
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/ports/SAMA/LLD/CRYPTOv1')
-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
7 files changed, 831 insertions, 0 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_ */