Exemple #1
0
    def assertSignature(  # pylint: disable=invalid-name
        self,
        chain: typing.Iterable[CertificateAuthority],
        cert: typing.Union[Certificate, CertificateAuthority],
    ) -> None:
        """Assert that `cert` is properly signed by `chain`.

        .. seealso:: http://stackoverflow.com/questions/30700348
        """
        store = X509Store()

        # set the time of the OpenSSL context - freezegun doesn't work, because timestamp comes from OpenSSL
        now = datetime.utcnow()
        store.set_time(now)

        for elem in chain:
            ca = load_certificate(FILETYPE_PEM, elem.pub.pem.encode())
            store.add_cert(ca)

            # Verify that the CA itself is valid
            store_ctx = X509StoreContext(store, ca)
            self.assertIsNone(store_ctx.verify_certificate())  # type: ignore[func-returns-value]

        loaded_cert = load_certificate(FILETYPE_PEM, cert.pub.pem.encode())
        store_ctx = X509StoreContext(store, loaded_cert)
        self.assertIsNone(store_ctx.verify_certificate())  # type: ignore[func-returns-value]
Exemple #2
0
    def verifyChainOfTrust(self, cert):
        if cert is None:
            return None
        storecontext = None

        certx509 = load_certificate(FILETYPE_PEM, cert)

        storecontext = X509StoreContext(self.ccStoreContext,
                                        certx509).verify_certificate()

        # try:
        #     certx509 = load_certificate(FILETYPE_PEM, cert)
        #     storecontext = X509StoreContext(self.ccStoreContext, certx509).verify_certificate()
        # except X509StoreContextError as strerror:
        #     #print("Impossible to verify the certificate given for the store context: \n{:s}".format(strerror.__doc__))
        #     return False
        # except Error as strerror:
        #     #print(ERROR,"The certificate to be verified wasn't loaded: \n Error Information:{:s}".format(strerror.__doc__))
        #     return False

        if storecontext is None:
            print("The smartcard  was sucessfully verified")
            return True
        else:
            return False
Exemple #3
0
def verify_chain(chain_path, cert_bytes_or_path):
    try:
        # If certificate bytes are passed load the certificate
        cert = load_certificate(FILETYPE_PEM, cert_bytes_or_path)
    except:
        # If certificate path is passed open the certificate and load it's bytes
        cert = load_certificate(FILETYPE_PEM,
                                open(cert_bytes_or_path, 'rb').read())

    chain_bytes = open(chain_path, 'rb').read()
    parts = chain_bytes.split(b'-----\n-----')
    n_certs = len(parts)

    store = X509Store()
    if n_certs == 1:
        store.add_cert(load_certificate(FILETYPE_PEM, parts[0]))
    else:
        cert_list = []
        store.add_cert(load_certificate(FILETYPE_PEM, (parts[0] + b'-----\n')))
        store.add_cert(load_certificate(FILETYPE_PEM, (b'-----' + parts[-1])))
        for i in parts[1:-1]:
            store.add_cert(
                load_certificate(FILETYPE_PEM, (b'-----' + i + b'-----\n')))

    store_ctx = X509StoreContext(store, cert)
    try:
        if store_ctx.verify_certificate() == None:
            return True
    except:
        return False
Exemple #4
0
    def validate_certificate(self,
                             certificate: str,
                             chain: str,
                             crl: str = None) -> None:
        """
        Tests if a certificate has been signed by the chain, is not revoked
        and has not yet been expired.
        :param certificate: the certificate to test as string
        :param chain: the certificate chain file content as string
        :param crl: the certificate revocation list file content as string
        :raises: InvalidCertificateException if the certificate is invalid
        :return: None
        """
        # root and intermediary certificate need to be split
        cas = pem.parse(chain.encode())
        store = X509Store()
        for ca in cas:
            store.add_cert(self._to_cert(str(ca)))

        cert = self._to_cert(certificate)

        if crl:
            parsed_crl = load_crl(FILETYPE_PEM, crl)
            store.set_flags(X509StoreFlags.CRL_CHECK)
            store.add_crl(parsed_crl)

        ctx = X509StoreContext(store, cert)
        err_msg = 'Certificate is invalid'

        try:
            result = ctx.verify_certificate()
            if result is not None:
                raise InvalidCertificateException(err_msg)
        except Exception as e:
            raise InvalidCertificateException('%s: %s' % (err_msg, str(e)))
    def verify_key_chain(peer_cert):
        root_cert = Encrypt.get_root_cert()
        root_cert = crypto.X509.from_cryptography(root_cert)
        peer_cert = crypto.X509.from_cryptography(peer_cert)

        store = X509Store()
        store.add_cert(root_cert)
        store_ctx = X509StoreContext(store, peer_cert)
        store_ctx.verify_certificate()
