Beispiel #1
0
    def generate_ec_key(self, key_slot, curve_name, timestamp=None):
        require_version(self.version, (5, 2, 0))
        """Requires Admin PIN verification."""
        if timestamp is None:
            timestamp = int(time.time())

        attributes = _format_ec_attributes(key_slot, curve_name)
        self._put_data(key_slot.key_id, attributes)
        resp = self._app.send_apdu(0, INS.GENERATE_ASYM, 0x80, 0x00, key_slot.crt)

        data = Tlv.parse_dict(Tlv.unpack(0x7F49, resp))
        pubkey_enc = data[0x86]

        self._put_data(key_slot.gen_time, struct.pack(">I", timestamp))
        # TODO: Calculate and write fingerprint

        if curve_name == "x25519":
            # Added in 2.0
            from cryptography.hazmat.primitives.asymmetric import x25519

            return x25519.X25519PublicKey.from_public_bytes(pubkey_enc)
        if curve_name == "ed25519":
            # Added in 2.6
            from cryptography.hazmat.primitives.asymmetric import ed25519

            return ed25519.Ed25519PublicKey.from_public_bytes(pubkey_enc)

        curve = getattr(ec, curve_name.upper())
        try:
            # Added in cryptography 2.5
            return ec.EllipticCurvePublicKey.from_encoded_point(curve(), pubkey_enc)
        except AttributeError:
            return ec.EllipticCurvePublicNumbers.from_encoded_point(
                curve(), pubkey_enc
            ).public_key(default_backend())
Beispiel #2
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 #3
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 #4
0
    def generate_rsa_key(self, key_slot, key_size, timestamp=None):
        """Requires Admin PIN verification."""
        if (4, 2, 0) <= self.version < (4, 3, 5):
            raise NotSupportedError(
                "RSA key generation not supported on this YubiKey")

        if timestamp is None:
            timestamp = int(time.time())

        neo = self.version < (4, 0, 0)
        if not neo:
            attributes = _format_rsa_attributes(key_size)
            self._put_data(key_slot.key_id, attributes)
        elif key_size != 2048:
            raise ValueError("Unsupported key size!")
        resp = self._app.send_apdu(0, INS.GENERATE_ASYM, 0x80, 0x00,
                                   key_slot.crt)

        data = Tlv.parse_dict(Tlv.unpack(0x7F49, resp))
        numbers = rsa.RSAPublicNumbers(bytes2int(data[0x82]),
                                       bytes2int(data[0x81]))

        self._put_data(key_slot.gen_time, struct.pack(">I", timestamp))
        # TODO: Calculate and write fingerprint

        return numbers.public_key(default_backend())
Beispiel #5
0
def is_pkcs12(data):
    """
    Tries to identify a PKCS12 container.
    The PFX PDU version is assumed to be v3.
    See: https://tools.ietf.org/html/rfc7292.
    """
    try:
        header = Tlv.parse_list(Tlv.unpack(0x30, data))[0]
        return header.tag == 0x02 and header.value == b"\x03"
    except ValueError:
        return False
Beispiel #6
0
def is_pkcs12(data):
    """
    Tries to identify a PKCS12 container.
    The PFX PDU version is assumed to be v3.
    See: https://tools.ietf.org/html/rfc7292.
    """
    try:
        header = Tlv.parse_from(Tlv.unpack(0x30, data))[0]
        return header.tag == 0x02 and header.value == b"\x03"
    except ValueError as e:
        logger.debug("Unable to parse TLV", exc_info=e)
    return False