def test_generate_self_signed_certificate_requires_pin(self, session): session.verify_pin(DEFAULT_PIN) public_key = generate_key(session, SLOT.AUTHENTICATION) with pytest.raises(ApduError): generate_self_signed_certificate(session, SLOT.AUTHENTICATION, public_key, "CN=alice", NOW, NOW) session.verify_pin(DEFAULT_PIN) generate_self_signed_certificate(session, SLOT.AUTHENTICATION, public_key, "CN=alice", NOW, NOW)
def _test_put_key_pairing(self, session, alg1, alg2): # Set up a key in the slot and create a certificate for it public_key = generate_key(session, SLOT.AUTHENTICATION, alg=alg1) session.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY) session.verify_pin(DEFAULT_PIN) cert = generate_self_signed_certificate(session, SLOT.AUTHENTICATION, public_key, "CN=test", NOW, NOW) session.put_certificate(SLOT.AUTHENTICATION, cert) assert check_key(session, SLOT.AUTHENTICATION, cert.public_key()) cert2 = session.get_certificate(SLOT.AUTHENTICATION) assert cert == cert2 session.delete_certificate(SLOT.AUTHENTICATION) # Overwrite the key with one of the same type generate_key(session, SLOT.AUTHENTICATION, alg=alg1) session.verify_pin(DEFAULT_PIN) assert not check_key(session, SLOT.AUTHENTICATION, cert.public_key()) # Overwrite the key with one of a different type generate_key(session, SLOT.AUTHENTICATION, alg=alg2) session.verify_pin(DEFAULT_PIN) assert not check_key(session, SLOT.AUTHENTICATION, cert.public_key())
def test_generate_self_signed_certificate(self, session, slot): public_key = generate_key(session, slot) session.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY) session.verify_pin(DEFAULT_PIN) cert = generate_self_signed_certificate(session, slot, public_key, "CN=alice", NOW, NOW) assert cert.public_key().public_numbers() == public_key.public_numbers( ) assert (cert.subject.get_attributes_for_oid( x509.NameOID.COMMON_NAME)[0].value == "alice")
def test_generate_self_signed_certificate(self, session, key_type, hash_algorithm): if key_type == KEY_TYPE.ECCP384 and session.version < (4, 0, 0): pytest.skip("ECCP384 requires YubiKey 4 or later") if key_type == KEY_TYPE.RSA1024 and is_fips_version(session.version): pytest.skip("RSA1024 not available on YubiKey FIPS") slot = SLOT.SIGNATURE public_key = import_key(session, slot, key_type) session.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY) session.verify_pin(DEFAULT_PIN) cert = generate_self_signed_certificate(session, slot, public_key, "CN=alice", NOW, NOW, hash_algorithm) assert cert.public_key().public_numbers() == public_key.public_numbers( ) verify_cert_signature(cert, public_key)
def reset_piv(self): '''Resets YubiKey PIV app and generates new key for GAM to use.''' reply = str( input( 'This will wipe all PIV keys and configuration from your YubiKey. Are you sure? (y/N) ' ).lower().strip()) if reply != 'y': sys.exit(1) try: conn = self._connect() with conn: piv = PivSession(conn) piv.reset() rnd = SystemRandom() pin_puk_chars = string.ascii_letters + string.digits + string.punctuation new_puk = ''.join(rnd.choice(pin_puk_chars) for _ in range(8)) new_pin = ''.join(rnd.choice(pin_puk_chars) for _ in range(8)) piv.change_puk('12345678', new_puk) piv.change_pin('123456', new_pin) print(f'PIN set to: {new_pin}') piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY) piv.verify_pin(new_pin) print('YubiKey is generating a non-exportable private key...') pubkey = piv.generate_key(SLOT.AUTHENTICATION, KEY_TYPE.RSA2048, PIN_POLICY.ALWAYS, TOUCH_POLICY.NEVER) now = datetime.datetime.utcnow() valid_to = now + datetime.timedelta(days=36500) subject = 'CN=GAM Created Key' piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY) piv.verify_pin(new_pin) cert = generate_self_signed_certificate( piv, SLOT.AUTHENTICATION, pubkey, subject, now, valid_to) piv.put_certificate(SLOT.AUTHENTICATION, cert) piv.put_object(OBJECT_ID.CHUID, generate_chuid()) except ValueError as err: controlflow.system_error_exit(8, f'YubiKey - {err}')
def piv_generate_certificate( self, slot_name, algorithm, subject, expiration_date, self_sign=True, csr_file_url=None, pin=None, mgm_key_hex=None): logger.debug('slot_name=%s algorithm=%s common_name=%s ' 'expiration_date=%s self_sign=%s csr_file_url=%s', slot_name, algorithm, subject, expiration_date, self_sign, csr_file_url) if csr_file_url: file_path = self._get_file_path(csr_file_url) with self._open_device([SmartCardConnection]) as conn: session = PivSession(conn) with PromptTimeout(): auth_failed = self._piv_ensure_authenticated( session, pin=pin, mgm_key_hex=mgm_key_hex) if auth_failed: return auth_failed pin_failed = self._piv_verify_pin(session, pin) if pin_failed: return pin_failed if self_sign: now = datetime.datetime.utcnow() try: year = int(expiration_date[0:4]) month = int(expiration_date[(4+1):(4+1+2)]) day = int(expiration_date[(4+1+2+1):(4+1+2+1+2)]) valid_to = datetime.datetime(year, month, day) except ValueError as e: logger.debug( 'Failed to parse date: ' + expiration_date, exc_info=e) return failure( 'invalid_iso8601_date', {'date': expiration_date}) try: public_key = session.generate_key( SLOT[slot_name], KEY_TYPE[algorithm]) except ApduError as e: if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED: logger.debug("Wrong management key", exc_info=e) return failure('wrong_mgm_key') pin_failed = self._piv_verify_pin(session, pin) if pin_failed: return pin_failed if "=" not in subject: # Old style, common name only. subject = "CN=" + subject try: if self_sign: cert = generate_self_signed_certificate(session, SLOT[slot_name], public_key, subject, now, valid_to) session.put_certificate(SLOT[slot_name], cert) session.put_object(OBJECT_ID.CHUID, generate_chuid()) else: csr = generate_csr(session, SLOT[slot_name], public_key, subject) with open(file_path, 'w+b') as csr_file: csr_file.write(csr.public_bytes( encoding=serialization.Encoding.PEM)) except ApduError as e: if e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED: return failure('pin_required') raise return success()