Exemple #6
0
    def assertSignature(self, chain, cert):
        # see: http://stackoverflow.com/questions/30700348
        store = X509Store()
        for elem in chain:
            store.add_cert(load_certificate(FILETYPE_PEM, elem.dump_certificate()))

        cert = load_certificate(FILETYPE_PEM, cert.dump_certificate())
        store_ctx = X509StoreContext(store, cert)
        self.assertIsNone(store_ctx.verify_certificate())
Exemple #7
0
def validate_cert(store, cert):
    store_ctx = X509StoreContext(store, cert)
    subject = cert.get_subject()
    try:
        store_ctx.verify_certificate()
        print('certificate %s is valid against CRL' % subject)
    except Exception as e:
        print('certificate %s is NOT valid against CRL' % subject)
        print(e)
Exemple #8
0
def submitProxy():
    """
    Submit a proxy certificate of a user.

    This operation requires user to provide personal certificate as
    client certificate in request. Proxy certificate that is to be submitted
    should be provided as raw data in request body.

    Function first verifies user's personal certificate against a
    CA certificate. If verification is successful, it procedes to read proxy
    certificate in body and insert it to database.

    Returns:
        status 200: A string with ID of a proxy certificate.
        status 401 or 500: A string with error message.
    """
    # The following validation procedure is done as per:
    # https://stackoverflow.com/questions/30700348/how-to-validate-verify-an-x509-certificate-chain-of-trust-in-python

    # user pem is client certificate in header
    user_pem = getCertString()
    if not user_pem:
        return 'Wrong or no client certificate', 401

    # get pem for CA
    caPath = os.path.join(os.environ['PATH'].split(':')[-1], 'ca.pem')
    try:
        caFile = open(caPath, 'r')  # TODO: ca.pem in bin directory
    except Exception as e:
        return 'Server error: {}'.format(str(e)), 500
    else:
        root_pem = caFile.read()
        caFile.close()

    # verify
    root_cert = load_certificate(FILETYPE_PEM, root_pem)
    user_cert = load_certificate(FILETYPE_PEM, user_pem)
    store = X509Store()
    store.add_cert(root_cert)
    store_ctx = X509StoreContext(store, user_cert)
    try:
        store_ctx.verify_certificate()
    except Exception as e:
        return 'Client certificate verification failed', 401

    pmgr = proxymgr.ProxyManager()  # TODO: handle error with pmgr and jmgr

    try:
        # TODO: ARC API does not fail when given genproxy script as proxy!!!!
        proxyStr = request.get_data()
        dn, exp_time = pmgr.readProxyString(proxyStr)
        proxyid = pmgr.actproxy.updateProxy(proxyStr, dn, '', exp_time)
    except Exception as e:
        return 'Server error: {}'.format(str(e)), 500
    else:
        return json.dumps(proxyid)
Exemple #9
0
    def assertSignature(self, chain, cert):
        # see: http://stackoverflow.com/questions/30700348
        store = X509Store()

        # set the time of the OpenSSL context - freezegun doesn't work, because timestamp comes from OpenSSL
        now = datetime.utcnow()
        store.set_time(now)

        for elem in chain:
            ca = load_certificate(FILETYPE_PEM, elem.dump_certificate())
            store.add_cert(ca)

            # Verify that the CA itself is valid
            store_ctx = X509StoreContext(store, ca)
            self.assertIsNone(store_ctx.verify_certificate())

        cert = load_certificate(FILETYPE_PEM, cert.dump_certificate())
        store_ctx = X509StoreContext(store, cert)
        self.assertIsNone(store_ctx.verify_certificate())
def verify_certs(certs, ca_certs):
    # Initialize trust store with CA certificates
    store = X509Store()
    for cert in ca_certs:
        store.add_cert(cert)

    # Incrementally build up trust by first checking intermedaries
    for cert in reversed(certs):
        store_ctx = X509StoreContext(store, cert)
        store_ctx.verify_certificate()
        # Add intermediary to trust
        store.add_cert(cert)
Exemple #11
0
    def verify_against_ca(self):
        if not hasattr(self, '_trusted_ca'):
            raise VerificationError(str(self), 'did not load trusted CA')

        store = X509Store()
        store.add_cert(self._trusted_ca._x509)
        store_ctx = X509StoreContext(store, self._x509)
        try:
            store_ctx.verify_certificate()
        except X509StoreContextError as e:
            # [20, 0, 'unable to get local issuer certificate']
            raise VerificationError(str(self), *e.args)
