Skip to content

Commit f669817

Browse files
chux0519BridgeAR
authored andcommitted
crypto: add support for chacha20-poly1305 for AEAD
openSSL supports AEAD_CHACHA20_POLY1305(rfc7539) since 1.1. PR-URL: #24081Fixes: #24080 Refs: https://tools.ietf.org/html/rfc7539 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 7cc3b93 commit f669817

File tree

4 files changed

+75
-26
lines changed

4 files changed

+75
-26
lines changed

‎doc/api/crypto.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,9 @@ Adversaries][] for details.
13821382
<!-- YAML
13831383
added: v0.1.94
13841384
changes:
1385+
- version: REPLACEME
1386+
pr-url: https://github.com/nodejs/node/pull/24081
1387+
description: The cipher `chacha20-poly1305` is now supported.
13851388
- version: v10.10.0
13861389
pr-url: https://github.com/nodejs/node/pull/21447
13871390
description: Ciphers in OCB mode are now supported.
@@ -1468,6 +1471,9 @@ to create the `Decipher` object.
14681471
<!-- YAML
14691472
added: v0.1.94
14701473
changes:
1474+
- version: REPLACEME
1475+
pr-url: https://github.com/nodejs/node/pull/24081
1476+
description: The cipher `chacha20-poly1305` is now supported.
14711477
- version: v10.10.0
14721478
pr-url: https://github.com/nodejs/node/pull/21447
14731479
description: Ciphers in OCB mode are now supported.

‎src/node_crypto.cc‎

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,12 +2548,21 @@ int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx){
25482548
return1;
25492549
}
25502550

