Beispiel #1
0
 def sign(self, message):
     if 'mplock' in globals():
         mplock.acquire()
     try:
         conn = self._connect()
         with conn:
             session = PivSession(conn)
             if self.pin:
                 try:
                     session.verify_pin(self.pin)
                 except InvalidPinError as err:
                     controlflow.system_error_exit(7, f'YubiKey - {err}')
             try:
                 signed = session.sign(slot=self.slot,
                                       key_type=self.key_type,
                                       message=message,
                                       hash_algorithm=hashes.SHA256(),
                                       padding=padding.PKCS1v15())
             except ApduError as err:
                 controlflow.system_error_exit(8, f'YubiKey - {err}')
     except ValueError as err:
         controlflow.system_error_exit(9, f'YubiKey - {err}')
     if 'mplock' in globals():
         mplock.release()
     return signed
Beispiel #2
0
def sign_certificate_builder(
    session: PivSession,
    slot: SLOT,
    key_type: KEY_TYPE,
    builder: x509.CertificateBuilder,
    hash_algorithm: Type[hashes.HashAlgorithm] = hashes.SHA256,
) -> x509.Certificate:
    """Sign a Certificate."""
    dummy_key = _dummy_key(key_type)
    cert = builder.sign(dummy_key, hash_algorithm(), default_backend())

    sig = session.sign(
        slot,
        key_type,
        cert.tbs_certificate_bytes,
        hash_algorithm(),
        padding.PKCS1v15(),  # Only used for RSA
    )

    seq = Tlv.parse_list(Tlv.unpack(0x30, cert.public_bytes(Encoding.DER)))
    # Replace signature, add unused bits = 0
    seq[2] = Tlv(seq[2].tag, b"\0" + sig)
    # Re-assemble sequence
    der = Tlv(0x30, b"".join(seq))

    return x509.load_der_x509_certificate(der, default_backend())
Beispiel #3
0
def sign_csr_builder(
    session: PivSession,
    slot: SLOT,
    public_key: Union[rsa.RSAPublicKey, ec.EllipticCurvePublicKey],
    builder: x509.CertificateSigningRequestBuilder,
    hash_algorithm: Type[hashes.HashAlgorithm] = hashes.SHA256,
) -> x509.CertificateSigningRequest:
    """Sign a CSR."""
    key_type = KEY_TYPE.from_public_key(public_key)
    dummy_key = _dummy_key(key_type)
    csr = builder.sign(dummy_key, hash_algorithm(), default_backend())
    seq = Tlv.parse_list(Tlv.unpack(0x30, csr.public_bytes(Encoding.DER)))

    # Replace public key
    pub_format = (PublicFormat.PKCS1 if key_type.algorithm == ALGORITHM.RSA
                  else PublicFormat.SubjectPublicKeyInfo)
    dummy_bytes = dummy_key.public_key().public_bytes(Encoding.DER, pub_format)
    pub_bytes = public_key.public_bytes(Encoding.DER, pub_format)
    seq[0] = Tlv(seq[0].replace(dummy_bytes, pub_bytes))

    sig = session.sign(
        slot,
        key_type,
        seq[0],
        hash_algorithm(),
        padding.PKCS1v15(),  # Only used for RSA
    )

    # Replace signature, add unused bits = 0
    seq[2] = Tlv(seq[2].tag, b"\0" + sig)
    # Re-assemble sequence
    der = Tlv(0x30, b"".join(seq))

    return x509.load_der_x509_csr(der, default_backend())
Beispiel #4
0
def check_key(
    session: PivSession,
    slot: SLOT,
    public_key: Union[rsa.RSAPublicKey, ec.EllipticCurvePublicKey],
) -> bool:
    """Check that a given public key corresponds to the private key in a slot.

    This will create a signature using the private key, so the PIN must be verified
    prior to calling this function if the PIN policy requires it.
    """
    try:
        test_data = b"test"

        test_sig = session.sign(
            slot,
            KEY_TYPE.from_public_key(public_key),
            test_data,
            hashes.SHA256(),
            padding.PKCS1v15(),  # Only used for RSA
        )

        if isinstance(public_key, rsa.RSAPublicKey):
            public_key.verify(
                test_sig,
                test_data,
                padding.PKCS1v15(),
                hashes.SHA256(),
            )
        elif isinstance(public_key, ec.EllipticCurvePublicKey):
            public_key.verify(test_sig, test_data, ec.ECDSA(hashes.SHA256()))
        else:
            raise ValueError("Unknown key type: " + type(public_key))
        return True

    except ApduError as e:
        if e.sw in (SW.INCORRECT_PARAMETERS, SW.WRONG_PARAMETERS_P1P2):
            return False
        raise

    except InvalidSignature:
        return False