Exemple #12
0
def _add_cert_to_store(store, cert):
    from OpenSSL.crypto import X509StoreContext, X509StoreContextError, Error as OpenSSLCryptoError
    try:
        X509StoreContext(store, cert).verify_certificate()
    except X509StoreContextError as e:
        raise InvalidCertificate(e)
    try:
        store.add_cert(cert)
        return cert
    except OpenSSLCryptoError as e:
        if e.args == ([('x509 certificate routines', 'X509_STORE_add_cert', 'cert already in hash table')],):
            raise RedundantCert(e)
        raise
Exemple #13
0
 def verifyChainOfTrust(self, cert):
     if cert is None:
         return None
     cert = base64.b64decode(cert)
     storecontext = None
     certx509 = load_certificate(FILETYPE_PEM, cert)
     storecontext = X509StoreContext(self.ccStoreContext,
                                     certx509).verify_certificate()
     if storecontext is None:
         print("The smartcard  was sucessfully verified")
         return True
     else:
         return False
Exemple #14
0
 def validate_chain(self, file_names, last_cert):
     store = X509Store()
     for cert_file in file_names:
         with open(cert_file, 'rb') as f:
             cert = load_certificate(FILETYPE_PEM, f.read())
             store.add_cert(cert)
     store_ctx = X509StoreContext(store,
                                  load_certificate(FILETYPE_PEM, last_cert))
     result = store_ctx.verify_certificate()
     if result is None:
         return True
     else:
         return False
Exemple #15
0
def verify_chain_of_trust(cert, ccStoreContext):
    if cert is None:
        return None
    cert = base64.b64decode(cert)
    storecontext = None
    try:
        certx509 = load_certificate(FILETYPE_PEM, cert)
        storecontext = X509StoreContext(ccStoreContext,
                                        certx509).verify_certificate()
    except OpenSSL.crypto.X509StoreContextError as e:
        return False
    if storecontext is None:
        #print("The smartcard  was sucessfully verified")
        return True
    else:
        return False
Exemple #16
0
def is_self_signed(cert: X509) -> bool:
    """
    Checks if a X509 certificate is self signed.
    """
    store = X509Store()
    store.add_cert(cert)
    validfrom_time = cert.get_notBefore()
    validfrom_datetime = datetime.strptime(validfrom_time.decode("utf-8"),
                                           "%Y%m%d%H%M%SZ")
    store.set_time(validfrom_datetime)
    store_ctx = X509StoreContext(store, cert)
    try:
        store_ctx.verify_certificate()
        return True
    except X509StoreContextError:
        return False
Exemple #17
0
 def verify_certificate(self, crt=None, cacrt=None):
     try:
         cert = load_certificate(FILETYPE_PEM, crt)
         intermediate_cert = load_certificate(FILETYPE_PEM, cacrt)
         validation_cert = load_certificate(FILETYPE_PEM, cacrt)
         store = X509Store()
         store.add_cert(intermediate_cert)
         store.add_cert(cert)
         store_ctx = X509StoreContext(store, validation_cert)
         if (store_ctx.verify_certificate() == None):
             print "Certificate verification Passed on Client side"
             return True
         else:
             raise Exception(
                 "Certificate Verification Failed on Client side")
     except Exception as e:
         raise Exception("Certificate Validation Failed on Client side", e)
Exemple #18
0
def estissuer_create(spec, patch, body, **_):
    """validate and mark issuers as ready"""
    # Secret must exist and be the correct type
    secret = get_secret_from_resource(body)
    if secret is None:
        raise kopf.TemporaryError(f"{spec['secretName']} not found")
    baseUrl = f"https://{spec['host']}:{spec.get('port', 443)}"
    path = "/".join(
        i for i in [WELLKNOWN, spec.get("label"), "cacerts"] if i is not None)
    # fetch /cacerts using explicit TA
    cacert = base64.b64decode(spec["cacert"])
    with tempfile.NamedTemporaryFile(suffix=".pem") as cafile:
        cafile.write(cacert)
        cafile.seek(0)
        session = requests.Session()
        session.mount(baseUrl, SSLContextAdapter())
        try:
            response = session.get(baseUrl + path, verify=cafile.name)
        except (
                requests.exceptions.SSLError,
                requests.exceptions.RequestException,
        ) as err:
            patch.metadata.annotations["estoperator-perm-fail"] = "yes"
            raise kopf.PermanentError(err) from err
    # 200 OK is good, anything else is an error
    if response.status_code != 200:
        raise kopf.TemporaryError(
            f"Unexpected response: {response.status}, {response.reason}", )
    # configured cacert must be in EST portal bundle
    explicit = pem.parse(cacert)
    store = X509Store()
    for cert in explicit:
        store.add_cert(load_certificate(FILETYPE_PEM, cert.as_text()))
    try:
        for leaf in pkcs7.load_der_pkcs7_certificates(
                base64.b64decode(response.content)):
            context = X509StoreContext(
                store,
                load_certificate(FILETYPE_PEM,
                                 leaf.public_bytes(Encoding.PEM)),
            )
            context.verify_certificate()
    except X509StoreContextError as err:
        raise kopf.PermanentError(
            f"Unable to verify /cacerts content: {err}") from err
    return {"Ready": "True"}
