Merge pull request #5545 from icing/evp_chacha

Add ChaCha20 as available cipher in the EVP API.
This commit is contained in:
David Garske 2022-09-06 10:42:54 -07:00 committed by GitHub
commit d72b401e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 181 additions and 3 deletions

View File

@ -1006,7 +1006,7 @@ const WOLFSSL_EVP_CIPHER* wolfSSL_quic_get_hp(WOLFSSL* ssl)
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case TLS_CHACHA20_POLY1305_SHA256:
evp_cipher = wolfSSL_EVP_chacha20_poly1305();
evp_cipher = wolfSSL_EVP_chacha20();
break;
#endif
#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_128)

View File

@ -38918,6 +38918,11 @@ int wolfSSL_RAND_poll(void)
break;
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
break;
#endif
case NULL_CIPHER_TYPE :
WOLFSSL_MSG("NULL");
break;
@ -39007,6 +39012,11 @@ int wolfSSL_RAND_poll(void)
break;
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
break;
#endif
case NULL_CIPHER_TYPE :
WOLFSSL_MSG("NULL");
break;

View File

@ -52094,6 +52094,68 @@ static int test_wolfssl_EVP_chacha20_poly1305(void)
return 0;
}
static int test_wolfssl_EVP_chacha20(void)
{
#if defined(OPENSSL_EXTRA) && defined(HAVE_CHACHA)
byte key[CHACHA_MAX_KEY_SZ];
byte iv [WOLFSSL_EVP_CHACHA_IV_BYTES];
byte plainText[] = {0xDE, 0xAD, 0xBE, 0xEF};
byte cipherText[sizeof(plainText)];
byte decryptedText[sizeof(plainText)];
EVP_CIPHER_CTX* ctx;
int outSz;
printf(testingFmt, "test_wolfssl_EVP_chacha20");
/* Encrypt. */
AssertNotNull((ctx = EVP_CIPHER_CTX_new()));
AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_chacha20(), NULL, NULL,
NULL), WOLFSSL_SUCCESS);
/* Any tag length must fail - not an AEAD cipher. */
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
16, NULL), WOLFSSL_FAILURE);
AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), WOLFSSL_SUCCESS);
AssertIntEQ(EVP_EncryptUpdate(ctx, cipherText, &outSz, plainText,
sizeof(plainText)), WOLFSSL_SUCCESS);
AssertIntEQ(outSz, sizeof(plainText));
AssertIntEQ(EVP_EncryptFinal_ex(ctx, cipherText, &outSz), WOLFSSL_SUCCESS);
AssertIntEQ(outSz, 0);
EVP_CIPHER_CTX_free(ctx);
/* Decrypt. */
AssertNotNull((ctx = EVP_CIPHER_CTX_new()));
AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_chacha20(), NULL, NULL,
NULL), WOLFSSL_SUCCESS);
AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), WOLFSSL_SUCCESS);
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptedText, &outSz, cipherText,
sizeof(cipherText)), WOLFSSL_SUCCESS);
AssertIntEQ(outSz, sizeof(cipherText));
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptedText, &outSz),
WOLFSSL_SUCCESS);
AssertIntEQ(outSz, 0);
EVP_CIPHER_CTX_free(ctx);
/* Test partial Inits. CipherInit() allow setting of key and iv
* in separate calls. */
AssertNotNull((ctx = EVP_CIPHER_CTX_new()));
AssertIntEQ(wolfSSL_EVP_CipherInit(ctx, EVP_chacha20(),
key, NULL, 1), WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, 1),
WOLFSSL_SUCCESS);
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptedText, &outSz, cipherText,
sizeof(cipherText)), WOLFSSL_SUCCESS);
AssertIntEQ(outSz, sizeof(cipherText));
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptedText, &outSz),
WOLFSSL_SUCCESS);
AssertIntEQ(outSz, 0);
EVP_CIPHER_CTX_free(ctx);
printf(resultFmt, passed);
#endif
return 0;
}
static int test_wolfSSL_EVP_PKEY_hkdf(void)
{
#if defined(OPENSSL_EXTRA) && defined(HAVE_HKDF)
@ -57991,6 +58053,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfssl_EVP_aes_gcm_AAD_2_parts),
TEST_DECL(test_wolfssl_EVP_aes_gcm),
TEST_DECL(test_wolfssl_EVP_chacha20_poly1305),
TEST_DECL(test_wolfssl_EVP_chacha20),
TEST_DECL(test_wolfSSL_EVP_PKEY_hkdf),
TEST_DECL(test_wolfSSL_PKEY_up_ref),
TEST_DECL(test_wolfSSL_EVP_Cipher_extra),

