Improved authenticode.js error handling for #4134
This commit is contained in:
parent
18c11a344c
commit
bf128a988c
148
authenticode.js
148
authenticode.js
|
@ -288,77 +288,95 @@ function createAuthenticodeHandler(path) {
|
||||||
var derlen = forge.asn1.getBerValueLength(forge.util.createBuffer(pkcs7raw.slice(1, 5))) + 4;
|
var derlen = forge.asn1.getBerValueLength(forge.util.createBuffer(pkcs7raw.slice(1, 5))) + 4;
|
||||||
if (derlen != pkcs7raw.length) { pkcs7raw = pkcs7raw.slice(0, derlen); }
|
if (derlen != pkcs7raw.length) { pkcs7raw = pkcs7raw.slice(0, derlen); }
|
||||||
|
|
||||||
// Decode the signature block
|
// Decode the signature block and check that it's valid
|
||||||
var pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(pkcs7raw));
|
var pkcs7der = null, valid = false;
|
||||||
|
try { pkcs7der = forge.asn1.fromDer(forge.util.createBuffer(pkcs7raw)); } catch (ex) { }
|
||||||
|
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) { }
|
||||||
|
if (pkcs7der == null) {
|
||||||
|
// Can't decode the signature
|
||||||
|
obj.header.sigpos = 0;
|
||||||
|
obj.header.siglen = 0;
|
||||||
|
obj.header.signed = false;
|
||||||
|
} else {
|
||||||
|
// To work around ForgeJS PKCS#7 limitation, this may break PKCS7 verify if ForgeJS adds support for it in the future
|
||||||
|
// Switch content type from "1.3.6.1.4.1.311.2.1.4" to "1.2.840.113549.1.7.1"
|
||||||
|
pkcs7der.value[1].value[0].value[2].value[0].value = forge.asn1.oidToDer(forge.pki.oids.data).data;
|
||||||
|
|
||||||
// To work around ForgeJS PKCS#7 limitation, this may break PKCS7 verify if ForgeJS adds support for it in the future
|
// Decode the PKCS7 message
|
||||||
// Switch content type from "1.3.6.1.4.1.311.2.1.4" to "1.2.840.113549.1.7.1"
|
var pkcs7 = null, pkcs7content = null;
|
||||||
pkcs7der.value[1].value[0].value[2].value[0].value = forge.asn1.oidToDer(forge.pki.oids.data).data;
|
try {
|
||||||
|
pkcs7 = p7.messageFromAsn1(pkcs7der);
|
||||||
|
pkcs7content = pkcs7.rawCapture.content.value[0];
|
||||||
|
} catch (ex) { }
|
||||||
|
|
||||||
// Decode the PKCS7 message
|
if ((pkcs7 == null) || (pkcs7content == null)) {
|
||||||
var pkcs7 = p7.messageFromAsn1(pkcs7der);
|
// Can't decode the signature
|
||||||
var pkcs7content = pkcs7.rawCapture.content.value[0];
|
obj.header.sigpos = 0;
|
||||||
|
obj.header.siglen = 0;
|
||||||
|
obj.header.signed = false;
|
||||||
|
} else {
|
||||||
|
// Verify a PKCS#7 signature
|
||||||
|
// Verify is not currently supported in node-forge, but if implemented in the future, this code could work.
|
||||||
|
//var caStore = forge.pki.createCaStore();
|
||||||
|
//for (var i in obj.certificates) { caStore.addCertificate(obj.certificates[i]); }
|
||||||
|
// Return is true if all signatures are valid and chain up to a provided CA
|
||||||
|
//if (!pkcs7.verify(caStore)) { throw ('Executable file has an invalid signature.'); }
|
||||||
|
|
||||||
// Verify a PKCS#7 signature
|
// Get the signing attributes
|
||||||
// Verify is not currently supported in node-forge, but if implemented in the future, this code could work.
|
obj.signingAttribs = [];
|
||||||
//var caStore = forge.pki.createCaStore();
|
try {
|
||||||
//for (var i in obj.certificates) { caStore.addCertificate(obj.certificates[i]); }
|
for (var i in pkcs7.rawCapture.authenticatedAttributes) {
|
||||||
// Return is true if all signatures are valid and chain up to a provided CA
|
|
||||||
//if (!pkcs7.verify(caStore)) { throw ('Executable file has an invalid signature.'); }
|
|
||||||
|
|
||||||
// Get the signing attributes
|
|
||||||
obj.signingAttribs = [];
|
|
||||||
try {
|
|
||||||
for (var i in pkcs7.rawCapture.authenticatedAttributes) {
|
|
||||||
if (
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[0] != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1] != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0] != null) &&
|
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value != null) &&
|
|
||||||
(forge.asn1.derToOid(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value) == obj.Oids.SPC_SP_OPUS_INFO_OBJID)) {
|
|
||||||
for (var j in pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value) {
|
|
||||||
if (
|
if (
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j] != null) &&
|
(pkcs7.rawCapture.authenticatedAttributes[i].value != null) &&
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value != null) &&
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[0] != null) &&
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0] != null) &&
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value != null) &&
|
||||||
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value != null)
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1] != null) &&
|
||||||
) {
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value != null) &&
|
||||||
var v = pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value;
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0] != null) &&
|
||||||
if (v.startsWith('http://') || v.startsWith('https://') || ((v.length % 2) == 1)) { obj.signingAttribs.push(v); } else {
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value != null) &&
|
||||||
var r = ''; // This string value is in UCS2 format, convert it to a normal string.
|
(forge.asn1.derToOid(pkcs7.rawCapture.authenticatedAttributes[i].value[0].value) == obj.Oids.SPC_SP_OPUS_INFO_OBJID)) {
|
||||||
for (var k = 0; k < v.length; k += 2) { r += String.fromCharCode((v.charCodeAt(k + 8) << 8) + v.charCodeAt(k + 1)); }
|
for (var j in pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value) {
|
||||||
obj.signingAttribs.push(r);
|
if (
|
||||||
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j] != null) &&
|
||||||
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value != null) &&
|
||||||
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0] != null) &&
|
||||||
|
(pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value != null)
|
||||||
|
) {
|
||||||
|
var v = pkcs7.rawCapture.authenticatedAttributes[i].value[1].value[0].value[j].value[0].value;
|
||||||
|
if (v.startsWith('http://') || v.startsWith('https://') || ((v.length % 2) == 1)) { obj.signingAttribs.push(v); } else {
|
||||||
|
var r = ''; // This string value is in UCS2 format, convert it to a normal string.
|
||||||
|
for (var k = 0; k < v.length; k += 2) { r += String.fromCharCode((v.charCodeAt(k + 8) << 8) + v.charCodeAt(k + 1)); }
|
||||||
|
obj.signingAttribs.push(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ex) { }
|
||||||
|
|
||||||
|
// Set the certificate chain
|
||||||
|
obj.certificates = pkcs7.certificates;
|
||||||
|
|
||||||
|
// Set the signature
|
||||||
|
obj.signature = Buffer.from(pkcs7.rawCapture.signature, 'binary');
|
||||||
|
|
||||||
|
// Get the file hashing algorithm
|
||||||
|
var hashAlgoOid = forge.asn1.derToOid(pkcs7content.value[1].value[0].value[0].value);
|
||||||
|
switch (hashAlgoOid) {
|
||||||
|
case forge.pki.oids.sha256: { obj.fileHashAlgo = 'sha256'; break; }
|
||||||
|
case forge.pki.oids.sha384: { obj.fileHashAlgo = 'sha384'; break; }
|
||||||
|
case forge.pki.oids.sha512: { obj.fileHashAlgo = 'sha512'; break; }
|
||||||
|
case forge.pki.oids.sha224: { obj.fileHashAlgo = 'sha224'; break; }
|
||||||
|
case forge.pki.oids.md5: { obj.fileHashAlgo = 'md5'; break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the signed file hash
|
||||||
|
obj.fileHashSigned = Buffer.from(pkcs7content.value[1].value[1].value, 'binary')
|
||||||
|
|
||||||
|
// Compute the actual file hash
|
||||||
|
if (obj.fileHashAlgo != null) { obj.fileHashActual = obj.getHash(obj.fileHashAlgo); }
|
||||||
}
|
}
|
||||||
} catch (ex) { }
|
|
||||||
|
|
||||||
// Set the certificate chain
|
|
||||||
obj.certificates = pkcs7.certificates;
|
|
||||||
|
|
||||||
// Set the signature
|
|
||||||
obj.signature = Buffer.from(pkcs7.rawCapture.signature, 'binary');
|
|
||||||
|
|
||||||
// Get the file hashing algorithm
|
|
||||||
var hashAlgoOid = forge.asn1.derToOid(pkcs7content.value[1].value[0].value[0].value);
|
|
||||||
switch (hashAlgoOid) {
|
|
||||||
case forge.pki.oids.sha256: { obj.fileHashAlgo = 'sha256'; break; }
|
|
||||||
case forge.pki.oids.sha384: { obj.fileHashAlgo = 'sha384'; break; }
|
|
||||||
case forge.pki.oids.sha512: { obj.fileHashAlgo = 'sha512'; break; }
|
|
||||||
case forge.pki.oids.sha224: { obj.fileHashAlgo = 'sha224'; break; }
|
|
||||||
case forge.pki.oids.md5: { obj.fileHashAlgo = 'md5'; break; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the signed file hash
|
|
||||||
obj.fileHashSigned = Buffer.from(pkcs7content.value[1].value[1].value, 'binary')
|
|
||||||
|
|
||||||
// Compute the actual file hash
|
|
||||||
if (obj.fileHashAlgo != null) { obj.fileHashActual = obj.getHash(obj.fileHashAlgo); }
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +504,7 @@ function createAuthenticodeHandler(path) {
|
||||||
fs.closeSync(output);
|
fs.closeSync(output);
|
||||||
|
|
||||||
// Indicate we are done
|
// Indicate we are done
|
||||||
func(null, written);
|
func(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1372,7 +1390,7 @@ function createAuthenticodeHandler(path) {
|
||||||
|
|
||||||
// Close the file
|
// Close the file
|
||||||
fs.closeSync(output);
|
fs.closeSync(output);
|
||||||
func(null, written);
|
func(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save an executable without the signature
|
// Save an executable without the signature
|
||||||
|
@ -1635,7 +1653,7 @@ function createAuthenticodeHandler(path) {
|
||||||
fs.closeSync(output);
|
fs.closeSync(output);
|
||||||
|
|
||||||
// Indicate success
|
// Indicate success
|
||||||
func(null, written);
|
func(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeExecutableEx(output, p7signature, written, func) {
|
function writeExecutableEx(output, p7signature, written, func) {
|
||||||
|
@ -1669,7 +1687,7 @@ function createAuthenticodeHandler(path) {
|
||||||
fs.closeSync(output);
|
fs.closeSync(output);
|
||||||
|
|
||||||
// Indicate success
|
// Indicate success
|
||||||
func(null, written);
|
func(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return null if we could not open the file
|
// Return null if we could not open the file
|
||||||
|
|
Loading…
Reference in New Issue