Exemple #19
0
    def validate_cert(chain, leaf):
        from datetime import timedelta
        from OpenSSL.crypto import X509, X509Store, X509StoreContext, X509StoreContextError

        store = X509Store()
        store.set_time(leaf.not_valid_before + timedelta(days=1))
        for c in chain:
            store.add_cert(X509.from_cryptography(c))

        x509_leaf = X509.from_cryptography(leaf)
        ctx = X509StoreContext(store, x509_leaf)
        try:
            ctx.verify_certificate()
        except X509StoreContextError as e:
            return False

        return True
Exemple #20
0
def _verify_report(as_root_ca_cert_path: str, enclave_info_path: str,
                   cert: Dict[str, Any], endpoint_name: str):
    if os.environ.get('SGX_MODE') == 'SW':
        return

    cert = x509.load_der_x509_certificate(cert, default_backend())
    ext = json.loads(cert.extensions[0].value.value)
    # print("ext = ", ext)

    report = bytes(ext["report"])
    signature = bytes(ext["signature"])
    signing_cert = bytes(ext["signing_cert"])
    signing_cert = load_certificate(FILETYPE_ASN1, signing_cert)

    # verify signing cert with AS root cert
    with open(as_root_ca_cert_path) as f:
        as_root_ca_cert = f.read()
    as_root_ca_cert = load_certificate(FILETYPE_PEM, as_root_ca_cert)
    store = X509Store()
    store.add_cert(as_root_ca_cert)
    store.add_cert(signing_cert)
    store_ctx = X509StoreContext(store, as_root_ca_cert)
    store_ctx.verify_certificate()

    # verify report's signature
    crypto.verify(signing_cert, signature, bytes(ext["report"]), 'sha256')

    report = json.loads(report)
    quote = report['isvEnclaveQuoteBody']
    quote = base64.b64decode(quote)

    # get mr_enclave and mr_signer from the quote
    mr_enclave = quote[112:112 + 32].hex()
    mr_signer = quote[176:176 + 32].hex()

    # get enclave_info
    enclave_info = toml.load(enclave_info_path)

    # verify mr_enclave and mr_signer
    enclave_name = "teaclave_" + endpoint_name + "_service"
    if mr_enclave != enclave_info[enclave_name]["mr_enclave"]:
        raise Exception("mr_enclave error")

    if mr_signer != enclave_info[enclave_name]["mr_signer"]:
        raise Exception("mr_signer error")
def verify(cert_path, ca_path, fqdn=False, port=443):
    """ Verify a couple of certificate and CA """
    if fqdn:
        st_cert = get_server_certificate((cert_path, port))
    else:
        st_cert = open(cert_path, "rt").read()
    st_ca = open(ca_path, "rt").read()
    cert = load_certificate(FILETYPE_PEM, st_cert)
    ca_cert = load_certificate(FILETYPE_PEM, st_ca)
    store = X509Store()
    store.add_cert(ca_cert)
    store_ctx = X509StoreContext(store, cert)
    try:
        if store_ctx.verify_certificate() is None:
            print(
                color_message("Verification successful !", "green", bold=True))
    except X509StoreContextError as error:
        print(
            color_message("Verification error: ", "red", bold=True) +
            str(error))
    def _validate_cert(self, to_verify, fprint, context, interm_mode):
        """
        Validates current certificate in the given context.
        Extension - different context for different validation method.
        :param to_verify:
        :param context:
        :return:
        """
        try:
            # current trust store with previously validated intermediate certificates
            cur_store = self._new_ossl_store()
            for crt in context.verified_certs:
                cur_store.add_cert(crt[0])

            # OSSL Verification w.r.t. base store
            store_ctx = X509StoreContext(cur_store, to_verify[0])
            store_ctx.verify_certificate()

            # Add valid intermediate to the verified registers
            if interm_mode and fprint not in self.root_fprints and fprint not in context.verified_fprints:
                context.verified_certs.append(to_verify)
                context.verified_fprints.add(fprint)

        except X509StoreContextError as cex:  # translate specific exception to our general exception
            self.trace_logger.log(
                cex,
                custom_msg='Exc in path validation, interm: %s. ' %
                interm_mode)

            # message - error, depth, message, certificate which caused an error
            ex = ValidationOsslException('Validation failed', cause=cex)
            try:
                ex.error_code = cex.message[0]
                ex.error_depth = cex.message[1]
                ex.error_msg = cex.message[2]
                ex.error_cert = cex.certificate
            except:
                pass

            raise ex
