def verify(self, subject, issuer_cert): """ Perform one step verification. :param str subject: the certificate subject. It can either be an AS, an email address or a domain address. :param str issuer_cert: the certificate issuer. It can only be an AS. :raises: SCIONVerificationError if the verification fails. """ if subject != self.subject: raise SCIONVerificationError( "The given subject (%s) doesn't match the certificate's subject (%s):\n%s" % (subject, self.subject, self)) if int(time.time()) >= self.expiration_time: raise SCIONVerificationError("This certificate expired:\n%s" % self) if int(time.time()) >= issuer_cert.expiration_time: raise SCIONVerificationError( "The issuer certificate expired:\n%s" % issuer_cert) try: self._verify_signature(self.signature_raw, issuer_cert.subject_sig_key_raw) except SCIONVerificationError: raise SCIONVerificationError("Signature verification failed:\n%s" % self)
def verify(self, subject, trc): """ Perform the entire chain verification. First verifies the AS certificate against the core AS certificate, then verifies the core AS certificate against the TRC. :param str subject: the subject of the first certificate in the certificate chain. :param trc: TRC containing all root of trust certificates for one ISD. :type trc: :class:`TRC` :raises: SCIONVerificationError if the verification fails. """ # Verify AS certificate against core AS certificate try: self.as_cert.verify(subject, self.core_as_cert.subject_sig_key_raw) except SCIONVerificationError as e: raise SCIONVerificationError( "AS certificate verification failed: %s" % e) # Verify core AS certificate against TRC try: self.core_as_cert.verify( self.as_cert.issuer, trc.core_ases[self.core_as_cert.issuer][ONLINE_KEY_STRING]) except SCIONVerificationError as e: raise SCIONVerificationError( "Core AS certificate verification failed: %s" % e)
def verify_sig_chain_trc(msg, sig, subject, chain, trc): """ Verify whether the packed message with attached signature is validly signed by a particular subject belonging to a valid certificate chain. :param bytes msg: message corresponding to the given signature. :param bytes sig: signature computed on msg. :param ISD_AS subject: signer identity. :param CertificateChain chain: Certificate chain containing the signing entity's certificate. :param TRC trc: Issuing TRC containing all root of trust certificates for one ISD. :raises: SCIONVerificationError if the verification fails. """ assert isinstance(chain, CertificateChain) assert isinstance(trc, TRC) subject = str(subject) try: chain.verify(subject, trc) except SCIONVerificationError as e: raise SCIONVerificationError( "The certificate chain verification failed:\n%s" % e) verifying_key = None for signer_cert in chain.certs: if signer_cert.subject == subject: verifying_key = signer_cert.subject_sig_key_raw break if verifying_key is None: if subject not in trc.core_ases: raise SCIONVerificationError( "Signer's public key has not been found: %s" % subject) verifying_key = trc.core_ases[subject].subject_sig_key_raw verify(msg, sig, verifying_key)
def verify(self, subject, verifying_key): """ Perform one step verification. :param str subject: the certificate subject. It can either be an AS, an email address or a domain address. :param bytes verifying_key: the key to be used for signature verification. :raises: SCIONVerificationError if the verification fails. """ if self.version == 0: raise SCIONVerificationError("Invalid certificate version 0:\n%s" % self) if subject != self.subject: raise SCIONVerificationError( "The given subject (%s) doesn't match the certificate's subject (%s):\n%s" % (subject, self.subject, self)) if int(time.time()) >= self.expiration_time: raise SCIONVerificationError("This certificate expired:\n%s" % self) try: self._verify_signature(self.signature_raw, verifying_key) except SCIONVerificationError: raise SCIONVerificationError("Signature verification failed:\n%s" % self)
def verify(self, subject, trc): """ Perform the entire chain verification. It verifies each pair and at the end verifies the last certificate of the chain with the root certificate that was used to sign it. :param str subject: the subject of the first certificate in the certificate chain. :param trc: TRC containing all root of trust certificates for one ISD. :type trc: :class:`TRC` :raises: SCIONVerificationError if the verification fails. """ if not self.certs: raise SCIONVerificationError( "The certificate chain is not initialized.") cert = self.certs[0] for issuer_cert in self.certs[1:]: if issuer_cert.subject == subject: break cert.verify(subject, issuer_cert) cert = issuer_cert subject = cert.subject # First check whether a root cert was added to the chain. if cert.issuer != subject: raise SCIONVerificationError( "Root Certificate added to chain:\n%s" % cert) # Try to find a root cert in the trc. try: cert.verify_core(trc.core_ases[cert.issuer][ONLINE_KEY_STRING]) except SCIONVerificationError: raise SCIONVerificationError( "Core AS certificate verification failed.")
def _verify_drkey_reply(self, rep, meta): """ Verify that the first order DRKey reply is legit. I.e. the signature matches, timestamp is recent. :param DRKeyReply rep: the first order DRKey reply. :param UDPMetadata meta: the metadata. :returns Certificate of the responder. :rtype: Certificate :raises: SCIONVerificationError """ if meta and meta.ia != rep.isd_as: raise SCIONVerificationError("Response from other ISD-AS: %s" % rep.isd_as) if drkey_time() - rep.p.timestamp > DRKEY_REQUEST_TIMEOUT: raise SCIONVerificationError("Expired reply from %s. %ss old. Max %ss" % ( rep.isd_as, drkey_time() - rep.p.timestamp, DRKEY_REQUEST_TIMEOUT)) trc = self.trust_store.get_trc(rep.isd_as[0]) chain = self.trust_store.get_cert(rep.isd_as, rep.p.certVerSrc) err = [] if not chain: self._send_cc_request(rep.isd_as, rep.p.certVerSrc) err.append("Certificate not present for %s(v: %s)" % (rep.isd_as, rep.p.certVerSrc)) if not trc: self._send_trc_request(rep.isd_as[0], rep.p.trcVer, rep.isd_as[1]) err.append("TRC not present for %s(v: %s)" % (rep.isd_as[0], rep.p.trcVer)) if err: raise SCIONVerificationError(", ".join(err)) raw = get_signing_input_rep(rep.isd_as, rep.p.timestamp, rep.p.expTime, rep.p.cipher) try: verify_sig_chain_trc(raw, rep.p.signature, rep.isd_as, chain, trc) except SCIONVerificationError as e: raise SCIONVerificationError(str(e)) return chain.certs[0]
def _verify_drkey_request(self, req, meta): """ Verify that the first order DRKey request is legit. I.e. the signature is valid, the correct ISD AS is queried, timestamp is recent. :param DRKeyRequest req: the first order DRKey request. :param UDPMetadata meta: the metadata. :returns Certificate of the requester. :rtype: Certificate :raises: SCIONVerificationError """ if self.addr.isd_as != req.isd_as: raise SCIONVerificationError("Request for other ISD-AS: %s" % req.isd_as) if drkey_time() - req.p.timestamp > DRKEY_REQUEST_TIMEOUT: raise SCIONVerificationError("Expired request from %s. %ss old. Max %ss" % ( meta.ia, drkey_time() - req.p.timestamp, DRKEY_REQUEST_TIMEOUT)) trc = self.trust_store.get_trc(meta.ia[0]) chain = self.trust_store.get_cert(meta.ia, req.p.certVer) err = [] if not chain: self._send_cc_request(meta.ia, req.p.certVer) err.append("Certificate not present for %s(v: %s)" % (meta.ia, req.p.certVer)) if not trc: self._send_trc_request(meta.ia[0], req.p.trcVer, meta.ia[1]) err.append("TRC not present for %s(v: %s)" % (meta.ia[0], req.p.trcVer)) if err: raise SCIONVerificationError(", ".join(err)) raw = drkey_signing_input_req(req.isd_as, req.p.flags.prefetch, req.p.timestamp) try: verify_sig_chain_trc(raw, req.p.signature, meta.ia, chain, trc) except SCIONVerificationError as e: raise SCIONVerificationError(str(e)) return chain.certs[0]
def check_active(self, max_trc=None): """ Check if trusted TRC is active and can be used for certificate chain verification. :param TRC max_trc: newest available TRC for same ISD. (If none, self is newest TRC) :raises: SCIONVerificationError """ if self.quarantine: raise SCIONVerificationError("Early announcement") now = int(time.time()) if not (self.create_time <= now <= self.exp_time): raise SCIONVerificationError( "Current time outside of validity period. " "Now %s Creation %s Expiration %s" % (now, self.create_time, self.exp_time)) if not max_trc or self.version == max_trc.version: return if self.version + 1 != max_trc.version: raise SCIONVerificationError( "Inactive TRC version: %s. Expected %s or %s" % (self.version, max_trc.version, max_trc.version - 1)) if now > max_trc.create_time + max_trc.grace_period: raise SCIONVerificationError( "TRC grace period has passed. Now %s Expiration %s" % (now, max_trc.create_time + max_trc.grace_period))
def verify_chain_trc(subject, chain, trc): """ Verify the certificate chain for subject. """ subject = str(subject) try: chain.verify(subject, trc) except SCIONVerificationError as e: raise SCIONVerificationError("The certificate chain verification failed:\n%s" % e)
def _verify_exp_time(self, exp_time, chain): """ Verify that certificate chain cover the expiration time. :raises SCIONVerificationError """ # chain is only verifiable if TRC.exp_time >= CoreCert.exp_time >= LeafCert.exp_time if chain.as_cert.expiration_time < exp_time: raise SCIONVerificationError( "Certificate chain %sv%s expires before path segment" % chain.get_leaf_isd_as_ver())
def verify_update(self, old_trc): """ Verify TRC update. Unsuccessful verification raises an error. :param TRC old_trc: a verified TRC, used as a trust anchor. :raises: SCIONVerificationError """ if old_trc.isd != self.isd: raise SCIONVerificationError("Invalid TRC ISD %s. Expected %s" % ( self.isd, old_trc.isd)) if old_trc.version + 1 != self.version: raise SCIONVerificationError("Invalid TRC version %s. Expected %s" % ( self.version, old_trc.version + 1)) if self.create_time < old_trc.create_time + old_trc.grace_period: raise SCIONVerificationError("Invalid timestamp %s. Expected > %s " % ( self.create_time, old_trc.create_time + old_trc.grace_period)) if self.quarantine or old_trc.quarantine: raise SCIONVerificationError("Early announcement") self._verify_signatures(old_trc)
def verify(self, trusted_trc): """ Verify TRC based on a trusted TRC. :param TRC trusted_trc: a verified TRC, used as a trust anchor. :raises: SCIONVerificationError """ if self.version == 0: raise SCIONVerificationError("Invalid TRC version 0") if self.isd == trusted_trc.isd: self.verify_update(trusted_trc) else: self.verify_xsig(trusted_trc)
def verify(msg, sig, verifying_key): """ Verify a signature. :param bytes msg: message that was signed. :param bytes sig: signature to verify. :param bytes verifying_key: verifying key from generate_signature_keypair(). :returns: True or False whether the verification succeeds or fails. :rtype: boolean """ try: return msg == VerifyKey(verifying_key).verify(msg, sig) except BadSignatureError: raise SCIONVerificationError("Signature corrupt or forged.") from None
def verify(self, spld: SignedCtrlPayload) -> bool: """ Verify checks if the signed control payload can be verified. If not, an error is raised. :param SignedCtrlPayload spld: the signed control payload to be verified. :returns: whether the verification was successful. :rtype: bool :raises: SCIONVerificationError """ try: cpld = spld.pld() except SCIONParseError as e: raise SCIONVerificationError( "Unable to unpack control payload. Error: %s" % e) from None if self.ignore_sign(cpld): return True try: vkey = self.get_verifying_key(spld.psign) except (SCIONKeyError, SCIONParseError, SCIONVerificationError) as e: raise SCIONVerificationError( "Unable to fetch verifying key. Error: %s" % e) from None return spld.verify(vkey)
def verify_sig_chain_trc(msg, sig, subject, chain, trc): """ Verify whether the packed message with attached signature is validly signed by a particular subject belonging to a valid certificate chain. :param bytes msg: message corresponding to the given signature. :param bytes sig: signature computed on msg. :param ISD_AS subject: signer identity. :param CertificateChain chain: Certificate chain containing the signing entity's certificate. :param TRC trc: Issuing TRC containing all root of trust certificates for one ISD. :raises: SCIONVerificationError if the verification fails. """ assert isinstance(chain, CertificateChain), type(chain) assert isinstance(trc, TRC), type(trc) verify_chain_trc(subject, chain, trc) verifying_key = chain.as_cert.subject_sig_key_raw if not verifying_key: raise SCIONVerificationError("Signer's public key has not been found: %s" % subject) verify(msg, sig, verifying_key)
def _verify_signatures(self, old_trc): """ Perform signature verification for core signatures as defined in old TRC. Raises an error if verification is unsuccessful. :param: TRC old_trc: the previous TRC which has already been verified. :raises: SCIONVerificationError """ # Only look at signatures which are from core ASes as defined in old TRC val_count = 0 # Count number of verifiable signatures for signer in old_trc.core_ases.keys(): public_key = old_trc.core_ases[signer][ONLINE_KEY_STRING] try: verify(self._sig_input(), self.signatures[signer], public_key) val_count += 1 except (SCIONVerificationError, KeyError): continue # Check if enough valid signatures if val_count < old_trc.quorum_trc: raise SCIONVerificationError("Not enough valid signatures %s. Expected %s" % ( val_count, old_trc.quorum_trc))
def verify(self, subject, trc): """ Perform the entire chain verification. First verifies the AS certificate against the core AS certificate, then verifies the core AS certificate against the TRC. :param str subject: the subject of the first certificate in the certificate chain. :param trc: TRC containing all root of trust certificates for one ISD. :type trc: :class:`TRC` :raises: SCIONVerificationError if the verification fails. """ # Verify AS certificate against core AS certificate leaf = self.as_cert core = self.core_as_cert if leaf.issuing_time < core.issuing_time: raise SCIONVerificationError( "AS certificate verification failed: Leaf issued before core certificate. Leaf: %s " "Core: %s" % (iso_timestamp( leaf.issuing_time), iso_timestamp(core.issuing_time))) if leaf.expiration_time > core.expiration_time: raise SCIONVerificationError( "AS certificate verification failed: Leaf expires after core certificate. Leaf: %s " "Core: %s" % (iso_timestamp(leaf.expiration_time), iso_timestamp(core.expiration_time))) if not core.can_issue: raise SCIONVerificationError( "AS certificate verification failed: Core certificate cannot issue certificates" ) try: leaf.verify(subject, core.subject_sig_key_raw) except SCIONVerificationError as e: raise SCIONVerificationError( "AS certificate verification failed: %s" % e) # Verify core AS certificate against TRC if core.expiration_time > trc.exp_time: raise SCIONVerificationError( "Core AS certificate verification failed: Core certificate expires after TRC. " "Core: %s TRC: %s" % (iso_timestamp( core.expiration_time), iso_timestamp(trc.exp_time))) try: core.verify(leaf.issuer, trc.core_ases[core.issuer][ONLINE_KEY_STRING]) except SCIONVerificationError as e: raise SCIONVerificationError( "Core AS certificate verification failed: %s" % e)