Skip to content

Commit

Permalink
crypto: fix aes crash when tag length too small
Browse files Browse the repository at this point in the history
Fixes: #38883

PR-URL: #38914
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
XadillaX authored and danielleadams committed Jun 21, 2021
1 parent c6aa685 commit cf9d686
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
17 changes: 15 additions & 2 deletions lib/internal/crypto/aes.js
Expand Up @@ -45,6 +45,8 @@ const {
kKeyObject,
} = require('internal/crypto/util');

const { PromiseReject } = primordials;

const {
codes: {
ERR_INVALID_ARG_TYPE,
Expand Down Expand Up @@ -167,9 +169,9 @@ function asyncAesGcmCipher(
data,
{ iv, additionalData, tagLength = 128 }) {
if (!ArrayPrototypeIncludes(kTagLengths, tagLength)) {
throw lazyDOMException(
return PromiseReject(lazyDOMException(
`${tagLength} is not a valid AES-GCM tag length`,
'OperationError');
'OperationError'));
}

iv = getArrayBufferOrView(iv, 'algorithm.iv');
Expand All @@ -188,6 +190,17 @@ function asyncAesGcmCipher(
const slice = ArrayBufferIsView(data) ?
TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice;
tag = slice(data, -tagByteLength);

// Refs: https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations
//
// > If *plaintext* has a length less than *tagLength* bits, then `throw`
// > an `OperationError`.
if (tagByteLength > tag.byteLength) {
return PromiseReject(lazyDOMException(
'The provided data is too small.',
'OperationError'));
}

data = slice(data, 0, -tagByteLength);
break;
case kWebCryptoCipherEncrypt:
Expand Down
29 changes: 29 additions & 0 deletions test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js
@@ -0,0 +1,29 @@
'use strict';

const common = require('../common');

if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const crypto = require('crypto').webcrypto;

crypto.subtle.importKey(
'raw',
new Uint8Array(32),
{
name: 'AES-GCM'
},
false,
[ 'encrypt', 'decrypt' ])
.then((k) => {
assert.rejects(() => {
return crypto.subtle.decrypt({
name: 'AES-GCM',
iv: new Uint8Array(12),
}, k, new Uint8Array(0));
}, {
name: 'OperationError',
message: /The provided data is too small/,
});
});

0 comments on commit cf9d686

Please sign in to comment.