Exemple #23
0
def _add_cert_to_store(store, cert):
    from OpenSSL.crypto import X509StoreContext, X509StoreContextError, Error as OpenSSLCryptoError

    # Added by Terry to capture cert expiry
    cert_expired = False
    try:
        X509StoreContext(store, cert).verify_certificate()

    except X509StoreContextError as e:
        # Terry: If certificate has expired, change cert_expired status to update functions outside
        if 'certificate has expired' in str(e):
            cert_expired = True
        else:
            raise InvalidCertificate(e)
    try:
        # This has already been changed
        store.add_cert(cert)
        return (cert, cert_expired)
    except OpenSSLCryptoError as e:
        if e.args == ([('x509 certificate routines', 'X509_STORE_add_cert', 'cert already in hash table')],):
            raise RedundantCert(e)
        raise
Exemple #24
0
def verify_x509_cert_chain(cert_chain, ca_pem_file=None, ca_path=None):
    from OpenSSL import SSL
    from OpenSSL.crypto import X509StoreContext, X509StoreContextError, Error as OpenSSLCryptoError
    context = SSL.Context(SSL.TLSv1_METHOD)
    if ca_pem_file is None and ca_path is None:
        import certifi
        ca_pem_file = certifi.where()
    context.load_verify_locations(ensure_bytes(ca_pem_file), capath=ca_path)
    store = context.get_cert_store()
    for cert in cert_chain:
        try:
            X509StoreContext(store, cert).verify_certificate()
        except X509StoreContextError as e:
            raise InvalidCertificate(e)

        try:
            store.add_cert(cert)
        except OpenSSLCryptoError as e:
            if e.args == ([('x509 certificate routines', 'X509_STORE_add_cert', 'cert already in hash table')],):
                continue
            else:
                raise
Exemple #25
0
import sys

from OpenSSL.crypto import load_certificate, load_privatekey
from OpenSSL.crypto import X509Store, X509StoreContext
from OpenSSL.SSL import Context, TLSv1_METHOD, VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, OP_NO_SSLv2
from OpenSSL.crypto import load_certificate, FILETYPE_PEM
# from six import u, b, binary_type, PY3

store = X509Store()

i = 0

for file_name in sys.argv[1:]:
    with open(file_name, "rb") as f:
        pem_data = f.read()
        cert = load_certificate(FILETYPE_PEM, pem_data)

        # cert = x509.load_pem_x509_certificate(pem_data, default_backend())
        # key = load_pem_private_key(pem_data, password=None,
        #                                backend=openssl_backend)
    i = i + 1
    print(i, len(sys.argv), "Came here", file_name)
    if i < len(sys.argv) - 1:
        store.add_cert(cert)
    else:
        store_ctx = X509StoreContext(store, cert)
        print("Verifying certificate " + file_name)
        print(store_ctx.verify_certificate())
