@@ -2661,6 +2661,11 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
2661
2661
cipher->Init (*cipher_type, key_buf, key_buf_len, auth_tag_len);
2662
2662
}
2663
2663
2664
+ static bool IsSupportedAuthenticatedMode (int mode) {
2665
+ return mode == EVP_CIPH_CCM_MODE ||
2666
+ mode == EVP_CIPH_GCM_MODE ||
2667
+ mode == EVP_CIPH_OCB_MODE;
2668
+ }
2664
2669
2665
2670
void CipherBase::InitIv (const char * cipher_type,
2666
2671
const char * key,
@@ -2678,8 +2683,7 @@ void CipherBase::InitIv(const char* cipher_type,
2678
2683
2679
2684
const int expected_iv_len = EVP_CIPHER_iv_length (cipher);
2680
2685
const int mode = EVP_CIPHER_mode (cipher);
2681
- const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == mode);
2682
- const bool is_ccm_mode = (EVP_CIPH_CCM_MODE == mode);
2686
+ const bool is_authenticated_mode = IsSupportedAuthenticatedMode (mode);
2683
2687
const bool has_iv = iv_len >= 0 ;
2684
2688
2685
2689
// Throw if no IV was passed and the cipher requires an IV
@@ -2690,7 +2694,7 @@ void CipherBase::InitIv(const char* cipher_type,
2690
2694
}
2691
2695
2692
2696
// Throw if an IV was passed which does not match the cipher's fixed IV length
2693
- if (!is_gcm_mode && !is_ccm_mode && has_iv && iv_len != expected_iv_len) {
2697
+ if (!is_authenticated_mode && has_iv && iv_len != expected_iv_len) {
2694
2698
return env ()->ThrowError (" Invalid IV length" );
2695
2699
}
2696
2700
@@ -2706,7 +2710,7 @@ void CipherBase::InitIv(const char* cipher_type,
2706
2710
" Failed to initialize cipher" );
2707
2711
}
2708
2712
2709
- if (IsAuthenticatedMode () ) {
2713
+ if (is_authenticated_mode ) {
2710
2714
CHECK (has_iv);
2711
2715
if (!InitAuthenticated (cipher_type, iv_len, auth_tag_len))
2712
2716
return ;
@@ -2781,7 +2785,7 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
2781
2785
}
2782
2786
2783
2787
const int mode = EVP_CIPHER_CTX_mode (ctx_.get ());
2784
- if (mode == EVP_CIPH_CCM_MODE) {
2788
+ if (mode == EVP_CIPH_CCM_MODE || mode == EVP_CIPH_OCB_MODE ) {
2785
2789
if (auth_tag_len == kNoAuthTagLength ) {
2786
2790
char msg[128 ];
2787
2791
snprintf (msg, sizeof (msg), " authTagLength required for %s" , cipher_type);
@@ -2791,27 +2795,29 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
2791
2795
2792
2796
#ifdef NODE_FIPS_MODE
2793
2797
// TODO(tniessen) Support CCM decryption in FIPS mode
2794
- if (kind_ == kDecipher && FIPS_mode ()) {
2798
+ if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher && FIPS_mode ()) {
2795
2799
env ()->ThrowError (" CCM decryption not supported in FIPS mode" );
2796
2800
return false ;
2797
2801
}
2798
2802
#endif
2799
2803
2800
- if (!EVP_CIPHER_CTX_ctrl (ctx_.get (), EVP_CTRL_CCM_SET_TAG, auth_tag_len,
2804
+ // Tell OpenSSL about the desired length.
2805
+ if (!EVP_CIPHER_CTX_ctrl (ctx_.get (), EVP_CTRL_AEAD_SET_TAG, auth_tag_len,
2801
2806
nullptr )) {
2802
2807
env ()->ThrowError (" Invalid authentication tag length" );
2803
2808
return false ;
2804
2809
}
2805
2810
2806
- // When decrypting in CCM mode, this field will be set in setAuthTag().
2807
- if (kind_ == kCipher )
2808
- auth_tag_len_ = auth_tag_len;
2811
+ // Remember the given authentication tag length for later.
2812
+ auth_tag_len_ = auth_tag_len;
2809
2813
2810
- // Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
2811
- CHECK (iv_len >= 7 && iv_len <= 13 );
2812
- max_message_size_ = INT_MAX;
2813
- if (iv_len == 12 ) max_message_size_ = 16777215 ;
2814
- if (iv_len == 13 ) max_message_size_ = 65535 ;
2814
+ if (mode == EVP_CIPH_CCM_MODE) {
2815
+ // Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
2816
+ CHECK (iv_len >= 7 && iv_len <= 13 );
2817
+ max_message_size_ = INT_MAX;
2818
+ if (iv_len == 12 ) max_message_size_ = 16777215 ;
2819
+ if (iv_len == 13 ) max_message_size_ = 65535 ;
2820
+ }
2815
2821
} else {
2816
2822
CHECK_EQ (mode, EVP_CIPH_GCM_MODE);
2817
2823
@@ -2850,7 +2856,7 @@ bool CipherBase::IsAuthenticatedMode() const {
2850
2856
// Check if this cipher operates in an AEAD mode that we support.
2851
2857
CHECK (ctx_);
2852
2858
const int mode = EVP_CIPHER_CTX_mode (ctx_.get ());
2853
- return mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE ;
2859
+ return IsSupportedAuthenticatedMode ( mode) ;
2854
2860
}
2855
2861
2856
2862
@@ -2883,7 +2889,6 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
2883
2889
return args.GetReturnValue ().Set (false );
2884
2890
}
2885
2891
2886
- // Restrict GCM tag lengths according to NIST 800-38d, page 9.
2887
2892
unsigned int tag_len = Buffer::Length (args[0 ]);
2888
2893
const int mode = EVP_CIPHER_CTX_mode (cipher->ctx_ .get ());
2889
2894
if (mode == EVP_CIPH_GCM_MODE) {
@@ -2901,6 +2906,17 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
2901
2906
" Valid GCM tag lengths are 4, 8, 12, 13, 14, 15, 16." , tag_len);
2902
2907
ProcessEmitDeprecationWarning (cipher->env (), msg, " DEP0090" );
2903
2908
}
2909
+ } else if (mode == EVP_CIPH_OCB_MODE) {
2910
+ // At this point, the tag length is already known and must match the
2911
+ // length of the given authentication tag.
2912
+ CHECK (mode == EVP_CIPH_CCM_MODE || mode == EVP_CIPH_OCB_MODE);
2913
+ CHECK_NE (cipher->auth_tag_len_ , kNoAuthTagLength );
2914
+ if (cipher->auth_tag_len_ != tag_len) {
2915
+ char msg[50 ];
2916
+ snprintf (msg, sizeof (msg),
2917
+ " Invalid authentication tag length: %u" , tag_len);
2918
+ return cipher->env ()->ThrowError (msg);
2919
+ }
2904
2920
}
2905
2921
2906
2922
// Note: we don't use std::min() here to work around a header conflict.
@@ -2991,7 +3007,7 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
2991
3007
if (kind_ == kDecipher && IsAuthenticatedMode () && auth_tag_len_ > 0 &&
2992
3008
auth_tag_len_ != kNoAuthTagLength && !auth_tag_set_) {
2993
3009
CHECK (EVP_CIPHER_CTX_ctrl (ctx_.get (),
2994
- EVP_CTRL_GCM_SET_TAG ,
3010
+ EVP_CTRL_AEAD_SET_TAG ,
2995
3011
auth_tag_len_,
2996
3012
reinterpret_cast <unsigned char *>(auth_tag_)));
2997
3013
auth_tag_set_ = true ;
@@ -3104,10 +3120,12 @@ bool CipherBase::Final(unsigned char** out, int* out_len) {
3104
3120
3105
3121
if (ok && kind_ == kCipher && IsAuthenticatedMode ()) {
3106
3122
// In GCM mode, the authentication tag length can be specified in advance,
3107
- // but defaults to 16 bytes when encrypting. In CCM mode, it must always
3108
- // be given by the user.
3109
- if (mode == EVP_CIPH_GCM_MODE && auth_tag_len_ == kNoAuthTagLength )
3123
+ // but defaults to 16 bytes when encrypting. In CCM and OCB mode, it must
3124
+ // always be given by the user.
3125
+ if (auth_tag_len_ == kNoAuthTagLength ) {
3126
+ CHECK (mode == EVP_CIPH_GCM_MODE);
3110
3127
auth_tag_len_ = sizeof (auth_tag_);
3128
+ }
3111
3129
CHECK_EQ (1 , EVP_CIPHER_CTX_ctrl (ctx_.get (), EVP_CTRL_AEAD_GET_TAG,
3112
3130
auth_tag_len_,
3113
3131
reinterpret_cast <unsigned char *>(auth_tag_)));
0 commit comments