def generate_core_certificate(as_): """ Create or update the Core AS Certificate for `as_`. If the AS already has a Core AS Certificate, the version number is incremented for the new certificate. Requires that TRC for the related ISD exists/is up to date. :param AS as_: a core AS :returns: the Core AS Certificate as a dict """ isd = as_.isd assert isd.trc trc = TRC(isd.trc) if as_.core_certificate: version = as_.core_certificate['Version'] + 1 else: version = 1 cert = Certificate.from_values( subject=as_.isd_as_str(), issuer=as_.isd_as_str(), trc_version=trc.version, version=version, comment="Core AS Certificate", can_issue=True, validity_period=min(trc.exp_time - int(time.time()) - 1, CORE_AS_VALIDITY_PERIOD), subject_enc_key=b"", subject_sig_key=base64.b64decode(as_.core_sig_pub_key), iss_priv_key=base64.b64decode(as_.core_online_priv_key)) return cert.dict()
def prep_approved_join_reply(request, join_rep_dict, own_isdas, own_as_obj): """ Prepares the join reply for the APPROVED case. """ logger.info("New AS ID = %s", request.POST['newASId']) joining_as = request.POST['newASId'] is_core = request.POST['join_as_a_core'] sig_pub_key = from_b64(request.POST['sig_pub_key']) enc_pub_key = from_b64(request.POST['enc_pub_key']) signing_as_sig_priv_key = from_b64(own_as_obj.sig_priv_key) joining_ia = TopoID.from_values(own_isdas[0], joining_as) if is_core.lower() == "true": validity = Certificate.CORE_AS_VALIDITY_PERIOD comment = "Core AS Certificate" else: validity = Certificate.AS_VALIDITY_PERIOD comment = "AS Certificate" cert = Certificate.from_values( str(joining_ia), str(own_isdas), INITIAL_TRC_VERSION, INITIAL_CERT_VERSION, comment, is_core, validity, enc_pub_key, sig_pub_key, SigningKey(signing_as_sig_priv_key) ) respond_ia_chain = CertificateChain.from_raw(own_as_obj.certificate) request_ia_chain = CertificateChain([cert, respond_ia_chain.core_as_cert]) join_rep_dict['JoiningIA'] = str(joining_ia) join_rep_dict['IsCore'] = is_core.lower() == "true" join_rep_dict['RespondIA'] = str(own_isdas) join_rep_dict['JoiningIACertificate'] = request_ia_chain.to_json() join_rep_dict['RespondIACertificate'] = respond_ia_chain.to_json() join_rep_dict['TRC'] = TRC.from_raw(own_as_obj.trc).to_json() logger.debug("Accepting Join Request = %s", join_rep_dict)
def _create_trc(self, isd): quorum_trc = min(self.core_count[isd], MAX_QUORUM_TRC) self.trcs[isd] = TRC.from_values(isd, "ISD %s" % isd, INITIAL_TRC_VERSION, {}, {}, {}, THRESHOLD_EEPKI, {}, quorum_trc, MAX_QUORUM_CAS, INITIAL_GRACE_PERIOD, False, {}, DEFAULT_TRC_VALIDITY)
def _check_trc(self, isd, expected_core_ases, expected_version=None): """ Check the ISD's TRC and return it as a TRC object. :param ISD isd: :param [str] expected_core_ases: ISD-AS strings for all core ases :param int expected_version: optional :returns: TRC :rtype: TRC """ self.assertEqual(set(isd.trc['CoreASes'].keys()), set(expected_core_ases)) self.assertEqual(set(isd.trc_priv_keys.keys()), set(expected_core_ases)) for isd_as in expected_core_ases: utils.check_sig_keypair(self, isd.trc['CoreASes'][isd_as]['OnlineKey'], isd.trc_priv_keys[isd_as]) json_trc = json.dumps( isd.trc) # round trip through json, just to make sure this works trc = TRC.from_raw(json_trc) trc.check_active() if expected_version is not None: self.assertEqual(trc.version, expected_version) return trc
def check_trc(testcase, isd, expected_core_ases=None, expected_version=None, prev_trc=None): """ Check the ISD's TRC and return it as a TRC object. :param ISD isd: :param [str] expected_core_ases: optional, ISD-AS strings for all core ases :param int expected_version: optional, expected version for current TRC. :param TRC prev_trc: optional, previous TRC to verify current TRC. :returns: TRC :rtype: TRC """ if expected_core_ases is None: expected_core_ases = set(as_.isd_as_str() for as_ in isd.ases.filter(is_core=True)) testcase.assertEqual(set(isd.trc['CoreASes'].keys()), set(expected_core_ases)) testcase.assertEqual(set(isd.trc_priv_keys.keys()), set(expected_core_ases)) for isd_as in isd.trc['CoreASes'].keys(): check_sig_keypair(testcase, isd.trc['CoreASes'][isd_as]['OnlineKey'], isd.trc_priv_keys[isd_as]) json_trc = json.dumps( isd.trc) # round trip through json, just to make sure this works trc = TRC.from_raw(json_trc) trc.check_active() if expected_version is not None: testcase.assertEqual(trc.version, expected_version) if prev_trc is not None: trc.verify(prev_trc) return trc
def check_core_cert(testcase, as_, trc): """ Check that the AS's core certificate can be verified with the TRC. """ testcase.assertIsNotNone(as_.core_certificate) cert = Certificate(as_.core_certificate) isd_as = as_.isd_as_str() cert.verify(isd_as, TRC(trc).core_ases[isd_as]['OnlineKey'])
def check_cert_chain(testcase, as_, trc): """ Check that the AS's certificate chain can be verified with the TRC. """ testcase.assertIsNotNone(as_.certificate_chain) json_cert_chain = json.dumps(as_.certificate_chain) cert_chain = CertificateChain.from_raw(json_cert_chain) cert_chain.verify(as_.isd_as_str(), TRC(trc))
def _init_trcs(self): # pragma: no cover trcfiles = list(glob.glob("%s/*.trc" % self._dir)) trcfiles.extend( glob.glob("%s/%s-*.trc" % (self._cachedir, self._ename))) for path in trcfiles: trc_raw = read_file(path) self.add_trc(TRC.from_raw(trc_raw), write=False) logging.debug("Loaded: %s" % path)
def _cached_trcs_handler(self, raw_entries): """ Handles cached (through ZK) TRCs, passed as a list. """ for raw in raw_entries: trc = TRC.from_raw(raw.decode('utf-8')) rep = TRCReply.from_values(trc) self.process_trc_reply(rep, None, from_zk=True) logging.debug("Processed %s trcs from ZK", len(raw_entries))
def generate_trc(isd): """ Create or update the TRC for the given ISD. Returns the TRC as a dict and a dict containing the private keys needed to sign the next TRC version. :param ISD isd: :returns: (dict, dict) TRC, trc_priv_keys """ if isd.trc: version = isd.trc['Version'] + 1 else: version = 1 core_ases = list(isd.ases.filter(is_core=True)) core_ases_keys = { as_.isd_as_str(): { ONLINE_KEY_STRING: as_.core_online_pub_key, ONLINE_KEY_ALG_STRING: KEYGEN_ALG, OFFLINE_KEY_STRING: as_.core_offline_pub_key, OFFLINE_KEY_ALG_STRING: KEYGEN_ALG } for as_ in core_ases } trc = TRC.from_values(isd=isd.isd_id, description=str(isd), version=version, core_ases=core_ases_keys, root_cas={}, cert_logs={}, threshold_eepki=0, rains={}, quorum_trc=len(core_ases), quorum_cas=0, grace_period=0, quarantine=False, signatures={}, validity_period=TRC_VALIDITY_PERIOD) # Sign with private keys corresponding to public keys (core AS online public keys) in previous # TRC version # For initial version simply use the private online keys core_ases_online_priv_keys = { as_.isd_as_str(): as_.core_online_priv_key for as_ in core_ases } signing_keys = isd.trc_priv_keys or core_ases_online_priv_keys for isd_as, sig_priv_key in signing_keys.items(): trc.sign(isd_as, base64.b64decode(sig_priv_key)) # Return trc and signing keys for next version: # The keys and signatures are contained as bytes-objects in the dict returned, encode them return _base64encode_dict( trc.dict(with_signatures=True)), core_ases_online_priv_keys
class TRCReply(CertMgmtBase): # pragma: no cover NAME = "TRCReply" PAYLOAD_TYPE = CertMgmtType.TRC_REPLY P_CLS = P.TRCRep def __init__(self, p): super().__init__(p) self.trc = TRC(p.trc, lz4_=True) @classmethod def from_values(cls, trc): return cls(cls.P_CLS.new_message(trc=trc.pack(lz4_=True))) def short_desc(self): return "%sv%s" % self.trc.get_isd_ver() def __str__(self): isd, ver = self.trc.get_isd_ver() return "%s: ISD: %s version: %s TRC: %s" % (self.NAME, isd, ver, self.trc)
def prep_approved_join_reply(request, join_rep_dict, own_isdas, own_as_obj): """ Prepares the join reply for the APPROVED case. """ logger.info("New AS ID = %s", request.POST['newASId']) joining_as = request.POST['newASId'] is_core = request.POST['join_as_a_core'] sig_pub_key = from_b64(request.POST['sig_pub_key']) enc_pub_key = from_b64(request.POST['enc_pub_key']) signing_as_sig_priv_key = from_b64(own_as_obj.sig_priv_key) joining_ia = ISD_AS.from_values(own_isdas[0], joining_as) cert = Certificate.from_values(str(joining_ia), str(own_isdas), INITIAL_CERT_VERSION, "", False, enc_pub_key, sig_pub_key, SigningKey(signing_as_sig_priv_key)) respond_ia_chain = CertificateChain.from_raw(own_as_obj.certificate) request_ia_chain = CertificateChain([cert, respond_ia_chain.certs[0]]) join_rep_dict['JoiningIA'] = str(joining_ia) join_rep_dict['IsCore'] = is_core.lower() == "true" join_rep_dict['RespondIA'] = str(own_isdas) join_rep_dict['JoiningIACertificate'] = request_ia_chain.to_json() join_rep_dict['RespondIACertificate'] = respond_ia_chain.to_json() join_rep_dict['TRC'] = TRC.from_raw(own_as_obj.trc).to_json() logger.debug("Accepting Join Request = %s", join_rep_dict)
def _init_trcs(self): # pragma: no cover for path in glob.glob("%s/*.trc" % self._dir): trc_raw = read_file(path) self.add_trc(TRC.from_raw(trc_raw), write=False) logging.debug("Loaded: %s" % path)
def _check_cert_chain(self, as_, trc): self.assertIsNotNone(as_.certificate_chain) json_cert_chain = json.dumps(as_.certificate_chain) cert_chain = CertificateChain.from_raw(json_cert_chain) cert_chain.verify(as_.isd_as_str(), TRC(trc))
def _check_core_cert(self, as_, trc): self.assertIsNotNone(as_.core_certificate) cert = Certificate(as_.core_certificate) isd_as = as_.isd_as_str() cert.verify(isd_as, TRC(trc).core_ases[isd_as]['OnlineKey'])
log.add(e) log.build() # test building for each node log.build() # Policy trees should be consistent random.shuffle(all_) assert log.policy_tree.get_root() == Log(all_).policy_tree.get_root() return log if __name__ == "__main__": # PYTHONPATH=..:../scion ./tests.py tmp/msc.cert tmp/scp.cert ISD1-V0.trc if len(sys.argv) != 2: print("%s <TRC>" % sys.argv[0]) sys.exit(-1) with open(sys.argv[1], "r") as f: trc = TRC.from_raw(f.read()) # Load generated objects mscs, scps = load_mscs_scps() for domain_name in mscs: msc = mscs[domain_name] scp = scps[domain_name] # Verify MSC verifier(msc, scp, trc, domain_name) # Test basic packing and parsing test_pack_parse(msc, scp) mscsl = list(mscs.values()) scpsl = list(scps.values()) # Test log operations log = test_log_local(mscsl, scpsl) # Test proofs test_proofs(log, mscsl, scpsl)
def _create_trc(self, isd): self.trcs[isd] = TRC.from_values(isd, "ISD %s" % isd, 0, {}, {}, {}, 2, 'dns_srv_addr', 2, 3, 18000, True, {})
def _create_trc(self, isd): self.trcs[isd] = TRC.from_values(isd, 0, {}, {'ca.com': 'ca.com_cert_base64'}, {}, 2, 'dns_srv_addr', 'dns_srv_cert', 2, 3, 2, True, {}, 18000)
def __init__(self, p): super().__init__(p) self.trc = TRC.from_raw(p.trc, lz4_=True)
def _create_trc(self, isd): validity_period = TRC.VALIDITY_PERIOD self.trcs[isd] = TRC.from_values(isd, "ISD %s" % isd, INITIAL_TRC_VERSION, {}, {}, {}, 2, {}, 2, 3, 18000, False, {}, validity_period)