node-ikev2 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,470 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transform = exports.transformTypeMap = exports.esnId = exports.dhId = exports.integId = exports.prfId = exports.encrId = exports.transformType = void 0;
4
+ const attribute_1 = require("./attribute");
5
+ /**
6
+ * Transform Substructure
7
+
8
+ 1 2 3
9
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11
+ ! 0 (last) or 3 ! RESERVED ! Transform Length !
12
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ !Transform Type ! RESERVED ! Transform ID !
14
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ ! !
16
+ ~ Transform Attributes ~
17
+ ! !
18
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+
20
+ Transform Substructure
21
+ */
22
+ /**
23
+ * Transform Type Values: \
24
+ RESERVED 0 \
25
+ Encryption Algorithm (ENCR) 1 (IKE and ESP) \
26
+ Pseudo-random Function (PRF) 2 (IKE) \
27
+ Integrity Algorithm (INTEG) 3 (IKE, AH, optional in ESP) \
28
+ Diffie-Hellman Group (D-H) 4 (IKE, optional in AH & ESP) \
29
+ Extended Sequence Numbers (ESN) 5 (AH and ESP)
30
+ */
31
+ var transformType;
32
+ (function (transformType) {
33
+ transformType[transformType["Encryption_Algorithm_ENCR"] = 1] = "Encryption_Algorithm_ENCR";
34
+ transformType[transformType["Pseudo_Random_PRF"] = 2] = "Pseudo_Random_PRF";
35
+ transformType[transformType["Integrity_Algorithm_INTEG"] = 3] = "Integrity_Algorithm_INTEG";
36
+ transformType[transformType["Diffie_Hellman_Group_DH"] = 4] = "Diffie_Hellman_Group_DH";
37
+ transformType[transformType["Extended_Sequence_Numbers_ESN"] = 5] = "Extended_Sequence_Numbers_ESN";
38
+ })(transformType || (exports.transformType = transformType = {}));
39
+ /**
40
+ * For Transform Type 1 (Encryption Algorithm), defined Transform IDs are: \
41
+ RESERVED 0 \
42
+ ENCR_DES_IV64 1 \
43
+ ENCR_DES 2 \
44
+ ENCR_3DES 3 \
45
+ ENCR_RC5 4 \
46
+ ENCR_IDEA 5 \
47
+ ENCR_CAST 6 \
48
+ ENCR_BLOWFISH 7 \
49
+ ENCR_3IDEA 8 \
50
+ ENCR_DES_IV32 9 \
51
+ RESERVED 10 \
52
+ ENCR_NULL 11 \
53
+ ENCR_AES_CBC 12 \
54
+ ENCR_AES_CTR 13 \
55
+ ENCR_AES_CCM_8 14 \
56
+ ENCR_AES_CCM_12 15 \
57
+ ENCR_AES_CCM_16 16 \
58
+ RESERVED 17 \
59
+ AES_GCM_8_OCTET_ICV 18 \
60
+ AES_GCM_12_OCTET_ICV 19 \
61
+ AES_GCM_16_OCTET_ICV 20 \
62
+ ENCR_NULL_AUTH_AES_GMAC 21 \
63
+ RESERVED_FOR_IEEE_P1619_XTS_AES 22 \
64
+ ENCR_CAMELLIA_CBC 23 \
65
+ ENCR_CAMELLIA_CTR 24 \
66
+ ENCR_CAMELLIA_CCM_8_OCTET_ICV 25 \
67
+ ENCR_CAMELLIA_CCM_12_OCTET_ICV 26 \
68
+ ENCR_CAMELLIA_CCM_16_OCTET_ICV 27 \
69
+ ENCR_CHACHA20_POLY1305 28 \
70
+ ENCR_AES_CCM_8_IIV 29 \
71
+ ENCR_AES_CCM_16_IIV 30 \
72
+ ENCR_CHACHA20_POLY1305_IIV 31 \
73
+ ENCR_KUZNYECHIK_MGM_KTREE 32 \
74
+ ENCR_MAGMA_MGM_KTREE 33 \
75
+ ENCR_KUZNYECHIK_MGM_MAC_KTREE 34 \
76
+ ENCR_MAGMA_MGM_MAC_KTREE 35 \
77
+ 36-1023 Unassigned \
78
+ 1024-65535 Reserved for Private Use
79
+ */
80
+ var encrId;
81
+ (function (encrId) {
82
+ // RESERVED = 0,
83
+ encrId[encrId["ENCR_DES_IV64"] = 1] = "ENCR_DES_IV64";
84
+ encrId[encrId["ENCR_DES"] = 2] = "ENCR_DES";
85
+ encrId[encrId["ENCR_3DES"] = 3] = "ENCR_3DES";
86
+ encrId[encrId["ENCR_RC5"] = 4] = "ENCR_RC5";
87
+ encrId[encrId["ENCR_IDEA"] = 5] = "ENCR_IDEA";
88
+ encrId[encrId["ENCR_CAST"] = 6] = "ENCR_CAST";
89
+ encrId[encrId["ENCR_BLOWFISH"] = 7] = "ENCR_BLOWFISH";
90
+ encrId[encrId["ENCR_3IDEA"] = 8] = "ENCR_3IDEA";
91
+ encrId[encrId["ENCR_DES_IV32"] = 9] = "ENCR_DES_IV32";
92
+ // RESERVED = 10,
93
+ encrId[encrId["ENCR_NULL"] = 11] = "ENCR_NULL";
94
+ encrId[encrId["ENCR_AES_CBC"] = 12] = "ENCR_AES_CBC";
95
+ encrId[encrId["ENCR_AES_CTR"] = 13] = "ENCR_AES_CTR";
96
+ encrId[encrId["ENCR_AES_CCM_8"] = 14] = "ENCR_AES_CCM_8";
97
+ encrId[encrId["ENCR_AES_CCM_12"] = 15] = "ENCR_AES_CCM_12";
98
+ encrId[encrId["ENCR_AES_CCM_16"] = 16] = "ENCR_AES_CCM_16";
99
+ // UNASSIGNED = 17,
100
+ encrId[encrId["ENCR_AES_GCM_8"] = 18] = "ENCR_AES_GCM_8";
101
+ encrId[encrId["ENCR_AES_GCM_12"] = 19] = "ENCR_AES_GCM_12";
102
+ encrId[encrId["ENCR_AES_GCM_16"] = 20] = "ENCR_AES_GCM_16";
103
+ encrId[encrId["ENCR_NULL_AUTH_AES_GMAC"] = 21] = "ENCR_NULL_AUTH_AES_GMAC";
104
+ encrId[encrId["RESERVED_FOR_IEEE_P1619_XTS_AES"] = 22] = "RESERVED_FOR_IEEE_P1619_XTS_AES";
105
+ encrId[encrId["ENCR_CAMELLIA_CBC"] = 23] = "ENCR_CAMELLIA_CBC";
106
+ encrId[encrId["ENCR_CAMELLIA_CTR"] = 24] = "ENCR_CAMELLIA_CTR";
107
+ encrId[encrId["ENCR_CAMELLIA_CCM_8"] = 25] = "ENCR_CAMELLIA_CCM_8";
108
+ encrId[encrId["ENCR_CAMELLIA_CCM_12"] = 26] = "ENCR_CAMELLIA_CCM_12";
109
+ encrId[encrId["ENCR_CAMELLIA_CCM_16"] = 27] = "ENCR_CAMELLIA_CCM_16";
110
+ encrId[encrId["ENCR_CHACHA20_POLY1305"] = 28] = "ENCR_CHACHA20_POLY1305";
111
+ encrId[encrId["ENCR_AES_CCM_8_IIV"] = 29] = "ENCR_AES_CCM_8_IIV";
112
+ encrId[encrId["ENCR_AES_GCM_16_IIV"] = 30] = "ENCR_AES_GCM_16_IIV";
113
+ encrId[encrId["ENCR_CHACHA20_POLY1305_IIV"] = 31] = "ENCR_CHACHA20_POLY1305_IIV";
114
+ encrId[encrId["ENCR_KUZNYECHIK_MGM_KTREE"] = 32] = "ENCR_KUZNYECHIK_MGM_KTREE";
115
+ encrId[encrId["ENCR_MAGMA_MGM_KTREE"] = 33] = "ENCR_MAGMA_MGM_KTREE";
116
+ encrId[encrId["ENCR_KUZNYECHIK_MGM_MAC_KTREE"] = 34] = "ENCR_KUZNYECHIK_MGM_MAC_KTREE";
117
+ encrId[encrId["ENCR_MAGMA_MGM_MAC_KTREE"] = 35] = "ENCR_MAGMA_MGM_MAC_KTREE";
118
+ // 36-1023 Unassigned
119
+ // 1024-65535 Reserved for Private Use
120
+ })(encrId || (exports.encrId = encrId = {}));
121
+ /**
122
+ * For Transform Type 2 (Pseudo-random Function), defined Transform IDs are: \
123
+ RESERVED 0 \
124
+ PRF_HMAC_MD5 1 \
125
+ PRF_HMAC_SHA1 2 \
126
+ PRF_HMAC_TIGER 3 \
127
+ PRF_AES128_XCBC 4 \
128
+ PRF_HMAC_SHA2_256 5 \
129
+ PRF_HMAC_SHA2_384 6 \
130
+ PRF_HMAC_SHA2_512 7 \
131
+ PRF_AES128_CMAC 8 \
132
+ PRF_HMAC_STREEBOG_512 9 \
133
+ 10-1023 Unassigned \
134
+ 1024-65535 Reserved for Private Use
135
+ */
136
+ var prfId;
137
+ (function (prfId) {
138
+ // RESERVED = 0,
139
+ prfId[prfId["PRF_HMAC_MD5"] = 1] = "PRF_HMAC_MD5";
140
+ prfId[prfId["PRF_HMAC_SHA1"] = 2] = "PRF_HMAC_SHA1";
141
+ prfId[prfId["PRF_HMAC_TIGER"] = 3] = "PRF_HMAC_TIGER";
142
+ prfId[prfId["PRF_AES128_XCBC"] = 4] = "PRF_AES128_XCBC";
143
+ prfId[prfId["PRF_HMAC_SHA2_256"] = 5] = "PRF_HMAC_SHA2_256";
144
+ prfId[prfId["PRF_HMAC_SHA2_384"] = 6] = "PRF_HMAC_SHA2_384";
145
+ prfId[prfId["PRF_HMAC_SHA2_512"] = 7] = "PRF_HMAC_SHA2_512";
146
+ prfId[prfId["PRF_AES128_CMAC"] = 8] = "PRF_AES128_CMAC";
147
+ prfId[prfId["PRF_HMAC_STREEBOG_512"] = 9] = "PRF_HMAC_STREEBOG_512";
148
+ // 10-1023 Unassigned
149
+ // 1024-65535 Reserved for Private Use
150
+ })(prfId || (exports.prfId = prfId = {}));
151
+ /**
152
+ * For Transform Type 3 (Integrity Algorithm), defined Transform IDs are: \
153
+ NONE 0 \
154
+ AUTH_HMAC_MD5_96 1 \
155
+ AUTH_HMAC_SHA1_96 2 \
156
+ AUTH_DES_MAC 3 \
157
+ AUTH_KPDK_MD5 4 \
158
+ AUTH_AES_XCBC_96 5 \
159
+ AUTH_HMAC_MD5_128 6 \
160
+ AUTH_HMAC_SHA1_160 7 \
161
+ AUTH_AES_CMAC_96 8 \
162
+ AUTH_AES_128_GMAC 9 \
163
+ AUTH_AES_192_GMAC 10 \
164
+ AUTH_AES_256_GMAC 11 \
165
+ AUTH_HMAC_SHA2_256_128 12 \
166
+ AUTH_HMAC_SHA2_384_192 13 \
167
+ AUTH_HMAC_SHA2_512_256 14 \
168
+ 15-1023 Unassigned \
169
+ 1024-65535 Reserved for Private Use
170
+ */
171
+ var integId;
172
+ (function (integId) {
173
+ integId[integId["NONE"] = 0] = "NONE";
174
+ integId[integId["AUTH_HMAC_MD5_96"] = 1] = "AUTH_HMAC_MD5_96";
175
+ integId[integId["AUTH_HMAC_SHA1_96"] = 2] = "AUTH_HMAC_SHA1_96";
176
+ integId[integId["AUTH_DES_MAC"] = 3] = "AUTH_DES_MAC";
177
+ integId[integId["AUTH_KPDK_MD5"] = 4] = "AUTH_KPDK_MD5";
178
+ integId[integId["AUTH_AES_XCBC_96"] = 5] = "AUTH_AES_XCBC_96";
179
+ integId[integId["AUTH_HMAC_MD5_128"] = 6] = "AUTH_HMAC_MD5_128";
180
+ integId[integId["AUTH_HMAC_SHA1_160"] = 7] = "AUTH_HMAC_SHA1_160";
181
+ integId[integId["AUTH_AES_CMAC_96"] = 8] = "AUTH_AES_CMAC_96";
182
+ integId[integId["AUTH_AES_128_GMAC"] = 9] = "AUTH_AES_128_GMAC";
183
+ integId[integId["AUTH_AES_192_GMAC"] = 10] = "AUTH_AES_192_GMAC";
184
+ integId[integId["AUTH_AES_256_GMAC"] = 11] = "AUTH_AES_256_GMAC";
185
+ integId[integId["AUTH_HMAC_SHA2_256_128"] = 12] = "AUTH_HMAC_SHA2_256_128";
186
+ integId[integId["AUTH_HMAC_SHA2_384_192"] = 13] = "AUTH_HMAC_SHA2_384_192";
187
+ integId[integId["AUTH_HMAC_SHA2_512_256"] = 14] = "AUTH_HMAC_SHA2_512_256";
188
+ // 15-1023 Unassigned
189
+ // 1024-65535 Reserved for Private Use
190
+ })(integId || (exports.integId = integId = {}));
191
+ /**
192
+ * For Transform Type 4 (Diffie-Hellman Group), defined Transform IDs are: \
193
+ RESERVED 0 \
194
+ DH_768_BIT_MODP 1 \
195
+ DH_1024_BIT_MODP 2 \
196
+ 3-4 Reserved \
197
+ DH_1536_BIT_MODP 5 \
198
+ 6-13 Unassigned \
199
+ DH_2048_BIT_MODP 14 \
200
+ DH_3072_BIT_MODP 15 \
201
+ DH_4096_BIT_MODP 16 \
202
+ DH_6144_BIT_MODP 17 \
203
+ DH_8192_BIT_MODP 18 \
204
+ DH_256_BIT_RANDOM_ECP 19 \
205
+ DH_384_BIT_RANDOM_ECP 20 \
206
+ DH_521_BIT_RANDOM_ECP 21 \
207
+ DH_1024_BIT_MODP_WITH_160_BIT_PRIME_ORDER 22 \
208
+ DH_2048_BIT_MODP_WITH_224_BIT_PRIME_ORDER 23 \
209
+ DH_2048_BIT_MODP_WITH_256_BIT_PRIME_ORDER 24 \
210
+ DH_192_BIT_RANDOM_ECP 25 \
211
+ DH_224_BIT_RANDOM_ECP 26 \
212
+ DH_BRAINPOOLP224R1 27 \
213
+ DH_BRAINPOOLP256R1 28 \
214
+ DH_BRAINPOOLP384R1 29 \
215
+ DH_BRAINPOOLP512R1 30 \
216
+ DH_CURVE25519 31 \
217
+ DH_CURVE448 32 \
218
+ DH_GOST3410_2012_256 33 \
219
+ DH_GOST3410_2012_512 34 \
220
+ DH_ML_KEM_512 35 \
221
+ DH_ML_KEM_768 36 \
222
+ DH_ML_KEM_1024 37 \
223
+ 38-1023 Unassigned \
224
+ 1024-65535 Reserved for Private Use
225
+ */
226
+ var dhId;
227
+ (function (dhId) {
228
+ dhId[dhId["NONE"] = 0] = "NONE";
229
+ dhId[dhId["DH_768_bit_MODP"] = 1] = "DH_768_bit_MODP";
230
+ dhId[dhId["DH_1024_bit_MODP"] = 2] = "DH_1024_bit_MODP";
231
+ // 3-4 Reserved
232
+ dhId[dhId["DH_1536_bit_MODP"] = 5] = "DH_1536_bit_MODP";
233
+ // 6-13 Unassigned
234
+ dhId[dhId["DH_2048_bit_MODP"] = 14] = "DH_2048_bit_MODP";
235
+ dhId[dhId["DH_3072_bit_MODP"] = 15] = "DH_3072_bit_MODP";
236
+ dhId[dhId["DH_4096_bit_MODP"] = 16] = "DH_4096_bit_MODP";
237
+ dhId[dhId["DH_6144_bit_MODP"] = 17] = "DH_6144_bit_MODP";
238
+ dhId[dhId["DH_8192_bit_MODP"] = 18] = "DH_8192_bit_MODP";
239
+ dhId[dhId["DH_256_bit_random_ECP"] = 19] = "DH_256_bit_random_ECP";
240
+ dhId[dhId["DH_384_bit_random_ECP"] = 20] = "DH_384_bit_random_ECP";
241
+ dhId[dhId["DH_521_bit_random_ECP"] = 21] = "DH_521_bit_random_ECP";
242
+ dhId[dhId["DH_1024_bit_MODP_with_160_bit_Prime_Order"] = 22] = "DH_1024_bit_MODP_with_160_bit_Prime_Order";
243
+ dhId[dhId["DH_2048_bit_MODP_with_224_bit_Prime_Order"] = 23] = "DH_2048_bit_MODP_with_224_bit_Prime_Order";
244
+ dhId[dhId["DH_2048_bit_MODP_with_256_bit_Prime_Order"] = 24] = "DH_2048_bit_MODP_with_256_bit_Prime_Order";
245
+ dhId[dhId["DH_192_bit_random_ECP"] = 25] = "DH_192_bit_random_ECP";
246
+ dhId[dhId["DH_224_bit_random_ECP"] = 26] = "DH_224_bit_random_ECP";
247
+ dhId[dhId["DH_brainpoolP224r1"] = 27] = "DH_brainpoolP224r1";
248
+ dhId[dhId["DH_brainpoolP256r1"] = 28] = "DH_brainpoolP256r1";
249
+ dhId[dhId["DH_brainpoolP384r1"] = 29] = "DH_brainpoolP384r1";
250
+ dhId[dhId["DH_brainpoolP512r1"] = 30] = "DH_brainpoolP512r1";
251
+ dhId[dhId["DH_Curve25519"] = 31] = "DH_Curve25519";
252
+ dhId[dhId["DH_Curve448"] = 32] = "DH_Curve448";
253
+ dhId[dhId["DH_GOST3410_2012_256"] = 33] = "DH_GOST3410_2012_256";
254
+ dhId[dhId["DH_GOST3410_2012_512"] = 34] = "DH_GOST3410_2012_512";
255
+ dhId[dhId["DH_ml_kem_512"] = 35] = "DH_ml_kem_512";
256
+ dhId[dhId["DH_ml_kem_768"] = 36] = "DH_ml_kem_768";
257
+ dhId[dhId["DH_ml_kem_1024"] = 37] = "DH_ml_kem_1024";
258
+ // 38-1023 Unassigned
259
+ // 1024-65535 Reserved for Private Use
260
+ })(dhId || (exports.dhId = dhId = {}));
261
+ /**
262
+ * For Transform Type 5 (Extended Sequence Numbers), defined Transform IDs are: \
263
+ No Extended Sequence Numbers 0 \
264
+ Extended Sequence Numbers 1 \
265
+ RESERVED 2 - 65535
266
+ */
267
+ var esnId;
268
+ (function (esnId) {
269
+ esnId[esnId["ESN_NONE"] = 0] = "ESN_NONE";
270
+ esnId[esnId["ESN"] = 1] = "ESN";
271
+ })(esnId || (exports.esnId = esnId = {}));
272
+ /**
273
+ * Transform Type Map to their Ids
274
+ */
275
+ exports.transformTypeMap = new Map([
276
+ [transformType.Encryption_Algorithm_ENCR, encrId],
277
+ [transformType.Pseudo_Random_PRF, prfId],
278
+ [transformType.Integrity_Algorithm_INTEG, integId],
279
+ [transformType.Diffie_Hellman_Group_DH, dhId],
280
+ [transformType.Extended_Sequence_Numbers_ESN, esnId],
281
+ ]);
282
+ /**
283
+ * IKEv2 Transform Substructure
284
+ * @class
285
+ * @property {number} lastSubstructure - Last Substructure (1 bit)
286
+ * @property {number} length - Transform Length (2 bytes)
287
+ * @property {transformType} type - Transform Type (1 byte)
288
+ * @property {number} id - Transform ID (2 bytes)
289
+ * @property {Attribute} attributes - Transform Attributes (n bytes)
290
+ */
291
+ class Transform {
292
+ constructor(lastSubstructure, length, type, id, attributes) {
293
+ this.lastSubstructure = lastSubstructure;
294
+ this.length = length;
295
+ this.type = type;
296
+ this.id = id;
297
+ this.attributes = attributes;
298
+ }
299
+ /**
300
+ * Parses a transform from a buffer
301
+ * @param buffer The buffer to parse from.
302
+ * @static
303
+ * @public
304
+ * @returns {Transform}
305
+ */
306
+ static parse(buffer) {
307
+ try {
308
+ const lastSubstructure = buffer.readUInt8(0); // First octet
309
+ const length = buffer.readUInt16BE(2); // Transform Length starts at byte 2
310
+ const type = buffer.readUInt8(4); // Transform Type at byte 4
311
+ const id = buffer.readUInt16BE(6); // Transform ID starts at byte 6
312
+ // Attributes start at byte 8 onward
313
+ const attributesBuffer = buffer.subarray(8, length);
314
+ const attributes = this.parseAttributes(attributesBuffer);
315
+ return new Transform(lastSubstructure, length, type, id, attributes);
316
+ }
317
+ catch (error) {
318
+ throw new Error("Failed to parse transform");
319
+ }
320
+ }
321
+ /**
322
+ * Serializes a JSON representation of the transform to a buffer
323
+ * @param json The JSON object to serialize.
324
+ * @static
325
+ * @public
326
+ * @returns {Buffer}
327
+ */
328
+ static serializeJSON(json) {
329
+ const lastSubstructure = json.lastSubstructure;
330
+ const length = json.length;
331
+ const type = json.type;
332
+ const id = json.id;
333
+ const attributesBuffer = json.attributes.map((attr) => attribute_1.Attribute.serializeJSON(attr));
334
+ const totalLength = 8 +
335
+ attributesBuffer.reduce((acc, buf) => acc + buf.length, 0);
336
+ const buffer = Buffer.alloc(totalLength);
337
+ buffer.writeUInt8(lastSubstructure, 0);
338
+ buffer.writeUInt8(0, 1);
339
+ buffer.writeUInt16BE(length, 2);
340
+ buffer.writeUInt8(type, 4);
341
+ buffer.writeUInt8(0, 5);
342
+ buffer.writeUInt16BE(id, 6);
343
+ Buffer.concat(attributesBuffer).copy(buffer, 8);
344
+ return buffer;
345
+ }
346
+ /**
347
+ * Parses attributes from a buffer
348
+ * @param buffer The buffer to parse from
349
+ * @static
350
+ * @private
351
+ * @returns {Attribute[]}
352
+ */
353
+ static parseAttributes(buffer) {
354
+ if (!Buffer.isBuffer(buffer)) {
355
+ throw new Error("Input must be a Buffer");
356
+ }
357
+ const attributes = [];
358
+ let offset = 0;
359
+ const maxIterations = 1000; // Prevent infinite loops
360
+ let iterationCount = 0;
361
+ while (offset < buffer.length && iterationCount < maxIterations) {
362
+ iterationCount++;
363
+ // Ensure we have at least 4 bytes for the attribute header
364
+ if (offset + 4 > buffer.length) {
365
+ throw new Error("Buffer too short for attribute header");
366
+ }
367
+ try {
368
+ const attribute = attribute_1.Attribute.parse(buffer.subarray(offset));
369
+ attributes.push(attribute);
370
+ // Calculate the actual length of the parsed attribute
371
+ const attributeLength = attribute.format === 0
372
+ ? 4 + attribute.length
373
+ : 4; // AF=1 --> fixed 4 bytes, value is in the "length" field
374
+ offset += attributeLength;
375
+ // Safety check: ensure we're making progress
376
+ if (attributeLength <= 0) {
377
+ throw new Error("Invalid attribute length: must be greater than 0");
378
+ }
379
+ }
380
+ catch (error) {
381
+ if (error instanceof Error) {
382
+ throw new Error(`Failed to parse attribute at offset ${offset}: ${error.message}`);
383
+ }
384
+ throw new Error(`Failed to parse attribute at offset ${offset}: Unknown error`);
385
+ }
386
+ }
387
+ if (iterationCount >= maxIterations) {
388
+ throw new Error("Too many attributes parsed, possible infinite loop detected");
389
+ }
390
+ return attributes;
391
+ }
392
+ get attributeKeyLength() {
393
+ var _a;
394
+ let keyLengthAttribute = (_a = this.attributes) === null || _a === void 0 ? void 0 : _a.find((attr) => attr.type === attribute_1.attributeType.KeyLength);
395
+ if (keyLengthAttribute &&
396
+ keyLengthAttribute.value &&
397
+ keyLengthAttribute.value.length === 2) {
398
+ return keyLengthAttribute.value.readUInt16BE(0);
399
+ }
400
+ return undefined;
401
+ }
402
+ set attributeKeyLength(keyLength) {
403
+ var _a;
404
+ let keyLengthBuffer = Buffer.alloc(2);
405
+ keyLengthBuffer.writeUInt16BE(keyLength, 0);
406
+ let keyLengthAttribute = (_a = this.attributes) === null || _a === void 0 ? void 0 : _a.find((attr) => attr.type === attribute_1.attributeType.KeyLength);
407
+ if (keyLengthAttribute) {
408
+ keyLengthAttribute.value = keyLengthBuffer;
409
+ keyLengthAttribute.length = 0;
410
+ }
411
+ else {
412
+ this.attributes.push(new attribute_1.Attribute(1, attribute_1.attributeType.KeyLength, keyLengthBuffer));
413
+ }
414
+ }
415
+ /**
416
+ * Serializes the transform to a buffer
417
+ * @method
418
+ * @public
419
+ * @returns {Buffer}
420
+ */
421
+ serialize() {
422
+ // Encode deep attributes first
423
+ const attributes = this.attributes.map((attr) => attr.serialize());
424
+ const attributesBuffer = Buffer.concat(attributes);
425
+ // Fix the length
426
+ this.length = 8 + attributesBuffer.length;
427
+ // Allocate a buffer with the exact length
428
+ const buffer = Buffer.alloc(this.length);
429
+ // Serialize fields into the buffer
430
+ buffer.writeUInt8(this.lastSubstructure, 0); // First byte: lastSubstructure
431
+ buffer.writeUInt8(0, 1);
432
+ buffer.writeUInt16BE(this.length, 2); // Transform Length (2 bytes)
433
+ buffer.writeUInt8(this.type, 4); // Transform Type (1 byte)
434
+ buffer.writeUInt8(0, 5); // Reserved (1 byte)
435
+ buffer.writeUInt16BE(this.id, 6); // Transform ID (2 bytes)
436
+ attributesBuffer.copy(buffer, 8); // Copy attributes starting at byte 8
437
+ return buffer;
438
+ }
439
+ /**
440
+ * Convert object to JSON
441
+ * @method
442
+ * @public
443
+ * @returns {Record<string, any>} JSON object
444
+ */
445
+ toJSON() {
446
+ return {
447
+ lastSubstructure: this.lastSubstructure,
448
+ length: this.length,
449
+ type: this.type,
450
+ id: this.id,
451
+ attributes: this.attributes.map((attr) => attr.toJSON()),
452
+ };
453
+ }
454
+ /**
455
+ * Returns a string representation of the transform
456
+ * @method
457
+ * @public
458
+ * @returns {void}
459
+ */
460
+ toString() {
461
+ const prettyJson = this.toJSON();
462
+ prettyJson.lastSubstructure =
463
+ this.lastSubstructure === 3 ? "Transform (3)" : "None (0)";
464
+ prettyJson.type = `${transformType[this.type] || "UNKNOWN"} (${prettyJson.type})`;
465
+ prettyJson.id = `${exports.transformTypeMap.get(this.type)[this.id] || "UNKNOWN"} (${prettyJson.id})`;
466
+ prettyJson.attributes = this.attributes.map((attr) => JSON.parse(attr.toString()));
467
+ return JSON.stringify(prettyJson, null, 2);
468
+ }
469
+ }
470
+ exports.Transform = Transform;
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "node-ikev2",
3
+ "title": "Node-IKEV2",
4
+ "version": "0.1.0",
5
+ "description": "IKEv2 parser and serializer for Node.js",
6
+ "main": "./lib/src/index.js",
7
+ "types": "./lib/src/index.d.ts",
8
+ "module": "./lib/src/index.js",
9
+ "files": [
10
+ "lib/src",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "lint": "eslint 'src/**/*.ts'",
17
+ "lint-fix": "eslint 'src/**/*.ts' --fix",
18
+ "test": "jest",
19
+ "build-and-test": "npm run build && npm run test",
20
+ "prepublishOnly": "npm run build-and-test"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/hyavari/node-ikev2.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/hyavari/node-ikev2/issues"
28
+ },
29
+ "homepage": "https://github.com/hyavari/node-ikev2#readme",
30
+ "keywords": [
31
+ "ikev2",
32
+ "ipsec",
33
+ "vpn",
34
+ "security",
35
+ "cryptography",
36
+ "parser"
37
+ ],
38
+ "author": "Hossein Yavari",
39
+ "license": "ISC",
40
+ "devDependencies": {
41
+ "@types/jest": "^29.5.14",
42
+ "@types/node": "^22.7.9",
43
+ "@typescript-eslint/eslint-plugin": "^8.10.0",
44
+ "@typescript-eslint/parser": "^8.10.0",
45
+ "eslint": "^9.12.0",
46
+ "eslint-config-prettier": "^9.1.0",
47
+ "eslint-plugin-prettier": "^5.2.1",
48
+ "globals": "^15.11.0",
49
+ "jest": "^29.7.0",
50
+ "prettier": "^3.3.3",
51
+ "ts-jest": "^29.2.5",
52
+ "ts-node": "^10.9.2",
53
+ "typescript": "^5.5.4",
54
+ "typescript-eslint": "^8.10.0"
55
+ }
56
+ }