@@ -2790,6 +2790,10 @@ void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
2790
2790
}
2791
2791
2792
2792
2793
+ static bool IsValidGCMTagLength (unsigned int tag_len) {
2794
+ return tag_len == 4 || tag_len == 8 || tag_len >= 12 && tag_len <= 16 ;
2795
+ }
2796
+
2793
2797
bool CipherBase::InitAuthenticated (const char *cipher_type, int iv_len,
2794
2798
int auth_tag_len) {
2795
2799
CHECK (IsAuthenticatedMode ());
@@ -2799,7 +2803,8 @@ bool CipherBase::InitAuthenticated(const char *cipher_type, int iv_len,
2799
2803
return false ;
2800
2804
}
2801
2805
2802
- if (EVP_CIPHER_CTX_mode (ctx_) == EVP_CIPH_CCM_MODE) {
2806
+ const int mode = EVP_CIPHER_CTX_mode (ctx_);
2807
+ if (mode == EVP_CIPH_CCM_MODE) {
2803
2808
if (auth_tag_len < 0 ) {
2804
2809
char msg[128 ];
2805
2810
snprintf (msg, sizeof (msg), " authTagLength required for %s" , cipher_type);
@@ -2832,6 +2837,21 @@ bool CipherBase::InitAuthenticated(const char *cipher_type, int iv_len,
2832
2837
} else {
2833
2838
max_message_size_ = INT_MAX;
2834
2839
}
2840
+ } else {
2841
+ CHECK_EQ (mode, EVP_CIPH_GCM_MODE);
2842
+
2843
+ if (auth_tag_len >= 0 ) {
2844
+ if (!IsValidGCMTagLength (auth_tag_len)) {
2845
+ char msg[50 ];
2846
+ snprintf (msg, sizeof (msg),
2847
+ " Invalid GCM authentication tag length: %u" , auth_tag_len);
2848
+ env ()->ThrowError (msg);
2849
+ return false ;
2850
+ }
2851
+
2852
+ // Remember the given authentication tag length for later.
2853
+ auth_tag_len_ = auth_tag_len;
2854
+ }
2835
2855
}
2836
2856
2837
2857
return true ;
@@ -2867,7 +2887,7 @@ void CipherBase::GetAuthTag(const FunctionCallbackInfo<Value>& args) {
2867
2887
// Only callable after Final and if encrypting.
2868
2888
if (cipher->ctx_ != nullptr ||
2869
2889
cipher->kind_ != kCipher ||
2870
- cipher->auth_tag_len_ == 0 ) {
2890
+ cipher->auth_tag_len_ == kNoAuthTagLength ) {
2871
2891
return args.GetReturnValue ().SetUndefined ();
2872
2892
}
2873
2893
@@ -2892,7 +2912,14 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
2892
2912
unsigned int tag_len = Buffer::Length (args[0 ]);
2893
2913
const int mode = EVP_CIPHER_CTX_mode (cipher->ctx_ );
2894
2914
if (mode == EVP_CIPH_GCM_MODE) {
2895
- if (tag_len > 16 || (tag_len < 12 && tag_len != 8 && tag_len != 4 )) {
2915
+ if (cipher->auth_tag_len_ != kNoAuthTagLength &&
2916
+ cipher->auth_tag_len_ != tag_len) {
2917
+ char msg[50 ];
2918
+ snprintf (msg, sizeof (msg),
2919
+ " Invalid GCM authentication tag length: %u" , tag_len);
2920
+ return cipher->env ()->ThrowError (msg);
2921
+ }
2922
+ if (!IsValidGCMTagLength (tag_len)) {
2896
2923
char msg[125 ];
2897
2924
snprintf (msg, sizeof (msg),
2898
2925
" Permitting authentication tag lengths of %u bytes is deprecated. "
@@ -2929,7 +2956,8 @@ bool CipherBase::SetAAD(const char* data, unsigned int len, int plaintext_len) {
2929
2956
if (!CheckCCMMessageLength (plaintext_len))
2930
2957
return false ;
2931
2958
2932
- if (kind_ == kDecipher && !auth_tag_set_ && auth_tag_len_ > 0 ) {
2959
+ if (kind_ == kDecipher && !auth_tag_set_ && auth_tag_len_ > 0 &&
2960
+ auth_tag_len_ != kNoAuthTagLength ) {
2933
2961
if (!EVP_CIPHER_CTX_ctrl (ctx_,
2934
2962
EVP_CTRL_CCM_SET_TAG,
2935
2963
auth_tag_len_,
@@ -2982,7 +3010,7 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
2982
3010
2983
3011
// on first update:
2984
3012
if (kind_ == kDecipher && IsAuthenticatedMode () && auth_tag_len_ > 0 &&
2985
- !auth_tag_set_) {
3013
+ auth_tag_len_ != kNoAuthTagLength && !auth_tag_set_) {
2986
3014
EVP_CIPHER_CTX_ctrl (ctx_,
2987
3015
EVP_CTRL_GCM_SET_TAG,
2988
3016
auth_tag_len_,
0 commit comments