Implement ChaCha20 and ChaCha20-Poly1305
Smoke tests: test data for ChaCha20 calculated with PyCryptodome; test
vector from RFC 7539 for ChaCha20-Poly1305.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 3e3c5eb..7794e7a 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -51,6 +51,8 @@
#include "mbedtls/bignum.h"
#include "mbedtls/blowfish.h"
#include "mbedtls/camellia.h"
+#include "mbedtls/chacha20.h"
+#include "mbedtls/chachapoly.h"
#include "mbedtls/cipher.h"
#include "mbedtls/ccm.h"
#include "mbedtls/cmac.h"
@@ -179,6 +181,14 @@
case MBEDTLS_ERR_CCM_HW_ACCEL_FAILED:
return( PSA_ERROR_HARDWARE_FAILURE );
+ case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE:
+ return( PSA_ERROR_BAD_STATE );
+ case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+
case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
return( PSA_ERROR_NOT_SUPPORTED );
case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:
@@ -466,6 +476,12 @@
return( PSA_ERROR_INVALID_ARGUMENT );
break;
#endif
+#if defined(MBEDTLS_CHACHA20_C)
+ case PSA_KEY_TYPE_CHACHA20:
+ if( bits != 256 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ break;
+#endif
default:
return( PSA_ERROR_NOT_SUPPORTED );
}
@@ -2026,6 +2042,7 @@
switch( alg )
{
case PSA_ALG_ARC4:
+ case PSA_ALG_CHACHA20:
mode = MBEDTLS_MODE_STREAM;
break;
case PSA_ALG_CTR:
@@ -2049,6 +2066,9 @@
case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ):
mode = MBEDTLS_MODE_GCM;
break;
+ case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ):
+ mode = MBEDTLS_MODE_CHACHAPOLY;
+ break;
default:
return( NULL );
}
@@ -2084,6 +2104,9 @@
case PSA_KEY_TYPE_ARC4:
cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
break;
+ case PSA_KEY_TYPE_CHACHA20:
+ cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
+ break;
default:
return( NULL );
}
@@ -3318,6 +3341,11 @@
{
operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type );
}
+#if defined(MBEDTLS_CHACHA20_C)
+ else
+ if( alg == PSA_ALG_CHACHA20 )
+ operation->iv_size = 12;
+#endif
exit:
if( status == 0 )
@@ -3631,6 +3659,9 @@
#if defined(MBEDTLS_GCM_C)
mbedtls_gcm_context gcm;
#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ mbedtls_chachapoly_context chachapoly;
+#endif /* MBEDTLS_CHACHAPOLY_C */
} ctx;
psa_algorithm_t core_alg;
uint8_t full_tag_length;
@@ -3715,6 +3746,22 @@
break;
#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ):
+ operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
+ operation->full_tag_length = 16;
+ /* We only support the default tag length. */
+ if( alg != PSA_ALG_CHACHA20_POLY1305 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ mbedtls_chachapoly_init( &operation->ctx.chachapoly );
+ status = mbedtls_to_psa_error(
+ mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
+ operation->slot->data.raw.data ) );
+ if( status != 0 )
+ goto cleanup;
+ break;
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
default:
return( PSA_ERROR_NOT_SUPPORTED );
}
@@ -3792,6 +3839,26 @@
}
else
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+ {
+ if( nonce_length != 12 || operation.tag_length != 16 )
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ status = mbedtls_to_psa_error(
+ mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
+ plaintext_length,
+ nonce,
+ additional_data,
+ additional_data_length,
+ plaintext,
+ ciphertext,
+ tag ) );
+ }
+ else
+#endif /* MBEDTLS_CHACHAPOLY_C */
{
return( PSA_ERROR_NOT_SUPPORTED );
}
@@ -3883,6 +3950,26 @@
}
else
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+ {
+ if( nonce_length != 12 || operation.tag_length != 16 )
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ status = mbedtls_to_psa_error(
+ mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
+ ciphertext_length - operation.tag_length,
+ nonce,
+ additional_data,
+ additional_data_length,
+ tag,
+ ciphertext,
+ plaintext ) );
+ }
+ else
+#endif /* MBEDTLS_CHACHAPOLY_C */
{
return( PSA_ERROR_NOT_SUPPORTED );
}