Files
safetynet/tests/broker-certificate-pins.test.mjs

40 lines
3.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
const require=createRequire(import.meta.url);
const {createBrokerCertificatePins,authorityFacts}=require('../apps/browser/broker-certificate-pins.cjs');
const {createSessionCertificates}=require('../apps/network-broker/tls-certificates.cjs');
test('exact session leaf accepted; other certificates use platform trust and revocation rejects known leaf',async()=>{
let current=true;const issuer=await createSessionCertificates({current:()=>true,authorized:()=>true});
const pins=createBrokerCertificatePins({generation:'synthetic-generation',policyVersion:4,current:()=>current,authorizedAuthority:()=>true});
try{
const leaf=issuer.publicMetadata({authority:'example.com:443'});
assert.equal(pins.accept({...leaf,generation:'synthetic-generation',policyVersion:4}),true);
const verify=(hostname,data)=>{let result;pins.verify({hostname,certificate:{data,fingerprint:leaf.fingerprint256}},code=>result=code);return result;};
assert.equal(verify('example.com',leaf.cert),0);
assert.equal(verify('attacker.test',leaf.cert),-3);
assert.equal(verify('example.com','unrelated-public-certificate'),-3);
current=false;assert.equal(verify('example.com',leaf.cert),-2);
current=true;pins.revoke();assert.equal(verify('example.com',leaf.cert),-2);
}finally{issuer.close();}
});
test('wrong generation, policy, SAN, fingerprint and unauthorized destination cannot publish pins',async()=>{
const issuer=await createSessionCertificates({current:()=>true,authorized:()=>true});
try{const leaf=issuer.publicMetadata({authority:'example.com:443'}),input={...leaf,generation:'one',policyVersion:4};
for(const patch of [{generation:'two'},{policyVersion:3},{authority:'attacker.test:443'},{fingerprint256:'wrong'},{cert:leaf.cert+'private trailing payload'},{cert:leaf.cert+leaf.cert}]){
const pins=createBrokerCertificatePins({generation:'one',policyVersion:4,current:()=>true,authorizedAuthority:()=>true});
assert.throws(()=>pins.accept({...input,...patch}),/broker-certificate-pin-rejected/);assert.equal(pins.status().pins,0);
}
const denied=createBrokerCertificatePins({generation:'one',policyVersion:4,current:()=>true,authorizedAuthority:()=>false});assert.throws(()=>denied.accept(input));
}finally{issuer.close();}
});
test('noncanonical authority and pin capacity cannot weaken trust',async()=>{
for(const value of ['127.1:443','EXAMPLE.com:443','example.com:0443','example.com:65536','example.com:[email protected]','[0:0:0:0:0:0:0:1]:443'])assert.throws(()=>authorityFacts(value));
assert.equal(authorityFacts('[::1]:443').hostname,'::1');
const issuer=await createSessionCertificates({current:()=>true,authorized:()=>true});
const pins=createBrokerCertificatePins({generation:'one',policyVersion:4,current:()=>true,authorizedAuthority:()=>true,maxPins:1});
try{for(const [index,authority]of ['example.com:443','other.test:443'].entries()){
const input={...issuer.publicMetadata({authority}),generation:'one',policyVersion:4};if(index===0)assert.equal(pins.accept(input),true);else assert.throws(()=>pins.accept(input));
}}finally{issuer.close();}
});