Skip to content

Commit 6f396de

Browse files
author
John Bland
committed
fix buffer length error by truncating buffer to out_len, add support for stream encryption and decryption
previously all output buffers we're returned as multiples of 16, now they are truncated to the correct length of the original unencrypted buffer. the WolfSSLEncryptionStream and WolfSSLDecryptionStream were implemented, they extend the stream Transform class and transform the data that passes through them using the evp cipher
1 parent 355dee4 commit 6f396de

File tree

8 files changed

+590
-164
lines changed

8 files changed

+590
-164
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/*
2+
build/*
3+
package-lock.json

WolfSSLDecryptor.js

Lines changed: 0 additions & 63 deletions
This file was deleted.

WolfSSLDecryptor.ts

Lines changed: 0 additions & 86 deletions
This file was deleted.

WolfSSLEVP.js

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
"use strict";
2+
var __extends = (this && this.__extends) || (function () {
3+
var extendStatics = function (d, b) {
4+
extendStatics = Object.setPrototypeOf ||
5+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7+
return extendStatics(d, b);
8+
};
9+
return function (d, b) {
10+
if (typeof b !== "function" && b !== null)
11+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12+
extendStatics(d, b);
13+
function __() { this.constructor = d; }
14+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15+
};
16+
})();
17+
exports.__esModule = true;
18+
exports.WolfSSLDecryptionStream = exports.WolfSSLEncryptionStream = exports.WolfSSLDecryptor = exports.WolfSSLEncryptor = void 0;
19+
var wolfcrypt = require('./build/Release/wolfcrypt');
20+
var stream = require('node:stream');
21+
var WolfSSLEVP = /** @class */ (function () {
22+
function WolfSSLEVP() {
23+
this.evp = Buffer.alloc(wolfcrypt.sizeof_EVP_CIPHER_CTX());
24+
this.totalInputLength = 0;
25+
}
26+
/**
27+
* Updates the internal state with data for cipher.
28+
*
29+
* @param data The data that will be added to the cipher.
30+
*
31+
* @returns The result data if possible.
32+
*
33+
* @throws {Error} If the decryption fails.
34+
*
35+
* @remarks This function should be called multiple times.
36+
*/
37+
WolfSSLEVP.prototype.update = function (data) {
38+
this.totalInputLength += data.length;
39+
var outBuffer = Buffer.alloc(this.totalInputLength);
40+
var ret = wolfcrypt.EVP_CipherUpdate(this.evp, outBuffer, data, data.length);
41+
if (ret < 0) {
42+
throw 'Failed to update cipher';
43+
}
44+
if (ret > 0) {
45+
this.totalInputLength -= ret;
46+
return outBuffer.subarray(0, ret);
47+
}
48+
return Buffer.alloc(0);
49+
};
50+
/**
51+
* Finalize the decryption process.
52+
*
53+
* @returns The last block of decrypted data.
54+
*
55+
* @throws {Error} If the decryption fails.
56+
*
57+
* @remarks This function should be called once to finalize the decryption
58+
* process.
59+
*/
60+
WolfSSLEVP.prototype.finalize = function () {
61+
if (this.totalInputLength % 16 != 0) {
62+
this.totalInputLength += (16 - this.totalInputLength % 16);
63+
}
64+
var outBuffer = Buffer.alloc(this.totalInputLength);
65+
this.totalInputLength = 0;
66+
var ret = wolfcrypt.EVP_CipherFinal(this.evp, outBuffer);
67+
if (ret < 0) {
68+
throw 'Failed to finalize cipher';
69+
}
70+
if (ret > 0) {
71+
return outBuffer.subarray(0, ret);
72+
}
73+
return Buffer.alloc(0);
74+
};
75+
return WolfSSLEVP;
76+
}());
77+
var WolfSSLEncryptor = /** @class */ (function (_super) {
78+
__extends(WolfSSLEncryptor, _super);
79+
/**
80+
* Initializes a new instance of the WolfSSLEncryptor class.
81+
*
82+
* @param cipher The cipher name to use.
83+
* @param key The decryption key to use.
84+
* @param iv The initialization vector.
85+
*
86+
* @throws {Error} If cipher is not available or unknown.
87+
* @throws {Error} If the creation of the Decryption object failed.
88+
*/
89+
function WolfSSLEncryptor(cipher, key, iv) {
90+
var _this = _super.call(this) || this;
91+
wolfcrypt.EVP_CipherInit(_this.evp, cipher, key, iv, 1);
92+
return _this;
93+
}
94+
return WolfSSLEncryptor;
95+
}(WolfSSLEVP));
96+
exports.WolfSSLEncryptor = WolfSSLEncryptor;
97+
var WolfSSLDecryptor = /** @class */ (function (_super) {
98+
__extends(WolfSSLDecryptor, _super);
99+
/**
100+
* Initializes a new instance of the WolfSSLDecryptor class.
101+
*
102+
* @param cipher The cipher name to use.
103+
* @param key The decryption key to use.
104+
* @param iv The initialization vector.
105+
*
106+
* @throws {Error} If cipher is not available or unknown.
107+
* @throws {Error} If the creation of the Decryption object failed.
108+
*/
109+
function WolfSSLDecryptor(cipher, key, iv) {
110+
var _this = _super.call(this) || this;
111+
wolfcrypt.EVP_CipherInit(_this.evp, cipher, key, iv, 0);
112+
return _this;
113+
}
114+
return WolfSSLDecryptor;
115+
}(WolfSSLEVP));
116+
exports.WolfSSLDecryptor = WolfSSLDecryptor;
117+
var WolfSSLEncryptionStream = /** @class */ (function (_super) {
118+
__extends(WolfSSLEncryptionStream, _super);
119+
/**
120+
* Initializes a new instance of the WolfSSLEncryptionStream class.
121+
*
122+
* @param cipher The cipher name to use.
123+
* @param key The decryption key to use.
124+
* @param iv The initialization vector.
125+
*
126+
* @throws {Error} If cipher is not available or unknown.
127+
* @throws {Error} If the creation of the Decryption object failed.
128+
*/
129+
function WolfSSLEncryptionStream(cipher, key, iv) {
130+
var _this = _super.call(this) || this;
131+
_this.encryptor = new WolfSSLEncryptor(cipher, key, iv);
132+
return _this;
133+
}
134+
WolfSSLEncryptionStream.prototype._transform = function (chunk, enc, cb) {
135+
var buffer = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, enc);
136+
var ret_buffer = this.encryptor.update(chunk);
137+
if (ret_buffer.length > 0) {
138+
this.push(ret_buffer);
139+
}
140+
cb();
141+
};
142+
WolfSSLEncryptionStream.prototype._flush = function (cb) {
143+
var ret_buffer = this.encryptor.finalize();
144+
if (ret_buffer.length > 0) {
145+
this.push(ret_buffer);
146+
}
147+
cb();
148+
};
149+
return WolfSSLEncryptionStream;
150+
}(stream.Transform));
151+
exports.WolfSSLEncryptionStream = WolfSSLEncryptionStream;
152+
var WolfSSLDecryptionStream = /** @class */ (function (_super) {
153+
__extends(WolfSSLDecryptionStream, _super);
154+
/**
155+
* Initializes a new instance of the WolfSSLEncryptionStream class.
156+
*
157+
* @param cipher The cipher name to use.
158+
* @param key The decryption key to use.
159+
* @param iv The initialization vector.
160+
*
161+
* @throws {Error} If cipher is not available or unknown.
162+
* @throws {Error} If the creation of the Decryption object failed.
163+
*/
164+
function WolfSSLDecryptionStream(cipher, key, iv) {
165+
var _this = _super.call(this) || this;
166+
_this.encryptor = new WolfSSLDecryptor(cipher, key, iv);
167+
return _this;
168+
}
169+
WolfSSLDecryptionStream.prototype._transform = function (chunk, enc, cb) {
170+
var buffer = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, enc);
171+
var ret_buffer = this.encryptor.update(chunk);
172+
if (ret_buffer.length > 0) {
173+
this.push(ret_buffer);
174+
}
175+
cb();
176+
};
177+
WolfSSLDecryptionStream.prototype._flush = function (cb) {
178+
var ret_buffer = this.encryptor.finalize();
179+
if (ret_buffer.length > 0) {
180+
this.push(ret_buffer);
181+
}
182+
cb();
183+
};
184+
return WolfSSLDecryptionStream;
185+
}(stream.Transform));
186+
exports.WolfSSLDecryptionStream = WolfSSLDecryptionStream;

0 commit comments

Comments
 (0)