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

sys/psa_crypto: one-shot Chacha20 support #20720

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -851,6 +851,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
Comment on lines +26 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have to remember doing similar checks for all the other cryptocell 310 glue code, too. I'll open a ticket.


/**
* @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 @@
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 @@ -182,7 +193,7 @@

const char *cryptocell310_status_to_humanly_readable(uint32_t status)
{
switch(status) {

Check warning on line 196 in pkg/driver_cryptocell_310/psa_cryptocell_310/error_conversion.c

View workflow job for this annotation

GitHub Actions / static-tests

keyword 'switch' not followed by a single space
case CRYS_ECDH_SVDP_DH_NOT_CONCENT_PUBL_AND_PRIV_DOMAIN_ID_ERROR:
return "CRYS_ECDH_SVDP_DH_NOT_CONCENT_PUBL_AND_PRIV_DOMAIN_ID_ERROR";
case CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR:
Expand Down Expand Up @@ -453,6 +464,28 @@
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
Loading