View File

@ -166,6 +166,10 @@
static const char EVP_CHACHA20_POLY1305[] = "CHACHA20-POLY1305";
#endif
#ifdef HAVE_CHACHA
static const char EVP_CHACHA20[] = "CHACHA20";
#endif
static const char EVP_NULL[] = "NULL";
#define EVP_CIPHER_TYPE_MATCHES(x, y) (XSTRCMP(x,y) == 0)
@ -246,6 +250,9 @@ int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c)
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case CHACHA20_POLY1305_TYPE: return 32;
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE: return CHACHA_MAX_KEY_SZ;
#endif
default:
return 0;
@ -702,6 +709,15 @@ int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
return WOLFSSL_SUCCESS;
}
}
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
if (wc_Chacha_Process(&ctx->cipher.chacha, out, in, inl) != 0) {
WOLFSSL_MSG("wc_ChaCha_Process failed");
return WOLFSSL_FAILURE;
}
*outl = inl;
return WOLFSSL_SUCCESS;
#endif
default:
/* fall-through */
@ -1298,6 +1314,11 @@ static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher)
return CHACHA20_POLY1305_TYPE;
#endif
#ifdef HAVE_CHACHA
else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_CHACHA20))
return CHACHA20_TYPE;
#endif
else return 0;
}
@ -1371,6 +1392,12 @@ int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher)
case CHACHA20_POLY1305_TYPE:
return 1;
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
return 1;
#endif
default:
return 0;
}
@ -1443,6 +1470,10 @@ unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
case CHACHA20_POLY1305_TYPE:
return WOLFSSL_EVP_CIPH_STREAM_CIPHER |
WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
#endif
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
return WOLFSSL_EVP_CIPH_STREAM_CIPHER;
#endif
default:
return 0;
@ -4176,6 +4207,10 @@ static const struct cipher{
{CHACHA20_POLY1305_TYPE, EVP_CHACHA20_POLY1305, NID_chacha20_poly1305},
#endif
#ifdef HAVE_CHACHA
{CHACHA20_TYPE, EVP_CHACHA20, NID_chacha20},
#endif
{ 0, NULL, 0}
};
@ -4275,6 +4310,9 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name)
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
{EVP_CHACHA20_POLY1305, "chacha20-poly1305"},
#endif
#ifdef HAVE_CHACHA
{EVP_CHACHA20, "chacha20"},
#endif
{ NULL, NULL}
};
@ -4394,6 +4432,11 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id)
return wolfSSL_EVP_chacha20_poly1305();
#endif
#ifdef HAVE_CHACHA
case NID_chacha20:
return wolfSSL_EVP_chacha20();
#endif
default:
WOLFSSL_MSG("Bad cipher id value");
}
@ -5298,6 +5341,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
}
#endif
#ifdef HAVE_CHACHA
const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20(void)
{
WOLFSSL_ENTER("wolfSSL_EVP_chacha20");
return EVP_CHACHA20;
}
#endif
const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
{
WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
@ -6652,6 +6703,39 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
}
}
#endif
#ifdef HAVE_CHACHA
if (ctx->cipherType == CHACHA20_TYPE ||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_CHACHA20))) {
WOLFSSL_MSG("EVP_CHACHA20");
ctx->cipherType = CHACHA20_TYPE;
ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
ctx->keyLen = CHACHA_MAX_KEY_SZ;
ctx->block_size = 1;
ctx->ivSz = WOLFSSL_EVP_CHACHA_IV_BYTES;
if (enc == 0 || enc == 1) {
ctx->enc = (byte) enc;
}
if (key != NULL && wc_Chacha_SetKey(&ctx->cipher.chacha,
key, ctx->keyLen) != 0) {
WOLFSSL_MSG("wc_Chacha_SetKey() failed");
return WOLFSSL_FAILURE;
}
if (iv != NULL) {
/* a bit silly. chacha takes an iv+counter and internally
* combines them to a new iv. EVP is given exactly *one* iv,
* so to pass it into chacha, we have to revert that first.
* The counter comes first in little-endian */
word32 counter = (uint32_t)iv[0] + (uint32_t)(iv[1] << 8) +
(uint32_t)(iv[2] << 16) + (uint32_t)(iv[3] << 24);
if (wc_Chacha_SetIV(&ctx->cipher.chacha,
iv + sizeof(counter), counter) != 0) {
WOLFSSL_MSG("wc_Chacha_SetIV() failed");
return WOLFSSL_FAILURE;
}
}
}
#endif
#ifndef NO_DES3
if (ctx->cipherType == DES_CBC_TYPE ||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_DES_CBC))) {
@ -8423,6 +8507,11 @@ int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
WOLFSSL_MSG("CHACHA20 POLY1305");
return CHACHA20_POLY1305_AEAD_IV_SIZE;
#endif /* HAVE_CHACHA HAVE_POLY1305 */
#ifdef HAVE_CHACHA
case CHACHA20_TYPE:
WOLFSSL_MSG("CHACHA20");
return WOLFSSL_EVP_CHACHA_IV_BYTES;
#endif /* HAVE_CHACHA */
case NULL_CIPHER_TYPE :
WOLFSSL_MSG("NULL");
@ -8512,6 +8601,11 @@ int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher)
return CHACHA20_POLY1305_AEAD_IV_SIZE;
#endif
#ifdef HAVE_CHACHA
if (XSTRCMP(name, EVP_CHACHA20) == 0)
return WOLFSSL_EVP_CHACHA_IV_BYTES;
#endif
(void)name;
return 0;

