@@ -2661,6 +2661,11 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
26612661 cipher->Init (*cipher_type, key_buf, key_buf_len, auth_tag_len);
26622662}
26632663
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+ }
26642669
26652670void CipherBase::InitIv (const char * cipher_type,
26662671 const char * key,
@@ -2678,8 +2683,7 @@ void CipherBase::InitIv(const char* cipher_type,
26782683
26792684 const int expected_iv_len = EVP_CIPHER_iv_length (cipher);
26802685 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);
26832687 const bool has_iv = iv_len >= 0 ;
26842688
26852689 // Throw if no IV was passed and the cipher requires an IV
@@ -2690,7 +2694,7 @@ void CipherBase::InitIv(const char* cipher_type,
26902694 }
26912695
26922696 // 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) {
26942698 return env ()->ThrowError (" Invalid IV length" );
26952699 }
26962700
@@ -2706,7 +2710,7 @@ void CipherBase::InitIv(const char* cipher_type,
27062710 " Failed to initialize cipher" );
27072711 }
27082712
2709- if (IsAuthenticatedMode () ) {
2713+ if (is_authenticated_mode ) {
27102714 CHECK (has_iv);
27112715 if (!InitAuthenticated (cipher_type, iv_len, auth_tag_len))
27122716 return ;
@@ -2781,7 +2785,7 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
27812785 }
27822786
27832787 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 ) {
27852789 if (auth_tag_len == kNoAuthTagLength ) {
27862790 char msg[128 ];
27872791 snprintf (msg, sizeof (msg), " authTagLength required for %s" , cipher_type);
@@ -2791,27 +2795,29 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
27912795
27922796#ifdef NODE_FIPS_MODE
27932797 // 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 ()) {
27952799 env ()->ThrowError (" CCM decryption not supported in FIPS mode" );
27962800 return false ;
27972801 }
27982802#endif
27992803
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,
28012806 nullptr )) {
28022807 env ()->ThrowError (" Invalid authentication tag length" );
28032808 return false ;
28042809 }
28052810
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;
28092813
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+ }
28152821 } else {
28162822 CHECK_EQ (mode, EVP_CIPH_GCM_MODE);
28172823
@@ -2850,7 +2856,7 @@ bool CipherBase::IsAuthenticatedMode() const {
28502856 // Check if this cipher operates in an AEAD mode that we support.
28512857 CHECK (ctx_);
28522858 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) ;
28542860}
28552861
28562862
@@ -2883,7 +2889,6 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
28832889 return args.GetReturnValue ().Set (false );
28842890 }
28852891
2886- // Restrict GCM tag lengths according to NIST 800-38d, page 9.
28872892 unsigned int tag_len = Buffer::Length (args[0 ]);
28882893 const int mode = EVP_CIPHER_CTX_mode (cipher->ctx_ .get ());
28892894 if (mode == EVP_CIPH_GCM_MODE) {
@@ -2901,6 +2906,17 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
29012906 " Valid GCM tag lengths are 4, 8, 12, 13, 14, 15, 16." , tag_len);
29022907 ProcessEmitDeprecationWarning (cipher->env (), msg, " DEP0090" );
29032908 }
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+ }
29042920 }
29052921
29062922 // 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,
29913007 if (kind_ == kDecipher && IsAuthenticatedMode () && auth_tag_len_ > 0 &&
29923008 auth_tag_len_ != kNoAuthTagLength && !auth_tag_set_) {
29933009 CHECK (EVP_CIPHER_CTX_ctrl (ctx_.get (),
2994- EVP_CTRL_GCM_SET_TAG ,
3010+ EVP_CTRL_AEAD_SET_TAG ,
29953011 auth_tag_len_,
29963012 reinterpret_cast <unsigned char *>(auth_tag_)));
29973013 auth_tag_set_ = true ;
@@ -3104,10 +3120,12 @@ bool CipherBase::Final(unsigned char** out, int* out_len) {
31043120
31053121 if (ok && kind_ == kCipher && IsAuthenticatedMode ()) {
31063122 // 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);
31103127 auth_tag_len_ = sizeof (auth_tag_);
3128+ }
31113129 CHECK_EQ (1 , EVP_CIPHER_CTX_ctrl (ctx_.get (), EVP_CTRL_AEAD_GET_TAG,
31123130 auth_tag_len_,
31133131 reinterpret_cast <unsigned char *>(auth_tag_)));
0 commit comments