pax_global_header00006660000000000000000000000064125666316440014527gustar00rootroot0000000000000052 comment=b02904917ac91c8cb785a9f3195156dd53700641 python-pyhsm-1.0.4l/000077500000000000000000000000001256663164400143645ustar00rootroot00000000000000python-pyhsm-1.0.4l/COPYING000066400000000000000000000024571256663164400154270ustar00rootroot00000000000000Copyright (c) 2011-2014 Yubico AB All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-pyhsm-1.0.4l/ChangeLog000066400000000000000000001700301256663164400161370ustar00rootroot000000000000002015-08-24 Dain Nilsson * NEWS: Prepare for release. 2015-08-24 Dain Nilsson * maintainer-scripts/README: Corrected release instructions in README. 2015-08-24 Dain Nilsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Corrected version and NEWS. 2015-08-21 Simon Josefsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Bump version. 2015-08-17 Jean Paul Galea * doc/Database_Usage.adoc: Documentation fixes. - newline between IMPORT/EXPORT examples. - capital letters. 2015-08-17 Jean Paul Galea * yubikey-ksm/yhsm-yubikey-ksm: Changes tabs -> spaces. - adhere with project convention, avoid subtle bugs due to incorrect indentation. 2015-08-11 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: commit the transaction after looking at all rows and print sqlalchemy exception 2014-10-30 Dain Nilsson * doc/Database_Usage.adoc: CAUTION instead of NOTE. 2014-10-30 Dain Nilsson * doc/DatabaseUsage.txt, doc/Database_Usage.adoc, doc/Intro.adoc, doc/Intro.txt, doc/RunningSelfTests.txt, doc/Running_Hardware_Tests.adoc, doc/YubiKeyKSM.txt, doc/YubiKey_KSM.adoc: Made doc/* into asciidoc. 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README: Update README 2014-10-29 Henrik Stråth * README.adoc: symlinked README 2014-09-22 Simon Josefsson * Lib/pyhsm/basic_cmd.py: Fix some cut'n'paste issues. 2014-09-18 Simon Josefsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Version 1.0.4k. 2014-09-18 Simon Josefsson * NEWS, utils/yhsm-db-export, utils/yhsm-db-import: Make it work. 2014-09-16 Simon Josefsson * NEWS: Version 1.0.4j. 2014-09-16 Simon Josefsson * yubikey-ksm/yhsm-yubikey-ksm: More verbose. 2014-09-16 Simon Josefsson * Lib/pyhsm/__init__.py, NEWS, setup.py, yubikey-ksm/yhsm-yubikey-ksm: yhsm-yubikey-ksm: Fix syntax error. 2014-09-16 Simon Josefsson * Lib/pyhsm/__init__.py: Prepare for release. 2014-09-16 Simon Josefsson * NEWS: Version 1.0.4i. 2014-09-16 Simon Josefsson * setup.py: Bump setup.py. 2014-09-16 Simon Josefsson * maintainer-scripts/make-release.sh: Fix release script. 2014-09-16 Simon Josefsson * MANIFEST.in: Drop wiki/. 2014-09-16 Simon Josefsson * README: Updates. 2014-09-16 Simon Josefsson * utils/yhsm-db-export.1, utils/yhsm-db-import.1: Typo. 2014-09-16 Klas Lindfors * utils/yhsm-db-export.1, utils/yhsm-db-import.1: man pages 2014-09-16 Simon Josefsson * utils/yhsm-db-export, utils/yhsm-db-import: Don't read username/password from stdin. 2014-09-16 Simon Josefsson * NEWS: Doc fixes. 2014-09-16 Simon Josefsson * yubikey-ksm/yhsm-yubikey-ksm: Fix error handling a bit. 2014-09-16 Simon Josefsson * yubikey-ksm/yhsm-yubikey-ksm: Don't read username/password from stdin. 2014-09-16 Klas Lindfors * doc/YubiKeyKSM.txt: update URL 2014-09-16 Simon Josefsson * utils/yhsm-db-export, utils/yhsm-db-import, yubikey-ksm/yhsm-yubikey-ksm: Fix tool descriptions. Fix SQLAlchemy import statements. 2014-09-16 Simon Josefsson * : commit 16d72e989905585ac3f671f683c03faf945c1006 Author: Klas Lindfors Date: Tue Sep 16 12:12:49 2014 +0200 2014-09-16 Simon Josefsson * : commit c9c66dfcae086e2112766a22a9c9743ab4a792db Author: Simon Josefsson Date: Tue Sep 16 11:44:15 2014 +0200 2014-09-16 Simon Josefsson * AUTHORS, Tests/README, doc/DatabaseUsage.txt, doc/RunningSelfTests.txt, utils/README.db.import-export: Doc fixes. 2014-09-16 Simon Josefsson * AUTHORS, README: Cleanup README. 2014-09-16 Simon Josefsson * doc/Intro.txt, doc/README, doc/YubiKeyKSM.txt: Simplify doc/README since we dropped the wiki. 2014-09-16 Simon Josefsson * .gitmodules: Drop .gitmodules. 2014-09-16 Simon Josefsson * .gitmodules, doc/wiki: Drop git submodule. 2014-09-15 Simon Josefsson * COPYING, maintainer-scripts/make-release.sh, utils/yhsm-daemon.1, utils/yhsm-decrypt-aead.1, utils/yhsm-generate-keys.1, utils/yhsm-keystore-unlock.1, utils/yhsm-linux-add-entropy.1, yhsm-val/yhsm-init-oath-token.1, yhsm-val/yhsm-validate-otp.1, yhsm-val/yhsm-validation-server.1, yubikey-ksm/yhsm-import-keys.1, yubikey-ksm/yhsm-yubikey-ksm.1: Fix URLs a bit. 2014-09-15 Simon Josefsson * BLURB: Fix URL. 2014-08-28 Klas Lindfors * : commit e4ea12b8c2fd5910e662924f5f572ade0de16910 Merge: ffab80a 457115e Author: Dain Nilsson Date: Tue Jun 24 11:18:32 2014 +0200 2014-06-16 Alex Fisher * setup.py: Add python-daemon dependency 2014-06-12 Alex Fisher * utils/yhsm-daemon: Add option to write pid file This option is similar to the one that already exists for yhsm-yubikey-ksm 2014-06-12 Alex Fisher * yubikey-ksm/yhsm-yubikey-ksm: Add option to run yhsm-yubikey-ksm as a proper daemon Uses https://pypi.python.org/pypi/python-daemon/ library. 2014-06-12 Alex Fisher * utils/yhsm-daemon: Add option to run yhsm-daemon as a proper daemon 2014-06-12 Alex Fisher * Lib/pyhsm/stick_client.py: Make stick_client raw_device() return the socket 2014-04-25 Simon Josefsson * README: Mention pycrypto >= 2.1. 2014-04-25 Klas Lindfors * utils/yhsm-generate-keys: use nonce correctly, not public_id we set the nonce variable already, just use it for generate_aead() 2014-03-20 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: restructure to get a new connection from engine for each query should use sqlalchemy's pool then 2014-03-17 Klas Lindfors * utils/yhsm-db-import: allow db-import to continue when getting errors 2014-03-17 Klas Lindfors * utils/yhsm-db-import: publicId -> public_id 2014-03-17 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: use transactions to avoid isolation issues 2014-02-19 Klas Lindfors * BLURB: add BLURB 2014-02-19 Klas Lindfors * BLURB: add BLURB 2014-01-30 Klas Lindfors * : commit 687e80be6f62026bdb2733023b04bec49c4e789d Author: Klas Lindfors Date: Wed Jan 29 15:38:47 2014 +0100 2014-01-29 Klas Lindfors * utils/yhsm-db-export, utils/yhsm-db-import, yubikey-ksm/yhsm-yubikey-ksm: whitespace cleanup 2014-01-29 Klas Lindfors * utils/yhsm-db-import: skip files that don't look like aeads 2014-01-29 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: more database work 2014-01-29 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: only set the key_handle if we get an aead back 2014-01-29 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: re-work dbload, use sqlalchemy 2014-01-28 Klas Lindfors * utils/yhsm-db-import: minor refactor of yhsm-db-import 2014-01-09 Dain Nilsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Bumped version and updated NEWS for release. 2014-01-09 Dain Nilsson * utils/yhsm-daemon, utils/yhsm-daemon.1: Added note about client/daemon version compatibility. 2014-01-08 Dain Nilsson * Lib/pyhsm/stick_client.py, utils/yhsm-daemon: Replaced pickle with JSON in yhsm-daemon. 2014-01-08 Dain Nilsson * .gitignore: Added .ropeproject to gitignore. 2013-11-01 Klas Lindfors * Tests/README: fixed README hsm configuration from tom@yubico.com moved from dpkg repo. 2013-09-18 tom * yubikey-ksm/yhsm-yubikey-ksm: database support now supports files system aeads also 2013-09-12 Tommaso Galassi De Orchi * yubikey-ksm/yhsm-yubikey-ksm: added AEADs loading from database with --db-url option 2013-08-14 Tommaso Galassi De Orchi * utils/yhsm-db-export, utils/yhsm-db-import: added load/save from lib 2013-08-13 Simon Josefsson * doc/db_schema: Add nonce field. Add explicit sizes. 2013-07-22 Tommaso Galassi De Orchi * utils/yhsm-db-export, utils/yhsm-db-import: minor improvements 2013-07-19 Tommaso Galassi De Orchi * utils/README.db.import-export: updated README.db.import-export 2013-07-19 Tommaso Galassi De Orchi * utils/README.db.import-export: updated README.db.import-export 2013-07-19 Tommaso Galassi De Orchi * utils/db_schema: removed db_schema 2013-07-18 Tommaso Galassi De Orchi * utils/yhsm-db-export: security improvment for yhsm-db-export 2013-07-17 Tommaso Galassi De Orchi * utils/yhsm-db-import: security fix for url 2013-07-16 Tommaso Galassi De Orchi * utils/yhsm-db-export: minor improvments 2013-07-16 Tommaso Galassi De Orchi * utils/README.db.import-export, utils/yhsm-db-export, utils/yhsm-db-import: minor improvments 2013-07-16 Tommaso Galassi De Orchi * utils/yhsm-db-export, utils/yhsm-db-import: added + on db-import-export 2013-07-16 Tommaso Galassi De Orchi * utils/README.db.import-export, utils/README.yhsm-dbimport-aead, utils/db_schema, utils/yhsm-db-export, utils/yhsm-db-import, utils/yhsm-db-manage: added yhsm-db-import and yhsm-db-export and db_schema 2013-07-12 Tommaso Galassi De Orchi * doc/db_schema: added db_schema in doc/ 2013-07-12 Tommaso Galassi De Orchi * utils/README.yhsm-dbimport-aead, utils/yhsm-db-manage: Added yhsm-db-manage and README.yhsm-db-manage for importing the AEADs into a Database 2013-05-06 Dain Nilsson * utils/yhsm-daemon: Removed debug print. 2013-05-06 Dain Nilsson * NEWS: Updated NEWS for release. 2013-05-06 Dain Nilsson * maintainer-scripts/README: Edit README 2013-05-06 Dain Nilsson * maintainer-scripts/update-release-page.sh: Removed update-release-page as it is no longer needed. 2013-05-06 Dain Nilsson * utils/yhsm-daemon: Raise YHSM_Error instead of Exception. 2013-05-06 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm.1: man page 2013-05-03 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: add stats collection and extraction through it's own url 2013-05-06 Dain Nilsson * Lib/pyhsm/stick_client.py, utils/yhsm-daemon: More daemon fixes. 2013-05-06 Dain Nilsson * NEWS: Updated NEWS. 2013-05-06 Dain Nilsson * Lib/pyhsm/base.py, Lib/pyhsm/stick_client.py, utils/yhsm-daemon, utils/yhsm-daemon.1: Improved yhsm-daemon. 2013-04-22 Dain Nilsson * maintainer-scripts/make-release.sh: Fix release publishing. 2013-04-12 Dain Nilsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Bumped version post release. 2013-04-12 Dain Nilsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Updated NEWS, setup.py, and __init__.py for new version. 2013-04-12 Dain Nilsson * utils/yhsm-daemon, utils/yhsm-daemon.1: Changed default port number. 2013-04-12 Dain Nilsson * utils/yhsm-daemon, utils/yhsm-daemon.1: Add man page for yhsm-daemon. 2013-04-12 Dain Nilsson * Lib/pyhsm/stick_server.py, utils/yhsm-daemon: Added yhsm-daemon. 2013-04-12 Dain Nilsson * Lib/pyhsm/stick_server.py: Improved locking. 2013-04-12 Dain Nilsson * Lib/pyhsm/base.py, Lib/pyhsm/stick_server.py, Tests/README, Tests/test_common.py, Tests/test_init.py: Allow running tests using a different device. 2013-04-12 Dain Nilsson * Lib/pyhsm/stick.py, Lib/pyhsm/stick_client.py, Lib/pyhsm/stick_server.py: Create device from url. 2013-04-04 Dain Nilsson * Lib/pyhsm/base.py, Lib/pyhsm/cmd.py, Lib/pyhsm/stick.py, Lib/pyhsm/stick_client.py, Lib/pyhsm/stick_server.py: Added client and server. 2013-04-11 Dain Nilsson * Tests/test_yubikey_validate.py: Fixed test passig wrong argument. 2013-04-11 Dain Nilsson * Tests/README: Added README for running tests. 2013-04-11 Dain Nilsson * setup.py: Lower required versions of pyserial and pycrypto. 2013-04-10 Dain Nilsson * .gitignore, MANIFEST.in, maintainer-scripts/make-release.sh: Rewrite of make-release.sh 2013-04-08 Fredrik Thulin * setup.py: Also depends on pycrypto. 2013-04-08 Fredrik Thulin * setup.py: Add missing dependency information. 2013-04-06 Simon Josefsson * NEWS: Version 1.0.4e. 2013-03-31 Simon Josefsson * NEWS: Doc fix. 2013-03-31 Simon Josefsson * utils/yhsm-decrypt-aead: Rework logging code so it produces correct results. 2013-03-31 Simon Josefsson * utils/yhsm-decrypt-aead: Cleanup warning/error diagnostics. Print them to stderr. 2013-03-30 Simon Josefsson * NEWS, utils/yhsm-decrypt-aead: yhsm-decrypt-aead: For yubikey-csv output, fix prefix field. 2013-03-18 Klas Lindfors * Lib/pyhsm/__init__.py, NEWS, setup.py: bump versions 2013-03-18 Klas Lindfors * NEWS: News for version 1.0.4d 2013-03-18 Klas Lindfors * yubikey-ksm/yhsm-yubikey-ksm: only set public_id as nonce if we didn't find a nonce in the file also making sure it's encoded correctly 2013-03-18 Klas Lindfors * Lib/pyhsm/__init__.py, NEWS, setup.py: bump versions post-release 2013-03-18 Klas Lindfors * COPYING: bump Copyright 2013-03-18 Klas Lindfors * NEWS: NEWS for 1.0.4c 2013-03-18 Klas Lindfors * maintainer-scripts/README: typo 2013-03-18 Klas Lindfors * README: new ppa and key 2013-03-18 Klas Lindfors * utils/yhsm-generate-keys, utils/yhsm-generate-keys.1, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-import-keys.1: add --random-nonce to yhsm-generate-keys and yhsm-import-keys 2013-03-15 Klas Lindfors * Lib/pyhsm/yubikey.py: fix the case where public_id and nonce differ the nonce is stored in the aead, so if it's there, use it 2013-02-11 Dain Nilsson * maintainer-scripts/make-release.sh: Added check for correct NEWS header. 2013-02-11 Dain Nilsson * Lib/pyhsm/__init__.py, NEWS, setup.py: Bumped version numbers post release. 2013-02-11 Dain Nilsson * maintainer-scripts/README: Added README to maintainer-scripts. 2013-02-11 Dain Nilsson * maintainer-scripts/update-release-page.sh: Added script to update releases on gh-pages. 2013-02-11 Dain Nilsson * NEWS: Updated NEWS 2013-02-11 Dain Nilsson * utils/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys: Don't create/import a zero (cc...c) key, as the nonce will be wrong. 2013-02-11 Dain Nilsson * Tests/test_aead.py, Tests/test_db.py: Skip some tests when running < 1.0.4 2013-02-08 Dain Nilsson * utils/yhsm-generate-keys: Fixed incorrect nonce when generating keys. 2013-02-08 Dain Nilsson * Lib/pyhsm/__init__.py: Bumped version to 1.0.4b 2013-02-07 Dain Nilsson * yubikey-ksm/yhsm-import-keys: Ignore lines starting with #. 2012-09-12 Simon Josefsson * setup.py: Bump version. 2012-09-12 Simon Josefsson * NEWS: Update. 2012-08-30 Fredrik Thulin * utils/yhsm-decrypt-aead: Better error handling for batch runs. Add --fail-fast to exit as soon as a failure is encountered (default: false). 2012-08-30 Fredrik Thulin * utils/yhsm-decrypt-aead: Ignore non-modhex files (other metadata) 2012-08-30 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: Support soft HSM AEAD generation. 2012-08-30 Fredrik Thulin * utils/yhsm-decrypt-aead: aead.nonce should be 6 bytes, not 12 chars. 2012-08-28 Fredrik Thulin * : commit e1e4abba10f57717c8684a37aab2f080b73974ef Author: Fredrik Thulin Date: Mon Aug 27 13:07:07 2012 +0200 2012-08-27 Fredrik Thulin * utils/yhsm-decrypt-aead: --aes-key-out should not be required. 2012-08-27 Fredrik Thulin * utils/yhsm-generate-keys: typo in documentation 2012-08-27 Fredrik Thulin * utils/yhsm-decrypt-aead: Add '--format aead' to genereate new AEADs. Also adds a number of other arguments : --output-dir --key-handle-out --aes-key-out This is usable to convert AEADs from one KSM to another. 2012-08-24 Fredrik Thulin * utils/yhsm-generate-keys: bugfix: public_id is not in hex here. 2012-08-22 Simon Josefsson * NEWS: Add. 2012-08-22 Fredrik Thulin * : commit 8d24b21e99a58e6ab2331d89806e7a38f422f3e2 Author: Simon Josefsson Date: Wed Aug 22 12:36:42 2012 +0200 2012-06-26 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.4a. 2012-06-26 Fredrik Thulin * Lib/pyhsm/base.py: Verify that data we send to and receive from the YubiHSM isn't mangled. 2012-06-26 Fredrik Thulin * yhsm-val/yhsm-validation-server, yubikey-ksm/yhsm-yubikey-ksm: Handle IPv6 addresses in --addr. We need to set address_family to AF_INET6 manually, since SocketServer.TCPserver() always try to use AF_INET. 2012-06-21 Fredrik Thulin * Lib/pyhsm/aead_cmd.py: mend epydoc generation 2012-06-21 Fredrik Thulin * COPYING, Lib/pyhsm/__init__.py, setup.py: Prepare for release 1.0.4. 2012-06-21 Fredrik Thulin * utils/yhsm-decrypt-aead: Minor bugfixes. 2012-06-21 Fredrik Thulin * utils/yhsm-decrypt-aead.1, utils/yhsm-generate-keys.1: init 2012-06-21 Fredrik Thulin * utils/yhsm-keystore-unlock.1, utils/yhsm-linux-add-entropy.1: copy-paste remains 2012-06-21 Fredrik Thulin * utils/yhsm-generate-keys: Produce meaningful exit-status. 2012-06-21 Fredrik Thulin * examples/yhsm-generate-keys: Not an example anymore (moved to utils/), bye. 2012-06-20 Fredrik Thulin * utils/yhsm-generate-keys: Not an example anymore. 2012-06-20 Fredrik Thulin * examples/yhsm-generate-keys: Update comment with info about new yhsm-decrypt-aead. 2012-06-20 Fredrik Thulin * examples/yhsm-generate-keys: Make work again. 2012-06-20 Fredrik Thulin * utils/yhsm-decrypt-aead: init 2012-06-20 Fredrik Thulin * Lib/pyhsm/soft_hsm.py, Tests/test_init.py, Tests/test_soft_hsm.py: Handle messages not multiple of block-size long. 2012-06-20 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, Lib/pyhsm/soft_hsm.py, Tests/test_soft_hsm.py: Implement AES CCM a'la YubiHSM in software. 2012-06-20 Fredrik Thulin * : commit fba63d51ff0badc8b593770b62bca60d49b61a80 Author: Fredrik Thulin Date: Tue Jun 19 16:05:29 2012 +0200 2012-02-24 Fredrik Thulin * Lib/pyhsm/aead_cmd.py: Store nonce used when generating an AEAD when saving an AEAD to file. If a nonce different from the public_id is used when generating an AEAD, we must keep track of the nonce separately. This commit changes the file format used, but should be backwards compatible by using the public_id as nonce on load() if the old file format is detected. 2012-01-25 Fredrik Thulin * Tests/test_yubikey_validate.py: Remove surplus comments. 2012-01-25 Fredrik Thulin * Tests/test_configure.py, Tests/test_otp_validate.py: Key 0x1002 also needs YSM_USER_NONCE now. 2012-01-24 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/version.py, Tests/test_db.py, doc/YubiHSM_if.h: Implement YSM_DB_YUBIKEY_AEAD_STORE2. 2012-01-24 Fredrik Thulin * Tests/test_aead.py, Tests/test_configure.py: Test FLAG_USER_NONCE_ENABLE. 2012-01-20 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/util.py, Tests/test_aead.py: Make AEAD generation with HSM generated nonce work. 2012-02-24 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/cmd.py: Documentation updates. 2012-01-11 Fredrik Thulin * Tests/test_init.py: Another fix for 0.9.8 testing. 2012-01-05 Fredrik Thulin * Tests/test_configure.py: Mend OTP replay in unlock test. 2012-01-05 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.3c. 2012-01-05 Fredrik Thulin * utils/yhsm-keystore-unlock, utils/yhsm-keystore-unlock.1: Add --stdin to read (piped) input from stdin. 2012-01-02 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.3b. 2012-01-02 Fredrik Thulin * .gitattributes: Include maintainer scripts in release tar-balls. Adapt to the Debian (?) definition of source: "preferred form for modification, including build scripts, etc". 2011-12-22 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.3a. 2011-12-21 Fredrik Thulin * examples/yhsm-generate-keys, yubikey-ksm/yhsm-generate-keys: Move currently useless yhsm-generate-keys to examples/. It is currently useless since it generates secrets for YubiKeys without allowing any YubiKeys to be programmed with these secrets. See longer explanation in top pydoc. 2011-12-21 Fredrik Thulin * utils/yhsm-keystore-unlock.1, utils/yhsm-linux-add-entropy.1, yhsm-val/yhsm-init-oath-token.1, yhsm-val/yhsm-validate-otp.1, yhsm-val/yhsm-validation-server.1, yubikey-ksm/yhsm-import-keys.1, yubikey-ksm/yhsm-yubikey-ksm.1: Add man-pages. 2011-12-21 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: Minor usage text improvements. 2011-12-21 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: Don't split --key-handles on comma. (to align with yhsm-yubikey-ksm) 2011-12-21 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Minor usage text improvements. 2011-12-21 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Remove unused parameter --public-id-chars. 2011-12-21 Fredrik Thulin * yhsm-val/yhsm-validation-server: Minor usage text improvement. 2011-12-21 Fredrik Thulin * yhsm-val/yhsm-init-oath-token: usage text improvements 2011-12-21 Fredrik Thulin * yhsm-val/yhsm-init-oath-token: Convey status in exit code. 2011-12-21 Fredrik Thulin * utils/yhsm-linux-add-entropy: Add proper args-parsing. 2011-12-20 Fredrik Thulin * maintainer-scripts/make-release.sh: Add --no-test and --no-sign. 2011-11-15 Fredrik Thulin * maintainer-scripts/make-release.sh: Produce a ChangeLog from git history. 2011-11-15 Fredrik Thulin * Tests/test_aes_ecb.py, Tests/test_common.py, Tests/test_init.py, Tests/test_misc.py: Make test suite work with 0.9.8 again. 2011-11-08 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.3. 2011-11-08 Fredrik Thulin * yhsm-val/yhsm-validation-server: Assorted minor changes. 2011-11-08 Fredrik Thulin * Lib/pyhsm/yubikey.py: Document these utility functions properly. 2011-11-08 Fredrik Thulin * README: Add note about timeout problems in Python 2.6 (SocketServer.py). 2011-11-02 Fredrik Thulin * : commit a80b8a32016eb9a12253638197c7a0dc088a2656 Author: Fredrik Thulin Date: Wed Nov 2 15:08:32 2011 +0100 2011-11-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: Response tinkering. 2011-11-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: Change Content-Type to text/plain. 2011-11-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: Correctly format error responses for 2.0 OTP validation. 2011-11-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: Working HMAC-SHA-1 request validation. 2011-11-01 Fredrik Thulin * Tests/test_configure.py: Update to handle firmware 1.0.3. 2011-11-01 Fredrik Thulin * Lib/pyhsm/cmd.py: typo 2011-08-29 Fredrik Thulin * Tests/test_common.py: Must ignore errors from OTP unlocking as well. 2011-11-01 Fredrik Thulin * Lib/pyhsm/cmd.py: Raise a nice YHSM_Error on unexpected responses. 2011-10-26 Fredrik Thulin * yhsm-val/yhsm-validation-server: Work in progress, mostly work but client id handling is missing. 2011-10-17 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: Indicate errors in exit code. 2011-10-07 Fredrik Thulin * utils/yhsm-keystore-unlock: Show 'Aborted' message even when not verbose. 2011-09-21 Fredrik Thulin * : commit 762cfd85e7bccc41e6e3eafcc5bac36195523034 Author: Fredrik Thulin Date: Wed Sep 21 13:46:46 2011 +0200 2011-09-21 Fredrik Thulin * COPYING, Lib/pyhsm/__init__.py, Lib/pyhsm/aead_cmd.py, Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/exception.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/oath_hotp.py, Lib/pyhsm/stick.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Lib/pyhsm/version.py, Lib/pyhsm/yubikey.py, README, Tests/test_aead.py, Tests/test_aes_ecb.py, Tests/test_basics.py, Tests/test_buffer.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_db.py, Tests/test_hmac.py, Tests/test_init.py, Tests/test_misc.py, Tests/test_oath.py, Tests/test_otp_validate.py, Tests/test_stick.py, Tests/test_util.py, Tests/test_yubikey_validate.py, examples/yhsm-monitor-exit.py, examples/yhsm-password-auth.py, examples/yhsm-sysinfo.py, utils/yhsm-keystore-unlock, utils/yhsm-linux-add-entropy, yhsm-val/yhsm-init-oath-token, yhsm-val/yhsm-validate-otp, yhsm-val/yhsm-validation-server, yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-yubikey-ksm: Clarify licensing by refering to the COPYING file. 2011-09-14 Simon Josefsson * README: Doc fix Some were suggested by Tollef Fog Heen . 2011-09-14 Simon Josefsson * README: Reorder and fix names after renaming. 2011-08-29 Fredrik Thulin * : commit 9cc369a1db92ad58c781f7877a687a866a71d2fe Author: Simon Josefsson Date: Wed Aug 24 15:43:19 2011 +0200 2011-08-24 Fredrik Thulin * utils/yhsm-keystore-unlock: Usage experience tweaks. 2011-08-24 Fredrik Thulin * utils/yhsm-keystore-unlock: Add --no-otp for use by init-scripts. 2011-08-21 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare version 1.0.2b. 2011-08-21 Fredrik Thulin * utils/yhsm-keystore-unlock: Add OTP support and improve usability. 2011-08-21 Fredrik Thulin * Lib/pyhsm/version.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_misc.py: Mend tests for 0.9.x that does not have OTP unlock. 2011-08-21 Fredrik Thulin * Lib/pyhsm/version.py: Correct have_YSM_BUFFER_LOAD. 2011-08-21 Fredrik Thulin * maintainer-scripts/make-release.sh: Fix tar-file name. 2011-08-21 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare for version 1.0.2a. 2011-08-21 Fredrik Thulin * Tests/run.sh: Set PYTHONPATH to make sure we test the current version. 2011-08-21 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_init.py: Implement missing YSM_HSM_UNLOCK. 2011-08-21 Fredrik Thulin * Tests/test_common.py, Tests/test_yubikey_validate.py, doc/wiki: Move YubiKeyEmu to test_common. 2011-08-18 Fredrik Thulin * Lib/pyhsm/base.py: Introduce unlock(), deprecating key_storage_unlock(). 2011-08-18 Fredrik Thulin * maintainer-scripts/make-release.sh: Keep python-pyhsm prefix in tar. 2011-08-18 Fredrik Thulin * .gitattributes, maintainer-scripts/make-release.sh: Tidy up generated release file. 2011-08-18 Fredrik Thulin * maintainer-scripts/make-release.sh: Exclude doc/wiki/.git. 2011-08-18 Fredrik Thulin * maintainer-scripts/generate_html.sh: No graphs. Made distribution unnecessarily big. 2011-08-18 Fredrik Thulin * maintainer-scripts/make-release.sh: Fix where the releases dir ends up. 2011-08-18 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare for version 1.0.2. 2011-08-18 Fredrik Thulin * maintainer-scripts/make-release.sh: Check that version variables are updated. 2011-08-18 Fredrik Thulin * .gitignore: Add generated doc/html 2011-08-18 Fredrik Thulin * doc/README: init 2011-08-18 Fredrik Thulin * .gitattributes, maintainer-scripts/make-release.sh: Prepare to make official releases. 2011-08-18 Fredrik Thulin * .gitmodules: Add Github wiki submodule. 2011-08-18 Fredrik Thulin * Lib/pyhsm/version.py, Tests/test_otp_validate.py: Fix a test case to work with 0.9.8 as well as 1.0. Hope this works - I don't have any 0.9.8 YubiHSM:s available to verify. 2011-08-18 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/version.py, Tests/test_aead.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_init.py, Tests/test_misc.py, Tests/test_oath.py, Tests/test_otp_validate.py, doc/YubiHSM_if.h, utils/yhsm-keystore-unlock: Update to support YubiHSM 1.0. The most significant change from version 0.9.8 is two new keystore unlock commands (deprecating the old YSM_KEY_STORAGE_UNLOCK). YSM_KEY_STORE_DECRYPT - decrypt (AES-256) the keystore into YubiHSM RAM with a passphrase YSM_HSM_UNLOCK - unlock HSM operations using a YubiKey OTP Either one, both or none of these two may be enabled when the YubiHSM is configured. 2011-08-02 Fredrik Thulin * examples/yhsm-linux-add-entropy.py, examples/yhsm-storage-unlock.py, utils/yhsm-keystore-unlock, utils/yhsm-linux-add-entropy: Promote two examples to new utils/ dir. 2011-08-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Add --pid-file support. 2011-08-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: Improve --help output. 2011-08-02 Fredrik Thulin * yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-yubikey-ksm: Change default AEAD directory to /var/cache/yubikey-ksm/aeads. Having the default on RAM disk was just convenient during development. Also did some general code/doc improvements. 2011-08-02 Fredrik Thulin * yhsm-val/yhsm-validation-server: pylint improvements 2011-08-01 Fredrik Thulin * doc/generate_html.sh, maintainer-scripts/generate_html.sh: rename 2011-08-01 Fredrik Thulin * examples/yhsm-storage-unlock.py: Add proper args parsing. 2011-07-29 Fredrik Thulin * yhsm-val/yhsm-validation-server: Show default value for all args. 2011-07-27 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/validate_cmd.py: More type annotations. 2011-07-26 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare for version 0.9.8e. 2011-07-26 Fredrik Thulin * yhsm-val/yhsm-validation-server: Add --pid-file support. 2011-07-26 Fredrik Thulin * doc/generate_html.sh: create doc/html/ if missing 2011-07-26 Fredrik Thulin * Lib/pyhsm/aes_ecb_cmd.py: Input-validate AES ECB block size on encrypt/decrypt. 2011-07-26 Fredrik Thulin * Lib/pyhsm/base.py: More type information. 2011-07-26 Fredrik Thulin * Lib/pyhsm/debug_cmd.py: comment 2011-07-25 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/exception.py: epydoc annotated API documentation. 2011-07-25 Fredrik Thulin * doc/generate_html.sh: init 2011-07-25 Fredrik Thulin * Lib/pyhsm/oath_hotp.py: pylint fix 2011-07-17 Fredrik Thulin * README: Add introduction. 2011-07-17 Fredrik Thulin * Tests/test_yubikey_validate.py: remove debug output 2011-07-04 Fredrik Thulin * Lib/pyhsm/util.py, Tests/test_yubikey_validate.py: Correct max AEAD size. 2011-06-23 Fredrik Thulin * : commit 8f2614ab596623d9c62ad06eaf7e1bdcb6948abb Author: Fredrik Thulin Date: Thu Jun 23 11:53:16 2011 +0200 2011-06-23 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: default args clarifications. 2011-06-23 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Add request timeout. Don't block forever on connections that suffer from network problems. 2011-06-09 Simon Josefsson * README: Mention python-pyhsm-dpkg. 2011-06-07 Fredrik Thulin * README: Add python version info. 2011-06-07 Fredrik Thulin * README: Add installation instructions. 2011-05-30 Fredrik Thulin * Tests/test_basics.py: Add test case for bug fixed in b8f71dceb. 2011-05-30 Fredrik Thulin * : Merge git://github.com/ThomasHabets/python-pyhsm 2011-05-29 Thomas Habets * Lib/pyhsm/basic_cmd.py: Fix type error in nonce repr format string 2011-05-26 Fredrik Thulin * Lib/pyhsm/base.py: speling 2011-05-25 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Prepare for version 0.9.8c. 2011-05-25 Fredrik Thulin * yubikey-ksm/yhsm-generate-keys: Bugfix calculation of bytes to randomize. 2011-05-25 Fredrik Thulin * Lib/pyhsm/util.py, Tests/test_util.py: Fix bug in input_validate_str. Bugfix the raising of exception when input string validation fails exact length check. Only resulted in a TypeError instead of the expected YHSM_WrongInputSize. 2011-05-23 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Support more than one key handle. 2011-05-12 Fredrik Thulin * Lib/pyhsm/__init__.py: remove redundantly listed module 'yubikey' 2011-05-04 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Forgot to update version for 0.9.8b. 2011-05-04 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py, examples/yhsm-storage-unlock.py: Implement YSM_KEY_STORAGE_UNLOCK. 2011-05-02 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/exception.py, Lib/pyhsm/stick.py, Lib/pyhsm/validate_cmd.py: Fix __all__ lists of classes. 2011-04-19 Fredrik Thulin * Lib/pyhsm/__init__.py: Update version to 0.9.8a. 2011-04-19 Fredrik Thulin * examples/yhsm-linux-add-entropy.py: init 2011-04-18 Fredrik Thulin * Lib/pyhsm/__init__.py: fix __all__ list and add basic usage doc. 2011-04-06 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Version 0.9.8. First public beta release. 2011-04-06 Fredrik Thulin * Lib/pyhsm/defines.py, Lib/pyhsm/oath_hotp.py, Tests/test_basics.py, Tests/test_oath.py: Namespace-fix TEMP_KEY_HANDLE -> YSM_TEMP_KEY_HANDLE. 2011-04-06 Fredrik Thulin * Tests/test_common.py: Use new define YSM_PROTOCOL_VERSION. 2011-04-06 Fredrik Thulin * yhsm-val/yhsm-validate-otp: Last minute pre-release fixes. 2011-04-06 Fredrik Thulin * yhsm-val/yhsm-validation-server: Give error message when disabled function is accessed. 2011-04-06 Fredrik Thulin * doc/YubiHSM_if.h: Namespace fixes. 2011-04-06 Fredrik Thulin * yhsm-val/yhsm-validation-server: Documentation and small fixes. 2011-04-06 Fredrik Thulin * yhsm-val/yhsm-init-oath-token: AEADs to be loaded into TEMP_KEY need flags now. 2011-04-06 Fredrik Thulin * yhsm-val/yhsm-validation-server: Change OATH to HOTP/OATH-HOTP. 2011-04-06 Fredrik Thulin * examples/yhsm-password-auth.py, yhsm-val/yhsm-validation-server: Use AEAD encrypt/validate instead of AES ECB encrypt/decrypt_cmd to get the integrity protection of the AEAD's MAC as well. 2011-04-05 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Tests/test_aes_ecb.py, Tests/test_hmac.py: Last-minute change of a lot of defined names. 2011-04-05 Fredrik Thulin * Lib/pyhsm/basic_cmd.py, Tests/test_basics.py, Tests/test_oath.py: Temp key now has flags. When generating an AEAD to be used as temp key, add four bytes with the permission flags the temp key handle should have if the AEAD is later loaded into the temp key. 2011-04-05 Fredrik Thulin * doc/YubiHSM_if.h: Add the C header file as documentation. 2011-04-05 Fredrik Thulin * yhsm-val/yhsm-validation-server: Implement pwhash validation. 2011-04-05 Fredrik Thulin * Lib/pyhsm/aes_ecb_cmd.py: Cleanups. 2011-04-05 Fredrik Thulin * Tests/test_basics.py: Fix test case after nonce change. 2011-04-04 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Aead -> AEAD 2011-04-04 Fredrik Thulin * yhsm-val/yhsm-init-oath-token, yhsm-val/yhsm-validate-otp, yhsm-val/yhsm-validation-server: init, validation application(s) 2011-04-04 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/oath_hotp.py, Tests/test_init.py, Tests/test_oath.py: init, OATH helper functions. 2011-04-04 Fredrik Thulin * Lib/pyhsm/basic_cmd.py: Remember nonce as 6 byte string too, for convenience. 2011-04-02 Fredrik Thulin * yhsm-val/yhsm-validate-otp, yhsm-val/yhsm-validation-server, yubikey-val/yhsm-validate-otp: init 2011-04-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: YHSM -> YubiHSM 2011-04-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Correct usage summary. 2011-04-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: better function name 2011-04-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Refactor and adhere more to the YubiKSM communication spec. Errors should not be returned as HTTP non-2xx, but as a HTTP 200 with a body containing the string ERR optional-reason 2011-04-02 Fredrik Thulin * Lib/pyhsm/__init__.py: add missing buffer_cmd and db_cmd 2011-04-02 Fredrik Thulin * Lib/pyhsm/__init__.py, yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-yubikey-ksm: secrets_cmd was merged with aead_cmd. 2011-04-02 Fredrik Thulin * yubikey-ksm/yhsm-yubikey-ksm: Add documentation. 2011-04-01 Fredrik Thulin * Tests/run.sh: Avoid deprecation warnings from nosetests. 2011-04-01 Fredrik Thulin * Lib/pyhsm/defines.py, Tests/test_basics.py: Bugs hide in every untested LOC. 2011-04-01 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/hmac_cmd.py, Tests/test_hmac.py: Fix (and test) HMAC-SHA1 to_buffer and flags. 2011-04-01 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/stick.py, Lib/pyhsm/util.py, Tests/test_basics.py, Tests/test_hmac.py, Tests/test_init.py, Tests/test_stick.py, Tests/test_util.py: polishing, more tests 2011-04-01 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, setup.py: Version 0.9.4pre1. 2011-04-01 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Lib/pyhsm/yubikey.py, Tests/test_basics.py, Tests/test_buffer.py, Tests/test_configure.py, Tests/test_db.py, Tests/test_hmac.py, Tests/test_yubikey_validate.py: Improve test coverage, centralize input validation #2. 2011-04-01 Fredrik Thulin * examples/yhsm-password-auth.py: Mention PBKDF2. 2011-04-01 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/util.py, Tests/test_aes_ecb.py, Tests/test_basics.py, Tests/test_configure.py: Improve test coverage, centralize input validation. 2011-04-01 Fredrik Thulin * Tests/run.sh: Implement --cover. 2011-03-31 Fredrik Thulin * Tests/test_aead.py, Tests/test_aes_ecb.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_hmac.py: First flags ACL tests. 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/hmac_cmd.py, Tests/test_hmac.py: Make base.hmac_sha1() execute() like all the others. 2011-03-31 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/hmac_cmd.py: pylint suggested fixes. 2011-03-31 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/secrets_cmd.py, Tests/test_aead.py, Tests/test_db.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py: Move YubiKey_Secret to aead_cmd.py. 2011-03-31 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/exception.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/secrets_cmd.py, Lib/pyhsm/validate_cmd.py, Lib/pyhsm/yubikey.py: Fix relative imports. 2011-03-31 Fredrik Thulin * Lib/pyhsm/cmd.py: Slightly better debug and comments. 2011-03-31 Fredrik Thulin * Tests/test_aead.py: Two more trivial tests. 2011-03-31 Fredrik Thulin * Lib/pyhsm/validate_cmd.py: Inherit from YHSM_AEAD_Cmd to reduce code duplication. 2011-03-31 Fredrik Thulin * Lib/pyhsm/validate_cmd.py, Tests/test_db.py, Tests/test_yubikey_validate.py: Sort out use/session ctr confusion in YubiKeyEmu. We have a known issue where the names of the 16 bit counter and the 8 bit since-power-up counter in the YubiKey have diverged. 2011-03-31 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/exception.py, Tests/test_aead.py, Tests/test_yubikey_validate.py: Remove confusion about validating only MACs of AEADs. The confusing comment in YubiHSM_if.h means that if you generate an AEAD with empty input, you can validate it using empty input - not that you could validate MACs of AEADs separately from the rest of the AEAD. 2011-03-31 Fredrik Thulin * Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/stick.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Tests/test_common.py, Tests/test_hmac.py: Increase pylint score. 2011-03-31 Fredrik Thulin * Lib/pyhsm/aes_ecb_cmd.py: Refactor. 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py, yubikey-ksm/yhsm-generate-keys: Change generate_secret into more generic load_random. 2011-03-31 Fredrik Thulin * Lib/pyhsm/buffer_cmd.py, Tests/test_buffer.py, Tests/test_init.py: Mend YHSM_Cmd_Buffer_Random_Load. 2011-03-31 Fredrik Thulin * Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py, Tests/test_basics.py: Implement YSM_TEMP_KEY_LOAD. 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py: Make load_secret() handle string input too. 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/stick.py: Implement set_debug(). 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py, Tests/test_basics.py: Implement YSM_RANDOM_RESEED. 2011-03-31 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py, Tests/test_basics.py, examples/yhsm-sysinfo.py: Add command YSM_NONCE_GET. 2011-03-30 Fredrik Thulin * examples/yhsm-password-auth.py: Show AEAD on --set even without --verbose. 2011-03-30 Fredrik Thulin * Lib/pyhsm/basic_cmd.py, Tests/test_basics.py: Fix off-by-one stealing one byte of random. 2011-03-30 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: documentation correction. 2011-03-30 Fredrik Thulin * examples/yhsm-monitor-exit.py: Honor --debug. 2011-03-30 Fredrik Thulin * Lib/pyhsm/yubikey.py, yubikey-val/yhsm-validate-otp: Add CLI to validate YubiKey OTP's. 2011-03-30 Fredrik Thulin * Lib/pyhsm/yubikey.py, Tests/test_yubikey_validate.py: Remove duplicate code in test suite. 2011-03-30 Fredrik Thulin * yubikey-ksm/yhsm-import-keys: Implement --internal-db to store AEADs in YubiHSM internal database. 2011-03-30 Fredrik Thulin * Lib/pyhsm/aead_cmd.py: Check nonce input. 2011-03-30 Fredrik Thulin * Lib/pyhsm/exception.py: correct YHSM_InputTooLong string 2011-03-30 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Tests/test_aead.py, Tests/test_aes_ecb.py, Tests/test_basics.py, Tests/test_db.py, Tests/test_init.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py: Implement more commands. 2011-03-29 Fredrik Thulin * Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/secrets_cmd.py, Tests/test_aead.py, Tests/test_hmac.py, Tests/test_init.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py, yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-yubikey-ksm: More 0.9.2 stuff. 2011-03-29 Fredrik Thulin * Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/exception.py, Lib/pyhsm/hmac_cmd.py, Lib/pyhsm/validate_cmd.py, Tests/test_aes_ecb.py, Tests/test_hmac.py, Tests/test_init.py: Don't mangle Jakobs TLA. 2011-03-29 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/aead_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/db_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/secrets_cmd.py, Lib/pyhsm/validate_cmd.py, Lib/pyhsm/yubikey.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py, yubikey-ksm/yhsm-yubikey-ksm: Assorted firmware 0.9.2 work. 2011-03-28 Fredrik Thulin * Lib/pyhsm/base.py, Lib/pyhsm/buffer_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/secrets_cmd.py, Tests/test_otp_validate.py, yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys: Update to match firmware 0.9.2. 2011-03-28 Fredrik Thulin * Tests/test_aes_ecb.py: Fix bugs in tests for bad compare. 2011-03-28 Fredrik Thulin * Lib/pyhsm/hmac_cmd.py: Update to firmware 0.9.2. 2011-03-28 Fredrik Thulin * Lib/pyhsm/basic_cmd.py: Fix YHSM_Cmd_Echo, and add length check. 2011-03-28 Fredrik Thulin * Lib/pyhsm/base.py: Work around small delay on YSM_NULL in firmware 0.9.2. 2011-03-28 Fredrik Thulin * Lib/pyhsm/cmd.py: YHSM_NULL command should NOT have byte count prepended. 2011-03-28 Fredrik Thulin * Lib/pyhsm/basic_cmd.py, Lib/pyhsm/defines.py: rename YHSM_RANDOM_GET to YHSM_RANDOM_GENERATE 2011-03-28 Fredrik Thulin * Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/hmac_cmd.py, Tests/test_aes_ecb.py, Tests/test_configure.py, Tests/test_hmac.py: Update to hardware version 0.9.2. 2011-03-28 Fredrik Thulin * Lib/pyhsm/stick.py: Add caller debug_info to read/write. 2011-03-28 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Version 0.9.2pre1 2011-03-28 Fredrik Thulin * Tests/test_configure.py: New firmware requires 8 chars key handles in 'keyload'. 2011-03-28 Fredrik Thulin * README: init 2011-03-28 Fredrik Thulin * yhsm-generate-keys, yhsm-import-keys, yhsm-yubikey-ksm, yubikey-ksm/yhsm-generate-keys, yubikey-ksm/yhsm-import-keys, yubikey-ksm/yhsm-yubikey-ksm: Move to subdirectory. 2011-03-28 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py: more copys of the copyright 2011-03-28 Fredrik Thulin * Lib/pyhsm/__init__.py, setup.py: Version 0.9.0. 2011-03-28 Fredrik Thulin * examples/yhsm-password-auth.py: init 2011-03-28 Fredrik Thulin * Tests/test_aes_ecb.py, Tests/test_basics.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_hmac.py, Tests/test_init.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py: Initialization cleanup. 2011-03-28 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, Lib/pyhsm/defines.py, Lib/pyhsm/exception.py, Lib/pyhsm/hmac_cmd.py, Tests/test_configure.py, Tests/test_hmac.py, Tests/test_init.py: Implement HMAC SHA1 command. 2011-03-25 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/aes_ecb_cmd.py, Lib/pyhsm/base.py, Lib/pyhsm/defines.py, Tests/test_aes_ecb.py, Tests/test_configure.py, Tests/test_init.py: Implement AES ECB encrypt/decrypt/compare. 2011-03-25 Fredrik Thulin * Lib/pyhsm/__init__.py, Lib/pyhsm/base.py, Lib/pyhsm/basic_cmd.py, Lib/pyhsm/cmd.py, Lib/pyhsm/debug_cmd.py, Lib/pyhsm/defines.py, Lib/pyhsm/exception.py, Lib/pyhsm/secrets_cmd.py, Lib/pyhsm/stick.py, Lib/pyhsm/util.py, Lib/pyhsm/validate_cmd.py, Lib/pyhsm/yubikey.py, Lib/serveronstick/__init__.py, Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py, Lib/serveronstick/cmd.py, Lib/serveronstick/debug_cmd.py, Lib/serveronstick/defines.py, Lib/serveronstick/exception.py, Lib/serveronstick/secrets_cmd.py, Lib/serveronstick/stick.py, Lib/serveronstick/util.py, Lib/serveronstick/validate_cmd.py, Lib/serveronstick/yubikey.py, Tests/test_basics.py, Tests/test_common.py, Tests/test_configure.py, Tests/test_init.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py, examples/yhsm-monitor-exit.py, examples/yhsm-sysinfo.py, setup.py, sos-generate-keys, sos-import-keys, sos-yubikey-ksm, yhsm-generate-keys, yhsm-import-keys, yhsm-yubikey-ksm: Massive rename. In-house working name during development was Server-on-Stick, but the product name will be YubiHSM. 2011-03-25 Fredrik Thulin * COPYING: init 2011-03-25 Fredrik Thulin * .gitignore: add tmp 2011-03-25 Fredrik Thulin * examples/yhsm-monitor-exit.py, examples/yhsm-sysinfo.py: Add examples. 2011-03-25 Fredrik Thulin * Tests/test_configure.py, Tests/test_init.py, Tests/test_otp_validate.py, Tests/test_yubikey_validate.py: Add YubiKey OTP validation tests. 2011-03-24 Fredrik Thulin * Tests/test_configure.py: Set up an OTP validation key. 2011-03-22 Fredrik Thulin * Tests/test_common.py, Tests/test_configure.py, Tests/test_init.py, Tests/test_otp_validate.py: More tests. 2011-03-22 Fredrik Thulin * Lib/serveronstick/secrets_cmd.py: Fix off-by-one bug in public_id extraction from generated blob response. 2011-03-22 Fredrik Thulin * Lib/serveronstick/exception.py: Store status for SoS_CommandFailed exception. 2011-03-22 Fredrik Thulin * : commit 9382db56de85abd03092c2bff5554d09b5107c6f Author: Fredrik Thulin Date: Tue Mar 22 17:19:29 2011 +0100 2011-03-22 Fredrik Thulin * Lib/serveronstick/__init__.py, Lib/serveronstick/base.py, Lib/serveronstick/debug_cmd.py, Lib/serveronstick/defines.py: Implement monitor_exit command, for testing. 2011-03-22 Fredrik Thulin * Tests/run.sh, Tests/test_basics.py, Tests/test_common.py, Tests/test_init.py, setup.py: Add first test cases. 2011-03-22 Fredrik Thulin * Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py: Bugfix random number generation after refactoring. 2011-03-20 Fredrik Thulin * Lib/serveronstick/__init__.py: HW version 0.9.0 2011-03-20 Fredrik Thulin * Lib/serveronstick/__init__.py: Works with hardware 0.3.0. 2011-03-10 Simon Josefsson * sos-yubikey-ksm: Drop spurious \n. 2011-03-10 Simon Josefsson * sos-yubikey-ksm: Improve log message to keep in sync with PHP yubikey-ksm. 2011-03-10 Fredrik Thulin * sos-yubikey-ksm: Handle exceptions from SoS, respond 'ERR'. 2011-03-10 Simon Josefsson * sos-yubikey-ksm: Make KSM output be consistent with current KSMs (use vs session counter). 2011-03-09 Fredrik Thulin * : commit 4bf1e7093962802d0034ec00ffee43376dae01f9 Author: Fredrik Thulin Date: Wed Mar 9 19:59:08 2011 +0100 2011-03-09 Simon Josefsson * sos-yubikey-ksm: Make syslog output match yubikey-ksm PHP server. 2011-03-09 Simon Josefsson * sos-yubikey-ksm: Low timestamp is also 16-bit. 2011-03-09 Simon Josefsson * sos-yubikey-ksm: Comply with KSM protocol. 2011-03-09 Fredrik Thulin * Lib/serveronstick/util.py, sos-generate-keys, sos-import-keys, sos-yubikey-ksm: Change blob filename hashing to get at most 256 entrys per directory. 2011-03-09 Fredrik Thulin * sos-generate-keys, sos-import-keys, sos-yubikey-ksm: Change default device to /dev/ttyACM0. 2011-03-09 Fredrik Thulin * Lib/serveronstick/defines.py: comment 2011-03-09 Fredrik Thulin * sos-yubikey-ksm: Don't use hard-coded length for serve_url now that it is an option. 2011-03-09 Fredrik Thulin * sos-yubikey-ksm: Check that from_key is 32-48 bytes of modhex. 2011-03-09 Fredrik Thulin * sos-yubikey-ksm: Log to syslog, and reduce number of global variables. 2011-02-25 Fredrik Thulin * sos-generate-keys, sos-import-keys, sos-yubikey-ksm: init, seemingly working tools 2011-02-25 Fredrik Thulin * Lib/serveronstick/util.py: Add key_handle_to_int. 2011-02-25 Fredrik Thulin * Lib/serveronstick/secrets_cmd.py: Add store/load to file. 2011-02-25 Fredrik Thulin * Lib/serveronstick/validate_cmd.py: Fix command name in exception. 2011-02-25 Fredrik Thulin * Lib/serveronstick/yubikey.py: Add split_id_otp function. 2011-02-24 Fredrik Thulin * Lib/serveronstick/defines.py, Lib/serveronstick/exception.py: more readable errors 2011-02-24 Fredrik Thulin * Lib/serveronstick/__init__.py: Import SoS from base. 2011-02-24 Fredrik Thulin * Lib/serveronstick/exception.py: Print bad command status in hex. 2011-02-24 Fredrik Thulin * Lib/serveronstick/stick.py: Handle open errors better. 2011-02-24 Fredrik Thulin * Lib/serveronstick/yubikey.py: add modhex_encode 2011-02-24 Fredrik Thulin * sos-generate-keys: writes to files 2011-02-24 Fredrik Thulin * sos-generate-keys: init, actually writing blobs to disk remain 2011-02-24 Fredrik Thulin * Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py, Lib/serveronstick/secrets_cmd.py, Lib/serveronstick/util.py, Lib/serveronstick/yubikey.py: More pylint - variable renames. 2011-02-24 Fredrik Thulin * Lib/serveronstick/validate_cmd.py: Implement class for validation response. 2011-02-24 Fredrik Thulin * Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py, Lib/serveronstick/cmd.py, Lib/serveronstick/exception.py, Lib/serveronstick/secrets_cmd.py, Lib/serveronstick/stick.py, Lib/serveronstick/validate_cmd.py, Lib/serveronstick/yubikey.py: pylint run 2011-02-23 Fredrik Thulin * Lib/serveronstick/__init__.py, Lib/serveronstick/exception.py, Lib/serveronstick/secrets_cmd.py: Improve generate_blob. 2011-02-22 Fredrik Thulin * Lib/serveronstick/secrets_cmd.py, Lib/serveronstick/validate_cmd.py: bugfixes 2011-02-22 Fredrik Thulin * Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py, Lib/serveronstick/cmd.py, Lib/serveronstick/defines.py, Lib/serveronstick/exception.py, Lib/serveronstick/secrets_cmd.py, Lib/serveronstick/stick.py, Lib/serveronstick/validate_cmd.py, Lib/serveronstick/yubikey.py: Major refactoring. Can actually validate OTPs now. 2011-02-22 Fredrik Thulin * .gitignore, Lib/serveronstick/base.py, Lib/serveronstick/basic_cmd.py, Lib/serveronstick/cmd.py, Lib/serveronstick/defines.py, Lib/serveronstick/secrets_cmd.py: Implement load/generate secrets etc. 2011-02-22 Fredrik Thulin * Lib/serveronstick/basic_cmd.py, Lib/serveronstick/cmd.py: Refactoring 2011-02-21 Fredrik Thulin * init, first nights work python-pyhsm-1.0.4l/Lib/000077500000000000000000000000001256663164400150725ustar00rootroot00000000000000python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/000077500000000000000000000000001256663164400177245ustar00rootroot00000000000000python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/PKG-INFO000066400000000000000000000003571256663164400210260ustar00rootroot00000000000000Metadata-Version: 1.0 Name: pyhsm Version: 1.0.4l Summary: Python code for talking to a YubiHSM Home-page: https://www.yubico.com/ Author: Fredrik Thulin Author-email: fredrik@yubico.com License: BSD Description: UNKNOWN Platform: UNKNOWN python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/SOURCES.txt000066400000000000000000000136321256663164400216150ustar00rootroot00000000000000COPYING ChangeLog MANIFEST.in NEWS README setup.py Lib/pyhsm/__init__.py Lib/pyhsm/aead_cmd.py Lib/pyhsm/aes_ecb_cmd.py Lib/pyhsm/base.py Lib/pyhsm/basic_cmd.py Lib/pyhsm/buffer_cmd.py Lib/pyhsm/cmd.py Lib/pyhsm/db_cmd.py Lib/pyhsm/debug_cmd.py Lib/pyhsm/defines.py Lib/pyhsm/exception.py Lib/pyhsm/hmac_cmd.py Lib/pyhsm/oath_hotp.py Lib/pyhsm/soft_hsm.py Lib/pyhsm/stick.py Lib/pyhsm/stick_client.py Lib/pyhsm/util.py Lib/pyhsm/validate_cmd.py Lib/pyhsm/version.py Lib/pyhsm/yubikey.py Lib/pyhsm.egg-info/PKG-INFO Lib/pyhsm.egg-info/SOURCES.txt Lib/pyhsm.egg-info/dependency_links.txt Lib/pyhsm.egg-info/requires.txt Lib/pyhsm.egg-info/top_level.txt Tests/run.sh Tests/test_aead.py Tests/test_aes_ecb.py Tests/test_basics.py Tests/test_buffer.py Tests/test_common.py Tests/test_configure.py Tests/test_db.py Tests/test_hmac.py Tests/test_init.py Tests/test_misc.py Tests/test_oath.py Tests/test_otp_validate.py Tests/test_soft_hsm.py Tests/test_stick.py Tests/test_util.py Tests/test_yubikey_validate.py doc/Database_Usage.adoc doc/Intro.adoc doc/README doc/Running_Hardware_Tests.adoc doc/YubiHSM_if.h doc/YubiKey_KSM.adoc doc/db_schema doc/html/api-objects.txt doc/html/class-tree.html doc/html/crarr.png doc/html/deprecated-index.html doc/html/epydoc.css doc/html/epydoc.js doc/html/frames.html doc/html/help.html doc/html/identifier-index.html doc/html/index.html doc/html/module-tree.html doc/html/pyhsm-module.html doc/html/pyhsm.aead_cmd-module.html doc/html/pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate-class.html doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate-class.html doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate-class.html doc/html/pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html doc/html/pyhsm.aead_cmd.YHSM_YubiKeySecret-class.html doc/html/pyhsm.aes_ecb_cmd-module.html doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare-class.html doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt-class.html doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt-class.html doc/html/pyhsm.base-module.html doc/html/pyhsm.base.YHSM-class.html doc/html/pyhsm.basic_cmd-module.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Echo-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Random-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html doc/html/pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html doc/html/pyhsm.basic_cmd.YHSM_NonceResponse-class.html doc/html/pyhsm.buffer_cmd-module.html doc/html/pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html doc/html/pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load-class.html doc/html/pyhsm.cmd-module.html doc/html/pyhsm.cmd.YHSM_Cmd-class.html doc/html/pyhsm.db_cmd-module.html doc/html/pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html doc/html/pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html doc/html/pyhsm.debug_cmd-module.html doc/html/pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit-class.html doc/html/pyhsm.defines-module.html doc/html/pyhsm.exception-module.html doc/html/pyhsm.exception.YHSM_CommandFailed-class.html doc/html/pyhsm.exception.YHSM_Error-class.html doc/html/pyhsm.exception.YHSM_InputTooLong-class.html doc/html/pyhsm.exception.YHSM_InputTooShort-class.html doc/html/pyhsm.exception.YHSM_WrongInputSize-class.html doc/html/pyhsm.exception.YHSM_WrongInputType-class.html doc/html/pyhsm.hmac_cmd-module.html doc/html/pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html doc/html/pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1-class.html doc/html/pyhsm.oath_hotp-module.html doc/html/pyhsm.soft_hsm-module.html doc/html/pyhsm.stick-module.html doc/html/pyhsm.stick.YHSM_Stick-class.html doc/html/pyhsm.stick_client-module.html doc/html/pyhsm.stick_client.YHSM_Stick_Client-class.html doc/html/pyhsm.util-module.html doc/html/pyhsm.validate_cmd-module.html doc/html/pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html doc/html/pyhsm.validate_cmd.YHSM_ValidationResult-class.html doc/html/pyhsm.version-module.html doc/html/pyhsm.version.YHSM_Version-class.html doc/html/pyhsm.yubikey-module.html doc/html/redirect.html doc/html/toc-everything.html doc/html/toc-pyhsm-module.html doc/html/toc-pyhsm.aead_cmd-module.html doc/html/toc-pyhsm.aes_ecb_cmd-module.html doc/html/toc-pyhsm.base-module.html doc/html/toc-pyhsm.basic_cmd-module.html doc/html/toc-pyhsm.buffer_cmd-module.html doc/html/toc-pyhsm.cmd-module.html doc/html/toc-pyhsm.db_cmd-module.html doc/html/toc-pyhsm.debug_cmd-module.html doc/html/toc-pyhsm.defines-module.html doc/html/toc-pyhsm.exception-module.html doc/html/toc-pyhsm.hmac_cmd-module.html doc/html/toc-pyhsm.oath_hotp-module.html doc/html/toc-pyhsm.soft_hsm-module.html doc/html/toc-pyhsm.stick-module.html doc/html/toc-pyhsm.stick_client-module.html doc/html/toc-pyhsm.util-module.html doc/html/toc-pyhsm.validate_cmd-module.html doc/html/toc-pyhsm.version-module.html doc/html/toc-pyhsm.yubikey-module.html doc/html/toc.html examples/yhsm-monitor-exit.py examples/yhsm-password-auth.py examples/yhsm-sysinfo.py maintainer-scripts/README maintainer-scripts/generate_html.sh maintainer-scripts/make-release.sh utils/yhsm-daemon utils/yhsm-daemon.1 utils/yhsm-db-export utils/yhsm-db-export.1 utils/yhsm-db-import utils/yhsm-db-import.1 utils/yhsm-decrypt-aead utils/yhsm-decrypt-aead.1 utils/yhsm-generate-keys utils/yhsm-generate-keys.1 utils/yhsm-keystore-unlock utils/yhsm-keystore-unlock.1 utils/yhsm-linux-add-entropy utils/yhsm-linux-add-entropy.1 yhsm-val/yhsm-init-oath-token yhsm-val/yhsm-init-oath-token.1 yhsm-val/yhsm-validate-otp yhsm-val/yhsm-validate-otp.1 yhsm-val/yhsm-validation-server yhsm-val/yhsm-validation-server.1 yubikey-ksm/yhsm-import-keys yubikey-ksm/yhsm-import-keys.1 yubikey-ksm/yhsm-yubikey-ksm yubikey-ksm/yhsm-yubikey-ksm.1python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/dependency_links.txt000066400000000000000000000000011256663164400237720ustar00rootroot00000000000000 python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/requires.txt000066400000000000000000000001111256663164400223150ustar00rootroot00000000000000pyserial >= 2.3 pycrypto >= 2.1 python-daemon >= 1.5 sqlalchemy >= 0.9.7 python-pyhsm-1.0.4l/Lib/pyhsm.egg-info/top_level.txt000066400000000000000000000000061256663164400224520ustar00rootroot00000000000000pyhsm python-pyhsm-1.0.4l/Lib/pyhsm/000077500000000000000000000000001256663164400162325ustar00rootroot00000000000000python-pyhsm-1.0.4l/Lib/pyhsm/__init__.py000066400000000000000000000043661256663164400203540ustar00rootroot00000000000000# Copyright (c) 2011-2015 Yubico AB # All rights reserved. # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following # conditions are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # """ the pyhsm package Basic usage :: import pyhsm try: hsm = pyhsm.base.YHSM(device="/dev/ttyACM0", debug=False) print "Version : %s" % (hsm.info()) except pyhsm.exception.YHSM_Error, e: print "ERROR: %s" % e See help(pyhsm.base) (L{pyhsm.base.YHSM}) for more information. """ __version__ = '1.0.4l' __copyright__ = 'Yubico AB' __organization__ = 'Yubico' __license__ = 'BSD' __authors__ = ['Fredrik Thulin', 'Dain Nilsson'] __all__ = ["base", "cmd", "defines", "exception", "stick", "util", "version", "yubikey", "soft_hsm", # "aead_cmd", "aes_ecb_cmd", "basic_cmd", "buffer_cmd", "db_cmd", "debug_cmd", "hmac_cmd", "oath_hotp", "validate_cmd", ] from pyhsm.base import YHSM python-pyhsm-1.0.4l/Lib/pyhsm/aead_cmd.py000066400000000000000000000254251256663164400203310ustar00rootroot00000000000000""" implementations of AEAD commands for the YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants 'YHSM_AEAD_File_Marker', # functions # classes 'YHSM_AEAD_Cmd', 'YHSM_Cmd_AEAD_Generate', 'YHSM_Cmd_AEAD_Random_Generate', 'YHSM_Cmd_AEAD_Buffer_Generate', 'YHSM_Cmd_AEAD_Decrypt_Cmp', 'YHSM_GeneratedAEAD', 'YHSM_YubiKeySecret', ] import pyhsm.defines import pyhsm.exception from pyhsm.cmd import YHSM_Cmd YHSM_AEAD_File_Marker = 'YubiHSM AEAD\n' class YHSM_AEAD_Cmd(YHSM_Cmd): """ Class for common non-trivial parse_result for commands returning a YSM_AEAD_GENERATE_RESP. """ nonce = '' key_handle = 0 status = 0 response = None def __repr__(self): if self.executed: return '<%s instance at %s: nonce=%s, key_handle=0x%x, status=%s>' % ( self.__class__.__name__, hex(id(self)), self.nonce.encode('hex'), self.key_handle, pyhsm.defines.status2str(self.status) ) else: return '<%s instance at %s (not executed)>' % ( self.__class__.__name__, hex(id(self)) ) def parse_result(self, data): """ Returns a YHSM_GeneratedAEAD instance, or throws pyhsm.exception.YHSM_CommandFailed. """ # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # YSM_STATUS status; // Status # uint8_t numBytes; // Number of bytes in AEAD block # uint8_t aead[YSM_AEAD_MAX_SIZE]; // AEAD block # } YSM_AEAD_GENERATE_RESP; nonce, \ key_handle, \ self.status, \ num_bytes = struct.unpack_from("< %is I B B" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE), data, 0) pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle) if self.status == pyhsm.defines.YSM_STATUS_OK: pyhsm.util.validate_cmd_response_nonce(nonce, self.nonce) offset = pyhsm.defines.YSM_AEAD_NONCE_SIZE + 6 aead = data[offset:offset + num_bytes] self.response = YHSM_GeneratedAEAD(nonce, key_handle, aead) return self.response else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_Cmd_AEAD_Generate(YHSM_AEAD_Cmd): """ Generate AEAD block from data for a specific key. `data' is either a string, or a YHSM_YubiKeySecret. """ def __init__(self, stick, nonce, key_handle, data): self.nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) self.data = pyhsm.util.input_validate_yubikey_secret(data) # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # uint8_t numBytes; // Number of data bytes # uint8_t data[YSM_DATA_BUF_SIZE]; // Data # } YSM_AEAD_GENERATE_REQ; fmt = "< %is I B %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE, len(self.data)) packed = struct.pack(fmt, nonce, key_handle, len(self.data), self.data) YHSM_AEAD_Cmd.__init__(self, stick, pyhsm.defines.YSM_AEAD_GENERATE, packed) class YHSM_Cmd_AEAD_Random_Generate(YHSM_AEAD_Cmd): """ Generate a random AEAD block using the YubiHSM internal TRNG. To generate a secret for a YubiKey, use public_id as nonce. """ def __init__(self, stick, nonce, key_handle, num_bytes): self.nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) self.num_bytes = pyhsm.util.input_validate_int(num_bytes, 'num_bytes') # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # uint8_t numBytes; // Number of bytes to randomize # } YSM_RANDOM_AEAD_GENERATE_REQ; fmt = "< %is I B" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE) packed = struct.pack(fmt, nonce, key_handle, num_bytes) YHSM_AEAD_Cmd.__init__(self, stick, pyhsm.defines.YSM_RANDOM_AEAD_GENERATE, packed) class YHSM_Cmd_AEAD_Buffer_Generate(YHSM_AEAD_Cmd): """ Generate AEAD block of data buffer for a specific key. After a key has been loaded into the internal data buffer, this command can be used a number of times to get AEADs of the data buffer for different key handles. For example, to encrypt a YubiKey secrets to one or more Yubico KSM's that all have a YubiHSM attached to them. Key handle (and system flags) permission flags required for this operation : YSM_BUFFER_AEAD_GENERATE YSM_BUFFER_LOAD if non-random data has been loaded into the internal buffer """ def __init__(self, stick, nonce, key_handle): self.nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # } YSM_BUFFER_AEAD_GENERATE_REQ; packed = struct.pack("< %is I" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE), \ self.nonce, self.key_handle) YHSM_AEAD_Cmd.__init__(self, stick, pyhsm.defines.YSM_BUFFER_AEAD_GENERATE, packed) class YHSM_Cmd_AEAD_Decrypt_Cmp(YHSM_Cmd): """ Validate an AEAD using the YubiHSM, matching it against some known plain text. Matching is done inside the YubiHSM so the decrypted AEAD is never exposed. """ status = None def __init__(self, stick, nonce, key_handle, aead, cleartext): aead = pyhsm.util.input_validate_aead(aead) expected_ct_len = len(aead) - pyhsm.defines.YSM_AEAD_MAC_SIZE cleartext = pyhsm.util.input_validate_str(cleartext, 'cleartext', exact_len = expected_ct_len) self.nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) data = cleartext + aead if len(data) > pyhsm.defines.YSM_MAX_PKT_SIZE - 10: raise pyhsm.exception.YHSM_InputTooLong( 'cleartext+aead', pyhsm.defines.YSM_MAX_PKT_SIZE - 10, len(data)) # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # uint8_t numBytes; // Number of data bytes (cleartext + aead) # uint8_t data[YSM_MAX_PKT_SIZE - 0x10]; // Data (cleartext + aead). Empty cleartext validates aead only # } YSM_AEAD_DECRYPT_CMP_REQ; fmt = "< %is I B %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE, len(data)) packed = struct.pack(fmt, self.nonce, key_handle, len(data), data) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_AEAD_DECRYPT_CMP, packed) def parse_result(self, data): # typedef struct { # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) # uint32_t keyHandle; // Key handle # YSM_STATUS status; // Status # } YSM_AEAD_DECRYPT_CMP_RESP; fmt = "< %is I B" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE) nonce, key_handle, self.status = struct.unpack(fmt, data) pyhsm.util.validate_cmd_response_str('nonce', nonce, self.nonce) pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle) if self.status == pyhsm.defines.YSM_STATUS_OK: return True if self.status == pyhsm.defines.YSM_MISMATCH: return False else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_GeneratedAEAD(): """ Small class to represent a YHSM_AEAD_GENERATE_RESP. """ def __init__(self, nonce, key_handle, aead): self.nonce = nonce self.key_handle = key_handle self.data = aead def __repr__(self): nonce_str = "None" if self.nonce is not None: nonce_str = self.nonce.encode('hex') return '<%s instance at %s: nonce=%s, key_handle=0x%x, data=%i bytes>' % ( self.__class__.__name__, hex(id(self)), nonce_str, self.key_handle, len(self.data) ) def save(self, filename): """ Store AEAD in a file. @param filename: File to create/overwrite @type filename: string """ aead_f = open(filename, "w") fmt = "< B I %is %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE, len(self.data)) version = 1 packed = struct.pack(fmt, version, self.key_handle, self.nonce, self.data) aead_f.write(YHSM_AEAD_File_Marker + packed) aead_f.close() def load(self, filename): """ Load AEAD from a file. @param filename: File to read AEAD from @type filename: string """ aead_f = open(filename, "r") buf = aead_f.read(1024) if buf.startswith(YHSM_AEAD_File_Marker): if buf[len(YHSM_AEAD_File_Marker)] == chr(1): # version 1 format fmt = "< I %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE) self.key_handle, self.nonce = struct.unpack_from(fmt, buf, len(YHSM_AEAD_File_Marker) + 1) self.data = buf[len(YHSM_AEAD_File_Marker) + 1 + struct.calcsize(fmt):] else: raise pyhsm.exception.YHSM_Error('Unknown AEAD file format') else: # version 0 format, just AEAD data self.data = buf[:pyhsm.defines.YSM_MAX_KEY_SIZE + pyhsm.defines.YSM_BLOCK_SIZE] aead_f.close() class YHSM_YubiKeySecret(): """ Small class to represent a YUBIKEY_SECRETS struct. """ def __init__(self, key, uid): self.key = pyhsm.util.input_validate_str(key, 'key', exact_len = pyhsm.defines.KEY_SIZE) self.uid = pyhsm.util.input_validate_str(uid, 'uid', max_len = pyhsm.defines.UID_SIZE) def pack(self): """ Return key and uid packed for sending in a command to the YubiHSM. """ # # 22-bytes Yubikey secrets block # typedef struct { # uint8_t key[KEY_SIZE]; // AES key # uint8_t uid[UID_SIZE]; // Unique (secret) ID # } YUBIKEY_SECRETS; return self.key + self.uid.ljust(pyhsm.defines.UID_SIZE, chr(0)) python-pyhsm-1.0.4l/Lib/pyhsm/aes_ecb_cmd.py000066400000000000000000000131231256663164400210100ustar00rootroot00000000000000""" implementations of AES ECB block cipher commands to execute on a YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes #'YHSM_Cmd_AES_ECB', 'YHSM_Cmd_AES_ECB_Encrypt', 'YHSM_Cmd_AES_ECB_Decrypt', 'YHSM_Cmd_AES_ECB_Compare', ] import pyhsm.defines import pyhsm.exception from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_AES_ECB(YHSM_Cmd): """ Common code for command classes in this module. """ status = None key_handle = 0x00 def __init__(self, stick, command, payload): YHSM_Cmd.__init__(self, stick, command, payload) def __repr__(self): return '<%s instance at %s: key_handle=0x%x>' % ( self.__class__.__name__, hex(id(self)), self.key_handle ) def parse_result(self, data): # typedef struct { # uint32_t keyHandle; // Key handle # uint8_t ciphertext[YSM_BLOCK_SIZE]; // Ciphertext block # YHSM_STATUS status; // Encryption status # } YHSM_ECB_BLOCK_ENCRYPT_RESP; # OR # typedef struct { # uint32_t keyHandle; // Key handle # uint8_t plaintext[YSM_BLOCK_SIZE]; // Plaintext block # YHSM_STATUS status; // Decryption status # } YHSM_ECB_BLOCK_DECRYPT_RESP; fmt = "< I %is B" % (pyhsm.defines.YSM_BLOCK_SIZE) key_handle, \ result, \ self.status = struct.unpack(fmt, data) # check that returned key_handle matches the one in the request pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle) if self.status == pyhsm.defines.YSM_STATUS_OK: return result else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_Cmd_AES_ECB_Encrypt(YHSM_Cmd_AES_ECB): """ Have the YubiHSM AES ECB encrypt something using the key of a key handle. """ def __init__(self, stick, key_handle, plaintext): pyhsm.util.input_validate_str(plaintext, name='plaintext', max_len = pyhsm.defines.YSM_BLOCK_SIZE) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) # typedef struct { # uint32_t keyHandle; // Key handle # uint8_t plaintext[YHSM_BLOCK_SIZE]; // Plaintext block # } YHSM_ECB_BLOCK_ENCRYPT_REQ; payload = struct.pack('' % ( self.__class__.__name__, hex(id(self)), self.stick.device ) def reset(self, test_sync = True): """ Perform stream resynchronization. @param test_sync: Verify sync with YubiHSM after reset @type test_sync: bool @return: True if successful @rtype: bool """ pyhsm.cmd.reset(self.stick) if test_sync: # Now verify we are in sync data = 'ekoeko' echo = self.echo(data) # XXX analyze 'echo' to see if we are in config mode, and produce a # nice exception if we are. return data == echo else: return True def set_debug(self, new): """ Set debug mode. @param new: new value @type new: bool @return: old value @rtype: bool """ if type(new) is not bool: raise pyhsm.exception.YHSM_WrongInputType( 'new', bool, type(new)) old = self.debug self.debug = new self.stick.set_debug(new) return old def test_comm(self): """ Verify that data we send to and receive from the YubiHSM isn't mangled. In some scenarios, communications with the YubiHSM might be affected by terminal line settings turning CR into LF for example. """ data = ''.join([chr(x) for x in range(256)]) data = data + '0d0a0d0a'.decode('hex') chunk_size = pyhsm.defines.YSM_MAX_PKT_SIZE - 10 # max size of echo count = 0 while data: this = data[:chunk_size] data = data[chunk_size:] res = self.echo(this) for i in xrange(len(this)): if res[i] != this[i]: msg = "Echo test failed at position %i (0x%x != 0x%x)" \ % (count + i, ord(res[i]), ord(this[i])) raise pyhsm.exception.YHSM_Error(msg) count += len(this) # # Basic commands # def echo(self, data): """ Echo test. @type data: string @return: data read from YubiHSM -- should equal `data' @rtype: string @see: L{pyhsm.basic_cmd.YHSM_Cmd_Echo} """ return pyhsm.basic_cmd.YHSM_Cmd_Echo(self.stick, data).execute() def info(self): """ Get firmware version and unique ID from YubiHSM. @return: System information @rtype: L{YHSM_Cmd_System_Info} @see: L{pyhsm.basic_cmd.YHSM_Cmd_System_Info} """ return pyhsm.basic_cmd.YHSM_Cmd_System_Info(self.stick).execute() def random(self, num_bytes): """ Get random bytes from YubiHSM. The random data is DRBG_CTR seeded on each startup by a hardware TRNG, so it should be of very good quality. @type num_bytes: integer @return: Bytes with random data @rtype: string @see: L{pyhsm.basic_cmd.YHSM_Cmd_Random} """ return pyhsm.basic_cmd.YHSM_Cmd_Random(self.stick, num_bytes).execute() def random_reseed(self, seed): """ Provide YubiHSM DRBG_CTR with a new seed. @param seed: new seed -- must be exactly 32 bytes @type seed: string @returns: True on success @rtype: bool @see: L{pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed} """ return pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed(self.stick, seed).execute() def get_nonce(self, increment=1): """ Get current nonce from YubiHSM. Use increment 0 to just fetch the value without incrementing it. @keyword increment: requested increment (optional) @return: nonce value _before_ increment @rtype: L{YHSM_NonceResponse} @see: L{pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get} """ return pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get(self.stick, increment).execute() def load_temp_key(self, nonce, key_handle, aead): """ Load the contents of an AEAD into the phantom key handle 0xffffffff. @param nonce: The nonce used when creating the AEAD @param key_handle: The key handle that can decrypt the AEAD @param aead: AEAD containing the cryptographic key and permission flags @type nonce: string @type key_handle: integer or string @type aead: L{YHSM_GeneratedAEAD} or string @returns: True on success @rtype: bool @see: L{pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load} """ return pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load(self.stick, nonce, key_handle, aead).execute() def unlock(self, password = None, otp = None): """ Unlock the YubiHSM using the master key and/or a YubiKey OTP. If the master key is given during configuration, all key handles will be encrypted (with AES-256) using that passphrase. If one or more admin Yubikey public id's are given during configuration, an OTP from one of these must be provided to the YubiHSM for it to start responding to cryptographic requests. The admin YubiKeys must be present in the internal database for this validation to work. @param password: The 'master key' set during YubiHSM configuration @type password: NoneType or string @param otp: A YubiKey OTP from an 'admin' YubiKey (modhex), to unlock YubiHSM. @type otp: NoneType or string @returns: Only returns (True) on success @rtype: bool @see: L{pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock} @see: L{pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock} """ if otp is not None and not self.version.have_unlock(): # only in 1.0 raise pyhsm.exception.YHSM_Error("Your YubiHSM does not support OTP unlocking.") if password is not None: if self.version.have_key_storage_unlock(): # 0.9.x res = pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock(self.stick, password).execute() elif self.version.have_key_store_decrypt(): # 1.0 res = pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt(self.stick, password).execute() else: raise pyhsm.exception.YHSM_Error("Don't know how to unlock your YubiHSM.") else: res = True if res and otp is not None: (public_id, otp,) = pyhsm.yubikey.split_id_otp(otp) public_id = pyhsm.yubikey.modhex_decode(public_id).decode('hex') otp = pyhsm.yubikey.modhex_decode(otp).decode('hex') return pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock(self.stick, public_id, otp).execute() return res def key_storage_unlock(self, password): """ @deprecated: Too specific (and hard to remember) name. @see: L{unlock} """ return self.unlock(password = password) # # AEAD related commands # def load_secret(self, secret): """ Ask YubiHSM to load a pre-existing YubiKey secret. The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more L{generate_aead} commands to actually retreive the generated secret (in encrypted form). @param secret: YubiKey secret to load @type secret: L{pyhsm.aead_cmd.YHSM_YubiKeySecret} or string @returns: Number of bytes in YubiHSM internal buffer after load @rtype: integer @see: L{pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load} """ if isinstance(secret, pyhsm.aead_cmd.YHSM_YubiKeySecret): secret = secret.pack() return pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load(self.stick, secret).execute() def load_data(self, data, offset): """ Ask YubiHSM to load arbitrary data into it's internal buffer, at any offset. The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more L{generate_aead} commands to actually retreive the generated secret (in encrypted form). Load data to offset 0 to reset the buffer. @param data: arbitrary data to load @type data: string @returns: Number of bytes in YubiHSM internal buffer after load @rtype: integer @see: L{pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load} """ return pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load(self.stick, data, offset).execute() def load_random(self, num_bytes, offset = 0): """ Ask YubiHSM to generate a number of random bytes to any offset of it's internal buffer. The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more L{generate_aead} commands to actually retreive the generated secret (in encrypted form). @param num_bytes: Number of bytes to generate @type num_bytes: integer @returns: Number of bytes in YubiHSM internal buffer after load @rtype: integer @see: L{pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load} """ return pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load(self.stick, num_bytes, offset).execute() def generate_aead_simple(self, nonce, key_handle, data): """ Generate AEAD block from data for a specific key in a single step (without using the YubiHSM internal buffer). @param nonce: The nonce to use when creating the AEAD @param key_handle: The key handle that can encrypt data into an AEAD @param data: Data to put inside the AEAD @type nonce: string @type key_handle: integer or string @type data: string @returns: The generated AEAD on success. @rtype: L{YHSM_GeneratedAEAD} @see: L{pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate} """ return pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate(self.stick, nonce, key_handle, data).execute() def generate_aead_random(self, nonce, key_handle, num_bytes): """ Generate a random AEAD block using the YubiHSM internal DRBG_CTR random generator. To generate a secret for a YubiKey, use public_id as nonce. @param nonce: The nonce to use when creating the AEAD @param key_handle: The key handle that can encrypt the random data into an AEAD @param num_bytes: Number of random data bytes to put inside the AEAD @type nonce: string @type key_handle: integer or string @type num_bytes: integer @returns: The generated AEAD on success. @rtype: L{YHSM_GeneratedAEAD} @see: L{pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate} """ return pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate(self.stick, nonce, key_handle, num_bytes).execute() def generate_aead(self, nonce, key_handle): """ Ask YubiHSM to return an AEAD made of the contents of it's internal buffer (see L{load_secret}, L{load_data} and L{load_random}) encrypted with the specified key_handle. For a YubiKey secret, the nonce should be the public_id. @param nonce: The nonce to use when creating the AEAD @param key_handle: The key handle that can create an AEAD @type nonce: string @type key_handle: integer or string @returns: The generated AEAD on success. @rtype: L{YHSM_GeneratedAEAD} @see: L{pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate} """ return pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate(self.stick, nonce, key_handle).execute() def validate_aead(self, nonce, key_handle, aead, cleartext): """ Validate the contents of an AEAD using the YubiHSM. The matching is done inside the YubiHSM so the contents of the AEAD is never exposed (well, except indirectionally when the cleartext does match). The cleartext should naturally be of the same length as the AEAD minus the size of the MAC (8 bytes). @param nonce: The nonce used when creating the AEAD @param key_handle: The key handle that can decrypt the AEAD @param aead: AEAD containing the cryptographic key and permission flags @param cleartext: The presumed cleartext of the AEAD @type nonce: string @type key_handle: integer or string @type aead: L{YHSM_GeneratedAEAD} or string @type cleartext: string @returns: Whether or not the cleartext matches the contents of the AEAD. @rtype: bool @see: L{pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp} """ return pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp(self.stick, nonce, key_handle, aead, cleartext).execute() def validate_aead_otp(self, public_id, otp, key_handle, aead): """ Ask YubiHSM to validate a YubiKey OTP using an AEAD and a key_handle to decrypt the AEAD. @param public_id: The six bytes public id of the YubiKey @param otp: The one time password (OTP) to validate @param key_handle: The key handle that can decrypt the AEAD @param aead: AEAD containing the cryptographic key and permission flags @type public_id: string @type otp: string @type key_handle: integer or string @type aead: L{YHSM_GeneratedAEAD} or string @returns: validation response @rtype: L{YHSM_ValidationResult} @see: L{pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP} """ if type(public_id) is not str: assert() if type(otp) is not str: assert() if type(key_handle) is not int: assert() if type(aead) is not str: assert() return pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP( \ self.stick, public_id, otp, key_handle, aead).execute() # # Debug/testing commands. # def monitor_exit(self): """ Ask YubiHSM to exit to configuration mode (requires 'debug' mode enabled). @returns: None @rtype: NoneType @see: L{pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit} """ return pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit(self.stick).execute(read_response=False) def get_raw_device(self): """ Get the raw device. Only intended for test code/debugging! @returns: serial device @rtype: Serial """ return self.stick.raw_device() def drain(self): """ Read until there is nothing more to be read. Only intended for test code/debugging! @returns: True on success @rtype: bool """ try: unlock = self.stick.acquire() return self.stick.drain() finally: unlock() # # AES ECB commands # def aes_ecb_encrypt(self, key_handle, plaintext): """ AES ECB encrypt using a key handle. @warning: Please be aware of the known limitations of AES ECB mode before using it! @param key_handle: Key handle to use for AES ECB encryption @param plaintext: Data to encrypt @type key_handle: integer or string @type plaintext: string @returns: Ciphertext @rtype: string @see: L{pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt} """ return pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt( \ self.stick, key_handle, plaintext).execute() def aes_ecb_decrypt(self, key_handle, ciphertext): """ AES ECB decrypt using a key handle. @warning: Please be aware of the known limitations of AES ECB mode before using it! @param key_handle: Key handle to use for AES ECB decryption @param ciphertext: Data to decrypt @type key_handle: integer or string @type ciphertext: string @returns: Plaintext @rtype: string @see: L{pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt} """ return pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt( \ self.stick, key_handle, ciphertext).execute() def aes_ecb_compare(self, key_handle, ciphertext, plaintext): """ AES ECB decrypt and then compare using a key handle. The comparison is done inside the YubiHSM so the plaintext is never exposed (well, except indirectionally when the provided plaintext does match). @warning: Please be aware of the known limitations of AES ECB mode before using it! @param key_handle: Key handle to use for AES ECB decryption @param plaintext: Data to decrypt @type key_handle: integer or string @type plaintext: string @returns: Match result @rtype: bool @see: L{pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare} """ return pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare( \ self.stick, key_handle, ciphertext, plaintext).execute() # # HMAC commands # def hmac_sha1(self, key_handle, data, flags = None, final = True, to_buffer = False): """ Have the YubiHSM generate a HMAC SHA1 of 'data' using a key handle. Use the L{pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.next} to add more input (until 'final' has been set to True). Use the L{pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.get_hash} to get the hash result this far. @param key_handle: Key handle to use when generating HMAC SHA1 @param data: what to calculate the HMAC SHA1 checksum of @keyword flags: bit-flags, overrides 'final' and 'to_buffer' @keyword final: True when there is no more data, False if there is more @keyword to_buffer: Should the final result be stored in the YubiHSM internal buffer or not @type key_handle: integer or string @type data: string @type flags: None or integer @returns: HMAC-SHA1 instance @rtype: L{YHSM_Cmd_HMAC_SHA1_Write} @see: L{pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write} """ return pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write( \ self.stick, key_handle, data, flags = flags, final = final, to_buffer = to_buffer).execute() # # Internal YubiKey database related commands # def db_store_yubikey(self, public_id, key_handle, aead, nonce = None): """ Ask YubiHSM to store data about a YubiKey in the internal database (not buffer). The input is an AEAD with the secrets of a YubiKey, perhaps previously created using L{load_secret}. @param public_id: The six bytes public id of the YubiKey @param key_handle: Key handle that can decrypt the YubiKey AEAD @param aead: AEAD of an L{pyhsm.aead_cmd.YHSM_YubiKeySecret} @param nonce: Nonce, if different from public_id. @type public_id: string @type key_handle: integer or string @type aead: L{YHSM_GeneratedAEAD} or string @type nonce: None or string @return: True on success @rtype: bool @see: L{pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store} """ if nonce is not None and not self.version.have_YSM_DB_YUBIKEY_AEAD_STORE2(): # introduced in 1.0.4 raise pyhsm.exception.YHSM_Error("YubiHSM does not support nonce != public_id.") return pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store( \ self.stick, public_id, key_handle, aead, nonce = nonce).execute() def db_validate_yubikey_otp(self, public_id, otp): """ Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database. @param public_id: The six bytes public id of the YubiKey @param otp: The OTP from a YubiKey in binary form (16 bytes) @type public_id: string @type otp: string @returns: validation response @rtype: L{YHSM_ValidationResult} @see: L{pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP} """ return pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP( \ self.stick, public_id, otp).execute() python-pyhsm-1.0.4l/Lib/pyhsm/basic_cmd.py000066400000000000000000000346321256663164400205200ustar00rootroot00000000000000""" implementations of basic commands to execute on a YubiHSM """ # Copyright (c) 2011-2014 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_Echo', 'YHSM_Cmd_System_Info', 'YHSM_Cmd_Random', 'YHSM_Cmd_Random_Reseed', 'YHSM_Cmd_Temp_Key_Load', 'YHSM_Cmd_Nonce_Get', 'YHSM_Cmd_Key_Storage_Unlock', 'YHSM_Cmd_Key_Store_Decrypt', 'YHSM_Cmd_HSM_Unlock', 'YHSM_NonceResponse', ] import pyhsm.defines import pyhsm.exception import pyhsm.aead_cmd from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_Echo(YHSM_Cmd): """ Send something to the stick, and expect to get it echoed back. """ def __init__(self, stick, payload=''): payload = pyhsm.util.input_validate_str(payload, 'payload', max_len = pyhsm.defines.YSM_MAX_PKT_SIZE - 1) # typedef struct { # uint8_t numBytes; // Number of bytes in data field # uint8_t data[YSM_MAX_PKT_SIZE - 1]; // Data # } YSM_ECHO_REQ; packed = chr(len(payload)) + payload YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_ECHO, packed) def parse_result(self, data): # typedef struct { # uint8_t numBytes; // Number of bytes in data field # uint8_t data[YSM_MAX_PKT_SIZE - 1]; // Data # } YSM_ECHO_RESP; return data[1:] class YHSM_Cmd_System_Info(YHSM_Cmd): """ Request system information from the YubiHSM. @ivar version_major: Major firmware version @ivar version_minor: Minor firmware version @ivar version_build: Firmware build version @ivar protocol_ver: Communication protocol version @ivar system_uid: Unique identifier for YubiHSM @type system_uid: string """ version_major = 0 version_minor = 0 version_build = 0 protocol_ver = 0 system_uid = None def __init__(self, stick): YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_SYSTEM_INFO_QUERY) def __repr__(self): if self.executed: return '<%s instance at %s: ver=%s, proto=%s, sysid=0x%s>' % ( self.__class__.__name__, hex(id(self)), (self.version_major, self.version_minor, self.version_build), self.protocol_ver, self.system_uid.encode('hex') ) else: return '<%s instance at %s (not executed)>' % ( self.__class__.__name__, hex(id(self)) ) def parse_result(self, data): # #define SYSTEM_ID_SIZE 12 # typedef struct { # uint8_t version_major; // Major version # # uint8_t version_minor; // Minor version # # uint8_t version_build; // Build version # # uint8_t protocolVersion; // Protocol version # # uint8_t systemUid[SYSTEM_ID_SIZE]; // System unique identifier # } YHSM_SYSTEM_INFO_RESP; self.version_major, \ self.version_minor, \ self.version_build, \ self.protocol_ver, \ self.system_uid = struct.unpack('BBBB12s', data) return self class YHSM_Cmd_Random(YHSM_Cmd): """ Ask stick to generate a number of random bytes. """ def __init__(self, stick, num_bytes): self.num_bytes = pyhsm.util.input_validate_int(num_bytes, 'num_bytes', pyhsm.defines.YSM_MAX_PKT_SIZE - 1) # typedef struct { # uint8_t numBytes; // Number of bytes to generate # } YSM_RANDOM_GENERATE_REQ; packed = chr(self.num_bytes) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_RANDOM_GENERATE, packed) def parse_result(self, data): # typedef struct { # uint8_t numBytes; // Number of bytes generated # uint8_t rnd[YSM_MAX_PKT_SIZE - 1]; // Random data # } YHSM_RANDOM_GENERATE_RESP; num_bytes = pyhsm.util.validate_cmd_response_int('num_bytes', ord(data[0]), self.num_bytes) return data[1:1 + num_bytes] class YHSM_Cmd_Random_Reseed(YHSM_Cmd): """ Provide YubiHSM DRBG_CTR with a new seed. """ status = None def __init__(self, stick, seed): seed = pyhsm.util.input_validate_str(seed, 'seed', exact_len = pyhsm.defines.YSM_CTR_DRBG_SEED_SIZE) # #define YSM_CTR_DRBG_SEED_SIZE 32 # typedef struct { # uint8_t seed[YSM_CTR_DRBG_SEED_SIZE]; // New seed # } YSM_RANDOM_RESEED_REQ; fmt = "%is" % (pyhsm.defines.YSM_CTR_DRBG_SEED_SIZE) packed = struct.pack(fmt, seed) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_RANDOM_RESEED, packed) def parse_result(self, data): # typedef struct { # YSM_STATUS status; // Status # } YSM_RANDOM_RESEED_RESP; fmt = "B" self.status, = struct.unpack(fmt, data) if self.status == pyhsm.defines.YSM_STATUS_OK: return True else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_Cmd_Temp_Key_Load(YHSM_Cmd): """ Load an AEAD into the phantom key handle 0xffffffff. The `aead' is either a YHSM_GeneratedAEAD, or a string. """ status = None def __init__(self, stick, nonce, key_handle, aead): self.nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) flags_size = struct.calcsize("' % ( self.__class__.__name__, hex(id(self)), self.nonce.encode('hex'), self.pu_count, self.volatile ) python-pyhsm-1.0.4l/Lib/pyhsm/buffer_cmd.py000066400000000000000000000072661256663164400207130ustar00rootroot00000000000000""" implementations of internal buffer commands for YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_Buffer_Load', 'YHSM_Cmd_Buffer_Random_Load', ] import pyhsm.defines import pyhsm.exception from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_Buffer_Load(YHSM_Cmd): """ Ask YubiHSM to load some data into it's internal buffer. @ivar data_len: Number of bytes (to be) loaded @ivar offset: Offset in internal buffer where data will be/was loaded @type data_len: integer @type offset: integer """ data_len = 0 offest = 0 def __init__(self, stick, data, offset = 0): data = pyhsm.util.input_validate_str(data, 'data', max_len = pyhsm.defines.YSM_DATA_BUF_SIZE) self.data_len = len(data) self.offset = pyhsm.util.input_validate_int(offset, 'offset', pyhsm.defines.YSM_DATA_BUF_SIZE - 1) # typedef struct { # uint8_t offs; // Offset in buffer. Zero flushes/resets buffer first # uint8_t numBytes; // Number of bytes to load # uint8_t data[YSM_DATA_BUF_SIZE]; // Data to load # } YSM_BUFFER_LOAD_REQ; fmt = "B B %is" % self.data_len packed = struct.pack(fmt, self.offset, self.data_len, data) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_BUFFER_LOAD, packed) def parse_result(self, data): """ Parse result of L{pyhsm.defines.YSM_BUFFER_LOAD} command. @return: Number of bytes now in the YubiHSM internal buffer. @rtype: integer @raise pyhsm.exception.YHSM_Error: Unexpected number of bytes were loaded """ # typedef struct { # uint8_t numBytes; // Number of bytes in buffer now # } YSM_BUFFER_LOAD_RESP; count = ord(data[0]) if self.offset == 0: # if offset was 0, the buffer was reset and # we can verify the length returned if count != self.data_len: raise pyhsm.exception.YHSM_Error("Incorrect number of bytes in buffer (got %i, expected %i)" \ % (self.data_len, count)) return count class YHSM_Cmd_Buffer_Random_Load(YHSM_Cmd): """ Ask YubiHSM to generate a secret for a specific public_id Generated secret is stored in YubiHSM's internal memory and is retreived using YHSM_Cmd_Blob_Generate. """ def __init__(self, stick, num_bytes, offset = 0): self.offset = offset self.num_bytes = num_bytes # typedef struct { # uint8_t offs; // Offset in buffer. Zero flushes/resets buffer first # uint8_t numBytes; // Number of bytes to randomize # } YSM_BUFFER_RANDOM_LOAD_REQ; fmt = "B B" packed = struct.pack(fmt, self.offset, self.num_bytes) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_BUFFER_RANDOM_LOAD, packed) def parse_result(self, data): """ Return True if the public_id in the response matches the one in the request. """ # typedef struct { # uint8_t numBytes; // Number of bytes in buffer now # } YSM_BUFFER_LOAD_RESP; count = ord(data[0]) if self.offset == 0: # if offset was 0, the buffer was reset and # we can verify the length returned if count != self.num_bytes: raise pyhsm.exception.YHSM_Error("Incorrect number of bytes in buffer (got %i, expected %i)" \ % (self.num_bytes, count)) return count python-pyhsm-1.0.4l/Lib/pyhsm/cmd.py000066400000000000000000000131571256663164400173560ustar00rootroot00000000000000""" module for accessing a YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import re import struct __all__ = [ # constants # functions 'reset', # classes 'YHSM_Cmd', ] import pyhsm.exception import pyhsm.defines class YHSM_Cmd(): """ Base class for YubiHSM commands. """ response_status = None executed = False def __init__(self, stick, command, payload=''): """ The base class for all YSM_ commands. @param stick: Reference to a YubiHSM @param command: The YSM_xxx command defined in pyhsm.defines. @param payload: a packed C struct, represented as a Python string @type stick: L{pyhsm.stick.YHSM_Stick} @type command: integer @type payload: string """ self.stick = stick self.command = command self.payload = payload return None def execute(self, read_response=True): """ Write command to HSM and read response. @param read_response: Whether to expect a response or not. @type read_response: bool """ # // Up- and downlink packet # typedef struct { # uint8_t bcnt; // Number of bytes (cmd + payload) # uint8_t cmd; // YSM_xxx command # uint8_t payload[YSM_MAX_PKT_SIZE]; // Payload # } YSM_PKT; if self.command != pyhsm.defines.YSM_NULL: # YSM_NULL is the exception to the rule - it should NOT be prefixed with YSM_PKT.bcnt cmd_buf = struct.pack('BB', len(self.payload) + 1, self.command) else: cmd_buf = chr(self.command) cmd_buf += self.payload debug_info = None unlock = self.stick.acquire() try: if self.stick.debug: debug_info = "%s (payload %i/0x%x)" % (pyhsm.defines.cmd2str(self.command), \ len(self.payload), len(self.payload)) self.stick.write(cmd_buf, debug_info) if not read_response: return None return self._read_response() finally: unlock() def _read_response(self): """ After writing a command, read response. @returns: Result of parse_data() @raises pyhsm.exception.YHSM_Error: On failure to read a response to the command we sent in a timely fashion. """ # // Up- and downlink packet # typedef struct { # uint8_t bcnt; // Number of bytes (cmd + payload) # uint8_t cmd; // YSM_xxx command # uint8_t payload[YSM_MAX_PKT_SIZE]; // Payload # } YSM_PKT; # read YSM_PKT.bcnt and YSM_PKT.cmd res = self.stick.read(2, 'response length + response status') if len(res) != 2: self._handle_invalid_read_response(res, 2) response_len, response_status = struct.unpack('BB', res) response_len -= 1 # the status byte has been read already debug_info = None if response_status & pyhsm.defines.YSM_RESPONSE: debug_info = "%s response (%i/0x%x bytes)" \ % (pyhsm.defines.cmd2str(response_status - pyhsm.defines.YSM_RESPONSE), \ response_len, response_len) # read YSM_PKT.payload res = self.stick.read(response_len, debug_info) if res: if response_status == self.command | pyhsm.defines.YSM_RESPONSE: self.executed = True self.response_status = response_status return self.parse_result(res) else: reset(self.stick) raise pyhsm.exception.YHSM_Error('YubiHSM responded to wrong command') else: raise pyhsm.exception.YHSM_Error('YubiHSM did not respond') def _handle_invalid_read_response(self, res, expected_len): """ This function is called when we do not get the expected frame header in response to a command. Probable reason is that we are not talking to a YubiHSM in HSM mode (might be a modem, or a YubiHSM in configuration mode). Throws a hopefully helpful exception. """ if not res: reset(self.stick) raise pyhsm.exception.YHSM_Error('YubiHSM did not respond to command %s' \ % (pyhsm.defines.cmd2str(self.command)) ) # try to check if it is a YubiHSM in configuration mode self.stick.write('\r\r\r', '(mode test)') res2 = self.stick.read(50) # expect a timeout lines = res2.split('\n') for this in lines: if re.match('^(NO_CFG|WSAPI|HSM).*> .*', this): raise pyhsm.exception.YHSM_Error('YubiHSM is in configuration mode') raise pyhsm.exception.YHSM_Error('Unknown response from serial device %s : "%s"' \ % (self.stick.device, res.encode('hex'))) def parse_result(self, data): """ This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM. """ return data def reset(stick): """ Send a bunch of zero-bytes to the YubiHSM, and flush the input buffer. """ nulls = (pyhsm.defines.YSM_MAX_PKT_SIZE - 1) * '\x00' res = YHSM_Cmd(stick, pyhsm.defines.YSM_NULL, payload = nulls).execute(read_response = False) unlock = stick.acquire() try: stick.flush() finally: unlock() return res == 0 python-pyhsm-1.0.4l/Lib/pyhsm/db_cmd.py000066400000000000000000000135021256663164400200150ustar00rootroot00000000000000""" implementations of internal DB commands for YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_DB_YubiKey_Store', 'YHSM_Cmd_DB_Validate_OTP', ] import pyhsm.defines import pyhsm.exception import pyhsm.aead_cmd import pyhsm.validate_cmd from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_DB_YubiKey_Store(YHSM_Cmd): """ Ask YubiHSM to store data about a YubiKey in the internal database (not buffer). The input is an AEAD, perhaps previously created using generate_aead(). If the nonce for the AEAD is not the same as the public_id, specify it with the nonce keyword argument. This requires a YubiHSM >= 1.0.4. """ status = None def __init__(self, stick, public_id, key_handle, aead, nonce = None): self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) self.public_id = pyhsm.util.input_validate_nonce(public_id, pad = True) aead = pyhsm.util.input_validate_aead(aead, expected_len = pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE) if nonce is None: # typedef struct { # uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) # uint32_t keyHandle; // Key handle # uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block # } YSM_DB_YUBIKEY_AEAD_STORE_REQ; fmt = "< %is I %is" % (pyhsm.defines.YSM_PUBLIC_ID_SIZE, \ pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE) packed = struct.pack(fmt, self.public_id, self.key_handle, aead) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE, packed) else: nonce = pyhsm.util.input_validate_nonce(nonce) # typedef struct { # uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id # uint32_t keyHandle; // Key handle # uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block # uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce # } YSM_DB_YUBIKEY_AEAD_STORE2_REQ; fmt = "< %is I %is %is" % (pyhsm.defines.YSM_PUBLIC_ID_SIZE, \ pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE, \ pyhsm.defines.YSM_AEAD_NONCE_SIZE) packed = struct.pack(fmt, self.public_id, self.key_handle, aead, nonce) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE2, packed) def parse_result(self, data): """ Return True if the AEAD was stored sucessfully. """ # typedef struct { # uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) # uint32_t keyHandle; // Key handle # YSM_STATUS status; // Validation status # } YSM_DB_YUBIKEY_AEAD_STORE_RESP; public_id, \ key_handle, \ self.status = struct.unpack("< %is I B" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE), data) pyhsm.util.validate_cmd_response_str('public_id', public_id, self.public_id) pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle) if self.status == pyhsm.defines.YSM_STATUS_OK: return True else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_Cmd_DB_Validate_OTP(YHSM_Cmd): """ Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database. """ response = None status = None def __init__(self, stick, public_id, otp): self.public_id = pyhsm.util.input_validate_nonce(public_id, pad = True) self.otp = pyhsm.util.input_validate_str(otp, 'otp', exact_len = pyhsm.defines.YSM_OTP_SIZE) # typedef struct { # uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id # uint8_t otp[YSM_OTP_SIZE]; // OTP # } YSM_DB_OTP_VALIDATE_REQ; fmt = "%is %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE, pyhsm.defines.YSM_OTP_SIZE) packed = struct.pack(fmt, self.public_id, self.otp) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_DB_OTP_VALIDATE, packed) def __repr__(self): if self.executed: return '<%s instance at %s: public_id=%s, status=0x%x>' % ( self.__class__.__name__, hex(id(self)), self.public_id.encode('hex'), self.status ) else: return '<%s instance at %s (not executed)>' % ( self.__class__.__name__, hex(id(self)) ) def parse_result(self, data): # typedef struct { # uint8_t public_id[YSM_PUBLIC_ID_SIZE]; // Public id # uint16_t use_ctr; // Use counter # uint8_t session_ctr; // Session counter # uint8_t tstph; // Timestamp (high part) # uint16_t tstpl; // Timestamp (low part) # YHSM_STATUS status; // Validation status # } YHSM_AEAD_OTP_DECODED_RESP; fmt = "%is H B B H B" % (pyhsm.defines.YSM_PUBLIC_ID_SIZE) public_id, \ use_ctr, \ session_ctr, \ ts_high, \ ts_low, \ self.status = struct.unpack(fmt, data) pyhsm.util.validate_cmd_response_str('public_id', public_id, self.public_id) if self.status == pyhsm.defines.YSM_STATUS_OK: self.response = pyhsm.validate_cmd.YHSM_ValidationResult( \ public_id, use_ctr, session_ctr, ts_high, ts_low) return self.response else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) python-pyhsm-1.0.4l/Lib/pyhsm/debug_cmd.py000066400000000000000000000017511256663164400205210ustar00rootroot00000000000000""" implementations of debugging commands to execute on a YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_Monitor_Exit', ] import pyhsm.defines from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_Monitor_Exit(YHSM_Cmd): """ Send magics to YubiHSM in debug mode, and get it to exit to configuration mode again. """ def __init__(self, stick, payload=''): #define YHSM_MONITOR_EXIT 0x7f // Exit to monitor (no response sent) #define YHSM_MONITOR_EXIT_MAGIC 0xbaadbeef # typedef struct { # uint32_t magic; // Magic number for trigger # uint32_t magicInv; // 1st complement of magic # } YHSM_MONITOR_EXIT_REQ; packed = struct.pack('' % ( self.__class__.__name__, hex(id(self)), self.reason ) class YHSM_WrongInputSize(YHSM_Error): """ Exception raised for errors in the size of an argument to some function. """ def __init__(self, name, expected, size): reason = "Bad size of argument '%s', expected %i got %i" % (name, expected, size) YHSM_Error.__init__(self, reason) class YHSM_InputTooShort(YHSM_Error): """ Exception raised for too short input to some function. """ def __init__(self, name, expected, size): reason = "Argument '%s' too short, expected min %i got %i" % (name, expected, size) YHSM_Error.__init__(self, reason) class YHSM_InputTooLong(YHSM_Error): """ Exception raised for too long input to some function. """ def __init__(self, name, expected, size): reason = "Argument '%s' too long, expected max %i got %i" % (name, expected, size) YHSM_Error.__init__(self, reason) class YHSM_WrongInputType(YHSM_Error): """ Exception raised for errors in the type of an argument to some function. """ def __init__(self, name, expected, name_type): reason = "Bad type of argument '%s', expected %s got %s" % (name, expected, name_type) YHSM_Error.__init__(self, reason) class YHSM_CommandFailed(YHSM_Error): """ Exception raised when a command sent to the YubiHSM returned an error. """ def __init__(self, name, status): self.status = status self.status_str = pyhsm.defines.status2str(status) reason = "Command %s failed: %s" % (name, self.status_str) YHSM_Error.__init__(self, reason) python-pyhsm-1.0.4l/Lib/pyhsm/hmac_cmd.py000066400000000000000000000115241256663164400203420ustar00rootroot00000000000000""" implementations of HMAC commands to execute on a YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_HMAC_SHA1_Write', 'YHSM_GeneratedHMACSHA1', ] import pyhsm.exception import pyhsm.defines from pyhsm.cmd import YHSM_Cmd class YHSM_Cmd_HMAC_SHA1_Write(YHSM_Cmd): """ Calculate HMAC SHA1 using a key_handle in the YubiHSM. Set final=False to not get a hash generated for the initial request. Set to_buffer=True to get the SHA1 stored into the internal buffer, for use in some other cryptographic operation. """ status = None result = None def __init__(self, stick, key_handle, data, flags = None, final = True, to_buffer = False): data = pyhsm.util.input_validate_str(data, 'data', max_len = pyhsm.defines.YSM_MAX_PKT_SIZE - 6) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) if flags != None: flags = pyhsm.util.input_validate_int(flags, 'flags', max_value=0xff) else: flags = pyhsm.defines.YSM_HMAC_SHA1_RESET if final: flags |= pyhsm.defines.YSM_HMAC_SHA1_FINAL if to_buffer: flags |= pyhsm.defines.YSM_HMAC_SHA1_TO_BUFFER self.final = final self.flags = flags packed = _raw_pack(self.key_handle, self.flags, data) YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_HMAC_SHA1_GENERATE, packed) def next(self, data, final = False, to_buffer = False): """ Add more input to the HMAC SHA1. """ if final: self.flags = pyhsm.defines.YSM_HMAC_SHA1_FINAL else: self.flags = 0x0 if to_buffer: self.flags |= pyhsm.defines.YSM_HMAC_SHA1_TO_BUFFER self.payload = _raw_pack(self.key_handle, self.flags, data) self.final = final return self def get_hash(self): """ Get the HMAC-SHA1 that has been calculated this far. """ if not self.executed: raise pyhsm.exception.YHSM_Error("HMAC-SHA1 hash not available, before execute().") return self.result.hash_result def __repr__(self): if self.executed: return '<%s instance at %s: key_handle=0x%x, flags=0x%x, executed=%s>' % ( self.__class__.__name__, hex(id(self)), self.key_handle, self.flags, self.executed, ) def parse_result(self, data): # typedef struct { # uint32_t keyHandle; // Key handle # YHSM_STATUS status; // Status # uint8_t numBytes; // Number of bytes in hash output # uint8_t hash[YSM_SHA1_HASH_SIZE]; // Hash output (if applicable) # } YHSM_HMAC_SHA1_GENERATE_RESP; key_handle, \ self.status, \ num_bytes = struct.unpack_from('' % ( self.__class__.__name__, hex(id(self)), self.key_handle, self.hash_result[:4].encode('hex'), self.final, ) python-pyhsm-1.0.4l/Lib/pyhsm/oath_hotp.py000066400000000000000000000036411256663164400205750ustar00rootroot00000000000000""" helper functions to work with OATH HOTP (RFC4226) OTP's and YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import string import struct __all__ = [ # constants # functions 'validate_oath_hotp_with_aead', # classes ] import pyhsm.exception import pyhsm.aead_cmd def search_for_oath_code(hsm, key_handle, nonce, aead, counter, user_code, look_ahead=1): """ Try to validate an OATH HOTP OTP generated by a token whose secret key is available to the YubiHSM through the AEAD. The parameter `aead' is either a string, or an instance of YHSM_GeneratedAEAD. Returns next counter value on successful auth, and None otherwise. """ key_handle = pyhsm.util.input_validate_key_handle(key_handle) nonce = pyhsm.util.input_validate_nonce(nonce, pad = False) aead = pyhsm.util.input_validate_aead(aead) counter = pyhsm.util.input_validate_int(counter, 'counter') user_code = pyhsm.util.input_validate_int(user_code, 'user_code') hsm.load_temp_key(nonce, key_handle, aead) # User might have produced codes never sent to us, so we support trying look_ahead # codes to see if we find the user's current code. for j in xrange(look_ahead): this_counter = counter + j secret = struct.pack("> Q", this_counter) hmac_result = hsm.hmac_sha1(pyhsm.defines.YSM_TEMP_KEY_HANDLE, secret).get_hash() this_code = truncate(hmac_result) if this_code == user_code: return this_counter + 1 return None def truncate(hmac_result, length=6): """ Perform the truncating. """ assert(len(hmac_result) == 20) offset = ord(hmac_result[19]) & 0xf bin_code = (ord(hmac_result[offset]) & 0x7f) << 24 \ | (ord(hmac_result[offset+1]) & 0xff) << 16 \ | (ord(hmac_result[offset+2]) & 0xff) << 8 \ | (ord(hmac_result[offset+3]) & 0xff) return bin_code % (10 ** length) python-pyhsm-1.0.4l/Lib/pyhsm/soft_hsm.py000066400000000000000000000066261256663164400204400ustar00rootroot00000000000000""" functions for implementing parts of the HSMs machinery in software """ # Copyright (c) 2012 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions 'aesCCM', # classes ] import pyhsm.exception from Crypto.Cipher import AES def _xor_block(a, b): """ XOR two blocks of equal length. """ return ''.join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)]) class _ctr_counter(): """ An object implementation of the struct aesCtr. """ def __init__(self, key_handle, nonce, flags = None, value = 0): self.flags = pyhsm.defines.YSM_CCM_CTR_SIZE - 1 if flags is None else flags self.key_handle = key_handle self.nonce = nonce self.value = value def next(self): """ Return next counter value, encoded into YSM_BLOCK_SIZE. """ self.value += 1 return self.pack() def pack(self): fmt = b'< B I %is BBB 2s' % (pyhsm.defines.YSM_AEAD_NONCE_SIZE) val = struct.pack('> H', self.value) return struct.pack(fmt, self.flags, self.key_handle, self.nonce, 0, 0, 0, # rfu val ) class _cbc_mac(): def __init__(self, key, key_handle, nonce, data_len): """ Initialize CBC-MAC like the YubiHSM does. """ flags = (((pyhsm.defines.YSM_AEAD_MAC_SIZE - 2) / 2) << 3) | (pyhsm.defines.YSM_CCM_CTR_SIZE - 1) t = _ctr_counter(key_handle, nonce, flags = flags, value = data_len) t_mac = t.pack() self.mac_aes = AES.new(key, AES.MODE_ECB) self.mac = self.mac_aes.encrypt(t_mac) def update(self, block): block = block.ljust(pyhsm.defines.YSM_BLOCK_SIZE, chr(0x0)) t1 = _xor_block(self.mac, block) t2 = self.mac_aes.encrypt(t1) self.mac = t2 def finalize(self, block): """ The final step of CBC-MAC encrypts before xor. """ t1 = self.mac_aes.encrypt(block) t2 = _xor_block(self.mac, t1) self.mac = t2 def get(self): return self.mac[: pyhsm.defines.YSM_AEAD_MAC_SIZE] def _split_data(data, pos): a = data[:pos] b = data[pos:] return (a, b,) def aesCCM(key, key_handle, nonce, data, decrypt=False): """ Function implementing YubiHSM AEAD encrypt/decrypt in software. """ if decrypt: (data, saved_mac) = _split_data(data, len(data) - pyhsm.defines.YSM_AEAD_MAC_SIZE) nonce = pyhsm.util.input_validate_nonce(nonce, pad = True) mac = _cbc_mac(key, key_handle, nonce, len(data)) counter = _ctr_counter(key_handle, nonce, value = 0) ctr_aes = AES.new(key, AES.MODE_CTR, counter = counter.next) out = [] while data: (thisblock, data) = _split_data(data, pyhsm.defines.YSM_BLOCK_SIZE) # encrypt/decrypt and CBC MAC if decrypt: aes_out = ctr_aes.decrypt(thisblock) mac.update(aes_out) else: mac.update(thisblock) aes_out = ctr_aes.encrypt(thisblock) out.append(aes_out) # Finalize MAC counter.value = 0 mac.finalize(counter.pack()) if decrypt: if mac.get() != saved_mac: raise pyhsm.exception.YHSM_Error('AEAD integrity check failed') else: out.append(mac.get()) return ''.join(out) python-pyhsm-1.0.4l/Lib/pyhsm/stick.py000066400000000000000000000103041256663164400177170ustar00rootroot00000000000000""" module for actually talking to the YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. __all__ = [ # constants # functions 'read', 'write', 'flush', # classes 'YHSM_Stick', ] import sys import serial import pyhsm.util import pyhsm.exception class YHSM_Stick(): """ The current YHSM is a USB device using serial communication. This class exposes the basic functions read, write and flush (input). """ def __init__(self, device, timeout=1, debug=False): """ Open YHSM device. """ self.debug = debug self.device = device self.num_read_bytes = 0 self.num_write_bytes = 0 self.ser = None # to not bomb in destructor on open fail self.ser = serial.serial_for_url(device) self.ser.baudrate = 115200 self.ser.timeout = timeout if self.debug: sys.stderr.write("%s: OPEN %s\n" %( self.__class__.__name__, self.ser )) return None def acquire(self): """ Do nothing """ return self.acquire def write(self, data, debug_info=None): """ Write data to YHSM device. """ self.num_write_bytes += len(data) if self.debug: if not debug_info: debug_info = str(len(data)) sys.stderr.write("%s: WRITE %s:\n%s\n" %( self.__class__.__name__, debug_info, pyhsm.util.hexdump(data) )) return self.ser.write(data) def read(self, num_bytes, debug_info=None): """ Read a number of bytes from YubiHSM device. """ if self.debug: if not debug_info: debug_info = str(num_bytes) sys.stderr.write("%s: READING %s\n" %( self.__class__.__name__, debug_info )) res = self.ser.read(num_bytes) if self.debug: sys.stderr.write("%s: READ %i:\n%s\n" %( self.__class__.__name__, len(res), pyhsm.util.hexdump(res) )) self.num_read_bytes += len(res) return res def flush(self): """ Flush input buffers. """ if self.debug: sys.stderr.write("%s: FLUSH INPUT (%i bytes waiting)\n" %( self.__class__.__name__, self.ser.inWaiting() )) self.ser.flushInput() def drain(self): """ Drain input. """ if self.debug: sys.stderr.write("%s: DRAIN INPUT (%i bytes waiting)\n" %( self.__class__.__name__, self.ser.inWaiting() )) old_timeout = self.ser.timeout self.ser.timeout = 0.1 data = self.ser.read(1) while len(data): if self.debug: sys.stderr.write("%s: DRAINED 0x%x (%c)\n" %(self.__class__.__name__, ord(data[0]), data[0])) data = self.ser.read(1) self.ser.timeout = old_timeout return True def raw_device(self): """ Get raw serial device. Only intended for test code/debugging! """ return self.ser def set_debug(self, new): """ Set debug mode (boolean). Returns old setting. """ if type(new) is not bool: raise pyhsm.exception.YHSM_WrongInputType( 'new', bool, type(new)) old = self.debug self.debug = new return old def __repr__(self): return '<%s instance at %s: %s - r:%i w:%i>' % ( self.__class__.__name__, hex(id(self)), self.device, self.num_read_bytes, self.num_write_bytes ) def __del__(self): """ Close device when YHSM instance is destroyed. """ if self.debug: sys.stderr.write("%s: CLOSE %s\n" %( self.__class__.__name__, self.ser )) if self.ser: self.ser.close() python-pyhsm-1.0.4l/Lib/pyhsm/stick_client.py000066400000000000000000000113731256663164400212640ustar00rootroot00000000000000""" module for talking to the YubiHSM over a socket. """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. __all__ = [ # constants # functions # classes 'YHSM_Stick_Client', ] import sys import re import socket import json import pyhsm.util import pyhsm.exception CMD_WRITE = 0 CMD_READ = 1 CMD_FLUSH = 2 CMD_DRAIN = 3 CMD_LOCK = 4 CMD_UNLOCK = 5 DEVICE_PATTERN = re.compile(r'yhsm://(?P[^:]+)(:(?P\d+))?/?') DEFAULT_PORT = 5348 def pack_data(data): if isinstance(data, basestring): return data.encode('base64') return data def unpack_data(data): if isinstance(data, basestring): return data.decode('base64') elif isinstance(data, dict) and 'error' in data: return pyhsm.exception.YHSM_Error(data['error']) return data def read_sock(sf): line = sf.readline() return unpack_data(json.loads(line)) def write_sock(sf, cmd, *args): json.dump([cmd] + map(pack_data, args), sf) sf.write("\n") sf.flush() class YHSM_Stick_Client(): """ The current YHSM is a USB device using serial communication. This class exposes the basic functions read, write and flush (input). """ def __init__(self, device, timeout=1, debug=False): """ Open YHSM device. """ self.debug = debug self.device = device self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) match = DEVICE_PATTERN.match(device) host = match.group('host') port = match.group('port') or DEFAULT_PORT self.socket.connect((host, int(port))) self.socket_file = self.socket.makefile('wb') self.num_read_bytes = 0 self.num_write_bytes = 0 if self.debug: sys.stderr.write("%s: OPEN %s\n" % ( self.__class__.__name__, self.socket )) return None def acquire(self): write_sock(self.socket_file, CMD_LOCK) return self.release def release(self): write_sock(self.socket_file, CMD_UNLOCK) def write(self, data, debug_info=None): """ Write data to YHSM device. """ self.num_write_bytes += len(data) if self.debug: if not debug_info: debug_info = str(len(data)) sys.stderr.write("%s: WRITE %s:\n%s\n" % ( self.__class__.__name__, debug_info, pyhsm.util.hexdump(data) )) write_sock(self.socket_file, CMD_WRITE, data) return read_sock(self.socket_file) def read(self, num_bytes, debug_info=None): """ Read a number of bytes from YubiHSM device. """ if self.debug: if not debug_info: debug_info = str(num_bytes) sys.stderr.write("%s: READING %s\n" % ( self.__class__.__name__, debug_info )) write_sock(self.socket_file, CMD_READ, num_bytes) res = read_sock(self.socket_file) if isinstance(res, Exception): raise res if self.debug: sys.stderr.write("%s: READ %i:\n%s\n" % ( self.__class__.__name__, len(res), pyhsm.util.hexdump(res) )) self.num_read_bytes += len(res) return res def flush(self): """ Flush input buffers. """ write_sock(self.socket_file, CMD_FLUSH) return read_sock(self.socket_file) def drain(self): """ Drain input. """ write_sock(self.socket_file, CMD_DRAIN) return read_sock(self.socket_file) def raw_device(self): """ Get the socket address. Only intended for test code/debugging! """ return self.socket def set_debug(self, new): """ Set debug mode (boolean). Returns old setting. """ if type(new) is not bool: raise pyhsm.exception.YHSM_WrongInputType( 'new', bool, type(new)) old = self.debug self.debug = new return old def __repr__(self): return '<%s instance at %s: %s - r:%i w:%i>' % ( self.__class__.__name__, hex(id(self)), self.device, self.num_read_bytes, self.num_write_bytes ) def __del__(self): """ Close device when YHSM instance is destroyed. """ if self.debug: sys.stderr.write("%s: CLOSE %s\n" % ( self.__class__.__name__, self.device )) try: self.socket_file.close() self.socket.close() except Exception: pass python-pyhsm-1.0.4l/Lib/pyhsm/util.py000066400000000000000000000131551256663164400175660ustar00rootroot00000000000000""" collection of utility functions """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions 'hexdump', 'group', 'key_handle_to_int', # classes ] import pyhsm.exception def hexdump(src, length=8): """ Produce a string hexdump of src, for debug output.""" if not src: return str(src) src = input_validate_str(src, 'src') offset = 0 result = '' for this in group(src, length): hex_s = ' '.join(["%02x" % ord(x) for x in this]) result += "%04X %s\n" % (offset, hex_s) offset += length return result def group(data, num): """ Split data into chunks of num chars each """ return [data[i:i+num] for i in xrange(0, len(data), num)] def key_handle_to_int(this): """ Turn "123" into 123 and "KSM1" into 827151179 (0x314d534b, 'K' = 0x4b, S = '0x53', M = 0x4d). YHSM is little endian, so this makes the bytes KSM1 appear in the most human readable form in packet traces. """ try: num = int(this) return num except ValueError: if this[:2] == "0x": return int(this, 16) if (len(this) == 4): num = struct.unpack(' max_len: raise pyhsm.exception.YHSM_InputTooLong(name, max_len, len(string)) if exact_len != None and len(string) != exact_len: raise pyhsm.exception.YHSM_WrongInputSize(name, exact_len, len(string)) return string def input_validate_int(value, name, max_value=None): """ Input validation for integers. """ if type(value) is not int: raise pyhsm.exception.YHSM_WrongInputType(name, int, type(value)) if max_value != None and value > max_value: raise pyhsm.exception.YHSM_WrongInputSize(name, max_value, value) return value def input_validate_nonce(nonce, name='nonce', pad = False): """ Input validation for nonces. """ if type(nonce) is not str: raise pyhsm.exception.YHSM_WrongInputType( \ name, str, type(nonce)) if len(nonce) > pyhsm.defines.YSM_AEAD_NONCE_SIZE: raise pyhsm.exception.YHSM_InputTooLong( name, pyhsm.defines.YSM_AEAD_NONCE_SIZE, len(nonce)) if pad: return nonce.ljust(pyhsm.defines.YSM_AEAD_NONCE_SIZE, chr(0x0)) else: return nonce def input_validate_key_handle(key_handle, name='key_handle'): """ Input validation for key_handles. """ if type(key_handle) is not int: try: return key_handle_to_int(key_handle) except pyhsm.exception.YHSM_Error: raise pyhsm.exception.YHSM_WrongInputType(name, int, type(key_handle)) return key_handle def input_validate_yubikey_secret(data, name='data'): """ Input validation for YHSM_YubiKeySecret or string. """ if isinstance(data, pyhsm.aead_cmd.YHSM_YubiKeySecret): data = data.pack() return input_validate_str(data, name) def input_validate_aead(aead, name='aead', expected_len=None, max_aead_len = pyhsm.defines.YSM_AEAD_MAX_SIZE): """ Input validation for YHSM_GeneratedAEAD or string. """ if isinstance(aead, pyhsm.aead_cmd.YHSM_GeneratedAEAD): aead = aead.data if expected_len != None: return input_validate_str(aead, name, exact_len = expected_len) else: return input_validate_str(aead, name, max_len=max_aead_len) def validate_cmd_response_int(name, got, expected): """ Check that some value returned in the response to a command matches what we put in the request (the command). """ if got != expected: raise(pyhsm.exception.YHSM_Error("Bad %s in response (got %i, expected %i)" \ % (name, got, expected))) return got def validate_cmd_response_hex(name, got, expected): """ Check that some value returned in the response to a command matches what we put in the request (the command). """ if got != expected: raise(pyhsm.exception.YHSM_Error("Bad %s in response (got 0x%x, expected 0x%x)" \ % (name, got, expected))) return got def validate_cmd_response_str(name, got, expected, hex_encode=True): """ Check that some value returned in the response to a command matches what we put in the request (the command). """ if got != expected: if hex_encode: got_s = got.encode('hex') exp_s = expected.encode('hex') else: got_s = got exp_s = expected raise(pyhsm.exception.YHSM_Error("Bad %s in response (got %s, expected %s)" \ % (name, got_s, exp_s))) return got def validate_cmd_response_nonce(got, used): """ Check that the returned nonce matches nonce used in request. A request nonce of 000000000000 means the HSM should generate a nonce internally though, so if 'used' is all zeros we actually check that 'got' does NOT match 'used'. """ if used == '000000000000'.decode('hex'): if got == used: raise(pyhsm.exception.YHSM_Error("Bad nonce in response (got %s, expected HSM generated nonce)" \ % (got.encode('hex')))) return got return validate_cmd_response_str('nonce', got, used) python-pyhsm-1.0.4l/Lib/pyhsm/validate_cmd.py000066400000000000000000000106071256663164400212240ustar00rootroot00000000000000""" implementations of validation commands for YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct __all__ = [ # constants # functions # classes 'YHSM_Cmd_AEAD_Validate_OTP', 'YHSM_ValidationResult', ] import pyhsm.defines import pyhsm.exception from pyhsm.aead_cmd import YHSM_AEAD_Cmd class YHSM_Cmd_AEAD_Validate_OTP(YHSM_AEAD_Cmd): """ Request the YubiHSM to validate an OTP using an externally stored AEAD. """ response = None status = None def __init__(self, stick, public_id, otp, key_handle, aead): self.public_id = pyhsm.util.input_validate_nonce(public_id, pad = True) self.otp = pyhsm.util.input_validate_str(otp, 'otp', exact_len = pyhsm.defines.YSM_OTP_SIZE) self.key_handle = pyhsm.util.input_validate_key_handle(key_handle) aead = pyhsm.util.input_validate_aead(aead, expected_len = pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE) # typedef struct { # uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) # uint32_t keyHandle; // Key handle # uint8_t otp[YSM_OTP_SIZE]; // OTP # uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block # } YSM_AEAD_YUBIKEY_OTP_DECODE_REQ; fmt = "< %is I %is %is" % (pyhsm.defines.YSM_AEAD_NONCE_SIZE, \ pyhsm.defines.YSM_OTP_SIZE, \ pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE) packed = struct.pack(fmt, self.public_id, \ self.key_handle, \ self.otp, \ aead) YHSM_AEAD_Cmd.__init__(self, stick, pyhsm.defines.YSM_AEAD_YUBIKEY_OTP_DECODE, packed) def parse_result(self, data): # typedef struct { # uint8_t public_id[YSM_PUBLIC_ID_SIZE]; // Public id # uint32_t keyHandle; // Key handle # uint16_t use_ctr; // Use counter # uint8_t session_ctr; // Session counter # uint8_t tstph; // Timestamp (high part) # uint16_t tstpl; // Timestamp (low part) # YHSM_STATUS status; // Validation status # } YHSM_AEAD_OTP_DECODED_RESP; fmt = "< %is I H B B H B" % (pyhsm.defines.YSM_PUBLIC_ID_SIZE) public_id, \ key_handle, \ use_ctr, \ session_ctr, \ ts_high, \ ts_low, \ self.status = struct.unpack(fmt, data) pyhsm.util.validate_cmd_response_str('public_id', public_id, self.public_id) pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle) if self.status == pyhsm.defines.YSM_STATUS_OK: self.response = YHSM_ValidationResult(self.public_id, use_ctr, session_ctr, ts_high, ts_low) return self.response else: raise pyhsm.exception.YHSM_CommandFailed(pyhsm.defines.cmd2str(self.command), self.status) class YHSM_ValidationResult(): """ The result of a Validate operation. Contains the counters and timestamps decrypted from the OTP. @ivar public_id: The six bytes public ID of the YubiKey that produced the OTP @ivar use_ctr: The 16-bit power-on non-volatile counter of the YubiKey @ivar session_ctr: The 8-bit volatile session counter of the YubiKey @ivar ts_high: The high 8 bits of the 24-bit 8 hz timer since power-on of the YubiKey @ivar ts_low: The low 16 bits of the 24-bit 8 hz timer since power-on of the YubiKey @type public_id: string @type use_ctr: integer @type session_ctr: integer @type ts_high: integer @type ts_low: integer """ public_id = use_ctr = session_ctr = ts_high = ts_low = None def __init__(self, public_id, use_ctr, session_ctr, ts_high, ts_low): self.public_id = public_id self.use_ctr = use_ctr self.session_ctr = session_ctr self.ts_high = ts_high self.ts_low = ts_low def __repr__(self): return '<%s instance at %s: public_id=%s, use_ctr=%i, session_ctr=%i, ts=%i/%i>' % ( self.__class__.__name__, hex(id(self)), self.public_id.encode('hex'), self.use_ctr, self.session_ctr, self.ts_high, self.ts_low ) python-pyhsm-1.0.4l/Lib/pyhsm/version.py000066400000000000000000000041441256663164400202740ustar00rootroot00000000000000""" module for keeping track of different capabilities in different versions """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. __all__ = [ # constants # functions # classes 'YHSM_Version' ] class YHSM_Version(): """ Keeps the YubiHSM's version number and can tell what capabilities it has. @ivar sysinfo: Sysinfo when YubiHSM was initialized. @type sysinfo: L{YHSM_Cmd_System_Info} """ def __init__(self, sysinfo): """ @param sysinfo: YubiHSM sysinfo. @type sysinfo: L{YHSM_Cmd_System_Info} """ self.sysinfo = sysinfo self.ver = (sysinfo.version_major, sysinfo.version_minor, sysinfo.version_build,) def have_key_storage_unlock(self): """ YSM_KEY_STORAGE_UNLOCK was removed in 1.0. The basic concept of a passphrase to unlock the YubiHSM is now provided with the more secure YSM_KEY_STORE_DECRYPT. """ return self.ver < (1, 0,) def have_key_store_decrypt(self): """ YSM_KEY_STORE_DECRYPT was introduced in 1.0, replacing YSM_KEY_STORAGE_UNLOCK. """ return self.ver >= (1, 0, 0) def have_unlock(self): """ YSM_HSM_UNLOCK, featuring YubiKey OTP unlocking of operations, was introduced in 1.0. """ return self.ver >= (1, 0, 0) def have_keycommit(self): """ YubiHSM have the 'keycommit' command in configuration mode. 'keycommit' was introduced in 1.0. """ return self.ver >= (1, 0, 0) def have_keydisable(self): """ YubiHSM have the 'keydis'(able) command in configuration mode. 'keydis' was introduced in 1.0. """ return self.ver >= (1, 0, 1) def have_YSM_BUFFER_LOAD(self): """ This is a key handle permission flag that was introduced in 0.9.9. """ return self.ver >= (0, 9, 9,) def have_YSM_DB_YUBIKEY_AEAD_STORE2(self): """ The 2nd generation store command (with public id != nonce) was introduced in 1.0.4. """ return self.ver >= (1, 0, 4) python-pyhsm-1.0.4l/Lib/pyhsm/yubikey.py000066400000000000000000000074461256663164400203000ustar00rootroot00000000000000""" helper functions to work with Yubikeys and YubiHSM """ # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import string __all__ = [ # constants # functions 'validate_otp', 'validate_yubikey_with_aead', 'modhex_encode', 'modhex_decode', 'split_id_otp', # classes ] import pyhsm.exception import pyhsm.aead_cmd def validate_otp(hsm, from_key): """ Try to validate an OTP from a YubiKey using the internal database on the YubiHSM. `from_key' is the modhex encoded string emitted when you press the button on your YubiKey. Will only return on succesfull validation. All failures will result in an L{pyhsm.exception.YHSM_CommandFailed}. @param hsm: The YHSM instance @param from_key: The OTP from a YubiKey (in modhex) @type hsm: L{pyhsm.YHSM} @type from_key: string @returns: validation response, if successful @rtype: L{YHSM_ValidationResult} @see: L{pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.parse_result} """ public_id, otp = split_id_otp(from_key) return hsm.db_validate_yubikey_otp(modhex_decode(public_id).decode('hex'), modhex_decode(otp).decode('hex') ) def validate_yubikey_with_aead(hsm, from_key, aead, key_handle): """ Try to validate an OTP from a YubiKey using the AEAD that can decrypt this YubiKey's internal secret, using the key_handle for the AEAD. `from_key' is the modhex encoded string emitted when you press the button on your YubiKey. Will only return on succesfull validation. All failures will result in an L{pyhsm.exception.YHSM_CommandFailed}. @param hsm: The YHSM instance @param from_key: The OTP from a YubiKey (in modhex) @param aead: AEAD containing the cryptographic key and permission flags @param key_handle: The key handle that can decrypt the AEAD @type hsm: L{pyhsm.YHSM} @type from_key: string @type aead: L{YHSM_GeneratedAEAD} or string @type key_handle: integer or string @returns: validation response @rtype: L{YHSM_ValidationResult} @see: L{pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP.parse_result} """ from_key = pyhsm.util.input_validate_str(from_key, 'from_key', max_len = 48) nonce = aead.nonce aead = pyhsm.util.input_validate_aead(aead) key_handle = pyhsm.util.input_validate_key_handle(key_handle) public_id, otp = split_id_otp(from_key) public_id = modhex_decode(public_id) otp = modhex_decode(otp) if not nonce: nonce = public_id.decode('hex') return hsm.validate_aead_otp(nonce, otp.decode('hex'), key_handle, aead) def modhex_decode(data): """ Convert a modhex string to ordinary hex. @param data: Modhex input @type data: string @returns: Hex @rtype: string """ t_map = string.maketrans("cbdefghijklnrtuv", "0123456789abcdef") return data.translate(t_map) def modhex_encode(data): """ Convert an ordinary hex string to modhex. @param data: Hex input @type data: string @returns: Modhex @rtype: string """ t_map = string.maketrans("0123456789abcdef", "cbdefghijklnrtuv") return data.translate(t_map) def split_id_otp(from_key): """ Separate public id from OTP given a YubiKey OTP as input. @param from_key: The OTP from a YubiKey (in modhex) @type from_key: string @returns: public_id and OTP @rtype: tuple of string """ if len(from_key) > 32: public_id, otp = from_key[:-32], from_key[-32:] elif len(from_key) == 32: public_id = '' otp = from_key else: raise pyhsm.exception.YHSM_Error("Bad from_key length %i < 32 : %s" \ % (len(from_key), from_key)) return public_id, otp python-pyhsm-1.0.4l/MANIFEST.in000066400000000000000000000003401256663164400161170ustar00rootroot00000000000000include COPYING include ChangeLog include NEWS include doc/* include doc/html/* include utils/* include yhsm-val/* include yubikey-ksm/* include Tests/* exclude Tests/*.pyc include examples/*.py include maintainer-scripts/* python-pyhsm-1.0.4l/NEWS000066400000000000000000000066251256663164400150740ustar00rootroot00000000000000Python-pyhsm NEWS -- History of user-visible changes. -*- outline -*- * Version 1.0.4l (released 2015-08-24) ** Documentation is now in asciidoc format. ** yhsm-yubikey-ksm: Fix bug when the same public ID occured for multiple keyhandles. * Version 1.0.4k (released 2014-09-18) ** yhsm-db-import, yhsm-db-export: Fix syntax error. * Version 1.0.4j (released 2014-09-16) ** yhsm-yubikey-ksm: Fix syntax error. * Version 1.0.4i (released 2014-09-16) ** yhsm-yubikey-ksm: Add --daemon. ** yhsm-yubikey-ksm: Add --db-url to specify SQL database path to AEAD store. ** yhsm-db-import, yhsm-db-export: New tools to do database import/export. ** Documentation cleanup. * Version 1.0.4h (released 2014-01-09) ** yhsm-daemon: Use JSON messages instead of Python pickling. (as suggested by Rogdham) * Version 1.0.4g (released 2013-05-06) ** yhsm-daemon: Support listening to non-loopback interfaces. ** yhsm-daemon: Forward exceptions to the client. ** yhsm-daemon: Handle device unavailable, and attempt to recover. * Version 1.0.4f (released 2013-04-12) ** Fix failing test. ** Support URLs in device field, for more info see: http://pyserial.sourceforge.net/pyserial_api.html#serial.serial_for_url ** Added yhsm-daemon. * Version 1.0.4e (released 2013-04-06) ** yhsm-decrypt-aead: For yubikey-csv output, fix prefix field. Before the prefix was set to the AEAD nonce which is only correct for old style AEAD files. Now it uses the AEAD filename for the prefix field. ** yhsm-decrypt-aead: Improve diagnostic messages. Errors and warnings are now printed to standard error. The count of number of failed and processsed AEADs should now be accurate. * Version 1.0.4d (released 2013-03-18) ** Fix so that yhsm-yubikey-ksm can work with the older format. * Version 1.0.4c (released 2013-03-18) ** When doing OTP verification, if a nonce is written to the AEAD file use that for decryption, not public id. ** yhsm-import-keys: add --random-nonce for using hsm generated nonce. ** yhsm-generate-keys: add --random-nonce for using hsm generated nonce. * Version 1.0.4b (released 2013-02-11) ** yhsm-import-keys: Support soft HSM AEAD generation. ** yhsm-import-keys: Ignore lines starting with #. ** yhsm-import-keys: Block all-zero (ccc...c) keys. ** yhsm-decrypt-keys: Support generating AEADs. ** yhsm-decrypt-keys: Ignores non-modhex files in AEAD directory trees. ** yhsm-generate-keys: Bugfix that caused AEAD generation to fail. ** yhsm-generate-keys: Bugfix that caused wrong nonce to be used. ** yhsm-generate-keys: Prevent generating all-zero (ccc...c) keys. ** Added this NEWS file, based on debian/changelog in the Debian package. * Version 1.0.4a (released 2012-06-26) ** Enable IPv6 --addr for network servers. ** Verifies communication with YubiHSM on initialization. * Version 1.0.4 (released 2012-06-21) ** Match firmware 1.0.4. Firmware adds flag YSM_USER_NONCE to address security problem for some usages where AEADs could be decrypted by an attacker capable of generating new AEADs. ** New file format for stored AEADs (code loading AEADs is backwards ** compatible), including key handle and nonce. ** AES CCM implementation compatible with YubiHSM in software, for ** transparency and to enable willfull decryption of AEADs. ** Tools to generate YubiKey secrets into AEADs as well as decrypt ** them to enable provisioning YubiKeys with the secrets. * Version 1.0.3c (released 2012-01-05) ** First public release. python-pyhsm-1.0.4l/PKG-INFO000066400000000000000000000003571256663164400154660ustar00rootroot00000000000000Metadata-Version: 1.0 Name: pyhsm Version: 1.0.4l Summary: Python code for talking to a YubiHSM Home-page: https://www.yubico.com/ Author: Fredrik Thulin Author-email: fredrik@yubico.com License: BSD Description: UNKNOWN Platform: UNKNOWN python-pyhsm-1.0.4l/README000066400000000000000000000057171256663164400152560ustar00rootroot00000000000000PyHSM - Python YubiHSM Project ============================== Introduction ------------ PyHSM is a Python package to talk to a YubiHSM. The YubiHSM is Yubico's take on the Hardware Security Module (HSM), designed for protecting secrets on authentication servers, including cryptographic keys and passwords, at unmatched simplicity and low cost. License ------- The project is licensed under the BSD license, see the file COPYING for exact wording. Description ----------- PyHSM aims to be a reference implementation implementing all the functions available in the YubiHSM. The base version number of pyhsm will match the supported hardware version of the YubiHSM: PyHSM releases 0.9.8, 0.9.8a, 0.9.8b are all intended to be used with hardware version 0.9.8. PyHSM also includes the regression test suite for the YubiHSM. In general, see the files in `utils/`, `examples/`, `yhsm-val/` and `yubikey-ksm/` to get an idea of how to use this code. In addition to the YubiHSM communication library, PyHSM also contains some applications utilizing the YubiHSM: * yhsm-val: a simple validation server supporting validation of YubiKey OTPs, OATH codes and password hashes. * yubikey-ksm: ykval YubiKey OTP decryption backend using the YubiHSM. Some smaller scripts are in the `utils/` directory: * yhsm-linux-add-entropy: Feed Linux kernel with random entropy from the TRNG on the YubiHSM. * yhsm-keystore-unlock: Unlock the key storage in the YubiHSM with your HSM password. Use with incorrect password to lock it again. * yhsm-daemon: Talk to the YubiHSM directly over TCP. And some more in `examples/`: * yhsm-sysinfo.py: Print basic system information about the connected YubiHSM. * yhsm-monitor-exit.py: Get a YubiHSM *in debug mode* to enter configuration mode again, without having to press the little button while inserting it into the USB port. * yhsm-password-auth.py: Example of how to turn passwords (or hashes of passwords if you like PBKDF2) into AEADs that can be used to verify the password later on. Installation ------------ PyHSM is known to work with Python 2.6 and 2.7, and is primarily tested using Debian/Ubuntu, but is of course meant to work on as many platforms as possible. NOTE: If you want to use any of the daemons (yhsm-validation-server, yhsm-yubikey-ksm) you will want to use Python 2.7 or later. `SocketServer.py` lacks critical timeout handling in Python 2.6. The http://pyserial.sourceforge.net[pyserial] package is needed. Debian: apt-get install python-serial For database support http://www.sqlalchemy.org[SQLAlchemy] is needed. Debian: apt-get install python-sqlalchemy To run the test suite, you need http://www.pycrypto.org[pycrypto]. Debian: apt-get install python-crypto Please note that the pycrypto version has to be 2.1 or higher -- it is known that RHEL6 has a lower version. PyHSM is installed like other Python packages: $ cd pyhsm-$ver $ python setup.py install This requires the Debian/Ubuntu 'python-setuptools' package. python-pyhsm-1.0.4l/Tests/000077500000000000000000000000001256663164400154665ustar00rootroot00000000000000python-pyhsm-1.0.4l/Tests/run.sh000077500000000000000000000005301256663164400166270ustar00rootroot00000000000000#!/bin/sh # # Run all tests. # mydir=`dirname $0` set -e : ${PYTHON:="python"} if [ "x$1" = "x--cover" ]; then cd $mydir/../Lib exclude="" if [ "x$YHSM_ZAP" = "x" ]; then exclude="--exclude=test_configure" fi nosetests --with-coverage $exclude . ../Tests/ else PYTHONPATH="Lib" $PYTHON $mydir/../setup.py test $* fipython-pyhsm-1.0.4l/Tests/test_aead.py000066400000000000000000000171311256663164400177740ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestAEAD(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) self.nonce = "4d4d4d4d4d4d".decode('hex') self.key = "A" * 16 self.uid = '\x4d\x01\x4d\x02\x4d\x03' self.secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(self.key, self.uid) def test_aead_cmd_class(self): """ Test YHSM_AEAD_Cmd class. """ this = pyhsm.aead_cmd.YHSM_AEAD_Cmd(None, None) # test repr method self.assertEquals(str, type(str(this))) this.executed = True self.assertEquals(str, type(str(this))) def test_generate_aead_simple(self): """ Test generate_aead_simple without specifying nonce. """ # Enabled flags 00000002 = YSM_AEAD_GENERATE # HSM> < keyload - Load key data now using flags 00000002. Press ESC to quit # 00000002 - stored ok key_handle = 2 nonce = '' aead = self.hsm.generate_aead_simple(nonce, key_handle, self.secret) self.assertNotEqual(aead.nonce, nonce) self.assertEqual(aead.key_handle, key_handle) # test repr method self.assertEquals(str, type(str(aead))) def test_generate_aead_simple_with_nonce(self): """ Test generate_aead_simple with specified nonce. """ # Enabled flags 20000002 = YSM_AEAD_GENERATE,YSM_USER_NONCE # HSM> < keyload - Load key data now using flags 20000002. Press ESC to quit # 20000002 - stored ok key_handle = 0x20000002 aead = self.hsm.generate_aead_simple(self.nonce, key_handle, self.secret) self.assertEqual(aead.nonce, self.nonce) self.assertEqual(aead.key_handle, key_handle) def test_generate_aead_simple_nonce_blocked(self): """ Test generate_aead_simple with unpermitted nonce. """ # Enabled flags 00000002 = YSM_AEAD_GENERATE # HSM> < keyload - Load key data now using flags 00000002. Press ESC to quit # 00000002 - stored ok if self.hsm.version.ver < (1,0,4): raise unittest.SkipTest("Requires 1.0.4 or greater") key_handle = 2 try: res = self.hsm.generate_aead_simple(self.nonce, key_handle, self.secret) self.fail("Expected YSM_FUNCTION_DISABLED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_FUNCTION_DISABLED) def test_generate_aead_simple_validates(self): """ Test validate_aead of generate_aead_simple result. """ # To successfully decrypt the AEAD we have to generate and decrypt # with the same key handle. Key handle 0x2000 has all flags set. kh_gen = 0x2000 kh_val = 0x2000 aead = self.hsm.generate_aead_simple('', kh_gen, self.secret) # test that the YubiHSM validates the generated AEAD # and confirms it contains our secret self.assertTrue(self.hsm.validate_aead(aead.nonce, kh_val, \ aead, cleartext = self.secret.pack())) def test_generate_aead_simple_hsm_nonce_validates(self): """ Test validate_aead of generate_aead_simple result with HSM nonce. """ # To successfully decrypt the AEAD we have to generate and decrypt # with the same key handle. Key handle 0x2000 has all flags set. kh_gen = 0x2000 kh_val = 0x2000 nonce = '000000000000'.decode('hex') aead = self.hsm.generate_aead_simple(nonce, kh_gen, self.secret) # test that the YubiHSM validates the generated AEAD # and confirms it contains our secret self.assertTrue(self.hsm.validate_aead(aead.nonce, kh_val, \ aead, cleartext = self.secret.pack())) def test_generate_aead_random_nonce_blocked(self): """ Test generate_aead_random with unpermitted nonce. """ # Enabled flags 00000008 = YSM_RANDOM_AEAD_GENERATE # 00000004 - stored ok if self.hsm.version.ver < (1,0,4): raise unittest.SkipTest("Requires 1.0.4 or greater") key_handle = 4 try: res = self.hsm.generate_aead_random(self.nonce, key_handle, 22) self.fail("Expected YSM_FUNCTION_DISABLED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_FUNCTION_DISABLED) def test_generate_aead_random_nonce_permitted(self): """ Test generate_aead_random with nonce. """ # Enabled flags 20000008 = YSM_RANDOM_AEAD_GENERATE,YSM_USER_NONCE # HSM> < keyload - Load key data now using flags 20000008. Press ESC to quit # 20000008 - stored ok key_handle = 0x20000008 num_bytes = 22 aead = self.hsm.generate_aead_random(self.nonce, key_handle, num_bytes) self.assertEqual(self.nonce, aead.nonce) self.assertEqual(num_bytes + pyhsm.defines.YSM_AEAD_MAC_SIZE, len(aead.data)) def test_generate_aead_random_without_nonce(self): """ Test decrypt_cmp of generate_aead_random result. """ # Enabled flags 00000008 = YSM_RANDOM_AEAD_GENERATE # 00000004 - stored ok key_handle = 4 nonce = '' # Test a number of different sizes for num_bytes in (1, \ pyhsm.defines.KEY_SIZE + pyhsm.defines.UID_SIZE, \ pyhsm.defines.YSM_AEAD_MAX_SIZE - pyhsm.defines.YSM_AEAD_MAC_SIZE): aead = self.hsm.generate_aead_random(nonce, key_handle, num_bytes) self.assertEqual(num_bytes + pyhsm.defines.YSM_AEAD_MAC_SIZE, len(aead.data)) # test num_bytes we expect to fail for num_bytes in (0, \ pyhsm.defines.YSM_AEAD_MAX_SIZE - pyhsm.defines.YSM_AEAD_MAC_SIZE + 1, \ 255): try: res = self.hsm.generate_aead_random(nonce, key_handle, num_bytes) self.fail("Expected YSM_INVALID_PARAMETER, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_INVALID_PARAMETER) def test_who_can_generate_random(self): """ Test what key handles can generate a random AEAD. """ # Enabled flags 00000008 = YSM_RANDOM_AEAD_GENERATE # 00000004 - stored ok this = lambda kh: self.hsm.generate_aead_random(self.nonce, kh, 10) self.who_can(this, expected = [0x04], extra_khs = [0x1002]) def test_who_can_generate_simple(self): """ Test what key handles can generate a simple AEAD. """ # Enabled flags 00000002 = YSM_AEAD_GENERATE # 00000002 - stored ok if self.hsm.version.ver < (1,0,4): raise unittest.SkipTest("Requires 1.0.4 or greater") this = lambda kh: self.hsm.generate_aead_simple(self.nonce, kh, self.secret) self.who_can(this, expected = [0x20000002], extra_khs = [0x1002, 0x20000002]) def test_who_can_validate(self): """ Test what key handles can validate an AEAD. """ # Enabled flags 00000002 = YSM_AEAD_GENERATE # 00000002 - stored ok gen_kh = 2 # Enabled flags 00000010 = YSM_AEAD_DECRYPT_CMP # 00000005 - stored ok aead = self.hsm.generate_aead_simple('', gen_kh, self.secret) this = lambda kh: self.hsm.validate_aead(aead.nonce, kh, \ aead, cleartext = self.secret.pack()) self.who_can(this, expected = [0x05], extra_khs = [0x1002, 0x20000002]) python-pyhsm-1.0.4l/Tests/test_aes_ecb.py000066400000000000000000000121111256663164400204540ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestOtpValidate(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) # Enabled flags 0000e000 = YHSM_ECB_BLOCK_ENCRYPT,YHSM_ECB_BLOCK_DECRYPT,YHSM_ECB_BLOCK_DECRYPT_CMP self.kh_encrypt = 0x1001 self.kh_decrypt = 0x1001 self.kh_compare = 0x1001 def test_aes_ecb_cmd_class(self): """ Test YHSM_Cmd_AES_ECB class. """ this = pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB(None, None, '') # test repr method self.assertEquals(str, type(str(this))) this.executed = True self.assertEquals(str, type(str(this))) def test_encrypt_decrypt(self): """ Test to AES ECB decrypt something encrypted. """ plaintext = 'Fjaellen 2011'.ljust(pyhsm.defines.YSM_BLOCK_SIZE) # pad for compare after decrypt ciphertext = self.hsm.aes_ecb_encrypt(self.kh_encrypt, plaintext) self.assertNotEqual(plaintext, ciphertext) decrypted = self.hsm.aes_ecb_decrypt(self.kh_decrypt, ciphertext) self.assertEqual(plaintext, decrypted) def test_compare(self): """ Test to AES ECB decrypt and then compare something. """ plaintext = 'Maverick'.ljust(pyhsm.defines.YSM_BLOCK_SIZE) ciphertext = self.hsm.aes_ecb_encrypt(self.kh_encrypt, plaintext) self.assertTrue(self.hsm.aes_ecb_compare(self.kh_compare, ciphertext, plaintext)) self.assertFalse(self.hsm.aes_ecb_compare(self.kh_compare, ciphertext, plaintext[:-1] + 'x')) def test_compare_bad(self): """ Test AES decrypt compare with incorrect plaintext. """ plaintext = 'Maverick'.ljust(pyhsm.defines.YSM_BLOCK_SIZE) ciphertext = self.hsm.aes_ecb_encrypt(self.kh_encrypt, plaintext) self.assertFalse(self.hsm.aes_ecb_compare(self.kh_compare, ciphertext, plaintext[:-1] + 'x')) def test_who_can_encrypt(self): """ Test what key handles can encrypt AES ECB encrypted blocks. """ # Enabled flags 00002000 = YSM_AES_ECB_BLOCK_ENCRYPT # 0000000e - stored ok kh_enc = 0x0e plaintext = 'sommar' this = lambda kh: self.hsm.aes_ecb_encrypt(kh, plaintext) self.who_can(this, expected = [kh_enc]) def test_who_can_decrypt(self): """ Test what key handles can decrypt AES ECB encrypted blocks. """ # Enabled flags 00002000 = YSM_AES_ECB_BLOCK_ENCRYPT # 0000000e - stored ok kh_enc = 0x0e # Enabled flags 00004000 = YSM_AES_ECB_BLOCK_DECRYPT # 0000000f - stored ok kh_dec = 0x0f plaintext = 'sommar' ciphertext = self.hsm.aes_ecb_encrypt(kh_enc, plaintext) this = lambda kh: self.hsm.aes_ecb_decrypt(kh, ciphertext) self.who_can(this, expected = [kh_dec]) def test_who_can_compare(self): """ Test what key handles can decrypt_compare AES ECB encrypted blocks. """ # Enabled flags 00002000 = YSM_AES_ECB_BLOCK_ENCRYPT # 0000000e - stored ok kh_enc = 0x0e # Enabled flags 00008000 = YSM_AES_ECB_BLOCK_DECRYPT_CMP # 00000010 - stored ok kh_cmp = 0x10 # Decrypt implies decrypt_cmp # # Enabled flags 00004000 = YSM_AES_ECB_BLOCK_DECRYPT # 0000000f - stored ok kh_dec = 0x0f plaintext = 'sommar' ciphertext = self.hsm.aes_ecb_encrypt(kh_enc, plaintext) this = lambda kh: self.hsm.aes_ecb_decrypt(kh, ciphertext) self.who_can(this, expected = [kh_cmp, kh_dec]) def test_aes_with_keystore_locked(self): """ Test AES with locking and then unlocking keystore. """ if self.hsm.version.ver <= (0, 9, 8,): print ("Test for known bug in 0.9.8 disabled.") return None cleartext = "reference" res_before = self.hsm.aes_ecb_encrypt(0x2000, cleartext) # lock key store try: res = self.hsm.key_storage_unlock("A" * 8) self.fail("Expected YSM_MISMATCH/YSM_KEY_STORAGE_LOCKED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: if self.hsm.version.have_key_store_decrypt(): self.assertEquals(e.status, pyhsm.defines.YSM_MISMATCH) else: self.assertEquals(e.status, pyhsm.defines.YSM_KEY_STORAGE_LOCKED) # make sure we can't AES encrypt when keystore is locked try: res = self.hsm.aes_ecb_encrypt(0x2000, cleartext) self.fail("Expected YSM_KEY_STORAGE_LOCKED, got %s (before lock: %s)" \ % (res.encode("hex"), res_before.encode("hex"))) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_KEY_STORAGE_LOCKED) # unlock key store with correct passphrase self.assertTrue(self.hsm.key_storage_unlock(test_common.HsmPassphrase.decode("hex"))) # make sure it is properly unlocked res_after = self.hsm.aes_ecb_encrypt(0x2000, cleartext) self.assertEquals(res_before, res_after) python-pyhsm-1.0.4l/Tests/test_basics.py000066400000000000000000000115631256663164400203510ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import serial import struct import test_common class TestBasics(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) def test_echo(self): """ Test echo command. """ self.assertTrue(self.hsm.echo('test')) def test_random(self): """ Test random number generator . """ r1 = self.hsm.random(10) r2 = self.hsm.random(10) self.assertNotEqual(r1, r2) self.assertEqual(len(r1), 10) def test_util_key_handle_to_int(self): """ Test util.key_handle_to_int. """ self.assertEqual(1, pyhsm.util.key_handle_to_int("1")) self.assertEqual(1, pyhsm.util.key_handle_to_int("0x1")) self.assertEqual(0xffffffee, pyhsm.util.key_handle_to_int("0xffffffee")) self.assertEqual(1413895238, pyhsm.util.key_handle_to_int("FTFT")) def test_nonce(self): """ Test nonce retreival. """ n1 = self.hsm.get_nonce() n2 = self.hsm.get_nonce() self.assertEqual(n1.nonce_int + 1, n2.nonce_int) n3 = self.hsm.get_nonce(9) # YubiHSM returns nonce _before_ adding increment, so the increment # is still only 1 between n2 and n3 self.assertEqual(n2.nonce_int + 1, n3.nonce_int) n4 = self.hsm.get_nonce(1) # and now we see the 9 increment self.assertEqual(n3.nonce_int + 9, n4.nonce_int) def test_nonce_class(self): """ Test nonce class. """ # test repr method self.assertEquals(str, type(str(self.hsm.get_nonce(0)))) def test_random_reseed(self): """ Tets random reseed. """ # Unsure if we can test anything except the status returned is OK self.assertTrue(self.hsm.random_reseed('A' * 32)) # at least test we didn't disable the RNG r1 = self.hsm.random(10) r2 = self.hsm.random(10) self.assertNotEqual(r1, r2) def test_load_temp_key(self): """ Test load_temp_key. """ key = "A" * 16 uid = '\x4d\x01\x4d\x02' nonce = 'f1f2f3f4f5f6'.decode('hex') # key 0x2000 has all flags set key_handle = 0x2000 my_flags = struct.pack("< I", 0xffffffff) # full permissions when loaded into phantom key handle my_key = 'C' * pyhsm.defines.YSM_MAX_KEY_SIZE self.hsm.load_secret(my_key + my_flags) aead = self.hsm.generate_aead(nonce, key_handle) self.assertTrue(isinstance(aead, pyhsm.aead_cmd.YHSM_GeneratedAEAD)) # Load the AEAD into the phantom key handle 0xffffffff. self.assertTrue(self.hsm.load_temp_key(nonce, key_handle, aead)) # Encrypt something with the phantom key plaintext = 'Testing'.ljust(pyhsm.defines.YSM_BLOCK_SIZE) # pad for compare after decrypt ciphertext = self.hsm.aes_ecb_encrypt(pyhsm.defines.YSM_TEMP_KEY_HANDLE, plaintext) self.assertNotEqual(plaintext, ciphertext) # Now decrypt it again and verify result decrypted = self.hsm.aes_ecb_decrypt(pyhsm.defines.YSM_TEMP_KEY_HANDLE, ciphertext) self.assertEqual(plaintext, decrypted) def test_yhsm_class(self): """ Test YHSM class. """ # test repr method self.assertEquals(str, type(str(self.hsm))) def test_yhsm_stick_class(self): """ Test YHSM_Stick class. """ # test repr method self.assertEquals(str, type(str(self.hsm.stick))) def test_set_debug(self): """ Test set_debug on YHSM. """ old = self.hsm.set_debug(True) if old: self.hsm.set_debug(False) self.hsm.set_debug(old) try: self.hsm.set_debug('Test') self.fail("Expected non-bool exception.") except pyhsm.exception.YHSM_WrongInputType: pass def test_sysinfo_cmd_class(self): """ Test YHSM_Cmd_System_Info class. """ this = pyhsm.basic_cmd.YHSM_Cmd_System_Info(None) # test repr method self.assertEquals(str, type(str(this))) def test_sysinfo(self): """ Test sysinfo. """ info = self.hsm.info() self.assertTrue(info.version_major > 0 or info.version_minor > 0) self.assertEqual(12, len(info.system_uid)) self.assertEquals(str, type(str(info))) def test_drain(self): """ Test YubiHSM drain. """ self.hsm.drain() def test_raw_device(self): """ Test YubiHSM raw device fetch. """ self.assertNotEqual(False, self.hsm.get_raw_device()) def test_unknown_defines(self): """ Test command/response to string. """ self.assertEqual("YSM_NULL", pyhsm.defines.cmd2str(0)) self.assertEqual("0xff", pyhsm.defines.cmd2str(0xff)) self.assertEqual("YSM_STATUS_OK", pyhsm.defines.status2str(0x80)) self.assertEqual("0x00", pyhsm.defines.status2str(0)) python-pyhsm-1.0.4l/Tests/test_buffer.py000066400000000000000000000037371256663164400203620ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestBuffer(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) def test_load_random(self): """ Test load_random. """ nonce = "abc123" # key 0x2000 has all flags set key_handle = 0x2000 self.hsm.load_random(16) aead1 = self.hsm.generate_aead(nonce, key_handle) # nonce should NEVER be re-used for the same key_handle, but # we do it to test that the random-function actually changes # the buffer. self.hsm.load_random(16) aead2 = self.hsm.generate_aead(nonce, key_handle) self.assertNotEqual(aead1.data, aead2.data) def test_would_overflow_buffer(self): """ Test overflow of buffer. """ nonce = "abc123" # key 0x2000 has all flags set key_handle = 0x2000 self.assertEqual(64, self.hsm.load_random(16, offset = pyhsm.defines.YSM_DATA_BUF_SIZE - 8)) self.assertEqual(16, self.hsm.load_random(16, offset = 0)) # offset = 0 clears buffer self.assertEqual(17, self.hsm.load_random(1, offset = 16)) self.assertEqual(17, self.hsm.load_random(7, offset = 10)) self.assertEqual(63, self.hsm.load_random(1, offset = 62)) self.assertEqual(64, self.hsm.load_random(63, offset = 62)) def test_load_data(self): """ Test loading data into buffer. """ c1 = self.hsm.load_data('Samp', offset = 0) self.assertEqual(c1, 4) c2 = self.hsm.load_data('123', offset = 3) self.assertEqual(c2, 6) c3 = self.hsm.load_data('ple #2', offset = 3) self.assertEqual(c3, 9) nonce = "abc123" # key 0x2000 has all flags set key_handle = 0x2000 aead = self.hsm.generate_aead(nonce, key_handle) self.assertEqual(aead.data.encode('hex'), '18a88fbd7bd2275ba0a722bf80423ffab7') python-pyhsm-1.0.4l/Tests/test_common.py000066400000000000000000000145371256663164400204010ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import os import sys import unittest import pyhsm import struct # configuration parameters CfgPassphrase = "" HsmPassphrase = "bada" * 2 PrimaryAdminYubiKey = ('ftftftfteeee', 'f0f1f2f3f4f5', '4d' * 16,) AdminYubiKeys = [PrimaryAdminYubiKey[0]] class YHSM_TestCase(unittest.TestCase): hsm = None def setUp(self, device = os.getenv('YHSM_DEVICE', '/dev/ttyACM0'), debug = False): """ Common initialization class for our tests. Initializes a YubiHSM in self.hsm. """ self.hsm = pyhsm.base.YHSM(device = device, debug = debug) # unlock keystore if our test configuration contains a passphrase if HsmPassphrase is not None and HsmPassphrase != "": try: self.hsm.unlock(password = HsmPassphrase.decode("hex")) self.otp_unlock() except pyhsm.exception.YHSM_CommandFailed, e: # ignore errors from the unlock function, in case our test configuration # hasn't been loaded into the YubiHSM yet pass def tearDown(self): # get destructor called properly self.hsm = None def who_can(self, what, expected = [], extra_khs = []): """ Try the lambda what() with all key handles between 1 and 32, except the expected one. Fail on anything but YSM_FUNCTION_DISABLED. """ for kh in list(xrange(1, 32)) + extra_khs: if kh in expected: continue res = None try: res = what(kh) self.fail("Expected YSM_FUNCTION_DISABLED for key handle 0x%0x, got '%s'" % (kh, res)) except pyhsm.exception.YHSM_CommandFailed, e: if e.status != pyhsm.defines.YSM_FUNCTION_DISABLED: self.fail("Expected YSM_FUNCTION_DISABLED for key handle 0x%0x, got %s" \ % (kh, e.status_str)) def otp_unlock(self): """ Do OTP unlock of the YubiHSM keystore. Since we don't always reprogram the YubiHSM, we might need to hunt for an unused OTP. """ if not self.hsm.version.have_unlock(): return None Params = PrimaryAdminYubiKey YK = FakeYubiKey(pyhsm.yubikey.modhex_decode(Params[0]).decode('hex'), Params[1].decode('hex'), Params[2].decode('hex') ) YK.session_ctr = 0 use_ctr = 1 # the 16 bit power-up counter of the YubiKey while use_ctr < 0xffff: YK.use_ctr = use_ctr otp = YK.from_key() try: res = self.hsm.unlock(otp = otp) self.assertTrue(res) # OK - if we got here we've got a successful response for this OTP break except pyhsm.exception.YHSM_CommandFailed, e: if e.status != pyhsm.defines.YSM_OTP_REPLAY: raise # don't bother with the session_ctr - test run 5 would mean we first have to # exhaust 4 * 256 session_ctr increases before the YubiHSM would pass our OTP use_ctr += 1 def crc16(data): """ Calculate an ISO13239 CRC checksum of the input buffer. """ m_crc = 0xffff for this in data: m_crc ^= ord(this) for _ in range(8): j = m_crc & 1 m_crc >>= 1 if j: m_crc ^= 0x8408 return m_crc class YubiKeyEmu(): """ Emulate the internal memory of a YubiKey. """ def __init__(self, user_id, use_ctr, timestamp, session_ctr): if len(user_id) != pyhsm.defines.UID_SIZE: raise pyhsm.exception.YHSM_WrongInputSize( 'user_id', pyhsm.defines.UID_SIZE, len(user_id)) self.user_id = user_id self.use_ctr = use_ctr self.timestamp = timestamp self.session_ctr = session_ctr self.rnd = struct.unpack('H', os.urandom(2))[0] def pack(self): """ Return contents packed. Only add AES ECB encryption and modhex to get your own YubiKey OTP (see function 'from_key'). """ #define UID_SIZE 6 #typedef struct { # uint8_t userId[UID_SIZE]; # uint16_t sessionCtr; # NOTE: this is use_ctr # uint24_t timestamp; # uint8_t sessionUse; # NOTE: this is session_ctr # uint16_t rnd; # uint16_t crc; #} TICKET; fmt = "< %is H HB B H" % (pyhsm.defines.UID_SIZE) ts_high = (self.timestamp & 0x00ff0000) >> 16 ts_low = self.timestamp & 0x0000ffff res = struct.pack(fmt, self.user_id, \ self.use_ctr, \ ts_low, ts_high, \ self.session_ctr, \ self.rnd) crc = 0xffff - crc16(res) return res + struct.pack(' < hsm ffffffff # Enabled flags ffffffff = ... # Enter cfg password (g to generate) # Enter admin Yubikey public id (enter when done) # Enter master key (g to generate) yes # Confirm current config being erased (type yes) AdminYubiKeysStr = '\r'.join(AdminYubiKeys) AdminYubiKeysStr += '\r' self.config_do ("hsm ffffffff\r%s\r%s\r%s\ryes" % (CfgPassphrase, AdminYubiKeysStr, HsmPassphrase)) self.hsm.drain() self.add_keys(xrange(31)) self.hsm.drain() self.config_do("keylist") if self.hsm.version.have_key_store_decrypt(): self.config_do("keycommit") # load a YubiKey (the first Admin YubiKey) into the internal database escape_char = chr(27) self.config_do("dbload\r00001,%s,%s,%s,\r" % (PrimaryAdminYubiKey) + escape_char, add_cr = False) self.config_do("dblist") # get back into HSM mode sys.stderr.write("exit") self.ser.write("exit\r") self.hsm.drain() self.hsm.reset() def test_zzz_unlock(self): """ Test unlock of keystore after reconfiguration. """ if self.hsm.version.have_unlock(): Params = PrimaryAdminYubiKey YK = test_common.FakeYubiKey(pyhsm.yubikey.modhex_decode(Params[0]).decode('hex'), Params[1].decode('hex'), Params[2].decode('hex') ) # After reconfigure, we know the counter values for PrimaryAdminYubiKey is zero # in the internal db. However, the test suite initialization will unlock the keystore # (in test_common.YHSM_TestCase.setUp) so a value of 0/1 should result in a replayed OTP. YK.use_ctr = 0 YK.session_ctr = 1 # first verify counters 1/0 gives the expected YSM_OTP_REPLAY try: self.hsm.unlock(otp = YK.from_key()) except pyhsm.exception.YHSM_CommandFailed, e: if e.status != pyhsm.defines.YSM_OTP_REPLAY: raise # now do real unlock with values 2/1 (there is an extra unlock done somewhere...) YK.use_ctr = 2 self.assertTrue(self.hsm.unlock(password = HsmPassphrase.decode("hex"), otp = YK.from_key())) else: self.assertTrue(self.hsm.unlock(password = HsmPassphrase.decode("hex"))) def test_zzz_echo(self): """ Test echo after reconfiguration. """ self.assertTrue(self.hsm.echo('test')) def config_do(self, cmd, add_cr = True): # Don't have to output command - it is echoed #sys.__stderr__.write("> " + cmd + "\n") if add_cr: self.ser.write(cmd + "\r") else: self.ser.write(cmd) #time.sleep(0.5) recv = '' fail_count = 0 sys.stderr.write("< ") while True: b = self.ser.read(1) if not b: fail_count += 1 if fail_count == 5: raise Exception("Did not get the next prompt", recv) sys.stderr.write(b) recv += b lines = recv.split('\n') if re.match('^(NO_CFG|WSAPI|HSM).*> .*', lines[-1]): break return recv def add_keys(self, iterator): # Set up one key for every available flag for num in iterator: flags = 1 << num key = ("%02x" % (num + 1)) * 32 self.add_key(flags, num + 1, key) # Set up some extra keys with the same key as the flag-keys, but other flags # flags YHSM_OTP_BLOB_VALIDATE (0x200) matching key 0x06 (with flags 0x20, YHSM_BLOB_GENERATE) flags = 0x200 key = "06" * 32 self.add_key(flags, 0x1000, key) # Key with full AES ECB capabilities # Enabled flags 0000e000 = YHSM_ECB_BLOCK_ENCRYPT,YHSM_ECB_BLOCK_DECRYPT,YHSM_ECB_BLOCK_DECRYPT_CMP flags = 0xe000 key = "1001" * 16 self.add_key(flags, 0x1001, key) # Key allowed to generate AEAD from known data (loaded into buffer), with user specified noncey flags = 0x4 | 0x40000000 | 0x20000000 key = "1002" * 16 self.add_key(flags, 0x1002, key) # Key with everything enabled at once flags = 0xffffffff key = "2000" * 16 self.add_key(flags, 0x2000, key) # Key with everything enabled at once, and then revoked flags = 0xffffffff key = "2001" * 16 self.add_key(flags, 0x2001, key) self.config_do("keydis 2001") # Key with NIST test vector for HMAC SHA1 # Enabled flags 00010000 = YSM_HMAC_SHA1_GENERATE flags = 0x10000 key = "303132333435363738393a3b3c3d3e3f40414243".ljust(64, '0') self.add_key(flags, 0x3031, key) # Key permitting AEAD generate with user specified nonce flags = 0x20000002 key = "20000002" * 8 self.add_key(flags, 0x20000002, key) # Key permitting random AEAD generate with user specified nonce flags = 0x20000008 key = "20000008" * 8 self.add_key(flags, 0x20000008, key) def add_key(self, flags, num, key): keyline = "%08x,%s\r" % (num, key) self.config_do("flags %04x" % (flags)) escape_char = chr(27) self.config_do("keyload\r" + keyline + escape_char, add_cr = False) python-pyhsm-1.0.4l/Tests/test_db.py000066400000000000000000000130541256663164400174670ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import os import sys import unittest import pyhsm import test_common from test_yubikey_validate import YubiKeyEmu class TestInternalDB(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) self.key = "A" * 16 self.uid = 'f0f1f2f3f4f5'.decode('hex') self.public_id = '4d4d4d4d4d4d'.decode('hex') def test_store_yubikey(self): """ Test storing a YubiKey in the internal database. """ # Key handle 0x2000 has all flags enabled key_handle = 0x2000 secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(self.key, self.uid) self.hsm.load_secret(secret) aead = self.hsm.generate_aead(self.public_id, key_handle) # Try to store a record. YSM_ID_DUPLICATE is not an error since we don't # always zap the configuration before running the test suite. try: self.assertTrue(self.hsm.db_store_yubikey(self.public_id, key_handle, aead)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEqual(e.status, pyhsm.defines.YSM_ID_DUPLICATE) # Now, try an invalid validation against that record try: res = self.hsm.db_validate_yubikey_otp(self.public_id, "x" * 16) self.fail("Expected YSM_OTP_INVALID, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEqual(e.status, pyhsm.defines.YSM_OTP_INVALID) def test_store_yubikey_with_nonce(self): """ Test storing a YubiKey generated with non-public-id nonce in the internal database. """ if not self.hsm.version.have_YSM_DB_YUBIKEY_AEAD_STORE2(): raise unittest.SkipTest("Test of command introduced in 1.0.4 disabled.") # Key handle 0x2000 has all flags enabled key_handle = 0x2000 public_id = '4d4d4d001122'.decode('hex') nonce = '010203040506'.decode('hex') key = 'T' * 16 uid = 'F' * 6 secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(key, uid) self.hsm.load_secret(secret) aead = self.hsm.generate_aead(nonce, key_handle) # Try to store a record. YSM_ID_DUPLICATE is not an error since we don't # always zap the configuration before running the test suite. try: self.assertTrue(self.hsm.db_store_yubikey(public_id, key_handle, aead, nonce = nonce)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEqual(e.status, pyhsm.defines.YSM_ID_DUPLICATE) # Now, try an invalid validation against that record try: res = self.hsm.db_validate_yubikey_otp(public_id, "x" * 16) self.fail("Expected YSM_OTP_INVALID, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEqual(e.status, pyhsm.defines.YSM_OTP_INVALID) def test_real_validate(self): """ Test real validation of YubiKey OTP against internal database. """ # Key handle 0x2000 has all flags enabled key_handle = 0x2000 # randomize last byte of public_id to not have to try so hard to # find an unused OTP ;) this_public_id = self.public_id[:-1] + os.urandom(1) secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(self.key, self.uid) self.hsm.load_secret(secret) aead = self.hsm.generate_aead(this_public_id, key_handle) # Try to store a record. YSM_ID_DUPLICATE is not a duplicate since we don't # always zap the configuration before running the test suite. try: self.assertTrue(self.hsm.db_store_yubikey(this_public_id, key_handle, aead)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEqual(e.status, pyhsm.defines.YSM_ID_DUPLICATE) # OK, now we know there is an entry for this_public_id in the database - use_ctr = 0 # the 16 bit power-up counter of the YubiKey session_ctr = 0 timestamp = 0xffff # dunno while use_ctr < 0xffff: YK = YubiKeyEmu(self.uid, use_ctr, timestamp, session_ctr) otp = YK.get_otp(self.key) try: res = self.hsm.db_validate_yubikey_otp(this_public_id, otp) self.assertTrue(isinstance(res, pyhsm.validate_cmd.YHSM_ValidationResult)) self.assertEqual(res.public_id, this_public_id) self.assertEqual(res.use_ctr, use_ctr) # OK - if we got here we've got a successful response for this OTP break except pyhsm.exception.YHSM_CommandFailed, e: if e.status != pyhsm.defines.YSM_OTP_REPLAY: raise # don't bother with the session_ctr - test run 5 would mean we first have to # exhaust 4 * 256 session_ctr increases before the YubiHSM would pass our OTP use_ctr += 1 # Now, check the same OTP again and make sure we get a REPLAY response YK = YubiKeyEmu(self.uid, use_ctr, timestamp, session_ctr) otp = YK.get_otp(self.key) try: res = self.hsm.db_validate_yubikey_otp(this_public_id, otp) self.fail("Expected YSM_OTP_REPLAY, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: if e.status != pyhsm.defines.YSM_OTP_REPLAY: raise # increase session_ctr and test using different method session_ctr += 1 YK = YubiKeyEmu(self.uid, use_ctr, timestamp, session_ctr) mh_from_key = YK.from_key(this_public_id, self.key) pyhsm.yubikey.validate_otp(self.hsm, mh_from_key) python-pyhsm-1.0.4l/Tests/test_hmac.py000066400000000000000000000124331256663164400200120ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestHMACSHA1(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) # Enabled flags 00010000 = YSM_HMAC_SHA1_GENERATE # 00003031 - stored ok self.kh = 0x3031 def test_nist_test_vector(self): """ Test HMAC SHA1 with NIST PUB 198 A.2 test vector. """ data = 'Sample #2' this = self.hsm.hmac_sha1(self.kh, data).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') # test of repr method self.assertEquals(str, type(str(this))) def test_hmac_numeric_flags(self): """ Test HMAC SHA1 with numeric flags. """ data = 'Sample #2' flags = pyhsm.defines.YSM_HMAC_SHA1_RESET | pyhsm.defines.YSM_HMAC_SHA1_FINAL this = self.hsm.hmac_sha1(self.kh, data, flags = flags).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') def test_hmac_continuation(self): """ Test HMAC continuation. """ data = 'Sample #2' this = self.hsm.hmac_sha1(self.kh, data[:3], final = False) self.assertEquals(this.get_hash().encode('hex'), '00' * 20) this.next(data[3:], final = True).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') def test_hmac_continuation2(self): """ Test HMAC nasty continuation. """ data = 'Sample #2' this = self.hsm.hmac_sha1(self.kh, '', final = False) self.assertEquals(this.get_hash().encode('hex'), '00' * 20) this.next(data[:3], final = False).execute() this.next(data[3:], final = False).execute() this.next('', final = True).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') def test_hmac_interrupted(self): """ Test interrupted HMAC. """ data = 'Sample #2' this = self.hsm.hmac_sha1(self.kh, data[:3], final = False) self.assertEquals(this.get_hash().encode('hex'), '00' * 20) self.assertTrue(self.hsm.echo('hmac unit test')) this.next(data[3:], final = True).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') def test_hmac_interrupted2(self): """ Test AES-interrupted HMAC. """ data = 'Sample #2' plaintext = 'Maverick'.ljust(pyhsm.defines.YSM_BLOCK_SIZE) kh_encrypt = 0x1001 kh_decrypt = 0x1001 this = self.hsm.hmac_sha1(self.kh, data[:3], final = False) self.assertEquals(this.get_hash().encode('hex'), '00' * 20) # AES encrypt-decrypt in the middle of HMAC calculation ciphertext = self.hsm.aes_ecb_encrypt(kh_encrypt, plaintext) self.assertNotEqual(plaintext, ciphertext) decrypted = self.hsm.aes_ecb_decrypt(kh_decrypt, ciphertext) self.assertEqual(plaintext, decrypted) # continue HMAC this.next(data[3:], final = True).execute() self.assertEquals(this.get_hash().encode('hex'), '0922d3405faa3d194f82a45830737d5cc6c75d24') def test_hmac_wrong_key_handle(self): """ Test HMAC SHA1 operation with wrong key handle. """ try: res = self.hsm.hmac_sha1(0x01, 'foo').execute() self.fail("Expected YSM_FUNCTION_DISABLED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_FUNCTION_DISABLED) def test_who_can_hash(self): """ Test what key handles can create HMAC SHA1 hashes. """ # Enabled flags 00010000 = YSM_HMAC_SHA1_GENERATE # 00000011 - stored ok data = 'Sample #2' this = lambda kh: self.hsm.hmac_sha1(kh, data).execute() self.who_can(this, expected = [0x11]) def test_generated_sha1_class(self): """ Test YHSM_GeneratedHMACSHA1 class. """ this = pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1(0x0, 'a' * 20, True) # test repr method self.assertEquals(str, type(str(this))) def test_sha1_to_buffer(self): """ Test HMAC SHA1 to internal buffer. """ self.assertEqual(0, self.hsm.load_random(0, offset = 0)) # offset = 0 clears buffer self.hsm.hmac_sha1(self.kh, 'testing is fun!', to_buffer = True) # Verify there is now 20 bytes in the buffer self.assertEqual(pyhsm.defines.YSM_SHA1_HASH_SIZE, self.hsm.load_random(0, offset = 1)) def test_hmac_continuation_with_buffer(self): """ Test HMAC continuation with buffer. """ data = 'Sample #2' self.assertEqual(0, self.hsm.load_random(0, offset = 0)) # offset = 0 clears buffer self.assertEqual(0, self.hsm.load_random(0, offset = 1)) this = self.hsm.hmac_sha1(self.kh, '', final = False) self.assertEquals(this.get_hash().encode('hex'), '00' * 20) this.next(data[:3], final = False).execute() this.next(data[3:], final = False).execute() this.next('', final = True, to_buffer = True).execute() # Verify there is now 20 bytes in the buffer self.assertEqual(pyhsm.defines.YSM_SHA1_HASH_SIZE, self.hsm.load_random(0, offset = 1)) python-pyhsm-1.0.4l/Tests/test_init.py000066400000000000000000000042721256663164400200470ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import os import sys import unittest import pyhsm import test_aead import test_aes_ecb import test_basics import test_buffer import test_db import test_hmac import test_oath import test_otp_validate import test_stick import test_util import test_yubikey_validate import test_misc import test_soft_hsm test_modules = [test_aead, test_aes_ecb, test_basics, test_buffer, test_db, test_hmac, test_oath, test_otp_validate, test_stick, test_util, test_yubikey_validate, test_misc, test_soft_hsm, ] # special, should not be addded to test_modules import test_configure def suite(): """ Create a test suite with all our tests. If the OS environment variable 'YHSM_ZAP' is set and evaluates to true, we will include the special test case class that erases the current YubiHSM config and creates a new one with known keys to be used by the other tests. NOTE that this is ONLY POSSIBLE if the YubiHSM is already in DEBUG mode. """ global test_modules # Check if we have a YubiHSM present, and start with locking it's keystore # XXX produce a better error message than 'error: None' when initializing fails hsm = pyhsm.YHSM(device = os.getenv('YHSM_DEVICE', '/dev/ttyACM0')) try: hsm.unlock("BADPASSPHRASE99") except pyhsm.exception.YHSM_CommandFailed, e: if hsm.version.have_key_store_decrypt(): if e.status != pyhsm.defines.YSM_MISMATCH: raise else: if e.status != pyhsm.defines.YSM_KEY_STORAGE_LOCKED and \ e.status != pyhsm.defines.YSM_FUNCTION_DISABLED: raise zap = [] if 'YHSM_ZAP' in os.environ: if os.environ['YHSM_ZAP']: zap = [unittest.TestLoader().loadTestsFromModule(test_configure)] l = zap + [unittest.TestLoader().loadTestsFromModule(this) for this in test_modules] return unittest.TestSuite(l) if __name__ == '__main__': unittest.main() python-pyhsm-1.0.4l/Tests/test_misc.py000066400000000000000000000046441256663164400200420ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestUtil(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) def test_using_disabled_keyhandle(self): """ Test using a disabled key handle. """ if not self.hsm.version.have_keydisable(): return None # HSM> < keyload - Load key data now using flags ffffffff. Press ESC to quit # 00002001 - stored ok # HSM> < keydis 2001 try: res = self.hsm.aes_ecb_encrypt(0x2001, "klartext") self.fail("Expected YSM_FUNCTION_DISABLED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_FUNCTION_DISABLED) def test_keystore_unlock(self): """ Test locking and then unlocking keystore. """ if self.hsm.version.ver <= (0, 9, 8,): print ("Test for known bug in 0.9.8 disabled.") return None cleartext = "reference" nonce = '010203040506'.decode('hex') res_before = self.hsm.generate_aead_simple(nonce, 0x2000, cleartext) # lock key store try: res = self.hsm.key_storage_unlock("A" * 8) self.fail("Expected YSM_MISMATCH/YSM_KEY_STORAGE_LOCKED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: if self.hsm.version.have_key_store_decrypt(): self.assertEquals(e.status, pyhsm.defines.YSM_MISMATCH) else: self.assertEquals(e.status, pyhsm.defines.YSM_KEY_STORAGE_LOCKED) # make sure we can't generate AEADs when keystore is locked try: res = self.hsm.generate_aead_simple(nonce, 0x2000, cleartext) self.fail("Expected YSM_KEY_STORAGE_LOCKED, got %s (before lock: %s)" \ % (res.data.encode('hex'), res_before.data.encode('hex'))) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_KEY_STORAGE_LOCKED) # unlock key store with correct passphrase self.assertTrue(self.hsm.key_storage_unlock(test_common.HsmPassphrase.decode("hex"))) # make sure it is properly unlocked res_after = self.hsm.generate_aead_simple(nonce, 0x2000, cleartext) self.assertEquals(res_before.data, res_after.data) python-pyhsm-1.0.4l/Tests/test_oath.py000066400000000000000000000054631256663164400200420ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import struct import unittest import pyhsm import pyhsm.oath_hotp import test_common class TestOath(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) key = "3132333435363738393031323334353637383930".decode('hex') # Enabled flags 00010000 = YSM_HMAC_SHA1_GENERATE flags = struct.pack("< I", 0x10000) self.nonce = 'f1f2f3f4f5f6'.decode('hex') # key 0x2000 has all flags set self.key_handle = 0x2000 self.phantom = pyhsm.defines.YSM_TEMP_KEY_HANDLE self.hsm.load_secret(key + flags) self.aead = self.hsm.generate_aead(self.nonce, self.key_handle) self.assertTrue(isinstance(self.aead, pyhsm.aead_cmd.YHSM_GeneratedAEAD)) # Load the AEAD into the phantom key handle 0xffffffff. self.assertTrue(self.hsm.load_temp_key(self.nonce, self.key_handle, self.aead)) def test_OATH_HOTP_values(self): """ Test OATH HOTP known results. """ test_vectors = [(0, "cc93cf18508d94934c64b65d8ba7667fb7cde4b0", 755224,), (1, "75a48a19d4cbe100644e8ac1397eea747a2d33ab", 287082,), (2, "0bacb7fa082fef30782211938bc1c5e70416ff44", 359152,), (3, "66c28227d03a2d5529262ff016a1e6ef76557ece", 969429,), (4, "a904c900a64b35909874b33e61c5938a8e15ed1c", 338314,), (5, "a37e783d7b7233c083d4f62926c7a25f238d0316", 254676,), (6, "bc9cd28561042c83f219324d3c607256c03272ae", 287922,), (7, "a4fb960c0bc06e1eabb804e5b397cdc4b45596fa", 162583,), (8, "1b3c89f65e6c9e883012052823443f048b4332db", 399871,), (9, "1637409809a679dc698207310c8c7fc07290d9e5", 520489,), (30, "543c61f8f9aeb35f6dbc3a6847c3fe288cc0ee4c", 26920,), ] for c, expected, code in test_vectors: hmac_result = self.hsm.hmac_sha1(self.phantom, struct.pack("> Q", c)).get_hash() self.assertEqual(expected, hmac_result.encode('hex')) self.assertEqual(code, pyhsm.oath_hotp.truncate(hmac_result, length=6)) def test_OATH_HOTP_validation(self): """ Test complete OATH HOTP code validation. """ oath = lambda counter, user_code, look_ahead: \ pyhsm.oath_hotp.search_for_oath_code(self.hsm, self.key_handle, self.nonce, self.aead, \ counter, user_code, look_ahead) self.assertEqual(1, oath(0, 755224, 1)) self.assertEqual(4, oath(0, 969429, 4)) self.assertEqual(None, oath(0, 969429, 3)) self.assertEqual(10, oath(9, 520489, 3)) self.assertEqual(31, oath(30, 26920, 1)) python-pyhsm-1.0.4l/Tests/test_otp_validate.py000066400000000000000000000046401256663164400215560ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestOtpValidate(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) def test_load_secret_wrong_key(self): """ Test load_secret with key that should not be allowed to. """ key = "A" * 16 uid = '\x4d\x4d\x4d\x4d\x4d\x4d' public_id = 'f0f1f2f3f4f5'.decode('hex') # Enabled flags 00000100 = YHSM_AEAD_STORE # HSM> < keyload - Load key data now using flags 00000100. Press ESC to quit # 00000009 - stored ok key_handle = 9 # Enabled flags 00000020 = YHSM_AEAD_GENERATE secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(key, uid) self.hsm.load_secret(secret) try: res = self.hsm.generate_aead(public_id, key_handle) self.fail("Expected YSM_FUNCTION_DISABLED, got %s" % (res)) except pyhsm.exception.YHSM_CommandFailed, e: self.assertEquals(e.status, pyhsm.defines.YSM_FUNCTION_DISABLED) def test_load_secret(self): """ Test load_secret. """ key = "A" * 16 uid = '\x4d\x01\x4d\x02' public_id = 'f1f2f3f4f5f6'.decode('hex') if self.hsm.version.have_YSM_BUFFER_LOAD(): # Enabled flags 60000004 = YSM_BUFFER_AEAD_GENERATE,YSM_USER_NONCE,YSM_BUFFER_LOAD # HSM (keys changed)> < keyload - Load key data now using flags 60000004. Press ESC to quit # 00001002 - stored ok key_handle = 0x1002 else: # Enabled flags 00000004 = YSM_BUFFER_AEAD_GENERATE # HSM> < keyload - Load key data now using flags 00000004. Press ESC to quit # 00000003 - stored ok key_handle = 3 secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(key, uid) self.hsm.load_secret(secret) aead = self.hsm.generate_aead(public_id, key_handle) self.assertTrue(isinstance(aead, pyhsm.aead_cmd.YHSM_GeneratedAEAD)) self.assertEqual(aead.nonce, public_id) self.assertEqual(aead.key_handle, key_handle) def test_yubikey_secrets(self): """ Test the class representing the YUBIKEY_SECRETS struct. """ aes_128_key = 'a' * 16 first = pyhsm.aead_cmd.YHSM_YubiKeySecret(aes_128_key, 'b') self.assertEqual(len(first.pack()), pyhsm.defines.KEY_SIZE + pyhsm.defines.UID_SIZE) python-pyhsm-1.0.4l/Tests/test_soft_hsm.py000066400000000000000000000072161256663164400207270ustar00rootroot00000000000000# Copyright (c) 2012 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestSoftHSM(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) self.nonce = "4d4d4d4d4d4d".decode('hex') self.key = "A" * 16 def test_aes_CCM_encrypt_decrypt(self): """ Test decrypting encrypted data. """ key = chr(0x09) * 16 key_handle = 1 plaintext = "foo".ljust(16, chr(0x0)) ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) pt = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, ct, decrypt = True) self.assertEquals(plaintext, pt) def test_aes_CCM_wrong_key(self): """ Test decrypting encrypted data with wrong key. """ key = chr(0x09) * 16 key_handle = 1 plaintext = "foo".ljust(16, chr(0x0)) ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) key = chr(0x08) * 16 self.assertRaises(pyhsm.exception.YHSM_Error, pyhsm.soft_hsm.aesCCM, key, key_handle, self.nonce, ct, decrypt = True) def test_aes_CCM_wrong_key_handle(self): """ Test decrypting encrypted data with wrong key_handle. """ key = chr(0x09) * 16 key_handle = 1 plaintext = "foo".ljust(16, chr(0x0)) ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) key_handle = 2 self.assertRaises(pyhsm.exception.YHSM_Error, pyhsm.soft_hsm.aesCCM, key, key_handle, self.nonce, ct, decrypt = True) def test_soft_simple_aead_generation(self): """ Test soft_hsm simple AEAD generation. """ key_handle = 0x2000 plaintext = 'foo'.ljust(16, chr(0x0)) key = str("2000" * 16).decode('hex') # generate soft AEAD ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) # generate hard AEAD aead = self.hsm.generate_aead_simple(self.nonce, key_handle, plaintext) ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) self.assertEquals(aead.data, ct) # decrypt the AEAD again pt = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, ct, decrypt = True) self.assertEquals(plaintext, pt) def test_soft_generate_long_aead(self): """ Test soft_hsm generation of long AEAD. """ key_handle = 0x2000 plaintext = 'A' * 64 key = str("2000" * 16).decode('hex') # generate soft AEAD ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) # generate hard AEAD aead = self.hsm.generate_aead_simple(self.nonce, key_handle, plaintext) self.assertEquals(aead.data, ct) # decrypt the AEAD again pt = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, ct, decrypt = True) self.assertEquals(plaintext, pt) def test_soft_generate_yubikey_secrets_aead(self): """ Test soft_hsm generation of YubiKey secrets AEAD. """ key_handle = 0x2000 plaintext = 'A' * 22 key = str("2000" * 16).decode('hex') # generate soft AEAD ct = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, plaintext, decrypt = False) # generate hard AEAD aead = self.hsm.generate_aead_simple(self.nonce, key_handle, plaintext) self.assertEquals(aead.data, ct) # decrypt the AEAD again pt = pyhsm.soft_hsm.aesCCM(key, key_handle, self.nonce, ct, decrypt = True) self.assertEquals(plaintext, pt) python-pyhsm-1.0.4l/Tests/test_stick.py000066400000000000000000000020051256663164400202110ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestUtil(test_common.YHSM_TestCase): def setUp(self): self.saved_stderr = sys.stderr # Discard everything written to stderr from these tests (i.e. debug output # from YubiHSM communication routines with debugging enabled). sys.stderr = DiscardOutput() DontChange = True # we test debug output from YubiHSM communication here test_common.YHSM_TestCase.setUp(self, debug = DontChange) def test_debug_output(self): """ Test debug output of YubiHSM communication. """ self.assertTrue(self.hsm.echo('testing')) self.assertTrue(self.hsm.drain()) def tearDown(self): # Close YubiHSM interface before restoring stderr, to avoid output # when it is closed. self.hsm = None sys.stderr = self.saved_stderr class DiscardOutput(object): def write(self, text): pass python-pyhsm-1.0.4l/Tests/test_util.py000066400000000000000000000035311256663164400200560ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import unittest import pyhsm import test_common class TestUtil(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) def test_hexdump(self): """ Test hexdump function. """ data1 = ''.join([chr(x) for x in xrange(8)]) self.assertEquals('0000 00 01 02 03 04 05 06 07\n', pyhsm.util.hexdump(data1)) data2 = ''.join([chr(x) for x in xrange(64)]) self.assertEquals(248, len(pyhsm.util.hexdump(data2))) self.assertEquals('', pyhsm.util.hexdump('')) def test_response_validation(self): """ Test response validation functions. """ self.assertRaises(pyhsm.exception.YHSM_Error, pyhsm.util.validate_cmd_response_str, \ 'test', 'abc', 'def', hex_encode=True) self.assertRaises(pyhsm.exception.YHSM_Error, pyhsm.util.validate_cmd_response_str, \ 'test', 'abc', 'def', hex_encode=False) def test_input_validate_str(self): """ Test string input validation. """ self.assertRaises(pyhsm.exception.YHSM_WrongInputType, pyhsm.util.input_validate_str, \ 0, 'foo', exact_len = 5) self.assertRaises(pyhsm.exception.YHSM_InputTooLong, pyhsm.util.input_validate_str, \ '1234', 'foo', max_len = 3) self.assertEquals('1234', pyhsm.util.input_validate_str('1234', 'foo', max_len = 4)) self.assertEquals('1234', pyhsm.util.input_validate_str('1234', 'foo', max_len = 14)) self.assertRaises(pyhsm.exception.YHSM_WrongInputSize, pyhsm.util.input_validate_str, \ '1234', 'foo', exact_len = 5) self.assertEquals('1234', pyhsm.util.input_validate_str('1234', 'foo', exact_len = 4)) python-pyhsm-1.0.4l/Tests/test_yubikey_validate.py000066400000000000000000000054051256663164400224350ustar00rootroot00000000000000# Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. import sys import string import unittest import pyhsm import test_common from test_common import YubiKeyEmu, YubiKeyRnd class TestYubikeyValidate(test_common.YHSM_TestCase): def setUp(self): test_common.YHSM_TestCase.setUp(self) self.yk_key = 'F' * 16 # 128 bit AES key self.yk_uid = '\x4d\x01\x4d\x02\x4d\x4d' self.yk_rnd = YubiKeyRnd(self.yk_uid) self.yk_public_id = '4d4d4d4d4d4d'.decode('hex') secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(self.yk_key, self.yk_uid) self.hsm.load_secret(secret) # YubiHSM includes key handle id in AES-CCM of aeads, so we must use same # key to generate and validate. Key 0x2000 has all flags. self.kh_generate = 0x2000 self.kh_validate = 0x2000 self.aead = self.hsm.generate_aead(self.yk_public_id, self.kh_generate) def test_validate_aead_cmp(self): """ Test that the AEAD generated contains our secrets. """ secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(self.yk_key, self.yk_uid) cleartext = secret.pack() self.assertTrue(self.hsm.validate_aead(self.yk_public_id, self.kh_validate, self.aead, cleartext)) wrong_cleartext = 'X' + cleartext[1:] self.assertFalse(self.hsm.validate_aead(self.yk_public_id, self.kh_validate, self.aead, wrong_cleartext)) def test_validate_aead_cmp_long(self): """ Test validating a long AEAD """ cleartext = 'C' * 36 key_handle = 0x2000 # key 0x2000 has all flags set nonce = '123456' aead = self.hsm.generate_aead_simple(nonce, key_handle, cleartext) self.assertTrue(self.hsm.validate_aead(nonce, key_handle, aead, cleartext)) wrong_cleartext = 'X' + cleartext[1:] self.assertFalse(self.hsm.validate_aead(nonce, key_handle, aead, wrong_cleartext)) def test_validate_yubikey(self): """ Test validate YubiKey OTP. """ from_key = self.yk_rnd.from_key(self.yk_public_id, self.yk_key) self.assertTrue(pyhsm.yubikey.validate_yubikey_with_aead( \ self.hsm, from_key, self.aead, self.kh_validate)) def test_modhex_encode_decode(self): """ Test modhex encoding/decoding. """ h = '4d014d024d4ddd5382b11195144da07d' self.assertEquals(h, pyhsm.yubikey.modhex_decode( pyhsm.yubikey.modhex_encode(h) ) ) def test_split_id_otp(self): """ Test public_id + OTP split function. """ public_id, otp, = pyhsm.yubikey.split_id_otp("ft" * 16) self.assertEqual(public_id, '') self.assertEqual(otp, "ft" * 16) public_id, otp, = pyhsm.yubikey.split_id_otp("cc" + "ft" * 16) self.assertEqual(public_id, 'cc') self.assertEqual(otp, "ft" * 16) python-pyhsm-1.0.4l/doc/000077500000000000000000000000001256663164400151315ustar00rootroot00000000000000python-pyhsm-1.0.4l/doc/Database_Usage.adoc000066400000000000000000000026001256663164400206070ustar00rootroot00000000000000== Database Usage IMPORT / EXPORT AEADs, to/from a database using yhsm-db-import and yhsm-db-export === INSTALLATION On Debian/Ubuntu install [source, sh] ~$ sudo apt-get install python-sqlalchemy (or any other method illustrated at: http://docs.sqlalchemy.org/en/rel_0_8/intro.html#installation) On other systems: Install SQLAlchemy from http://docs.sqlalchemy.org/en/rel_0_8/intro.html#installation A database schema is provided to configure the database table for the import/export tools. Create your favourite database and use te schema db_schema provided. [source, sh] ---- ~$ cat doc/db_schema CREATE TABLE aead_table ( public_id varchar(16) NOT NULL, keyhandle INT NOT NULL, aead BLOB NOT NULL, PRIMARY KEY (public_id, keyhandle) ); ---- === USAGE IMPORT: yhsm-db-import aeads_source_folder database_url EXPORT: yhsm-db-export aeads_destination_folder database_url [CAUTION] It is not safe to execute the command with the database url containing username and password. ==== IMPORT [source, sh] ~$ python yhsm-db-import /root/aeads/ mysql://localhost/database_name OR [source, sh] ~$ python yhsm-db-import /root/aeads/ mysql://root:password@localhost:3306/database_name ==== EXPORT [source, sh] ~$ python yhsm-db-export /root/aeads/ mysql://localhost/database_name OR [source, sh] ~$ python yhsm-db-export /root/aeads/ mysql://root:password@localhost:3306/database_name python-pyhsm-1.0.4l/doc/Intro.adoc000066400000000000000000000031431256663164400170550ustar00rootroot00000000000000== Installation === API To learn about the API, either download an official release tar.gz file and look in doc/html/ (more details in doc/README file), or install pyhsm and start reading the pydoc documentation. === Installation ==== Quick Ubuntu guide [source, sh] ---- $ sudo add-apt-repository ppa:yubico/stable $ sudo apt-get update $ sudo apt-get install python-pyhsm $ pydoc pyhsm $ pydoc pyhsm.base ---- ==== Windows python-pyhsm has been tested on Windows with Python 2.6 (2.7 will probably also work) from http://www.python.org/. You need to install pySerial (tested with pyserial-2.5.win32.exe) from http://pypi.python.org/pypi/pyserial. When you first insert the YubiHSM in your computer, Windows will indicate it cannot install the hardware. Download the .INF file from http://www.yubico.com/yubihsm/ and select that in the Windows dialog. Now, you should be able to communicate with the YubiHSM from Python like this (for this simple test, I put a copy of the pyhsm source tree in Z:\tmp\pyhsm): [source, py] ---- Z:\tmp\pyhsm>c:\Python26\python.exe Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path.append("Z:\\tmp\\pyhsm\\Lib") >>> import pyhsm >>> hsm = pyhsm.YHSM(device = "COM3") >>> hsm.info() >>> ---- Here is how to for example get five bytes of random binary data from the YubiHSM: [source, py] ---- >>> hsm.random(5) '\x9c\x0fu\xcfP' >>> hsm.random(5).encode("hex") 'b562456719' >>> ---- python-pyhsm-1.0.4l/doc/README000066400000000000000000000014211256663164400160070ustar00rootroot00000000000000This is the documentation directory of pyhsm. ---- API documentation ---- In doc/html/ you will find API documentation generated from pydoc in the source tree at the time of release. If you have checked out the source code from the repository rather than downloaded an official release, you can generate the HTML API documentation yourself by installing 'epydoc' (package 'python-epydoc' in Debian/Ubuntu) and then executing the ./maintainer-scripts/generate_html.sh script. ---- Assorted usage documentation ---- Please note that there might be more updated documentation available online. ---- Low level documentation ---- The reference manual is available from http://www.yubico.com/yubihsm/ The file doc/YubiHSM_if.h details all the available commands of the YubiHSM. python-pyhsm-1.0.4l/doc/Running_Hardware_Tests.adoc000066400000000000000000000011321256663164400223750ustar00rootroot00000000000000== PyHSM hardware tests with a YubiHSM Tests require a YubiHSM to be run. === Preparation Prepare the HSM as follows: ..... zap yes hsm ffffffff yes keycommit exit ..... === Running tests When the HSM is prepared the run script must be invoked with YHSM_ZAP: [source, sh] $ YHSM_ZAP=1 ./Tests/run.sh Subsequent runs do not require this: [source, sh] $ ./Tests/run.sh === Selecting the device By default the tests will use /dev/ttyACM0, but you can change this by providing the device to use with YHSM_DEVICE: [source, sh] $ YHSM_DEVICE="/dev/ttyACM1" ./Tests/run.sh python-pyhsm-1.0.4l/doc/YubiHSM_if.h000066400000000000000000000466361256663164400172570ustar00rootroot00000000000000/************************************************************************* ** ** ** YubiHSM_if - HSM mode interface declarations ** ** ** ** Copyright 2011 - Yubico AB ** ** ** ** Date / Sig / Rev / History ** ** 110205 / J E / 0.00 / Main ** ** 110412 / J E / 0.98 / Release changes ** ** 110809 / J E / 1.01 / Release changes ** ** ** *************************************************************************/ #ifndef __YUBIHSM_H_INCLUDED #define __YUBIHSM_H_INCLUDED #include #ifdef _WIN32 typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; #endif #define YSM_PUBLIC_ID_SIZE 6 // Size of public id for std OTP validation #define YSM_OTP_SIZE 16 // Size of OTP #define YSM_BLOCK_SIZE 16 // Size of block operations #define YSM_MAX_KEY_SIZE 32 // Max size of CCMkey #define YSM_DATA_BUF_SIZE 64 // Size of internal data buffer #define YSM_AEAD_NONCE_SIZE 6 // Size of AEAD nonce (excluding size of key handle) #define YSM_AEAD_MAC_SIZE 8 // Size of AEAD MAC field #define YSM_CCM_CTR_SIZE 2 // Sizeof of AES CCM counter field #define YSM_AEAD_MAX_SIZE (YSM_DATA_BUF_SIZE + YSM_AEAD_MAC_SIZE) // Max size of an AEAD block #define YSM_YUBIKEY_AEAD_SIZE (KEY_SIZE + UID_SIZE + YSM_AEAD_MAC_SIZE) #define YSM_SHA1_HASH_SIZE 20 // 160-bit SHA1 hash size #define YSM_CTR_DRBG_SEED_SIZE 32 // Size of CTR-DRBG entropy #define YSM_MAX_PKT_SIZE 0x60 // Max size of a packet (excluding command byte) #define YSM_PROTOCOL_VERSION 1 // Protocol version for this file #define YSM_TEMP_KEY_HANDLE 0xffffffff // Phantom temporary key handle // 22-bytes Yubikey secrets block typedef struct { uint8_t key[KEY_SIZE]; // AES key uint8_t uid[UID_SIZE]; // Unique (secret) ID } YSM_YUBIKEY_SECRETS; // AES CCM nonce typedef struct { uint32_t keyHandle; // Key handle uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce / public id } YSM_CCM_NONCE; // Up- and downlink packet typedef struct { uint8_t bcnt; // Number of bytes (cmd + payload) uint8_t cmd; // YSM_xxx command uint8_t payload[YSM_MAX_PKT_SIZE]; // Payload } YSM_PKT; // HSM commands #define YSM_RESPONSE 0x80 // Response bit // Status codes typedef uint8_t YSM_STATUS; #define YSM_STATUS_OK 0x80 // Executed successfully #define YSM_KEY_HANDLE_INVALID 0x81 // Key handle is invalid #define YSM_AEAD_INVALID 0x82 // Supplied AEAD block is invalid #define YSM_OTP_INVALID 0x83 // Supplied OTP is invalid (CRC or UID) #define YSM_OTP_REPLAY 0x84 // Supplied OTP is replayed #define YSM_ID_DUPLICATE 0x85 // The supplied public ID is already in the database #define YSM_ID_NOT_FOUND 0x86 // The supplied public ID was not found in the database #define YSM_DB_FULL 0x87 // The database storage is full #define YSM_MEMORY_ERROR 0x88 // Memory read/write error #define YSM_FUNCTION_DISABLED 0x89 // Function disabled via attribute(s) #define YSM_KEY_STORAGE_LOCKED 0x8a // Key storage locked #define YSM_MISMATCH 0x8b // Verification mismatch #define YSM_INVALID_PARAMETER 0x8c // Invalid parameter #define YSM_CUSTOM_STATUS_FIRST 0xf0 // Start custom status codes #define YSM_CUSTOM_STATUS_LAST 0xff // Start custom status codes //////////////////////////////////// // NULL / resync command //////////////////////////////////// #define YSM_NULL 0x00 typedef struct { uint8_t allNull[YSM_MAX_PKT_SIZE - 1]; // Set all to NULL when sending resync } YSM_RESYNC_REQ; //////////////////////////////////// // Generate AEAD block from data for a specific key //////////////////////////////////// #define YSM_AEAD_GENERATE 0x01 typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle uint8_t numBytes; // Number of data bytes uint8_t data[YSM_DATA_BUF_SIZE]; // Data } YSM_AEAD_GENERATE_REQ; #define YSM_AEAD_GENERATED (YSM_AEAD_GENERATE | YSM_RESPONSE) typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle YSM_STATUS status; // Status uint8_t numBytes; // Number of bytes in AEAD block uint8_t aead[YSM_AEAD_MAX_SIZE]; // AEAD block } YSM_AEAD_GENERATE_RESP; //////////////////////////////////// // Generate AEAD block of data buffer for a specific key //////////////////////////////////// #define YSM_BUFFER_AEAD_GENERATE 0x02 typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle } YSM_BUFFER_AEAD_GENERATE_REQ; #define YSM_BUFFER_AEAD_GENERATED (YSM_BUFFER_AEAD_GENERATE | YSM_RESPONSE) typedef YSM_AEAD_GENERATE_RESP YSM_BUFFER_AEAD_GENERATE_RESP; //////////////////////////////////// // Generate random AEAD block in one stroke //////////////////////////////////// #define YSM_RANDOM_AEAD_GENERATE 0x03 typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle uint8_t numBytes; // Number of bytes to randomize } YSM_RANDOM_AEAD_GENERATE_REQ; #define YSM_RANDOM_AEAD_GENERATED (YSM_RANDOM_AEAD_GENERATE | YSM_RESPONSE) typedef YSM_AEAD_GENERATE_RESP YSM_RANDOM_AEAD_GENERATE_RESP; //////////////////////////////////// // Decrypt AEAD block and compare with plaintext //////////////////////////////////// #define YSM_AEAD_DECRYPT_CMP 0x04 typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle uint8_t numBytes; // Number of data bytes (cleartext + aead) uint8_t data[YSM_MAX_PKT_SIZE - 0x10]; // Data (cleartext + aead). Empty cleartext validates aead only } YSM_AEAD_DECRYPT_CMP_REQ; #define YSM_AEAD_DECRYPT_CMPD (YSM_AEAD_DECRYPT_CMP | YSM_RESPONSE) typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce (publicId for Yubikey AEADs) uint32_t keyHandle; // Key handle YSM_STATUS status; // Status } YSM_AEAD_DECRYPT_CMP_RESP; //////////////////////////////////// // Store Yubikey specific AEAD block in internal store (nonce == public id) //////////////////////////////////// #define YSM_DB_YUBIKEY_AEAD_STORE 0x05 typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (and nonce in this case) uint32_t keyHandle; // Key handle uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block } YSM_DB_YUBIKEY_AEAD_STORE_REQ; #define YSM_DB_YUBIKEY_AEAD_STORED (YSM_DB_YUBIKEY_AEAD_STORE | YSM_RESPONSE) typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) uint32_t keyHandle; // Key handle YSM_STATUS status; // Validation status } YSM_DB_YUBIKEY_AEAD_STORE_RESP; //////////////////////////////////// // Decode Yubico OTP using supplied AEAD block //////////////////////////////////// #define YSM_AEAD_YUBIKEY_OTP_DECODE 0x06 typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) uint32_t keyHandle; // Key handle uint8_t otp[YSM_OTP_SIZE]; // OTP uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block } YSM_AEAD_YUBIKEY_OTP_DECODE_REQ; #define YSM_AEAD_YUBIKEY_OTP_DECODED (YSM_AEAD_YUBIKEY_OTP_DECODE | YSM_RESPONSE) typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id (nonce) uint32_t keyHandle; // Key handle uint16_t useCtr; // Use counter uint8_t sessionCtr; // Session counter uint8_t tstph; // Timestamp (high part) uint16_t tstpl; // Timestamp (low part) YSM_STATUS status; // Validation status } YSM_AEAD_YUBIKEY_OTP_DECODE_RESP; //////////////////////////////////// // Validate OTP using interal store //////////////////////////////////// #define YSM_DB_YUBIKEY_OTP_VALIDATE 0x07 typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id uint8_t otp[YSM_OTP_SIZE]; // OTP } YSM_DB_YUBIKEY_OTP_VALIDATE_REQ; #define YSM_DB_YUBIKEY_OTP_VALIDATED (YSM_DB_YUBIKEY_OTP_VALIDATE | YSM_RESPONSE) typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id uint16_t useCtr; // Use counter uint8_t sessionCtr; // Session counter uint8_t tstph; // Timestamp (high part) uint16_t tstpl; // Timestamp (low part) YSM_STATUS status; // Validation status } YSM_DB_YUBIKEY_OTP_VALIDATE_RESP; //////////////////////////////////// // Store Yubikey specific AEAD block in internal store (nonce != public id) //////////////////////////////////// #define YSM_DB_YUBIKEY_AEAD_STORE2 0x08 typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id uint32_t keyHandle; // Key handle uint8_t aead[YSM_YUBIKEY_AEAD_SIZE]; // AEAD block uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce } YSM_DB_YUBIKEY_AEAD_STORE2_REQ; #define YSM_DB_YUBIKEY_AEAD_STORED2 (YSM_DB_YUBIKEY_AEAD_STORE2 | YSM_RESPONSE) typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id uint32_t keyHandle; // Key handle YSM_STATUS status; // Validation status } YSM_DB_YUBIKEY_AEAD_STORE2_RESP; //////////////////////////////////// // AES ECB block encrypt request //////////////////////////////////// #define YSM_AES_ECB_BLOCK_ENCRYPT 0x0d typedef struct { uint32_t keyHandle; // Key handle uint8_t plaintext[YSM_BLOCK_SIZE]; // Plaintext block } YSM_AES_ECB_BLOCK_ENCRYPT_REQ; #define YSM_AES_ECB_BLOCK_ENCRYPTED (YSM_AES_ECB_BLOCK_ENCRYPT | YSM_RESPONSE) typedef struct { uint32_t keyHandle; // Key handle uint8_t ciphertext[YSM_BLOCK_SIZE]; // Ciphertext block YSM_STATUS status; // Encryption status } YSM_AES_ECB_BLOCK_ENCRYPT_RESP; //////////////////////////////////// // ECB block decrypt request //////////////////////////////////// #define YSM_AES_ECB_BLOCK_DECRYPT 0x0e typedef struct { uint32_t keyHandle; // Key handle uint8_t ciphertext[YSM_BLOCK_SIZE]; // Ciphertext block } YSM_AES_ECB_BLOCK_DECRYPT_REQ; #define YSM_AES_ECB_BLOCK_DECRYPTED (YSM_AES_ECB_BLOCK_DECRYPT | YSM_RESPONSE) typedef struct { uint32_t keyHandle; // Key handle uint8_t plaintext[YSM_BLOCK_SIZE]; // Plaintext block YSM_STATUS status; // Decryption status } YSM_AES_ECB_BLOCK_DECRYPT_RESP; //////////////////////////////////// // ECB block decrypt and verify request //////////////////////////////////// #define YSM_AES_ECB_BLOCK_DECRYPT_CMP 0x0f typedef struct { uint32_t keyHandle; // Key handle uint8_t ciphertext[YSM_BLOCK_SIZE]; // Ciphertext block uint8_t plaintext[YSM_BLOCK_SIZE]; // Plaintext block } YSM_AES_ECB_BLOCK_DECRYPT_CMP_REQ; #define YSM_AES_ECB_BLOCK_DECRYPT_CMPD (YSM_AES_ECB_BLOCK_DECRYPT_CMP | YSM_RESPONSE) typedef struct { uint32_t keyHandle; // Key handle YSM_STATUS status; // Decryption + verification status } YSM_AES_ECB_BLOCK_DECRYPT_CMP_RESP; //////////////////////////////////// // HMAC-SHA1 data input //////////////////////////////////// #define YSM_HMAC_SHA1_GENERATE 0x10 #define YSM_HMAC_SHA1_RESET 0x01 // Flag to indicate reset at first packet #define YSM_HMAC_SHA1_FINAL 0x02 // Flag to indicate that the hash shall be calculated #define YSM_HMAC_SHA1_TO_BUFFER 0x04 // Flag to transfer HMAC to buffer typedef struct { uint32_t keyHandle; // Key handle uint8_t flags; // Flags uint8_t numBytes; // Number of bytes in data packet uint8_t data[YSM_MAX_PKT_SIZE - 6]; // Data to be written } YSM_HMAC_SHA1_GENERATE_REQ; #define YSM_HMAC_SHA1_GENERATED (YSM_HMAC_SHA1_GENERATE | YSM_RESPONSE) typedef struct { uint32_t keyHandle; // Key handle YSM_STATUS status; // Status uint8_t numBytes; // Number of bytes in hash output uint8_t hash[YSM_SHA1_HASH_SIZE]; // Hash output (if applicable) } YSM_HMAC_SHA1_GENERATE_RESP; //////////////////////////////////// // Load temporary key from AEAD input //////////////////////////////////// #define YSM_TEMP_KEY_LOAD 0x11 typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce uint32_t keyHandle; // Key handle to unlock AEAD uint8_t numBytes; // Number of bytes (explicit key size 16, 20, 24 or 32 bytes + flags + MAC) uint8_t aead[YSM_MAX_KEY_SIZE + sizeof(uint32_t) + YSM_AEAD_MAC_SIZE]; // AEAD block (including flags) } YSM_TEMP_KEY_LOAD_REQ; #define YSM_TEMP_KEY_LOADED (YSM_TEMP_KEY_LOAD | YSM_RESPONSE) typedef struct { uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce uint32_t keyHandle; // Key handle YSM_STATUS status; // Status } YSM_TEMP_KEY_LOAD_RESP; //////////////////////////////////// // Load data buffer with data //////////////////////////////////// #define YSM_BUFFER_LOAD 0x20 typedef struct { uint8_t offs; // Offset in buffer. Zero flushes/resets buffer first uint8_t numBytes; // Number of bytes to load uint8_t data[YSM_DATA_BUF_SIZE]; // Data to load } YSM_BUFFER_LOAD_REQ; #define YSM_BUFFER_LOADED (YSM_BUFFER_LOAD | YSM_RESPONSE) typedef struct { uint8_t numBytes; // Number of bytes in buffer now } YSM_BUFFER_LOAD_RESP; //////////////////////////////////// // Load data buffer with random data //////////////////////////////////// #define YSM_BUFFER_RANDOM_LOAD 0x21 typedef struct { uint8_t offs; // Offset in buffer. Zero flushes/resets buffer first uint8_t numBytes; // Number of bytes to randomize } YSM_BUFFER_RANDOM_LOAD_REQ; #define YSM_BUFFER_RANDOM_LOADED (YSM_BUFFER_RANDOM_LOAD | YSM_RESPONSE) typedef struct { uint8_t numBytes; // Number of bytes in buffer now } YSM_BUFFER_RANDOM_LOAD_RESP; //////////////////////////////////// // Get new unique nonce //////////////////////////////////// #define YSM_NONCE_GET 0x22 typedef struct { uint16_t postIncrement; // Step in post increment } YSM_NONCE_GET_REQ; #define YSM_NONCE_GOT (YSM_NONCE_GET | YSM_RESPONSE) typedef struct { YSM_STATUS status; // Status uint8_t nonce[YSM_AEAD_NONCE_SIZE]; // Nonce } YSM_NONCE_GET_RESP; //////////////////////////////////// // Echo (loopback test) //////////////////////////////////// #define YSM_ECHO 0x23 typedef struct { uint8_t numBytes; // Number of bytes in data field uint8_t data[YSM_MAX_PKT_SIZE - 1]; // Data } YSM_ECHO_REQ; #define YSM_ECHOED (YSM_ECHO | YSM_RESPONSE) typedef struct { uint8_t numBytes; // Number of bytes in data field uint8_t data[YSM_MAX_PKT_SIZE - 1]; // Data } YSM_ECHO_RESP; //////////////////////////////////// // Generate random number block(s) //////////////////////////////////// #define YSM_RANDOM_GENERATE 0x24 typedef struct { uint8_t numBytes; // Number of bytes to generate } YSM_RANDOM_GENERATE_REQ; #define YSM_RANDOM_GENERATED (YSM_RANDOM_GENERATE | YSM_RESPONSE) typedef struct { uint8_t numBytes; // Number of bytes generated uint8_t rnd[YSM_MAX_PKT_SIZE - 1]; // Random data } YSM_RANDOM_GENERATE_RESP; //////////////////////////////////// // Re-seed CTR-DRBG //////////////////////////////////// #define YSM_RANDOM_RESEED 0x25 typedef struct { uint8_t seed[YSM_CTR_DRBG_SEED_SIZE]; // New seed } YSM_RANDOM_RESEED_REQ; #define YSM_RANDOM_RESEEDED (YSM_RANDOM_RESEED | YSM_RESPONSE) typedef struct { YSM_STATUS status; // Status } YSM_RANDOM_RESEED_RESP; //////////////////////////////////// // System information query //////////////////////////////////// #define YSM_SYSTEM_INFO_QUERY 0x26 #define YSM_SYSTEM_INFO (YSM_SYSTEM_INFO_QUERY | YSM_RESPONSE) #define YSM_SYSTEM_UID_SIZE 12 // Sizeof unique identifier typedef struct { uint8_t versionMajor; // Major version # uint8_t versionMinor; // Minor version # uint8_t versionBuild; // Build version # uint8_t protocolVersion; // Protocol version # uint8_t systemUid[YSM_SYSTEM_UID_SIZE]; // System unique identifier } YSM_SYSTEM_INFO_RESP; //////////////////////////////////// // Unlock key handle based operations (version 0.x) //////////////////////////////////// #define YSM_KEY_STORAGE_UNLOCK 0x27 typedef struct { uint8_t password[YSM_BLOCK_SIZE]; // Unlock password } YSM_KEY_STORAGE_UNLOCK_REQ; #define YSM_KEY_STORAGE_UNLOCKED (YSM_KEY_STORAGE_UNLOCK | YSM_RESPONSE) typedef struct { YSM_STATUS status; // Unlock status } YSM_KEY_STORAGE_UNLOCK_RESP; //////////////////////////////////// // Unlock HSM mode of operation (version 1.x) //////////////////////////////////// #define YSM_HSM_UNLOCK 0x28 typedef struct { uint8_t publicId[YSM_PUBLIC_ID_SIZE]; // Public id uint8_t otp[YSM_OTP_SIZE]; // OTP } YSM_HSM_UNLOCK_REQ; #define YSM_HSM_UNLOCKED (YSM_HSM_UNLOCK | YSM_RESPONSE) typedef struct { YSM_STATUS status; // Unlock status } YSM_HSM_UNLOCK_RESP; //////////////////////////////////// // Decrypt key store //////////////////////////////////// #define YSM_KEY_STORE_DECRYPT 0x29 typedef struct { uint8_t key[YSM_MAX_KEY_SIZE]; // Key store decryption key } YSM_KEY_STORE_DECRYPT_REQ; #define YSM_KEY_STORE_DECRYPTED (YSM_KEY_STORE_DECRYPT | YSM_RESPONSE) typedef struct { YSM_STATUS status; // Unlock status } YSM_KEY_STORE_DECRYPT_RESP; //////////////////////////////////// // Exit HSM mode (debug mode only) //////////////////////////////////// #define YSM_MONITOR_EXIT 0x7f // Exit to monitor (no response sent) #define YSM_MONITOR_EXIT_MAGIC 0xbaadbeef typedef struct { uint32_t magic; // Magic number for trigger uint32_t magicInv; // 1st complement of magic } YSM_MONITOR_EXIT_REQ; #define YSM_EXTENDED_CMD_FIRST 0x60 #define YSM_EXTENDED_CMD_LAST 0x6f #endif // __YUBIHSM_H_INCLUDED python-pyhsm-1.0.4l/doc/YubiKey_KSM.adoc000066400000000000000000000076071256663164400200660ustar00rootroot00000000000000== YubiKey Key Storage Module using the YubiHSM === Introduction The YubiCloud architecture separates the online validation servers where queries are sent from the place where the actual secret YubiKey AES keys are stored. The KSM decrypts the YubiKey OTP using the AES key identified by the "public id" part of the OTP, and return the counter values of the OTP to the querying validation server, which decides if the OTP is valid or not. The application "yubikey-ksm" bundled with pyhsm is a KSM backend using the YubiHSM to further protect the AES keys. The interface exposed to the validation servers is a simple REST web interface, currently implemented using the BaseHTTPServer. It is inter- changeable with the original PHP based KSM found at https://developers.yubico.com/yubikey-ksm/ [WARNING] The server is currently single threaded, and uses a short timeout (5 seconds by default) to prevent blocking on bad requests (typically network problems between a validation server and a KSM). [NOTE] .Key handle You need to configure the YubiHSM connected to the KSM server with at least one key handle that has the YSM_AEAD_OTP_DECODE permission flag set. It is preferable to use a separate server (and YubiHSM) to create AEAD:s, in which case the other YubiHSM will have the same key handle with the same secret key, but with different permission flags (the appropriate YSM AEAD generate flags for the type of keys you use). === Installation on Debian/Ubuntu You can install the yhsm-yubikey-ksm from the package repositories : [source, sh] ---- $ sudo apt-get install yhsm-yubikey-ksm $ sudo $EDITOR /etc/default/yhsm-yubikey-ksm ---- === Non-Debian/Ubuntu installation instructions . Install pyhsm (see README in top level of pyhsm) . Install yhsm-yubikey-ksm into a suitable directory such as /usr/local/sbin/ . Run yhsm-yubikey-ksm --help to see what options are available. You will need to supply *--key-handles*, and possibly other parameters (verify --output-dir for example). === The AEAD files yhsm-yubikey-ksm is supposed to work with at least a couple of million YubiKeys (although the use of BaseHTTPServer might prove to be a bit too simplistic for a validation service of that magnitude, since it is not threaded). To keep things (such as adding new keys to a non-stop service) simple, and thereby hopefully robust, the initial scheme is to use the filesystem as database. We store the secrets of every YubiKey (22 bytes) in a separate file. The secrets are randomized and encrypted by a YubiHSM (preferably a separate one at a key provisioning site) so that they are protected from attackers even if they were to gain administrative access to the server/servers with YubiHSM's attached to them. The YubiHSM adds a MAC of 8 bytes to the 22 bytes secret data of the YubiKey, resulting in an AEAD of 30 bytes. This data is opaque by nature to everyone but the YubiHSM, since it is the only one with the key to decrypt the AEAD. Most filesystems start under-performing if you put a million files in a single directory. To avoid that, the AEAD file is hashed into a directory for each octet but the last one in the public ID. This ensures there will never be more than 256 AEAD files in each directory : .... public id key handle AEAD file ccbbddeeffcc 0x20 /var/cache/yubikey-ksm/aeads/0x20/cc/bb/dd/ee/ff/ccbbddeeffcc .... An important note for storing large numbers of AEAD files in a filesystem is that it will use up large numbers of inodes. Consideration for this should be taken into account when setting up the filesystem. === Importing YubiKey secrets If you had a YK-KSM server before getting a YubiHSM, use the export utility to export all the secrets into a text file of this format : .... ykksm 1 123456,ftftftcccccc,534543524554,fcacd309a20ce1809c2db257f0e8d6ea,000000000000,,, ... .... and then use the import utility /usr/sbin/yhsm-import-keys to create AEAD's for all YubiKey's listed in the text file. python-pyhsm-1.0.4l/doc/db_schema000066400000000000000000000002621256663164400167610ustar00rootroot00000000000000CREATE TABLE aead_table ( public_id varchar(16) NOT NULL, keyhandle INT NOT NULL, nonce BLOB(6) NOT NULL, aead BLOB(32) NOT NULL, PRIMARY KEY (public_id, keyhandle) ); python-pyhsm-1.0.4l/doc/html/000077500000000000000000000000001256663164400160755ustar00rootroot00000000000000python-pyhsm-1.0.4l/doc/html/api-objects.txt000066400000000000000000001210731256663164400210420ustar00rootroot00000000000000pyhsm pyhsm-module.html pyhsm.__organization__ pyhsm-module.html#__organization__ pyhsm.__package__ pyhsm-module.html#__package__ pyhsm.aead_cmd pyhsm.aead_cmd-module.html pyhsm.aead_cmd.YHSM_AEAD_File_Marker pyhsm.aead_cmd-module.html#YHSM_AEAD_File_Marker pyhsm.aead_cmd.__package__ pyhsm.aead_cmd-module.html#__package__ pyhsm.aes_ecb_cmd pyhsm.aes_ecb_cmd-module.html pyhsm.aes_ecb_cmd.__package__ pyhsm.aes_ecb_cmd-module.html#__package__ pyhsm.base pyhsm.base-module.html pyhsm.base.__package__ pyhsm.base-module.html#__package__ pyhsm.basic_cmd pyhsm.basic_cmd-module.html pyhsm.basic_cmd.__package__ pyhsm.basic_cmd-module.html#__package__ pyhsm.buffer_cmd pyhsm.buffer_cmd-module.html pyhsm.buffer_cmd.__package__ pyhsm.buffer_cmd-module.html#__package__ pyhsm.cmd pyhsm.cmd-module.html pyhsm.cmd.reset pyhsm.cmd-module.html#reset pyhsm.cmd.__package__ pyhsm.cmd-module.html#__package__ pyhsm.db_cmd pyhsm.db_cmd-module.html pyhsm.db_cmd.__package__ pyhsm.db_cmd-module.html#__package__ pyhsm.debug_cmd pyhsm.debug_cmd-module.html pyhsm.debug_cmd.__package__ pyhsm.debug_cmd-module.html#__package__ pyhsm.defines pyhsm.defines-module.html pyhsm.defines.YSM_AEAD_INVALID pyhsm.defines-module.html#YSM_AEAD_INVALID pyhsm.defines.YSM_AEAD_YUBIKEY_OTP_DECODE pyhsm.defines-module.html#YSM_AEAD_YUBIKEY_OTP_DECODE pyhsm.defines.YSM_AES_ECB_BLOCK_ENCRYPT pyhsm.defines-module.html#YSM_AES_ECB_BLOCK_ENCRYPT pyhsm.defines.YSM_HSM_UNLOCK pyhsm.defines-module.html#YSM_HSM_UNLOCK pyhsm.defines.YSM_NULL pyhsm.defines-module.html#YSM_NULL pyhsm.defines.YSM_KEY_HANDLE_INVALID pyhsm.defines-module.html#YSM_KEY_HANDLE_INVALID pyhsm.defines.YSM_OTP_REPLAY pyhsm.defines-module.html#YSM_OTP_REPLAY pyhsm.defines.YSM_SYSTEM_INFO_QUERY pyhsm.defines-module.html#YSM_SYSTEM_INFO_QUERY pyhsm.defines.YSM_DATA_BUF_SIZE pyhsm.defines-module.html#YSM_DATA_BUF_SIZE pyhsm.defines.YSM_BUFFER_RANDOM_LOAD pyhsm.defines-module.html#YSM_BUFFER_RANDOM_LOAD pyhsm.defines.YSM_MAX_PKT_SIZE pyhsm.defines-module.html#YSM_MAX_PKT_SIZE pyhsm.defines.YSM_AEAD_MAX_SIZE pyhsm.defines-module.html#YSM_AEAD_MAX_SIZE pyhsm.defines.YSM_AEAD_NONCE_SIZE pyhsm.defines-module.html#YSM_AEAD_NONCE_SIZE pyhsm.defines.YSM_KEY_STORAGE_LOCKED pyhsm.defines-module.html#YSM_KEY_STORAGE_LOCKED pyhsm.defines.KEY_SIZE pyhsm.defines-module.html#KEY_SIZE pyhsm.defines.YSM_MISMATCH pyhsm.defines-module.html#YSM_MISMATCH pyhsm.defines.YSM_OTP_INVALID pyhsm.defines-module.html#YSM_OTP_INVALID pyhsm.defines.YSM_AES_ECB_BLOCK_DECRYPT pyhsm.defines-module.html#YSM_AES_ECB_BLOCK_DECRYPT pyhsm.defines.YSM_ID_DUPLICATE pyhsm.defines-module.html#YSM_ID_DUPLICATE pyhsm.defines.YSM_HMAC_SHA1_FINAL pyhsm.defines-module.html#YSM_HMAC_SHA1_FINAL pyhsm.defines.YSM_FUNCTION_DISABLED pyhsm.defines-module.html#YSM_FUNCTION_DISABLED pyhsm.defines.YSM_KEY_STORAGE_UNLOCK pyhsm.defines-module.html#YSM_KEY_STORAGE_UNLOCK pyhsm.defines.YSM_RESPONSE pyhsm.defines-module.html#YSM_RESPONSE pyhsm.defines.YSM_AEAD_GENERATE pyhsm.defines-module.html#YSM_AEAD_GENERATE pyhsm.defines.YSM_STATUS_OK pyhsm.defines-module.html#YSM_STATUS_OK pyhsm.defines.__package__ pyhsm.defines-module.html#__package__ pyhsm.defines.YSM_TEMP_KEY_HANDLE pyhsm.defines-module.html#YSM_TEMP_KEY_HANDLE pyhsm.defines.YSM_PUBLIC_ID_SIZE pyhsm.defines-module.html#YSM_PUBLIC_ID_SIZE pyhsm.defines.YSM_BUFFER_LOAD pyhsm.defines-module.html#YSM_BUFFER_LOAD pyhsm.defines.YSM_NONCE_GET pyhsm.defines-module.html#YSM_NONCE_GET pyhsm.defines.YSM_KEY_STORE_DECRYPT pyhsm.defines-module.html#YSM_KEY_STORE_DECRYPT pyhsm.defines.YSM_HMAC_SHA1_RESET pyhsm.defines-module.html#YSM_HMAC_SHA1_RESET pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE2 pyhsm.defines-module.html#YSM_DB_YUBIKEY_AEAD_STORE2 pyhsm.defines.UID_SIZE pyhsm.defines-module.html#UID_SIZE pyhsm.defines.YSM_INVALID_PARAMETER pyhsm.defines-module.html#YSM_INVALID_PARAMETER pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE pyhsm.defines-module.html#YSM_DB_YUBIKEY_AEAD_STORE pyhsm.defines.YSM_HMAC_SHA1_TO_BUFFER pyhsm.defines-module.html#YSM_HMAC_SHA1_TO_BUFFER pyhsm.defines.YSM_DB_OTP_VALIDATE pyhsm.defines-module.html#YSM_DB_OTP_VALIDATE pyhsm.defines.YSM_OTP_SIZE pyhsm.defines-module.html#YSM_OTP_SIZE pyhsm.defines.YSM_RANDOM_RESEED pyhsm.defines-module.html#YSM_RANDOM_RESEED pyhsm.defines.YSM_ECHO pyhsm.defines-module.html#YSM_ECHO pyhsm.defines.YSM_TEMP_KEY_LOAD pyhsm.defines-module.html#YSM_TEMP_KEY_LOAD pyhsm.defines.YSM_CCM_CTR_SIZE pyhsm.defines-module.html#YSM_CCM_CTR_SIZE pyhsm.defines.YSM_MEMORY_ERROR pyhsm.defines-module.html#YSM_MEMORY_ERROR pyhsm.defines.YSM_PROTOCOL_VERSION pyhsm.defines-module.html#YSM_PROTOCOL_VERSION pyhsm.defines.YSM_RANDOM_AEAD_GENERATE pyhsm.defines-module.html#YSM_RANDOM_AEAD_GENERATE pyhsm.defines.status2str pyhsm.defines-module.html#status2str pyhsm.defines.YSM_MAX_KEY_SIZE pyhsm.defines-module.html#YSM_MAX_KEY_SIZE pyhsm.defines.YSM_AEAD_MAC_SIZE pyhsm.defines-module.html#YSM_AEAD_MAC_SIZE pyhsm.defines.YSM_BUFFER_AEAD_GENERATE pyhsm.defines-module.html#YSM_BUFFER_AEAD_GENERATE pyhsm.defines.YSM_SHA1_HASH_SIZE pyhsm.defines-module.html#YSM_SHA1_HASH_SIZE pyhsm.defines.YSM_ID_NOT_FOUND pyhsm.defines-module.html#YSM_ID_NOT_FOUND pyhsm.defines.YSM_MONITOR_EXIT pyhsm.defines-module.html#YSM_MONITOR_EXIT pyhsm.defines.cmd2str pyhsm.defines-module.html#cmd2str pyhsm.defines.YSM_CTR_DRBG_SEED_SIZE pyhsm.defines-module.html#YSM_CTR_DRBG_SEED_SIZE pyhsm.defines.YSM_AEAD_DECRYPT_CMP pyhsm.defines-module.html#YSM_AEAD_DECRYPT_CMP pyhsm.defines.YSM_BLOCK_SIZE pyhsm.defines-module.html#YSM_BLOCK_SIZE pyhsm.defines.YSM_AES_ECB_BLOCK_DECRYPT_CMP pyhsm.defines-module.html#YSM_AES_ECB_BLOCK_DECRYPT_CMP pyhsm.defines.YSM_DB_FULL pyhsm.defines-module.html#YSM_DB_FULL pyhsm.defines.YSM_YUBIKEY_AEAD_SIZE pyhsm.defines-module.html#YSM_YUBIKEY_AEAD_SIZE pyhsm.defines.YSM_HMAC_SHA1_GENERATE pyhsm.defines-module.html#YSM_HMAC_SHA1_GENERATE pyhsm.defines.YSM_RANDOM_GENERATE pyhsm.defines-module.html#YSM_RANDOM_GENERATE pyhsm.exception pyhsm.exception-module.html pyhsm.exception.__package__ pyhsm.exception-module.html#__package__ pyhsm.hmac_cmd pyhsm.hmac_cmd-module.html pyhsm.hmac_cmd._raw_pack pyhsm.hmac_cmd-module.html#_raw_pack pyhsm.hmac_cmd.__package__ pyhsm.hmac_cmd-module.html#__package__ pyhsm.oath_hotp pyhsm.oath_hotp-module.html pyhsm.oath_hotp.truncate pyhsm.oath_hotp-module.html#truncate pyhsm.oath_hotp.__package__ pyhsm.oath_hotp-module.html#__package__ pyhsm.oath_hotp.search_for_oath_code pyhsm.oath_hotp-module.html#search_for_oath_code pyhsm.soft_hsm pyhsm.soft_hsm-module.html pyhsm.soft_hsm._xor_block pyhsm.soft_hsm-module.html#_xor_block pyhsm.soft_hsm._split_data pyhsm.soft_hsm-module.html#_split_data pyhsm.soft_hsm.aesCCM pyhsm.soft_hsm-module.html#aesCCM pyhsm.soft_hsm.__package__ pyhsm.soft_hsm-module.html#__package__ pyhsm.stick pyhsm.stick-module.html pyhsm.stick.__package__ pyhsm.stick-module.html#__package__ pyhsm.stick_client pyhsm.stick_client-module.html pyhsm.stick_client.unpack_data pyhsm.stick_client-module.html#unpack_data pyhsm.stick_client.pack_data pyhsm.stick_client-module.html#pack_data pyhsm.stick_client.CMD_FLUSH pyhsm.stick_client-module.html#CMD_FLUSH pyhsm.stick_client.CMD_DRAIN pyhsm.stick_client-module.html#CMD_DRAIN pyhsm.stick_client.DEVICE_PATTERN pyhsm.stick_client-module.html#DEVICE_PATTERN pyhsm.stick_client.read_sock pyhsm.stick_client-module.html#read_sock pyhsm.stick_client.CMD_WRITE pyhsm.stick_client-module.html#CMD_WRITE pyhsm.stick_client.CMD_LOCK pyhsm.stick_client-module.html#CMD_LOCK pyhsm.stick_client.__package__ pyhsm.stick_client-module.html#__package__ pyhsm.stick_client.DEFAULT_PORT pyhsm.stick_client-module.html#DEFAULT_PORT pyhsm.stick_client.write_sock pyhsm.stick_client-module.html#write_sock pyhsm.stick_client.CMD_UNLOCK pyhsm.stick_client-module.html#CMD_UNLOCK pyhsm.stick_client.CMD_READ pyhsm.stick_client-module.html#CMD_READ pyhsm.util pyhsm.util-module.html pyhsm.util.input_validate_yubikey_secret pyhsm.util-module.html#input_validate_yubikey_secret pyhsm.util.input_validate_nonce pyhsm.util-module.html#input_validate_nonce pyhsm.util.hexdump pyhsm.util-module.html#hexdump pyhsm.util.group pyhsm.util-module.html#group pyhsm.util.validate_cmd_response_nonce pyhsm.util-module.html#validate_cmd_response_nonce pyhsm.util.input_validate_int pyhsm.util-module.html#input_validate_int pyhsm.util.input_validate_key_handle pyhsm.util-module.html#input_validate_key_handle pyhsm.util.key_handle_to_int pyhsm.util-module.html#key_handle_to_int pyhsm.util.__package__ pyhsm.util-module.html#__package__ pyhsm.util.validate_cmd_response_int pyhsm.util-module.html#validate_cmd_response_int pyhsm.util.input_validate_str pyhsm.util-module.html#input_validate_str pyhsm.util.validate_cmd_response_str pyhsm.util-module.html#validate_cmd_response_str pyhsm.util.validate_cmd_response_hex pyhsm.util-module.html#validate_cmd_response_hex pyhsm.util.input_validate_aead pyhsm.util-module.html#input_validate_aead pyhsm.validate_cmd pyhsm.validate_cmd-module.html pyhsm.validate_cmd.__package__ pyhsm.validate_cmd-module.html#__package__ pyhsm.version pyhsm.version-module.html pyhsm.version.__package__ pyhsm.version-module.html#__package__ pyhsm.yubikey pyhsm.yubikey-module.html pyhsm.yubikey.validate_otp pyhsm.yubikey-module.html#validate_otp pyhsm.yubikey.validate_yubikey_with_aead pyhsm.yubikey-module.html#validate_yubikey_with_aead pyhsm.yubikey.__package__ pyhsm.yubikey-module.html#__package__ pyhsm.yubikey.split_id_otp pyhsm.yubikey-module.html#split_id_otp pyhsm.yubikey.modhex_decode pyhsm.yubikey-module.html#modhex_decode pyhsm.yubikey.modhex_encode pyhsm.yubikey-module.html#modhex_encode pyhsm.aead_cmd.YHSM_AEAD_Cmd pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html pyhsm.aead_cmd.YHSM_AEAD_Cmd.nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd.status pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.aead_cmd.YHSM_AEAD_Cmd.key_handle pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#key_handle pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.aead_cmd.YHSM_AEAD_Cmd.__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.response pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#response pyhsm.cmd.YHSM_Cmd.__init__ pyhsm.cmd.YHSM_Cmd-class.html#__init__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.parse_result pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#parse_result pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate-class.html pyhsm.aead_cmd.YHSM_AEAD_Cmd.nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd.status pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.aead_cmd.YHSM_AEAD_Cmd.key_handle pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#key_handle pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.aead_cmd.YHSM_AEAD_Cmd.__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.response pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#response pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate.__init__ pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate-class.html#__init__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.parse_result pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#parse_result pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp.status pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp.__init__ pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html#__init__ pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp.parse_result pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html#parse_result pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate-class.html pyhsm.aead_cmd.YHSM_AEAD_Cmd.nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd.status pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.aead_cmd.YHSM_AEAD_Cmd.key_handle pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#key_handle pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.aead_cmd.YHSM_AEAD_Cmd.__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.response pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#response pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate.__init__ pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate-class.html#__init__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.parse_result pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#parse_result pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate-class.html pyhsm.aead_cmd.YHSM_AEAD_Cmd.nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd.status pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.aead_cmd.YHSM_AEAD_Cmd.key_handle pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#key_handle pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.aead_cmd.YHSM_AEAD_Cmd.__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.response pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#response pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate.__init__ pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate-class.html#__init__ pyhsm.aead_cmd.YHSM_AEAD_Cmd.parse_result pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#parse_result pyhsm.aead_cmd.YHSM_GeneratedAEAD pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html pyhsm.aead_cmd.YHSM_GeneratedAEAD.load pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html#load pyhsm.aead_cmd.YHSM_GeneratedAEAD.save pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html#save pyhsm.aead_cmd.YHSM_GeneratedAEAD.__repr__ pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html#__repr__ pyhsm.aead_cmd.YHSM_GeneratedAEAD.__init__ pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html#__init__ pyhsm.aead_cmd.YHSM_YubiKeySecret pyhsm.aead_cmd.YHSM_YubiKeySecret-class.html pyhsm.aead_cmd.YHSM_YubiKeySecret.__init__ pyhsm.aead_cmd.YHSM_YubiKeySecret-class.html#__init__ pyhsm.aead_cmd.YHSM_YubiKeySecret.pack pyhsm.aead_cmd.YHSM_YubiKeySecret-class.html#pack pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare.__init__ pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare-class.html#__init__ pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare.parse_result pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare-class.html#parse_result pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt.__init__ pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt-class.html#__init__ pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt.__init__ pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt-class.html#__init__ pyhsm.base.YHSM pyhsm.base.YHSM-class.html pyhsm.base.YHSM.test_comm pyhsm.base.YHSM-class.html#test_comm pyhsm.base.YHSM.random pyhsm.base.YHSM-class.html#random pyhsm.base.YHSM.echo pyhsm.base.YHSM-class.html#echo pyhsm.base.YHSM.key_storage_unlock pyhsm.base.YHSM-class.html#key_storage_unlock pyhsm.base.YHSM.unlock pyhsm.base.YHSM-class.html#unlock pyhsm.base.YHSM.get_nonce pyhsm.base.YHSM-class.html#get_nonce pyhsm.base.YHSM.__init__ pyhsm.base.YHSM-class.html#__init__ pyhsm.base.YHSM.set_debug pyhsm.base.YHSM-class.html#set_debug pyhsm.base.YHSM.aes_ecb_decrypt pyhsm.base.YHSM-class.html#aes_ecb_decrypt pyhsm.base.YHSM.load_temp_key pyhsm.base.YHSM-class.html#load_temp_key pyhsm.base.YHSM.generate_aead_random pyhsm.base.YHSM-class.html#generate_aead_random pyhsm.base.YHSM.validate_aead pyhsm.base.YHSM-class.html#validate_aead pyhsm.base.YHSM.reset pyhsm.base.YHSM-class.html#reset pyhsm.base.YHSM.validate_aead_otp pyhsm.base.YHSM-class.html#validate_aead_otp pyhsm.base.YHSM.load_secret pyhsm.base.YHSM-class.html#load_secret pyhsm.base.YHSM.load_random pyhsm.base.YHSM-class.html#load_random pyhsm.base.YHSM.generate_aead pyhsm.base.YHSM-class.html#generate_aead pyhsm.base.YHSM.aes_ecb_compare pyhsm.base.YHSM-class.html#aes_ecb_compare pyhsm.base.YHSM.hmac_sha1 pyhsm.base.YHSM-class.html#hmac_sha1 pyhsm.base.YHSM.db_store_yubikey pyhsm.base.YHSM-class.html#db_store_yubikey pyhsm.base.YHSM.random_reseed pyhsm.base.YHSM-class.html#random_reseed pyhsm.base.YHSM.aes_ecb_encrypt pyhsm.base.YHSM-class.html#aes_ecb_encrypt pyhsm.base.YHSM.info pyhsm.base.YHSM-class.html#info pyhsm.base.YHSM.drain pyhsm.base.YHSM-class.html#drain pyhsm.base.YHSM.monitor_exit pyhsm.base.YHSM-class.html#monitor_exit pyhsm.base.YHSM.db_validate_yubikey_otp pyhsm.base.YHSM-class.html#db_validate_yubikey_otp pyhsm.base.YHSM.load_data pyhsm.base.YHSM-class.html#load_data pyhsm.base.YHSM.get_raw_device pyhsm.base.YHSM-class.html#get_raw_device pyhsm.base.YHSM.generate_aead_simple pyhsm.base.YHSM-class.html#generate_aead_simple pyhsm.base.YHSM.__repr__ pyhsm.base.YHSM-class.html#__repr__ pyhsm.basic_cmd.YHSM_Cmd_Echo pyhsm.basic_cmd.YHSM_Cmd_Echo-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Echo.__init__ pyhsm.basic_cmd.YHSM_Cmd_Echo-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Echo.parse_result pyhsm.basic_cmd.YHSM_Cmd_Echo-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock.status pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock.__init__ pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock.parse_result pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock.status pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock.__init__ pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock.parse_result pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt.status pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt.__init__ pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt.parse_result pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get.status pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get.response pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html#response pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get.__init__ pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get.parse_result pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Random pyhsm.basic_cmd.YHSM_Cmd_Random-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Random.__init__ pyhsm.basic_cmd.YHSM_Cmd_Random-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Random.parse_result pyhsm.basic_cmd.YHSM_Cmd_Random-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed.status pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed.__init__ pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed.parse_result pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_System_Info pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html pyhsm.basic_cmd.YHSM_Cmd_System_Info.system_uid pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#system_uid pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.basic_cmd.YHSM_Cmd_System_Info.version_major pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#version_major pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.basic_cmd.YHSM_Cmd_System_Info.protocol_ver pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#protocol_ver pyhsm.basic_cmd.YHSM_Cmd_System_Info.version_build pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#version_build pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.basic_cmd.YHSM_Cmd_System_Info.__repr__ pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#__repr__ pyhsm.basic_cmd.YHSM_Cmd_System_Info.version_minor pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#version_minor pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_System_Info.__init__ pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_System_Info.parse_result pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html#parse_result pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load.status pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load.__init__ pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html#__init__ pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load.parse_result pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html#parse_result pyhsm.basic_cmd.YHSM_NonceResponse pyhsm.basic_cmd.YHSM_NonceResponse-class.html pyhsm.basic_cmd.YHSM_NonceResponse.nonce pyhsm.basic_cmd.YHSM_NonceResponse-class.html#nonce pyhsm.basic_cmd.YHSM_NonceResponse.nonce_int pyhsm.basic_cmd.YHSM_NonceResponse-class.html#nonce_int pyhsm.basic_cmd.YHSM_NonceResponse.volatile pyhsm.basic_cmd.YHSM_NonceResponse-class.html#volatile pyhsm.basic_cmd.YHSM_NonceResponse.__repr__ pyhsm.basic_cmd.YHSM_NonceResponse-class.html#__repr__ pyhsm.basic_cmd.YHSM_NonceResponse.pu_count pyhsm.basic_cmd.YHSM_NonceResponse-class.html#pu_count pyhsm.basic_cmd.YHSM_NonceResponse.__init__ pyhsm.basic_cmd.YHSM_NonceResponse-class.html#__init__ pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load.offset pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html#offset pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load.offest pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html#offest pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load.data_len pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html#data_len pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load.__init__ pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html#__init__ pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load.parse_result pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html#parse_result pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load.__init__ pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load-class.html#__init__ pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load.parse_result pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load-class.html#parse_result pyhsm.cmd.YHSM_Cmd pyhsm.cmd.YHSM_Cmd-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd.__init__ pyhsm.cmd.YHSM_Cmd-class.html#__init__ pyhsm.cmd.YHSM_Cmd.parse_result pyhsm.cmd.YHSM_Cmd-class.html#parse_result pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.status pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.__repr__ pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html#__repr__ pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.response pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html#response pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.__init__ pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html#__init__ pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP.parse_result pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html#parse_result pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store.status pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store.__init__ pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html#__init__ pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store.parse_result pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html#parse_result pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit-class.html pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit.__init__ pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit-class.html#__init__ pyhsm.cmd.YHSM_Cmd.parse_result pyhsm.cmd.YHSM_Cmd-class.html#parse_result pyhsm.exception.YHSM_CommandFailed pyhsm.exception.YHSM_CommandFailed-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_CommandFailed.__init__ pyhsm.exception.YHSM_CommandFailed-class.html#__init__ pyhsm.exception.YHSM_Error pyhsm.exception.YHSM_Error-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_Error.__init__ pyhsm.exception.YHSM_Error-class.html#__init__ pyhsm.exception.YHSM_InputTooLong pyhsm.exception.YHSM_InputTooLong-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_InputTooLong.__init__ pyhsm.exception.YHSM_InputTooLong-class.html#__init__ pyhsm.exception.YHSM_InputTooShort pyhsm.exception.YHSM_InputTooShort-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_InputTooShort.__init__ pyhsm.exception.YHSM_InputTooShort-class.html#__init__ pyhsm.exception.YHSM_WrongInputSize pyhsm.exception.YHSM_WrongInputSize-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_WrongInputSize.__init__ pyhsm.exception.YHSM_WrongInputSize-class.html#__init__ pyhsm.exception.YHSM_WrongInputType pyhsm.exception.YHSM_WrongInputType-class.html pyhsm.exception.YHSM_Error.__str__ pyhsm.exception.YHSM_Error-class.html#__str__ pyhsm.exception.YHSM_Error.reason pyhsm.exception.YHSM_Error-class.html#reason pyhsm.exception.YHSM_WrongInputType.__init__ pyhsm.exception.YHSM_WrongInputType-class.html#__init__ pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.status pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#status pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.__repr__ pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#__repr__ pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.get_hash pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#get_hash pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.result pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#result pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.next pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#next pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.__init__ pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#__init__ pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.parse_result pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html#parse_result pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1 pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1-class.html pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1.__repr__ pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1-class.html#__repr__ pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1.__init__ pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1-class.html#__init__ pyhsm.stick.YHSM_Stick pyhsm.stick.YHSM_Stick-class.html pyhsm.stick.YHSM_Stick.raw_device pyhsm.stick.YHSM_Stick-class.html#raw_device pyhsm.stick.YHSM_Stick.drain pyhsm.stick.YHSM_Stick-class.html#drain pyhsm.stick.YHSM_Stick.read pyhsm.stick.YHSM_Stick-class.html#read pyhsm.stick.YHSM_Stick.set_debug pyhsm.stick.YHSM_Stick-class.html#set_debug pyhsm.stick.YHSM_Stick.acquire pyhsm.stick.YHSM_Stick-class.html#acquire pyhsm.stick.YHSM_Stick.write pyhsm.stick.YHSM_Stick-class.html#write pyhsm.stick.YHSM_Stick.__del__ pyhsm.stick.YHSM_Stick-class.html#__del__ pyhsm.stick.YHSM_Stick.__repr__ pyhsm.stick.YHSM_Stick-class.html#__repr__ pyhsm.stick.YHSM_Stick.flush pyhsm.stick.YHSM_Stick-class.html#flush pyhsm.stick.YHSM_Stick.__init__ pyhsm.stick.YHSM_Stick-class.html#__init__ pyhsm.stick_client.YHSM_Stick_Client pyhsm.stick_client.YHSM_Stick_Client-class.html pyhsm.stick_client.YHSM_Stick_Client.raw_device pyhsm.stick_client.YHSM_Stick_Client-class.html#raw_device pyhsm.stick_client.YHSM_Stick_Client.drain pyhsm.stick_client.YHSM_Stick_Client-class.html#drain pyhsm.stick_client.YHSM_Stick_Client.read pyhsm.stick_client.YHSM_Stick_Client-class.html#read pyhsm.stick_client.YHSM_Stick_Client.set_debug pyhsm.stick_client.YHSM_Stick_Client-class.html#set_debug pyhsm.stick_client.YHSM_Stick_Client.acquire pyhsm.stick_client.YHSM_Stick_Client-class.html#acquire pyhsm.stick_client.YHSM_Stick_Client.write pyhsm.stick_client.YHSM_Stick_Client-class.html#write pyhsm.stick_client.YHSM_Stick_Client.__del__ pyhsm.stick_client.YHSM_Stick_Client-class.html#__del__ pyhsm.stick_client.YHSM_Stick_Client.__repr__ pyhsm.stick_client.YHSM_Stick_Client-class.html#__repr__ pyhsm.stick_client.YHSM_Stick_Client.flush pyhsm.stick_client.YHSM_Stick_Client-class.html#flush pyhsm.stick_client.YHSM_Stick_Client.release pyhsm.stick_client.YHSM_Stick_Client-class.html#release pyhsm.stick_client.YHSM_Stick_Client.__init__ pyhsm.stick_client.YHSM_Stick_Client-class.html#__init__ pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP.status pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html#status pyhsm.aead_cmd.YHSM_AEAD_Cmd.nonce pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#nonce pyhsm.cmd.YHSM_Cmd.execute pyhsm.cmd.YHSM_Cmd-class.html#execute pyhsm.cmd.YHSM_Cmd.executed pyhsm.cmd.YHSM_Cmd-class.html#executed pyhsm.aead_cmd.YHSM_AEAD_Cmd.key_handle pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#key_handle pyhsm.cmd.YHSM_Cmd.response_status pyhsm.cmd.YHSM_Cmd-class.html#response_status pyhsm.cmd.YHSM_Cmd._read_response pyhsm.cmd.YHSM_Cmd-class.html#_read_response pyhsm.cmd.YHSM_Cmd._handle_invalid_read_response pyhsm.cmd.YHSM_Cmd-class.html#_handle_invalid_read_response pyhsm.aead_cmd.YHSM_AEAD_Cmd.__repr__ pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html#__repr__ pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP.response pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html#response pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP.__init__ pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html#__init__ pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP.parse_result pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html#parse_result pyhsm.validate_cmd.YHSM_ValidationResult pyhsm.validate_cmd.YHSM_ValidationResult-class.html pyhsm.validate_cmd.YHSM_ValidationResult.public_id pyhsm.validate_cmd.YHSM_ValidationResult-class.html#public_id pyhsm.validate_cmd.YHSM_ValidationResult.use_ctr pyhsm.validate_cmd.YHSM_ValidationResult-class.html#use_ctr pyhsm.validate_cmd.YHSM_ValidationResult.session_ctr pyhsm.validate_cmd.YHSM_ValidationResult-class.html#session_ctr pyhsm.validate_cmd.YHSM_ValidationResult.ts_low pyhsm.validate_cmd.YHSM_ValidationResult-class.html#ts_low pyhsm.validate_cmd.YHSM_ValidationResult.ts_high pyhsm.validate_cmd.YHSM_ValidationResult-class.html#ts_high pyhsm.validate_cmd.YHSM_ValidationResult.__init__ pyhsm.validate_cmd.YHSM_ValidationResult-class.html#__init__ pyhsm.validate_cmd.YHSM_ValidationResult.__repr__ pyhsm.validate_cmd.YHSM_ValidationResult-class.html#__repr__ pyhsm.version.YHSM_Version pyhsm.version.YHSM_Version-class.html pyhsm.version.YHSM_Version.have_key_store_decrypt pyhsm.version.YHSM_Version-class.html#have_key_store_decrypt pyhsm.version.YHSM_Version.have_keydisable pyhsm.version.YHSM_Version-class.html#have_keydisable pyhsm.version.YHSM_Version.have_YSM_BUFFER_LOAD pyhsm.version.YHSM_Version-class.html#have_YSM_BUFFER_LOAD pyhsm.version.YHSM_Version.have_key_storage_unlock pyhsm.version.YHSM_Version-class.html#have_key_storage_unlock pyhsm.version.YHSM_Version.have_unlock pyhsm.version.YHSM_Version-class.html#have_unlock pyhsm.version.YHSM_Version.have_keycommit pyhsm.version.YHSM_Version-class.html#have_keycommit pyhsm.version.YHSM_Version.sysinfo pyhsm.version.YHSM_Version-class.html#sysinfo pyhsm.version.YHSM_Version.have_YSM_DB_YUBIKEY_AEAD_STORE2 pyhsm.version.YHSM_Version-class.html#have_YSM_DB_YUBIKEY_AEAD_STORE2 pyhsm.version.YHSM_Version.__init__ pyhsm.version.YHSM_Version-class.html#__init__ python-pyhsm-1.0.4l/doc/html/class-tree.html000066400000000000000000000340011256663164400210230ustar00rootroot00000000000000 Class Hierarchy
 
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Class Hierarchy

python-pyhsm-1.0.4l/doc/html/crarr.png000066400000000000000000000005241256663164400177150ustar00rootroot00000000000000PNG  IHDR eE,tEXtCreation TimeTue 22 Aug 2006 00:43:10 -0500` XtIME)} pHYsnu>gAMA aEPLTEðf4sW ЊrD`@bCܖX{`,lNo@xdE螊dƴ~TwvtRNS@fMIDATxc`@0&+(;; /EXؑ? n  b;'+Y#(r<"IENDB`python-pyhsm-1.0.4l/doc/html/deprecated-index.html000066400000000000000000000076511256663164400222010ustar00rootroot00000000000000 Deprecation List
 
[frames] | no frames]
[ Identifiers | Deprecations ]

Deprecation List



python-pyhsm-1.0.4l/doc/html/epydoc.css000066400000000000000000000372271256663164400201050ustar00rootroot00000000000000 /* Epydoc CSS Stylesheet * * This stylesheet can be used to customize the appearance of epydoc's * HTML output. * */ /* Default Colors & Styles * - Set the default foreground & background color with 'body'; and * link colors with 'a:link' and 'a:visited'. * - Use bold for decision list terms. * - The heading styles defined here are used for headings *within* * docstring descriptions. All headings used by epydoc itself use * either class='epydoc' or class='toc' (CSS styles for both * defined below). */ body { background: #ffffff; color: #000000; } p { margin-top: 0.5em; margin-bottom: 0.5em; } a:link { color: #0000ff; } a:visited { color: #204080; } dt { font-weight: bold; } h1 { font-size: +140%; font-style: italic; font-weight: bold; } h2 { font-size: +125%; font-style: italic; font-weight: bold; } h3 { font-size: +110%; font-style: italic; font-weight: normal; } code { font-size: 100%; } /* N.B.: class, not pseudoclass */ a.link { font-family: monospace; } /* Page Header & Footer * - The standard page header consists of a navigation bar (with * pointers to standard pages such as 'home' and 'trees'); a * breadcrumbs list, which can be used to navigate to containing * classes or modules; options links, to show/hide private * variables and to show/hide frames; and a page title (using *

). The page title may be followed by a link to the * corresponding source code (using 'span.codelink'). * - The footer consists of a navigation bar, a timestamp, and a * pointer to epydoc's homepage. */ h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; } h2.epydoc { font-size: +130%; font-weight: bold; } h3.epydoc { font-size: +115%; font-weight: bold; margin-top: 0.2em; } td h3.epydoc { font-size: +115%; font-weight: bold; margin-bottom: 0; } table.navbar { background: #a0c0ff; color: #000000; border: 2px groove #c0d0d0; } table.navbar table { color: #000000; } th.navbar-select { background: #70b0ff; color: #000000; } table.navbar a { text-decoration: none; } table.navbar a:link { color: #0000ff; } table.navbar a:visited { color: #204080; } span.breadcrumbs { font-size: 85%; font-weight: bold; } span.options { font-size: 70%; } span.codelink { font-size: 85%; } td.footer { font-size: 85%; } /* Table Headers * - Each summary table and details section begins with a 'header' * row. This row contains a section title (marked by * 'span.table-header') as well as a show/hide private link * (marked by 'span.options', defined above). * - Summary tables that contain user-defined groups mark those * groups using 'group header' rows. */ td.table-header { background: #70b0ff; color: #000000; border: 1px solid #608090; } td.table-header table { color: #000000; } td.table-header table a:link { color: #0000ff; } td.table-header table a:visited { color: #204080; } span.table-header { font-size: 120%; font-weight: bold; } th.group-header { background: #c0e0f8; color: #000000; text-align: left; font-style: italic; font-size: 115%; border: 1px solid #608090; } /* Summary Tables (functions, variables, etc) * - Each object is described by a single row of the table with * two cells. The left cell gives the object's type, and is * marked with 'code.summary-type'. The right cell gives the * object's name and a summary description. * - CSS styles for the table's header and group headers are * defined above, under 'Table Headers' */ table.summary { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin-bottom: 0.5em; } td.summary { border: 1px solid #608090; } code.summary-type { font-size: 85%; } table.summary a:link { color: #0000ff; } table.summary a:visited { color: #204080; } /* Details Tables (functions, variables, etc) * - Each object is described in its own div. * - A single-row summary table w/ table-header is used as * a header for each details section (CSS style for table-header * is defined above, under 'Table Headers'). */ table.details { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } table.details table { color: #000000; } table.details a:link { color: #0000ff; } table.details a:visited { color: #204080; } /* Fields */ dl.fields { margin-left: 2em; margin-top: 1em; margin-bottom: 1em; } dl.fields dd ul { margin-left: 0em; padding-left: 0em; } dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; } div.fields { margin-left: 2em; } div.fields p { margin-bottom: 0.5em; } /* Index tables (identifier index, term index, etc) * - link-index is used for indices containing lists of links * (namely, the identifier index & term index). * - index-where is used in link indices for the text indicating * the container/source for each link. * - metadata-index is used for indices containing metadata * extracted from fields (namely, the bug index & todo index). */ table.link-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; } td.link-index { border-width: 0px; } table.link-index a:link { color: #0000ff; } table.link-index a:visited { color: #204080; } span.index-where { font-size: 70%; } table.metadata-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } td.metadata-index { border-width: 1px; border-style: solid; } table.metadata-index a:link { color: #0000ff; } table.metadata-index a:visited { color: #204080; } /* Function signatures * - sig* is used for the signature in the details section. * - .summary-sig* is used for the signature in the summary * table, and when listing property accessor functions. * */ .sig-name { color: #006080; } .sig-arg { color: #008060; } .sig-default { color: #602000; } .summary-sig { font-family: monospace; } .summary-sig-name { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:link { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:visited { color: #006080; font-weight: bold; } .summary-sig-arg { color: #006040; } .summary-sig-default { color: #501800; } /* Subclass list */ ul.subclass-list { display: inline; } ul.subclass-list li { display: inline; } /* To render variables, classes etc. like functions */ table.summary .summary-name { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:link { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:visited { color: #006080; font-weight: bold; font-family: monospace; } /* Variable values * - In the 'variable details' sections, each varaible's value is * listed in a 'pre.variable' box. The width of this box is * restricted to 80 chars; if the value's repr is longer than * this it will be wrapped, using a backslash marked with * class 'variable-linewrap'. If the value's repr is longer * than 3 lines, the rest will be ellided; and an ellipsis * marker ('...' marked with 'variable-ellipsis') will be used. * - If the value is a string, its quote marks will be marked * with 'variable-quote'. * - If the variable is a regexp, it is syntax-highlighted using * the re* CSS classes. */ pre.variable { padding: .5em; margin: 0; background: #dce4ec; color: #000000; border: 1px solid #708890; } .variable-linewrap { color: #604000; font-weight: bold; } .variable-ellipsis { color: #604000; font-weight: bold; } .variable-quote { color: #604000; font-weight: bold; } .variable-group { color: #008000; font-weight: bold; } .variable-op { color: #604000; font-weight: bold; } .variable-string { color: #006030; } .variable-unknown { color: #a00000; font-weight: bold; } .re { color: #000000; } .re-char { color: #006030; } .re-op { color: #600000; } .re-group { color: #003060; } .re-ref { color: #404040; } /* Base tree * - Used by class pages to display the base class hierarchy. */ pre.base-tree { font-size: 80%; margin: 0; } /* Frames-based table of contents headers * - Consists of two frames: one for selecting modules; and * the other listing the contents of the selected module. * - h1.toc is used for each frame's heading * - h2.toc is used for subheadings within each frame. */ h1.toc { text-align: center; font-size: 105%; margin: 0; font-weight: bold; padding: 0; } h2.toc { font-size: 100%; font-weight: bold; margin: 0.5em 0 0 -0.3em; } /* Syntax Highlighting for Source Code * - doctest examples are displayed in a 'pre.py-doctest' block. * If the example is in a details table entry, then it will use * the colors specified by the 'table pre.py-doctest' line. * - Source code listings are displayed in a 'pre.py-src' block. * Each line is marked with 'span.py-line' (used to draw a line * down the left margin, separating the code from the line * numbers). Line numbers are displayed with 'span.py-lineno'. * The expand/collapse block toggle button is displayed with * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not * modify the font size of the text.) * - If a source code page is opened with an anchor, then the * corresponding code block will be highlighted. The code * block's header is highlighted with 'py-highlight-hdr'; and * the code block's body is highlighted with 'py-highlight'. * - The remaining py-* classes are used to perform syntax * highlighting (py-string for string literals, py-name for names, * etc.) */ pre.py-doctest { padding: .5em; margin: 1em; background: #e8f0f8; color: #000000; border: 1px solid #708890; } table pre.py-doctest { background: #dce4ec; color: #000000; } pre.py-src { border: 2px solid #000000; background: #f0f0f0; color: #000000; } .py-line { border-left: 2px solid #000000; margin-left: .2em; padding-left: .4em; } .py-lineno { font-style: italic; font-size: 90%; padding-left: .5em; } a.py-toggle { text-decoration: none; } div.py-highlight-hdr { border-top: 2px solid #000000; border-bottom: 2px solid #000000; background: #d8e8e8; } div.py-highlight { border-bottom: 2px solid #000000; background: #d0e0e0; } .py-prompt { color: #005050; font-weight: bold;} .py-more { color: #005050; font-weight: bold;} .py-string { color: #006030; } .py-comment { color: #003060; } .py-keyword { color: #600000; } .py-output { color: #404040; } .py-name { color: #000050; } .py-name:link { color: #000050 !important; } .py-name:visited { color: #000050 !important; } .py-number { color: #005000; } .py-defname { color: #000060; font-weight: bold; } .py-def-name { color: #000060; font-weight: bold; } .py-base-class { color: #000060; } .py-param { color: #000060; } .py-docstring { color: #006030; } .py-decorator { color: #804020; } /* Use this if you don't want links to names underlined: */ /*a.py-name { text-decoration: none; }*/ /* Graphs & Diagrams * - These CSS styles are used for graphs & diagrams generated using * Graphviz dot. 'img.graph-without-title' is used for bare * diagrams (to remove the border created by making the image * clickable). */ img.graph-without-title { border: none; } img.graph-with-title { border: 1px solid #000000; } span.graph-title { font-weight: bold; } span.graph-caption { } /* General-purpose classes * - 'p.indent-wrapped-lines' defines a paragraph whose first line * is not indented, but whose subsequent lines are. * - The 'nomargin-top' class is used to remove the top margin (e.g. * from lists). The 'nomargin' class is used to remove both the * top and bottom margin (but not the left or right margin -- * for lists, that would cause the bullets to disappear.) */ p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em; margin: 0; } .nomargin-top { margin-top: 0; } .nomargin { margin-top: 0; margin-bottom: 0; } /* HTML Log */ div.log-block { padding: 0; margin: .5em 0 .5em 0; background: #e8f0f8; color: #000000; border: 1px solid #000000; } div.log-error { padding: .1em .3em .1em .3em; margin: 4px; background: #ffb0b0; color: #000000; border: 1px solid #000000; } div.log-warning { padding: .1em .3em .1em .3em; margin: 4px; background: #ffffb0; color: #000000; border: 1px solid #000000; } div.log-info { padding: .1em .3em .1em .3em; margin: 4px; background: #b0ffb0; color: #000000; border: 1px solid #000000; } h2.log-hdr { background: #70b0ff; color: #000000; margin: 0; padding: 0em 0.5em 0em 0.5em; border-bottom: 1px solid #000000; font-size: 110%; } p.log { font-weight: bold; margin: .5em 0 .5em 0; } tr.opt-changed { color: #000000; font-weight: bold; } tr.opt-default { color: #606060; } pre.log { margin: 0; padding: 0; padding-left: 1em; } python-pyhsm-1.0.4l/doc/html/epydoc.js000066400000000000000000000245251256663164400177260ustar00rootroot00000000000000function toggle_private() { // Search for any private/public links on this page. Store // their old text in "cmd," so we will know what action to // take; and change their text to the opposite action. var cmd = "?"; var elts = document.getElementsByTagName("a"); for(var i=0; i...
"; elt.innerHTML = s; } } function toggle(id) { elt = document.getElementById(id+"-toggle"); if (elt.innerHTML == "-") collapse(id); else expand(id); return false; } function highlight(id) { var elt = document.getElementById(id+"-def"); if (elt) elt.className = "py-highlight-hdr"; var elt = document.getElementById(id+"-expanded"); if (elt) elt.className = "py-highlight"; var elt = document.getElementById(id+"-collapsed"); if (elt) elt.className = "py-highlight"; } function num_lines(s) { var n = 1; var pos = s.indexOf("\n"); while ( pos > 0) { n += 1; pos = s.indexOf("\n", pos+1); } return n; } // Collapse all blocks that mave more than `min_lines` lines. function collapse_all(min_lines) { var elts = document.getElementsByTagName("div"); for (var i=0; i 0) if (elt.id.substring(split, elt.id.length) == "-expanded") if (num_lines(elt.innerHTML) > min_lines) collapse(elt.id.substring(0, split)); } } function expandto(href) { var start = href.indexOf("#")+1; if (start != 0 && start != href.length) { if (href.substring(start, href.length) != "-") { collapse_all(4); pos = href.indexOf(".", start); while (pos != -1) { var id = href.substring(start, pos); expand(id); pos = href.indexOf(".", pos+1); } var id = href.substring(start, href.length); expand(id); highlight(id); } } } function kill_doclink(id) { var parent = document.getElementById(id); parent.removeChild(parent.childNodes.item(0)); } function auto_kill_doclink(ev) { if (!ev) var ev = window.event; if (!this.contains(ev.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } } function doclink(id, name, targets_id) { var elt = document.getElementById(id); // If we already opened the box, then destroy it. // (This case should never occur, but leave it in just in case.) if (elt.childNodes.length > 1) { elt.removeChild(elt.childNodes.item(0)); } else { // The outer box: relative + inline positioning. var box1 = document.createElement("div"); box1.style.position = "relative"; box1.style.display = "inline"; box1.style.top = 0; box1.style.left = 0; // A shadow for fun var shadow = document.createElement("div"); shadow.style.position = "absolute"; shadow.style.left = "-1.3em"; shadow.style.top = "-1.3em"; shadow.style.background = "#404040"; // The inner box: absolute positioning. var box2 = document.createElement("div"); box2.style.position = "relative"; box2.style.border = "1px solid #a0a0a0"; box2.style.left = "-.2em"; box2.style.top = "-.2em"; box2.style.background = "white"; box2.style.padding = ".3em .4em .3em .4em"; box2.style.fontStyle = "normal"; box2.onmouseout=auto_kill_doclink; box2.parentID = id; // Get the targets var targets_elt = document.getElementById(targets_id); var targets = targets_elt.getAttribute("targets"); var links = ""; target_list = targets.split(","); for (var i=0; i" + target[0] + ""; } // Put it all together. elt.insertBefore(box1, elt.childNodes.item(0)); //box1.appendChild(box2); box1.appendChild(shadow); shadow.appendChild(box2); box2.innerHTML = "Which "+name+" do you want to see documentation for?" + ""; } return false; } function get_anchor() { var href = location.href; var start = href.indexOf("#")+1; if ((start != 0) && (start != href.length)) return href.substring(start, href.length); } function redirect_url(dottedName) { // Scan through each element of the "pages" list, and check // if "name" matches with any of them. for (var i=0; i-m" or "-c"; // extract the portion & compare it to dottedName. var pagename = pages[i].substring(0, pages[i].length-2); if (pagename == dottedName.substring(0,pagename.length)) { // We've found a page that matches `dottedName`; // construct its URL, using leftover `dottedName` // content to form an anchor. var pagetype = pages[i].charAt(pages[i].length-1); var url = pagename + ((pagetype=="m")?"-module.html": "-class.html"); if (dottedName.length > pagename.length) url += "#" + dottedName.substring(pagename.length+1, dottedName.length); return url; } } } python-pyhsm-1.0.4l/doc/html/frames.html000066400000000000000000000010771256663164400202450ustar00rootroot00000000000000 pyhsm python-pyhsm-1.0.4l/doc/html/help.html000066400000000000000000000252511256663164400177200ustar00rootroot00000000000000 Help
 
[frames] | no frames]

API Documentation

This document contains the API (Application Programming Interface) documentation for pyhsm. Documentation for the Python objects defined by the project is divided into separate pages for each package, module, and class. The API documentation also includes two pages containing information about the project as a whole: a trees page, and an index page.

Object Documentation

Each Package Documentation page contains:

  • A description of the package.
  • A list of the modules and sub-packages contained by the package.
  • A summary of the classes defined by the package.
  • A summary of the functions defined by the package.
  • A summary of the variables defined by the package.
  • A detailed description of each function defined by the package.
  • A detailed description of each variable defined by the package.

Each Module Documentation page contains:

  • A description of the module.
  • A summary of the classes defined by the module.
  • A summary of the functions defined by the module.
  • A summary of the variables defined by the module.
  • A detailed description of each function defined by the module.
  • A detailed description of each variable defined by the module.

Each Class Documentation page contains:

  • A class inheritance diagram.
  • A list of known subclasses.
  • A description of the class.
  • A summary of the methods defined by the class.
  • A summary of the instance variables defined by the class.
  • A summary of the class (static) variables defined by the class.
  • A detailed description of each method defined by the class.
  • A detailed description of each instance variable defined by the class.
  • A detailed description of each class (static) variable defined by the class.

Project Documentation

The Trees page contains the module and class hierarchies:

  • The module hierarchy lists every package and module, with modules grouped into packages. At the top level, and within each package, modules and sub-packages are listed alphabetically.
  • The class hierarchy lists every class, grouped by base class. If a class has more than one base class, then it will be listed under each base class. At the top level, and under each base class, classes are listed alphabetically.

The Index page contains indices of terms and identifiers:

  • The term index lists every term indexed by any object's documentation. For each term, the index provides links to each place where the term is indexed.
  • The identifier index lists the (short) name of every package, module, class, method, function, variable, and parameter. For each identifier, the index provides a short description, and a link to its documentation.

The Table of Contents

The table of contents occupies the two frames on the left side of the window. The upper-left frame displays the project contents, and the lower-left frame displays the module contents:

Project
Contents
...
API
Documentation
Frame


Module
Contents
 
...
 

The project contents frame contains a list of all packages and modules that are defined by the project. Clicking on an entry will display its contents in the module contents frame. Clicking on a special entry, labeled "Everything," will display the contents of the entire project.

The module contents frame contains a list of every submodule, class, type, exception, function, and variable defined by a module or package. Clicking on an entry will display its documentation in the API documentation frame. Clicking on the name of the module, at the top of the frame, will display the documentation for the module itself.

The "frames" and "no frames" buttons below the top navigation bar can be used to control whether the table of contents is displayed or not.

The Navigation Bar

A navigation bar is located at the top and bottom of every page. It indicates what type of page you are currently viewing, and allows you to go to related pages. The following table describes the labels on the navigation bar. Note that not some labels (such as [Parent]) are not displayed on all pages.

Label Highlighted when... Links to...
[Parent] (never highlighted) the parent of the current package
[Package] viewing a package the package containing the current object
[Module] viewing a module the module containing the current object
[Class] viewing a class the class containing the current object
[Trees] viewing the trees page the trees page
[Index] viewing the index page the index page
[Help] viewing the help page the help page

The "show private" and "hide private" buttons below the top navigation bar can be used to control whether documentation for private objects is displayed. Private objects are usually defined as objects whose (short) names begin with a single underscore, but do not end with an underscore. For example, "_x", "__pprint", and "epydoc.epytext._tokenize" are private objects; but "re.sub", "__init__", and "type_" are not. However, if a module defines the "__all__" variable, then its contents are used to decide which objects are private.

A timestamp below the bottom navigation bar indicates when each page was last updated.

python-pyhsm-1.0.4l/doc/html/identifier-index.html000066400000000000000000002510631256663164400222210ustar00rootroot00000000000000 Identifier Index
 
[frames] | no frames]
[ Identifiers | Deprecations ]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

A

B

C

D

E

F

G

H

I

K

L

M

N

O

P

R

S

T

U

V

W

Y

_



python-pyhsm-1.0.4l/doc/html/index.html000066400000000000000000000010771256663164400200770ustar00rootroot00000000000000 pyhsm python-pyhsm-1.0.4l/doc/html/module-tree.html000066400000000000000000000163411256663164400212120ustar00rootroot00000000000000 Module Hierarchy
 
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Module Hierarchy

python-pyhsm-1.0.4l/doc/html/pyhsm-module.html000066400000000000000000000203661256663164400214150ustar00rootroot00000000000000 pyhsm
Package pyhsm
[frames] | no frames]

Package pyhsm

the pyhsm package

Basic usage :

 import pyhsm

 try:
     hsm = pyhsm.base.YHSM(device="/dev/ttyACM0", debug=False)
     print "Version : %s" % (hsm.info())
 except pyhsm.exception.YHSM_Error, e:
     print "ERROR: %s" % e

See help(pyhsm.base) (pyhsm.base.YHSM) for more information.


Version: 1.0.4l

Authors:
Fredrik Thulin, Dain Nilsson

Copyright: Yubico AB

License: BSD

Submodules

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd-module.html000066400000000000000000000164201256663164400231250ustar00rootroot00000000000000 pyhsm.aead_cmd
Package pyhsm :: Module aead_cmd
[frames] | no frames]

Module aead_cmd

implementations of AEAD commands for the YubiHSM

Classes
  YHSM_AEAD_Cmd
Class for common non-trivial parse_result for commands returning a YSM_AEAD_GENERATE_RESP.
  YHSM_Cmd_AEAD_Generate
Generate AEAD block from data for a specific key.
  YHSM_Cmd_AEAD_Random_Generate
Generate a random AEAD block using the YubiHSM internal TRNG.
  YHSM_Cmd_AEAD_Buffer_Generate
Generate AEAD block of data buffer for a specific key.
  YHSM_Cmd_AEAD_Decrypt_Cmp
Validate an AEAD using the YubiHSM, matching it against some known plain text.
  YHSM_GeneratedAEAD
Small class to represent a YHSM_AEAD_GENERATE_RESP.
  YHSM_YubiKeySecret
Small class to represent a YUBIKEY_SECRETS struct.
Variables
  YHSM_AEAD_File_Marker = 'YubiHSM AEAD\n'
python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_AEAD_Cmd-class.html000066400000000000000000000227731256663164400250710ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_AEAD_Cmd
Package pyhsm :: Module aead_cmd :: Class YHSM_AEAD_Cmd
[frames] | no frames]

Class YHSM_AEAD_Cmd

cmd.YHSM_Cmd --+
               |
              YHSM_AEAD_Cmd
Known Subclasses:

Class for common non-trivial parse_result for commands returning a YSM_AEAD_GENERATE_RESP.

Instance Methods
 
__repr__(self)
 
parse_result(self, data)
Returns a YHSM_GeneratedAEAD instance, or throws pyhsm.exception.YHSM_CommandFailed.

Inherited from cmd.YHSM_Cmd: __init__, execute

Class Variables
  key_handle = 0
  nonce = ''
  response = None
  status = 0

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

parse_result(self, data)

 

Returns a YHSM_GeneratedAEAD instance, or throws pyhsm.exception.YHSM_CommandFailed.

Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate-class.html000066400000000000000000000224551256663164400301710ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate
Package pyhsm :: Module aead_cmd :: Class YHSM_Cmd_AEAD_Buffer_Generate
[frames] | no frames]

Class YHSM_Cmd_AEAD_Buffer_Generate

cmd.YHSM_Cmd --+    
               |    
   YHSM_AEAD_Cmd --+
                   |
                  YHSM_Cmd_AEAD_Buffer_Generate

Generate AEAD block of data buffer for a specific key.

After a key has been loaded into the internal data buffer, this command can be used a number of times to get AEADs of the data buffer for different key handles.

For example, to encrypt a YubiKey secrets to one or more Yubico KSM's that all have a YubiHSM attached to them.

Key handle (and system flags) permission flags required for this operation : YSM_BUFFER_AEAD_GENERATE YSM_BUFFER_LOAD if non-random data has been loaded into the internal buffer

Instance Methods
 
__init__(self, stick, nonce, key_handle)
The base class for all YSM_ commands.

Inherited from YHSM_AEAD_Cmd: __repr__, parse_result

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_AEAD_Cmd: key_handle, nonce, response, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, nonce, key_handle)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp-class.html000066400000000000000000000240721256663164400273540ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp
Package pyhsm :: Module aead_cmd :: Class YHSM_Cmd_AEAD_Decrypt_Cmp
[frames] | no frames]

Class YHSM_Cmd_AEAD_Decrypt_Cmp

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_AEAD_Decrypt_Cmp

Validate an AEAD using the YubiHSM, matching it against some known plain text. Matching is done inside the YubiHSM so the decrypted AEAD is never exposed.

Instance Methods
 
__init__(self, stick, nonce, key_handle, aead, cleartext)
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, nonce, key_handle, aead, cleartext)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate-class.html000066400000000000000000000216551256663164400267010ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate
Package pyhsm :: Module aead_cmd :: Class YHSM_Cmd_AEAD_Generate
[frames] | no frames]

Class YHSM_Cmd_AEAD_Generate

cmd.YHSM_Cmd --+    
               |    
   YHSM_AEAD_Cmd --+
                   |
                  YHSM_Cmd_AEAD_Generate

Generate AEAD block from data for a specific key.

`data' is either a string, or a YHSM_YubiKeySecret.

Instance Methods
 
__init__(self, stick, nonce, key_handle, data)
The base class for all YSM_ commands.

Inherited from YHSM_AEAD_Cmd: __repr__, parse_result

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_AEAD_Cmd: key_handle, nonce, response, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, nonce, key_handle, data)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate-class.html000066400000000000000000000217651256663164400302030ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate
Package pyhsm :: Module aead_cmd :: Class YHSM_Cmd_AEAD_Random_Generate
[frames] | no frames]

Class YHSM_Cmd_AEAD_Random_Generate

cmd.YHSM_Cmd --+    
               |    
   YHSM_AEAD_Cmd --+
                   |
                  YHSM_Cmd_AEAD_Random_Generate

Generate a random AEAD block using the YubiHSM internal TRNG.

To generate a secret for a YubiKey, use public_id as nonce.

Instance Methods
 
__init__(self, stick, nonce, key_handle, num_bytes)
The base class for all YSM_ commands.

Inherited from YHSM_AEAD_Cmd: __repr__, parse_result

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_AEAD_Cmd: key_handle, nonce, response, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, nonce, key_handle, num_bytes)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_GeneratedAEAD-class.html000066400000000000000000000207651256663164400261240ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_GeneratedAEAD
Package pyhsm :: Module aead_cmd :: Class YHSM_GeneratedAEAD
[frames] | no frames]

Class YHSM_GeneratedAEAD

Small class to represent a YHSM_AEAD_GENERATE_RESP.

Instance Methods
 
__init__(self, nonce, key_handle, aead)
 
__repr__(self)
 
save(self, filename)
Store AEAD in a file.
 
load(self, filename)
Load AEAD from a file.
Method Details

save(self, filename)

 

Store AEAD in a file.

Parameters:
  • filename (string) - File to create/overwrite

load(self, filename)

 

Load AEAD from a file.

Parameters:
  • filename (string) - File to read AEAD from

python-pyhsm-1.0.4l/doc/html/pyhsm.aead_cmd.YHSM_YubiKeySecret-class.html000066400000000000000000000126441256663164400263370ustar00rootroot00000000000000 pyhsm.aead_cmd.YHSM_YubiKeySecret
Package pyhsm :: Module aead_cmd :: Class YHSM_YubiKeySecret
[frames] | no frames]

Class YHSM_YubiKeySecret

Small class to represent a YUBIKEY_SECRETS struct.

Instance Methods
 
__init__(self, key, uid)
 
pack(self)
Return key and uid packed for sending in a command to the YubiHSM.
python-pyhsm-1.0.4l/doc/html/pyhsm.aes_ecb_cmd-module.html000066400000000000000000000124041256663164400236120ustar00rootroot00000000000000 pyhsm.aes_ecb_cmd
Package pyhsm :: Module aes_ecb_cmd
[frames] | no frames]

Module aes_ecb_cmd

implementations of AES ECB block cipher commands to execute on a YubiHSM

Classes
  YHSM_Cmd_AES_ECB_Encrypt
Have the YubiHSM AES ECB encrypt something using the key of a key handle.
  YHSM_Cmd_AES_ECB_Decrypt
Have the YubiHSM AES ECB decrypt something using the key of a key handle.
  YHSM_Cmd_AES_ECB_Compare
Have the YubiHSM AES ECB decrypt something using the key of a key handle, and then compare it with a plaintext we supply.
python-pyhsm-1.0.4l/doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare-class.html000066400000000000000000000242321256663164400276050ustar00rootroot00000000000000 pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare
Package pyhsm :: Module aes_ecb_cmd :: Class YHSM_Cmd_AES_ECB_Compare
[frames] | no frames]

Class YHSM_Cmd_AES_ECB_Compare

cmd.YHSM_Cmd --+    
               |    
YHSM_Cmd_AES_ECB --+
                   |
                  YHSM_Cmd_AES_ECB_Compare

Have the YubiHSM AES ECB decrypt something using the key of a key handle, and then compare it with a plaintext we supply.

Requires you to know the plaintext to verify if the ciphertext matches it, providing added security in some applications.

Instance Methods
 
__init__(self, stick, key_handle, ciphertext, plaintext)
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from YHSM_Cmd_AES_ECB: __repr__

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_Cmd_AES_ECB: key_handle, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, key_handle, ciphertext, plaintext)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt-class.html000066400000000000000000000204041256663164400276260ustar00rootroot00000000000000 pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt
Package pyhsm :: Module aes_ecb_cmd :: Class YHSM_Cmd_AES_ECB_Decrypt
[frames] | no frames]

Class YHSM_Cmd_AES_ECB_Decrypt

cmd.YHSM_Cmd --+    
               |    
YHSM_Cmd_AES_ECB --+
                   |
                  YHSM_Cmd_AES_ECB_Decrypt

Have the YubiHSM AES ECB decrypt something using the key of a key handle.

Instance Methods
 
__init__(self, stick, key_handle, ciphertext)
The base class for all YSM_ commands.

Inherited from YHSM_Cmd_AES_ECB: __repr__, parse_result

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_Cmd_AES_ECB: key_handle, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, key_handle, ciphertext)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt-class.html000066400000000000000000000204021256663164400276360ustar00rootroot00000000000000 pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt
Package pyhsm :: Module aes_ecb_cmd :: Class YHSM_Cmd_AES_ECB_Encrypt
[frames] | no frames]

Class YHSM_Cmd_AES_ECB_Encrypt

cmd.YHSM_Cmd --+    
               |    
YHSM_Cmd_AES_ECB --+
                   |
                  YHSM_Cmd_AES_ECB_Encrypt

Have the YubiHSM AES ECB encrypt something using the key of a key handle.

Instance Methods
 
__init__(self, stick, key_handle, plaintext)
The base class for all YSM_ commands.

Inherited from YHSM_Cmd_AES_ECB: __repr__, parse_result

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from YHSM_Cmd_AES_ECB: key_handle, status

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, key_handle, plaintext)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.base-module.html000066400000000000000000000104631256663164400223230ustar00rootroot00000000000000 pyhsm.base
Package pyhsm :: Module base
[frames] | no frames]

Module base

module for accessing a YubiHSM

Classes
  YHSM
Base class for accessing a YubiHSM.
python-pyhsm-1.0.4l/doc/html/pyhsm.base.YHSM-class.html000066400000000000000000001777711256663164400227420ustar00rootroot00000000000000 pyhsm.base.YHSM
Package pyhsm :: Module base :: Class YHSM
[frames] | no frames]

Class YHSM

Base class for accessing a YubiHSM.

Instance Methods
 
__init__(self, device, debug=False, timeout=1, test_comm=True)
 
__repr__(self)
bool
reset(self, test_sync=True)
Perform stream resynchronization.
bool
set_debug(self, new)
Set debug mode.
 
test_comm(self)
Verify that data we send to and receive from the YubiHSM isn't mangled.
string
echo(self, data)
Echo test.
YHSM_Cmd_System_Info
info(self)
Get firmware version and unique ID from YubiHSM.
string
random(self, num_bytes)
Get random bytes from YubiHSM.
bool
random_reseed(self, seed)
Provide YubiHSM DRBG_CTR with a new seed.
YHSM_NonceResponse
get_nonce(self, increment=1)
Get current nonce from YubiHSM.
bool
load_temp_key(self, nonce, key_handle, aead)
Load the contents of an AEAD into the phantom key handle 0xffffffff.
bool
unlock(self, password=None, otp=None)
Unlock the YubiHSM using the master key and/or a YubiKey OTP.
 
key_storage_unlock(self, password)
integer
load_secret(self, secret)
Ask YubiHSM to load a pre-existing YubiKey secret.
integer
load_data(self, data, offset)
Ask YubiHSM to load arbitrary data into it's internal buffer, at any offset.
integer
load_random(self, num_bytes, offset=0)
Ask YubiHSM to generate a number of random bytes to any offset of it's internal buffer.
YHSM_GeneratedAEAD
generate_aead_simple(self, nonce, key_handle, data)
Generate AEAD block from data for a specific key in a single step (without using the YubiHSM internal buffer).
YHSM_GeneratedAEAD
generate_aead_random(self, nonce, key_handle, num_bytes)
Generate a random AEAD block using the YubiHSM internal DRBG_CTR random generator.
YHSM_GeneratedAEAD
generate_aead(self, nonce, key_handle)
Ask YubiHSM to return an AEAD made of the contents of it's internal buffer (see load_secret, load_data and load_random) encrypted with the specified key_handle.
bool
validate_aead(self, nonce, key_handle, aead, cleartext)
Validate the contents of an AEAD using the YubiHSM.
YHSM_ValidationResult
validate_aead_otp(self, public_id, otp, key_handle, aead)
Ask YubiHSM to validate a YubiKey OTP using an AEAD and a key_handle to decrypt the AEAD.
NoneType
monitor_exit(self)
Ask YubiHSM to exit to configuration mode (requires 'debug' mode enabled).
Serial
get_raw_device(self)
Get the raw device.
bool
drain(self)
Read until there is nothing more to be read.
string
aes_ecb_encrypt(self, key_handle, plaintext)
AES ECB encrypt using a key handle.
string
aes_ecb_decrypt(self, key_handle, ciphertext)
AES ECB decrypt using a key handle.
bool
aes_ecb_compare(self, key_handle, ciphertext, plaintext)
AES ECB decrypt and then compare using a key handle.
YHSM_Cmd_HMAC_SHA1_Write
hmac_sha1(self, key_handle, data, flags=None, final=True, to_buffer=False)
Have the YubiHSM generate a HMAC SHA1 of 'data' using a key handle.
bool
db_store_yubikey(self, public_id, key_handle, aead, nonce=None)
Ask YubiHSM to store data about a YubiKey in the internal database (not buffer).
YHSM_ValidationResult
db_validate_yubikey_otp(self, public_id, otp)
Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database.
Method Details

reset(self, test_sync=True)

 

Perform stream resynchronization.

Parameters:
  • test_sync (bool) - Verify sync with YubiHSM after reset
Returns: bool
True if successful

set_debug(self, new)

 

Set debug mode.

Parameters:
  • new (bool) - new value
Returns: bool
old value

test_comm(self)

 

Verify that data we send to and receive from the YubiHSM isn't mangled.

In some scenarios, communications with the YubiHSM might be affected by terminal line settings turning CR into LF for example.

echo(self, data)

 

Echo test.

Parameters:
  • data (string)
Returns: string
data read from YubiHSM -- should equal `data'

info(self)

 

Get firmware version and unique ID from YubiHSM.

Returns: YHSM_Cmd_System_Info
System information

random(self, num_bytes)

 

Get random bytes from YubiHSM.

The random data is DRBG_CTR seeded on each startup by a hardware TRNG, so it should be of very good quality.

Parameters:
  • num_bytes (integer)
Returns: string
Bytes with random data

random_reseed(self, seed)

 

Provide YubiHSM DRBG_CTR with a new seed.

Parameters:
  • seed (string) - new seed -- must be exactly 32 bytes
Returns: bool
True on success

get_nonce(self, increment=1)

 

Get current nonce from YubiHSM.

Use increment 0 to just fetch the value without incrementing it.

Parameters:
  • increment - requested increment (optional)
Returns: YHSM_NonceResponse
nonce value _before_ increment

load_temp_key(self, nonce, key_handle, aead)

 

Load the contents of an AEAD into the phantom key handle 0xffffffff.

Parameters:
  • nonce (string) - The nonce used when creating the AEAD
  • key_handle (integer or string) - The key handle that can decrypt the AEAD
  • aead (YHSM_GeneratedAEAD or string) - AEAD containing the cryptographic key and permission flags
Returns: bool
True on success

unlock(self, password=None, otp=None)

 

Unlock the YubiHSM using the master key and/or a YubiKey OTP.

If the master key is given during configuration, all key handles will be encrypted (with AES-256) using that passphrase.

If one or more admin Yubikey public id's are given during configuration, an OTP from one of these must be provided to the YubiHSM for it to start responding to cryptographic requests. The admin YubiKeys must be present in the internal database for this validation to work.

Parameters:
  • password (NoneType or string) - The 'master key' set during YubiHSM configuration
  • otp (NoneType or string) - A YubiKey OTP from an 'admin' YubiKey (modhex), to unlock YubiHSM.
Returns: bool
Only returns (True) on success

key_storage_unlock(self, password)

 

Deprecated: Too specific (and hard to remember) name.

See Also: unlock

load_secret(self, secret)

 

Ask YubiHSM to load a pre-existing YubiKey secret.

The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more generate_aead commands to actually retreive the generated secret (in encrypted form).

Parameters:
Returns: integer
Number of bytes in YubiHSM internal buffer after load

load_data(self, data, offset)

 

Ask YubiHSM to load arbitrary data into it's internal buffer, at any offset.

The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more generate_aead commands to actually retreive the generated secret (in encrypted form).

Load data to offset 0 to reset the buffer.

Parameters:
  • data (string) - arbitrary data to load
Returns: integer
Number of bytes in YubiHSM internal buffer after load

load_random(self, num_bytes, offset=0)

 

Ask YubiHSM to generate a number of random bytes to any offset of it's internal buffer.

The data is stored internally in the YubiHSM in temporary memory - this operation would typically be followed by one or more generate_aead commands to actually retreive the generated secret (in encrypted form).

Parameters:
  • num_bytes (integer) - Number of bytes to generate
Returns: integer
Number of bytes in YubiHSM internal buffer after load

generate_aead_simple(self, nonce, key_handle, data)

 

Generate AEAD block from data for a specific key in a single step (without using the YubiHSM internal buffer).

Parameters:
  • nonce (string) - The nonce to use when creating the AEAD
  • key_handle (integer or string) - The key handle that can encrypt data into an AEAD
  • data (string) - Data to put inside the AEAD
Returns: YHSM_GeneratedAEAD
The generated AEAD on success.

generate_aead_random(self, nonce, key_handle, num_bytes)

 

Generate a random AEAD block using the YubiHSM internal DRBG_CTR random generator.

To generate a secret for a YubiKey, use public_id as nonce.

Parameters:
  • nonce (string) - The nonce to use when creating the AEAD
  • key_handle (integer or string) - The key handle that can encrypt the random data into an AEAD
  • num_bytes (integer) - Number of random data bytes to put inside the AEAD
Returns: YHSM_GeneratedAEAD
The generated AEAD on success.

generate_aead(self, nonce, key_handle)

 

Ask YubiHSM to return an AEAD made of the contents of it's internal buffer (see load_secret, load_data and load_random) encrypted with the specified key_handle.

For a YubiKey secret, the nonce should be the public_id.

Parameters:
  • nonce (string) - The nonce to use when creating the AEAD
  • key_handle (integer or string) - The key handle that can create an AEAD
Returns: YHSM_GeneratedAEAD
The generated AEAD on success.

validate_aead(self, nonce, key_handle, aead, cleartext)

 

Validate the contents of an AEAD using the YubiHSM. The matching is done inside the YubiHSM so the contents of the AEAD is never exposed (well, except indirectionally when the cleartext does match).

The cleartext should naturally be of the same length as the AEAD minus the size of the MAC (8 bytes).

Parameters:
  • nonce (string) - The nonce used when creating the AEAD
  • key_handle (integer or string) - The key handle that can decrypt the AEAD
  • aead (YHSM_GeneratedAEAD or string) - AEAD containing the cryptographic key and permission flags
  • cleartext (string) - The presumed cleartext of the AEAD
Returns: bool
Whether or not the cleartext matches the contents of the AEAD.

validate_aead_otp(self, public_id, otp, key_handle, aead)

 

Ask YubiHSM to validate a YubiKey OTP using an AEAD and a key_handle to decrypt the AEAD.

Parameters:
  • public_id (string) - The six bytes public id of the YubiKey
  • otp (string) - The one time password (OTP) to validate
  • key_handle (integer or string) - The key handle that can decrypt the AEAD
  • aead (YHSM_GeneratedAEAD or string) - AEAD containing the cryptographic key and permission flags
Returns: YHSM_ValidationResult
validation response

monitor_exit(self)

 

Ask YubiHSM to exit to configuration mode (requires 'debug' mode enabled).

Returns: NoneType
None

get_raw_device(self)

 

Get the raw device. Only intended for test code/debugging!

Returns: Serial
serial device

drain(self)

 

Read until there is nothing more to be read. Only intended for test code/debugging!

Returns: bool
True on success

aes_ecb_encrypt(self, key_handle, plaintext)

 

AES ECB encrypt using a key handle.

Parameters:
  • key_handle (integer or string) - Key handle to use for AES ECB encryption
  • plaintext (string) - Data to encrypt
Returns: string
Ciphertext

Warning: Please be aware of the known limitations of AES ECB mode before using it!

See Also: pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt

aes_ecb_decrypt(self, key_handle, ciphertext)

 

AES ECB decrypt using a key handle.

Parameters:
  • key_handle (integer or string) - Key handle to use for AES ECB decryption
  • ciphertext (string) - Data to decrypt
Returns: string
Plaintext

Warning: Please be aware of the known limitations of AES ECB mode before using it!

See Also: pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt

aes_ecb_compare(self, key_handle, ciphertext, plaintext)

 

AES ECB decrypt and then compare using a key handle.

The comparison is done inside the YubiHSM so the plaintext is never exposed (well, except indirectionally when the provided plaintext does match).

Parameters:
  • key_handle (integer or string) - Key handle to use for AES ECB decryption
  • plaintext (string) - Data to decrypt
Returns: bool
Match result

Warning: Please be aware of the known limitations of AES ECB mode before using it!

See Also: pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare

hmac_sha1(self, key_handle, data, flags=None, final=True, to_buffer=False)

 

Have the YubiHSM generate a HMAC SHA1 of 'data' using a key handle.

Use the pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.next to add more input (until 'final' has been set to True).

Use the pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write.get_hash to get the hash result this far.

Parameters:
  • key_handle (integer or string) - Key handle to use when generating HMAC SHA1
  • data (string) - what to calculate the HMAC SHA1 checksum of
  • flags (None or integer) - bit-flags, overrides 'final' and 'to_buffer'
  • final - True when there is no more data, False if there is more
  • to_buffer - Should the final result be stored in the YubiHSM internal buffer or not
Returns: YHSM_Cmd_HMAC_SHA1_Write
HMAC-SHA1 instance

db_store_yubikey(self, public_id, key_handle, aead, nonce=None)

 

Ask YubiHSM to store data about a YubiKey in the internal database (not buffer).

The input is an AEAD with the secrets of a YubiKey, perhaps previously created using load_secret.

Parameters:
  • public_id (string) - The six bytes public id of the YubiKey
  • key_handle (integer or string) - Key handle that can decrypt the YubiKey AEAD
  • aead (YHSM_GeneratedAEAD or string) - AEAD of an pyhsm.aead_cmd.YHSM_YubiKeySecret
  • nonce (None or string) - Nonce, if different from public_id.
Returns: bool
True on success

db_validate_yubikey_otp(self, public_id, otp)

 

Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database.

Parameters:
  • public_id (string) - The six bytes public id of the YubiKey
  • otp (string) - The OTP from a YubiKey in binary form (16 bytes)
Returns: YHSM_ValidationResult
validation response

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd-module.html000066400000000000000000000167661256663164400233310ustar00rootroot00000000000000 pyhsm.basic_cmd
Package pyhsm :: Module basic_cmd
[frames] | no frames]

Module basic_cmd

implementations of basic commands to execute on a YubiHSM

Classes
  YHSM_Cmd_Echo
Send something to the stick, and expect to get it echoed back.
  YHSM_Cmd_System_Info
Request system information from the YubiHSM.
  YHSM_Cmd_Random
Ask stick to generate a number of random bytes.
  YHSM_Cmd_Random_Reseed
Provide YubiHSM DRBG_CTR with a new seed.
  YHSM_Cmd_Temp_Key_Load
Load an AEAD into the phantom key handle 0xffffffff.
  YHSM_Cmd_Nonce_Get
Get nonce value from YubiHSM - causes it to increment by one (or a specified number).
  YHSM_Cmd_Key_Storage_Unlock
Have the YubiHSM unlock it's key storage using the HSM password.
  YHSM_Cmd_Key_Store_Decrypt
Have the YubiHSM decrypt it's key store using the master key.
  YHSM_Cmd_HSM_Unlock
Have the YubiHSM unlock the HSM operations (those involving the keystore) with a YubiKey OTP.
  YHSM_NonceResponse
Small class to hold response of Nonce_Get command.
python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Echo-class.html000066400000000000000000000231751256663164400254410ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Echo
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Echo
[frames] | no frames]

Class YHSM_Cmd_Echo

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Echo

Send something to the stick, and expect to get it echoed back.

Instance Methods
 
__init__(self, stick, payload='')
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, payload='')
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock-class.html000066400000000000000000000251571256663164400265270ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_HSM_Unlock
[frames] | no frames]

Class YHSM_Cmd_HSM_Unlock

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_HSM_Unlock

Have the YubiHSM unlock the HSM operations (those involving the keystore) with a YubiKey OTP.

Admin YubiKeys public id's are entered during initial configuration. These must then be made available in the internal database.

Instance Methods
 
__init__(self, stick, public_id, otp)
The base class for all YSM_ commands.
bool
parse_result(self, data)
Parse result of pyhsm.defines.YSM_HSM_UNLOCK command.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Instance Variables
integer status = None
The result of the unlock operation
Method Details

__init__(self, stick, public_id, otp)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Parse result of pyhsm.defines.YSM_HSM_UNLOCK command.

Returns: bool
Only returns (True) on successful unlock
Raises:
Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock-class.html000066400000000000000000000256561256663164400303200ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Key_Storage_Unlock
[frames] | no frames]

Class YHSM_Cmd_Key_Storage_Unlock

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Key_Storage_Unlock

Have the YubiHSM unlock it's key storage using the HSM password.

If an incorrect password is given when the key storage is unlocked, it will be locked again.

This command was replaced by YHSM_Cmd_Key_Store_Decrypt in YubiHSM 1.0.

Instance Methods
 
__init__(self, stick, password='')
The base class for all YSM_ commands.
bool
parse_result(self, data)
Parse result of pyhsm.defines.YSM_KEY_STORAGE_UNLOCK command.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Instance Variables
integer status = None
The result of the unlock operation
Method Details

__init__(self, stick, password='')
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Parse result of pyhsm.defines.YSM_KEY_STORAGE_UNLOCK command.

Returns: bool
Only returns (True) on successful unlock
Raises:
Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt-class.html000066400000000000000000000255211256663164400301560ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Key_Store_Decrypt
[frames] | no frames]

Class YHSM_Cmd_Key_Store_Decrypt

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Key_Store_Decrypt

Have the YubiHSM decrypt it's key store using the master key.

If an incorrect master key is given, the key store will become unavailable (cleared from RAM in YubiHSM).

Instance Methods
 
__init__(self, stick, key='')
The base class for all YSM_ commands.
bool
parse_result(self, data)
Parse result of pyhsm.defines.YSM_KEY_STORE_DECRYPT command.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Instance Variables
integer status = None
The result of the decrypt operation
Method Details

__init__(self, stick, key='')
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Parse result of pyhsm.defines.YSM_KEY_STORE_DECRYPT command.

Returns: bool
Only returns (True) on successful decrypt
Raises:
Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get-class.html000066400000000000000000000237711256663164400264260ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Nonce_Get
[frames] | no frames]

Class YHSM_Cmd_Nonce_Get

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Nonce_Get

Get nonce value from YubiHSM - causes it to increment by one (or a specified number).

Call with post_increment 0 to just fetch current value.

Instance Methods
 
__init__(self, stick, post_increment)
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None
  response = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, post_increment)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Random-class.html000066400000000000000000000225261256663164400260020ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Random
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Random
[frames] | no frames]

Class YHSM_Cmd_Random

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Random

Ask stick to generate a number of random bytes.

Instance Methods
 
__init__(self, stick, num_bytes)
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, num_bytes)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed-class.html000066400000000000000000000232021256663164400272610ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Random_Reseed
[frames] | no frames]

Class YHSM_Cmd_Random_Reseed

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Random_Reseed

Provide YubiHSM DRBG_CTR with a new seed.

Instance Methods
 
__init__(self, stick, seed)
The base class for all YSM_ commands.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, seed)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_System_Info-class.html000066400000000000000000000273011256663164400270150ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_System_Info
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_System_Info
[frames] | no frames]

Class YHSM_Cmd_System_Info

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_System_Info

Request system information from the YubiHSM.

Instance Methods
 
__init__(self, stick)
The base class for all YSM_ commands.
 
__repr__(self)
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Instance Variables
  version_major = 0
Major firmware version
  version_minor = 0
Minor firmware version
  version_build = 0
Firmware build version
  protocol_ver = 0
Communication protocol version
string system_uid = None
Unique identifier for YubiHSM
Method Details

__init__(self, stick)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load-class.html000066400000000000000000000241771256663164400272420ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load
Package pyhsm :: Module basic_cmd :: Class YHSM_Cmd_Temp_Key_Load
[frames] | no frames]

Class YHSM_Cmd_Temp_Key_Load

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Temp_Key_Load

Load an AEAD into the phantom key handle 0xffffffff.

The `aead' is either a YHSM_GeneratedAEAD, or a string.

Instance Methods
 
__init__(self, stick, nonce, key_handle, aead)
The base class for all YSM_ commands.
bool
parse_result(self, data)
Parse result of pyhsm.defines.YSM_TEMP_KEY_LOAD command.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, nonce, key_handle, aead)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Parse result of pyhsm.defines.YSM_TEMP_KEY_LOAD command.

Returns: bool
Only returns (True) on successful load
Raises:
Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.basic_cmd.YHSM_NonceResponse-class.html000066400000000000000000000155511256663164400265600ustar00rootroot00000000000000 pyhsm.basic_cmd.YHSM_NonceResponse
Package pyhsm :: Module basic_cmd :: Class YHSM_NonceResponse
[frames] | no frames]

Class YHSM_NonceResponse

Small class to hold response of Nonce_Get command.

Instance Methods
 
__init__(self, nonce)
 
__repr__(self)
Instance Variables
integer volatile = 0
Volatile part of nonce
integer pu_count = 0
Power-up count -- persistent part of nonce
long nonce_int = 0
Current nonce
string nonce = None
Current nonce
python-pyhsm-1.0.4l/doc/html/pyhsm.buffer_cmd-module.html000066400000000000000000000114101256663164400234760ustar00rootroot00000000000000 pyhsm.buffer_cmd
Package pyhsm :: Module buffer_cmd
[frames] | no frames]

Module buffer_cmd

implementations of internal buffer commands for YubiHSM

Classes
  YHSM_Cmd_Buffer_Load
Ask YubiHSM to load some data into it's internal buffer.
  YHSM_Cmd_Buffer_Random_Load
Ask YubiHSM to generate a secret for a specific public_id
python-pyhsm-1.0.4l/doc/html/pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load-class.html000066400000000000000000000260121256663164400271140ustar00rootroot00000000000000 pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load
Package pyhsm :: Module buffer_cmd :: Class YHSM_Cmd_Buffer_Load
[frames] | no frames]

Class YHSM_Cmd_Buffer_Load

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Buffer_Load

Ask YubiHSM to load some data into it's internal buffer.

Instance Methods
 
__init__(self, stick, data, offset=0)
The base class for all YSM_ commands.
integer
parse_result(self, data)
Parse result of pyhsm.defines.YSM_BUFFER_LOAD command.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  offest = 0

Inherited from cmd.YHSM_Cmd: executed, response_status

Instance Variables
integer data_len = 0
Number of bytes (to be) loaded
integer offset
Offset in internal buffer where data will be/was loaded
Method Details

__init__(self, stick, data, offset=0)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Parse result of pyhsm.defines.YSM_BUFFER_LOAD command.

Returns: integer
Number of bytes now in the YubiHSM internal buffer.
Raises:
Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load-class.html000066400000000000000000000230161256663164400304150ustar00rootroot00000000000000 pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load
Package pyhsm :: Module buffer_cmd :: Class YHSM_Cmd_Buffer_Random_Load
[frames] | no frames]

Class YHSM_Cmd_Buffer_Random_Load

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Buffer_Random_Load

Ask YubiHSM to generate a secret for a specific public_id

Generated secret is stored in YubiHSM's internal memory and is retreived using YHSM_Cmd_Blob_Generate.

Instance Methods
 
__init__(self, stick, num_bytes, offset=0)
The base class for all YSM_ commands.
 
parse_result(self, data)
Return True if the public_id in the response matches the one in the request.

Inherited from cmd.YHSM_Cmd: execute

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, num_bytes, offset=0)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Return True if the public_id in the response matches the one in the request.

Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.cmd-module.html000066400000000000000000000124061256663164400221530ustar00rootroot00000000000000 pyhsm.cmd
Package pyhsm :: Module cmd
[frames] | no frames]

Module cmd

module for accessing a YubiHSM

Classes
  YHSM_Cmd
Base class for YubiHSM commands.
Functions
 
reset(stick)
Send a bunch of zero-bytes to the YubiHSM, and flush the input buffer.
python-pyhsm-1.0.4l/doc/html/pyhsm.cmd.YHSM_Cmd-class.html000066400000000000000000000274451256663164400233460ustar00rootroot00000000000000 pyhsm.cmd.YHSM_Cmd
Package pyhsm :: Module cmd :: Class YHSM_Cmd
[frames] | no frames]

Class YHSM_Cmd

Known Subclasses:

Base class for YubiHSM commands.

Instance Methods
 
__init__(self, stick, command, payload='')
The base class for all YSM_ commands.
 
execute(self, read_response=True)
Write command to HSM and read response.
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.
Class Variables
  executed = False
  response_status = None
Method Details

__init__(self, stick, command, payload='')
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick (pyhsm.stick.YHSM_Stick) - Reference to a YubiHSM
  • command (integer) - The YSM_xxx command defined in pyhsm.defines.
  • payload (string) - a packed C struct, represented as a Python string

execute(self, read_response=True)

 

Write command to HSM and read response.

Parameters:
  • read_response (bool) - Whether to expect a response or not.

python-pyhsm-1.0.4l/doc/html/pyhsm.db_cmd-module.html000066400000000000000000000114661256663164400226250ustar00rootroot00000000000000 pyhsm.db_cmd
Package pyhsm :: Module db_cmd
[frames] | no frames]

Module db_cmd

implementations of internal DB commands for YubiHSM

Classes
  YHSM_Cmd_DB_YubiKey_Store
Ask YubiHSM to store data about a YubiKey in the internal database (not buffer).
  YHSM_Cmd_DB_Validate_OTP
Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database.
python-pyhsm-1.0.4l/doc/html/pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP-class.html000066400000000000000000000250661256663164400267100ustar00rootroot00000000000000 pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP
Package pyhsm :: Module db_cmd :: Class YHSM_Cmd_DB_Validate_OTP
[frames] | no frames]

Class YHSM_Cmd_DB_Validate_OTP

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_DB_Validate_OTP

Request the YubiHSM to validate an OTP for a YubiKey stored in the internal database.

Instance Methods
 
__init__(self, stick, public_id, otp)
The base class for all YSM_ commands.
 
__repr__(self)
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  response = None
  status = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, public_id, otp)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store-class.html000066400000000000000000000240161256663164400271640ustar00rootroot00000000000000 pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store
Package pyhsm :: Module db_cmd :: Class YHSM_Cmd_DB_YubiKey_Store
[frames] | no frames]

Class YHSM_Cmd_DB_YubiKey_Store

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_DB_YubiKey_Store

Ask YubiHSM to store data about a YubiKey in the internal database (not buffer).

The input is an AEAD, perhaps previously created using generate_aead().

If the nonce for the AEAD is not the same as the public_id, specify it with the nonce keyword argument. This requires a YubiHSM >= 1.0.4.

Instance Methods
 
__init__(self, stick, public_id, key_handle, aead, nonce=None)
The base class for all YSM_ commands.
 
parse_result(self, data)
Return True if the AEAD was stored sucessfully.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, public_id, key_handle, aead, nonce=None)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Return True if the AEAD was stored sucessfully.

Overrides: cmd.YHSM_Cmd.parse_result

python-pyhsm-1.0.4l/doc/html/pyhsm.debug_cmd-module.html000066400000000000000000000107101256663164400233150ustar00rootroot00000000000000 pyhsm.debug_cmd
Package pyhsm :: Module debug_cmd
[frames] | no frames]

Module debug_cmd

implementations of debugging commands to execute on a YubiHSM

Classes
  YHSM_Cmd_Monitor_Exit
Send magics to YubiHSM in debug mode, and get it to exit to configuration mode again.
python-pyhsm-1.0.4l/doc/html/pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit-class.html000066400000000000000000000202241256663164400272000ustar00rootroot00000000000000 pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit
Package pyhsm :: Module debug_cmd :: Class YHSM_Cmd_Monitor_Exit
[frames] | no frames]

Class YHSM_Cmd_Monitor_Exit

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_Monitor_Exit

Send magics to YubiHSM in debug mode, and get it to exit to configuration mode again.

Instance Methods
 
__init__(self, stick, payload='')
The base class for all YSM_ commands.

Inherited from cmd.YHSM_Cmd: execute, parse_result

Class Variables

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, payload='')
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.defines-module.html000066400000000000000000000475101256663164400230310ustar00rootroot00000000000000 pyhsm.defines
Package pyhsm :: Module defines
[frames] | no frames]

Module defines

Various defines from pyhsm_if.h.

Functions
 
status2str(num)
Return YubiHSM response status code as string.
 
cmd2str(cmd)
Return command as string.
Variables
  YSM_PUBLIC_ID_SIZE = 6
  YSM_OTP_SIZE = 16
  YSM_BLOCK_SIZE = 16
  YSM_MAX_KEY_SIZE = 32
  YSM_DATA_BUF_SIZE = 64
  YSM_AEAD_NONCE_SIZE = 6
  YSM_AEAD_MAC_SIZE = 8
  YSM_CCM_CTR_SIZE = 2
  YSM_AEAD_MAX_SIZE = 72
  YSM_SHA1_HASH_SIZE = 20
  YSM_CTR_DRBG_SEED_SIZE = 32
  YSM_MAX_PKT_SIZE = 96
  YSM_PROTOCOL_VERSION = 1
  YSM_TEMP_KEY_HANDLE = 4294967295
  UID_SIZE = 6
  KEY_SIZE = 16
  YSM_STATUS_OK = 128
  YSM_KEY_HANDLE_INVALID = 129
  YSM_AEAD_INVALID = 130
  YSM_OTP_INVALID = 131
  YSM_OTP_REPLAY = 132
  YSM_ID_DUPLICATE = 133
  YSM_ID_NOT_FOUND = 134
  YSM_DB_FULL = 135
  YSM_MEMORY_ERROR = 136
  YSM_FUNCTION_DISABLED = 137
  YSM_KEY_STORAGE_LOCKED = 138
  YSM_MISMATCH = 139
  YSM_INVALID_PARAMETER = 140
  YSM_NULL = 0
  YSM_AEAD_GENERATE = 1
  YSM_BUFFER_AEAD_GENERATE = 2
  YSM_RANDOM_AEAD_GENERATE = 3
  YSM_AEAD_DECRYPT_CMP = 4
  YSM_DB_YUBIKEY_AEAD_STORE = 5
  YSM_AEAD_YUBIKEY_OTP_DECODE = 6
  YSM_DB_OTP_VALIDATE = 7
  YSM_DB_YUBIKEY_AEAD_STORE2 = 8
  YSM_AES_ECB_BLOCK_ENCRYPT = 13
  YSM_AES_ECB_BLOCK_DECRYPT = 14
  YSM_AES_ECB_BLOCK_DECRYPT_CMP = 15
  YSM_HMAC_SHA1_GENERATE = 16
  YSM_TEMP_KEY_LOAD = 17
  YSM_BUFFER_LOAD = 32
  YSM_BUFFER_RANDOM_LOAD = 33
  YSM_NONCE_GET = 34
  YSM_ECHO = 35
  YSM_RANDOM_GENERATE = 36
  YSM_RANDOM_RESEED = 37
  YSM_SYSTEM_INFO_QUERY = 38
  YSM_MONITOR_EXIT = 127
python-pyhsm-1.0.4l/doc/html/pyhsm.exception-module.html000066400000000000000000000141341256663164400234060ustar00rootroot00000000000000 pyhsm.exception
Package pyhsm :: Module exception
[frames] | no frames]

Module exception

common exceptions for the pyhsm package

Classes
  YHSM_Error
Base class for YHSM exceptions in this package.
  YHSM_WrongInputSize
Exception raised for errors in the size of an argument to some function.
  YHSM_InputTooShort
Exception raised for too short input to some function.
  YHSM_InputTooLong
Exception raised for too long input to some function.
  YHSM_WrongInputType
Exception raised for errors in the type of an argument to some function.
  YHSM_CommandFailed
Exception raised when a command sent to the YubiHSM returned an error.
python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_CommandFailed-class.html000066400000000000000000000217771256663164400265630ustar00rootroot00000000000000 pyhsm.exception.YHSM_CommandFailed
Package pyhsm :: Module exception :: Class YHSM_CommandFailed
[frames] | no frames]

Class YHSM_CommandFailed

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                      YHSM_Error --+
                                   |
                                  YHSM_CommandFailed

Exception raised when a command sent to the YubiHSM returned an error.

Instance Methods
 
__init__(self, name, status)
x.__init__(...) initializes x; see help(type(x)) for signature

Inherited from YHSM_Error: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables

Inherited from YHSM_Error: reason

Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, name, status)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_Error-class.html000066400000000000000000000243511256663164400251600ustar00rootroot00000000000000 pyhsm.exception.YHSM_Error
Package pyhsm :: Module exception :: Class YHSM_Error
[frames] | no frames]

Class YHSM_Error

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              YHSM_Error
Known Subclasses:

Base class for YHSM exceptions in this package.

Instance Methods
 
__init__(self, reason)
x.__init__(...) initializes x; see help(type(x)) for signature
 
__str__(self)
str(x)

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables
string reason = None
explanation of the error
Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, reason)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

__str__(self)
(Informal representation operator)

 

str(x)

Overrides: object.__str__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_InputTooLong-class.html000066400000000000000000000221071256663164400264650ustar00rootroot00000000000000 pyhsm.exception.YHSM_InputTooLong
Package pyhsm :: Module exception :: Class YHSM_InputTooLong
[frames] | no frames]

Class YHSM_InputTooLong

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                      YHSM_Error --+
                                   |
                                  YHSM_InputTooLong

Exception raised for too long input to some function.

Instance Methods
 
__init__(self, name, expected, size)
x.__init__(...) initializes x; see help(type(x)) for signature

Inherited from YHSM_Error: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables

Inherited from YHSM_Error: reason

Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, name, expected, size)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_InputTooShort-class.html000066400000000000000000000221161256663164400266650ustar00rootroot00000000000000 pyhsm.exception.YHSM_InputTooShort
Package pyhsm :: Module exception :: Class YHSM_InputTooShort
[frames] | no frames]

Class YHSM_InputTooShort

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                      YHSM_Error --+
                                   |
                                  YHSM_InputTooShort

Exception raised for too short input to some function.

Instance Methods
 
__init__(self, name, expected, size)
x.__init__(...) initializes x; see help(type(x)) for signature

Inherited from YHSM_Error: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables

Inherited from YHSM_Error: reason

Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, name, expected, size)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_WrongInputSize-class.html000066400000000000000000000221511256663164400270320ustar00rootroot00000000000000 pyhsm.exception.YHSM_WrongInputSize
Package pyhsm :: Module exception :: Class YHSM_WrongInputSize
[frames] | no frames]

Class YHSM_WrongInputSize

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                      YHSM_Error --+
                                   |
                                  YHSM_WrongInputSize

Exception raised for errors in the size of an argument to some function.

Instance Methods
 
__init__(self, name, expected, size)
x.__init__(...) initializes x; see help(type(x)) for signature

Inherited from YHSM_Error: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables

Inherited from YHSM_Error: reason

Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, name, expected, size)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.exception.YHSM_WrongInputType-class.html000066400000000000000000000221631256663164400270440ustar00rootroot00000000000000 pyhsm.exception.YHSM_WrongInputType
Package pyhsm :: Module exception :: Class YHSM_WrongInputType
[frames] | no frames]

Class YHSM_WrongInputType

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                      YHSM_Error --+
                                   |
                                  YHSM_WrongInputType

Exception raised for errors in the type of an argument to some function.

Instance Methods
 
__init__(self, name, expected, name_type)
x.__init__(...) initializes x; see help(type(x)) for signature

Inherited from YHSM_Error: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __unicode__

Inherited from object: __format__, __hash__, __reduce_ex__, __sizeof__, __subclasshook__

Instance Variables

Inherited from YHSM_Error: reason

Properties

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details

__init__(self, name, expected, name_type)
(Constructor)

 

x.__init__(...) initializes x; see help(type(x)) for signature

Overrides: object.__init__
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.hmac_cmd-module.html000066400000000000000000000113701256663164400231420ustar00rootroot00000000000000 pyhsm.hmac_cmd
Package pyhsm :: Module hmac_cmd
[frames] | no frames]

Module hmac_cmd

implementations of HMAC commands to execute on a YubiHSM

Classes
  YHSM_Cmd_HMAC_SHA1_Write
Calculate HMAC SHA1 using a key_handle in the YubiHSM.
  YHSM_GeneratedHMACSHA1
Small class to represent a YHSM_HMAC_SHA1_GENERATE_RESP.
python-pyhsm-1.0.4l/doc/html/pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write-class.html000066400000000000000000000312411256663164400270410ustar00rootroot00000000000000 pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write
Package pyhsm :: Module hmac_cmd :: Class YHSM_Cmd_HMAC_SHA1_Write
[frames] | no frames]

Class YHSM_Cmd_HMAC_SHA1_Write

cmd.YHSM_Cmd --+
               |
              YHSM_Cmd_HMAC_SHA1_Write

Calculate HMAC SHA1 using a key_handle in the YubiHSM.

Set final=False to not get a hash generated for the initial request.

Set to_buffer=True to get the SHA1 stored into the internal buffer, for use in some other cryptographic operation.

Instance Methods
 
__init__(self, stick, key_handle, data, flags=None, final=True, to_buffer=False)
The base class for all YSM_ commands.
 
next(self, data, final=False, to_buffer=False)
Add more input to the HMAC SHA1.
 
get_hash(self)
Get the HMAC-SHA1 that has been calculated this far.
 
__repr__(self)
 
parse_result(self, data)
This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  status = None
  result = None

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, key_handle, data, flags=None, final=True, to_buffer=False)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

This function is intended to be overridden by sub-classes that implements commands that should not just return the data read from the YubiHSM.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1-class.html000066400000000000000000000126571256663164400265760ustar00rootroot00000000000000 pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1
Package pyhsm :: Module hmac_cmd :: Class YHSM_GeneratedHMACSHA1
[frames] | no frames]

Class YHSM_GeneratedHMACSHA1

Small class to represent a YHSM_HMAC_SHA1_GENERATE_RESP.

Instance Methods
 
__init__(self, key_handle, sha1, final)
 
__repr__(self)
python-pyhsm-1.0.4l/doc/html/pyhsm.oath_hotp-module.html000066400000000000000000000073541256663164400234030ustar00rootroot00000000000000 pyhsm.oath_hotp
Package pyhsm :: Module oath_hotp
[frames] | no frames]

Module oath_hotp

helper functions to work with OATH HOTP (RFC4226) OTP's and YubiHSM

python-pyhsm-1.0.4l/doc/html/pyhsm.soft_hsm-module.html000066400000000000000000000116561256663164400232400ustar00rootroot00000000000000 pyhsm.soft_hsm
Package pyhsm :: Module soft_hsm
[frames] | no frames]

Module soft_hsm

functions for implementing parts of the HSMs machinery in software

Functions
 
aesCCM(key, key_handle, nonce, data, decrypt=False)
Function implementing YubiHSM AEAD encrypt/decrypt in software.
python-pyhsm-1.0.4l/doc/html/pyhsm.stick-module.html000066400000000000000000000105511256663164400225240ustar00rootroot00000000000000 pyhsm.stick
Package pyhsm :: Module stick
[frames] | no frames]

Module stick

module for actually talking to the YubiHSM

Classes
  YHSM_Stick
The current YHSM is a USB device using serial communication.
python-pyhsm-1.0.4l/doc/html/pyhsm.stick.YHSM_Stick-class.html000066400000000000000000000276451256663164400242740ustar00rootroot00000000000000 pyhsm.stick.YHSM_Stick
Package pyhsm :: Module stick :: Class YHSM_Stick
[frames] | no frames]

Class YHSM_Stick

The current YHSM is a USB device using serial communication.

This class exposes the basic functions read, write and flush (input).

Instance Methods
 
__init__(self, device, timeout=1, debug=False)
Open YHSM device.
 
acquire(self)
Do nothing
 
write(self, data, debug_info=None)
Write data to YHSM device.
 
read(self, num_bytes, debug_info=None)
Read a number of bytes from YubiHSM device.
 
flush(self)
Flush input buffers.
 
drain(self)
Drain input.
 
raw_device(self)
Get raw serial device.
 
set_debug(self, new)
Set debug mode (boolean).
 
__repr__(self)
 
__del__(self)
Close device when YHSM instance is destroyed.
Method Details

raw_device(self)

 

Get raw serial device. Only intended for test code/debugging!

set_debug(self, new)

 

Set debug mode (boolean).

Returns old setting.


python-pyhsm-1.0.4l/doc/html/pyhsm.stick_client-module.html000066400000000000000000000106401256663164400240610ustar00rootroot00000000000000 pyhsm.stick_client
Package pyhsm :: Module stick_client
[frames] | no frames]

Module stick_client

module for talking to the YubiHSM over a socket.

Classes
  YHSM_Stick_Client
The current YHSM is a USB device using serial communication.
python-pyhsm-1.0.4l/doc/html/pyhsm.stick_client.YHSM_Stick_Client-class.html000066400000000000000000000310201256663164400271060ustar00rootroot00000000000000 pyhsm.stick_client.YHSM_Stick_Client
Package pyhsm :: Module stick_client :: Class YHSM_Stick_Client
[frames] | no frames]

Class YHSM_Stick_Client

The current YHSM is a USB device using serial communication.

This class exposes the basic functions read, write and flush (input).

Instance Methods
 
__init__(self, device, timeout=1, debug=False)
Open YHSM device.
 
acquire(self)
 
release(self)
 
write(self, data, debug_info=None)
Write data to YHSM device.
 
read(self, num_bytes, debug_info=None)
Read a number of bytes from YubiHSM device.
 
flush(self)
Flush input buffers.
 
drain(self)
Drain input.
 
raw_device(self)
Get the socket address.
 
set_debug(self, new)
Set debug mode (boolean).
 
__repr__(self)
 
__del__(self)
Close device when YHSM instance is destroyed.
Method Details

raw_device(self)

 

Get the socket address. Only intended for test code/debugging!

set_debug(self, new)

 

Set debug mode (boolean).

Returns old setting.


python-pyhsm-1.0.4l/doc/html/pyhsm.util-module.html000066400000000000000000000161611256663164400223670ustar00rootroot00000000000000 pyhsm.util
Package pyhsm :: Module util
[frames] | no frames]

Module util

collection of utility functions

Functions
 
hexdump(src, length=8)
Produce a string hexdump of src, for debug output.
 
group(data, num)
Split data into chunks of num chars each
 
key_handle_to_int(this)
Turn "123" into 123 and "KSM1" into 827151179 (0x314d534b, 'K' = 0x4b, S = '0x53', M = 0x4d).
Function Details

key_handle_to_int(this)

 

Turn "123" into 123 and "KSM1" into 827151179 (0x314d534b, 'K' = 0x4b, S = '0x53', M = 0x4d).

YHSM is little endian, so this makes the bytes KSM1 appear in the most human readable form in packet traces.


python-pyhsm-1.0.4l/doc/html/pyhsm.validate_cmd-module.html000066400000000000000000000114211256663164400240200ustar00rootroot00000000000000 pyhsm.validate_cmd
Package pyhsm :: Module validate_cmd
[frames] | no frames]

Module validate_cmd

implementations of validation commands for YubiHSM

Classes
  YHSM_Cmd_AEAD_Validate_OTP
Request the YubiHSM to validate an OTP using an externally stored AEAD.
  YHSM_ValidationResult
The result of a Validate operation.
python-pyhsm-1.0.4l/doc/html/pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP-class.html000066400000000000000000000255521256663164400303210ustar00rootroot00000000000000 pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP
Package pyhsm :: Module validate_cmd :: Class YHSM_Cmd_AEAD_Validate_OTP
[frames] | no frames]

Class YHSM_Cmd_AEAD_Validate_OTP

      cmd.YHSM_Cmd --+    
                     |    
aead_cmd.YHSM_AEAD_Cmd --+
                         |
                        YHSM_Cmd_AEAD_Validate_OTP

Request the YubiHSM to validate an OTP using an externally stored AEAD.

Instance Methods
 
__init__(self, stick, public_id, otp, key_handle, aead)
The base class for all YSM_ commands.
 
parse_result(self, data)
Returns a YHSM_GeneratedAEAD instance, or throws pyhsm.exception.YHSM_CommandFailed.

Inherited from aead_cmd.YHSM_AEAD_Cmd: __repr__

Inherited from cmd.YHSM_Cmd: execute

Class Variables
  response = None
  status = None

Inherited from aead_cmd.YHSM_AEAD_Cmd: key_handle, nonce

Inherited from cmd.YHSM_Cmd: executed, response_status

Method Details

__init__(self, stick, public_id, otp, key_handle, aead)
(Constructor)

 

The base class for all YSM_ commands.

Parameters:
  • stick - Reference to a YubiHSM
  • command - The YSM_xxx command defined in pyhsm.defines.
  • payload - a packed C struct, represented as a Python string
Overrides: cmd.YHSM_Cmd.__init__
(inherited documentation)

parse_result(self, data)

 

Returns a YHSM_GeneratedAEAD instance, or throws pyhsm.exception.YHSM_CommandFailed.

Overrides: cmd.YHSM_Cmd.parse_result
(inherited documentation)

python-pyhsm-1.0.4l/doc/html/pyhsm.validate_cmd.YHSM_ValidationResult-class.html000066400000000000000000000172611256663164400300000ustar00rootroot00000000000000 pyhsm.validate_cmd.YHSM_ValidationResult
Package pyhsm :: Module validate_cmd :: Class YHSM_ValidationResult
[frames] | no frames]

Class YHSM_ValidationResult

The result of a Validate operation.

Contains the counters and timestamps decrypted from the OTP.

Instance Methods
 
__init__(self, public_id, use_ctr, session_ctr, ts_high, ts_low)
 
__repr__(self)
Instance Variables
integer ts_low = None
The low 16 bits of the 24-bit 8 hz timer since power-on of the YubiKey
integer ts_high = None
The high 8 bits of the 24-bit 8 hz timer since power-on of the YubiKey
integer session_ctr = None
The 8-bit volatile session counter of the YubiKey
integer use_ctr = None
The 16-bit power-on non-volatile counter of the YubiKey
string public_id = None
The six bytes public ID of the YubiKey that produced the OTP
python-pyhsm-1.0.4l/doc/html/pyhsm.version-module.html000066400000000000000000000106561256663164400231020ustar00rootroot00000000000000 pyhsm.version
Package pyhsm :: Module version
[frames] | no frames]

Module version

module for keeping track of different capabilities in different versions

Classes
  YHSM_Version
Keeps the YubiHSM's version number and can tell what capabilities it has.
python-pyhsm-1.0.4l/doc/html/pyhsm.version.YHSM_Version-class.html000066400000000000000000000321561256663164400252050ustar00rootroot00000000000000 pyhsm.version.YHSM_Version
Package pyhsm :: Module version :: Class YHSM_Version
[frames] | no frames]

Class YHSM_Version

Keeps the YubiHSM's version number and can tell what capabilities it has.

Instance Methods
 
__init__(self, sysinfo)
 
have_key_storage_unlock(self)
YSM_KEY_STORAGE_UNLOCK was removed in 1.0.
 
have_key_store_decrypt(self)
YSM_KEY_STORE_DECRYPT was introduced in 1.0, replacing YSM_KEY_STORAGE_UNLOCK.
 
have_unlock(self)
YSM_HSM_UNLOCK, featuring YubiKey OTP unlocking of operations, was introduced in 1.0.
 
have_keycommit(self)
YubiHSM have the 'keycommit' command in configuration mode.
 
have_keydisable(self)
YubiHSM have the 'keydis'(able) command in configuration mode.
 
have_YSM_BUFFER_LOAD(self)
This is a key handle permission flag that was introduced in 0.9.9.
 
have_YSM_DB_YUBIKEY_AEAD_STORE2(self)
The 2nd generation store command (with public id != nonce) was introduced in 1.0.4.
Instance Variables
YHSM_Cmd_System_Info sysinfo
Sysinfo when YubiHSM was initialized.
Method Details

__init__(self, sysinfo)
(Constructor)

 
Parameters:

have_key_storage_unlock(self)

 

YSM_KEY_STORAGE_UNLOCK was removed in 1.0.

The basic concept of a passphrase to unlock the YubiHSM is now provided with the more secure YSM_KEY_STORE_DECRYPT.

have_keycommit(self)

 

YubiHSM have the 'keycommit' command in configuration mode.

'keycommit' was introduced in 1.0.

have_keydisable(self)

 

YubiHSM have the 'keydis'(able) command in configuration mode.

'keydis' was introduced in 1.0.


python-pyhsm-1.0.4l/doc/html/pyhsm.yubikey-module.html000066400000000000000000000343271256663164400230770ustar00rootroot00000000000000 pyhsm.yubikey
Package pyhsm :: Module yubikey
[frames] | no frames]

Module yubikey

helper functions to work with Yubikeys and YubiHSM

Functions
YHSM_ValidationResult
validate_otp(hsm, from_key)
Try to validate an OTP from a YubiKey using the internal database on the YubiHSM.
YHSM_ValidationResult
validate_yubikey_with_aead(hsm, from_key, aead, key_handle)
Try to validate an OTP from a YubiKey using the AEAD that can decrypt this YubiKey's internal secret, using the key_handle for the AEAD.
string
modhex_decode(data)
Convert a modhex string to ordinary hex.
string
modhex_encode(data)
Convert an ordinary hex string to modhex.
tuple of string
split_id_otp(from_key)
Separate public id from OTP given a YubiKey OTP as input.
Function Details

validate_otp(hsm, from_key)

 

Try to validate an OTP from a YubiKey using the internal database on the YubiHSM.

`from_key' is the modhex encoded string emitted when you press the button on your YubiKey.

Will only return on succesfull validation. All failures will result in an pyhsm.exception.YHSM_CommandFailed.

Parameters:
  • hsm (pyhsm.YHSM) - The YHSM instance
  • from_key (string) - The OTP from a YubiKey (in modhex)
Returns: YHSM_ValidationResult
validation response, if successful

validate_yubikey_with_aead(hsm, from_key, aead, key_handle)

 

Try to validate an OTP from a YubiKey using the AEAD that can decrypt this YubiKey's internal secret, using the key_handle for the AEAD.

`from_key' is the modhex encoded string emitted when you press the button on your YubiKey.

Will only return on succesfull validation. All failures will result in an pyhsm.exception.YHSM_CommandFailed.

Parameters:
  • hsm (pyhsm.YHSM) - The YHSM instance
  • from_key (string) - The OTP from a YubiKey (in modhex)
  • aead (YHSM_GeneratedAEAD or string) - AEAD containing the cryptographic key and permission flags
  • key_handle (integer or string) - The key handle that can decrypt the AEAD
Returns: YHSM_ValidationResult
validation response

modhex_decode(data)

 

Convert a modhex string to ordinary hex.

Parameters:
  • data (string) - Modhex input
Returns: string
Hex

modhex_encode(data)

 

Convert an ordinary hex string to modhex.

Parameters:
  • data (string) - Hex input
Returns: string
Modhex

split_id_otp(from_key)

 

Separate public id from OTP given a YubiKey OTP as input.

Parameters:
  • from_key (string) - The OTP from a YubiKey (in modhex)
Returns: tuple of string
public_id and OTP

python-pyhsm-1.0.4l/doc/html/redirect.html000066400000000000000000000057221256663164400205720ustar00rootroot00000000000000Epydoc Redirect Page

Epydoc Auto-redirect page

When javascript is enabled, this page will redirect URLs of the form redirect.html#dotted.name to the documentation for the object with the given fully-qualified dotted name.

 

python-pyhsm-1.0.4l/doc/html/toc-everything.html000066400000000000000000000331651256663164400217420ustar00rootroot00000000000000 Everything

Everything


All Classes

pyhsm.aead_cmd.YHSM_AEAD_Cmd
pyhsm.aead_cmd.YHSM_Cmd_AEAD_Buffer_Generate
pyhsm.aead_cmd.YHSM_Cmd_AEAD_Decrypt_Cmp
pyhsm.aead_cmd.YHSM_Cmd_AEAD_Generate
pyhsm.aead_cmd.YHSM_Cmd_AEAD_Random_Generate
pyhsm.aead_cmd.YHSM_GeneratedAEAD
pyhsm.aead_cmd.YHSM_YubiKeySecret
pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Compare
pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Decrypt
pyhsm.aes_ecb_cmd.YHSM_Cmd_AES_ECB_Encrypt
pyhsm.base.YHSM
pyhsm.basic_cmd.YHSM_Cmd_Echo
pyhsm.basic_cmd.YHSM_Cmd_HSM_Unlock
pyhsm.basic_cmd.YHSM_Cmd_Key_Storage_Unlock
pyhsm.basic_cmd.YHSM_Cmd_Key_Store_Decrypt
pyhsm.basic_cmd.YHSM_Cmd_Nonce_Get
pyhsm.basic_cmd.YHSM_Cmd_Random
pyhsm.basic_cmd.YHSM_Cmd_Random_Reseed
pyhsm.basic_cmd.YHSM_Cmd_System_Info
pyhsm.basic_cmd.YHSM_Cmd_Temp_Key_Load
pyhsm.basic_cmd.YHSM_NonceResponse
pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Load
pyhsm.buffer_cmd.YHSM_Cmd_Buffer_Random_Load
pyhsm.cmd.YHSM_Cmd
pyhsm.db_cmd.YHSM_Cmd_DB_Validate_OTP
pyhsm.db_cmd.YHSM_Cmd_DB_YubiKey_Store
pyhsm.debug_cmd.YHSM_Cmd_Monitor_Exit
pyhsm.exception.YHSM_CommandFailed
pyhsm.exception.YHSM_Error
pyhsm.exception.YHSM_InputTooLong
pyhsm.exception.YHSM_InputTooShort
pyhsm.exception.YHSM_WrongInputSize
pyhsm.exception.YHSM_WrongInputType
pyhsm.hmac_cmd.YHSM_Cmd_HMAC_SHA1_Write
pyhsm.hmac_cmd.YHSM_GeneratedHMACSHA1
pyhsm.stick.YHSM_Stick
pyhsm.validate_cmd.YHSM_Cmd_AEAD_Validate_OTP
pyhsm.validate_cmd.YHSM_ValidationResult
pyhsm.version.YHSM_Version

All Functions

pyhsm.cmd.reset
pyhsm.defines.cmd2str
pyhsm.defines.status2str
pyhsm.soft_hsm.aesCCM
pyhsm.util.group
pyhsm.util.hexdump
pyhsm.util.key_handle_to_int
pyhsm.yubikey.modhex_decode
pyhsm.yubikey.modhex_encode
pyhsm.yubikey.split_id_otp
pyhsm.yubikey.validate_otp
pyhsm.yubikey.validate_yubikey_with_aead

All Variables

pyhsm.aead_cmd.YHSM_AEAD_File_Marker
pyhsm.defines.KEY_SIZE
pyhsm.defines.UID_SIZE
pyhsm.defines.YSM_AEAD_DECRYPT_CMP
pyhsm.defines.YSM_AEAD_GENERATE
pyhsm.defines.YSM_AEAD_INVALID
pyhsm.defines.YSM_AEAD_MAC_SIZE
pyhsm.defines.YSM_AEAD_MAX_SIZE
pyhsm.defines.YSM_AEAD_NONCE_SIZE
pyhsm.defines.YSM_AEAD_YUBIKEY_OTP_DECODE
pyhsm.defines.YSM_AES_ECB_BLOCK_DECRYPT
pyhsm.defines.YSM_AES_ECB_BLOCK_DECRYPT_CMP
pyhsm.defines.YSM_AES_ECB_BLOCK_ENCRYPT
pyhsm.defines.YSM_BLOCK_SIZE
pyhsm.defines.YSM_BUFFER_AEAD_GENERATE
pyhsm.defines.YSM_BUFFER_LOAD
pyhsm.defines.YSM_BUFFER_RANDOM_LOAD
pyhsm.defines.YSM_CCM_CTR_SIZE
pyhsm.defines.YSM_CTR_DRBG_SEED_SIZE
pyhsm.defines.YSM_DATA_BUF_SIZE
pyhsm.defines.YSM_DB_FULL
pyhsm.defines.YSM_DB_OTP_VALIDATE
pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE
pyhsm.defines.YSM_DB_YUBIKEY_AEAD_STORE2
pyhsm.defines.YSM_ECHO
pyhsm.defines.YSM_FUNCTION_DISABLED
pyhsm.defines.YSM_HMAC_SHA1_GENERATE
pyhsm.defines.YSM_ID_DUPLICATE
pyhsm.defines.YSM_ID_NOT_FOUND
pyhsm.defines.YSM_INVALID_PARAMETER
pyhsm.defines.YSM_KEY_HANDLE_INVALID
pyhsm.defines.YSM_KEY_STORAGE_LOCKED
pyhsm.defines.YSM_MAX_KEY_SIZE
pyhsm.defines.YSM_MAX_PKT_SIZE
pyhsm.defines.YSM_MEMORY_ERROR
pyhsm.defines.YSM_MISMATCH
pyhsm.defines.YSM_MONITOR_EXIT
pyhsm.defines.YSM_NONCE_GET
pyhsm.defines.YSM_NULL
pyhsm.defines.YSM_OTP_INVALID
pyhsm.defines.YSM_OTP_REPLAY
pyhsm.defines.YSM_OTP_SIZE
pyhsm.defines.YSM_PROTOCOL_VERSION
pyhsm.defines.YSM_PUBLIC_ID_SIZE
pyhsm.defines.YSM_RANDOM_AEAD_GENERATE
pyhsm.defines.YSM_RANDOM_GENERATE
pyhsm.defines.YSM_RANDOM_RESEED
pyhsm.defines.YSM_SHA1_HASH_SIZE
pyhsm.defines.YSM_STATUS_OK
pyhsm.defines.YSM_SYSTEM_INFO_QUERY
pyhsm.defines.YSM_TEMP_KEY_HANDLE
pyhsm.defines.YSM_TEMP_KEY_LOAD

python-pyhsm-1.0.4l/doc/html/toc-pyhsm-module.html000066400000000000000000000014741256663164400221770ustar00rootroot00000000000000 pyhsm

Module pyhsm



python-pyhsm-1.0.4l/doc/html/toc-pyhsm.aead_cmd-module.html000066400000000000000000000035011256663164400237040ustar00rootroot00000000000000 aead_cmd

Module aead_cmd


Classes

YHSM_AEAD_Cmd
YHSM_Cmd_AEAD_Buffer_Generate
YHSM_Cmd_AEAD_Decrypt_Cmp
YHSM_Cmd_AEAD_Generate
YHSM_Cmd_AEAD_Random_Generate
YHSM_GeneratedAEAD
YHSM_YubiKeySecret

Variables

YHSM_AEAD_File_Marker

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.aes_ecb_cmd-module.html000066400000000000000000000023441256663164400243770ustar00rootroot00000000000000 aes_ecb_cmd

Module aes_ecb_cmd


Classes

YHSM_Cmd_AES_ECB_Compare
YHSM_Cmd_AES_ECB_Decrypt
YHSM_Cmd_AES_ECB_Encrypt

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.base-module.html000066400000000000000000000016511256663164400231050ustar00rootroot00000000000000 base

Module base


Classes

YHSM

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.basic_cmd-module.html000066400000000000000000000037651256663164400241070ustar00rootroot00000000000000 basic_cmd

Module basic_cmd


Classes

YHSM_Cmd_Echo
YHSM_Cmd_HSM_Unlock
YHSM_Cmd_Key_Storage_Unlock
YHSM_Cmd_Key_Store_Decrypt
YHSM_Cmd_Nonce_Get
YHSM_Cmd_Random
YHSM_Cmd_Random_Reseed
YHSM_Cmd_System_Info
YHSM_Cmd_Temp_Key_Load
YHSM_NonceResponse

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.buffer_cmd-module.html000066400000000000000000000021371256663164400242670ustar00rootroot00000000000000 buffer_cmd

Module buffer_cmd


Classes

YHSM_Cmd_Buffer_Load
YHSM_Cmd_Buffer_Random_Load

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.cmd-module.html000066400000000000000000000020411256663164400227300ustar00rootroot00000000000000 cmd

Module cmd


Classes

YHSM_Cmd

Functions

reset

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.db_cmd-module.html000066400000000000000000000021231256663164400233760ustar00rootroot00000000000000 db_cmd

Module db_cmd


Classes

YHSM_Cmd_DB_Validate_OTP
YHSM_Cmd_DB_YubiKey_Store

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.debug_cmd-module.html000066400000000000000000000017321256663164400241040ustar00rootroot00000000000000 debug_cmd

Module debug_cmd


Classes

YHSM_Cmd_Monitor_Exit

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.defines-module.html000066400000000000000000000151761256663164400236170ustar00rootroot00000000000000 defines

Module defines


Functions

cmd2str
status2str

Variables

KEY_SIZE
UID_SIZE
YSM_AEAD_DECRYPT_CMP
YSM_AEAD_GENERATE
YSM_AEAD_INVALID
YSM_AEAD_MAC_SIZE
YSM_AEAD_MAX_SIZE
YSM_AEAD_NONCE_SIZE
YSM_AEAD_YUBIKEY_OTP_DECODE
YSM_AES_ECB_BLOCK_DECRYPT
YSM_AES_ECB_BLOCK_DECRYPT_CMP
YSM_AES_ECB_BLOCK_ENCRYPT
YSM_BLOCK_SIZE
YSM_BUFFER_AEAD_GENERATE
YSM_BUFFER_LOAD
YSM_BUFFER_RANDOM_LOAD
YSM_CCM_CTR_SIZE
YSM_CTR_DRBG_SEED_SIZE
YSM_DATA_BUF_SIZE
YSM_DB_FULL
YSM_DB_OTP_VALIDATE
YSM_DB_YUBIKEY_AEAD_STORE
YSM_DB_YUBIKEY_AEAD_STORE2
YSM_ECHO
YSM_FUNCTION_DISABLED
YSM_HMAC_SHA1_GENERATE
YSM_ID_DUPLICATE
YSM_ID_NOT_FOUND
YSM_INVALID_PARAMETER
YSM_KEY_HANDLE_INVALID
YSM_KEY_STORAGE_LOCKED
YSM_MAX_KEY_SIZE
YSM_MAX_PKT_SIZE
YSM_MEMORY_ERROR
YSM_MISMATCH
YSM_MONITOR_EXIT
YSM_NONCE_GET
YSM_NULL
YSM_OTP_INVALID
YSM_OTP_REPLAY
YSM_OTP_SIZE
YSM_PROTOCOL_VERSION
YSM_PUBLIC_ID_SIZE
YSM_RANDOM_AEAD_GENERATE
YSM_RANDOM_GENERATE
YSM_RANDOM_RESEED
YSM_SHA1_HASH_SIZE
YSM_STATUS_OK
YSM_SYSTEM_INFO_QUERY
YSM_TEMP_KEY_HANDLE
YSM_TEMP_KEY_LOAD

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.exception-module.html000066400000000000000000000027731256663164400241770ustar00rootroot00000000000000 exception

Module exception


Classes

YHSM_CommandFailed
YHSM_Error
YHSM_InputTooLong
YHSM_InputTooShort
YHSM_WrongInputSize
YHSM_WrongInputType

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.hmac_cmd-module.html000066400000000000000000000021251256663164400237230ustar00rootroot00000000000000 hmac_cmd

Module hmac_cmd


Classes

YHSM_Cmd_HMAC_SHA1_Write
YHSM_GeneratedHMACSHA1

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.oath_hotp-module.html000066400000000000000000000015041256663164400241550ustar00rootroot00000000000000 oath_hotp

Module oath_hotp



python-pyhsm-1.0.4l/doc/html/toc-pyhsm.soft_hsm-module.html000066400000000000000000000016741256663164400240220ustar00rootroot00000000000000 soft_hsm

Module soft_hsm


Functions

aesCCM

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.stick-module.html000066400000000000000000000016701256663164400233110ustar00rootroot00000000000000 stick

Module stick


Classes

YHSM_Stick

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.stick_client-module.html000066400000000000000000000015511256663164400246450ustar00rootroot00000000000000 stick_client

Module stick_client


Classes


python-pyhsm-1.0.4l/doc/html/toc-pyhsm.util-module.html000066400000000000000000000021601256663164400231440ustar00rootroot00000000000000 util

Module util


Functions

group
hexdump
key_handle_to_int

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.validate_cmd-module.html000066400000000000000000000021471256663164400246100ustar00rootroot00000000000000 validate_cmd

Module validate_cmd


Classes

YHSM_Cmd_AEAD_Validate_OTP
YHSM_ValidationResult

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.version-module.html000066400000000000000000000017021256663164400236550ustar00rootroot00000000000000 version

Module version


Classes

YHSM_Version

python-pyhsm-1.0.4l/doc/html/toc-pyhsm.yubikey-module.html000066400000000000000000000025651256663164400236610ustar00rootroot00000000000000 yubikey

Module yubikey


Functions

modhex_decode
modhex_encode
split_id_otp
validate_otp
validate_yubikey_with_aead

python-pyhsm-1.0.4l/doc/html/toc.html000066400000000000000000000104241256663164400175510ustar00rootroot00000000000000 Table of Contents

Table of Contents


Everything

Modules

pyhsm
pyhsm.aead_cmd
pyhsm.aes_ecb_cmd
pyhsm.base
pyhsm.basic_cmd
pyhsm.buffer_cmd
pyhsm.cmd
pyhsm.db_cmd
pyhsm.debug_cmd
pyhsm.defines
pyhsm.exception
pyhsm.hmac_cmd
pyhsm.oath_hotp
pyhsm.soft_hsm
pyhsm.stick
pyhsm.util
pyhsm.validate_cmd
pyhsm.version
pyhsm.yubikey

python-pyhsm-1.0.4l/examples/000077500000000000000000000000001256663164400162025ustar00rootroot00000000000000python-pyhsm-1.0.4l/examples/yhsm-monitor-exit.py000077500000000000000000000027361256663164400222030ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # # Utility to send a MONITOR_EXIT command to a YubiHSM. # # MONITOR_EXIT only works if the YubiHSM is in debug mode. It would # be a security problem to allow remote reconfiguration of a production # YubiHSM. # # If your YubiHSM is not in debug mode, enter configuration mode by # pressing the small button while inserting the YubiHSM in the USB port. # import sys sys.path.append('Lib'); import pyhsm device = "/dev/ttyACM0" # simplified arguments parsing d_argv = dict.fromkeys(sys.argv) debug = d_argv.has_key('-v') raw = d_argv.has_key('-v') if d_argv.has_key('-h'): sys.stderr.write("Syntax: %s [-v] [-R]\n" % (sys.argv[0])) sys.stderr.write("\nOptions :\n") sys.stderr.write(" -v verbose\n") sys.stderr.write(" -R raw MONITOR_EXIT command\n") sys.exit(0) res = 0 try: s = pyhsm.base.YHSM(device=device, debug = debug) if raw: # No initialization s.write('\x7f\xef\xbe\xad\xba\x10\x41\x52\x45') else: print "Version: %s" % s.info() s.monitor_exit() print "Exited monitor-mode (maybe)" if raw: print "s.stick == %s" % s.stick print "s.stick.ser == %s" % s.stick.ser for _ in xrange(3): s.stick.ser.write("\n") line = s.stick.ser.readline() print "%s" % (line) except pyhsm.exception.YHSM_Error, e: print "ERROR: %s" % e res = 1 sys.exit(res) python-pyhsm-1.0.4l/examples/yhsm-password-auth.py000077500000000000000000000141611256663164400223410ustar00rootroot00000000000000#!/usr/bin/env python # # Utility to generate an AEAD (encrypted block) from a password, # that can later on be validated securely. # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # # If you only have a single YubiHSM, you have to have one key handle # that can both ENCRYPT and COMPARE AES ECB blocks. # # If you have two (or more) YubiHSM's, you can have a key handle in # YubiHSM 1 that can only ENCRYPT, and the same key (!) with the same # key handle (!) in YubiHSM 2 that can only COMPARE. This might add # to the overall security in certain applications. # # Hashing the password before sending it to the YubiHSM (e.g. using PBKDF2) # in order to further enhance security is left as an exercise to the reader. # # Example usage : # # First, set password (create AEAD) : # # $ yhsm-password-auth.py --set --key-handle 8192 --nonce 010203040506 --verbose # Enter password to encrypt : # Success! Remember the nonce and use this AEAD to validate the password later : # # AEAD: 2b70c81e3f84db190f772d8e8dbfe05ebded5db881e9574939a52257 NONCE: 010203040506 # $ # # Then, later on, validate the password using the AEAD and NONCE from above : # # $ yhsm-password-auth.py --key-handle 8192 --nonce 010203040506 --verbose \ # --validate 2b70c81e3f84db190f772d8e8dbfe05ebded5db881e9574939a52257 # Enter password to validate : # OK! Password validated. # $ # import sys sys.path.append('Lib'); import pyhsm import argparse import getpass default_device = "/dev/ttyACM0" def parse_args(): """ Parse the command line arguments """ global default_device parser = argparse.ArgumentParser(description = "Generate password AEAD using YubiHSM", add_help=True ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device (default : "%s").' % default_device ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation.' ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation.' ) parser.add_argument('--key-handle', type=int, dest='key_handle', required=True, help='Key handle to use. Must have YHSM_ECB_BLOCK_ENCRYPT and/or YHSM_ECB_BLOCK_DECRYPT_CMP flag set.' ) parser.add_argument('-N', '--nonce', dest='nonce', required=True, help='Nonce to use. 6 bytes encoded as 12 chars hex.' ) parser.add_argument('--set', dest='set', action='store_true', default=False, help='Set password mode.' ) parser.add_argument('--validate', dest='validate', help='AEAD to validate.' ) parser.add_argument('--min_length', type=int, dest='min_len', required=False, default=20, help='Minimum length to pad passwords to (default: 20).' ) args = parser.parse_args() if args.set and args.validate: sys.stderr.write("Arguments --set and --validate are mutually exclusive.\n") sys.exit(1) if not args.set and not args.validate: sys.stderr.write("Either --set or --validate must be specified.\n") sys.exit(1) return args def generate_aead(hsm, args, password): """ Generate an AEAD using the YubiHSM. """ try: pw = password.ljust(args.min_len, chr(0x0)) return hsm.generate_aead_simple(args.nonce.decode('hex'), args.key_handle, pw) except pyhsm.exception.YHSM_CommandFailed, e: if e.status_str == 'YHSM_FUNCTION_DISABLED': print "ERROR: The key handle %s is not permitted to YSM_AEAD_GENERATE." % (args.key_handle) return None else: print "ERROR: %s" % (e.reason) def validate_aead(hsm, args, password): """ Validate a previously generated AEAD using the YubiHSM. """ try: pw = password.ljust(args.min_len, chr(0x0)) return hsm.validate_aead(args.nonce.decode('hex'), args.key_handle, args.validate.decode('hex'), pw) except pyhsm.exception.YHSM_CommandFailed, e: if e.status_str == 'YHSM_FUNCTION_DISABLED': print "ERROR: The key handle %s is not permitted to do AES ECB compare." % (args.key_handle) return None else: print "ERROR: %s" % (e.reason) def main(): args = parse_args() what="encrypt" if args.validate: what="validate" user_input = getpass.getpass('Enter password to %s : ' % (what)) if not user_input: print "\nAborted.\n" return 0 try: hsm = pyhsm.base.YHSM(device=args.device, debug=args.debug) except pyhsm.exception.YHSM_Error, e: print "ERROR: %s" % e return 1 if args.set: # # SET password # aead = generate_aead(hsm, args, user_input) if not aead: return 1 if args.verbose: print "Success! Remember the nonce and use this AEAD to validate the password later :\n" print "AEAD: %s NONCE: %s" % (aead.data.encode('hex'), args.nonce) else: # # VALIDATE password # if not validate_aead(hsm, args, user_input): if args.verbose: print "FAIL! Password does not match the generated AEAD." return 1 if args.verbose: print "OK! Password validated." return 0 if __name__ == '__main__': res = main() sys.exit(res) python-pyhsm-1.0.4l/examples/yhsm-sysinfo.py000077500000000000000000000013021256663164400212230ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # # Utility to show system information of a YubiHSM. # import sys sys.path.append('Lib'); import pyhsm device = "/dev/ttyACM0" # simplified arguments parsing d_argv = dict.fromkeys(sys.argv) debug = d_argv.has_key('-v') if d_argv.has_key('-h'): sys.stderr.write("Syntax: %s [-v]\n" % (sys.argv[0])) sys.exit(0) res = 0 try: s = pyhsm.base.YHSM(device=device, debug=debug) print "Version : %s" % (s.info()) nonce = s.get_nonce() print "Power-up count : %i" % (nonce.pu_count) except pyhsm.exception.YHSM_Error, e: print "ERROR: %s" % e res = 1 sys.exit(res) python-pyhsm-1.0.4l/maintainer-scripts/000077500000000000000000000000001256663164400202005ustar00rootroot00000000000000python-pyhsm-1.0.4l/maintainer-scripts/README000066400000000000000000000005141256663164400210600ustar00rootroot00000000000000All scripts should be run from the main directory. make-release.sh --------------- Creates, tags and signs a release, placing the resulting files in the dist/ directory. generate_html.sh ------------- Generates the HTML documentation in doc/html/. This file is called by make-release.sh and does not need to be called by itself. python-pyhsm-1.0.4l/maintainer-scripts/generate_html.sh000077500000000000000000000006271256663164400233620ustar00rootroot00000000000000#!/bin/sh if [ ! -d "Lib/pyhsm/" ]; then echo "$0: Directory Lib/pyhsm/ not found" exit 1 fi if [ ! -d "doc/" ]; then echo "$0: Directory doc/ not found" exit 1 fi test -d doc/html || mkdir doc/html/ if [ ! -d "doc/html/" ]; then echo "$0: Directory doc/html/ not found and could not be created" exit 1 fi epydoc -n pyhsm --no-private --no-sourcecode -v -o doc/html Lib/pyhsm/ python-pyhsm-1.0.4l/maintainer-scripts/make-release.sh000077500000000000000000000032341256663164400230740ustar00rootroot00000000000000#!/bin/bash if [ ! -f Lib/pyhsm/base.py ]; then echo "$0: Must be executed from top pyhsm dir." exit 1 fi do_test="true" if [ "x$1" == "x--no-test" ]; then do_test="false" shift fi keyid="$1" if [ "x$keyid" = "x" ]; then echo "Syntax: $0 [--no-test] " exit 1 fi set -e version=$(grep "version\s*=" setup.py | sed "s/^.\{1,\}version\s\{0,\}=\s\{0,\}'\(.\{1,\}\)'.\{1,\}$/\1/") sed -n -e 3p NEWS | grep -q "Version $version (released `date -I`)" || \ (echo 'error: You need to update date/version in NEWS'; exit 1) init_ver=$(grep __version__ Lib/pyhsm/__init__.py | awk -F \' '{print $2}') if [ "x$init_ver" != "x$version" ]; then echo "" echo "Lib/pyhsm/__init__.py version mismatch! ($init_ver != $version) Press enter to ignore." read foo fi if git tag | grep -q "^$version\$"; then echo "Tag $version already exists!" echo "Did you remember to update the version in setup.py?" exit 1 fi # update API documentation rm -rf doc/html ./maintainer-scripts/generate_html.sh git2cl > ChangeLog if [ "x$do_test" != "xfalse" ]; then # run all unit tests PYTHONPATH="Lib" ./Tests/run.sh fi python setup.py sdist gpg --detach-sign --default-key $keyid dist/pyhsm-$version.tar.gz gpg --verify dist/pyhsm-$version.tar.gz.sig git tag -s -u $keyid -m "python-pyhsm $version" $version #Publish release if test ! -d "$YUBICO_WWW_REPO"; then echo "warn: YUBICO_WWW_REPO not set or invalid!" echo " This release will not be published!" else $YUBICO_WWW_REPO/publish python-pyhsm $version dist/pyhsm-$version.tar.gz* fi echo "Done! Don't forget to git push && git push --tags" echo "" echo "Finished" echo "" ls -l dist/pyhsm-$version.tar.gz* python-pyhsm-1.0.4l/setup.cfg000066400000000000000000000000731256663164400162050ustar00rootroot00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 python-pyhsm-1.0.4l/setup.py000066400000000000000000000012651256663164400161020ustar00rootroot00000000000000#!/usr/bin/env python from setuptools import setup, find_packages from distutils import versionpredicate import sys sys.path.append('Tests'); setup(name = 'pyhsm', version = '1.0.4l', description = 'Python code for talking to a YubiHSM', author = 'Fredrik Thulin', author_email = 'fredrik@yubico.com', url = 'https://www.yubico.com/', license = 'BSD', packages = ['pyhsm'], package_dir = {'': 'Lib'}, test_suite = "test_init.suite", install_requires = ['pyserial >= 2.3', 'pycrypto >= 2.1', 'python-daemon >= 1.5', 'sqlalchemy >= 0.9.7'], ) python-pyhsm-1.0.4l/utils/000077500000000000000000000000001256663164400155245ustar00rootroot00000000000000python-pyhsm-1.0.4l/utils/yhsm-daemon000077500000000000000000000122741256663164400177010ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (C) 2013 Yubico AB. All rights reserved. # """ This is a daemon to allow multiple users of a YubiHSM without requiring permission to use the device. The daemon listens on a TCP port on localhost and allows multiple connections to share a YubiHSM. Access the YubiHSM via the daemon by specifying a device string following the yhsm://: syntax: hsm = YHSM('yhsm://localhost:5348') Note that the daemon and clients need to share the same version number to be compatible. """ import sys import socket import json import threading import argparse import pyhsm.stick import daemon import os CMD_WRITE = 0 CMD_READ = 1 CMD_FLUSH = 2 CMD_DRAIN = 3 CMD_LOCK = 4 CMD_UNLOCK = 5 COMMANDS = { CMD_WRITE: 'write', CMD_READ: 'read', CMD_FLUSH: 'flush', CMD_DRAIN: 'drain' } context = daemon.DaemonContext() def pack_data(data): if isinstance(data, basestring): return data.encode('base64') return data def unpack_data(data): if isinstance(data, basestring): return data.decode('base64') return data def write_pid_file(fn): """ Create a file with our PID. """ if not fn: return None if fn == '' or fn == "''": # work around argument passings in init-scripts return None f = open(fn, "w") f.write("%s\n" % (os.getpid())) f.close() class YHSM_Stick_Server(): def __init__(self, device, addr): self.device = device self._stick = None self.pidfile = None self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self.socket.bind(addr) self.lock = threading.Lock() def serve(self): write_pid_file(self.pidfile) self.socket.listen(20) try: while True: cs, address = self.socket.accept() thread = threading.Thread(target=self.client_handler, args=(cs,)) thread.start() except Exception as e: print e sys.exit(1) def invoke(self, cmd, *args): try: if not self._stick: self._stick = pyhsm.stick.YHSM_Stick(self.device) res = getattr(self._stick, COMMANDS[cmd])(*args) except Exception as e: res = e print e self._stick = None return res def client_handler(self, socket): socket_file = socket.makefile('wb') has_lock = False try: while True: data = json.loads(socket_file.readline()) cmd = data[0] args = map(unpack_data, data[1:]) if cmd == CMD_LOCK: if not has_lock: self.lock.acquire() has_lock = True elif has_lock: if cmd == CMD_UNLOCK: self.lock.release() has_lock = False else: res = self.invoke(cmd, *args) json.dump(pack_data(res), socket_file) socket_file.write("\n") socket_file.flush() else: err = 'Command run without holding lock!' print err json.dump({'error': err}, socket_file) socket_file.write("\n") socket_file.flush() break except Exception: # Client disconnected, ignore. pass finally: if has_lock: self.lock.release() socket_file.close() socket.close() if __name__ == '__main__': parser = argparse.ArgumentParser( description='YubiHSM server daemon', add_help=True, formatter_class=argparse.ArgumentDefaultsHelpFormatter ) parser.add_argument('-D', '--device', nargs='?', default='/dev/ttyACM0', help='device name') parser.add_argument('-d', '--daemon', default=False, action='store_true', help='run as daemon') parser.add_argument('-I', '--interface', nargs='?', default='localhost', help='network interface to bind to') parser.add_argument('-P', '--port', nargs='?', type=int, default=5348, help='TCP port to bind to') parser.add_argument('--pid-file', dest='pid_file', default=None, required=False, help='PID file', metavar='FILENAME') args = parser.parse_args() print 'Starting YubiHSM daemon for device: %s, listening on: %s:%d' % \ (args.device, args.interface, args.port) server = YHSM_Stick_Server(args.device, (args.interface, args.port)) print 'You can connect to the server using the following device string:' print 'yhsm://127.0.0.1:%d' % args.port server.pidfile = args.pid_file context.files_preserve = [server.socket] if args.daemon: with context: server.serve() else: server.serve() python-pyhsm-1.0.4l/utils/yhsm-daemon.1000066400000000000000000000024461256663164400200350ustar00rootroot00000000000000.\" Copyright (c) 2013-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-daemon "1" "May 2013" "python-pyhsm" .SH NAME yhsm-daemon \(hy Allow multiple users of a YubiHSM. .SH SYNOPSIS .B yhsm\-daemon [\fIoptions\fR] [device] [port] .SH DESCRIPTION This is a daemon to allow multiple users of a YubiHSM without requiring permission to use the device. The daemon listens on a TCP port on localhost and allows multiple connections to share a YubiHSM. Access the YubiHSM via the daemon by specifying a device string following the yhsm://: syntax: hsm = YHSM('yhsm://localhost:5348') Note that the daemon and clients need to share the same version number to be compatible. .SH OPTIONS .PP .TP \fB\-h\fR, \fB\-\-help\fR Shows this help message and exit .TP \fB\-D\fR, \fB\-\-device\fR YubiHSM device name .TP \fB\-I\fR, \fB\-\-interface\fR Network interface to bind to .TP \fB\-P\fR, \fB\-\-port\fR TCP port to bind to .SH BUGS Report python-pyhsm/yhsm-daemon bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs and YubiKeys can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-db-export000077500000000000000000000053771256663164400203500ustar00rootroot00000000000000#!/usr/bin/python # # Copyright (c) 2013-2014 Yubico AB # See the file COPYING for licence statement. # """ Export AEAD from database. """ import os import sys import io import hashlib import re import time import errno import argparse import sqlalchemy from os.path import abspath sys.path.append('Lib') from pyhsm.util import key_handle_to_int import pyhsm.aead_cmd ########################## # Functions Declarartion # ########################## # #insert_slash insert / every 2 char # def insert_slash(string, every=2): return '/'.join(string[i:i+every] for i in xrange(0, len(string), every)) # #mkdir -p: creates path like mkdir -p # def mkdir_p(path): try: os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise ################################# # END of functions declariation # ################################# ####################### # # # Initialization Area # # # ####################### parser = argparse.ArgumentParser(description='Import AEADs into the database') parser.add_argument('path', action="store", type=str) parser.add_argument('dburl', action="store") args = vars(parser.parse_args()) if len(sys.argv) != 3: print("\nUsage: python export_aeads.py /path/to/export/ database_url\ni.e. python export_aeads.py /root/aeads/ mysql://root:password@localhost:3306/database_name") sys.exit(2) if not os.path.isdir(sys.argv[1]): print("\nInvalid path, check your spelling.\n") sys.exit(2) #set the path path = args['path'] #mysql url databaseUrl = args['dburl'] try: #check database connection engine = sqlalchemy.create_engine(databaseUrl) #SQLAlchemy voodoo metadata = sqlalchemy.MetaData() aeadobj = sqlalchemy.Table('aead_table', metadata, autoload=True, autoload_with=engine) connection = engine.connect() except: print "FATAL: Database connect failure" sys.exit(1) aead = None nonce = None key_handle = None aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(nonce, key_handle, aead) #get data from the database result = connection.execute("SELECT * from aead_table") #cycle through resutls for row in result: #read values row by row aead.data = row['aead'] publicId = row['public_id'] aead.key_handle = row['keyhandle'] aead.nonce = row['nonce'] path = ''.join([path, '/', str(hex(aead.key_handle)).rstrip('L'), '/', insert_slash(publicId)]) #sanitize path path = os.path.normpath(path) #create path mkdir_p(path) #write the file in the path pyhsm.aead_cmd.YHSM_GeneratedAEAD.save(aead, path+'/'+publicId) #reset path constructor path = sys.argv[1] #close connection connection.close() #exit without error sys.exit(0) python-pyhsm-1.0.4l/utils/yhsm-db-export.1000066400000000000000000000015171256663164400204740ustar00rootroot00000000000000.\" Copyright (c) 2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-db-export "1" "September 2014" "python-pyhsm" .SH NAME yhsm-db-export \(hy Export AEADs from a database to a filesystem structure .SH SYNOPSIS .B yhsm-db-export [\fIoptions\fR] .SH DESCRIPTION Use this program to export AEADs from a sql database to a filesystem structure. .SH OPTIONS .PP .TP \fB\-\-path\fR filesystem path of where to put AEADs .TP \fB\-\-dburl\fR connection URL for the database .SH BUGS Report python-pyhsm/yhsm-db-export bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-db-import000077500000000000000000000071321256663164400203300ustar00rootroot00000000000000#!/usr/bin/python # # Copyright (c) 2013-2014 Yubico AB # See the file COPYING for licence statement. # """ Import AEADs to database. """ #import lib import os import sys import io import hashlib import re import time import argparse import sqlalchemy from os.path import abspath sys.path.append('Lib') from pyhsm.util import key_handle_to_int from pyhsm.yubikey import modhex_decode import pyhsm.aead_cmd ########################## # Functions Declarations # ########################## # # extract keyhandle value from the path # def extract_keyhandle(path, filepath): keyhandle = filepath.lstrip(path) keyhandle = keyhandle.split("/") return keyhandle[0] # #insert_query: this functions read the response fields and creates sql query. then inserts everything inside the database # def insert_query(publicId, aead, keyhandle, aeadobj): #turn the keyhandle into an integer keyhandle = key_handle_to_int(keyhandle) if not keyhandle == aead.key_handle: print "WARNING: keyhandle does not match aead.key_handle" return None #creates the query object try: sql = aeadobj.insert().values(public_id=publicId, keyhandle=aead.key_handle, nonce=aead.nonce, aead=aead.data) #insert the query result = connection.execute(sql) return result except sqlalchemy.exc.IntegrityError: pass return None; ################################# # END of functions declariation # ################################# ####################### # # # Initialization Area # # # ####################### parser = argparse.ArgumentParser(description='Import AEADs into the database') parser.add_argument('path', action="store", type=str) parser.add_argument('dburl', action="store") args = vars(parser.parse_args()) if len(sys.argv) != 3: print("\nUsage: python import_aeads.py /path/to/keyhandle/ database_url\ni.e. python import_aeads.py /root/aeads/ mysql://root:password@localhost:3306/database_name") sys.exit(2) if not os.path.isdir(sys.argv[1]): print("\nInvalid path, check your spelling.\n") sys.exit(2) #set the path path = args['path'] #mysql url databaseUrl = args['dburl'] try: #check database connection engine = sqlalchemy.create_engine(databaseUrl) #SQLAlchemy voodoo metadata = sqlalchemy.MetaData() aeadobj = sqlalchemy.Table('aead_table', metadata, autoload=True, autoload_with=engine) connection = engine.connect() except: print "FATAL: Database connect failure" sys.exit(1) #################### # Computation area # #################### for root, subFolders, files in os.walk(path): if files: aead = None nonce = None key_handle = None if not re.match(r'^[cbdefghijklnrtuv]+$', files[0]): continue #build file path filepath = os.path.join(root,files[0]) #extract the key handle from the path keyhandle = extract_keyhandle(path, filepath) kh_int = pyhsm.util.key_handle_to_int(keyhandle) #instantiate a new aead object aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(None, kh_int, '') aead.load(filepath) #set the public_id public_id = str(files[0]) #check it is old format aead if not aead.nonce: #configure values for oldformat aead.nonce = pyhsm.yubikey.modhex_decode(public_id).decode('hex') aead.key_handle = key_handle_to_int(keyhandle) if not insert_query(public_id, aead, keyhandle, aeadobj): print "WARNING: could not insert %s" % public_id #close sqlalchemy connection.close() #exit without error sys.exit(0) python-pyhsm-1.0.4l/utils/yhsm-db-import.1000066400000000000000000000015041256663164400204610ustar00rootroot00000000000000.\" Copyright (c) 2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-db-import "1" "September 2014" "python-pyhsm" .SH NAME yhsm-db-import \(hy Import AEADs from filesystem to database .SH SYNOPSIS .B yhsm-db-import [\fIoptions\fR] .SH DESCRIPTION Use this program to import AEADs from a filesystem structure into a sql database. .SH OPTIONS .PP .TP \fB\-\-path\fR filesystem path of where to find AEADs .TP \fB\-\-dburl\fR connection URL for the database .SH BUGS Report python-pyhsm/yhsm-db-import bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-decrypt-aead000077500000000000000000000256021256663164400207770ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (C) 2012-2013 Yubico AB. All rights reserved. # """ This is a tool to decrypt AEADs generated using a YubiHSM, provided that you know the key_handle used as well as the AES key used. This can be used together with yhsm-generate-keys to generate a number of AEADs, and then decrypt them to program YubiKeys accordingly. """ import os import re import sys import fcntl import argparse import traceback import pyhsm args = None yknum = 0 def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = 'Decrypt AEADs', add_help = True, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation', ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation', ) parser.add_argument('--format', dest='format', default='raw', help='Select output format (aead, raw or yubikey-csv)', ) parser.add_argument('--output-dir', dest='output_dir', help='Output dir basename (for --format aead)', metavar='DIR', ) parser.add_argument('--print-filename', dest='print_filename', action='store_true', default=False, help='Prefix each row with the AEAD filename', ) parser.add_argument('--key-handle', dest='key_handle', help='Key handle used when generating the AEADs.', metavar='HANDLE', ) parser.add_argument('--key-handle-out', dest='key_handle_out', help='Key handle used when generating *new* AEADs (with --format aead).', metavar='HANDLE', ) parser.add_argument('--aes-key', dest='aes_key', required=True, help='AES key used when generating the AEADs.', metavar='HEXSTR', ) parser.add_argument('--aes-key-out', dest='aes_key_out', required=False, help='AES key used when generating *new* AEADs (with --format aead).', metavar='HEXSTR', ) parser.add_argument('--start-public-id', dest='start_id', required=False, default=None, help='The first public id to decrypt', metavar='INT-OR-MODHEX', ) parser.add_argument('--stop-public-id', dest='stop_id', required=False, default=None, help='The last public id to decrypt', metavar='INT-OR-MODHEX', ) parser.add_argument('--fail-fast', dest='fail_fast', action='store_true', default=False, help='Terminate on the first AEAD failure, rather than keep going.', ) parser.add_argument('paths', nargs='+', help='Files and/or directories to process.', metavar='FILE-OR-DIR' ) args = parser.parse_args() # argument fixups args.format = args.format.lower() args.aes_key = args.aes_key.decode('hex') if args.key_handle: args.key_handle = pyhsm.util.key_handle_to_int(args.key_handle) if args.start_id is not None: try: n = int(args.start_id) except ValueError: hexstr = pyhsm.yubikey.modhex_decode(args.start_id) n = int(hexstr, 16) args.start_id = n if args.stop_id is not None: try: n = int(args.stop_id) except ValueError: hexstr = pyhsm.yubikey.modhex_decode(args.stop_id) n = int(hexstr, 16) args.stop_id = n # some checks if args.format == 'aead': if not args.output_dir: sys.stderr.write("error: --output-dir is required when using --format aead.\n") return False if not os.path.isdir(args.output_dir): sys.stderr.write("error: Output directory '%s' not found\n" % (args.output_dir)) return False if not args.aes_key_out: sys.stderr.write("error: --aes-key-out is required when using --format aead.\n") return False if not args.key_handle_out: sys.stderr.write("error: --key-handle-out is required when using --format aead.\n") return False # argument fixups args.aes_key_out = args.aes_key_out.decode('hex') args.key_handle_out_orig = args.key_handle_out # save to use in AEAD output paths args.key_handle_out = pyhsm.util.key_handle_to_int(args.key_handle_out) return args class MyState(): """ Class to keep track of failed files. """ def __init__(self, args): self.args = args self.failed_files = [] self.file_count = 0 def log_failed(self, fn): self.failed_files.append(fn) self.file_count += 1 def log_success(self, fn): self.file_count += 1 def should_quit(self): return (self.failed_files and self.args.fail_fast) def process_file(path, fn, args, state): """ The main function for reading a file and decrypting it. """ full_fn = os.path.join(path, fn) if not re.match("^[cbdefghijklnrtuv]+$", fn): if args.debug: sys.stderr.write("warning: Ignoring non-modhex file '%s'\n" % (full_fn)) return True if (args.start_id is not None) or (args.stop_id is not None): this = int(pyhsm.yubikey.modhex_decode(fn), 16) if (args.start_id is not None) and this < args.start_id: if args.debug: sys.stderr.write("warning: Skipping public id %s (%i) < %i\n" % (fn, this, args.start_id)) return True if (args.stop_id is not None) and this > args.stop_id: if args.debug: sys.stderr.write("warning: Skipping public id %s (%i) > %i\n" % (fn, this, args.stop_id)) return True if args.debug: sys.stderr.write("Loading AEAD : %s\n" % full_fn) aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(None, None, '') aead.load(full_fn) if not aead.nonce: # AEAD file version 0, need to fill in nonce etc. if args.key_handle is None: sys.stderr.write("error: AEAD in file %s does not include key_handle, and none provided.\n" % (full_fn)) state.log_failed(full_fn) return False aead.key_handle = args.key_handle aead.nonce = pyhsm.yubikey.modhex_decode(fn).decode('hex') if args.debug: sys.stderr.write("%s\n" % aead) sys.stderr.write("AEAD len %i : %s\n" % (len(aead.data), aead.data.encode('hex'))) pt = pyhsm.soft_hsm.aesCCM(args.aes_key, aead.key_handle, aead.nonce, aead.data, decrypt = True) if args.print_filename: print("%s " % (full_fn)), if args.format == 'raw': print(pt.encode('hex')) elif args.format == 'aead': # encrypt secrets with new key ct = pyhsm.soft_hsm.aesCCM(args.aes_key_out, args.key_handle_out, aead.nonce, pt, decrypt = False) aead_out = pyhsm.aead_cmd.YHSM_GeneratedAEAD(aead.nonce, args.key_handle_out, ct) filename = aead_filename(args.output_dir, args.key_handle_out_orig, fn) aead_out.save(filename) if args.print_filename: print "" elif args.format == 'yubikey-csv': key = pt[:pyhsm.defines.KEY_SIZE] uid = pt[pyhsm.defines.KEY_SIZE:] access_code = '00' * 6 timestamp = '' global yknum yknum += 1 print("%i,%s,%s,%s,%s,%s,,,,," % (yknum, fn, uid.encode('hex'), key.encode('hex'), access_code, timestamp, )) state.log_success(full_fn) return True def aead_filename(aead_dir, key_handle, public_id): """ Return the filename of the AEAD for this public_id, and create any missing directorys. """ parts = [aead_dir, key_handle] + pyhsm.util.group(public_id, 2) path = os.path.join(*parts) if not os.path.isdir(path): os.makedirs(path) return os.path.join(path, public_id) def safe_process_files(path, files, args, state): """ Process a number of files in a directory. Catches any exception from the processing and checks if we should fail directly or keep going. """ for fn in files: full_fn = os.path.join(path, fn) try: if not process_file(path, fn, args, state): return False except Exception, e: sys.stderr.write("error: %s\n%s\n" % (os.path.join(path, fn), traceback.format_exc())) state.log_failed(full_fn) if state.should_quit(): return False return True def walk_dir(path, args, state): """ Check all files in `path' to see if there is any requests that we should send out on the bus. """ if args.debug: sys.stderr.write("Walking %s\n" % path) for root, _dirs, files in os.walk(path): if not safe_process_files(root, files, args, state): return False if state.should_quit(): return False return True def main(): """ Main function when running as a program. """ global args args = parse_args() if not args: return False state = MyState(args) for path in args.paths: if os.path.isdir(path): walk_dir(path, args, state) else: safe_process_files(os.path.dirname(path), [os.path.basename(path)], args, state) if state.should_quit(): break if state.failed_files: sys.stderr.write("error: %i/%i AEADs failed\n" % (len(state.failed_files), state.file_count)) return False if args.debug: sys.stderr.write("Successfully processed %i AEADs\n" % (state.file_count)) return True if __name__ == '__main__': if main(): sys.exit(0) sys.exit(1) python-pyhsm-1.0.4l/utils/yhsm-decrypt-aead.1000066400000000000000000000030521256663164400211260ustar00rootroot00000000000000.\" Copyright (c) 2012-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-decrypt-aead "1" "June 2012" "python-pyhsm" .SH NAME yhsm-decrypt-aead \(hy Decrypt AEADs (with secrets for YubiKeys) .SH SYNOPSIS .B yhsm\-decrypt\-aead [\fIoptions\fR] \-\-aes\-key KEY file-or-dir [...] .SH DESCRIPTION Decrypt AEADs generated using a YubiHSM. \fBNOTE\fR that this requires knowledge of the AES key used in the YubiHSM. After a number of YubiKey secrets have been generated using .BR yhsm-generate-keys (1) , this tool can decrypt them and produce a CSV file usable to personalize corresponding YubiKeys. .SH OPTIONS .PP .TP \fB\-v\fR, \fB\-\-verbose\fR Enable verbose operation. .TP \fB\-\-debug\fR Enable debug printout. .TP \fB\-\-format str\fR Select output format (raw or yubikey-csv). .TP \fB\-\-print\-filename\fR Prefix any output with the input filename. .TP \fB\-\-key\-handle kh\fR Key handle used when generated AEADs, if not stored in the AEAD file (AEAD generated with python-pyhsm 1.0.3 or lower). .TP \fB\-\-aes\-key hexstr\fR AES key used to generate the AEADs. .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" OK .IP "\fB1\fR" 4 .IX Item "1" Fail .SH BUGS Report python-pyhsm/yhsm-decrypt-aead bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs and YubiKeys can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-generate-keys000077500000000000000000000155541256663164400212050ustar00rootroot00000000000000#!/usr/bin/env python # """ Tool to generate YubiKey secret keys using YubiHSM. After generation with this tool, you can (given that you know the AES key for the key handle used in the HSM) generate a CSV file of the unencrypted AEADs formatted for YubiKey personalization using the YubiKey multi configuration utility (Windows) using the command yhsm-decrypt-aead. Example : 1) Configure HSM with key handle 99 having key 2000200020002000200020002000200020002000200020002000200020002000 2) Generate 1000 AEADs for YubiKeys using something like this (XXXX can be a customer specific public_id prefix allocated by Yubico - 0000-0009 (in modhex) are for tests) $ yhsm-generate-keys --key-handles 99 --start-public-id djXXXXcccccc \ -O /var/cache/yubikey-ksm/aeads --count 1000 3) Create CSV-file with $ yhsm-decrypt-aead --aes-key 2000...2000 --format yubikey-csv \ /var/cache/yubikey-ksm/aeads 4) Program YubiKeys using CSV file contents 5) Start a KSM to decrypt OTPs from the YubiKeys $ yhsm-yubikey-ksm --key-handle 99 """ # # Copyright (c) 2011, 2012 Yubico AB # See the file COPYING for licence statement. # import os import sys import argparse sys.path.append('Lib') import pyhsm import pyhsm.yubikey default_device = "/dev/ttyACM0" default_dir = "/var/cache/yubikey-ksm/aeads" def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Generate secrets for YubiKeys using YubiHSM", add_help=True, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-O', '--output-dir', '--aead-dir', dest='output_dir', default=default_dir, required=False, help='Output directory (AEAD base dir)', ) parser.add_argument('-c', '--count', dest='count', type=int, default=1, required=False, help='Number of secrets to generate', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation', ) parser.add_argument('--public-id-chars', dest='public_id_chars', type=int, default=12, required=False, help='Number of chars in generated public ids', ) parser.add_argument('--key-handles', dest='key_handles', nargs='+', required=True, help='Key handles to encrypt the generated secrets with', ) parser.add_argument('--start-public-id', dest='start_id', required=True, help='The first public id to generate AEAD for', ) parser.add_argument('--random-nonce', dest='random_nonce', required=False, action='store_true', default=False, help='Let the HSM generate nonce', ) return parser.parse_args() def args_fixup(args): if not os.path.isdir(args.output_dir): sys.stderr.write("Output directory '%s' does not exist.\n" % (args.output_dir)) sys.exit(1) keyhandles_fixup(args) try: n = int(args.start_id) except ValueError: hexstr = pyhsm.yubikey.modhex_decode(args.start_id) n = int(hexstr, 16) if(n <= 0): sys.stderr.write("Start ID must be greater than 0, was %d\n" % (n)) sys.exit(1) args.start_id = n def keyhandles_fixup(args): """ Walk through the supplied key handles and normalize them, while keeping the input format too (as value in a dictionary). The input format is used in AEAD filename paths. """ new_handles = {} for val in args.key_handles: for this in val.split(','): n = pyhsm.util.key_handle_to_int(this) new_handles[n] = this args.key_handles = new_handles def gen_keys(hsm, args): """ The main key generating loop. """ if args.verbose: print "Generating %i keys :\n" % (args.count) else: print "Generating %i keys" % (args.count) for int_id in range(args.start_id, args.start_id + args.count): public_id = ("%x" % int_id).rjust(args.public_id_chars, '0') padded_id = pyhsm.yubikey.modhex_encode(public_id) if args.verbose: print " %s" % (padded_id) num_bytes = len(pyhsm.aead_cmd.YHSM_YubiKeySecret('a' * 16, 'b' * 6).pack()) hsm.load_random(num_bytes) for kh in args.key_handles.keys(): if args.random_nonce: nonce = "" else: nonce = public_id.decode('hex') aead = hsm.generate_aead(nonce, kh) filename = output_filename(args.output_dir, args.key_handles[kh], padded_id) if args.verbose: print " %4s, %i bytes (%s) -> %s" % \ (args.key_handles[kh], len(aead.data), shorten_aead(aead), filename) aead.save(filename) if args.verbose: print "" print "\nDone\n" def shorten_aead(aead): """ Produce pretty-printable version of long AEAD. """ head = aead.data[:4].encode('hex') tail = aead.data[-4:].encode('hex') return "%s...%s" % (head, tail) def output_filename(output_dir, key_handle, public_id): """ Return an output filename for a generated AEAD. Creates a hashed directory structure using the last three bytes of the public id to get equal usage. """ parts = [output_dir, key_handle] + pyhsm.util.group(public_id, 2) path = os.path.join(*parts) if not os.path.isdir(path): os.makedirs(path) return os.path.join(path, public_id) def main(): args = parse_args() args_fixup(args) print "output dir : %s" % (args.output_dir) print "keys to generate : %s" % (args.count) print "key handles : %s" % (args.key_handles) print "start public_id : %s (0x%x)" % (args.start_id, args.start_id) print "YHSM device : %s" % (args.device) print "" hsm = pyhsm.YHSM(device = args.device) gen_keys(hsm, args) if __name__ == '__main__': if main(): sys.exit(0) sys.exit(1) python-pyhsm-1.0.4l/utils/yhsm-generate-keys.1000066400000000000000000000041541256663164400213330ustar00rootroot00000000000000.\" Copyright (c) 2012-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-generate-keys "1" "June 2012" "python-pyhsm" .SH NAME yhsm-generate-keys \(hy Generate AEADs with secrets for YubiKeys using a YubiHSM .SH SYNOPSIS .B yhsm\-generate\-keys \-\-key\-handles KEY_HANDLES \-\-start\-public\-id START_ID [\fIoptions\fR] .SH DESCRIPTION With this tool, a YubiHSM can generate random secrets (using it's internal true random number generator), and these secrets protected in AEAD files can be stored on the host computer. The AEADs will be ready to be used by for example .BR yhsm-yubikey-ksm (1) ), as a part of a YubiKey OTP validation service. To program YubiKeys with the generated secrets, it is possible to decrypt the AEADs (knowledge of the AES key used inside the YubiHSM is required) using .BR yhsm-decrypt-aead (1) . .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR Device file name (default: /dev/ttyACM0). .TP \fB\-v\fR, \fB\-\-verbose\fR Enable verbose operation. .TP \fB\-\-debug\fR Enable debug printout, including all data sent to/from YubiHSM. .TP \fB\-O dir\fR Base output directory (default: /var/cache/yubikey-ksm/aeads). .TP \fB\-c integer\fR Number of AEADs to generate. .TP \fB\-\-public\-id\-chars integer\fR Number of chars in generated public ids (default: 12). Changing this might not work well. .TP \fB\-\-key\-handles kh [kh ...]\fR Key handles to encrypt the generated secrets with. Examples : "1", "0xabcd". .TP \fB\-\-start\-public\-id id\fR Public id of the first generated secret, in modhex. .TP \fB\-\-random\-nonce\fR Use random nonce generated from YubiHSM. .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" Secrets generated successfully. .IP "\fB1\fR" 4 .IX Item "1" Failed to generate secrets. .SH BUGS Report python-pyhsm/yhsm-generate-keys bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs and YubiKeys can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-keystore-unlock000077500000000000000000000103231256663164400215650ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # """ Utility to unlock the key store of a YubiHSM, using the 'HSM password'/'master key'. """ import sys sys.path.append('Lib') import pyhsm import argparse import getpass default_device = "/dev/ttyACM0" def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Unlock key store of YubiHSM", add_help = True, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation' ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation' ) parser.add_argument('--no-otp', dest='no_otp', action='store_true', default=False, help='Don\'t ask for OTP, even if YubiHSM supports it', ) parser.add_argument('--stdin', dest='stdin', action='store_true', default=False, help='Read data from stdin instead of prompting', ) args = parser.parse_args() return args def get_password(hsm, args): """ Get password of correct length for this YubiHSM version. """ expected_len = 32 name = 'HSM password' if hsm.version.have_key_store_decrypt(): expected_len = 64 name = 'master key' if args.stdin: password = sys.stdin.readline() while password and password[-1] == '\n': password = password[:-1] else: if args.debug: password = raw_input('Enter %s (press enter to skip) (will be echoed) : ' % (name)) else: password = getpass.getpass('Enter %s (press enter to skip) : ' % (name)) if len(password) <= expected_len: password = password.decode('hex') if not password: return None return password else: sys.stderr.write("ERROR: Invalid HSM password (expected max %i chars, got %i)\n" % \ (expected_len, len(password))) return 1 def get_otp(hsm, args): """ Get OTP from YubiKey. """ if args.no_otp: return None if hsm.version.have_unlock(): if args.stdin: otp = sys.stdin.readline() while otp and otp[-1] == '\n': otp = otp[:-1] else: otp = raw_input('Enter admin YubiKey OTP (press enter to skip) : ') if len(otp) == 44: # YubiHSM admin OTP's always have a public_id length of 6 bytes return otp if otp: sys.stderr.write("ERROR: Invalid YubiKey OTP\n") return None def main(): """ What will be executed when running as a stand alone program. """ args = parse_args() try: hsm = pyhsm.base.YHSM(device=args.device, debug=args.debug) if args.debug or args.verbose: print "Device : %s" % (args.device) print "Version : %s" % (hsm.info()) print "" password = get_password(hsm, args) otp = get_otp(hsm, args) if not password and not otp: print "\nAborted\n" return 1 else: if args.debug or args.verbose: print "" if hsm.unlock(password = password, otp = otp): if args.debug or args.verbose: print "OK\n" except pyhsm.exception.YHSM_Error, e: sys.stderr.write("ERROR: %s\n" % (e.reason)) return 1 return 0 if __name__ == '__main__': sys.exit(main()) python-pyhsm-1.0.4l/utils/yhsm-keystore-unlock.1000066400000000000000000000046171256663164400217320ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-keystore-unlock "1" "December 2011" "python-pyhsm" .SH NAME yhsm-keystore-unlock \(hy Unlock the keystore in a YubiHSM .SH SYNOPSIS .B yhsm-keystore-unlock [\fIoptions\fR] .SH DESCRIPTION In versions of the YubiHSM before 1.0, the YubiHSM could be protected using a 'HSM password'. The YubiHSM would unlock it's cryptographic functions if the correct password was given, but it was a simple comparision test. In YubiHSM 1.0, the password was changed into an actual key that was used to decrypt the contents of the YubiHSM internal key store, which was then AES-256 encrypted using the new 'Master key' when stored in the device. In YubiHSM 1.0, the option to also require an YubiKey OTP to unlock the keystore was also added. One or more 'Admin YubiKeys' can be configured in the YubiHSM, and an OTP from one of these must also be provided before the YubiHSM will enable it's cryptographic functions. The OTP is simply validated against the non-encrypted internal database (not key store) in the YubiHSM though, but together with a 'Master key' not stored on the server with the YubiHSM, it provides enhanced security by being a second factor that an attacker can't just intercept even if the server is compromised. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0). .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation. .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM. .TP \fB\-\-no-otp\fR skip the prompt for an OTP. For use by scripts where no OTP is required and the Master Key is stored on the server with the YubiHSM. .TP \fB\-\-stdin\fR read password and/or OTP from stdin rather than prompting for them. Python prompts does not accept piped input, so this option have to be used to unlock the YubiHSM from a script for example. .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" YubiHSM keystore successfully unlocked. .IP "\fB1\fR" 4 .IX Item "1" Failed to unlock keystore. .SH BUGS Report python-pyhsm/yhsm-keystore-unlock bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/utils/yhsm-linux-add-entropy000077500000000000000000000061531256663164400220200ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # """ Get random data from TRNG on YubiHSM and insert it into host entropy pool. Probably only works on Linux since the ioctl() request value RNDADDENTROPY seems Linux specific. """ import os import sys import fcntl import struct import argparse sys.path.append('Lib') import pyhsm default_device = "/dev/ttyACM0" default_iterations = 100 default_entropy_ratio = 2 # number of bits of entropy per byte of random data RNDADDENTROPY = 1074287107 # from /usr/include/linux/random.h def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Add random data from YubiHSM to Linux entropy", add_help = True, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation' ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation' ) parser.add_argument('-r', '--ratio', dest='ratio', type=int, default=default_entropy_ratio, help='Bits per byte of data read to use as entropy', ) parser.add_argument('-c', '--count', dest='iterations', type=int, default=default_iterations, help='Number of iterations to run', ) args = parser.parse_args() return args def get_entropy(hsm, iterations, entropy_ratio): """ Read entropy from YubiHSM and feed it to Linux as entropy using ioctl() syscall. """ fd = os.open("/dev/random", os.O_WRONLY) # struct rand_pool_info { # int entropy_count; # int buf_size; # __u32 buf[0]; # }; fmt = 'ii%is' % (pyhsm.defines.YSM_MAX_PKT_SIZE - 1) for _ in xrange(iterations): rnd = hsm.random(pyhsm.defines.YSM_MAX_PKT_SIZE - 1) this = struct.pack(fmt, entropy_ratio * len(rnd), len(rnd), rnd) fcntl.ioctl(fd, RNDADDENTROPY, this) os.close(fd) def main(): """ What will be executed when running as a stand alone program. """ args = parse_args() try: s = pyhsm.base.YHSM(device=args.device, debug=args.debug) get_entropy(s, args.iterations, args.ratio) return 0 except pyhsm.exception.YHSM_Error, e: sys.stderr.write("ERROR: %s" % (e.reason)) return 1 if __name__ == '__main__': sys.exit(main()) python-pyhsm-1.0.4l/utils/yhsm-linux-add-entropy.1000066400000000000000000000037521256663164400221560ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-linux-add-entropy "1" "December 2011" "python-pyhsm" .SH NAME yhsm-linux-add-entropy \(hy Seed the Linux entropy pool with data from YubiHSM TRNG .SH SYNOPSIS .B yhsm-linux-add-entropy [\fIoptions\fR] .SH DESCRIPTION The YubiHSM uses "Avalanche Noise" TRNG together with USB SOF jitter sampling to feed a DRBG_CTR algorithm (NIST publication SP800-90). The result has been verified as being random data of good quality by at least one third party cryptographer. .URL "http://sartryck.idg.se/Art/Yubihsm_1_TW072011.html" Use this program to add random data from the YubiHSM to the entropy pool of your Linux operating system. This is useful whenever lots of random data is needed, such as when generating chryptographic keys (GPG-keys), on a server terminating SSL sessions etc. You may run this script from cron, or in a while-loop. Make sure it does not run at the same time as something else accessing the YubiHSM though, or the two tasks may interrupt each other \(hy probably making both fail. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0). .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation. .TP \fB\-c\fR, \fB\-\-count\fR number of iterations to run (default: 100). .TP \fB\-r\fR, \fB\-\-ratio\fR bits per byte read to use. 8 is probably fine, but as a conservative default 2 is used. .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM. .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" Entropy added successfully .IP "\fB1\fR" 4 .IX Item "1" Failure .SH BUGS Report python-pyhsm/yhsm-linux-add-entropy bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/yhsm-val/000077500000000000000000000000001256663164400161245ustar00rootroot00000000000000python-pyhsm-1.0.4l/yhsm-val/yhsm-init-oath-token000077500000000000000000000174001256663164400220440ustar00rootroot00000000000000#!/usr/bin/env python # # Tool to add an OATH token to the yhsm-validation-server database. # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # import sys import struct import sqlite3 import argparse sys.path.append('Lib'); import pyhsm import pyhsm.oath_hotp default_device = "/dev/ttyACM0" default_db_file = "/var/yubico/yhsm-validation-server.db" def parse_args(): """ Parse the command line arguments """ global default_device parser = argparse.ArgumentParser(description = 'Initialize OATH token for use with yhsm-validation-server', add_help=True, formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation', ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation', ) parser.add_argument('--force', dest='force', action='store_true', default=False, help='Overwrite any present entry', ) parser.add_argument('--key-handle', dest='key_handle', required=True, help='Key handle to create AEAD', metavar='HANDLE', ) parser.add_argument('--uid', dest='uid', required=True, help='User ID', metavar='STR', ) parser.add_argument('--oath-c', dest='oath_c', required=False, default = 0, help='Initial OATH counter value', metavar='INT', ) parser.add_argument('--test-oath-window', dest='look_ahead', required=False, default = 10, help='Number of codes to search with --test-code', metavar='INT', ) parser.add_argument('--test-code', dest='test_code', type=int, required=False, help='Optional OTP from token for verification', metavar='INT', ) parser.add_argument('--oath-k', dest='oath_k', required=False, help='The secret key of the token, hex encoded', metavar='HEXSTR', ) parser.add_argument('--db-file', dest='db_file', default=default_db_file, required=False, help='DB file for storing AEAD\'s for --pwhash and --oath in the yhsm-validation-server', metavar='FN', ) args = parser.parse_args() return args def args_fixup(args): keyhandles_fixup(args) def keyhandles_fixup(args): args.key_handle = pyhsm.util.key_handle_to_int(args.key_handle) def generate_aead(hsm, args): """ Protect the oath-k in an AEAD. """ key = get_oath_k(args) # Enabled flags 00010000 = YSM_HMAC_SHA1_GENERATE flags = struct.pack("< I", 0x10000) hsm.load_secret(key + flags) nonce = hsm.get_nonce().nonce aead = hsm.generate_aead(nonce, args.key_handle) if args.debug: print "AEAD: %s (%s)" % (aead.data.encode('hex'), aead) return nonce, aead def validate_oath_c(hsm, args, nonce, aead): if args.test_code: if args.verbose: print "Trying to validate the OATH counter value in the range %i..%i." \ % (args.oath_c, args.oath_c + args.look_ahead) counter = pyhsm.oath_hotp.search_for_oath_code(hsm, args.key_handle, nonce, aead, \ args.oath_c, args.test_code, args.look_ahead \ ) if type(counter) != int: sys.stderr.write("Failed validating OTP %s (in range %i..%i) using supplied key.\n" \ % (args.test_code, args.oath_c, args.oath_c + args.look_ahead)) sys.exit(1) if args.verbose: print "OATH C==%i validated with code %s" % (counter - 1, args.test_code) return counter return args.oath_c def get_oath_k(args): """ Get the OATH K value (secret key), either from args or by prompting. """ if args.oath_k: decoded = args.oath_k.decode('hex') else: t = raw_input("Enter OATH key (hex encoded) : ") decoded = t.decode('hex') if len(decoded) != 20: sys.stderr.write("Supplied OATH key is not 20 bytes (%i).\n" % (len(decoded))) sys.exit(1) return decoded class ValOathDb(): """ Provides access to database with AEAD's and other information. """ def __init__(self, filename): self.filename = filename self.conn = sqlite3.connect(self.filename) self.create_table() def create_table(self): c = self.conn.cursor() c.execute("CREATE TABLE IF NOT EXISTS oath " \ "(key TEXT PRIMARY KEY, nonce TEXT, key_handle INTEGER, aead TEXT, oath_C INTEGER, oath_T INTEGER)") def add(self, entry): """ Add entry to database. """ c = self.conn.cursor() c.execute("INSERT INTO oath (key, aead, nonce, key_handle, oath_C, oath_T) VALUES (?, ?, ?, ?, ?, ?)", (entry.data["key"], \ entry.data["aead"], \ entry.data["nonce"], \ entry.data["key_handle"], \ entry.data["oath_C"], \ entry.data["oath_T"],)) self.conn.commit() return c.rowcount == 1 def delete(self, entry): """ Delete entry from database. """ c = self.conn.cursor() c.execute("DELETE FROM oath WHERE key = ?", (entry.data["key"],)) class ValOathEntry(): """ Class to hold a row of ValOathDb. """ def __init__(self, row): if row: self.data = row def store_oath_entry(args, nonce, aead, oath_c): """ Store the AEAD in the database. """ data = {"key": args.uid, "aead": aead.data.encode('hex'), "nonce": nonce.encode('hex'), "key_handle": args.key_handle, "oath_C": oath_c, "oath_T": None, } entry = ValOathEntry(data) db = ValOathDb(args.db_file) try: if args.force: db.delete(entry) db.add(entry) except sqlite3.IntegrityError, e: sys.stderr.write("ERROR: %s\n" % (e)) return False return True def main(): args = parse_args() args_fixup(args) print "Key handle : %s" % (args.key_handle) print "YHSM device : %s" % (args.device) print "" hsm = pyhsm.YHSM(device = args.device, debug=args.debug) nonce, aead = generate_aead(hsm, args) oath_c = validate_oath_c(hsm, args, nonce, aead) return store_oath_entry(args, nonce, aead, oath_c) if __name__ == '__main__': if main(): sys.exit(0) sys.exit(1) python-pyhsm-1.0.4l/yhsm-val/yhsm-init-oath-token.1000066400000000000000000000036061256663164400222030ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-init-oath-token "1" "December 2011" "python-pyhsm" .SH NAME yhsm-init-oath-token \(hy Tool to add an OATH token to the \fIyhsm-validation-server\fR\|(1) database. .SH SYNOPSIS .B yhsm-init-oath-token \fI--key-handle kh\fR \fI--uid name\fR [\fIoptions\fR] .SH DESCRIPTION Use this tool to add OATH token entrys to the \fIyhsm-validation-server\fR\|(1) database. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0) .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM .TP \fB\-\-force\fR overwrite any present entry .TP \fB\-\-key-handle\fR kh key handle to create AEAD. Examples : "1", "0xabcd". .TP \fB\-\-uid\fR name user id (lookup key in token database) .TP \fB\-\-oath-c\fR num initial OATH counter value (integer) .TP \fB\-\-test-oath-window\fR num number of codes to search with \-\-test-code .TP \fB\-\-test-code\fR digits optional OTP from token for verification .TP \fB\-\-oath-k\fR str secret HMAC-SHA-1 key of the token, hex encoded .TP \fB\-\-db-file\fR fn db file for storing AEADs for later use by the \fIyhsm-validation-server\fR\|(1) (default: /var/yubico/yhsm-validation-server.db) .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" YubiHSM keystore successfully unlocked .IP "\fB1\fR" 4 .IX Item "1" Failed to unlock keystore .IP "\fB255\fR" 4 .IX Item "255" Client ID not found in internal database .SH BUGS Report python-pyhsm/yhsm-init-oath-token bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/yhsm-val/yhsm-validate-otp000077500000000000000000000064251256663164400214300ustar00rootroot00000000000000#!/usr/bin/env python # # Tool to validate a YubiKey OTP using the YubiHSM internal database. # # This requires that you have imported the secret AES key of the YubiKey # into the database with `../yubikey-ksm/yhsm-import-keys --internal-db' # or otherwise. # # Copyright (c) 2011 Yubico AB # See the file COPYING for licence statement. # import os import re import sys import struct import argparse sys.path.append('Lib'); import pyhsm import pyhsm.yubikey default_device = "/dev/ttyACM0" def parse_args(): """ Parse the command line arguments """ global default_device parser = argparse.ArgumentParser(description = "Validate YubiKey OTP's using YubiHSM", add_help=True ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device (default : %s).' % default_device ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation.' ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation.' ) group = parser.add_argument_group('Modes', 'What you want to validate') mode_group = group.add_mutually_exclusive_group(required = True) mode_group.add_argument('--otp', dest='otp', help='The output from your YubiKey.' ) mode_group.add_argument('--oath', dest='oath', help='The output from your OATH-HOTP token.' ) args = parser.parse_args() return args def validate_otp(hsm, args): """ Validate an OTP. """ try: res = pyhsm.yubikey.validate_otp(hsm, args.otp) if args.verbose: print "OK counter=%04x low=%04x high=%02x use=%02x" % \ (res.use_ctr, res.ts_low, res.ts_high, res.session_ctr) return 0 except pyhsm.exception.YHSM_CommandFailed, e: if args.verbose: print "%s" % (pyhsm.defines.status2str(e.status)) # figure out numerical response code for r in [pyhsm.defines.YSM_OTP_INVALID, \ pyhsm.defines.YSM_OTP_REPLAY, \ pyhsm.defines.YSM_ID_NOT_FOUND]: if e.status == r: return r - pyhsm.defines.YSM_RESPONSE # not found return 0xff def validate_oath(hsm, args): """ Validate an OATH OTP. """ print "ERROR: Not implemented, try 'yhsm-validation-server'." return 0 def main(): args = parse_args() if args.debug: print "YHSM device : %s" % (args.device) print "" hsm = pyhsm.YHSM(device = args.device, debug=args.debug) status = 1 if args.otp: status = validate_otp(hsm, args) elif args.oath: status = validate_oath(hsm, args) sys.exit(status) if __name__ == '__main__': main() python-pyhsm-1.0.4l/yhsm-val/yhsm-validate-otp.1000066400000000000000000000027201256663164400215560ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-validate-otp "1" "December 2011" "python-pyhsm" .SH NAME yhsm-validate-otp \(hy Validate an OTP using a YubiHSM. .SH SYNOPSIS .B yhsm-validate-otp \fImode\fR [\fIoptions\fR] .SH DESCRIPTION This tool allows simple validation of YubiKey OTP from shell scripts. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0). .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation. .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM. .SH MODES \fB\-\-otp\fR Validate YubiKey OTP against entry in the YubiHSM internal database. .\"\fB\-\-oath\fR .\"\fBNot implemented yet.\fR .\"Validate an OATH code using HMAC-SHA-1 in the YubiHSM. The OATH counter .\"database must be initialized using \fIyhsm-init-oath-token\fR\|(1) first. .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" YubiHSM keystore successfully unlocked .IP "\fB1\fR" 4 .IX Item "1" Failed to unlock keystore .IP "\fB255\fR" 4 .IX Item "255" Client ID not found in internal database .SH BUGS Report python-pyhsm/yhsm-validate-otp bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/yhsm-val/yhsm-validation-server000077500000000000000000000573721256663164400225040ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011, 2012 Yubico AB # See the file COPYING for licence statement. # """ Credential validation server utilizing YubiHSM. Modes of operation : OTP - YubiKey validation using internal DB in YubiHSM. The YubiHSM can take care of complete Yubico OTP validation - including storing seen counter values in an internal database. There is an --otp mode available that tries to be compatible with YK-VAL, and there is a --short-otp mode that gives responses looking like YK-KSM. HOTP - OATH-HOTP validation using secrets stored on host computer (in secure AEADs only decryptable inside YubiHSM). The HMAC-SHA1 of the OATH counter value is done inside the YubiHSM, so the OATH Key is never exposed outside the YubiHSM. PWHASH - Uses AEAD plaintext compare in the YubiHSM to see if a supplied password hash matches the password hash used in an earlier 'set' operation. These AEADs can be generated using `yhsm-password-auth.py --set ...'. All these modes must be explicitly enabled on the command line to be allowed (--otp, --hotp and --pwhash). Examples using OATH-HOTP : > GET /yhsm/validate?hotp=ubftcdcdckcf359152 HTTP/1.1 ... < HTTP/1.0 200 OK < OK counter=0003 same again (replay), differently formatted : > GET /yhsm/validate?uid=ubftcdcdckcf&hotp=359152 HTTP/1.1 ... < HTTP/1.0 200 OK < ERR Could not validate OATH-HOTP OTP Example PWHASH (AEAD and NONCE as returned by `yhsm-password-auth.py --set ...') : > GET /yhsm/validate?pwhash=pbkdf2-of-password-here&aead=2b70...2257&nonce=010203040506&kh=8192 HTTP/1.1 ... < HTTP/1.0 200 OK < OK pwhash validated """ import re import os import sys import time import hmac import syslog import serial import socket import base64 import hashlib import sqlite3 import argparse import urlparse import BaseHTTPServer sys.path.append('Lib') import pyhsm import pyhsm.yubikey default_device = "/dev/ttyACM0" default_serve_url = "/yhsm/validate?" default_db_file = "/var/yubico/yhsm-validation-server.db" default_clients_file = "/var/yubico/yhsm-validation-server_client-id.conf" default_hotp_window = 5 default_pid_file = None ykotp_valid_input = re.compile('^[cbdefghijklnrtuv]{32,48}$') hotp_valid_input = re.compile('^[cbdefghijklnrtuv0-9]{6,20}$') hsm = None args = None saved_key_handle = None client_ids = {} class YHSM_VALRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """ Handle HTTP GET requests according to configuration in global variable `args'. """ def do_GET(self): """ Process validation GET requests. All modes of validation (OTP, OATH and PWHASH) must be explicitly enabled in `args' to be allowed. """ if self.path.startswith(args.serve_url): res = None log_res = None mode = None params = urlparse.parse_qs(self.path[len(args.serve_url):]) if "otp" in params: if args.mode_short_otp: # YubiKey internal db OTP in KSM mode mode = 'YubiKey OTP (short)' res = validate_yubikey_otp_short(self, params) elif args.mode_otp: # YubiKey internal db OTP validation 2.0 mode = 'YubiKey OTP' res = validate_yubikey_otp(self, params) #status = [x for x in res.split('\n') if x.startswith("status=")] #if len(status) == 1: # res = status[0][7:] log_res = '&'.join(res.split('\n')) else: res = "ERR 'otp/otp2' disabled" elif "hotp" in params: if args.mode_hotp: mode = 'OATH-HOTP' res = validate_oath_hotp(self, params) else: res = "ERR 'hotp' disabled" elif "pwhash" in params: if args.mode_pwhash: mode = 'Password hash' res = validate_pwhash(self, params) else: res = "ERR 'pwhash' disabled" if not log_res: log_res = res self.log_message("%s validation result: %s -> %s", mode, self.path, log_res) if res != None: self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write(res) self.wfile.write("\n") else: self.log_error ("No validation result to '%s' (responding 403)" % (self.path)) self.send_response(403, 'Forbidden') self.end_headers() else: self.log_error ("Bad URL '%s' - I'm serving '%s' (responding 403)" % (self.path, args.serve_url)) self.send_response(403, 'Forbidden') self.end_headers() def log_error(self, fmt, *fmt_args): """ Log to syslog. """ msg = self.my_address_string() + " - - " + fmt % fmt_args my_log_message(args, syslog.LOG_ERR, msg) def log_message(self, fmt, *fmt_args): """ Log to syslog. """ msg = self.my_address_string() + " - - " + fmt % fmt_args my_log_message(args, syslog.LOG_INFO, msg) def my_address_string(self): """ For logging client host without resolving. """ return self.client_address[0] class YHSM_VALServer(BaseHTTPServer.HTTPServer): """ Wrapper class to properly initialize address_family for IPv6 addresses. """ def __init__(self, server_address, req_handler): if ":" in server_address[0]: self.address_family = socket.AF_INET6 BaseHTTPServer.HTTPServer.__init__(self, server_address, req_handler) def validate_yubikey_otp_short(self, params): """ Validate YubiKey OTP using YubiHSM internal database. """ from_key = params["otp"][0] if not re.match(ykotp_valid_input, from_key): self.log_error("IN: %s, Invalid OTP" % (from_key)) return "ERR Invalid OTP" try: res = pyhsm.yubikey.validate_otp(hsm, from_key) return "OK counter=%04x low=%04x high=%02x use=%02x" % \ (res.use_ctr, res.ts_low, res.ts_high, res.session_ctr) except pyhsm.exception.YHSM_CommandFailed, e: return "ERR %s" % (pyhsm.defines.status2str(e.status)) def validate_yubikey_otp(self, params): """ Validate YubiKey OTP using YubiHSM internal database. """ vres = {} from_key = params["otp"][0] if not re.match(ykotp_valid_input, from_key): self.log_error("IN: %s, Invalid OTP" % (from_key)) vres["status"] = "BAD_OTP" else: vres["otp"] = from_key if not "nonce" in params: self.log_error("IN: %s, no nonce" % (from_key)) vres["status"] = "MISSING_PARAMETER" else: nonce = params["nonce"][0] if len(nonce) < 16 or len(nonce) > 40: self.log_error("IN: %s, bad nonce : %s" % (from_key, nonce)) vres["status"] = "MISSING_PARAMETER" else: vres["nonce"] = nonce if "sl" in params and not (params["sl"] == "100" or params["sl"] == "secure"): self.log_error("IN: %s, sync level unsupported" % (from_key)) vres["status"] = "BACKEND_ERROR" sig, client_key, = check_signature(params) if sig != True: self.log_error("IN: %s, signature validation error" % (from_key)) if client_key == None: vres["status"] = "NO_SUCH_CLIENT" # To be compatible with YK-VAL, we will sign this response using a null key client_key = chr(0) else: vres["status"] = "BAD_SIGNATURE" if "status" not in vres: try: res = pyhsm.yubikey.validate_otp(hsm, from_key) vres.update({"status": "OK", "sessioncounter": str(res.use_ctr), # known confusion "sessionuse": str(res.session_ctr), # known confusion "timestamp": str((res.ts_high << 16 | res.ts_low) / 8) } ) if "sl" in params: vres["sl"] = "100" if "timestamp" in params: vres["t"] = time.strftime("%FT%TZ0000", time.gmtime()) except pyhsm.exception.YHSM_CommandFailed, e: if e.status == pyhsm.defines.YSM_ID_NOT_FOUND: vres["status"] = "BAD_OTP" elif e.status == pyhsm.defines.YSM_OTP_REPLAY: vres["status"] = "REPLAYED_OTP" elif e.status == pyhsm.defines.YSM_OTP_INVALID: vres["status"] = "BAD_OTP" else: vres["status"] = "BACKEND_ERROR" self.log_error("IN: %s, validation result %s (replying %s)" % (from_key, pyhsm.defines.status2str(e.status), vres["status"])) return make_otp_response(vres, client_key) def make_otp_response(vres, client_key): """ Create validation response (signed, if a client key is supplied). """ if client_key is not None: sig = make_signature(vres, client_key) vres['h'] = sig # produce "key=value" pairs from vres pairs = [x + "=" + ''.join(vres[x]) for x in sorted(vres.keys())] return '\n'.join(pairs) def check_signature(params): """ Verify the signature of the parameters in an OTP v2.0 verify request. Returns ValResultBool, Key """ if 'id' in params: try: id_int = int(params['id'][0]) except: my_log_message(args, syslog.LOG_INFO, "Non-numerical client id (%s) in request." % (params['id'][0])) return False, None key = client_ids.get(id_int) if key: if 'h' in params: sig = params['h'][0] good_sig = make_signature(params, key) if sig == good_sig: #my_log_message(args, syslog.LOG_DEBUG, "Good signature (client id '%i')" % id_int) return True, key else: my_log_message(args, syslog.LOG_INFO, "Bad signature from client id '%i' (%s, expected %s)." \ % (id_int, sig, good_sig)) else: my_log_message(args, syslog.LOG_INFO, "Client id (%i) but no HMAC in request." % (id_int)) return False, key else: my_log_message(args, syslog.LOG_INFO, "Unknown client id '%i'" % (id_int)) return False, None return True, None def make_signature(params, hmac_key): """ Calculate a HMAC-SHA-1 (using hmac_key) of all the params except "h=". Returns base64 encoded signature as string. """ # produce a list of "key=value" for all entrys in params except `h' pairs = [x + "=" + ''.join(params[x]) for x in sorted(params.keys()) if x != "h"] sha = hmac.new(hmac_key, '&'.join(pairs), hashlib.sha1) return base64.b64encode(sha.digest()) def validate_oath_hotp(self, params): """ Validate OATH-HOTP code using YubiHSM HMAC-SHA1 hashing with token keys secured in AEAD's that we have stored in an SQLite3 database. """ from_key = params["hotp"][0] if not re.match(hotp_valid_input, from_key): self.log_error("IN: %s, Invalid OATH-HOTP OTP" % (params)) return "ERR Invalid OATH-HOTP OTP" uid, otp, = get_oath_hotp_bits(params) if not uid or not otp: self.log_error("IN: %s, could not get UID/OTP ('%s'/'%s')" % (params, uid, otp)) return "ERR Invalid OATH-HOTP input" if args.debug: print "OATH-HOTP uid %s, OTP %s" % (uid, otp) # Fetch counter value for `uid' from database try: db = ValOathDb(args.db_file) entry = db.get(uid) except Exception, e: self.log_error("IN: %s, database error : '%s'" % (params, e)) return "ERR Internal error" # Check for correct OATH-HOTP OTP nonce = entry.data["nonce"].decode('hex') aead = entry.data["aead"].decode('hex') new_counter = pyhsm.oath_hotp.search_for_oath_code(hsm, entry.data["key_handle"], nonce, aead, \ entry.data["oath_c"], otp, args.look_ahead) if args.debug: print "OATH-HOTP %i..%i -> new C == %s" \ % (entry.data["oath_c"], entry.data["oath_c"] + args.look_ahead, new_counter) if type(new_counter) != int: # XXX increase 'throttling parameter' to make brute forcing harder/impossible return "ERR Could not validate OATH-HOTP OTP" try: # Must successfully store new_counter before we return OK if db.update_oath_hotp_c(entry, new_counter): return "OK counter=%04x" % (new_counter) else: return "ERR replayed OATH-HOTP" except Exception, e: self.log_error("IN: %s, database error updating counter : %s" % (params, e)) return "ERR Internal error" def validate_pwhash(_self, params): """ Validate password hash using YubiHSM. """ pwhash, nonce, aead, key_handle = get_pwhash_bits(params) d_aead = aead.decode('hex') plaintext_len = len(d_aead) - pyhsm.defines.YSM_AEAD_MAC_SIZE pw = pwhash.ljust(plaintext_len, chr(0x0)) if hsm.validate_aead(nonce.decode('hex'), key_handle, d_aead, pw): return "OK pwhash validated" return "ERR Could not validate pwhash" def get_pwhash_bits(params): """ Extract bits for password hash validation from params. """ if not "pwhash" in params or \ not "nonce" in params or \ not "aead" in params or \ not "kh" in params: raise Exception("Missing required parameter in request (pwhash, nonce, aead or kh)") pwhash = params["pwhash"][0] nonce = params["nonce"][0] aead = params["aead"][0] key_handle = pyhsm.util.key_handle_to_int(params["kh"][0]) return pwhash, nonce, aead, key_handle def get_oath_hotp_bits(params): """ Extract the OATH-HOTP uid and OTP from params. """ if "uid" in params: return params["uid"][0], int(params["hotp"][0]) m = re.match("^([cbdefghijklnrtuv]*)([0-9]{6,8})", params["hotp"][0]) uid, otp, = m.groups() return uid, int(otp), class ValOathDb(): """ Provides access to database with AEAD's and other information for OATH tokens. """ def __init__(self, filename): self.filename = filename self.conn = sqlite3.connect(self.filename) self.conn.row_factory = sqlite3.Row def get(self, key): """ Fetch entry from database. """ c = self.conn.cursor() for row in c.execute("SELECT key, nonce, key_handle, aead, oath_C, oath_T FROM oath WHERE key = ?", (key,)): return ValOathEntry(row) raise Exception("OATH token for '%s' not found in database (%s)" % (key, self.filename)) def update_oath_hotp_c(self, entry, new_c): """ Update the OATH-HOTP counter value for `entry' in the database. Use SQL statement to ensure we only ever increase the counter. """ key = entry.data["key"] c = self.conn.cursor() c.execute("UPDATE oath SET oath_c = ? WHERE key = ? AND ? > oath_c", (new_c, key, new_c,)) self.conn.commit() return c.rowcount == 1 class ValOathEntry(): """ Class to hold a row of ValOathDb. """ def __init__(self, row): if row: self.data = row def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Validate secrets using YubiHSM", add_help=True, formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-U', '--serve-url', dest='serve_url', default=default_serve_url, required=False, help='Base URL for validation web service', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation', ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation', ) parser.add_argument('--port', dest='listen_port', type=int, default=8003, required=False, help='Port to listen on', metavar='PORT', ) parser.add_argument('--addr', dest='listen_addr', default="127.0.0.1", required=False, help='Address to bind to', metavar='ADDR', ) parser.add_argument('--hmac-kh', dest='hmac_kh', required=False, default=0, help='Key handle to use for creating HMAC-SHA1 hashes', metavar='KEY_HANDLE', ) parser.add_argument('--short-otp', dest='mode_short_otp', action='store_true', default=False, help='Enable YubiKey OTP validation (KSM style response)', ) parser.add_argument('--otp', dest='mode_otp', action='store_true', default=False, help='Enable YubiKey OTP validation 2.0', ) parser.add_argument('--hotp', dest='mode_hotp', action='store_true', default=False, help='Enable OATH-HOTP validation', ) parser.add_argument('--pwhash', dest='mode_pwhash', action='store_true', default=False, help='Enable password hash validation', ) parser.add_argument('--db-file', dest='db_file', default=default_db_file, required=False, help='DB file for storing AEAD\'s etc. for --pwhash and --hotp', metavar='FILENAME', ) # XXX bad interaction with argparse.ArgumentDefaultsHelpFormatter here - we don't want to # use default=default_clients_file since we need to know if this option was specified explicitly # or not. parser.add_argument('--clients-file', dest='clients_file', default=None, required=False, help='File with OTP validation clients shared secrets. for --otp. Default : %s' % (default_clients_file), metavar='FILENAME', ) parser.add_argument('--hotp-window', dest='look_ahead', type=int, required=False, default = default_hotp_window, help='Number of OATH-HOTP codes to search', metavar='NUM', ) parser.add_argument('--pid-file', dest='pid_file', default=default_pid_file, required=False, help='PID file', metavar='FILENAME', ) return parser.parse_args() def args_fixup(): """ Various cleanups/initializations based on result of parse_args(). """ global saved_key_handle saved_key_handle = args.hmac_kh args.key_handle = pyhsm.util.key_handle_to_int(args.hmac_kh) if not (args.mode_otp or args.mode_short_otp or args.mode_hotp or args.mode_pwhash): my_log_message(args, syslog.LOG_ERR, 'No validation mode enabled') sys.exit(1) global client_ids if args.clients_file != None: if not args.mode_otp: my_log_message(args, syslog.LOG_ERR, 'Clients file should only be used with --otp.') sys.exit(1) client_ids = load_clients_file(args.clients_file) if not client_ids: my_log_message(args, syslog.LOG_ERR, 'Failed loading clients file "%s"' % (args.clients_file)) sys.exit(1) else: # we accept failure to load this file when the default is used loaded_client_ids = load_clients_file(default_clients_file) if loaded_client_ids: args.clients_file = default_clients_file client_ids = loaded_client_ids def load_clients_file(filename): """ Load a list of base64 encoded shared secrets for numerical client ids. Returns a dict. Format of file is expected to be # This is a comment. Blank lines are OK. 123,c2hhcmVkIHNlY3JldA== 456,MTIzNDU2Nzg5MDEyMw== """ res = {} content = [] try: fhandle = file(filename) content = fhandle.readlines() fhandle.close() except IOError: return None linenum = 0 for line in content: linenum += 1 while line.endswith("\r") or line.endswith("\n"): line = line[:-1] if re.match("(^\s*#|^\s*$)", line): # skip comments and empty lines continue parts = [x.strip() for x in line.split(',')] try: if len(parts) != 2: raise Exception() id_num = int(parts[0]) key = base64.b64decode(parts[1]) res[id_num] = key except: my_log_message(args, syslog.LOG_ERR, 'Bad data on line %i of clients file "%s" : "%s"' % (linenum, filename, line)) return None return res def write_pid_file(fn): """ Create a file with our PID. """ if not fn: return None if fn == '' or fn == "''": # work around argument passings in init-scripts return None f = open(fn, "w") f.write("%s\n" % (os.getpid())) f.close() def run(): """ Start the BaseHTTPServer and serve requests forever. """ server_address = (args.listen_addr, args.listen_port) httpd = YHSM_VALServer(server_address, YHSM_VALRequestHandler) my_log_message(args, syslog.LOG_INFO, "Serving requests to 'http://%s:%s%s' (YubiHSM: '%s')" \ % (args.listen_addr, args.listen_port, args.serve_url, args.device)) httpd.serve_forever() def my_log_message(my_args, prio, msg): """ Log msg to syslog, and possibly also output to stderr. """ syslog.syslog(prio, msg) if my_args.debug or my_args.verbose or prio == syslog.LOG_ERR: sys.stderr.write("%s\n" % (msg)) def main(): """ The main function that will be executed when running this as a stand alone script. """ my_name = os.path.basename(sys.argv[0]) if not my_name: my_name = "yhsm-validation-server" syslog.openlog(my_name, syslog.LOG_PID, syslog.LOG_LOCAL0) global args args = parse_args() args_fixup() global hsm try: hsm = pyhsm.YHSM(device = args.device, debug = args.debug) except serial.SerialException, e: my_log_message(args, syslog.LOG_ERR, 'Failed opening YubiHSM device "%s" : %s' %(args.device, e)) sys.exit(1) write_pid_file(args.pid_file) try: run() except KeyboardInterrupt: print "" print "Shutting down" print "" if __name__ == '__main__': main() python-pyhsm-1.0.4l/yhsm-val/yhsm-validation-server.1000066400000000000000000000066641256663164400226360ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-validation-server "1" "December 2011" "python-pyhsm" .SH NAME yhsm-validation-server \(hy Credential validation server utilizing YubiHSM .SH SYNOPSIS .B yhsm-validation-server [\fImode\fR] .SH DESCRIPTION This is a validation server using the YubiHSM for cryptographic operations. It is primarily built to validate YubiKey OTPs (\fInot\fR stored in the YubiHSM internal database), but it can also validate OATH token codes and legacy passwords. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0) .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM .TP \fB\-\-U\fR, \fB\-\-serve-url\fR base base of URL for validation web service (default: /yhsm/validate?) .TP \fB\-\-port\fR num port to listen on (default: 8003) .TP \fB\-\-addr\fR addr address to bind to (default: 127.0.0.1) .TP \fB\-\-hmac-kh\fR kh key handle to use for HMAC\(hySHA\(hy1. Examples : "1", "0xabcd". .TP \fB\-\-hotp-window\fR num number of OATH counter values to try (default: 5) .TP \fB\-\-db-file\fR fn db file holding AEADs (see \fIyhsm-init-oath-token\fR\|(1)) (default: /var/yubico/yhsm-validation-server.db) .TP \fB\-\-clients-file\fR fn text file with mode OTP validation client shared secrets (see \fIyhsm-init-oath-token\fR\|(1)) (default: /var/yubico/yhsm-validation-server.db) .TP \fB\-\-pid-file\fR fn write process id of server to this file .SH "MODES" .TP \fB\-\-otp\fR Validate YubiKey OTP against entry in the YubiHSM internal database. Response should be compatible with those of .URL "http://code.google.com/p/yubikey-val-server-php/" "yubikey-val-server-php" "." .TP \fB\-\-short-otp\fR Validate YubiKey OTP against entry in the YubiHSM internal database. Returns a single line with the decrypted information from the OTP, compatible with .URL "http://code.google.com/p/yubikey-ksm/" "yubikey-ksm" "." .TP \fB\-\-hotp\fR Validate codes using the OATH HOTP algorithm, performing the HMAC\(hySHA\(hy1 inside the YubiHSM. .TP \fB\-\-pwhash\fR Validate that a string (a PBKDF2 hash of a password for example) matches the one in an AEAD. Can be used to protect legacy passwords within an AEAD only readable to a YubiHSM, but still recoverable if you know the AEAD key (since you put it in the YubiHSM). .\"\fB\-\-oath\fR .\"\fBNot implemented yet.\fR .\"Validate an OATH code using HMAC\(hySHA\(hy1 in the YubiHSM. The OATH counter .\"database must be initialized using \fIyhsm-init-oath-token\fR\|(1) first. .SH "CLIENTS FILE" This file holds HMAC\(hySHA\(hy1 secrets shared between the validation client and server. An example file, with a single entry for id 4711 would be : .in +4n .nf # hash-style comments and blank lines are ignored 4711,grF5BERXEXPPpww1/TBvFg== # end .fi .in .SH "EXIT STATUS" .IX Header "EXIT STATUS" .IP "\fB0\fR" 4 .IX Item "0" YubiHSM keystore successfully unlocked .IP "\fB1\fR" 4 .IX Item "1" Failed to unlock keystore .IP "\fB255\fR" 4 .IX Item "255" Client ID not found in internal database .SH "BUGS" Report python-pyhsm/yhsm-validation-server bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/yubikey-ksm/000077500000000000000000000000001256663164400166355ustar00rootroot00000000000000python-pyhsm-1.0.4l/yubikey-ksm/yhsm-import-keys000077500000000000000000000213411256663164400220250ustar00rootroot00000000000000#!/usr/bin/env python # """ Tool to import YubiKey secrets to YubiHSM. The default mode is to turn each YubiKey secret into an AEAD (Authenticated Encryption with Associated Data) block that is stored in a file on the host computer (one file per YubiKey). This enables validation of virtually unlimited numbers of YubiKey's OTPs. If --internal-db is used, the YubiKey secret will be stored inside the YubiHSM, and complete validation (including counter management) will be done inside the YubiHSM. The internal database is currently limited to 1024 entrys. The input is supposed to be a comma-separated list of entrys like this # ykksm 1 123456,ftftftcccc,534543524554,fcacd309a20ce1809c2db257f0e8d6ea,000000000000,,, (seqno, public id, private uid, AES key, dunno,,,) This is also the format of a database export from a traditional YK-KSM. """ # # Copyright (c) 2011, 2012 Yubico AB # See the file COPYING for licence statement. # import os import re import sys import struct import argparse sys.path.append('Lib') import pyhsm import pyhsm.yubikey default_device = "/dev/ttyACM0" default_dir = "/var/cache/yubikey-ksm/aeads" default_public_id_chars = 12 def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Import existing secrets to YubiHSM eco system", add_help=True, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device', ) parser.add_argument('-O', '--output-dir', '--aead-dir', dest='output_dir', default=default_dir, required=False, help='Output directory (AEAD base dir)', metavar='DIR', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation', ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation', ) parser.add_argument('--public-id-chars', dest='public_id_chars', type=int, default=default_public_id_chars, required=False, help='Number of chars in generated public ids', metavar='NUM', ) parser.add_argument('--key-handles', dest='key_handles', nargs='+', required=True, help='Key handle(s) to encrypt the imported secrets with', metavar='HANDLE', ) parser.add_argument('--internal-db', dest='internal_db', action='store_true', default=False, help='Store key in YubiHSM internal database', ) parser.add_argument('--aes-key', dest='aes_key', required=False, default=None, help='AES key to use when generating AEADs (no YubiHSM)', metavar='HEXSTR', ) parser.add_argument('--random-nonce', dest='random_nonce', action='store_true', default=False, help='Let the HSM generate random nonce', ) args = parser.parse_args() if args.internal_db: if len(args.key_handles) != 1: sys.stderr.write("--internal-db requires exactly one key handle.\n") sys.exit(1) if args.aes_key: sys.stderr.write("--internal-db incompatible with --aes-key.\n") sys.exit(1) return args def args_fixup(args): if not args.internal_db and not os.path.isdir(args.output_dir): sys.stderr.write("Output directory '%s' does not exist.\n" % (args.output_dir)) sys.exit(1) if args.aes_key: args.aes_key = args.aes_key.decode('hex') keyhandles_fixup(args) def keyhandles_fixup(args): """ Walk through the supplied key handles and normalize them, while keeping the input format too (as value in a dictionary). The input format is used in AEAD filename paths. """ new_handles = {} for val in args.key_handles: n = pyhsm.util.key_handle_to_int(val) new_handles[n] = val args.key_handles = new_handles def import_keys(hsm, args): """ The main stdin iteration loop. """ res = True # ykksm 1 #123456,ftftftcccc,534543524554,fcacd309a20ce1809c2db257f0e8d6ea,000000000000,,, for line in sys.stdin: if line[0] == '#': continue l = line.split(',') modhex_id = l[1] uid = l[2].decode('hex') key = l[3].decode('hex') if modhex_id and uid and key: public_id = pyhsm.yubikey.modhex_decode(modhex_id) padded_id = modhex_id.rjust(args.public_id_chars, 'c') if int(public_id, 16) == 0: print "WARNING: Skipping import of key with public ID: %s" % (padded_id) print "This public ID is unsupported by the YubiHSM.\n" continue if args.verbose: print " %s" % (padded_id) secret = pyhsm.aead_cmd.YHSM_YubiKeySecret(key, uid) if hsm: hsm.load_secret(secret) for kh in args.key_handles.keys(): if hsm: if(args.random_nonce): nonce = "" else: nonce = public_id.decode('hex') aead = hsm.generate_aead(nonce, kh) else: nonce = public_id.decode('hex') ct = pyhsm.soft_hsm.aesCCM(args.aes_key, kh, nonce, secret.pack(), decrypt = False) aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(nonce, kh, ct) if args.internal_db: if not store_in_internal_db(args, hsm, modhex_id, public_id, kh, aead): res = False continue filename = output_filename(args.output_dir, args.key_handles[kh], padded_id) if args.verbose: print " %4s, %i bytes (%s) -> %s" % \ (args.key_handles[kh], len(aead.data), shorten_aead(aead), filename) aead.save(filename) if args.verbose: print "" if res: print "\nDone\n" else: print "\nDone (one or more entrys rejected)" return res def store_in_internal_db(args, hsm, modhex_id, public_id, kh, aead): """ Store record (AEAD) in YubiHSM internal DB """ if args.verbose: print " %i bytes (%s) -> internal db..." % \ (len(aead.data), shorten_aead(aead)), try: hsm.db_store_yubikey(public_id.decode('hex'), kh, aead) if args.verbose: print "OK" except pyhsm.exception.YHSM_CommandFailed, e: if args.verbose: print "%s" % (pyhsm.defines.status2str(e.status)) else: print "Storing ID %s FAILED: %s" % (modhex_id, pyhsm.defines.status2str(e.status)) return False return True def shorten_aead(aead): """ Produce pretty-printable version of long AEAD. """ head = aead.data[:4].encode('hex') tail = aead.data[-4:].encode('hex') return "%s...%s" % (head, tail) def output_filename(output_dir, key_handle, public_id): """ Return an output filename for a generated AEAD. Creates a hashed directory structure using the last three bytes of the public id to get equal usage. """ parts = [output_dir, key_handle] + pyhsm.util.group(public_id, 2) path = os.path.join(*parts) if not os.path.isdir(path): os.makedirs(path) return os.path.join(path, public_id) def main(): args = parse_args() args_fixup(args) if sys.stdin.readline() != "# ykksm 1\n": sys.stderr.write("Did not get '# ykksm 1' header as first line of input.\n") sys.exit(1) print "output dir : %s" % (args.output_dir) print "key handles : %s" % (args.key_handles) print "YHSM device : %s" % (args.device) print "" if not args.aes_key: hsm = pyhsm.YHSM(device = args.device, debug=args.debug) else: hsm = None return not import_keys(hsm, args) if __name__ == '__main__': sys.exit(main()) python-pyhsm-1.0.4l/yubikey-ksm/yhsm-import-keys.1000066400000000000000000000046071256663164400221670ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-import-keys "1" "December 2011" "python-pyhsm" .SH NAME yhsm-import-keys \(hy import YubiKey secrets to YubiHSM .SH SYNOPSIS .B yhsm-import-keys \fI--key-handles\fR ... [\fIoptions\fR] .SH DESCRIPTION Read YubiKey token data from standard input, and store it in files or in the YubiHSM internal database. The default mode is to turn each YubiKey secret into an AEAD (Authenticated Encryption with Associated Data) block that is stored in a file on the host computer (one file per YubiKey). This enables validation of virtually unlimited numbers of YubiKey's OTPs. If \-\-internal-db is used, the YubiKey secret will be stored inside the YubiHSM, and complete validation (including counter management) will be done inside the YubiHSM. The internal database is currently limited to 1024 entrys. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0) .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM .TP \fB\-\-public_id_chars\fR num number of chars to pad public id to (default: 12) .TP \fB\-\-key-handles\fR kh key handles to use for decoding OTPs. Examples : "1", "0xabcd" .TP \fB\-\-output-dir\fR dir, \fB\-\-aead-dir\fR dir, \fB\-O\fR dir base directory for AEADs (default: /var/cache/yubikey-ksm/aeads) .TP \fB\-\-internal-db\fR add entrys to YubiHSM internal database, rather than creating AEAD files .TP \fB\-\-random-nonce\fR use random nonce generated from YubiHSM .SH "INPUT FORMAT" The format of the input matches the export format of various Yubico tools, notably the PHP based .URL "http://code.google.com/p/yubikey-ksm/" "soft KSM" "." An example file, with a single entry for id 4711 would be : .in +4n .nf # ykksm 1 123456,ftftftcccc,534543524554,fcacd309a20ce1809c2db257f0e8d6ea,000000000000,,, .fi .in (seqno, public id, private uid, AES key, dunno,,,) The #ykksm 1 is a file marker, and has to be on the very first line of input. .SH "BUGS" Report python-pyhsm/yhsm-import-keys bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "." python-pyhsm-1.0.4l/yubikey-ksm/yhsm-yubikey-ksm000077500000000000000000000355331256663164400220230ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2011-2014 Yubico AB # See the file COPYING for licence statement. # """ Small network server decrypting YubiKey OTPs using an attached YubiHSM. To support unlimited numbers of YubiKeys, the YubiKey AES keys are stored in AEAD's (Authenticated Encryption with Associated Data) on the host computer. When an OTP is received, we find the right AEAD for this key (based on the public ID of the YubiKey), and then send the AEAD together with the OTP to the YubiHSM. The YubiHSM is able to decrypt the AEAD (if it has the appropriate key handle configured), and then able to decrypt the YubiKey OTP using the AES key stored in the AEAD. The information the YubiKey encrypted using it's AES key is then returned in clear text from the YubiHSM. This includes the counter information and also (relative) timestamps. It is not the job of the KSM (or YubiHSM) to ensure that the OTP has not been seen before - that is done by the validation server (using the database) : O +----------+ /|\ |Validation| +-----+ +---------+ | -- OTP--> | server | --> | KSM +---| YubiHSM | / \ +----------+ +-----+ +---------+ | user +--+--+ | DB | +-----+ """ import os import sys import BaseHTTPServer import socket import argparse import syslog import re sys.path.append('Lib'); import pyhsm import pyhsm.yubikey import serial import daemon import sqlalchemy default_device = "/dev/ttyACM0" default_dir = "/var/cache/yubikey-ksm/aeads" default_serve_url = "/wsapi/decrypt?otp=" default_listen_addr = "127.0.0.1" default_port = 8002 default_reqtimeout = 5 default_pid_file = None default_db_url = None valid_input_from_key = re.compile('^[cbdefghijklnrtuv]{32,48}$') hsm = None args = None stats = { 'ok': 0, 'invalid': 0, 'no_aead': 0, 'err': 0 } context = daemon.DaemonContext() class YHSM_KSMRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """ Handle a HTTP request. Try to be careful and validate the input, and then look for an AEAD file matching the public id of the OTP. If an AEAD for one of our key handles is found, we ask the YubiHSM to decrypt the OTP using the AEAD and return the result (counter and timestamp information). """ def __init__(self, *other_args, **kwargs): self.timeout = args.reqtimeout if args.engine is not None: self.engine = args.engine self.aead_table = args.aead_table BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *other_args, **kwargs) def do_GET(self): """ Handle a HTTP GET request. """ # Example session: # in : GET /wsapi/decrypt?otp=ftftftccccdvvbfcfduvvcubikngtchlubtutucrld HTTP/1.0 # out : OK counter=0004 low=f585 high=3e use=03 if self.path.startswith(args.serve_url): from_key = self.path[len(args.serve_url):] val_res = decrypt_yubikey_otp(self, from_key) self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(val_res) self.wfile.write("\n") elif args.stats_url and self.path == args.stats_url: self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() for key in stats: self.wfile.write("%s %d\n" % (key, stats[key])) else: self.log_error ("Bad URL '%s' - I'm serving '%s' (responding 403)" % (self.path, args.serve_url)) self.send_response(403, 'Forbidden') self.end_headers() def log_error(self, fmt, *fmt_args): """ Log to syslog. """ msg = self.my_address_string() + " - - " + fmt % fmt_args my_log_message(args, syslog.LOG_ERR, msg) def log_message(self, fmt, *fmt_args): """ Log to syslog. """ msg = self.my_address_string() + " - - " + fmt % fmt_args my_log_message(args, syslog.LOG_INFO, msg) def my_address_string(self): """ For logging client host without resolving. """ return self.client_address[0] def dbload(self, public_id): """ Loads AEAD from the specified database. """ connection = self.engine.connect() trans = connection.begin() aead = None try: s = sqlalchemy.select([self.aead_table]).where(self.aead_table.c.public_id == public_id) result = connection.execute(s) for row in result: kh_int = row['keyhandle'] aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(None, kh_int, ''); aead.data = row['aead'] aead.nonce = row['nonce'] trans.commit() except Exception, e: self.log_error("No AEAD in DB for public_id %s (%s)" % (public_id, str(e))) aead = None if aead is None: trans.rollback() connection.close() return aead class YHSM_KSMServer(BaseHTTPServer.HTTPServer): """ Wrapper class to properly initialize address_family for IPv6 addresses. """ def __init__(self, server_address, req_handler): if ":" in server_address[0]: self.address_family = socket.AF_INET6 BaseHTTPServer.HTTPServer.__init__(self, server_address, req_handler) def dbconnect(my_args): """ Connect to a database """ engine = None try: engine = sqlalchemy.create_engine(my_args.db_url) metadata = sqlalchemy.MetaData() aead_table = sqlalchemy.Table('aead_table', metadata, autoload=True, autoload_with=engine) except: my_log_message(my_args, syslog.LOG_ERR, "Could not connect to database: %s" % (my_args.db_url)) sys.exit(1) return (engine, aead_table) def decrypt_yubikey_otp(self, from_key): """ Try to decrypt a YubiKey OTP. Returns a string starting with either 'OK' or 'ERR' : 'OK counter=ab12 low=dd34 high=2a use=0a' 'ERR Unknown public_id' on YubiHSM errors (or bad OTP), only 'ERR' is returned. """ if not re.match(valid_input_from_key, from_key): self.log_error("IN: %s, Invalid OTP" % (from_key)) if args.stats_url: stats['invalid'] += 1 return "ERR Invalid OTP" public_id, _otp = pyhsm.yubikey.split_id_otp(from_key) aead_kh_int = None fn_list = [] if args.db_url is not None: #loads an AEAD from the DB with the specific public_id aead = self.dbload(public_id) if(aead): aead_kh_int = aead.key_handle else : for kh, kh_int in args.key_handles: aead = pyhsm.aead_cmd.YHSM_GeneratedAEAD(None, kh_int, '') filename = aead_filename(args.aead_dir, kh, public_id) fn_list.append(filename) try: aead.load(filename) if not aead.nonce: aead.nonce = pyhsm.yubikey.modhex_decode(public_id).decode('hex') aead_kh_int = kh_int break except IOError: continue if aead_kh_int == None: self.log_error("IN: %s, Found no (readable) AEAD for public_id %s" % (from_key, public_id)) self.log_message("Tried to load AEAD from : %s" % (fn_list)) if args.stats_url: stats['no_aead'] += 1 return "ERR Unknown public_id" try: res = pyhsm.yubikey.validate_yubikey_with_aead(hsm, from_key, aead, aead_kh_int) # XXX double-check public_id in res, in case BaseHTTPServer suddenly becomes multi-threaded # XXX fix use vs session counter confusion val_res = "OK counter=%04x low=%04x high=%02x use=%02x" % \ (res.use_ctr, res.ts_low, res.ts_high, res.session_ctr) if args.stats_url: stats['ok'] += 1 except pyhsm.exception.YHSM_Error, e: self.log_error ("IN: %s, Validate FAILED: %s" % (from_key, str(e))) val_res = "ERR" if args.stats_url: stats['err'] += 1 self.log_message("SUCCESS OTP %s PT hsm %s", from_key, val_res) return val_res def aead_filename(aead_dir, key_handle, public_id): """ Return the filename of the AEAD for this public_id. """ parts = [aead_dir, key_handle] + pyhsm.util.group(public_id, 2) + [public_id] return os.path.join(*parts) def parse_args(): """ Parse the command line arguments """ parser = argparse.ArgumentParser(description = "Decrypt YubiKey OTPs using YubiHSM", add_help = True, formatter_class = argparse.ArgumentDefaultsHelpFormatter ) parser.add_argument('-D', '--device', dest='device', default=default_device, required=False, help='YubiHSM device' ) parser.add_argument('-B', '--aead-dir', dest='aead_dir', default=default_dir, required=False, help='AEAD directory - base directory of your AEADs', metavar='DIR', ) parser.add_argument('-U', '--serve-url', dest='serve_url', default=default_serve_url, required=False, help='Base URL for decrypt web service', metavar='URL', ) parser.add_argument('-S', '--stats-url', dest='stats_url', required=False, help='URL where statistics can be retrieved', metavar='URL', ) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Enable verbose operation' ) parser.add_argument('-d', '--daemon', dest='daemon', action='store_true', default=False, help='Run as daemon' ) parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='Enable debug operation' ) parser.add_argument('--port', dest='listen_port', type=int, default=default_port, required=False, help='Port to listen on', metavar='PORT', ) parser.add_argument('--addr', dest='listen_addr', default=default_listen_addr, required=False, help='Address to bind to', metavar='ADDR', ) parser.add_argument('--reqtimeout', dest='reqtimeout', type=int, default=default_reqtimeout, required=False, help='Request timeout in seconds', metavar='SECONDS', ) parser.add_argument('--key-handle', '--key-handles', dest='key_handles', nargs='+', required=True, help='Key handle(s) to use to decrypt AEADs on the YHSM.', metavar='HANDLE', ) parser.add_argument('--pid-file', dest='pid_file', default=default_pid_file, required=False, help='PID file', metavar='FILENAME', ) parser.add_argument('--db-url', dest='db_url', default=default_db_url, required=False, help='The database url to read the AEADs from', metavar='DBURL', ) return parser.parse_args() def args_fixup(my_args): """ Additional checks/cleanups of parsed arguments. """ if not os.path.isdir(my_args.aead_dir): my_log_message(my_args, syslog.LOG_ERR, "AEAD directory '%s' does not exist." % (my_args.aead_dir)) sys.exit(1) # cache key_handle_to_int of all key handles, turning args.key_handles into # a list of tuples with both original value and integer res = [] for kh in my_args.key_handles: kh_int = pyhsm.util.key_handle_to_int(kh) res.append((kh, kh_int,)) my_args.key_handles = res #evaluate database url and connect to the database #execute only if in database mode if my_args.db_url is not None: (my_args.engine,my_args.aead_table) = dbconnect(my_args) else: my_args.engine = None def write_pid_file(fn): """ Create a file with our PID. """ if not fn: return None if fn == '' or fn == "''": # work around argument passings in init-scripts return None f = open(fn, "w") f.write("%s\n" % (os.getpid())) f.close() def run(args): """ Start a BaseHTTPServer.HTTPServer and serve requests forever. """ write_pid_file(args.pid_file) server_address = (args.listen_addr, args.listen_port) httpd = YHSM_KSMServer(server_address, YHSM_KSMRequestHandler) my_log_message(args, syslog.LOG_INFO, "Serving requests to 'http://%s:%s%s' with key handle(s) %s (YubiHSM: '%s', AEADs in '%s', DB in '%s')" \ % (args.listen_addr, args.listen_port, args.serve_url, args.key_handles, args.device, args.aead_dir, args.db_url)) httpd.serve_forever() def my_log_message(my_args, prio, msg): """ Log to syslog, and possibly also to stderr. """ syslog.syslog(prio, msg) if my_args.debug or my_args.verbose or prio == syslog.LOG_ERR: sys.stderr.write("%s\n" % (msg)) def main(): """ Main program. """ my_name = os.path.basename(sys.argv[0]) if not my_name: my_name = "yhsm-yubikey-ksm" syslog.openlog(my_name, syslog.LOG_PID, syslog.LOG_LOCAL0) global args args = parse_args() args_fixup(args) global hsm try: hsm = pyhsm.YHSM(device = args.device, debug = args.debug) except serial.SerialException, e: my_log_message(args, syslog.LOG_ERR, 'Failed opening YubiHSM device "%s" : %s' %(args.device, e)) sys.exit(1) context.files_preserve = [hsm.get_raw_device()] if args.daemon: with context: run(args) else: try: run(args) except KeyboardInterrupt: print "" print "Shutting down" print "" if __name__ == '__main__': main() python-pyhsm-1.0.4l/yubikey-ksm/yhsm-yubikey-ksm.1000066400000000000000000000041071256663164400221500ustar00rootroot00000000000000.\" Copyright (c) 2011-2014 Yubico AB .\" See the file COPYING for license statement. .\" .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. .if \n[.g] .mso www.tmac .TH yhsm-yubikey-ksm "1" "December 2011" "python-pyhsm" .SH NAME yhsm-yubikey-ksm \(hy Decrypt YubiKey OTPs using an attached YubiHSM .SH SYNOPSIS .B yhsm-yubikey-ksm \fI--key-handles\fR ... [\fIoptions\fR] .SH DESCRIPTION This is a small network server with a REST-like API that decodes YubiKey OTPs. It can be used as a decryption backend (Key Storage Module) to a validation service such as the YubiCloud. The AES keys of the YubiKeys must be present as AEAD files decryptable to the attached YubiHSM. Such AEADs can for example be created using \fIyhsm-import-keys\fR\|(1). Note that this daemon is single threaded \(hy it will only handle a single request at once. A request timeout is therefor most important. .SH OPTIONS .PP .TP \fB\-D\fR, \fB\-\-device\fR device file name (default: /dev/ttyACM0) .TP \fB\-v\fR, \fB\-\-verbose\fR enable verbose operation .TP \fB\-\-debug\fR enable debug printout, including all data sent to/from YubiHSM .TP \fB\-U\fR, \fB\-\-serve\-url\fR base base of URL for decrypt web service (default: /yhsm/validate?) .TP \fB\-S\fR, \fB\-\-stats\-url\fR url URL where some basic statistics about operations since start can be collected .TP \fB\-\-port\fR num port to listen on (default: 8002) .TP \fB\-\-addr\fR addr address to bind to (default: 127.0.0.1) .TP \fB\-\-key-handles\fR kh, \fB\-\-key-handle\fR kh key handles to use for decoding OTPs. Examples : "1", "0xabcd". .TP \fB\-\-aead-dir\fR dir, \fB\-B\fR dir base directory for AEADs (default: /var/cache/yubikey-ksm/aeads) .TP \fB\-\-reqtimeout\fR num number of seconds before a request times out (default: 5) .TP \fB\-\-pid-file\fR fn write process id of server to this file .SH "BUGS" Report python-pyhsm/yhsm-yubikey-ksm bugs in .URL "https://github.com/Yubico/python-pyhsm/issues/" "the issue tracker" .SH "SEE ALSO" The .URL "https://developers.yubico.com/python-pyhsm/" "home page" .PP YubiHSMs can be obtained from .URL "http://www.yubico.com/" "Yubico" "."