@@ -427,61 +427,44 @@ bool CipherBase::InitAuthenticated(const char* cipher_type,
427427 return false ;
428428 }
429429
430- if (ctx_.isGcmMode ()) {
431- if (auth_tag_len != kNoAuthTagLength ) {
432- if (!Cipher::IsValidGCMTagLength (auth_tag_len)) {
433- THROW_ERR_CRYPTO_INVALID_AUTH_TAG (
434- env (),
435- " Invalid authentication tag length: %u" ,
436- auth_tag_len);
437- return false ;
438- }
439-
440- // Remember the given authentication tag length for later.
441- auth_tag_len_ = auth_tag_len;
442- }
443- } else {
444- if (auth_tag_len == kNoAuthTagLength ) {
445- // We treat ChaCha20-Poly1305 specially. Like GCM, the authentication tag
446- // length defaults to 16 bytes when encrypting. Unlike GCM, the
447- // authentication tag length also defaults to 16 bytes when decrypting,
448- // whereas GCM would accept any valid authentication tag length.
449- if (ctx_.isChaCha20Poly1305 ()) {
450- auth_tag_len = EVP_CHACHAPOLY_TLS_TAG_LEN;
451- } else {
452- THROW_ERR_CRYPTO_INVALID_AUTH_TAG (
453- env (), " authTagLength required for %s" , cipher_type);
454- return false ;
455- }
456- }
457-
430+ if (ctx_.isCcmMode ()) {
458431 // TODO(tniessen) Support CCM decryption in FIPS mode
459-
460- if (ctx_.isCcmMode () && kind_ == kDecipher && ncrypto::isFipsEnabled ()) {
461- THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION (env (),
462- " CCM encryption not supported in FIPS mode" );
432+ if (kind_ == kDecipher && ncrypto::isFipsEnabled ()) {
433+ THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION (
434+ env (), " CCM encryption not supported in FIPS mode" );
463435 return false ;
464436 }
465437
466- // Tell OpenSSL about the desired length.
467- if (!ctx_.setAeadTagLength (auth_tag_len)) {
438+ // Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
439+ CHECK (iv_len >= 7 && iv_len <= 13 );
440+ max_message_size_ = INT_MAX;
441+ if (iv_len == 12 ) max_message_size_ = 16777215 ;
442+ if (iv_len == 13 ) max_message_size_ = 65535 ;
443+ }
444+
445+ if (auth_tag_len == kNoAuthTagLength ) {
446+ // Both GCM and ChaCha20-Poly1305 have a default tag length of 16 bytes.
447+ // Other modes (CCM, OCB) require an explicit tag length.
448+ if (ctx_.isGcmMode ()) {
449+ auth_tag_len = EVP_GCM_TLS_TAG_LEN;
450+ } else if (ctx_.isChaCha20Poly1305 ()) {
451+ auth_tag_len = EVP_CHACHAPOLY_TLS_TAG_LEN;
452+ } else {
468453 THROW_ERR_CRYPTO_INVALID_AUTH_TAG (
469- env (), " Invalid authentication tag length: %u " , auth_tag_len );
454+ env (), " authTagLength required for %s " , cipher_type );
470455 return false ;
471456 }
472-
473- // Remember the given authentication tag length for later.
474- auth_tag_len_ = auth_tag_len;
475-
476- if (ctx_.isCcmMode ()) {
477- // Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
478- CHECK (iv_len >= 7 && iv_len <= 13 );
479- max_message_size_ = INT_MAX;
480- if (iv_len == 12 ) max_message_size_ = 16777215 ;
481- if (iv_len == 13 ) max_message_size_ = 65535 ;
482- }
457+ } else if ((ctx_.isGcmMode () && !Cipher::IsValidGCMTagLength (auth_tag_len)) ||
458+ (!ctx_.isGcmMode () && !ctx_.setAeadTagLength (auth_tag_len))) {
459+ // GCM authentication tag lengths are restricted according to NIST 800-38d,
460+ // page 9. For other modes, we rely on OpenSSL to validate the length.
461+ THROW_ERR_CRYPTO_INVALID_AUTH_TAG (
462+ env (), " Invalid authentication tag length: %u" , auth_tag_len);
463+ return false ;
483464 }
484465
466+ // Remember the given authentication tag length for later.
467+ auth_tag_len_ = auth_tag_len;
485468 return true ;
486469}
487470
@@ -510,11 +493,11 @@ void CipherBase::GetAuthTag(const FunctionCallbackInfo<Value>& args) {
510493
511494 // Only callable after Final and if encrypting.
512495 if (cipher->ctx_ || cipher->kind_ != kCipher ||
513- cipher->auth_tag_len_ == kNoAuthTagLength ||
514496 cipher->auth_tag_state_ != kAuthTagComputed ) {
515497 return ;
516498 }
517499
500+ CHECK_NE (cipher->auth_tag_len_ , kNoAuthTagLength );
518501 Local<Value> ret;
519502 if (Buffer::Copy (env, cipher->auth_tag_ , cipher->auth_tag_len_ )
520503 .ToLocal (&ret)) {
@@ -540,30 +523,17 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
540523 }
541524 unsigned int tag_len = auth_tag.size ();
542525
543- bool is_valid;
544- if (cipher->ctx_ .isGcmMode ()) {
545- // Restrict GCM tag lengths according to NIST 800-38d, page 9.
546- is_valid = (cipher->auth_tag_len_ == kNoAuthTagLength ||
547- cipher->auth_tag_len_ == tag_len) &&
548- Cipher::IsValidGCMTagLength (tag_len);
549- } else {
550- // At this point, the tag length is already known and must match the
551- // length of the given authentication tag.
552- CHECK_NE (cipher->auth_tag_len_ , kNoAuthTagLength );
553- is_valid = cipher->auth_tag_len_ == tag_len;
554- }
555-
556- // TODO(tniessen): refactor this check.
557- if (!is_valid ||
558- (cipher->ctx_ .isGcmMode () && cipher->auth_tag_len_ == kNoAuthTagLength &&
559- tag_len != EVP_GCM_TLS_TAG_LEN)) {
526+ // Older versions of Node.js did allow setting the auth tag length implicitly
527+ // for GCM mode (see DEP0182). We now require knowledge of the expected tag
528+ // length up front, so it must have been set during initialization.
529+ // The configured tag length must match the length of the given auth tag.
530+ CHECK_NE (cipher->auth_tag_len_ , kNoAuthTagLength );
531+ if (cipher->auth_tag_len_ != tag_len) {
560532 return THROW_ERR_CRYPTO_INVALID_AUTH_TAG (
561533 env, " Invalid authentication tag length: %u" , tag_len);
562534 }
563535
564- cipher->auth_tag_len_ = tag_len;
565536 CHECK_LE (cipher->auth_tag_len_ , ncrypto::Cipher::MAX_AUTH_TAG_LENGTH);
566-
567537 if (!cipher->ctx_ .setAeadTag ({auth_tag.data (), cipher->auth_tag_len_ })) {
568538 return args.GetReturnValue ().Set (false );
569539 }
@@ -772,13 +742,7 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
772742 }
773743
774744 if (ok && kind_ == kCipher && IsAuthenticatedMode ()) {
775- // In GCM mode, the authentication tag length can be specified in advance,
776- // but defaults to 16 bytes when encrypting. In CCM and OCB mode, it must
777- // always be given by the user.
778- if (auth_tag_len_ == kNoAuthTagLength ) {
779- CHECK (ctx_.isGcmMode ());
780- auth_tag_len_ = EVP_GCM_TLS_TAG_LEN;
781- }
745+ CHECK_NE (auth_tag_len_, kNoAuthTagLength );
782746 ok = ctx_.getAeadTag (auth_tag_len_,
783747 reinterpret_cast <unsigned char *>(auth_tag_));
784748 if (ok) {
0 commit comments