Skip to content

Commit

Permalink
Merge pull request #20720 from netd-tud/chacha20-glue-code-implementa…
Browse files Browse the repository at this point in the history
…tion

sys/psa_crypto: one-shot Chacha20 support
  • Loading branch information
mguetschow authored Oct 29, 2024
2 parents 1fc9d1b + b9396c4 commit 00e25ad
Show file tree
Hide file tree
Showing 26 changed files with 637 additions and 64 deletions.
1 change: 1 addition & 0 deletions cpu/nrf52/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ifneq (,$(filter nrf52840xxaa,$(CPU_MODEL)))
FEATURES_PROVIDED += periph_hash_sha_512
FEATURES_PROVIDED += periph_hmac_sha_256
FEATURES_PROVIDED += periph_cipher_aes_128_cbc
FEATURES_PROVIDED += periph_cipher_chacha20
FEATURES_PROVIDED += periph_ecc_p192r1
FEATURES_PROVIDED += periph_ecc_p256r1
FEATURES_PROVIDED += periph_ecc_ed25519
Expand Down
5 changes: 5 additions & 0 deletions cpu/nrf52/periph/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ ifneq (,$(filter periph_cipher_aes_128_cbc,$(USEMODULE)))
USEMODULE += psa_cryptocell_310_aes_cbc
endif

ifneq (,$(filter periph_cipher_chacha20,$(USEMODULE)))
USEPKG += driver_cryptocell_310
USEMODULE += psa_cryptocell_310_cipher_chacha20
endif

ifneq (,$(filter periph_hmac_sha_256,$(USEMODULE)))
USEPKG += driver_cryptocell_310
USEMODULE += psa_cryptocell_310_hmac
Expand Down
2 changes: 2 additions & 0 deletions features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,8 @@ groups:
help: A Hardware Random Number Generator (HWRNG) peripheral is present.
- name: periph_cipher_aes_128_cbc
help: AES 128 CBC hardware acceleration present
- name: periph_cipher_chacha20
help: ChaCha20 hardware acceleration present
- name: periph_ecc_p192r1
help: ECC P192R1 hardware acceleration peripheral present.
- name: periph_ecc_p256r1
Expand Down
1 change: 1 addition & 0 deletions makefiles/features_existing.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ FEATURES_EXISTING := \
periph_adc_continuous \
periph_can \
periph_cipher_aes_128_cbc \
periph_cipher_chacha20 \
periph_clic \
periph_coretimer \
periph_cpuid \
Expand Down
1 change: 1 addition & 0 deletions makefiles/features_modules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ USEMODULE += $(PERIPH_FEATURES)
# Add all USED periph_% init modules unless they are blacklisted
PERIPH_IGNORE_MODULES := \
periph_cipher_aes_128_cbc \
periph_cipher_chacha20 \
periph_clic \
periph_common \
periph_coretimer \
Expand Down
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ PSEUDOMODULES += psa_riot_cipher_aes_128_ecb
PSEUDOMODULES += psa_riot_cipher_aes_128_cbc
PSEUDOMODULES += psa_riot_cipher_aes_192_cbc
PSEUDOMODULES += psa_riot_cipher_aes_256_cbc
PSEUDOMODULES += psa_riot_cipher_chacha20
PSEUDOMODULES += psa_riot_hashes_md5
PSEUDOMODULES += psa_riot_hashes_sha_1
PSEUDOMODULES += psa_riot_hashes_sha_224
Expand Down
1 change: 1 addition & 0 deletions pkg/driver_cryptocell_310/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CFLAGS += -Wno-cast-align

