Improved authenticode.js error handling for #4134
Ylian Saint-Hilaire committed
Jun 18, 2022 at 08:38 UTC
bf128a988c644f43fc2c808b6202f191f3dd1544
1 file changed
+85
-67
authenticode.js
+85
-67
@@ -288,77 +288,95 @@ function createAuthenticodeHandler(path) {
288
var derlen = forge.asn1.getBerValueLength(forge.util.createBuffer(pkcs7raw.slice(1, 5))) + 4;
289
if (derlen != pkcs7raw.length) { pkcs7raw = pkcs7raw.slice(0, derlen); }
290
291
- // Decode the signature block
292
- var pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(pkcs7raw));
293
-
294
- // To work around ForgeJS PKCS#7 limitation, this may break PKCS7 verify if ForgeJS adds support for it in the future
295
- // Switch content type from "1.3.6.1.4.1.311.2.1.4" to "1.2.840.113549.1.7.1"
296
- pkcs7der.value[1].value[0].value[2].value[0].value = forge.asn1.oidToDer(forge.pki.oids.data).data;
291
+ // Decode the signature block and check that it's valid
292
+ var pkcs7der = null, valid = false;
293
+ try { pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(pkcs7raw)); } catch (ex) { }
294
+ try { valid = ((pkcs7der != null) && (forge.asn1.derToOid(pkcs7der.value[1].value[0].value[2].value[0].value) == "1.3.6.1.4.1.311.2.1.4")); } catch (ex) { }
295
+ if (pkcs7der == null) {
296
+ // Can't decode the signature
297
+ obj.header.sigpos = 0;
298
+ obj.header.siglen = 0;
299
+ obj.header.signed = false;
300
+ } else {
301
+ // To work around ForgeJS PKCS#7 limitation, this may break PKCS7 verify if ForgeJS adds support for it in the future
302
+ // Switch content type from "1.3.6.1.4.1.311.2.1.4" to "1.2.840.113549.1.7.1"
303
+ pkcs7der.value[1].value[0].value[2].value[0].value = forge.asn1.oidToDer(forge.pki.oids.data).data;
304
298
- // Decode the PKCS7 message
299
- var pkcs7 = p7.messageFromAsn1(pkcs7der);
300
- var pkcs7content = pkcs7.rawCapture.content.value[0];
301
-
302
- // Verify a PKCS#7 signature
303
- // Verify is not currently supported in node-forge, but if implemented in the future, this code could work.
304
- //var caStore = forge.pki.createCaStore();
305
- //for (var i in obj.certificates) { caStore.addCertificate(obj.certificates[i]); }
306
- // Return is true if all signatures are valid and chain up to a provided CA
307
- //if (!pkcs7.verify(caStore)) { throw ('Executable file has an invalid signature.'); }
308
-
309
- // Get the signing attributes
310
- obj.signingAttribs = [];
311
- try {
312
- for (var i in pkcs7.rawCapture.authenticatedAttributes) {
313
- if (
314
- (pkcs7.rawCapture.authenticatedAttributes[i].value != null) &&
315
- (pkcs7.rawCapture.authenticatedAttributes[i].value[0] != null) &&
316
- (pkcs7.rawCapture.authenticatedAttributes[i].value[0].value != null) &&
317
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1] != null) &&
318
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value != null) &&
319
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0] != null) &&
320
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value != null) &&
321
- (forge.asn1.derToOid(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value) == obj.Oids.SPC_SP_OPUS_INFO_OBJID)) {
322
- for (var j in pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value) {
305
+ // Decode the PKCS7 message
306
+ var pkcs7 = null, pkcs7content = null;
307
+ try {
308
+ pkcs7 = p7.messageFromAsn1(pkcs7der);
309
+ pkcs7content = pkcs7.rawCapture.content.value[0];
310
+ } catch (ex) { }
311
+
312
+ if ((pkcs7 == null) || (pkcs7content == null)) {
313
+ // Can't decode the signature
314
+ obj.header.sigpos = 0;
315
+ obj.header.siglen = 0;
316
+ obj.header.signed = false;
317
+ } else {
318
+ // Verify a PKCS#7 signature
319
+ // Verify is not currently supported in node-forge, but if implemented in the future, this code could work.
320
+ //var caStore = forge.pki.createCaStore();
321
+ //for (var i in obj.certificates) { caStore.addCertificate(obj.certificates[i]); }
322
+ // Return is true if all signatures are valid and chain up to a provided CA
323
+ //if (!pkcs7.verify(caStore)) { throw ('Executable file has an invalid signature.'); }
324
+
325
+ // Get the signing attributes
326
+ obj.signingAttribs = [];
327
+ try {
328
+ for (var i in pkcs7.rawCapture.authenticatedAttributes) {
329
if (
324
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j] != null) &&
325
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value != null) &&
326
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0] != null) &&
327
- (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value != null)
328
- ) {
329
- var v = pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value;
330
- if (v.startsWith('http://') || v.startsWith('https://') || ((v.length % 2) == 1)) { obj.signingAttribs.push(v); } else {
331
- var r = ''; // This string value is in UCS2 format, convert it to a normal string.
332
- for (var k = 0; k < v.length; k += 2) { r += String.fromCharCode((v.charCodeAt(k + 8) << 8) + v.charCodeAt(k + 1)); }
333
- obj.signingAttribs.push(r);
330
+ (pkcs7.rawCapture.authenticatedAttributes[i].value != null) &&
331
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[0] != null) &&
332
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[0].value != null) &&
333
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1] != null) &&
334
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value != null) &&
335
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0] != null) &&
336
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value != null) &&
337
+ (forge.asn1.derToOid(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value) == obj.Oids.SPC_SP_OPUS_INFO_OBJID)) {
338
+ for (var j in pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value) {
339
+ if (
340
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j] != null) &&
341
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value != null) &&
342
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0] != null) &&
343
+ (pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value != null)
344
+ ) {
345
+ var v = pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value;
346
+ if (v.startsWith('http://') || v.startsWith('https://') || ((v.length % 2) == 1)) { obj.signingAttribs.push(v); } else {
347
+ var r = ''; // This string value is in UCS2 format, convert it to a normal string.
348
+ for (var k = 0; k < v.length; k += 2) { r += String.fromCharCode((v.charCodeAt(k + 8) << 8) + v.charCodeAt(k + 1)); }
349
+ obj.signingAttribs.push(r);
350
+ }
351
+ }
352
}
353
}
354
}
355
+ } catch (ex) { }
356
+
357
+ // Set the certificate chain
358
+ obj.certificates = pkcs7.certificates;
359
+
360
+ // Set the signature
361
+ obj.signature = Buffer.from(pkcs7.rawCapture.signature, 'binary');
362
+
363
+ // Get the file hashing algorithm
364
+ var hashAlgoOid = forge.asn1.derToOid(pkcs7content.value[1].value[0].value[0].value);
365
+ switch (hashAlgoOid) {
366
+ case forge.pki.oids.sha256: { obj.fileHashAlgo = 'sha256'; break; }
367
+ case forge.pki.oids.sha384: { obj.fileHashAlgo = 'sha384'; break; }
368
+ case forge.pki.oids.sha512: { obj.fileHashAlgo = 'sha512'; break; }
369
+ case forge.pki.oids.sha224: { obj.fileHashAlgo = 'sha224'; break; }
370
+ case forge.pki.oids.md5: { obj.fileHashAlgo = 'md5'; break; }
371
}
338
- }
339
- } catch (ex) { }
340
-
341
- // Set the certificate chain
342
- obj.certificates = pkcs7.certificates;
343
-
344
- // Set the signature
345
- obj.signature = Buffer.from(pkcs7.rawCapture.signature, 'binary');
346
-
347
- // Get the file hashing algorithm
348
- var hashAlgoOid = forge.asn1.derToOid(pkcs7content.value[1].value[0].value[0].value);
349
- switch (hashAlgoOid) {
350
- case forge.pki.oids.sha256: { obj.fileHashAlgo = 'sha256'; break; }
351
- case forge.pki.oids.sha384: { obj.fileHashAlgo = 'sha384'; break; }
352
- case forge.pki.oids.sha512: { obj.fileHashAlgo = 'sha512'; break; }
353
- case forge.pki.oids.sha224: { obj.fileHashAlgo = 'sha224'; break; }
354
- case forge.pki.oids.md5: { obj.fileHashAlgo = 'md5'; break; }
355
- }
372
357
- // Get the signed file hash
358
- obj.fileHashSigned = Buffer.from(pkcs7content.value[1].value[1].value, 'binary')
373
+ // Get the signed file hash
374
+ obj.fileHashSigned = Buffer.from(pkcs7content.value[1].value[1].value, 'binary')
375
360
- // Compute the actual file hash
361
- if (obj.fileHashAlgo != null) { obj.fileHashActual = obj.getHash(obj.fileHashAlgo); }
376
+ // Compute the actual file hash
377
+ if (obj.fileHashAlgo != null) { obj.fileHashActual = obj.getHash(obj.fileHashAlgo); }
378
+ }
379
+ }
380
}
381
return true;
382
}
@@ -486,7 +504,7 @@ function createAuthenticodeHandler(path) {
504
fs.closeSync(output);
505
506
// Indicate we are done
489
- func(null, written);
507
+ func(null);
508
});
509
});
510
@@ -1372,7 +1390,7 @@ function createAuthenticodeHandler(path) {
1390
1391
// Close the file
1392
fs.closeSync(output);
1375
- func(null, written);
1393
+ func(null);
1394
}
1395
1396
// Save an executable without the signature
@@ -1635,7 +1653,7 @@ function createAuthenticodeHandler(path) {
1653
fs.closeSync(output);
1654
1655
// Indicate success
1638
- func(null, written);
1656
+ func(null);
1657
}
1658
1659
function writeExecutableEx(output, p7signature, written, func) {
@@ -1669,7 +1687,7 @@ function createAuthenticodeHandler(path) {
1687
fs.closeSync(output);
1688
1689
// Indicate success
1672
- func(null, written);
1690
+ func(null);
1691
}
1692
1693
// Return null if we could not open the file