Skip to content

Commit cf9d686

Browse files
XadillaXdanielleadams
authored andcommitted
crypto: fix aes crash when tag length too small
Fixes: #38883 PR-URL: #38914 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent c6aa685 commit cf9d686

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/internal/crypto/aes.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const {
4545
kKeyObject,
4646
} = require('internal/crypto/util');
4747

48+
const { PromiseReject } = primordials;
49+
4850
const {
4951
codes: {
5052
ERR_INVALID_ARG_TYPE,
@@ -167,9 +169,9 @@ function asyncAesGcmCipher(
167169
data,
168170
{ iv, additionalData, tagLength = 128 }) {
169171
if (!ArrayPrototypeIncludes(kTagLengths, tagLength)) {
170-
throw lazyDOMException(
172+
return PromiseReject(lazyDOMException(
171173
`${tagLength} is not a valid AES-GCM tag length`,
172-
'OperationError');
174+
'OperationError'));
173175
}
174176

175177
iv = getArrayBufferOrView(iv, 'algorithm.iv');
@@ -188,6 +190,17 @@ function asyncAesGcmCipher(
188190
const slice = ArrayBufferIsView(data) ?
189191
TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice;
190192
tag = slice(data, -tagByteLength);
193+
194+
// Refs: https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations
195+
//
196+
// > If *plaintext* has a length less than *tagLength* bits, then `throw`
197+
// > an `OperationError`.
198+
if (tagByteLength > tag.byteLength) {
199+
return PromiseReject(lazyDOMException(
200+
'The provided data is too small.',
201+
'OperationError'));
202+
}
203+
191204
data = slice(data, 0, -tagByteLength);
192205
break;
193206
case kWebCryptoCipherEncrypt:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
if (!common.hasCrypto)
6+
common.skip('missing crypto');
7+
8+
const assert = require('assert');
9+
const crypto = require('crypto').webcrypto;
10+
11+
crypto.subtle.importKey(
12+
'raw',
13+
new Uint8Array(32),
14+
{
15+
name: 'AES-GCM'
16+
},
17+
false,
18+
[ 'encrypt', 'decrypt' ])
19+
.then((k) => {
20+
assert.rejects(() => {
21+
return crypto.subtle.decrypt({
22+
name: 'AES-GCM',
23+
iv: new Uint8Array(12),
24+
}, k, new Uint8Array(0));
25+
}, {
26+
name: 'OperationError',
27+
message: /The provided data is too small/,
28+
});
29+
});

0 commit comments

Comments
 (0)