2551-
staticboolIsSupportedAuthenticatedMode(int mode){
2552-
return mode == EVP_CIPH_CCM_MODE ||
2551+
staticboolIsSupportedAuthenticatedMode(const EVP_CIPHER* cipher){
2552+
constint mode = EVP_CIPHER_mode(cipher);
2553+
// Check `chacha20-poly1305` separately, it is also an AEAD cipher,
2554+
// but its mode is 0 which doesn't indicate
2555+
returnEVP_CIPHER_nid(cipher) == NID_chacha20_poly1305 ||
2556+
mode == EVP_CIPH_CCM_MODE ||
25532557
mode == EVP_CIPH_GCM_MODE ||
25542558
IS_OCB_MODE(mode);
25552559
}
25562560

2561+
staticboolIsSupportedAuthenticatedMode(const EVP_CIPHER_CTX* ctx){
2562+
const EVP_CIPHER* cipher = EVP_CIPHER_CTX_cipher(ctx);
2563+
returnIsSupportedAuthenticatedMode(cipher);
2564+
}
2565+
25572566
voidCipherBase::Initialize(Environment* env, Local<Object> target){
25582567
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
25592568

@@ -2601,7 +2610,7 @@ void CipherBase::CommonInit(const char* cipher_type,
26012610
"Failed to initialize cipher");
26022611
}
26032612

2604-
if (IsSupportedAuthenticatedMode(mode)){
2613+
if (IsSupportedAuthenticatedMode(cipher)){
26052614
CHECK_GE(iv_len, 0);
26062615
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
26072616
return;
@@ -2703,8 +2712,7 @@ void CipherBase::InitIv(const char* cipher_type,
27032712
}
27042713

27052714
constint expected_iv_len = EVP_CIPHER_iv_length(cipher);
2706-
constint mode = EVP_CIPHER_mode(cipher);
2707-
constbool is_authenticated_mode = IsSupportedAuthenticatedMode(mode);
2715+
constbool is_authenticated_mode = IsSupportedAuthenticatedMode(cipher);
27082716
constbool has_iv = iv_len >= 0;
27092717

27102718
// Throw if no IV was passed and the cipher requires an IV
@@ -2776,7 +2784,20 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
27762784
}
27772785

27782786
constint mode = EVP_CIPHER_CTX_mode(ctx_.get());
2779-
if (mode == EVP_CIPH_CCM_MODE || IS_OCB_MODE(mode)){
2787+
if (mode == EVP_CIPH_GCM_MODE){
2788+
if (auth_tag_len != kNoAuthTagLength){
2789+
if (!IsValidGCMTagLength(auth_tag_len)){
2790+
char msg[50];
2791+
snprintf(msg, sizeof(msg),
2792+
"Invalid authentication tag length: %u", auth_tag_len);
2793+
env()->ThrowError(msg);
2794+
returnfalse;
2795+
}
2796+
2797+
// Remember the given authentication tag length for later.
2798+
auth_tag_len_ = auth_tag_len;
2799+
}
2800+
} else{
27802801
if (auth_tag_len == kNoAuthTagLength){
27812802
char msg[128];
27822803
snprintf(msg, sizeof(msg), "authTagLength required for %s", cipher_type);
@@ -2809,21 +2830,6 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
28092830
if (iv_len == 12) max_message_size_ = 16777215;
28102831
if (iv_len == 13) max_message_size_ = 65535;
28112832
}
2812-
} else{
2813-
CHECK_EQ(mode, EVP_CIPH_GCM_MODE);
2814-
2815-
if (auth_tag_len != kNoAuthTagLength){
2816-
if (!IsValidGCMTagLength(auth_tag_len)){
2817-
char msg[50];
2818-
snprintf(msg, sizeof(msg),
2819-
"Invalid authentication tag length: %u", auth_tag_len);
2820-
env()->ThrowError(msg);
2821-
returnfalse;
2822-
}
2823-
2824-
// Remember the given authentication tag length for later.
2825-
auth_tag_len_ = auth_tag_len;
2826-
}
28272833
}
28282834

28292835
returntrue;
@@ -2846,8 +2852,7 @@ bool CipherBase::CheckCCMMessageLength(int message_len){
28462852
boolCipherBase::IsAuthenticatedMode() const{
28472853
// Check if this cipher operates in an AEAD mode that we support.
28482854
CHECK(ctx_);
2849-
constint mode = EVP_CIPHER_CTX_mode(ctx_.get());
2850-
returnIsSupportedAuthenticatedMode(mode);
2855+
returnIsSupportedAuthenticatedMode(ctx_.get());
28512856
}
28522857

28532858

@@ -2892,7 +2897,7 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args){
28922897
} else{
28932898
// At this point, the tag length is already known and must match the
28942899
// length of the given authentication tag.
2895-
CHECK(mode == EVP_CIPH_CCM_MODE || IS_OCB_MODE(mode));
2900+
CHECK(IsSupportedAuthenticatedMode(cipher->ctx_.get()));
28962901
CHECK_NE(cipher->auth_tag_len_, kNoAuthTagLength);
28972902
is_valid = cipher->auth_tag_len_ == tag_len;
28982903
}
@@ -3099,7 +3104,7 @@ bool CipherBase::Final(unsigned char** out, int* out_len){
30993104
*out = Malloc<unsignedchar>(
31003105
static_cast<size_t>(EVP_CIPHER_CTX_block_size(ctx_.get())));
31013106

3102-
if (kind_ == kDecipher && IsSupportedAuthenticatedMode(mode)){
3107+
if (kind_ == kDecipher && IsSupportedAuthenticatedMode(ctx_.get())){
31033108
MaybePassAuthTagToOpenSSL();
31043109
}
31053110

‎test/fixtures/aead-vectors.js‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,5 +662,42 @@ module.exports = [
662662
'481529c76b6a',
663663
tag: 'd0c515f4d1cdd4fdac4f02ab',
664664
tampered: true
665+
},
666+
667+
// Test case from rfc7539 section 2.8.2
668+
{algo: 'chacha20-poly1305',
669+
key: '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
670+
iv: '070000004041424344454647',
671+
plain: '4c616469657320616e642047656e746c656d656e206f662074686520636c6173'+
672+
'73206f66202739393a204966204920636f756c64206f6666657220796f75206f'+
673+
'6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73'+
674+
'637265656e20776f756c642062652069742e',
675+
plainIsHex: true,
676+
aad: '50515253c0c1c2c3c4c5c6c7',
677+
ct: 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5'+
678+
'a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e06'+
679+
'0b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa'+
680+
'b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d265'+
681+
'86cec64b6116',
682+
tag: '1ae10b594f09e26a7e902ecbd0600691',
683+
tampered: false
684+
},
685+
686+
{algo: 'chacha20-poly1305',
687+
key: '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
688+
iv: '070000004041424344454647',
689+
plain: '4c616469657320616e642047656e746c656d656e206f662074686520636c6173'+
690+
'73206f66202739393a204966204920636f756c64206f6666657220796f75206f'+
691+
'6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73'+
692+
'637265656e20776f756c642062652069742e',
693+
plainIsHex: true,
694+
aad: '50515253c0c1c2c3c4c5c6c7',
695+
ct: 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5'+
696+
'a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e06'+
697+
'0b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa'+
698+
'b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d265'+
699+
'86cec64b6116',
700+
tag: '1ae10b594f09e26a7e902ecbd0600692',
701+
tampered: true
665702
}
666703
];

‎test/parallel/test-crypto-authenticated.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,10 @@ for (const test of TEST_CASES){
9494

9595
constisCCM=/^aes-(128|192|256)-ccm$/.test(test.algo);
9696
constisOCB=/^aes-(128|192|256)-ocb$/.test(test.algo);
97+
constisChacha20Poly1305=test.algo==='chacha20-poly1305';
9798

9899
letoptions;
99-
if(isCCM||isOCB)
100+
if(isCCM||isOCB||isChacha20Poly1305)
100101
options={authTagLength: test.tag.length/2};
101102

102103
constinputEncoding=test.plainIsHex ? 'hex' : 'ascii';

0 commit comments

Comments
(0)