def passive_auth(
    efsod: bytes,
    ee_deviant_doc: bool = False,
    dump: bool = False
) -> Tuple[str, bytes, bytes, Optional[List[PassiveAuthenticationError]]]:
    """
    Do Passive Authentication

    :returns:
    hash_alg that is used to hash DGs,
    data_group_hash_values
    """
    exceptions: List[PassiveAuthenticationError] = []

    # get root node
    i = asn1_node_root(efsod)
    # unpack application data 0x77
    i = asn1_node_first_child(efsod, i)
    # unpack sequence
    i = asn1_node_first_child(efsod, i)
    # print id-signedData OBJECT IDENTIFIER
    if dump:
        print(dump_asn1(asn1_get_all(efsod, i)))
    # get 2nd item inside (SignedData EXPLICIT tagged)
    i = asn1_node_next(efsod, i)
    # unpack SignedData EXPLICIT tag
    i = asn1_node_first_child(efsod, i)
    # get 1st item inside (CMSVersion Value = v3)
    i = asn1_node_first_child(efsod, i)
    # get 2nd item (DigestAlgorithmIdentifiers) collection of message digest algorithm identifiers.
    # There MAY be any number of elements in the collection, including zero.
    i = asn1_node_next(efsod, i)
    # get 3rd item (EncapsulatedContentInfo) (LDS Document Security Object)
    i = asn1_node_next(efsod, i)

    # get 1st item inside (eContentType)
    # (OID joint-iso-itu-t (2) international(23) icao(136) mrtd(1) security(1) ldsSecurityObject(1))
    j = asn1_node_first_child(efsod, i)
    e_content_type = asn1_get_all(efsod, j)
    # get the EXPLICIT tagged encoded contents of ldsSecurityObject
    j = asn1_node_next(efsod, j)
    # get the encoded contents of ldsSecurityObject
    j = asn1_node_first_child(efsod, j)
    # print the value of eContent hash
    encapsulated_content = asn1_get_value_of_type(efsod, j, "OCTET STRING")
    del j

    signer_infos, certificates, crls = None, None, None
    while signer_infos is None:
        # https://stackoverflow.com/a/52041365/6077951
        # get 4th item
        i = asn1_node_next(efsod, i)
        if efsod[i[0]] == 0xA0:
            # Constructed, Context-Specific 0
            certificates = i
            print("[+] CertificateSet exist")
        elif efsod[i[0]] == 0xA1:
            # Constructed, Context-Specific 1
            crls = i
            print("[+] Crls exist")
        else:
            signer_infos = i

    # The inspection system SHALL build and validate a certification path
    # from a Trust Anchor to the Document Signer Certificate used to
    # sign the Document Security Object (SOD) according to Doc 9303-11.

    # store was already built in the first run
    store = build_store.store

    doc_sig_cert = asn1_get_value(efsod, certificates)

    if certificates is not None:
        if ee_deviant_doc:
            doc_sig_cert = add_seconds_to_certificate(doc_sig_cert, 43200)
        CDS = load_certificate(FILETYPE_ASN1, doc_sig_cert)
        store_ctx = X509StoreContext(store, CDS)
        try:
            if store_ctx.verify_certificate() is None:
                print(
                    "[+] Document Signer Certificate is signed by a CSCA certificate"
                )
        except X509StoreContextError as ex:
            exceptions.append(
                PassiveAuthenticationError(
                    "[-] Document Signer Certificate is not signed "
                    "by a CSCA certificate or is invalid!\n" + str(ex)))
    else:
        raise PassiveAuthenticationCriticalError(
            "[-] This application doesn't support this kind of document yet!")

    # get 1st signerInfo inside signerInfos
    i = asn1_node_first_child(efsod, signer_infos)
    # get 1st item inside 1st signerInfo (CMSVersion)
    i = asn1_node_first_child(efsod, i)
    signer_info_ver = int.from_bytes(asn1_get_value_of_type(
        efsod, i, "INTEGER"),
                                     byteorder="big")

    issuer_and_serial_number, subject_key_identifier = None, None
    # get 2nd item inside 1st signerInfo (SignerIdentifier)
    i = asn1_node_next(efsod, i)
    if signer_info_ver == 1:
        issuer_and_serial_number = i
    elif signer_info_ver == 3:
        subject_key_identifier = i

    if dump:
        print(
            dump_asn1(
                asn1_get_all(
                    efsod, issuer_and_serial_number
                    or subject_key_identifier)))

    # get 3rd item inside 1st signerInfo (DigestAlgorithmIdentifier)
    i = asn1_node_next(efsod, i)
    # get hash algorithm used for encapsulatedContent and SignedAttrs
    hash_alg = asn1_get_all(efsod, asn1_node_first_child(efsod, i))
    try:
        hash_alg = get_digestalg_name(hash_alg)
    except ValueError as ex:
        raise PassiveAuthenticationCriticalError(
            "[-] Hash algorithm is not recognized.") from ex

    # get 4th item inside 1st signerInfo ([0] IMPLICIT SignedAttributes)
    i = asn1_node_next(efsod, i)
    # use EXPLICIT SET OF tag, rather than of the IMPLICIT [0] tag
    signed_attrs = asn1_get_all(efsod, i)
    signed_attrs = b"\x31" + signed_attrs[1:]

    # get the first Attribute from SignedAttributes
    j = asn1_node_first_child(efsod, i)
    content_type, signed_attrs_hash = None, None
    while content_type is None or signed_attrs_hash is None:
        # get the content-type and the message-digest
        k = asn1_node_first_child(efsod, j)
        # contentType
        if asn1_get_all(efsod, k) == encode_oid_string("1.2.840.113549.1.9.3"):
            # then the content-type attribute value MUST match
            # the SignedData encapContentInfo eContentType value.
            # checked in line 195
            k = asn1_node_next(efsod, k)
            k = asn1_node_first_child(efsod, k)
            content_type = asn1_get_all(efsod, k)
        # messageDigest
        elif asn1_get_all(efsod,
                          k) == encode_oid_string("1.2.840.113549.1.9.4"):
            k = asn1_node_next(efsod, k)
            k = asn1_node_first_child(efsod, k)
            signed_attrs_hash = asn1_get_value_of_type(efsod, k,
                                                       "OCTET STRING")
        j = asn1_node_next(efsod, j)
    del k, j

    hash_object = hashlib.new(hash_alg)
    hash_object.update(encapsulated_content)
    e_content_hash = hash_object.digest()
    del hash_object
    # print("[+] Calculated hash of eContent =", eContent_hash.hex())
    # print("[+] Hash of eContent in SignedAttributes =", signedAttrs_hash.hex())

    if e_content_type == content_type:
        print(
            "[+] Content Type of eContent match with the Content Type in SignedAttributes"
        )
    else:
        exceptions.append(
            PassiveAuthenticationError(
                "[-] Content Type of eContent DOES NOT "
                "match with the Content Type in SignedAttributes."))

    if hmac.compare_digest(signed_attrs_hash, e_content_hash):
        print("[+] Hash of eContent match with the hash in SignedAttributes")
    else:
        exceptions.append(
            PassiveAuthenticationError(
                "[+] Hash of eContent DOES NOT match with the hash in SignedAttributes."
            ))

    # get 4th item inside 1st signerInfo (SignatureAlgorithmIdentifier)
    i = asn1_node_next(efsod, i)
    # get 5th item inside 1st signerInfo (SignatureValue)
    i = asn1_node_next(efsod, i)
    signature = asn1_get_value_of_type(efsod, i, "OCTET STRING")

    # Verify the signature with DS_cert using hash_alg
    try:
        if verify(CDS, signature, signed_attrs, hash_alg) is None:
            print("[+] The signature on EF_SOD is valid.")
    except ex:
        exceptions.append(
            PassiveAuthenticationError(
                "[-] The signature on EF_SOD is not valid or failed."))

    i = asn1_node_root(encapsulated_content)
    i = asn1_node_first_child(encapsulated_content, i)
    i = asn1_node_next(encapsulated_content, i)
    i = asn1_node_next(encapsulated_content, i)

    data_group_hash_values = asn1_get_all(encapsulated_content, i)

    if len(exceptions) == 0:
        return hash_alg, data_group_hash_values, doc_sig_cert, None
    return hash_alg, data_group_hash_values, doc_sig_cert, exceptions
)

