Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AES-CCM from tinydtls #91

Closed
wants to merge 13 commits into from
7 changes: 6 additions & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ build_task:
MBEDTLS_LIB: /usr/lib/x86_64-linux-gnu/libmbedcrypto.so
install_script:
- apt update
- apt install -y libgcc-6-dev build-essential pkg-config libcunit1-dev wget libsodium-dev libmbedtls-dev ca-certificates
- apt install -y libgcc-8-dev build-essential pkg-config libcunit1-dev wget libsodium-dev libmbedtls-dev ca-certificates
- git clone https://github.com/intel/tinycbor/ ../tinycbor
- bash -c "cd ../tinycbor && make -j"
- git clone https://github.com/bergzand/nanocbor/ ../nanocbor
Expand Down Expand Up @@ -69,6 +69,11 @@ build_task:
- apt install -y unzip
- wget https://www.dlbeer.co.nz/downloads/c25519-2017-10-05.zip -O ../c25519.zip
- bash -c 'cd .. && unzip c25519.zip'
- name: tinydtls
env:
CRYPTO: tinydtls
crypto_script:
- git clone https://github.com/eclipse/tinydtls.git ../tinydtls -b develop
test_script:
- ls -al
- pwd
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ endif
ifneq (,$(filter c25519,$(CRYPTO)))
include $(MK_DIR)/c25519.mk
endif
ifneq (,$(filter tinydtls,$(CRYPTO)))
include $(MK_DIR)/tinydtls.mk
endif

CFLAGS += $(CFLAGS_CRYPTO)