PSEUDOMODULES += psa_cryptocell_310_aes_cbc
PSEUDOMODULES += psa_cryptocell_310_aes_common
PSEUDOMODULES += psa_cryptocell_310_cipher_chacha20
PSEUDOMODULES += psa_cryptocell_310_ecc_common
PSEUDOMODULES += psa_cryptocell_310_ecc_p192
PSEUDOMODULES += psa_cryptocell_310_ecc_p256
Expand Down
4 changes: 4 additions & 0 deletions pkg/driver_cryptocell_310/include/cryptocell_310_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
extern "C" {
#endif

#ifdef CPU_NRF52
#define CHECK_POINTER_DMA_ACCESS(p) ((unsigned int)p >= 0x20000000 ? (unsigned int)p < 0x40000000 : 0)

Check warning on line 27 in pkg/driver_cryptocell_310/include/cryptocell_310_util.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
#endif

/**
* @brief Enable CryptoCell module and IRQs.
*
Expand Down
1 change: 1 addition & 0 deletions pkg/driver_cryptocell_310/include/psa_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C" {
#include "crys_ec_mont_edw_error.h"
#include "crys_hash_error.h"
#include "ssi_aes_error.h"
#include "crys_chacha_error.h"

/**
* @brief Convert CryptoCell CRYS errors to PSA status values
Expand Down
135 changes: 135 additions & 0 deletions pkg/driver_cryptocell_310/psa_cryptocell_310/cipher_chacha20.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (C) 2024 TU Dresden
*
* 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.
*/

/**
* @ingroup pkg_driver_cryptocell_310
* @{
*
* @file
* @brief PSA Crypto wrapper for the CryptoCell 310 ChaCha API.
*
* @author Lennard Melling <[email protected]>
*
*/
#ifndef PSA_CRYPTOCELL_310_CHACHA_H
#define PSA_CRYPTOCELL_310_CHACHA_H

#ifdef __cplusplus
extern "C" {
#endif

#include "psa/crypto.h"
#include "crys_chacha.h"
#include "cryptocell_310_util.h"
#include "psa_error.h"

#define ENABLE_DEBUG 0
#include "debug.h"

psa_status_t psa_cipher_chacha20_encrypt(uint8_t *key_buffer,
size_t key_buffer_size,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
DEBUG("Peripheral ChaCha20 Cipher encryption");
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

if (!CHECK_POINTER_DMA_ACCESS(key_buffer) ||
!CHECK_POINTER_DMA_ACCESS(input) ||
!CHECK_POINTER_DMA_ACCESS(output)) {
return PSA_ERROR_DATA_INVALID;
}

if (output_size < (input_length + CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}

if (key_buffer_size != CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES) {
return PSA_ERROR_INVALID_ARGUMENT;
}

uint8_t *nonce = &output[0];
uint8_t *data_out = &output[CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES];
status = psa_generate_random(nonce, CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES);
if (status != PSA_SUCCESS) {
return status;
}

cryptocell_310_enable();
CRYSError_t periph_status = CRYS_CHACHA(nonce, CRYS_CHACHA_Nonce96BitSize,
key_buffer, 0UL,
CRYS_CHACHA_Encrypt,
(uint8_t *) input,
input_length,
data_out);
cryptocell_310_disable();
status = CRYS_to_psa_error(periph_status);
if (status != PSA_SUCCESS) {
return status;
}

*output_length = input_length + CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES;
return PSA_SUCCESS;
}

psa_status_t psa_cipher_chacha20_decrypt(uint8_t *key_buffer,
size_t key_buffer_size,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
DEBUG("Peripheral ChaCha20 Cipher decryption");
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

if (!CHECK_POINTER_DMA_ACCESS(key_buffer) ||
!CHECK_POINTER_DMA_ACCESS(input) ||
!CHECK_POINTER_DMA_ACCESS(output)) {
return PSA_ERROR_DATA_INVALID;
}

if ((key_buffer_size != CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES) ||
(input_length < CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES)) {
return PSA_ERROR_INVALID_ARGUMENT;
}

if (output_size < (input_length - CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}

const uint8_t *nonce = &input[0];
const uint8_t *data_in = &input[CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES];
size_t data_size = input_length - CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES;

cryptocell_310_enable();
CRYSError_t periph_status = CRYS_CHACHA((uint8_t *)nonce, CRYS_CHACHA_Nonce96BitSize,
key_buffer, 0UL,
CRYS_CHACHA_Decrypt,
(uint8_t *)data_in,
data_size,
output);
cryptocell_310_disable();
status = CRYS_to_psa_error(periph_status);
if (status != PSA_SUCCESS) {
return status;
}

*output_length = data_size;
return PSA_SUCCESS;
}

#ifdef __cplusplus
}
#endif

#endif /* PSA_CRYPTOCELL_310_CHACHA_H */
/** @} */
33 changes: 33 additions & 0 deletions pkg/driver_cryptocell_310/psa_cryptocell_310/error_conversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,23 @@ psa_status_t CRYS_to_psa_error(CRYSError_t error)
return PSA_SUCCESS;
case CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR:
case CRYS_HASH_IS_NOT_SUPPORTED:
case CRYS_CHACHA_IS_NOT_SUPPORTED:
return PSA_ERROR_NOT_SUPPORTED;
case CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR:
return PSA_ERROR_CORRUPTION_DETECTED;
case CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR:
case CRYS_ECEDW_SIGN_VERIFY_FAILED_ERROR:
return PSA_ERROR_INVALID_SIGNATURE;
case CRYS_CHACHA_CTX_SIZES_ERROR:
case CRYS_CHACHA_DATA_IN_POINTER_INVALID_ERROR:
case CRYS_CHACHA_DATA_IN_SIZE_ILLEGAL:
case CRYS_CHACHA_DATA_OUT_POINTER_INVALID_ERROR:
case CRYS_CHACHA_ILLEGAL_KEY_SIZE_ERROR:
case CRYS_CHACHA_INVALID_ENCRYPT_MODE_ERROR:
case CRYS_CHACHA_INVALID_KEY_POINTER_ERROR:
case CRYS_CHACHA_INVALID_NONCE_ERROR:
case CRYS_CHACHA_INVALID_NONCE_PTR_ERROR:
case CRYS_CHACHA_INVALID_USER_CONTEXT_POINTER_ERROR:
case CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR:
case CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR:
case CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR:
Expand Down Expand Up @@ -453,6 +464,28 @@ const char *cryptocell310_status_to_humanly_readable(uint32_t status)
return "CRYS_ECMONT_IS_NOT_SUPPORTED";
case CRYS_ECEDW_IS_NOT_SUPPORTED:
return "CRYS_ECEDW_IS_NOT_SUPPORTED";
case CRYS_CHACHA_CTX_SIZES_ERROR:
return "CRYS_CHACHA_CTX_SIZES_ERROR";
case CRYS_CHACHA_DATA_IN_POINTER_INVALID_ERROR:
return "CRYS_CHACHA_DATA_IN_POINTER_INVALID_ERROR";
case CRYS_CHACHA_DATA_IN_SIZE_ILLEGAL:
return "CRYS_CHACHA_DATA_IN_SIZE_ILLEGAL";
case CRYS_CHACHA_DATA_OUT_POINTER_INVALID_ERROR:
return "CRYS_CHACHA_DATA_OUT_POINTER_INVALID_ERROR";
case CRYS_CHACHA_ILLEGAL_KEY_SIZE_ERROR:
return "CRYS_CHACHA_ILLEGAL_KEY_SIZE_ERROR";
case CRYS_CHACHA_INVALID_ENCRYPT_MODE_ERROR:
return "CRYS_CHACHA_INVALID_ENCRYPT_MODE_ERROR";
case CRYS_CHACHA_INVALID_KEY_POINTER_ERROR:
return "CRYS_CHACHA_INVALID_KEY_POINTER_ERROR";
case CRYS_CHACHA_INVALID_NONCE_ERROR:
return "CRYS_CHACHA_INVALID_NONCE_ERROR";
case CRYS_CHACHA_INVALID_NONCE_PTR_ERROR:
return "CRYS_CHACHA_INVALID_NONCE_PTR_ERROR";
case CRYS_CHACHA_INVALID_USER_CONTEXT_POINTER_ERROR:
return "CRYS_CHACHA_INVALID_USER_CONTEXT_POINTER_ERROR";
case CRYS_CHACHA_IS_NOT_SUPPORTED:
return "CRYS_CHACHA_IS_NOT_SUPPORTED";
default:
return "Error value not recognized";
}
Expand Down
19 changes: 14 additions & 5 deletions sys/crypto/chacha20poly1305.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,22 @@ static void _keystream(chacha20poly1305_ctx_t *ctx, const uint8_t *key,
}

static void _xcrypt(chacha20poly1305_ctx_t *ctx, const uint8_t *key,
const uint8_t *nonce, const uint8_t *in, uint8_t *out, size_t len)
const uint8_t *nonce, const uint8_t *in, uint8_t *out,
size_t len, size_t counter)
{
/* Number of full 64 byte blocks */
const size_t num_blocks = len >> 6;
size_t pos = 0;
/* xcrypt full blocks */
for (size_t i = 0; i < num_blocks; i++, pos += 64) {
_keystream(ctx, key, nonce, i+1);
_keystream(ctx, key, nonce, i + counter);
for (size_t j = 0; j < 64; j++) {
out[pos+j] = in[pos+j] ^ ((uint8_t*)ctx->state)[j];
}
}
/* xcrypt remaining bytes */
if (len - pos) {
_keystream(ctx, key, nonce, num_blocks+1);
_keystream(ctx, key, nonce, num_blocks + counter);
for (size_t j = 0; j < len - pos; j++) {
out[pos+j] = in[pos+j] ^ ((uint8_t*)ctx->state)[j];
}
Expand Down Expand Up @@ -142,7 +143,7 @@ void chacha20poly1305_encrypt(uint8_t *cipher, const uint8_t *msg,
const uint8_t *key, const uint8_t *nonce)
{
chacha20poly1305_ctx_t ctx;
_xcrypt(&ctx, key, nonce, msg, cipher, msglen);
_xcrypt(&ctx, key, nonce, msg, cipher, msglen, 1);
crypto_secure_wipe(&ctx, sizeof(ctx));
/* Generate tag */
_poly1305_gentag(&cipher[msglen], key, nonce,
Expand All @@ -164,6 +165,14 @@ int chacha20poly1305_decrypt(const uint8_t *cipher, size_t cipherlen,
}
chacha20poly1305_ctx_t ctx;
/* Number of full blocks */
_xcrypt(&ctx, key, nonce, cipher, msg, *msglen);
_xcrypt(&ctx, key, nonce, cipher, msg, *msglen, 1);
return 1;
}

void chacha20_encrypt_decrypt(const uint8_t *input, uint8_t *output,
const uint8_t *key, const uint8_t *nonce,
size_t inputlen)
{
chacha20poly1305_ctx_t ctx;
_xcrypt(&ctx, key, nonce, input, output, inputlen, 0);
}
Loading

0 comments on commit 00e25ad

Please sign in to comment.