Skip to content

Commit 73a21d2

Browse files
author
John Bland
committed
add free method to EVP, add typescript wrapper for Hmac and HmacStream
previously the EVP_CIPHER_CTX was freed only by calling finalize, now a separate free function is available to free it, additionally the evp pointer is set to null when not allocated and an error is thrown when update or finalize are called with a null evp object the typescript wrapper for Hmac is in the same format as the EVP wrapper and also include a stream transformer to hmac the contents of a stream buffer
1 parent ed3bf7c commit 73a21d2

File tree

11 files changed

+604
-71
lines changed

11 files changed

+604
-71
lines changed

WolfSSLEVP.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ var wolfcrypt = require('./build/Release/wolfcrypt');
2020
var stream = require('stream');
2121
var WolfSSLEVP = /** @class */ (function () {
2222
function WolfSSLEVP() {
23+
// actually holds a pointer but nodejs has no pointer type
24+
this.evp = null;
25+
this.totalInputLength = 0;
2326
this.evp = wolfcrypt.EVP_CIPHER_CTX_new();
2427
this.totalInputLength = 0;
2528
}
@@ -35,6 +38,9 @@ var WolfSSLEVP = /** @class */ (function () {
3538
* @remarks This function should be called multiple times.
3639
*/
3740
WolfSSLEVP.prototype.update = function (data) {
41+
if (this.evp == null) {
42+
throw 'Cipher is not allocated';
43+
}
3844
this.totalInputLength += data.length;
3945
var outBuffer = Buffer.alloc(this.totalInputLength);
4046
var ret = wolfcrypt.EVP_CipherUpdate(this.evp, outBuffer, data, data.length);
@@ -58,13 +64,17 @@ var WolfSSLEVP = /** @class */ (function () {
5864
* process.
5965
*/
6066
WolfSSLEVP.prototype.finalize = function () {
67+
if (this.evp == null) {
68+
throw 'Cipher is not allocated';
69+
}
6170
if (this.totalInputLength % 16 != 0) {
6271
this.totalInputLength += (16 - this.totalInputLength % 16);
6372
}
6473
var outBuffer = Buffer.alloc(this.totalInputLength);
6574
this.totalInputLength = 0;
6675
var ret = wolfcrypt.EVP_CipherFinal(this.evp, outBuffer);
6776
wolfcrypt.EVP_CIPHER_CTX_free(this.evp);
77+
this.evp = null;
6878
if (ret < 0) {
6979
throw 'Failed to finalize cipher';
7080
}
@@ -73,6 +83,15 @@ var WolfSSLEVP = /** @class */ (function () {
7383
}
7484
return Buffer.alloc(0);
7585
};
86+
WolfSSLEVP.prototype.free = function () {
87+
if (this.evp != null) {
88+
wolfcrypt.EVP_CIPHER_CTX_free(this.evp);
89+
this.evp = null;
90+
}
91+
else {
92+
throw 'Cipher is not allocated';
93+
}
94+
};
7695
return WolfSSLEVP;
7796
}());
7897
var WolfSSLEncryptor = /** @class */ (function (_super) {

WolfSSLEVP.ts

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
const wolfcrypt = require( './build/Release/wolfcrypt' );
22
const stream = require( 'stream' );
33

4-
class WolfSSLEVP {
5-
protected evp: number
6-
protected totalInputLength: number
4+
class WolfSSLEVP
5+
{
6+
// actually holds a pointer but nodejs has no pointer type
7+
protected evp: number = null
8+
protected totalInputLength: number = 0
79

8-
public constructor() {
10+
public constructor()
11+
{
912
this.evp = wolfcrypt.EVP_CIPHER_CTX_new()
1013
this.totalInputLength = 0
1114
}
@@ -21,7 +24,13 @@ class WolfSSLEVP {
2124
*
2225
* @remarks This function should be called multiple times.
2326
*/
24-
public update(data: Buffer): Buffer {
27+
public update(data: Buffer): Buffer
28+
{
29+
if ( this.evp == null )
30+
{
31+
throw 'Cipher is not allocated'
32+
}
33+
2534
this.totalInputLength += data.length
2635

2736
let outBuffer = Buffer.alloc( this.totalInputLength )
@@ -53,7 +62,13 @@ class WolfSSLEVP {
5362
* @remarks This function should be called once to finalize the decryption
5463
* process.
5564
*/
56-
public finalize(): Buffer {
65+
public finalize(): Buffer
66+
{
67+
if ( this.evp == null )
68+
{
69+
throw 'Cipher is not allocated'
70+
}
71+
5772
if ( this.totalInputLength % 16 != 0 )
5873
{
5974
this.totalInputLength += ( 16 - this.totalInputLength % 16 )
@@ -63,7 +78,9 @@ class WolfSSLEVP {
6378
this.totalInputLength = 0;
6479

6580
let ret = wolfcrypt.EVP_CipherFinal( this.evp, outBuffer )
81+
6682
wolfcrypt.EVP_CIPHER_CTX_free( this.evp )
83+
this.evp = null
6784

6885
if ( ret < 0 )
6986
{
@@ -78,6 +95,19 @@ class WolfSSLEVP {
7895
return Buffer.alloc( 0 )
7996
}
8097

98+
public free()
99+
{
100+
if ( this.evp != null )
101+
{
102+
wolfcrypt.EVP_CIPHER_CTX_free( this.evp )
103+
this.evp = null
104+
}
105+
else
106+
{
107+
throw 'Cipher is not allocated'
108+
}
109+
}
110+
81111
/**
82112
* Enables the FIPS mode.
83113
*/
@@ -90,7 +120,8 @@ class WolfSSLEVP {
90120
*/
91121
}
92122

93-
export class WolfSSLEncryptor extends WolfSSLEVP {
123+
export class WolfSSLEncryptor extends WolfSSLEVP
124+
{
94125
/**
95126
* Initializes a new instance of the WolfSSLEncryptor class.
96127
*
@@ -101,7 +132,8 @@ export class WolfSSLEncryptor extends WolfSSLEVP {
101132
* @throws {Error} If cipher is not available or unknown.
102133
* @throws {Error} If the creation of the Decryption object failed.
103134
*/
104-
public constructor(cipher: string, key: Buffer, iv: Buffer) {
135+
public constructor(cipher: string, key: Buffer, iv: Buffer)
136+
{
105137
super()
106138
wolfcrypt.EVP_CipherInit( this.evp, cipher, key, iv, 1 )
107139
}
@@ -118,13 +150,15 @@ export class WolfSSLDecryptor extends WolfSSLEVP {
118150
* @throws {Error} If cipher is not available or unknown.
119151
* @throws {Error} If the creation of the Decryption object failed.
120152
*/
121-
public constructor(cipher: string, key: Buffer, iv: Buffer) {
153+
public constructor(cipher: string, key: Buffer, iv: Buffer)
154+
{
122155
super()
123156
wolfcrypt.EVP_CipherInit( this.evp, cipher, key, iv, 0 )
124157
}
125158
}
126159

127-
export class WolfSSLEncryptionStream extends stream.Transform {
160+
export class WolfSSLEncryptionStream extends stream.Transform
161+
{
128162
private encryptor: WolfSSLEncryptor
129163
/**
130164
* Initializes a new instance of the WolfSSLEncryptionStream class.
@@ -136,7 +170,8 @@ export class WolfSSLEncryptionStream extends stream.Transform {
136170
* @throws {Error} If cipher is not available or unknown.
137171
* @throws {Error} If the creation of the Decryption object failed.
138172
*/
139-
public constructor(cipher: string, key: Buffer, iv: Buffer) {
173+
public constructor(cipher: string, key: Buffer, iv: Buffer)
174+
{
140175
super()
141176
this.encryptor = new WolfSSLEncryptor( cipher, key, iv )
142177
}
@@ -180,7 +215,8 @@ export class WolfSSLDecryptionStream extends stream.Transform {
180215
* @throws {Error} If cipher is not available or unknown.
181216
* @throws {Error} If the creation of the Decryption object failed.
182217
*/
183-
public constructor(cipher: string, key: Buffer, iv: Buffer) {
218+
public constructor(cipher: string, key: Buffer, iv: Buffer)
219+
{
184220
super()
185221
this.encryptor = new WolfSSLDecryptor( cipher, key, iv )
186222
}

WolfSSLHmac.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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.WolfSSLHmacStream = exports.WolfSSLHmac = void 0;
19+
var wolfcrypt = require('./build/Release/wolfcrypt');
20+
var stream = require('stream');
21+
var WolfSSLHmac = /** @class */ (function () {
22+
function WolfSSLHmac(type, key) {
23+
// actually holds a pointer but nodejs has no pointer type
24+
this.hmac = null;
25+
this.hashType = -1;
26+
this.digestLength = -1;
27+
this.hmac = Buffer.alloc(wolfcrypt.sizeof_Hmac());
28+
this.hashType = wolfcrypt.typeof_Hmac(type);
29+
this.digestLength = wolfcrypt.Hmac_digest_length(this.hashType);
30+
wolfcrypt.wc_HmacSetKey(this.hmac, this.hashType, key, key.length);
31+
}
32+
/**
33+
* Updates the internal state with data for hash.
34+
*
35+
* @param data The data that will be added to the hash.
36+
*
37+
* @throws {Error} If the hash fails.
38+
*
39+
* @remarks This function should be called multiple times.
40+
*/
41+
WolfSSLHmac.prototype.update = function (data) {
42+
if (this.hmac == null) {
43+
throw 'Hmac is not allocated';
44+
}
45+
var ret = wolfcrypt.wc_HmacUpdate(this.hmac, data, data.length);
46+
if (ret != 0) {
47+
throw 'Failed to update hash';
48+
}
49+
};
50+
/**
51+
* Finalize the hmac process.
52+
*
53+
* @returns The digest of the hashed data.
54+
*
55+
* @throws {Error} If the digest fails.
56+
*
57+
* @remarks This function should be called once to finalize the hmac
58+
* process.
59+
*/
60+
WolfSSLHmac.prototype.finalize = function () {
61+
if (this.hmac == null) {
62+
throw 'Hmac is not allocated';
63+
}
64+
var outBuffer = Buffer.alloc(this.digestLength);
65+
var ret = wolfcrypt.wc_HmacFinal(this.hmac, outBuffer);
66+
wolfcrypt.wc_HmacFree(this.hmac);
67+
this.hmac = null;
68+
if (ret != 0) {
69+
throw 'Failed to finalize digest';
70+
}
71+
return outBuffer;
72+
};
73+
WolfSSLHmac.prototype.free = function () {
74+
if (this.hmac != null) {
75+
wolfcrypt.wc_HmacFree(this.hmac);
76+
this.hmac = null;
77+
}
78+
else {
79+
throw 'Hmac is not allocated';
80+
}
81+
};
82+
return WolfSSLHmac;
83+
}());
84+
exports.WolfSSLHmac = WolfSSLHmac;
85+
var WolfSSLHmacStream = /** @class */ (function (_super) {
86+
__extends(WolfSSLHmacStream, _super);
87+
/**
88+
* Initializes a new instance of the WolfSSLEncryptionStream class.
89+
*
90+
* @param cipher The cipher name to use.
91+
* @param key The decryption key to use.
92+
* @param iv The initialization vector.
93+
*
94+
* @throws {Error} If cipher is not available or unknown.
95+
* @throws {Error} If the creation of the Decryption object failed.
96+
*/
97+
function WolfSSLHmacStream(type, key) {
98+
var _this = _super.call(this) || this;
99+
_this.hmac = new WolfSSLHmac(type, key);
100+
return _this;
101+
}
102+
WolfSSLHmacStream.prototype._transform = function (chunk, enc, cb) {
103+
var buffer = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, enc);
104+
this.hmac.update(chunk);
105+
cb();
106+
};
107+
WolfSSLHmacStream.prototype._flush = function (cb) {
108+
var ret_buffer = this.hmac.finalize();
109+
if (ret_buffer.length > 0) {
110+
this.push(ret_buffer);
111+
}
112+
cb();
113+
};
114+
return WolfSSLHmacStream;
115+
}(stream.Transform));
116+
exports.WolfSSLHmacStream = WolfSSLHmacStream;

0 commit comments

Comments
 (0)