store = X509Store()
certs = {
    "csca_Estonia_2007.cer": FILETYPE_PEM,
    "csca_Estonia_2007-2009-link.cer": FILETYPE_PEM,
    "csca_Estonia_2009.crt": FILETYPE_ASN1,
    "csca_Estonia_2009-2012-link.cer": FILETYPE_PEM,
    "csca_Estonia_2012.cer": FILETYPE_ASN1,
    "csca_Estonia_2012-2015-link.crt": FILETYPE_ASN1,
    "csca_Estonia_2015.cer": FILETYPE_ASN1,
    "csca_Estonia_2015-2016-link.crt": FILETYPE_ASN1,
    "csca_Estonia_2016.cer": FILETYPE_ASN1,
    "csca_Estonia_2016-2019-link.crt": FILETYPE_ASN1,
    "csca_Estonia_2019.cer": FILETYPE_ASN1,
    "csca_Estonia_2019-2020-link.der": FILETYPE_ASN1,
    "csca_Estonia_2020.der": FILETYPE_ASN1,
}

for fn, ft in certs.items():
    with open("CSCA_certs/" + fn, "rb") as infile:
        CSCA = load_certificate(ft, infile.read())
    store.add_cert(CSCA)

with open("CDS", "rb") as infile:
    CDS = load_certificate(FILETYPE_ASN1, infile.read())

store_ctx = X509StoreContext(store, CDS)

