diff --git a/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.c b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.c new file mode 100644 index 0000000000..8d56325b0b --- /dev/null +++ b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.c @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * 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 "cmsis.h" +#include "mbed_assert.h" +#include "nu_modutil.h" +#include "nu_bitutil.h" + +static int crypto_inited = 0; + +void crypto_init(void) +{ + if (crypto_inited) { + return; + } + crypto_inited = 1; + + CLK_EnableModuleClock(CRPT_MODULE); +} + +/* Implementation that should never be optimized out by the compiler */ +void crypto_zeroize(void *v, size_t n) +{ + volatile unsigned char *p = (unsigned char*) v; + while (n--) { + *p++ = 0; + } +} diff --git a/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.h b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.h new file mode 100644 index 0000000000..0f67465166 --- /dev/null +++ b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/crypto.h @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * 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 MBED_CRYPTO_H +#define MBED_CRYPTO_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void crypto_init(void); +void crypto_zeroize(void *v, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.c b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.c new file mode 100644 index 0000000000..867e27b5f9 --- /dev/null +++ b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.c @@ -0,0 +1,410 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_DES_ALT) + +#include +#include "mbedtls/des.h" +#include "des_alt.h" +#include "crypto.h" +#include "nu_bitutil.h" +#include "toolchain.h" + +// Must be a multiple of 64-bit block size +#define MAXSIZE_DMABUF (8 * 5) +static uint8_t dmabuf_in[MAXSIZE_DMABUF] MBED_ALIGN(4); +static uint8_t dmabuf_out[MAXSIZE_DMABUF] MBED_ALIGN(4); + +static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length, + unsigned char iv[8], const unsigned char *input, unsigned char *output); + +void mbedtls_des_init(mbedtls_des_context *ctx) +{ + crypto_init(); + memset(ctx, 0, sizeof(mbedtls_des_context)); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if (ctx == NULL) { + return; + } + + crypto_zeroize(ctx, sizeof(mbedtls_des_context)); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + crypto_init(); + memset(ctx, 0, sizeof(mbedtls_des3_context)); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if (ctx == NULL) { + return; + } + + crypto_zeroize(ctx, sizeof (mbedtls_des3_context)); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]) +{ + int i; + + for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) { + key[i] = odd_parity_table[key[i] / 2]; + } +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + ctx->enc = 1; + // Keying option 3: All three keys are identical, i.e. K1 = K2 = K3. + ctx->keyopt = 3; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + ctx->enc = 0; + // Keying option 3: All three keys are identical, i.e. K1 = K2 = K3. + ctx->keyopt = 3; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + ctx->enc = 1; + // Keying option 2: K1 and K2 are independent, and K3 = K1. + ctx->keyopt = 2; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + ctx->enc = 0; + // Keying option 2: K1 and K2 are independent, and K3 = K1. + ctx->keyopt = 2; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + ctx->enc = 1; + // Keying option 1: All three keys are independent. + ctx->keyopt = 1; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key + MBEDTLS_DES_KEY_SIZE * 2, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + ctx->enc = 0; + // Keying option 1: All three keys are independent. + ctx->keyopt = 1; + memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE); + memcpy(ctx->key[2], key + MBEDTLS_DES_KEY_SIZE * 2, MBEDTLS_DES_KEY_SIZE); + + return 0; +} + +/* + * DES-ECB block encryption/decryption + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + unsigned char iv[8] = {0x00}; + return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + unsigned char iv[8] = {0x00}; + return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + + +static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length, + unsigned char iv[8], const unsigned char *input, unsigned char *output) +{ + if (length % 8) { + return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; + } + + // NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting. + CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) | + tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos); + + // Keying option 1: All three keys are independent. + // Keying option 2: K1 and K2 are independent, and K3 = K1. + // Keying option 3: All three keys are identical, i.e. K1 = K2 = K3. + if (keyopt == 1) { + CRPT->TDES_CTL |= CRPT_TDES_CTL_3KEYS_Msk; + } + else { + CRPT->TDES_CTL &= ~CRPT_TDES_CTL_3KEYS_Msk; + } + + // Set DES/TDES keys + // NOTE: Don't call driver function TDES_SetKey in BSP because it doesn't support endian swap. + uint32_t val; + volatile uint32_t *tdes_key = (uint32_t *) ((uint32_t) &CRPT->TDES0_KEY1H + (0x40 * 0)); + val = nu_get32_be(key[0] + 0); + *tdes_key ++ = val; + val = nu_get32_be(key[0] + 4); + *tdes_key ++ = val; + val = nu_get32_be(key[1] + 0); + *tdes_key ++ = val; + val = nu_get32_be(key[1] + 4); + *tdes_key ++ = val; + val = nu_get32_be(key[2] + 0); + *tdes_key ++ = val; + val = nu_get32_be(key[2] + 4); + *tdes_key ++ = val; + + uint32_t rmn = length; + const unsigned char *in_pos = input; + const unsigned char *out_pos = output; + + while (rmn) { + uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF; + + uint32_t ivh, ivl; + ivh = nu_get32_be(iv); + ivl = nu_get32_be(iv + 4); + TDES_SetInitVect(0, ivh, ivl); + + memcpy(dmabuf_in, in_pos, data_len); + + TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len); + + // Start enc/dec. + // NOTE: Don't call driver function TDES_Start in BSP because it will override TDES_CTL[3KEYS] setting. + CRPT->TDES_CTL |= CRPT_TDES_CTL_START_Msk | (CRYPTO_DMA_ONE_SHOT << CRPT_TDES_CTL_DMALAST_Pos); + while (CRPT->TDES_STS & CRPT_TDES_STS_BUSY_Msk); + + memcpy(out_pos, dmabuf_out, data_len); + in_pos += data_len; + out_pos += data_len; + rmn -= data_len; + + // Update IV for next block enc/dec in next function call + switch (tdes_opmode) { + case DES_MODE_OFB: + case TDES_MODE_OFB: { + // OFB: IV (enc/dec) = output block XOR input block + uint32_t lbh, lbl; + // Last block of input data + lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4); + lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0); + // Last block of output data + ivh = nu_get32_be(dmabuf_out + 4); + ivl = nu_get32_be(dmabuf_out + 0); + ivh = ivh ^ lbh; + ivl = ivl ^ lbl; + nu_set32_be(iv + 4, ivh); + nu_set32_be(iv, ivl); + break; + } + case DES_MODE_CBC: + case DES_MODE_CFB: + case TDES_MODE_CBC: + case TDES_MODE_CFB: { + // CBC/CFB: IV (enc) = output block + // IV (dec) = input block + if (enc) { + memcpy(iv, dmabuf_out + data_len - 8, 8); + } + else { + memcpy(iv, dmabuf_in + data_len - 8, 8); + } + } + } + } + + return 0; +} + +#endif /* MBEDTLS_DES_ALT */ +#endif /* MBEDTLS_DES_C */ diff --git a/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.h b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.h new file mode 100644 index 0000000000..67a1420ece --- /dev/null +++ b/hal/targets/hal/TARGET_NUVOTON/TARGET_NUC472/des_alt.h @@ -0,0 +1,279 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * 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 MBEDTLS_DES_ALT_H +#define MBEDTLS_DES_ALT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_ALT) + +#include +#include +#include "des.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + */ +typedef struct +{ + int enc; /*!< 0: dec, 1: enc */ + uint16_t keyopt; + uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + int enc; /*!< 0: dec, 1: enc */ + uint16_t keyopt; + uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */ +} +mbedtls_des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_DES_ALT */ + +#endif /* des_alt.h */