View File

@ -139,6 +139,11 @@ WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void);
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20_poly1305(void);
#endif
#ifdef HAVE_CHACHA
/* ChaCha IV + counter is set as one IV in EVP */
#define WOLFSSL_EVP_CHACHA_IV_BYTES (CHACHA_IV_BYTES + sizeof(word32))
WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20(void);
#endif
typedef union {
@ -212,6 +217,9 @@ typedef union {
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
ChaChaPoly_Aead chachaPoly;
#endif
#ifdef HAVE_CHACHA
ChaCha chacha;
#endif
} WOLFSSL_Cipher;
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
@ -282,7 +290,8 @@ enum {
AES_256_OFB_TYPE = 35,
AES_128_XTS_TYPE = 36,
AES_256_XTS_TYPE = 37,
CHACHA20_POLY1305_TYPE = 38
CHACHA20_POLY1305_TYPE = 38,
CHACHA20_TYPE = 39
};
enum {
@ -357,7 +366,8 @@ enum {
NID_aes_256_xts = 914,
NID_camellia_128_cbc = 751,
NID_camellia_256_cbc = 753,
NID_chacha20_poly1305 = 1018
NID_chacha20_poly1305 = 1018,
NID_chacha20 = 1019
};
enum {
@ -898,6 +908,7 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
#define EVP_des_ede3_cbc wolfSSL_EVP_des_ede3_cbc
#define EVP_des_ede3_ecb wolfSSL_EVP_des_ede3_ecb
#define EVP_rc4 wolfSSL_EVP_rc4
#define EVP_chacha20 wolfSSL_EVP_chacha20
#define EVP_chacha20_poly1305 wolfSSL_EVP_chacha20_poly1305
#define EVP_enc_null wolfSSL_EVP_enc_null