-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for xchacha20 and xchacha20-poly1305
xchacha is a chacha stream that allows for an extended nonce, which in turn makes it feasible to use random nonces. ok tb@
- Loading branch information
dlg
committed
Jan 22, 2019
1 parent
1450233
commit f9ad715
Showing
10 changed files
with
399 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: chacha.c,v 1.7 2015/12/09 14:07:55 bcook Exp $ */ | ||
/* $OpenBSD: chacha.c,v 1.8 2019/01/22 00:59:21 dlg Exp $ */ | ||
/* | ||
* Copyright (c) 2014 Joel Sing <[email protected]> | ||
* | ||
|
@@ -75,3 +75,13 @@ CRYPTO_chacha_20(unsigned char *out, const unsigned char *in, size_t len, | |
|
||
chacha_encrypt_bytes(&ctx, in, out, (uint32_t)len); | ||
} | ||
|
||
void | ||
CRYPTO_xchacha_20(unsigned char *out, const unsigned char *in, size_t len, | ||
const unsigned char key[32], const unsigned char iv[24]) | ||
{ | ||
uint8_t subkey[32]; | ||
|
||
CRYPTO_hchacha_20(subkey, key, iv); | ||
CRYPTO_chacha_20(out, in, len, subkey, iv + 16, 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: chacha.h,v 1.7 2015/12/09 14:07:55 bcook Exp $ */ | ||
/* $OpenBSD: chacha.h,v 1.8 2019/01/22 00:59:21 dlg Exp $ */ | ||
/* | ||
* Copyright (c) 2014 Joel Sing <[email protected]> | ||
* | ||
|
@@ -46,6 +46,10 @@ void ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, | |
|
||
void CRYPTO_chacha_20(unsigned char *out, const unsigned char *in, size_t len, | ||
const unsigned char key[32], const unsigned char iv[8], uint64_t counter); | ||
void CRYPTO_xchacha_20(unsigned char *out, const unsigned char *in, size_t len, | ||
const unsigned char key[32], const unsigned char iv[24]); | ||
void CRYPTO_hchacha_20(unsigned char out[32], | ||
const unsigned char key[32], const unsigned char iv[16]); | ||
|
||
#ifdef __cplusplus | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: e_chacha20poly1305.c,v 1.18 2017/08/28 17:48:02 jsing Exp $ */ | ||
/* $OpenBSD: e_chacha20poly1305.c,v 1.19 2019/01/22 00:59:21 dlg Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2015 Reyk Floter <[email protected]> | ||
|
@@ -36,6 +36,7 @@ | |
#define CHACHA20_CONSTANT_LEN 4 | ||
#define CHACHA20_IV_LEN 8 | ||
#define CHACHA20_NONCE_LEN (CHACHA20_CONSTANT_LEN + CHACHA20_IV_LEN) | ||
#define XCHACHA20_NONCE_LEN 24 | ||
|
||
struct aead_chacha20_poly1305_ctx { | ||
unsigned char key[32]; | ||
|
@@ -246,6 +247,108 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out, | |
return 1; | ||
} | ||
|
||
static int | ||
aead_xchacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, | ||
size_t *out_len, size_t max_out_len, const unsigned char *nonce, | ||
size_t nonce_len, const unsigned char *in, size_t in_len, | ||
const unsigned char *ad, size_t ad_len) | ||
{ | ||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; | ||
unsigned char poly1305_key[32]; | ||
unsigned char subkey[32]; | ||
poly1305_state poly1305; | ||
|
||
if (max_out_len < in_len + c20_ctx->tag_len) { | ||
EVPerror(EVP_R_BUFFER_TOO_SMALL); | ||
return 0; | ||
} | ||
|
||
if (nonce_len != ctx->aead->nonce_len) { | ||
EVPerror(EVP_R_IV_TOO_LARGE); | ||
return 0; | ||
} | ||
|
||
CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce); | ||
|
||
CRYPTO_chacha_20(out, in, in_len, subkey, nonce + 16, 1); | ||
|
||
memset(poly1305_key, 0, sizeof(poly1305_key)); | ||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), | ||
subkey, nonce + 16, 0); | ||
|
||
CRYPTO_poly1305_init(&poly1305, poly1305_key); | ||
poly1305_update_with_pad16(&poly1305, ad, ad_len); | ||
poly1305_update_with_pad16(&poly1305, out, in_len); | ||
poly1305_update_with_length(&poly1305, NULL, ad_len); | ||
poly1305_update_with_length(&poly1305, NULL, in_len); | ||
|
||
if (c20_ctx->tag_len != POLY1305_TAG_LEN) { | ||
unsigned char tag[POLY1305_TAG_LEN]; | ||
CRYPTO_poly1305_finish(&poly1305, tag); | ||
memcpy(out + in_len, tag, c20_ctx->tag_len); | ||
*out_len = in_len + c20_ctx->tag_len; | ||
return 1; | ||
} | ||
|
||
CRYPTO_poly1305_finish(&poly1305, out + in_len); | ||
*out_len = in_len + POLY1305_TAG_LEN; | ||
return 1; | ||
} | ||
|
||
static int | ||
aead_xchacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out, | ||
size_t *out_len, size_t max_out_len, const unsigned char *nonce, | ||
size_t nonce_len, const unsigned char *in, size_t in_len, | ||
const unsigned char *ad, size_t ad_len) | ||
{ | ||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; | ||
unsigned char mac[POLY1305_TAG_LEN]; | ||
unsigned char poly1305_key[32]; | ||
unsigned char subkey[32]; | ||
poly1305_state poly1305; | ||
size_t plaintext_len; | ||
|
||
if (in_len < c20_ctx->tag_len) { | ||
EVPerror(EVP_R_BAD_DECRYPT); | ||
return 0; | ||
} | ||
|
||
if (nonce_len != ctx->aead->nonce_len) { | ||
EVPerror(EVP_R_IV_TOO_LARGE); | ||
return 0; | ||
} | ||
|
||
plaintext_len = in_len - c20_ctx->tag_len; | ||
|
||
if (max_out_len < plaintext_len) { | ||
EVPerror(EVP_R_BUFFER_TOO_SMALL); | ||
return 0; | ||
} | ||
|
||
CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce); | ||
|
||
memset(poly1305_key, 0, sizeof(poly1305_key)); | ||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), | ||
subkey, nonce + 16, 0); | ||
|
||
CRYPTO_poly1305_init(&poly1305, poly1305_key); | ||
poly1305_update_with_pad16(&poly1305, ad, ad_len); | ||
poly1305_update_with_pad16(&poly1305, in, plaintext_len); | ||
poly1305_update_with_length(&poly1305, NULL, ad_len); | ||
poly1305_update_with_length(&poly1305, NULL, plaintext_len); | ||
|
||
CRYPTO_poly1305_finish(&poly1305, mac); | ||
if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) { | ||
EVPerror(EVP_R_BAD_DECRYPT); | ||
return 0; | ||
} | ||
|
||
CRYPTO_chacha_20(out, in, plaintext_len, subkey, nonce + 16, 1); | ||
|
||
*out_len = plaintext_len; | ||
return 1; | ||
} | ||
|
||
/* RFC 7539 */ | ||
static const EVP_AEAD aead_chacha20_poly1305 = { | ||
.key_len = 32, | ||
|
@@ -265,4 +368,22 @@ EVP_aead_chacha20_poly1305() | |
return &aead_chacha20_poly1305; | ||
} | ||
|
||
static const EVP_AEAD aead_xchacha20_poly1305 = { | ||
.key_len = 32, | ||
.nonce_len = XCHACHA20_NONCE_LEN, | ||
.overhead = POLY1305_TAG_LEN, | ||
.max_tag_len = POLY1305_TAG_LEN, | ||
|
||
.init = aead_chacha20_poly1305_init, | ||
.cleanup = aead_chacha20_poly1305_cleanup, | ||
.seal = aead_xchacha20_poly1305_seal, | ||
.open = aead_xchacha20_poly1305_open, | ||
}; | ||
|
||
const EVP_AEAD * | ||
EVP_aead_xchacha20_poly1305() | ||
{ | ||
return &aead_xchacha20_poly1305; | ||
} | ||
|
||
#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: evp.h,v 1.71 2019/01/19 01:24:18 tb Exp $ */ | ||
/* $OpenBSD: evp.h,v 1.72 2019/01/22 00:59:21 dlg Exp $ */ | ||
/* Copyright (C) 1995-1998 Eric Young ([email protected]) | ||
* All rights reserved. | ||
* | ||
|
@@ -1243,6 +1243,8 @@ const EVP_AEAD *EVP_aead_aes_256_gcm(void); | |
#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) | ||
/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */ | ||
const EVP_AEAD *EVP_aead_chacha20_poly1305(void); | ||
/* EVP_aead_xchacha20_poly1305 is XChaCha20 with a Poly1305 authenticator. */ | ||
const EVP_AEAD *EVP_aead_xchacha20_poly1305(void); | ||
#endif | ||
|
||
/* EVP_AEAD_key_length returns the length of the keys used. */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.