Expand Down
26 changes: 26 additions & 0 deletions include/cose/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
#if defined(CRYPTO_HACL)
#include "cose/crypto/hacl.h"
#endif
#if defined(CRYPTO_TINYDTLS)
#include "cose/crypto/tinydtls.h"
#endif

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -150,6 +153,9 @@ extern "C" {
#define COSE_CRYPTO_AEAD_AES256GCM_NONCEBYTES COSE_CRYPTO_AEAD_AESGCM_NONCEBYTES
#define COSE_CRYPTO_AEAD_AES256GCM_ABYTES COSE_CRYPTO_AEAD_AESGCM_ABYTES

#define COSE_CRYPTO_AEAD_AESCCM_16_64_128_KEYBYTES 16
#define COSE_CRYPTO_AEAD_AESCCM_16_64_128_ABYTES 8
#define COSE_CRYPTO_AEAD_AESCCM_16_64_128_NONCEBYTES 13

/** @} */

Expand Down Expand Up @@ -233,6 +239,26 @@ int cose_crypto_aead_decrypt_aesgcm(uint8_t *msg,
const uint8_t *k,
size_t keysize);

int cose_crypto_aead_encrypt_aesccm(uint8_t *c,
size_t *clen,
const uint8_t *msg,
size_t msglen,
const uint8_t *aad,
size_t aadlen,
const uint8_t *npub,
const uint8_t *k,
size_t keysize);

int cose_crypto_aead_decrypt_aesccm(uint8_t *msg,
size_t *msglen,
const uint8_t *c,
size_t clen,
const uint8_t *aad,
size_t aadlen,
const uint8_t *npub,
const uint8_t *k,
size_t keysize);

/**
* Generate a symmetric key for AEAD operations
*/
Expand Down
45 changes: 45 additions & 0 deletions include/cose/crypto/tinydtls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2018 Freie Universitat Berlin
* Copyright (C) 2018 Inria
* Copyright (C) 2020 Christian Amsüss <christian@amsuess.com> and Ericsson AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup cose_cryto_tinydtls Crypto glue layer, tinydtls definitions
* @ingroup cose_crypto
*
* Crypto function api for glueing tinydtls' AEAD functions.
* @{
*
* @file
* @brief Crypto function api for glueing tinydtls.
*
* @author Christian Amsüss <christian@amsuess.com>
*/

#ifndef COSE_CRYPTO_TINYDTLS_H
#define COSE_CRYPTO_TINYDTLS_H

#ifdef __cplusplus
extern "C" {
#endif

/**
* @name list of provided algorithms
*
* @{
*/
#define HAVE_ALGO_AESCCM_16_64_128 /**< AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce */
/** @} */

#ifdef __cplusplus
}
#endif

#endif

/** @} */
1 change: 1 addition & 0 deletions include/cose_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ typedef enum {
COSE_ALGO_A128GCM = 1, /**< AES-GCM mode w/ 128-bit key, 128-bit tag */
COSE_ALGO_A192GCM = 2, /**< AES-GCM mode w/ 192-bit key, 128-bit tag */
COSE_ALGO_A256GCM = 3, /**< AES-GCM mode w/ 256-bit key, 128-bit tag */
COSE_ALGO_AESCCM_16_64_128 = 10, /**< AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce */
COSE_ALGO_CHACHA20POLY1305 = 24, /**< IETF ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag */
} cose_algo_t;

Expand Down
14 changes: 14 additions & 0 deletions makefiles/tinydtls.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
TINYDTLS_DIR ?= ../tinydtls
TINYDTLS_CONFIGDIR ?= makefiles/tinydtls_config/
CFLAGS += -DCRYPTO_TINYDTLS
CRYPTOSRC += $(SRC_DIR)/crypt/tinydtls.c
CFLAGS_CRYPTO += -I$(TINYDTLS_DIR)
CFLAGS_CRYPTO += -I$(TINYDTLS_CONFIGDIR)
CRYPTOOBJS += $(TINYDTLS_DIR)/crypto.o
CRYPTOOBJS += $(TINYDTLS_DIR)/aes/rijndael.o
CRYPTOOBJS += $(TINYDTLS_DIR)/aes/rijndael_wrap.o
CRYPTOOBJS += $(TINYDTLS_DIR)/hmac.o
CRYPTOOBJS += $(TINYDTLS_DIR)/ccm.o
CRYPTOOBJS += $(TINYDTLS_DIR)/sha2/sha2.o
CRYPTOOBJS += $(TINYDTLS_DIR)/netq.o
$(CRYPTOOBJS): CFLAGS += -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-function
10 changes: 10 additions & 0 deletions makefiles/tinydtls_config/dtls_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Not that we'd need *that* code, but if neither ECC nro PSK is defined,
// there's empty unions and such (and newer verisons of the library complain
// more explicitly)
chrysn marked this conversation as resolved.
Show resolved Hide resolved
#define DTLS_PSK

// Similarly, without a SHA algorithm, there's unused variables and such
chrysn marked this conversation as resolved.
Show resolved Hide resolved
#define WITH_SHA256

// Without, we get a #warning that is escalated to an #error by -Werror
chrysn marked this conversation as resolved.
Show resolved Hide resolved
#define HAVE_ASSERT_H
22 changes: 22 additions & 0 deletions src/cose_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ bool cose_crypto_is_aead(cose_algo_t algo)
switch(algo) {
case COSE_ALGO_CHACHA20POLY1305:
return true;
#ifdef HAVE_ALGO_AESCCM_16_64_128
case COSE_ALGO_AESCCM_16_64_128:
return true;
#endif
default:
return false;
}
Expand Down Expand Up @@ -82,6 +86,10 @@ int cose_crypto_aead_encrypt(uint8_t *c, /* NOLINT(readability-non-const-parame
#ifdef HAVE_ALGO_AES128GCM
case COSE_ALGO_A128GCM:
return cose_crypto_aead_encrypt_aesgcm(c, clen, msg, msglen, aad, aadlen, npub, key, COSE_CRYPTO_AEAD_AES128GCM_KEYBYTES);
#endif
#ifdef HAVE_ALGO_AESCCM_16_64_128
case COSE_ALGO_AESCCM_16_64_128:
return cose_crypto_aead_encrypt_aesccm(c, clen, msg, msglen, aad, aadlen, npub, key, COSE_CRYPTO_AEAD_AESCCM_16_64_128_KEYBYTES);
#endif
default:
(void)c;
Expand Down Expand Up @@ -124,6 +132,10 @@ int cose_crypto_aead_decrypt(uint8_t *msg, /* NOLINT(readability-non-const-param
#ifdef HAVE_ALGO_AES128GCM
case COSE_ALGO_A128GCM:
return cose_crypto_aead_decrypt_aesgcm(msg, msglen, c, clen, aad, aadlen, npub, k, COSE_CRYPTO_AEAD_AES128GCM_KEYBYTES);
#endif
#ifdef HAVE_ALGO_AESCCM_16_64_128
case COSE_ALGO_AESCCM_16_64_128:
return cose_crypto_aead_decrypt_aesccm(msg, msglen, c, clen, aad, aadlen, npub, k, COSE_CRYPTO_AEAD_AESCCM_16_64_128_KEYBYTES);
#endif
default:
(void)c;
Expand Down Expand Up @@ -169,6 +181,11 @@ int cose_crypto_sign(const cose_key_t *key, uint8_t *sign, size_t *signlen, uint
break;
#endif
default:
(void)key;
(void)sign;
(void)signlen;
(void)msg;
(void)msglen;
return COSE_ERR_NOTIMPLEMENTED;
}
return 0;
Expand All @@ -192,6 +209,11 @@ int cose_crypto_verify(const cose_key_t *key, const uint8_t *sign, size_t signle
break;
#endif
default:
(void)key;
(void)sign;
(void)signlen;
(void)msg;
(void)msglen;
return COSE_ERR_NOTIMPLEMENTED;
}
return 0;
Expand Down
56 changes: 56 additions & 0 deletions src/crypt/tinydtls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2020 Christian Amsüss <christian@amsuess.com> and Ericsson AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* Glue layer between libcose and tinydtls
*/

#include "cose.h"
#include "cose/crypto.h"

#include <crypto.h> /* tinydtls', that is */

int cose_crypto_aead_encrypt_aesccm(uint8_t *c,
size_t *clen,
const uint8_t *msg,
size_t msglen,
const uint8_t *aad,
size_t aadlen,
const uint8_t *npub,
const uint8_t *k,
size_t keysize)
{
// Casts: discarding const -- see https://github.com/eclipse/tinydtls/issues/25
chrysn marked this conversation as resolved.
Show resolved Hide resolved
int ret = dtls_encrypt(msg, msglen, c, (uint8_t*)npub, (uint8_t*)k, keysize, aad, aadlen);
if (ret >= 0 && (size_t)ret == msglen + COSE_CRYPTO_AEAD_AESCCM_16_64_128_ABYTES) {
*clen = ret;
return COSE_OK;
} else {
return COSE_ERR_CRYPTO;
}
}

int cose_crypto_aead_decrypt_aesccm(uint8_t *msg,
size_t *msglen,
const uint8_t *c,
size_t clen,
const uint8_t *aad,
size_t aadlen,
const uint8_t *npub,
const uint8_t *k,
size_t keysize)
{
// Casts: discarding const -- see https://github.com/eclipse/tinydtls/issues/25
chrysn marked this conversation as resolved.
Show resolved Hide resolved
int ret = dtls_decrypt(c, clen, msg, (uint8_t*)npub, (uint8_t*)k, keysize, aad, aadlen);
if (ret >= 0 && (size_t)ret == clen - COSE_CRYPTO_AEAD_AESCCM_16_64_128_ABYTES) {
*msglen = ret;
return COSE_OK;
} else {
return COSE_ERR_CRYPTO;
}
}
75 changes: 75 additions & 0 deletions tests/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,75 @@ void test_crypto_aes256(void)
}
#endif

#ifdef HAVE_ALGO_AESCCM_16_64_128
// Values from https://www.rfc-editor.org/rfc/rfc3610.html#section-8
chrysn marked this conversation as resolved.
Show resolved Hide resolved
static const uint8_t aesccm1_key[16] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
};

static const uint8_t aesccm1_nonce[13] = {
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
};

static const uint8_t aesccm1_input[31] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
};

