crypto: add support for OCB mode for AEAD
PR-URL: https://github.com/nodejs/node/pull/21447 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
b75bde3bc5
commit
b3f459e6cf
@ -249,11 +249,11 @@ added: v1.0.0
|
||||
- `plaintextLength` {number}
|
||||
* Returns: {Cipher} for method chaining.
|
||||
|
||||
When using an authenticated encryption mode (only `GCM` and `CCM` are currently
|
||||
supported), the `cipher.setAAD()` method sets the value used for the
|
||||
When using an authenticated encryption mode (`GCM`, `CCM` and `OCB` are
|
||||
currently supported), the `cipher.setAAD()` method sets the value used for the
|
||||
_additional authenticated data_ (AAD) input parameter.
|
||||
|
||||
The `options` argument is optional for `GCM`. When using `CCM`, the
|
||||
The `options` argument is optional for `GCM` and `OCB`. When using `CCM`, the
|
||||
`plaintextLength` option must be specified and its value must match the length
|
||||
of the plaintext in bytes. See [CCM mode][].
|
||||
|
||||
@ -263,8 +263,8 @@ The `cipher.setAAD()` method must be called before [`cipher.update()`][].
|
||||
<!-- YAML
|
||||
added: v1.0.0
|
||||
-->
|
||||
* Returns: {Buffer} When using an authenticated encryption mode (only `GCM` and
|
||||
`CCM` are currently supported), the `cipher.getAuthTag()` method returns a
|
||||
* Returns: {Buffer} When using an authenticated encryption mode (`GCM`, `CCM`
|
||||
and `OCB` are currently supported), the `cipher.getAuthTag()` method returns a
|
||||
[`Buffer`][] containing the _authentication tag_ that has been computed from
|
||||
the given data.
|
||||
|
||||
@ -412,8 +412,8 @@ changes:
|
||||
- `plaintextLength` {number}
|
||||
* Returns: {Decipher} for method chaining.
|
||||
|
||||
When using an authenticated encryption mode (only `GCM` and `CCM` are currently
|
||||
supported), the `decipher.setAAD()` method sets the value used for the
|
||||
When using an authenticated encryption mode (`GCM`, `CCM` and `OCB` are
|
||||
currently supported), the `decipher.setAAD()` method sets the value used for the
|
||||
_additional authenticated data_ (AAD) input parameter.
|
||||
|
||||
The `options` argument is optional for `GCM`. When using `CCM`, the
|
||||
@ -436,8 +436,8 @@ changes:
|
||||
* `buffer` {Buffer | TypedArray | DataView}
|
||||
* Returns: {Decipher} for method chaining.
|
||||
|
||||
When using an authenticated encryption mode (only `GCM` and `CCM` are currently
|
||||
supported), the `decipher.setAuthTag()` method is used to pass in the
|
||||
When using an authenticated encryption mode (`GCM`, `CCM` and `OCB` are
|
||||
currently supported), the `decipher.setAuthTag()` method is used to pass in the
|
||||
received _authentication tag_. If no tag is provided, or if the cipher text
|
||||
has been tampered with, [`decipher.final()`][] will throw, indicating that the
|
||||
cipher text should be discarded due to failed authentication. If the tag length
|
||||
@ -1321,6 +1321,9 @@ This property is deprecated. Please use `crypto.setFips()` and
|
||||
added: v0.1.94
|
||||
deprecated: v10.0.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/21447
|
||||
description: Ciphers in OCB mode are now supported.
|
||||
- version: v10.2.0
|
||||
pr-url: https://github.com/nodejs/node/pull/20235
|
||||
description: The `authTagLength` option can now be used to produce shorter
|
||||
@ -1338,7 +1341,7 @@ Creates and returns a `Cipher` object that uses the given `algorithm` and
|
||||
`password`.
|
||||
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength`
|
||||
option is not required but can be used to set the length of the authentication
|
||||
@ -1373,6 +1376,9 @@ Adversaries][] for details.
|
||||
<!-- YAML
|
||||
added: v0.1.94
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/21447
|
||||
description: Ciphers in OCB mode are now supported.
|
||||
- version: v10.2.0
|
||||
pr-url: https://github.com/nodejs/node/pull/20235
|
||||
description: The `authTagLength` option can now be used to produce shorter
|
||||
@ -1392,7 +1398,7 @@ Creates and returns a `Cipher` object, with the given `algorithm`, `key` and
|
||||
initialization vector (`iv`).
|
||||
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength`
|
||||
option is not required but can be used to set the length of the authentication
|
||||
@ -1419,6 +1425,10 @@ of time what a given IV will be.
|
||||
<!-- YAML
|
||||
added: v0.1.94
|
||||
deprecated: v10.0.0
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/21447
|
||||
description: Ciphers in OCB mode are now supported.
|
||||
-->
|
||||
|
||||
> Stability: 0 - Deprecated: Use [`crypto.createDecipheriv()`][] instead.
|
||||
@ -1432,7 +1442,7 @@ Creates and returns a `Decipher` object that uses the given `algorithm` and
|
||||
`password` (key).
|
||||
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][].
|
||||
|
||||
@ -1452,6 +1462,9 @@ to create the `Decipher` object.
|
||||
<!-- YAML
|
||||
added: v0.1.94
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/21447
|
||||
description: Ciphers in OCB mode are now supported.
|
||||
- version: v10.2.0
|
||||
pr-url: https://github.com/nodejs/node/pull/20039
|
||||
description: The `authTagLength` option can now be used to restrict accepted
|
||||
@ -1471,7 +1484,7 @@ Creates and returns a `Decipher` object that uses the given `algorithm`, `key`
|
||||
and initialization vector (`iv`).
|
||||
|
||||
The `options` argument controls stream behavior and is optional except when a
|
||||
cipher in CCM mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the
|
||||
`authTagLength` option is required and specifies the length of the
|
||||
authentication tag in bytes, see [CCM mode][]. In GCM mode, the `authTagLength`
|
||||
option is not required but can be used to restrict accepted authentication tags
|
||||
@ -2321,7 +2334,7 @@ See the reference for other recommendations and details.
|
||||
|
||||
### CCM mode
|
||||
|
||||
CCM is one of the two supported [AEAD algorithms][]. Applications which use this
|
||||
CCM is one of the supported [AEAD algorithms][]. Applications which use this
|
||||
mode must adhere to certain restrictions when using the cipher API:
|
||||
|
||||
- The authentication tag length must be specified during cipher creation by
|
||||
|
@ -2683,6 +2683,11 @@ void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
|
||||
cipher->Init(*cipher_type, key_buf, key_buf_len, auth_tag_len);
|
||||
}
|
||||
|
||||
static bool IsSupportedAuthenticatedMode(int mode) {
|
||||
return mode == EVP_CIPH_CCM_MODE ||
|
||||
mode == EVP_CIPH_GCM_MODE ||
|
||||
mode == EVP_CIPH_OCB_MODE;
|
||||
}
|
||||
|
||||
void CipherBase::InitIv(const char* cipher_type,
|
||||
const char* key,
|
||||
@ -2700,8 +2705,7 @@ void CipherBase::InitIv(const char* cipher_type,
|
||||
|
||||
const int expected_iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
const int mode = EVP_CIPHER_mode(cipher);
|
||||
const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == mode);
|
||||
const bool is_ccm_mode = (EVP_CIPH_CCM_MODE == mode);
|
||||
const bool is_authenticated_mode = IsSupportedAuthenticatedMode(mode);
|
||||
const bool has_iv = iv_len >= 0;
|
||||
|
||||
// Throw if no IV was passed and the cipher requires an IV
|
||||
@ -2712,7 +2716,7 @@ void CipherBase::InitIv(const char* cipher_type,
|
||||
}
|
||||
|
||||
// Throw if an IV was passed which does not match the cipher's fixed IV length
|
||||
if (!is_gcm_mode && !is_ccm_mode && has_iv && iv_len != expected_iv_len) {
|
||||
if (!is_authenticated_mode && has_iv && iv_len != expected_iv_len) {
|
||||
return env()->ThrowError("Invalid IV length");
|
||||
}
|
||||
|
||||
@ -2728,7 +2732,7 @@ void CipherBase::InitIv(const char* cipher_type,
|
||||
"Failed to initialize cipher");
|
||||
}
|
||||
|
||||
if (IsAuthenticatedMode()) {
|
||||
if (is_authenticated_mode) {
|
||||
CHECK(has_iv);
|
||||
if (!InitAuthenticated(cipher_type, iv_len, auth_tag_len))
|
||||
return;
|
||||
@ -2803,7 +2807,7 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
|
||||
}
|
||||
|
||||
const int mode = EVP_CIPHER_CTX_mode(ctx_.get());
|
||||
if (mode == EVP_CIPH_CCM_MODE) {
|
||||
if (mode == EVP_CIPH_CCM_MODE || mode == EVP_CIPH_OCB_MODE) {
|
||||
if (auth_tag_len == kNoAuthTagLength) {
|
||||
char msg[128];
|
||||
snprintf(msg, sizeof(msg), "authTagLength required for %s", cipher_type);
|
||||
@ -2813,25 +2817,29 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
|
||||
|
||||
#ifdef NODE_FIPS_MODE
|
||||
// TODO(tniessen) Support CCM decryption in FIPS mode
|
||||
if (kind_ == kDecipher && FIPS_mode()) {
|
||||
if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher && FIPS_mode()) {
|
||||
env()->ThrowError("CCM decryption not supported in FIPS mode");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_CCM_SET_TAG, auth_tag_len,
|
||||
// Tell OpenSSL about the desired length.
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, auth_tag_len,
|
||||
nullptr)) {
|
||||
env()->ThrowError("Invalid authentication tag length");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember the given authentication tag length for later.
|
||||
auth_tag_len_ = auth_tag_len;
|
||||
|
||||
// Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
|
||||
CHECK(iv_len >= 7 && iv_len <= 13);
|
||||
max_message_size_ = INT_MAX;
|
||||
if (iv_len == 12) max_message_size_ = 16777215;
|
||||
if (iv_len == 13) max_message_size_ = 65535;
|
||||
if (mode == EVP_CIPH_CCM_MODE) {
|
||||
// Restrict the message length to min(INT_MAX, 2^(8*(15-iv_len))-1) bytes.
|
||||
CHECK(iv_len >= 7 && iv_len <= 13);
|
||||
max_message_size_ = INT_MAX;
|
||||
if (iv_len == 12) max_message_size_ = 16777215;
|
||||
if (iv_len == 13) max_message_size_ = 65535;
|
||||
}
|
||||
} else {
|
||||
CHECK_EQ(mode, EVP_CIPH_GCM_MODE);
|
||||
|
||||
@ -2870,7 +2878,7 @@ bool CipherBase::IsAuthenticatedMode() const {
|
||||
// Check if this cipher operates in an AEAD mode that we support.
|
||||
CHECK(ctx_);
|
||||
const int mode = EVP_CIPHER_CTX_mode(ctx_.get());
|
||||
return mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE;
|
||||
return IsSupportedAuthenticatedMode(mode);
|
||||
}
|
||||
|
||||
|
||||
@ -2903,16 +2911,18 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) {
|
||||
return args.GetReturnValue().Set(false);
|
||||
}
|
||||
|
||||
// Restrict GCM tag lengths according to NIST 800-38d, page 9.
|
||||
unsigned int tag_len = Buffer::Length(args[0]);
|
||||
const int mode = EVP_CIPHER_CTX_mode(cipher->ctx_.get());
|
||||
bool is_valid;
|
||||
if (mode == EVP_CIPH_GCM_MODE) {
|
||||
// Restrict GCM tag lengths according to NIST 800-38d, page 9.
|
||||
is_valid = (cipher->auth_tag_len_ == kNoAuthTagLength ||
|
||||
cipher->auth_tag_len_ == tag_len) &&
|
||||
IsValidGCMTagLength(tag_len);
|
||||
} else {
|
||||
CHECK_EQ(mode, EVP_CIPH_CCM_MODE);
|
||||
// At this point, the tag length is already known and must match the
|
||||
// length of the given authentication tag.
|
||||
CHECK(mode == EVP_CIPH_CCM_MODE || mode == EVP_CIPH_OCB_MODE);
|
||||
CHECK_NE(cipher->auth_tag_len_, kNoAuthTagLength);
|
||||
is_valid = cipher->auth_tag_len_ == tag_len;
|
||||
}
|
||||
@ -3008,7 +3018,7 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
|
||||
if (kind_ == kDecipher && IsAuthenticatedMode() && auth_tag_len_ > 0 &&
|
||||
auth_tag_len_ != kNoAuthTagLength && !auth_tag_set_) {
|
||||
CHECK(EVP_CIPHER_CTX_ctrl(ctx_.get(),
|
||||
EVP_CTRL_GCM_SET_TAG,
|
||||
EVP_CTRL_AEAD_SET_TAG,
|
||||
auth_tag_len_,
|
||||
reinterpret_cast<unsigned char*>(auth_tag_)));
|
||||
auth_tag_set_ = true;
|
||||
@ -3121,10 +3131,12 @@ bool CipherBase::Final(unsigned char** out, int* out_len) {
|
||||
|
||||
if (ok && kind_ == kCipher && IsAuthenticatedMode()) {
|
||||
// In GCM mode, the authentication tag length can be specified in advance,
|
||||
// but defaults to 16 bytes when encrypting. In CCM mode, it must always
|
||||
// be given by the user.
|
||||
if (mode == EVP_CIPH_GCM_MODE && auth_tag_len_ == kNoAuthTagLength)
|
||||
// but defaults to 16 bytes when encrypting. In CCM and OCB mode, it must
|
||||
// always be given by the user.
|
||||
if (auth_tag_len_ == kNoAuthTagLength) {
|
||||
CHECK(mode == EVP_CIPH_GCM_MODE);
|
||||
auth_tag_len_ = sizeof(auth_tag_);
|
||||
}
|
||||
CHECK_EQ(1, EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_GET_TAG,
|
||||
auth_tag_len_,
|
||||
reinterpret_cast<unsigned char*>(auth_tag_)));
|
||||
|
@ -499,6 +499,207 @@ const TEST_CASES = [
|
||||
tag: '65a6002b2cdfe9f00027f839332ca6fc',
|
||||
tampered: false
|
||||
},
|
||||
|
||||
// OCB test cases from RFC7253
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221100',
|
||||
plain: '',
|
||||
ct: '',
|
||||
tag: '785407bfffc8ad9edcc5520ac9111ee6'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221101',
|
||||
plain: '0001020304050607',
|
||||
plainIsHex: true,
|
||||
aad: '0001020304050607',
|
||||
ct: '6820b3657b6f615a',
|
||||
tag: '5725bda0d3b4eb3a257c9af1f8f03009'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221102',
|
||||
plain: '',
|
||||
aad: '0001020304050607',
|
||||
ct: '',
|
||||
tag: '81017f8203f081277152fade694a0a00'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221103',
|
||||
plain: '0001020304050607',
|
||||
plainIsHex: true,
|
||||
ct: '45dd69f8f5aae724',
|
||||
tag: '14054cd1f35d82760b2cd00d2f99bfa9'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221104',
|
||||
plain: '000102030405060708090a0b0c0d0e0f',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f',
|
||||
ct: '571d535b60b277188be5147170a9a22c',
|
||||
tag: '3ad7a4ff3835b8c5701c1ccec8fc3358'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221105',
|
||||
plain: '',
|
||||
aad: '000102030405060708090a0b0c0d0e0f',
|
||||
ct: '',
|
||||
tag: '8cf761b6902ef764462ad86498ca6b97'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221106',
|
||||
plain: '000102030405060708090a0b0c0d0e0f',
|
||||
plainIsHex: true,
|
||||
ct: '5ce88ec2e0692706a915c00aeb8b2396',
|
||||
tag: 'f40e1c743f52436bdf06d8fa1eca343d'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221107',
|
||||
plain: '000102030405060708090a0b0c0d0e0f1011121314151617',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f1011121314151617',
|
||||
ct: '1ca2207308c87c010756104d8840ce1952f09673a448a122',
|
||||
tag: 'c92c62241051f57356d7f3c90bb0e07f'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221108',
|
||||
plain: '',
|
||||
aad: '000102030405060708090a0b0c0d0e0f1011121314151617',
|
||||
ct: '',
|
||||
tag: '6dc225a071fc1b9f7c69f93b0f1e10de'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa99887766554433221109',
|
||||
plain: '000102030405060708090a0b0c0d0e0f1011121314151617',
|
||||
plainIsHex: true,
|
||||
ct: '221bd0de7fa6fe993eccd769460a0af2d6cded0c395b1c3c',
|
||||
tag: 'e725f32494b9f914d85c0b1eb38357ff'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110a',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
ct: 'bd6f6c496201c69296c11efd138a467abd3c707924b964deaffc40319af5a485',
|
||||
tag: '40fbba186c5553c68ad9f592a79a4240'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110b',
|
||||
plain: '',
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
ct: '',
|
||||
tag: 'fe80690bee8a485d11f32965bc9d2a32'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110c',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
plainIsHex: true,
|
||||
ct: '2942bfc773bda23cabc6acfd9bfd5835bd300f0973792ef46040c53f1432bcdf',
|
||||
tag: 'b5e1dde3bc18a5f840b52e653444d5df'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110d',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' +
|
||||
'2021222324252627',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20' +
|
||||
'21222324252627',
|
||||
ct: 'd5ca91748410c1751ff8a2f618255b68a0a12e093ff454606e59f9c1d0ddc54b65e8' +
|
||||
'628e568bad7a',
|
||||
tag: 'ed07ba06a4a69483a7035490c5769e60'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110e',
|
||||
plain: '',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20' +
|
||||
'21222324252627',
|
||||
ct: '',
|
||||
tag: 'c5cd9d1850c141e358649994ee701b68'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '000102030405060708090a0b0c0d0e0f',
|
||||
iv: 'bbaa9988776655443322110f',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' +
|
||||
'2021222324252627',
|
||||
plainIsHex: true,
|
||||
ct: '4412923493c57d5de0d700f753cce0d1d2d95060122e9f15a5ddbfc5787e50b5cc55' +
|
||||
'ee507bcb084e',
|
||||
tag: '479ad363ac366b95a98ca5f3000b1479'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '0f0e0d0c0b0a09080706050403020100',
|
||||
iv: 'bbaa9988776655443322110d',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' +
|
||||
'2021222324252627',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20' +
|
||||
'21222324252627',
|
||||
ct: '1792a4e31e0755fb03e31b22116e6c2ddf9efd6e33d536f1a0124b0a55bae884ed93' +
|
||||
'481529c76b6a',
|
||||
tag: 'd0c515f4d1cdd4fdac4f02aa'
|
||||
},
|
||||
|
||||
{
|
||||
algo: 'aes-128-ocb',
|
||||
key: '0f0e0d0c0b0a09080706050403020100',
|
||||
iv: 'bbaa9988776655443322110d',
|
||||
plain: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' +
|
||||
'2021222324252627',
|
||||
plainIsHex: true,
|
||||
aad: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20' +
|
||||
'21222324252627',
|
||||
ct: '1792a4e31e0755fb03e31b22116e6c2ddf9efd6e33d536f1a0124b0a55bae884ed93' +
|
||||
'481529c76b6a',
|
||||
tag: 'd0c515f4d1cdd4fdac4f02ab',
|
||||
tampered: true
|
||||
}
|
||||
];
|
||||
|
||||
const errMessages = {
|
||||
@ -554,9 +755,10 @@ for (const test of TEST_CASES) {
|
||||
}
|
||||
|
||||
const isCCM = /^aes-(128|192|256)-ccm$/.test(test.algo);
|
||||
const isOCB = /^aes-(128|192|256)-ocb$/.test(test.algo);
|
||||
|
||||
let options;
|
||||
if (isCCM)
|
||||
if (isCCM || isOCB)
|
||||
options = { authTagLength: test.tag.length / 2 };
|
||||
|
||||
const inputEncoding = test.plainIsHex ? 'hex' : 'ascii';
|
||||
@ -881,30 +1083,40 @@ for (const test of TEST_CASES) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that create(De|C)ipher(iv)? throws if the mode is CCM and no
|
||||
// Test that create(De|C)ipher(iv)? throws if the mode is CCM or OCB and no
|
||||
// authentication tag has been specified.
|
||||
{
|
||||
assert.throws(() => {
|
||||
crypto.createCipheriv('aes-256-ccm',
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6S');
|
||||
}, /^Error: authTagLength required for aes-256-ccm$/);
|
||||
|
||||
// CCM decryption and create(De|C)ipher are unsupported in FIPS mode.
|
||||
if (!common.hasFipsCrypto) {
|
||||
for (const mode of ['ccm', 'ocb']) {
|
||||
assert.throws(() => {
|
||||
crypto.createDecipheriv('aes-256-ccm',
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6S');
|
||||
}, /^Error: authTagLength required for aes-256-ccm$/);
|
||||
crypto.createCipheriv(`aes-256-${mode}`,
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6S');
|
||||
}, {
|
||||
message: `authTagLength required for aes-256-${mode}`
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
crypto.createCipher('aes-256-ccm', 'very bad password');
|
||||
}, /^Error: authTagLength required for aes-256-ccm$/);
|
||||
// CCM decryption and create(De|C)ipher are unsupported in FIPS mode.
|
||||
if (!common.hasFipsCrypto) {
|
||||
assert.throws(() => {
|
||||
crypto.createDecipheriv(`aes-256-${mode}`,
|
||||
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
|
||||
'qkuZpJWCewa6S');
|
||||
}, {
|
||||
message: `authTagLength required for aes-256-${mode}`
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
crypto.createDecipher('aes-256-ccm', 'very bad password');
|
||||
}, /^Error: authTagLength required for aes-256-ccm$/);
|
||||
assert.throws(() => {
|
||||
crypto.createCipher(`aes-256-${mode}`, 'very bad password');
|
||||
}, {
|
||||
message: `authTagLength required for aes-256-${mode}`
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
crypto.createDecipher(`aes-256-${mode}`, 'very bad password');
|
||||
}, {
|
||||
message: `authTagLength required for aes-256-${mode}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user