Skip to content

Commit

Permalink
verify: pick up responders
Browse files Browse the repository at this point in the history
  • Loading branch information
indutny committed Apr 3, 2017
1 parent 0e1af74 commit 6ed19f0
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 27 deletions.
32 changes: 28 additions & 4 deletions lib/ocsp/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var asn1 = require('asn1.js');
var rfc2560 = require('asn1.js-rfc2560');

exports['id-ad-caIssuers'] = [ 1, 3, 6, 1, 5, 5, 7, 48, 2 ];
exports['id-kp-OCSPSigning'] = [ 1, 3, 6, 1, 5, 5, 7, 3, 9 ];

exports.getResponse = function getResponse(uri, req, cb) {
uri = url.parse(uri);
Expand Down Expand Up @@ -74,17 +75,40 @@ exports.parseResponse = function parseResponse(raw) {
var bytes = response.responseBytes.response;

var tbs = { start: body.start, end: body.end };
var certsTbs = [];
var basic = rfc2560.BasicOCSPResponse.decode(bytes, 'der', {
track: function(key, start, end, type) {
if (type !== 'tagged' || key !== 'tbsResponseData')
if (type !== 'tagged')
return;

tbs.start = body.start + start;
tbs.end = body.start + end;
if (key === 'tbsResponseData') {
tbs.start = body.start + start;
tbs.end = body.start + end;
} else if (key === 'certs/tbsCertificate') {
certsTbs.push({ start: body.start + start, end: body.start + end });
}
}
});

return { start: tbs.start, end: tbs.end, value: basic };
var OCSPSigning = exports['id-kp-OCSPSigning'].join('.');
var certs = (basic.certs || []).filter(function(cert) {
return cert.tbsCertificate.extensions.some(function(ext) {
if (ext.extnID !== 'extendedKeyUsage')
return false;

return ext.extnValue.some(function(value) {
return value.join('.') === OCSPSigning;
});
});
});

return {
start: tbs.start,
end: tbs.end,
value: basic,
certs: certs,
certsTbs: certsTbs
};
};

exports.digest = {
Expand Down
41 changes: 36 additions & 5 deletions lib/ocsp/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@ var ocsp = require('../ocsp');
var rfc5280 = require('asn1.js-rfc5280');
var crypto = require('crypto');

// TODO(indutny): verify issuer, etc...
function findResponder(issuer, certs, raws) {
var issuerKey = issuer.tbsCertificate.subjectPublicKeyInfo;
issuerKey = ocsp.utils.toPEM(
rfc5280.SubjectPublicKeyInfo.encode(issuerKey, 'der'), 'PUBLIC KEY');

for (var i = 0; i < certs.length; i++) {
var cert = certs[i];
var signAlg = ocsp.utils.sign[cert.signatureAlgorithm.algorithm.join('.')];
if (!signAlg) {
throw new Error('Unknown signature algorithm ' +
cert.signatureAlgorithm.algorithm);
}

var verify = crypto.createVerify(signAlg);

verify.update(raws[i]);
if (!verify.verify(issuerKey, cert.signature.data))
throw new Error('Invalid signature');

var certKey = cert.tbsCertificate.subjectPublicKeyInfo;
certKey = ocsp.utils.toPEM(
rfc5280.SubjectPublicKeyInfo.encode(certKey, 'der'), 'PUBLIC KEY');
return certKey;
}

return issuerKey;
}

module.exports = function verify(options, cb) {
var req = options.request;
var issuer;
Expand All @@ -26,27 +55,29 @@ module.exports = function verify(options, cb) {
}

var rawTBS = options.response.slice(res.start, res.end);
var certs = res.certs;
var raws = res.certsTbs.map(function(tbs) {
return options.response.slice(tbs.start, tbs.end);
});
res = res.value;

// Verify signature using CAs Public Key
// TODO(indutny): support other responders
var signAlg = ocsp.utils.sign[res.signatureAlgorithm.algorithm.join('.')];
if (!signAlg) {
done(new Error('Unknown signature algorithm ' +
res.signatureAlgorithm.algorithm));
return;
}

var responderKey = findResponder(issuer, certs, raws);

var verify = crypto.createVerify(signAlg);
var tbs = res.tbsResponseData;

var issuerKey = issuer.tbsCertificate.subjectPublicKeyInfo;
issuerKey = ocsp.utils.toPEM(
rfc5280.SubjectPublicKeyInfo.encode(issuerKey, 'der'), 'PUBLIC KEY');
var signature = res.signature.data;

verify.update(rawTBS);
if (!verify.verify(issuerKey, signature))
if (!verify.verify(responderKey, signature))
return done(new Error('Invalid signature'));

if (tbs.responses.length < 1)
Expand Down
36 changes: 18 additions & 18 deletions test/agent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ describe('OCSP Agent', function() {
a = new ocsp.Agent();
});

it('should connect and validate google.com', function(cb) {
var req = https.get({
host: 'www.google.com',
port: 443,
agent: a
}, function(res) {
res.resume();
cb();
});
});
var websites = [
'www.google.com',
'google.com',
'helloworld.letsencrypt.org',
'yahoo.com',
'nytimes.com',
'microsoft.com'
];

it('should connect and validate letsencrypt.org', function(cb) {
var req = https.get({
host: 'helloworld.letsencrypt.org',
port: 443,
agent: a
}, function(res) {
res.resume();
cb();
websites.forEach(function(host) {
it('should connect and validate ' + host, function(cb) {
var req = https.get({
host: host,
port: 443,
agent: a
}, function(res) {
res.resume();
cb();
});
});
});
});

0 comments on commit 6ed19f0

Please sign in to comment.