if store_ctx.verify_certificate() is None:
    print("[+] Document Signer Certificate is signed by a CSCA certificate")
    def roots(self, fname):
        """
        One root file processing
        :param fname: 
        :return: 
        """
        self.cur_file = fname
        before_file_certs_size = len(self.all_certs)
        with open(fname) as fh:
            for line in fh:
                try:
                    if '"ca": false' in line:
                        continue

                    js = json.loads(line)
                    fprint = None
                    raw = None
                    rawb = None

                    if 'fprint' in js:
                        fprint = js['fprint']

                    if 'ca' in js and not js['ca']:
                        continue

                    fprint_requires_raw = fprint is None or len(fprint) != 40
                    if fprint_requires_raw and 'raw' not in js:
                        self.num_no_fprint_raw += 1
                        continue

                    if fprint_requires_raw:
                        raw = js['raw']
                        rawb = base64.b64decode(raw)
                        fprint = hashlib.sha1(rawb).hexdigest()

                    # Already seen in this round, may become valid in the next round.
                    if fprint in self.chain_cert_db:
                        continue

                    # Already assigned to a trust category
                    if fprint in self.assigned_fprints:
                        continue

                    if 'raw' not in js:
                        self.num_no_raw += 1
                        continue

                    if rawb is None:
                        raw = js['raw']
                        rawb = base64.b64decode(raw)

                    self.chain_cert_db.add(fprint)
                    crypt_cert = load_der_x509_certificate(rawb, get_backend())

                    if not utils.try_is_ca(crypt_cert):
                        if self.num_not_ca % 1000 == 0:
                            logger.debug('Cert is not CA: %s (%d)' %
                                         (fprint, self.num_not_ca))
                        self.num_not_ca += 1
                        continue

                    # Verify
                    ossl_cert = load_certificate(FILETYPE_ASN1, rawb)
                    self.cur_store.set_flags(0x200000)
                    store_ctx = X509StoreContext(self.cur_store, ossl_cert)
                    try:
                        store_ctx.verify_certificate()
                        self.interms[self.cur_depth].append(js)
                        self.assigned_fprints.add(fprint)
                        self.all_certs.append(ossl_cert)
                        self.test_cert(crypt_cert, js)

                    except X509StoreContextError as cex:
                        self.trace_logger.log(cex,
                                              custom_msg='Exc in verification')
                        if isinstance(cex.message,
                                      (types.ListType, types.TupleType)):
                            if cex.message[0] == 10:
                                self.num_expired += 1
                                self.test_cert(crypt_cert, js, 'Expired')

                    except Exception as e:
                        self.trace_logger.log(
                            e, custom_msg='General Exc in verification')

                    self.report()

                except Exception as e:
                    logger.error('Exception in processing certs %s' % e)
                    self.trace_logger.log(e)
                    self.num_errs += 1
        new_certs_size = len(self.all_certs) - before_file_certs_size
        logger.info('File %s contributed with %s certificates' %
                    (fname, new_certs_size))
Exemple #29
0
def validate_certificate_chain(
    *,
    x5c: List[bytes],
    pem_root_certs_bytes: Optional[List[bytes]] = None,
) -> bool:
    """Validate that the certificates in x5c chain back to a known root certificate

    Args:
        `x5c`: X5C certificates from a registration response's attestation statement
        (optional) `pem_root_certs_bytes`: Any additional (PEM-formatted)
        root certificates that may complete the certificate chain

    Raises:
        `helpers.exceptions.InvalidCertificateChain` if chain cannot be validated
    """
    if pem_root_certs_bytes is None or len(pem_root_certs_bytes) < 1:
        # We have no root certs to chain back to, so just pass on validation
        return True

    # Make sure we have at least one certificate to try and link back to a root cert
    if len(x5c) < 1:
        raise InvalidCertificateChain("x5c was empty")

    # Prepare leaf cert
    try:
        leaf_cert_bytes = x5c[0]
        leaf_cert_crypto = load_der_x509_certificate(leaf_cert_bytes,
                                                     default_backend())
        leaf_cert = X509().from_cryptography(leaf_cert_crypto)
    except Exception as err:
        raise InvalidCertificateChain(f"Could not prepare leaf cert: {err}")

    # Prepare any intermediate certs
    try:
        # May be an empty array, that's fine
        intermediate_certs_bytes = x5c[1:]
        intermediate_certs_crypto = [
            load_der_x509_certificate(cert, default_backend())
            for cert in intermediate_certs_bytes
        ]
        intermediate_certs = [
            X509().from_cryptography(cert)
            for cert in intermediate_certs_crypto
        ]
    except Exception as err:
        raise InvalidCertificateChain(
            f"Could not prepare intermediate certs: {err}")

    # Prepare a collection of possible root certificates
    root_certs_store = X509Store()
    try:
        for cert in pem_root_certs_bytes:
            root_certs_store.add_cert(pem_cert_bytes_to_open_ssl_x509(cert))
    except Exception as err:
        raise InvalidCertificateChain(f"Could not prepare root certs: {err}")

    # Load certs into a "context" for validation
    context = X509StoreContext(
        store=root_certs_store,
        certificate=leaf_cert,
        chain=intermediate_certs,
    )

    # Validate the chain (will raise if it can't)
    try:
        context.verify_certificate()
    except X509StoreContextError:
        raise InvalidCertificateChain(
            "Certificate chain could not be validated")

    return True