static const uint8_t aesccm1_output[39] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x58, 0x8c, 0x97, 0x9a,
0x61, 0xc6, 0x63, 0xd2, 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17, 0xe8, 0xd1, 0x2c, 0xfd,
0xf9, 0x26, 0xe0,
};

// The input and output packets in the RFC's test vectors are shown in
// concatenated form AAD || cleartext and AAD || ciphertext || tag,
// respectively; this plucks them apart.
chrysn marked this conversation as resolved.
Show resolved Hide resolved

static const uint8_t *aesccm1_aad = &aesccm1_input[0];
#define AESCCM1_AAD_LEN 8

static const uint8_t *aesccm1_plaintext = &aesccm1_input[AESCCM1_AAD_LEN];
#define AESCCM1_PLAINTEXT_LEN (sizeof(aesccm1_input) - AESCCM1_AAD_LEN)

static const uint8_t *aesccm1_ciphertext = &aesccm1_output[AESCCM1_AAD_LEN];
#define AESCCM1_CIPHERTEXT_LEN (sizeof(aesccm1_output) - AESCCM1_AAD_LEN)

void test_crypto_aesccm_vector(void)
{
unsigned char ciphertext[AESCCM1_CIPHERTEXT_LEN];
unsigned char plaintext[AESCCM1_PLAINTEXT_LEN];

size_t cipherlen = 0;
size_t msglen = 0;
/* Generate key */
cose_crypto_aead_encrypt(
ciphertext, &cipherlen,
aesccm1_plaintext, AESCCM1_PLAINTEXT_LEN,
aesccm1_aad, AESCCM1_AAD_LEN,
NULL, aesccm1_nonce,
aesccm1_key,
COSE_ALGO_AESCCM_16_64_128
);
CU_ASSERT_EQUAL(AESCCM1_CIPHERTEXT_LEN, cipherlen);
CU_ASSERT_EQUAL(memcmp(ciphertext, aesccm1_ciphertext, AESCCM1_CIPHERTEXT_LEN), 0);
CU_ASSERT_EQUAL(
cose_crypto_aead_decrypt(
plaintext, &msglen,
ciphertext, cipherlen,
aesccm1_aad, AESCCM1_AAD_LEN,
aesccm1_nonce,
aesccm1_key,
COSE_ALGO_AESCCM_16_64_128
),
0 );
CU_ASSERT_EQUAL(msglen, AESCCM1_PLAINTEXT_LEN);
CU_ASSERT_EQUAL(memcmp(aesccm1_plaintext, plaintext, AESCCM1_PLAINTEXT_LEN), 0);
}
#endif

const test_t tests_crypto[] = {
#ifdef HAVE_ALGO_EDDSA
{
Expand Down Expand Up @@ -220,6 +289,12 @@ const test_t tests_crypto[] = {
.f = test_crypto_aes256,
.n = "AEAD aes256gcm encrypt/decrypt",
},
#endif
#ifdef HAVE_ALGO_AESCCM_16_64_128
{
.f = test_crypto_aesccm_vector,
.n = "AEAD Chacha20poly1305 encrypt/decrypt with IETF test vector",
},
#endif
{
.f = NULL,
Expand Down
Loading