Commit 05b2c869 authored by Afif Elghraoui's avatar Afif Elghraoui

New upstream version 2.0.0

parent 8593f8e9
......@@ -3,7 +3,6 @@ include NEWS
include ChangeLog
include resources/*
include doc/*.adoc
include test/**/**/**
recursive-include test *
include README.adoc
include ykman/VERSION
* Version 2.0.0 (unreleased)
** Add support for Security Key NFC
** Add experimental support for external smart card reader. See --reader flag
** Add a minimal manpage
** Add examples in help texts
** PIV: update CHUID when importing a certificate
** PIV: Optionally validate that private key and certificate match when importing a certificate (on by default in CLI)
** PIV: Improve support for importing certificate chains and .PEM files with comments
** Breaking API changes:
*** Merge CCID status word constants into a single SW enum in ykman.driver_ccid
*** Throw custom exception types instead of raw APDUErrors from many methods of PivController
*** Write CLI prompts to standard error instead of standard output
*** Replace function `ykman.util.parse_certificate` with `parse_certificates` which returns a list
* Version 1.0.1 (released 2018-10-10)
** Support for YubiKey 5A
** OATH: Ignore extra parameters in URI parsing
** Bugfix: Never say that NFC is supported for YubiKeys without NFC
* Version 1.0.0 (released 2018-09-24)
** Add support for YubiKey 5 Series
** Config: Add flag to generate a random configuration lock
** OATH: Give a proper error message when a touch credential times out
** NDEF: Allow setting the NDEF prefix from the CLI
** FIDO: Block reset when multiple YubiKeys are connected
* Version 0.7.1 (released 2018-07-09)
** Support for YubiKey FIPS.
** OTP: Allow setting and removing access codes on the slots.
......@@ -33,7 +59,7 @@
** CLI breaking changes:
*** OATH: Touch prompt now written to stderr instead of stdout
*** OATH: `-a|--algorithm` option to `list` command removed
*** OATH: Columns in `code` command are now dymanically spaced depending on contents
*** OATH: Columns in `code` command are now dynamically spaced depending on contents
*** OATH: `delete` command now requires confirmation or `-f|--force` argument
*** OATH: IDs printed by `list` command now include TOTP period if not 30
*** Changed outputs:
......@@ -64,10 +90,10 @@
** OATH: Don't print issuer if there is no issuer.
* Version 0.4.4 (released 2017-09-06)
** OATH: Fix yet another issue with backwards compability, for adding new credentials.
** OATH: Fix yet another issue with backwards compatibility, for adding new credentials.
* Version 0.4.3 (released 2017-09-06)
** OATH: Fix issue with backwards compability, when used as a library.
** OATH: Fix issue with backwards compatibility, when used as a library.
* Version 0.4.2 (released 2017-09-05)
** OATH: Support 7 digit credentials.
......@@ -76,7 +102,7 @@
* Version 0.4.1 (released 2017-08-10)
** PIV: Dropped support for deriving a management key from PIN.
** PIV: Addded support for generating a random management key and storing it on the device protected by the PIN.
** PIV: Added support for generating a random management key and storing it on the device protected by the PIN.
** OpenPGP: The reset command now handles a device in terminated state.
** OATH: Credential filtering is now working properly on Python 2.
......
Metadata-Version: 1.2
Name: yubikey-manager
Version: 0.7.1
Version: 2.0.0
Summary: Tool for managing your YubiKey configuration.
Home-page: https://github.com/Yubico/yubikey-manager
Author: Dain Nilsson
......
......@@ -5,6 +5,7 @@ image:https://ci.appveyor.com/api/projects/status/fp7nb97m8372axq8?svg=true["App
Python library and command line tool for configuring a YubiKey. If you're looking for the full graphical application, which also includes the command line tool, it's https://developers.yubico.com/yubikey-manager-qt/[here].
=== Usage
For more usage information and examples, see the https://support.yubico.com/support/solutions/articles/15000012643-yubikey-manager-cli-ykman-user-guide[YubiKey Manager CLI User Manual].
....
Usage: ykman [OPTIONS] COMMAND [ARGS]...
......@@ -14,20 +15,20 @@ Options:
-v, --version
-d, --device SERIAL
-l, --log-level [DEBUG|INFO|WARNING|ERROR|CRITICAL]
Enable logging at given verbosity level
--log-file FILE Write logs to the given FILE instead of standard error;
ignored unless --log-level is also set
Enable logging at given verbosity level.
--log-file FILE Write logs to the given FILE instead of standard error; ignored unless --log-level is also set.
-h, --help Show this message and exit.
Commands:
config Enable/Disable applications.
fido Manage FIDO applications.
info Show general information.
list List connected YubiKeys.
mode Manage connection modes (USB Interfaces).
oath Manage OATH application.
openpgp Manage OpenPGP application.
oath Manage OATH Application.
openpgp Manage OpenPGP Application.
otp Manage OTP Application.
piv Manage PIV application.
piv Manage PIV Application.
....
=== Installation
......@@ -42,11 +43,6 @@ Commands:
$ brew install ykman
Or from source:
$ brew install swig ykpers libusb
$ pip install --user yubikey-manager
==== Windows
The command line tool is installed together with the GUI version of https://developers.yubico.com/yubikey-manager-qt/[YubiKey Manager].
......@@ -58,6 +54,9 @@ The command line tool is installed together with the GUI version of https://deve
In order for the pip package to work, https://developers.yubico.com/yubikey-personalization/[ykpers] and http://libusb.info/[libusb] need to be installed on your system as well.
https://pyscard.sourceforge.io/[Pyscard] is also needed in some form, and if it's not installed pip builds it using http://www.swig.org/[swig] and potentially https://pcsclite.alioth.debian.org/pcsclite.html[PCSC lite].
==== Source
To install from source, see the https://github.com/Yubico/yubikey-manager/blob/master/doc/development.adoc[development] instructions.
=== Bash completion
Experimental Bash completion for the command line tool is available, but not
......
== Setting up a development environment on Ubuntu 16.04 (Xenial)
== Working with the code
Install development dependencies:
=== Install dependencies
$ sudo apt-get install python-pip python-pyscard libykpers-1-1 libu2f-host0
It's assumed a Python environment with pip is installed.
Setup the repository:
==== Windows
Make sure the http://www.swig.org/[swig] executable is in your PATH. Add http://libusb.info/[libusb]
and https://developers.yubico.com/yubikey-personalization/[ykpers] DLLs to the root of the repository.
==== macOS
$ brew install swig ykpers libusb
==== Linux (Debian-based distributions)
$ sudo apt install swig libykpers-1-1 libu2f-udev pcscd libpcsclite-dev
=== Install yubikey-manager from source
Clone the repository:
$ git clone https://github.com/Yubico/yubikey-manager.git
$ cd yubikey-manager
Install in editable mode with pip (from root of repository):
Install in editable mode with pip:
$ sudo pip install -e .
$ pip install -e .
Run the app:
Show available commands:
$ ykman --help
To update once installed, just make sure the repo is up to date:
Show information about inserted YubiKey:
$ ykman info
Run ykman in DEBUG mode:
$ git pull
$ ykman --log-level DEBUG info
To uninstall, run:
$ sudo pip uninstall yubikey-manager
$ pip uninstall yubikey-manager
=== Code Style
......@@ -46,27 +64,3 @@ WARNING: ONLY run these on a dedicated developer key, as it will permanently del
To run integration tests, indicate the serial number (given by `ykman list`) of the YubiKey to test with:
$ DESTRUCTIVE_TEST_YUBIKEY_SERIAL=123456 python setup.py test
== Using vagrant for development
A Vagrantfile with a development environment based on Ubuntu 16.04 is included in the repository.
Modify the Vagrantfile to set up a USB filter to capture the device with VirtualBox.
== Publishing to Ubuntu PPA
1. Update version number and signoff in `debian/changelog`.
2. Build and upload package.
For (2) you can use the Vagrant VM in `vagrant/ppa`. You'll need to set up the
VM to capture the YubiKey containing your signing key. If you use VirtualBox,
you can do this by uncommenting the USB filter included in the `Vagrantfile`.
Then:
alice@work $ cd yubikey-manager/vagrant/ppa
alice@work $ vagrant up
alice@work $ vagrant ssh
ubuntu@ubuntu-xenial $ gpg2 --recv-keys ABCDEF78
ubuntu@ubuntu-xenial $ gpg2 --card-status
ubuntu@ubuntu-xenial $ cd yubikey-manager
ubuntu@ubuntu-xenial $ ~/scripts/make-ppa -k ABCDEF78 -p gpg2
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDGAQa8eT5T9FjSP2Xcw/uj5LZrq5/hdpEGG7XO10IfPy0wbwqP
j+omaCxJlAPXuxFy0cYFNQlangIu0HAJ/TMAZXPJLBSRwdK7X/aZn/Ds2vRNAcp5
av+Pym9cfnfgMoS+6CvbUMAduLhzrnh4tQv4lb/AkliomHuoczdbcWHvKwIDAQAB
AoGAXzxrIwgmBHeIqUe5FOBnDsOZQlyAQA+pXYjCf8Rll2XptFwUdkzAUMzWUGWT
G5ZspA9l8Wc7IozRe/bhjMxuVK5yZhPDKbjqRdWICA95Jd7fxlIirHOVMQRdzI7x
NKqMNQN05MLJfsEHUYtOLhZE+tfhJTJnnmB7TMwnJgc4O5ECQQD8oOJ45tyr46zc
OAt6ao7PefVLiW5Qu+PxfoHmZmDV2UQqeM5XtZg4O97VBSugOs3+quIdAC6LotYl
/6N+E4y3AkEAyKWD2JNCrAgtjk2bfF1HYt24tq8+q7x2ek3/cUhqwInkrZqOFoke
x3+yBB879TuUOadvBXndgMHHcJQKSAJlLQJAXRuGnHyptAhTe06EnHeNbtZKG67p
I4Q8PJMdmSb+ZZKP1v9zPUxGb+NQ+z3OmF1T8ppUf8/DV9+KAbM4NI1L/QJAdGBs
BKYFObrUkYE5+fwwd4uao3sponqBTZcH3jDemiZg2MCYQUHu9E+AdRuYrziLVJVk
s4xniVLb1tRG0lVxUQJASfjdGT81HDJSzTseigrM+JnBKPPrzpeEp0RbTP52Lm23
YARjLCwmPMMdAwYZsvqeTuHEDQcOHxLHWuyN/zgP2A==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC2jCCAkMCAg38MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG
A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE
MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl
YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw
ODIyMDUyNzQxWhcNMTcwODIxMDUyNzQxWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE
CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs
ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0z9FeMynsC8+u
dvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut
bMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J
NRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW
+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic
7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2
4DDHCPhZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQMv+BFvGdMVzkQaQ3/+2noVz
/uAKbzpEL8xTcxYyP3lkOeh4FoxiSWqy5pGFALdPONoDuYFpLhjJSZaEwuvjI/Tr
rGhLV1pRG9frwDFshqD2Vaj4ENBCBh6UpeBop5+285zQ4SI7q4U9oSebUDJiuOx6
+tZ9KynmrbJpTSi0+BM=
-----END CERTIFICATE-----
Subject: Subject Name
Another comment
-----BEGIN CERTIFICATE-----
MIIC2jCCAkMCAg38MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG
A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE
MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl
YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw
ODIyMDUyNzQxWhcNMTcwODIxMDUyNzQxWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE
CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs
ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0z9FeMynsC8+u
dvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut
bMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J
NRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW
+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic
7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2
4DDHCPhZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQMv+BFvGdMVzkQaQ3/+2noVz
/uAKbzpEL8xTcxYyP3lkOeh4FoxiSWqy5pGFALdPONoDuYFpLhjJSZaEwuvjI/Tr
rGhLV1pRG9frwDFshqD2Vaj4ENBCBh6UpeBop5+285zQ4SI7q4U9oSebUDJiuOx6
+tZ9KynmrbJpTSi0+BM=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA5ltzQUrGUklMtSXFHG7bb4BcQ4UPCpV09X9oUCvOt/IqU6GB
bGHb4K6IZcFi3Jd/3LKknNmV3wq16Jjvc38/vtPlsI+hw733I4d73feyR/+NHt/e
dL9pmSAjSyui6HY/Cdu+Gacd8lDekAe/Hndn9Z4E9eitTkCjQwfJulZg1AqFNUxi
yeIxJPTF8xTHxgLiXEuK+x8gmu1kpT1aZo++MqFsV+PHuh6wSrO6K1LGJAMdOYWc
IrAfI6z8geKrE7XdXdyUwofJNN8qdtxwl4z33Af2f/0uLX9wNNasmh8gA/LSXYXJ
VEp8vF5PNkF1WF/4PqouEyvGvPJBcaxW7sf6hQIDAQABAoIBADud1VFDidoH8Fs9
YCsAobfUr4wl5oOltHRIufVtsP04Ji4osTcciGw4n0I+b1iJuOSkMygIw9nKitOc
qPPqLdQ0QNCWC5Z+FnTSfoMutKwffiVMaOUsGKcxgxDURUAGQkBJ54P6FSz+Mutx
pcu7uWL+t2fxBNEot1gErveTnVGiva0lX+xTQM8c+Ghce5IXHrjFD9Em7Mu+1mms
OYxlinwfUQvgvaJArHmKKOGmG9/nwNIrRuvQCWHfVSj0feEubFaZIxHRRU3k21OB
51knwBPh6vDwQ2ksqyWvRyshq0EsWNuLT5l2+Zb1C+NXwqh8/SlxzHUqi3LbK4Gg
MRPEhO0CgYEA9SPEwe2MCOv3onpFWJOtsBulyrLed+MzVbDqRC29Y3PjHFftb6mi
2Dh0LpkjoFeGA+L29JZJnqfkhVLbu+5z8LB6Z/zem4EzxXMxQ2b8h9MnbJQYqDHg
Xq1XeVmxPJMKN67O8u5ku19av5vZHGq0Q65nln77UiKwEND54DoOBucCgYEA8JAG
+INMMYPAAJIjhWAV8UbiY0IRcpE+eIpb4gjWmPciskzxLKAjedrQxJywebu12r8r
IH2redvfTSyeDWH1dAj2n71W14flZThbPmkSlb5gO2R0wEhDw2pUdTBTtegP88+Z
rL5WIA+Hle/AU7uFQKOn4r6php474Bt06sZzwbMCgYEAktjxdeZyO6n3NyqdvfkB
U/zL7UgHQrQkvVF0lJD94cS7KPB3OKva9EGlP4DXOacUjeF5ZH1e7p7OoxtGrCak
52sgeIifZXIZbE+cFC9uWYMhG8b/mkn+iVi3jOcw6AOBXGfoathqGWB+wUd/4Kj/
AYhJX3sD3GkRJZG6DhtY6cMCgYEAp7RAp88gtwQaPkui58Bsi5/XA0tzzmLjIjWS
iKmQsWLYlWR+XZXmJXUeRXLWtIbf6HeNIUF64aEeszZ/mOTJsPLuu73LZMYgbcg0
E/Y8NphZjg4iNkoqs3jVGD1wnkgBlv8LKxomAIPTCfvyIG2CH+X3jGNO28JEC6AY
ifN/j3ECgYBkWWh8gQEHIEFkce4GvjDI0TQiT1HAO01MNVl1Si5BjBL9rPLlbAPO
sMkiGjKCbAn/w7xhln9IcsTm8EhsKrpsNkAon2sNNGg5uoCsMwO9CqGIvVTBsX84
lSqIz1Vex5yCZAySKgPUFw89Llvu+WLcy6ZXf9ZDiH6oqR+rdmd6EQ==
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,579D3F4E703C6287
lYbBuzBurcdWdxmt+cEZNYsKtIpmkPUtHZ+/WuP7CSiINuIx3fxZyitIKAMiwuYM
404t+/iR5jmzJWPEwWkj+XXCPN5vJDbf4euLY+d++3VSbXWas2fxutfzIPRRXdoQ
WvjnR4vQDIUE3vHYcDyS1j2gwmbyeBaZBFlJ8Qyloy1W3rLTn3nxizfK7KqkGSaO
lm1eSfTw8wj2M6nryPPBDHq9PS3Ic+mJDL0gIXPq8D+UcnTbVCXluguErn+4y7LJ
f0RX2sJ8KaR5CmRpfHL7kzVc+oXI5CoWqOFZpjNojpvDqSrh97DpIArOoYrlX6dR
pXlRdXhhXdzQ4CpGLcAthyAhuaSzSKF3+X1S/oRXM1TtkBvAGxw6b1x10hOu/7Cn
/tzFcpz1E2LYL67+jGJ9IpEZkT2e8inVeBBq2nb8qN214XNVpdia4Xm5rV0qVMpB
E8hLmkmzZyOJGKWJbwgjAjCv9C7E4urgKySjBjWdBmpQnqTJoiAE60qjlyuC6VT6
BOr5rq1qIpqy3lJZulANABPMAdj7rLSdlKhncp0WLlBjMpQhpyF0SEiiEULDvbIp
jwMBfP8K1gsAJRsIUvNrWC6PaD0plNAPn1+yMps0cNddMALFhddXuLau86QrPpOT
BZkS4zqUKDOOGxqs5aVjyaK66ilf79Ga09vjvU5d2A6fysVs5w58LJbz8za/zyt5
qst9Tg8kUXs4aRHeABV7v2/F8CxDoUdFYH49Ga8IJQn2nGX0zqF7lOBVv5LZlTDy
/2g3Q7yqCObfHofKIBt7U266IrHbg2Sn5px2suyAjKxgbAE+GXamiLrfpwZ4ao0G
5BAkIc65JE795JfEXuWc1ZwC7yvfF1W2e0UTjj1HHSWZQzcO8W6nlNGSKl21b1Ez
wdjDXnKxi1OGVN0qjEVJxB62GoLatVMtl3diivE7gdg8TRDZtGbEBbRNG/Wwa6LT
phKO3H66bjyQJmldK5eYRQwToAIKJ3lyZH/gnGV/jrOZ2FuAR6CTAOdUTmFD6Hww
+eRomTvawWrqXOut8LS9uWixzEANnBTZ7iR3bL6ux8Auv4utNbaLtAfwpAHGHrOD
ULW6zums2qNb2J1K1f36L/Y7GESCOcgeZ4I1yHaKAcdyJmoEg4tYTMGmMUNl3w1U
47mBpQu0Sg8PtFCt3hp79qaRNOMIn6MEkmTeIyootjt7KxtD5BMYxy0DxpTBhAuj
Z2gxUSR4Ozm1vHbcOi87ZW2nPA8L5C2/SD03DsJPf4BbnVLuP7swLlLPDs4Ra6nL
qrm6devSZjeuXj1+jqLoqR5L5QBAzFOw5p5YfoPkVu4TrNM44Pv1tdkfYE/SX2tZ
UkLPLwfhDa2Q3zqvuzaTAQTZ4PjQTfB4c/eVC4c/463aTywri963WqSg1kKESAMw
O7XFSvUhUDljR1CGAOAYZWQ8cQ9A1kHinooJLHBpzWeoVAjajJrgusv1mryQzcjs
TVL75mveOGetHrcPcR1aUXiFDcYZp5OYo23A2z34wYagORSvdg0UWgtDj+9EPwRk
plMZ77cnkLkd6x7cQCobj2yHRH0foN1L1ntKLxO0joo85UQUsSoba9nCoeS2Hvlj
-----END RSA PRIVATE KEY-----
......@@ -107,6 +107,84 @@ class KeyManagement(PivTestCase):
csr = x509.load_pem_x509_csr(output.encode(), default_backend())
self.assertTrue(csr.is_signature_valid)
def test_import_correct_cert_succeeds_with_pin(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
DEFAULT_MANAGEMENT_KEY, '--pin-policy', 'ALWAYS', '-')
ykman_cli(
'piv', 'generate-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, '-s', 'test',
input=public_key_pem)
ykman_cli('piv', 'export-certificate', '9a', '/tmp/test-pub-key.pem')
with self.assertRaises(SystemExit):
ykman_cli(
'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY)
ykman_cli(
'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN)
ykman_cli(
'piv', 'import-certificate', '9a', '/tmp/test-pub-key.pem',
'-m', DEFAULT_MANAGEMENT_KEY, input=DEFAULT_PIN)
def test_import_wrong_cert_fails(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
DEFAULT_MANAGEMENT_KEY, '--pin-policy', 'ALWAYS', '-')
ykman_cli(
'piv', 'generate-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, '-s', 'test',
input=public_key_pem)
cert_pem = ykman_cli('piv', 'export-certificate', '9a', '-')
# Overwrite the key with a new one
ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
DEFAULT_MANAGEMENT_KEY, '--pin-policy', 'ALWAYS', '-',
input=public_key_pem)
with self.assertRaises(SystemExit):
ykman_cli(
'piv', 'import-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, input=cert_pem)
def test_import_wrong_cert_can_be_forced(self):
# Set up a key in the slot and create a certificate for it
public_key_pem = ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
DEFAULT_MANAGEMENT_KEY, '--pin-policy', 'ALWAYS', '-')
ykman_cli(
'piv', 'generate-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, '-s', 'test',
input=public_key_pem)
cert_pem = ykman_cli('piv', 'export-certificate', '9a', '-')
# Overwrite the key with a new one
ykman_cli(
'piv', 'generate-key', '9a', '-a', 'ECCP256', '-m',
DEFAULT_MANAGEMENT_KEY, '--pin-policy', 'ALWAYS', '-',
input=public_key_pem)
with self.assertRaises(SystemExit):
ykman_cli(
'piv', 'import-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, input=cert_pem)
ykman_cli(
'piv', 'import-certificate', '9a', '-',
'-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, '--no-verify',
input=cert_pem)
@unittest.skipIf(*no_attestation)
def test_export_attestation_certificate(self):
output = ykman_cli('piv', 'export-certificate', 'f9', '-')
......
import unittest
from .util import (DestructiveYubikeyTestCase, ykman_cli, can_write_config)
VALID_LOCK_CODE = 'a' * 32
INVALID_LOCK_CODE_NON_HEX = 'z' * 32
@unittest.skipIf(not can_write_config(), 'Device can not write config')
class TestConfigUSB(DestructiveYubikeyTestCase):
def setUp(self):
ykman_cli('config', 'usb', '--enable-all', '-f')
def tearDown(self):
ykman_cli('config', 'usb', '--enable-all', '-f')
def test_disable_otp(self):
ykman_cli('config', 'usb', '--disable', 'OTP', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('OTP', output)
def test_disable_u2f(self):
ykman_cli('config', 'usb', '--disable', 'U2F', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('FIDO U2F', output)
def test_disable_openpgp(self):
ykman_cli('config', 'usb', '--disable', 'OPGP', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('OpenPGP', output)
def test_disable_piv(self):
ykman_cli('config', 'usb', '--disable', 'PIV', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('PIV', output)
def test_disable_oath(self):
ykman_cli('config', 'usb', '--disable', 'OATH', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('OATH', output)
def test_disable_fido2(self):
ykman_cli('config', 'usb', '--disable', 'FIDO2', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('FIDO2', output)
def test_disable_and_enable(self):
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'usb', '--disable', 'FIDO2', '--enable',
'FIDO2', '-f')
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'usb', '--enable-all', '--disable', 'FIDO2', '-f')
def test_disable_all(self):
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'usb', '-d', 'FIDO2', '-d', 'U2F', '-d',
'OATH', '-d', 'OPGP', 'PIV', '-d', 'OTP')
def test_mode_command(self):
ykman_cli('mode', 'ccid', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('FIDO U2F', output)
self.assertNotIn('FIDO2', output)
self.assertNotIn('OTP', output)
ykman_cli('mode', 'otp', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('FIDO U2F', output)
self.assertNotIn('FIDO2', output)
self.assertNotIn('OpenPGP', output)
self.assertNotIn('PIV', output)
self.assertNotIn('OATH', output)
ykman_cli('mode', 'fido', '-f')
output = ykman_cli('config', 'usb', '--list')
self.assertNotIn('OTP', output)
self.assertNotIn('OATH', output)
self.assertNotIn('PIV', output)
self.assertNotIn('OpenPGP', output)
@unittest.skipIf(not can_write_config(), 'Device can not write config')
class TestConfigNFC(DestructiveYubikeyTestCase):
def setUp(self):
ykman_cli('config', 'nfc', '--enable-all', '-f')
def tearDown(self):
ykman_cli('config', 'nfc', '--enable-all', '-f')
def test_disable_otp(self):
ykman_cli('config', 'nfc', '--disable', 'OTP', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('OTP', output)
def test_disable_u2f(self):
ykman_cli('config', 'nfc', '--disable', 'U2F', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('FIDO U2F', output)
def test_disable_openpgp(self):
ykman_cli('config', 'nfc', '--disable', 'OPGP', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('OpenPGP', output)
def test_disable_piv(self):
ykman_cli('config', 'nfc', '--disable', 'PIV', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('PIV', output)
def test_disable_oath(self):
ykman_cli('config', 'nfc', '--disable', 'OATH', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('OATH', output)
def test_disable_fido2(self):
ykman_cli('config', 'nfc', '--disable', 'FIDO2', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertNotIn('FIDO2', output)
def test_disable_all(self):
ykman_cli('config', 'nfc', '--disable-all', '-f')
output = ykman_cli('config', 'nfc', '--list')
self.assertFalse(output)
def test_disable_and_enable(self):
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'nfc', '--disable', 'FIDO2',
'--enable', 'FIDO2', '-f')
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'nfc', '--disable-all', '--enable', 'FIDO2', '-f')
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'nfc', '--enable-all', '--disable', 'FIDO2', '-f')
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'nfc', '--enable-all', '--disable-all', 'FIDO2', '-f')
@unittest.skipIf(not can_write_config(), 'Device can not write config')
class TestConfigLockCode(DestructiveYubikeyTestCase):
def test_set_lock_code(self):
ykman_cli(
'config', 'set-lock-code', '--new-lock-code', VALID_LOCK_CODE)
output = ykman_cli('info')
self.assertIn(
'Configured applications are protected by a lock code', output)
ykman_cli(
'config', 'set-lock-code', '-l', VALID_LOCK_CODE, '--clear')
output = ykman_cli('info')
self.assertNotIn(
'Configured applications are protected by a lock code', output)
def test_set_invalid_lock_code(self):
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'set-lock-code',
'--new-lock-code', 'aaaa')
with self.assertRaises(SystemExit):
ykman_cli(
'config', 'set-lock-code',
'--new-lock-code', INVALID_LOCK_CODE_NON_HEX)
import unittest
from .util import (DestructiveYubikeyTestCase, is_fips, ykman_cli)
class TestYkmanInfo(DestructiveYubikeyTestCase):
def test_ykman_info(self):
info = ykman_cli('info')
self.assertIn('Device type:', info)
self.assertIn('Serial number:', info)
self.assertIn('Firmware version:', info)
@unittest.skipIf(is_fips(), 'Not applicable to YubiKey FIPS.')
def test_ykman_info_does_not_report_fips_for_non_fips_device(self):
info = ykman_cli('info')
self.assertNotIn('FIPS', info)
@unittest.skipIf(not is_fips(), 'YubiKey FIPS required.')
def test_ykman_info_reports_fips_status(self):
info = ykman_cli('info')
self.assertIn('FIPS Approved Mode:', info)
self.assertIn(' FIDO U2F:', info)
self.assertIn(' OATH:', info)
self.assertIn(' OTP:', info)
# -*- coding: utf-8 -*-
import unittest
from ykman.util import TRANSPORT
from .util import (DestructiveYubikeyTestCase, missing_mode, ykman_cli,
get_version, is_fips)
URI_HOTP_EXAMPLE = 'otpauth://hotp/Example:demo@example.com?' \
'secret=JBSWY3DPK5XXE3DEJ5TE6QKUJA======&issuer=Example&counter=1'
URI_TOTP_EXAMPLE = (
'otpauth://totp/ACME%20Co:john.doe@email.com?'
'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co'
'&algorithm=SHA1&digits=6&period=30')
URI_TOTP_EXAMPLE_B = (
'otpauth://totp/ACME%20Co:john.doe.b@email.com?'
'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co'
'&algorithm=SHA1&digits=6&period=30')
URI_TOTP_EXAMPLE_EXTRA_PARAMETER = (
'otpauth://totp/ACME%20Co:john.doe.extra@email.com?'
'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co'
'&algorithm=SHA1&digits=6&period=30&skid=JKS3424d')
PASSWORD = 'aaaa'
@unittest.skipIf(*missing_mode(TRANSPORT.CCID))
class TestOATH(DestructiveYubikeyTestCase):
@classmethod
def setUpClass(cls):
ykman_cli('oath', 'reset', '-f')
def test_oath_info(self):
output = ykman_cli('oath', 'info')
self.assertIn('version:', output)
@unittest.skipIf(is_fips(), 'Not applicable to YubiKey FIPS.')
def test_info_does_not_indicate_fips_mode_for_non_fips_key(self):
info = ykman_cli('oath', 'info')
self.assertNotIn('FIPS:', info)
def test_oath_add_credential(self):
ykman_cli('oath', 'add', 'test-name', 'abba')
creds = ykman_cli('oath', 'list')
self.assertIn('test-name', creds)
def test_oath_add_credential_prompt(self):
ykman_cli('oath', 'add', 'test-name-2', input='abba')
creds = ykman_cli('oath', 'list')
self.assertIn('test-name-2', creds)
def test_oath_add_credential_with_space(self):
ykman_cli('oath', 'add', 'test-name-space', 'ab ba')
creds = ykman_cli('oath', 'list')
self.assertIn('test-name-space', creds)
def test_oath_hidden_cred(self):
ykman_cli('oath', 'add', '_hidden:name', 'abba')
creds = ykman_cli('oath', 'code')
self.assertNotIn('_hidden:name', creds)
creds = ykman_cli('oath', 'code', '-H')
self.assertIn('_hidden:name', creds)
def test_oath_add_uri_hotp(self):
ykman_cli('oath', 'uri', URI_HOTP_EXAMPLE)
creds = ykman_cli('oath', 'list')
self.assertIn('Example:demo', creds)
def test_oath_add_uri_totp(self):
ykman_cli('oath', 'uri', URI_TOTP_EXAMPLE)
creds = ykman_cli('oath', 'list')
self.assertIn('john.doe', creds)
def test_oath_add_uri_totp_extra_parameter(self):
ykman_cli('oath', 'uri', URI_TOTP_EXAMPLE_EXTRA_PARAMETER)
creds = ykman_cli('oath', 'list')
self.assertIn('john.doe.extra', creds)
def test_oath_add_uri_totp_prompt(self):
ykman_cli('oath', 'uri', input=URI_TOTP_EXAMPLE_B)
creds = ykman_cli('oath', 'list')
self.assertIn('john.doe', creds)
def test_oath_code(self):