Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package yubico-piv-tool The latest upstream release contains security-critical changes (see #926551). I apologise for the larger-than-necessary diff, which includes some packaging changes that were pending upload :( The debdiff is enclosed; it isn't authoritative, as the package still needs to be uploaded to sid (I accidentally let my signing key expire while ill, so this is waiting on a sponsored upload...) Best, nicoo unblock yubico-piv-tool/1.7.0-1 -- System Information: Debian Release: buster/sid APT prefers testing APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 4.19.0-2-amd64 (SMP w/4 CPU cores) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
diff -Nru yubico-piv-tool-1.6.2/ChangeLog yubico-piv-tool-1.7.0/ChangeLog --- yubico-piv-tool-1.6.2/ChangeLog 2018-09-14 09:33:28.000000000 +0200 +++ yubico-piv-tool-1.7.0/ChangeLog 2019-04-03 09:53:53.000000000 +0200 @@ -1,3 +1,156 @@ +2019-04-03 Klas Lindfors <k...@yubico.com> + + * NEWS, configure.ac: NEWS for 1.7.0 + +2019-04-03 Klas Lindfors <k...@yubico.com> + + * : commit 7b64528cf7ba87e803a3ed29c8ca877e88796e24 Author: Dave + Pate <dp...@yubico.com> Date: Tue Jan 22 13:59:06 2019 -0800 + +2019-01-22 Dave Pate <dp...@yubico.com> + + * lib/internal.h, lib/ykpiv.c: lib: tlv length buffer checks + +2019-01-22 Dave Pate <dp...@yubico.com> + + * lib/util.c: lib: handle realloc failures safely + +2019-01-22 Dave Pate <dp...@yubico.com> + + * lib/util.c: lib: clear secrets in set_protected_mgm + +2019-01-22 Dave Pate <dp...@yubico.com> + + * lib/ykpiv.c: lib: clear secrets in ykpiv_import_private_key + +2019-01-21 Dave Pate <dp...@yubico.com> + + * lib/internal.h, lib/util.c: lib: correct zero memory defines, + correct overflow checks in _write_certificate + +2019-01-17 Dave Pate <dp...@yubico.com> + + * lib/ykpiv.c: lib: clear secrets in auth api + +2019-01-17 Dave Pate <dp...@yubico.com> + + * lib/ykpiv.c: lib: check that serial/version checks occur during + select + +2019-01-07 Dave Pate <dp...@yubico.com> + + * lib/internal.c, lib/internal.h, lib/ykpiv.c: lib: define constant + for max pin len magic numbers lib: clear pin buffers when no longer + used + +2019-01-07 Dave Pate <dp...@yubico.com> + + * lib/ykpiv.c: lib: check internal authentication crypt errors + +2019-01-07 Dave Pate <dp...@yubico.com> + + * lib/internal.c, lib/ykpiv.c: lib: clear buffers containing key + material + +2019-01-07 Dave Pate <dp...@yubico.com> + + * lib/internal.h, lib/util.c: lib: use secure zero memory platform + functions + +2019-01-07 Dave Pate <dp...@yubico.com> + + * lib/util.c, lib/ykpiv.c: lib: resolves potential reads of + uninitialized data + +2019-03-06 pedro martelletto <pe...@yubico.com> + + * doc/YubiKey_PIV_introduction.adoc: doc: set LC_CTYPE=C; fixes + ef81d164 on MacOS + +2019-03-06 Alessio Di Mauro <a-...@users.noreply.github.com> + + * : Merge pull request #187 from Yubico/pvs_remove_warnings Remove some warnings + +2019-03-06 Gabriel Kihlman <g.kihl...@yubico.com> + + * ykcs11/ykcs11.c: Do not assign variable twice + +2019-03-06 Gabriel Kihlman <g.kihl...@yubico.com> + + * ykcs11/ykcs11.c: Remove duplicate check on op_info.type != + YKCS11_SIGN + +2019-03-05 Klas Lindfors <k...@yubico.com> + + * : commit ef81d1646536d5d9f2056cdc78a4a1052e8851a7 Author: pedro + martelletto <pe...@yubico.com> Date: Tue Mar 5 07:58:09 2019 +0100 + +2019-02-20 Alessio Di Mauro <ales...@yubico.com> + + * : Merge PR#184 + +2019-02-18 Klas Lindfors <k...@yubico.com> + + * windows.mk: bump openssl version and don't include check binaries + +2019-02-15 Alessio Di Mauro <ales...@yubico.com> + + * : Merge PR#183 + +2019-02-15 Alessio Di Mauro <ales...@yubico.com> + + * : Merge PR #182 + +2019-01-07 Alessio Di Mauro <ales...@yubico.com> + + * ykcs11/ykcs11.c: ykcs11: use a large enough buffer when writing EC + signatures + +2019-01-02 Klas Lindfors <k...@yubico.com> + + * : commit 811ddbb22d293aea6508d69bb7b98d8386fc8071 Author: Stacey + Sheldon <s...@solidgoldbomb.org> Date: Tue Jan 1 01:43:51 2019 + -0500 + +2019-01-01 Stacey Sheldon <s...@solidgoldbomb.org> + + * tools/fasc.pl: FASC-N: correct encoding of the packed 4-bit + decimal format with odd parity The BCD digits in the FASC-N credential are sent lsb first followed + by an odd parity. Since this perl script is simply packing the bits + in their expected order, the encodings should exactly match figure 7 + in "Technical Implementation Guidance: Smart Card Enabled Physical + Access Control Systems Version 2.2". + +2018-12-18 Klas Lindfors <k...@yubico.com> + + * tools/fasc.pl: fix fasc-n value of 1 relates #177 + +2018-09-21 Klas Lindfors <k...@yubico.com> + + * : commit 898b85821cbfa2c0b841e46d39a45b42e9891bfd Author: Klas + Lindfors <k...@yubico.com> Date: Tue Sep 18 08:38:57 2018 +0200 + +2018-09-14 Dave Pate <notdp...@gmail.com> + + * configure.ac, lib/internal.c, lib/internal.h, lib/util.c, + lib/ykpiv.c, lib/ykpiv.h, lib/ykpiv.map, tool/yubico-piv-tool.c: + libykpiv/piv-tool 1.6.3 lib: promote get_serial to base API lib: add + ykpiv_get_serial to external API tool: add serial number/version to + status command build: fix msvc build of case insensitive-reader + (missing strncasecmp and cast warnings) lib: consolidate neo/yk4 + + yk5 serial number routines lib: fix GCC 8 compilier warnings lib: + reimplement deauthenticate to select mgmt aid build: disable + -Waggregate-return lib: fix warning differences between gcc and msvc + lib: add option to disable implicit card transactions lib: remove + application reselect prior to crypt operations build: fix msvc + warnings wrt length checking logic fixes lib: fix error condition + logic in untransacted internal functions lib: create internal + transactionless ykpiv_transfer_data + +2018-09-14 Klas Lindfors <k...@yubico.com> + + * NEWS, configure.ac: bump version to 1.6.3 + 2018-09-14 Klas Lindfors <k...@yubico.com> * NEWS: NEWS for 1.6.2 diff -Nru yubico-piv-tool-1.6.2/configure yubico-piv-tool-1.7.0/configure --- yubico-piv-tool-1.6.2/configure 2018-09-14 09:21:38.000000000 +0200 +++ yubico-piv-tool-1.7.0/configure 2019-04-03 09:53:50.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for yubico-piv-tool 1.6.2. +# Generated by GNU Autoconf 2.69 for yubico-piv-tool 1.7.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='yubico-piv-tool' PACKAGE_TARNAME='yubico-piv-tool' -PACKAGE_VERSION='1.6.2' -PACKAGE_STRING='yubico-piv-tool 1.6.2' +PACKAGE_VERSION='1.7.0' +PACKAGE_STRING='yubico-piv-tool 1.7.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1430,7 +1430,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures yubico-piv-tool 1.6.2 to adapt to many kinds of systems. +\`configure' configures yubico-piv-tool 1.7.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1501,7 +1501,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of yubico-piv-tool 1.6.2:";; + short | recursive ) echo "Configuration of yubico-piv-tool 1.7.0:";; esac cat <<\_ACEOF @@ -1649,7 +1649,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -yubico-piv-tool configure 1.6.2 +yubico-piv-tool configure 1.7.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2014,7 +2014,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by yubico-piv-tool $as_me 1.6.2, which was +It was created by yubico-piv-tool $as_me 1.7.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2397,11 +2397,11 @@ # Interfaces changed/added/removed: CURRENT++ REVISION=0 # Interfaces added: AGE++ # Interfaces removed: AGE=0 -LT_CURRENT=5 +LT_CURRENT=6 -LT_REVISION=4 +LT_REVISION=0 -LT_AGE=4 +LT_AGE=5 am__api_version='1.15' @@ -2890,7 +2890,7 @@ # Define the identity of the package. PACKAGE='yubico-piv-tool' - VERSION='1.6.2' + VERSION='1.7.0' cat >>confdefs.h <<_ACEOF @@ -15433,6 +15433,7 @@ nw="$nw -Wconversion" # Too many warnings for now nw="$nw -Wsuggest-attribute=pure" # Is it worth using attributes? nw="$nw -Wsuggest-attribute=const" # Is it worth using attributes? + nw="$nw -Waggregate-return" # returning structs shouldn't be a problem @@ -16435,7 +16436,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by yubico-piv-tool $as_me 1.6.2, which was +This file was extended by yubico-piv-tool $as_me 1.7.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16492,7 +16493,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -yubico-piv-tool config.status 1.6.2 +yubico-piv-tool config.status 1.7.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru yubico-piv-tool-1.6.2/configure.ac yubico-piv-tool-1.7.0/configure.ac --- yubico-piv-tool-1.6.2/configure.ac 2018-08-17 09:45:01.000000000 +0200 +++ yubico-piv-tool-1.7.0/configure.ac 2019-04-03 09:49:28.000000000 +0200 @@ -25,7 +25,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -AC_INIT([yubico-piv-tool], [1.6.2]) +AC_INIT([yubico-piv-tool], [1.7.0]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) @@ -33,9 +33,9 @@ # Interfaces changed/added/removed: CURRENT++ REVISION=0 # Interfaces added: AGE++ # Interfaces removed: AGE=0 -AC_SUBST([LT_CURRENT], 5) -AC_SUBST([LT_REVISION], 4) -AC_SUBST([LT_AGE], 4) +AC_SUBST([LT_CURRENT], 6) +AC_SUBST([LT_REVISION], 0) +AC_SUBST([LT_AGE], 5) AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AM_SILENT_RULES([yes]) @@ -224,6 +224,7 @@ nw="$nw -Wconversion" # Too many warnings for now nw="$nw -Wsuggest-attribute=pure" # Is it worth using attributes? nw="$nw -Wsuggest-attribute=const" # Is it worth using attributes? + nw="$nw -Waggregate-return" # returning structs shouldn't be a problem gl_MANYWARN_ALL_GCC([ws]) gl_MANYWARN_COMPLEMENT(ws, [$ws], [$nw]) diff -Nru yubico-piv-tool-1.6.2/debian/changelog yubico-piv-tool-1.7.0/debian/changelog --- yubico-piv-tool-1.6.2/debian/changelog 2018-09-25 11:40:12.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/changelog 2019-04-06 20:21:30.000000000 +0200 @@ -1,3 +1,19 @@ +yubico-piv-tool (1.7.0-1) UNRELEASED; urgency=high (security fixes) + + [ Nicolas Braud-Santoni ] + * New upstream version 1.7.0 + + Security fixes. + + Documentation fixes. + + ykcs11: Fix ECDSA signatures. + + * debian/control: Update Uploader's email address + * debian/upstream: Update keyring and its generation script + + [ Simon Josefsson ] + * Drop myself from Uploaders. + + -- Nicolas Braud-Santoni <ni...@debian.org> Sat, 06 Apr 2019 20:21:30 +0200 + yubico-piv-tool (1.6.2-1) unstable; urgency=high * New upstream version 1.6.2. diff -Nru yubico-piv-tool-1.6.2/debian/compat yubico-piv-tool-1.7.0/debian/compat --- yubico-piv-tool-1.6.2/debian/compat 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/compat 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -11 diff -Nru yubico-piv-tool-1.6.2/debian/control yubico-piv-tool-1.7.0/debian/control --- yubico-piv-tool-1.6.2/debian/control 2018-09-25 11:40:12.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/control 2019-04-06 20:21:30.000000000 +0200 @@ -1,15 +1,14 @@ Source: yubico-piv-tool Maintainer: Debian Authentication Maintainers <pkg-auth-maintain...@lists.alioth.debian.org> Uploaders: - Nicolas Braud-Santoni <nico...@braud-santoni.eu>, + Nicolas Braud-Santoni <ni...@debian.org>, Alessio Di Mauro <ales...@yubico.com>, - Simon Josefsson <si...@josefsson.org>, Klas Lindfors <k...@yubico.com>, Dain Nilsson <d...@yubico.com> Section: utils Priority: optional -Build-Depends: debhelper (>= 11), pkg-config, libpcsclite-dev, check, libssl-dev, gengetopt, help2man, chrpath -Standards-Version: 4.2.1 +Build-Depends: debhelper-compat (= 12), pkg-config, libpcsclite-dev, check, libssl-dev, gengetopt, help2man +Standards-Version: 4.3.0 Homepage: https://developers.yubico.com/yubico-piv-tool/ Vcs-Browser: https://salsa.debian.org/auth-team/yubico-piv-tool Vcs-Git: https://salsa.debian.org/auth-team/yubico-piv-tool.git diff -Nru yubico-piv-tool-1.6.2/debian/libykpiv1.symbols yubico-piv-tool-1.7.0/debian/libykpiv1.symbols --- yubico-piv-tool-1.6.2/debian/libykpiv1.symbols 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/libykpiv1.symbols 2019-04-06 20:21:30.000000000 +0200 @@ -1,9 +1,11 @@ libykpiv.so.1 libykpiv1 #MINVER# +* Build-Depends-Package: libykpiv-dev YKPIV_0.1.0@YKPIV_0.1.0 0.1.0 YKPIV_0.2.0@YKPIV_0.2.0 1.0.0 YKPIV_1.1.0@YKPIV_1.1.0 1.4.0 YKPIV_1.2.0@YKPIV_1.2.0 1.4.0 YKPIV_1.3.0@YKPIV_1.3.0 1.4.0 + YKPIV_1.6.0@YKPIV_1.6.0 1.7.0 ykpiv_authenticate@YKPIV_0.1.0 0.1.0 ykpiv_change_pin@YKPIV_1.3.0 1.4.0 ykpiv_change_puk@YKPIV_1.3.0 1.4.0 @@ -34,6 +36,7 @@ ykpiv_connect_with_external_card@YKPIV_1.5.0 1.5.0 ykpiv_done_with_external_card@YKPIV_1.5.0 1.5.0 ykpiv_get_pin_retries@YKPIV_1.5.0 1.5.0 + ykpiv_get_serial@YKPIV_1.6.0 1.7.0 ykpiv_init_with_allocator@YKPIV_1.5.0 1.5.0 ykpiv_set_pin_retries@YKPIV_1.5.0 1.5.0 ykpiv_util_block_puk@YKPIV_1.5.0 1.5.0 diff -Nru yubico-piv-tool-1.6.2/debian/libykpiv-dev.install yubico-piv-tool-1.7.0/debian/libykpiv-dev.install --- yubico-piv-tool-1.6.2/debian/libykpiv-dev.install 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/libykpiv-dev.install 2019-04-06 20:21:30.000000000 +0200 @@ -1,4 +1,4 @@ usr/lib/*/libykpiv.so usr/lib/*/libykpiv.a -usr/lib/*/pkgconfig +usr/lib/*/pkgconfig/ykpiv.pc usr/include/ykpiv diff -Nru yubico-piv-tool-1.6.2/debian/not-installed yubico-piv-tool-1.7.0/debian/not-installed --- yubico-piv-tool-1.6.2/debian/not-installed 1970-01-01 01:00:00.000000000 +0100 +++ yubico-piv-tool-1.7.0/debian/not-installed 2019-04-06 20:21:30.000000000 +0200 @@ -0,0 +1,7 @@ +# ykcs11 is a PKCS#11 provider +usr/lib/*/libykcs11.a +usr/lib/*/pkgconfig/ykcs11.pc + +# Do not ship libtools cruft +usr/lib/*/libykcs11.la +usr/lib/*/libykpiv.la diff -Nru yubico-piv-tool-1.6.2/debian/rules yubico-piv-tool-1.7.0/debian/rules --- yubico-piv-tool-1.6.2/debian/rules 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/rules 2019-04-06 20:21:30.000000000 +0200 @@ -5,11 +5,8 @@ %: dh $@ -override_dh_install: - chrpath -d $(CURDIR)/debian/tmp/usr/bin/* - chrpath -d $(CURDIR)/debian/tmp/usr/lib/*/libykpiv.so.* - chrpath -d $(CURDIR)/debian/tmp/usr/lib/*/libykcs11.so.* - find debian/tmp -name \*.la -delete - find debian/tmp -name libykcs11.a -delete - find debian/tmp -name ykcs11-version.h -delete - dh_install --fail-missing +override_dh_auto_configure: + dh_auto_configure -- --disable-rpath + +override_dh_missing: + dh_missing --fail-missing diff -Nru yubico-piv-tool-1.6.2/debian/upstream/signing-key.asc yubico-piv-tool-1.7.0/debian/upstream/signing-key.asc --- yubico-piv-tool-1.6.2/debian/upstream/signing-key.asc 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/upstream/signing-key.asc 2019-04-06 20:21:30.000000000 +0200 @@ -7,36 +7,36 @@ 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 @@ -782,183 +782,129 @@ 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 -=o33d +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 +df3P4O4hfB3YkRQ= +=D4Rg -----END PGP PUBLIC KEY BLOCK----- diff -Nru yubico-piv-tool-1.6.2/debian/upstream/signing-key.sh yubico-piv-tool-1.7.0/debian/upstream/signing-key.sh --- yubico-piv-tool-1.6.2/debian/upstream/signing-key.sh 2018-09-25 11:38:58.000000000 +0200 +++ yubico-piv-tool-1.7.0/debian/upstream/signing-key.sh 2019-04-06 20:21:30.000000000 +0200 @@ -2,16 +2,20 @@ set -euo pipefail KEYS=( - 0A3B0262BCA1705307D5FF06BCA00FD4B2168C0A # Klas Lindfors <k...@yubico.com> - 20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <d...@yubico.com> - B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <ales...@yubico.com> - FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <t...@yubico.com> - B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanp...@yubico.com> - 8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <d...@yubico.com> - 57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <e...@yubico.com> - 268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <tre...@yubico.com> - EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pe...@yubico.com> + 0A3B0262BCA1705307D5FF06BCA00FD4B2168C0A # Klas Lindfors <k...@yubico.com> + 20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <d...@yubico.com> + B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <ales...@yubico.com> + FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <t...@yubico.com> + B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanp...@yubico.com> + 8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <d...@yubico.com> + 57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <e...@yubico.com> + 268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <tre...@yubico.com> + EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pe...@yubico.com> ) -exec gpg --export --export-options export-minimal -a -o signing-key.asc --yes \ - "${KEYS[@]}" +if [ $# -gt 0 ]; then + exec gpg "$@" "${KEYS[@]}" +else + exec gpg --export --export-options export-minimal -a --yes \ + -o "$(dirname "$0")/signing-key.asc" "${KEYS[@]}" +fi diff -Nru yubico-piv-tool-1.6.2/debian/ykcs11.lintian-overrides yubico-piv-tool-1.7.0/debian/ykcs11.lintian-overrides --- yubico-piv-tool-1.6.2/debian/ykcs11.lintian-overrides 1970-01-01 01:00:00.000000000 +0100 +++ yubico-piv-tool-1.7.0/debian/ykcs11.lintian-overrides 2019-04-06 20:21:30.000000000 +0200 @@ -0,0 +1,5 @@ +# Lintian overrides for quirks related to ykcs11 being a PKCS#11 provider +# (essentially a dlopen-able plugin) +package-name-doesnt-match-sonames libykcs11-1 +non-dev-pkg-with-shlib-symlink usr/lib/x86_64-linux-gnu/libykcs11.so.* usr/lib/x86_64-linux-gnu/libykcs11.so +no-symbols-control-file usr/lib/x86_64-linux-gnu/libykcs11.so.* diff -Nru yubico-piv-tool-1.6.2/doc/YubiKey_PIV_introduction.adoc yubico-piv-tool-1.7.0/doc/YubiKey_PIV_introduction.adoc --- yubico-piv-tool-1.6.2/doc/YubiKey_PIV_introduction.adoc 2017-10-17 10:17:18.000000000 +0200 +++ yubico-piv-tool-1.7.0/doc/YubiKey_PIV_introduction.adoc 2019-04-03 09:44:44.000000000 +0200 @@ -37,30 +37,30 @@ software will ask for key/pin to be input. For the management key option (-k) this is achieved by leaving out the value but will specifying -k. - $ key=`dd if=/dev/random bs=1 count=24 2>/dev/null | hexdump -v -e '/1 "%02X"'` - $ echo $key - $ yubico-piv-tool -aset-mgm-key -n$key + $ key=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -d '[:lower:]' | tr -cd '[:xdigit:]' | fold -w48 | head -1) + $ echo ${key} + $ yubico-piv-tool -aset-mgm-key -n${key} The PIN and PUK should be changed as well. - $ pin=`dd if=/dev/random bs=1 count=6 2>/dev/null | hexdump -v -e '/1 "%u"'|cut -c1-6` - $ echo $pin + $ pin=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd '[:digit:]' | fold -w6 | head -1) + $ echo ${pin} - $ puk=`dd if=/dev/random bs=1 count=6 2>/dev/null | hexdump -v -e '/1 "%u"'|cut -c1-8` - $ echo $puk + $ puk=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd '[:digit:]' | fold -w8 | head -1) + $ echo ${puk} - $ yubico-piv-tool -achange-pin -P123456 -N$pin - $ yubico-piv-tool -achange-puk -P12345678 -N$puk + $ yubico-piv-tool -achange-pin -P123456 -N${pin} + $ yubico-piv-tool -achange-puk -P12345678 -N${puk} === Other useful commands To generate a new private key: - $ yubico-piv-tool -k$key -agenerate -s9c + $ yubico-piv-tool -k${key} -agenerate -s9c To reset PIN/PUK retry counter AND codes (default pin 123456 puk 12345678): - $ yubico-piv-tool -k$key -averify -P$pin -apin-retries --pin-retries=3 --puk-retries=3 + $ yubico-piv-tool -k${key} -averify -P${pin} -apin-retries --pin-retries=3 --puk-retries=3 To reset the application (PIN/PUK need to be blocked hence trying a couple of times -- you need to modify this if you have changed the default diff -Nru yubico-piv-tool-1.6.2/lib/internal.c yubico-piv-tool-1.7.0/lib/internal.c --- yubico-piv-tool-1.6.2/lib/internal.c 2018-08-09 10:23:52.000000000 +0200 +++ yubico-piv-tool-1.7.0/lib/internal.c 2019-04-03 09:47:54.000000000 +0200 @@ -241,6 +241,7 @@ EXIT: #ifdef _WINDOWS if (pbSessionBlob) { + yc_memzero(pbSessionBlob, cbSessionBlob); free(pbSessionBlob); pbSessionBlob = NULL; } @@ -304,8 +305,11 @@ #else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" /* openssl returns void */ DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 1); +#pragma GCC diagnostic pop #endif @@ -336,8 +340,11 @@ #else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" /* openssl returns void */ DES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 0); +#pragma GCC diagnostic pop #endif @@ -347,6 +354,7 @@ bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key) { #ifdef _WINDOWS + bool rv = false; /* defined weak keys, borrowed from openssl to be consistent across platforms */ static const unsigned char weak_keys[][DES_LEN_DES] = { /* weak keys */ @@ -394,13 +402,20 @@ if ((0 == memcmp(weak_keys[i], tmp, DES_LEN_DES)) || (0 == memcmp(weak_keys[i], tmp + DES_LEN_DES, DES_LEN_DES)) || (0 == memcmp(weak_keys[i], tmp + 2*DES_LEN_DES, DES_LEN_DES))) { - return true; + rv = true; + break; } } - return false; + yc_memzero(tmp, DES_LEN_3DES); + return rv; #else + (void)cb_key; /* unused */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" return DES_is_weak_key((const_DES_cblock *)key); +#pragma GCC diagnostic pop #endif } @@ -431,7 +446,7 @@ return rc; } -pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key) { +pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key) { pkcs5_rc rc = PKCS5_OK; #ifdef _WINDOWS @@ -447,6 +462,8 @@ */ if (STATUS_SUCCESS == BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG)) { + /* suppress const qualifier warning b/c BCrypt doesn't take const input buffers */ +#pragma warning(suppress: 4090) if (STATUS_SUCCESS != BCryptDeriveKeyPBKDF2(hAlg, (PUCHAR)password, (ULONG)cb_password, (PUCHAR)salt, (ULONG)cb_salt, iterations, key, (ULONG)cb_key, 0)) { rc = PKCS5_GENERAL_ERROR; } @@ -459,8 +476,11 @@ #else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" /* for some reason openssl always returns 1 for PBKDF2 */ - PKCS5_PBKDF2_HMAC_SHA1((const char*)password, cb_password, salt, cb_salt, iterations, cb_key, key); + PKCS5_PBKDF2_HMAC_SHA1((const char*)password, cb_password, salt, cb_salt, iterations, cb_key, (unsigned char*)key); +#pragma GCC diagnostic pop #endif @@ -491,7 +511,6 @@ #ifdef _WIN32 HKEY hKey = 0; - DWORD dwErr = 0; DWORD dwValue = 0; DWORD dwType = 0; DWORD cbValue = sizeof(dwValue); diff -Nru yubico-piv-tool-1.6.2/lib/internal.h yubico-piv-tool-1.7.0/lib/internal.h --- yubico-piv-tool-1.6.2/lib/internal.h 2018-05-08 09:52:22.000000000 +0200 +++ yubico-piv-tool-1.7.0/lib/internal.h 2019-04-03 09:47:54.000000000 +0200 @@ -126,6 +126,7 @@ #define CB_OBJ_TAG_MIN 2 // 1 byte tag + 1 byte len #define CB_OBJ_TAG_MAX (CB_OBJ_TAG_MIN + 2) // 1 byte tag + 3 bytes len +#define CB_PIN_MAX 8 #define member_size(type, member) sizeof(((type*)0)->member) typedef enum { @@ -178,21 +179,21 @@ typedef union u_APDU APDU; typedef struct des_key des_key; -extern unsigned const char aid[]; - des_rc des_import_key(const int type, const unsigned char* keyraw, const size_t keyrawlen, des_key** key); des_rc des_destroy_key(des_key* key); des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen); des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen); -pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key); +pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key); bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key); prng_rc _ykpiv_prng_generate(unsigned char *buffer, const size_t cb_req); ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state); ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state); ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state); -int _ykpiv_set_length(unsigned char *buffer, size_t length); -int _ykpiv_get_length(const unsigned char *buffer, size_t *len); +ykpiv_rc _ykpiv_select_application(ykpiv_state *state); +unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length); +unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len); +bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len); void* _ykpiv_alloc(ykpiv_state *state, size_t size); void* _ykpiv_realloc(ykpiv_state *state, void *address, size_t size); @@ -200,8 +201,14 @@ ykpiv_rc _ykpiv_save_object(ykpiv_state *state, int object_id, unsigned char *indata, size_t len); ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, unsigned char *data, unsigned long *len); ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu, unsigned char *data, uint32_t *recv_len, int *sw); -ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version); -ykpiv_rc _ykpiv_util_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force); +ykpiv_rc _ykpiv_transfer_data( + ykpiv_state *state, + const unsigned char *templ, + const unsigned char *in_data, + long in_len, + unsigned char *out_data, + unsigned long *out_len, + int *sw); /* authentication functions not ready for public api */ ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const size_t challenge_len); @@ -231,6 +238,21 @@ void yc_log_event(uint32_t id, yc_log_level_t level, const char *sz_format, ...); +#ifdef _WIN32 +#include <windows.h> +#define yc_memzero SecureZeroMemory +#elif defined(BSD) +#include <strings.h> +#define yc_memzero explicit_bzero +#elif defined(__linux__) +#include <openssl/crypto.h> +#define yc_memzero OPENSSL_cleanse +#else +#define __STDC_WANT_LIB_EXT1__ 1 +#include <string.h> +#define yc_memzero(_p, _n) (void)memset_s(_p, (rsize_t)_n, 0, (rsize_t)_n) +#endif + #ifdef __cplusplus } #endif diff -Nru yubico-piv-tool-1.6.2/lib/util.c yubico-piv-tool-1.7.0/lib/util.c --- yubico-piv-tool-1.6.2/lib/util.c 2018-08-09 10:23:52.000000000 +0200 +++ yubico-piv-tool-1.7.0/lib/util.c 2019-04-03 09:47:54.000000000 +0200 @@ -57,8 +57,8 @@ */ const uint8_t CHUID_TMPL[] = { 0x30, 0x19, 0xd4, 0xe7, 0x39, 0xda, 0x73, 0x9c, 0xed, 0x39, 0xce, 0x73, 0x9d, - 0x83, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0x38, 0x42, 0x10, 0xc3, - 0xf5, 0x34, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0xc8, 0x42, 0x10, 0xc3, + 0xeb, 0x34, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x08, 0x32, 0x30, 0x33, 0x30, 0x30, 0x31, 0x30, 0x31, 0x3e, 0x00, 0xfe, 0x00, }; @@ -208,8 +208,9 @@ } ykpiv_devmodel ykpiv_util_devicemodel(ykpiv_state *state) { - if (!state || state->context == SCARD_E_INVALID_HANDLE) + if (!state || !state->context || (state->context == (uintptr_t)-1)) { return DEVTYPE_UNKNOWN; + } return (state->isNEO ? DEVTYPE_NEOr3 : DEVTYPE_YK4); } @@ -217,6 +218,7 @@ ykpiv_rc res = YKPIV_OK; ykpiv_key *pKey = NULL; uint8_t *pData = NULL; + uint8_t *pTemp = NULL; size_t cbData = 0; size_t offset = 0; uint8_t buf[CB_BUF_MAX]; @@ -273,17 +275,21 @@ for (i = 0; i < sizeof(SLOTS); i++) { cbBuf = sizeof(buf); + res = _read_certificate(state, SLOTS[i], buf, &cbBuf); - if (YKPIV_OK == (res = _read_certificate(state, SLOTS[i], buf, &cbBuf))) { + if ((res == YKPIV_OK) && (cbBuf > 0)) { // add current slot to result, grow result buffer if necessary cbRealloc = (sizeof(ykpiv_key) + cbBuf - 1) > (cbData - offset) ? MAX((sizeof(ykpiv_key) + cbBuf - 1) - (cbData - offset), CB_PAGE) : 0; if (0 != cbRealloc) { - if (NULL == (pData = _ykpiv_realloc(state, pData, cbData + cbRealloc))) { + if (!(pTemp = _ykpiv_realloc(state, pData, cbData + cbRealloc))) { + /* realloc failed, pData will be freed in cleanup */ res = YKPIV_MEMORY_ERROR; goto Cleanup; } + pData = pTemp; + pTemp = NULL; } cbData += cbRealloc; @@ -343,7 +349,15 @@ *data_len = 0; if (YKPIV_OK == (res = _read_certificate(state, slot, buf, &cbBuf))) { - if (NULL == (*data = _ykpiv_alloc(state, cbBuf))) { + + /* handle those who write empty certificate blobs to PIV objects */ + if (cbBuf == 0) { + *data = NULL; + *data_len = 0; + goto Cleanup; + } + + if (!(*data = _ykpiv_alloc(state, cbBuf))) { res = YKPIV_MEMORY_ERROR; goto Cleanup; } @@ -415,7 +429,7 @@ memcpy(&flags, p_item, cb_item); } else { - if (state->verbose) { fprintf(stderr, "admin flags exist, but are incorrect size = %zu", cb_item); } + if (state->verbose) { fprintf(stderr, "admin flags exist, but are incorrect size = %lu", (unsigned long)cb_item); } } } } @@ -454,17 +468,17 @@ if (YKPIV_OK == (res = _ykpiv_fetch_object(state, YKPIV_OBJ_MSCMAP, buf, (unsigned long*)&cbBuf))) { ptr = buf; - // check that object contents are at least large enough to read the header + /* check that object contents are at least large enough to read the header */ if (cbBuf < CB_OBJ_TAG_MIN) { res = YKPIV_OK; goto Cleanup; } if (*ptr++ == TAG_MSCMAP) { - ptr += _ykpiv_get_length(ptr, &len); + ptr += (unsigned long)_ykpiv_get_length(ptr, &len); - // check that decoded length represents object contents - if (len > (cbBuf - (ptr - buf))) { + /* check that decoded length represents object contents */ + if (len > (cbBuf - (size_t)(ptr - buf))) { res = YKPIV_OK; goto Cleanup; } @@ -474,7 +488,7 @@ goto Cleanup; } - // should check if container map isn't corrupt + /* should check if container map isn't corrupt */ memcpy(*containers, ptr, len); *n_containers = len / sizeof(ykpiv_container); @@ -516,7 +530,7 @@ // encode object data for storage // calculate the required length of the encoded object - req_len = 1 /* data tag */ + _ykpiv_set_length(buf, data_len) + data_len; + req_len = 1 /* data tag */ + (unsigned long)_ykpiv_set_length(buf, data_len) + data_len; if (req_len > _obj_size_max(state)) { res = YKPIV_SIZE_ERROR; @@ -546,6 +560,7 @@ int object_id = 0; uint8_t tag = 0; uint8_t *pData = NULL; + uint8_t *pTemp = NULL; size_t cbData = 0; size_t cbRealloc = 0; size_t offset = 0; @@ -588,7 +603,7 @@ ptr += _ykpiv_get_length(ptr, &len); // check that decoded length represents object contents - if (len > (cbBuf - (ptr - buf))) { + if (len > (cbBuf - (size_t)(ptr - buf))) { res = YKPIV_OK; goto Cleanup; } @@ -596,10 +611,13 @@ cbRealloc = len > (cbData - offset) ? len - (cbData - offset) : 0; if (0 != cbRealloc) { - if (NULL == (pData = _ykpiv_realloc(state, pData, cbData + cbRealloc))) { + if (!(pTemp = _ykpiv_realloc(state, pData, cbData + cbRealloc))) { + /* realloc failed, pData will be freed in cleanup */ res = YKPIV_MEMORY_ERROR; goto Cleanup; } + pData = pTemp; + pTemp = NULL; } cbData += cbRealloc; @@ -671,14 +689,14 @@ offset = 0; data_chunk = MIN(cb_obj_max - CB_OBJ_TAG_MAX, data_len - data_offset); - // encode object data for storage + /* encode object data for storage */ buf[offset++] = (i == (n_objs - 1)) ? TAG_MSROOTS_END : TAG_MSROOTS_MID; offset += _ykpiv_set_length(buf + offset, data_chunk); memcpy(buf + offset, data + data_offset, data_chunk); offset += data_chunk; - // write onto device - res = _ykpiv_save_object(state, YKPIV_OBJ_MSROOTS1 + i, buf, offset); + /* write onto device */ + res = _ykpiv_save_object(state, (int)(YKPIV_OBJ_MSROOTS1 + i), buf, offset); if (YKPIV_OK != res) { goto Cleanup; @@ -811,7 +829,7 @@ *in_ptr++ = touch_policy; } - if (YKPIV_OK != (res = ykpiv_transfer_data(state, templ, in_data, (long)(in_ptr - in_data), data, &recv_len, &sw))) { + if (YKPIV_OK != (res = _ykpiv_transfer_data(state, templ, in_data, (long)(in_ptr - in_data), data, &recv_len, &sw))) { if (state->verbose) { fprintf(stderr, "Failed to communicate.\n"); } goto Cleanup; } @@ -1084,7 +1102,7 @@ if (YKPIV_OK == (res = _read_metadata(state, TAG_ADMIN, data, &cb_data))) { if (YKPIV_OK == (res = _get_metadata_item(data, cb_data, TAG_ADMIN_SALT, &p_item, &cb_item))) { if (cb_item != CB_ADMIN_SALT) { - if (state->verbose) fprintf(stderr, "derived mgm salt exists, but is incorrect size = %zu\n", cb_item); + if (state->verbose) fprintf(stderr, "derived mgm salt exists, but is incorrect size = %lu\n", (unsigned long)cb_item); res = YKPIV_GENERIC_ERROR; goto Cleanup; } @@ -1127,7 +1145,7 @@ } if (cb_item != member_size(ykpiv_mgm, data)) { - if (state->verbose) fprintf(stderr, "protected data contains mgm, but is the wrong size = %zu\n", cb_item); + if (state->verbose) fprintf(stderr, "protected data contains mgm, but is the wrong size = %lu\n", (unsigned long)cb_item); res = YKPIV_AUTHENTICATION_ERROR; goto Cleanup; } @@ -1136,7 +1154,7 @@ Cleanup: - memset(data, 0, sizeof(data)); + yc_memzero(data, sizeof(data)); _ykpiv_end_transaction(state); return res; @@ -1174,7 +1192,7 @@ } } - if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; + if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) { res = YKPIV_PCSC_ERROR; goto Cleanup; } if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; /* try to set the mgm key as long as we don't encounter a fatal error */ @@ -1245,7 +1263,7 @@ memcpy(&flags_1, p_item, cb_item); } else { - if (state->verbose) fprintf(stderr, "admin data flags are an incorrect size = %zu\n", cb_item); + if (state->verbose) fprintf(stderr, "admin data flags are an incorrect size = %lu\n", (unsigned long)cb_item); } /* remove any existing salt */ @@ -1269,8 +1287,8 @@ Cleanup: - memset(data, 0, sizeof(data)); - memset(mgm_key, 0, sizeof(mgm_key)); + yc_memzero(data, sizeof(data)); + yc_memzero(mgm_key, sizeof(mgm_key)); _ykpiv_end_transaction(state); return res; @@ -1303,7 +1321,7 @@ object_id = YKPIV_OBJ_SIGNATURE; break; - case YKPIV_KEY_KEYMGM: + case YKPIV_KEY_KEYMGM: object_id = YKPIV_OBJ_KEY_MANAGEMENT; break; @@ -1322,88 +1340,13 @@ break; } - return object_id; -} - -/* caller must make sure that this is wrapped in a transaction for synchronized operation */ -ykpiv_rc _ykpiv_util_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force) { - ykpiv_rc res = YKPIV_OK; - APDU apdu; - const uint8_t yk_applet[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 }; - unsigned char data[0xff]; - uint32_t recv_len = sizeof(data); - int sw; - uint8_t *p_temp = NULL; - - if (!state) { - return YKPIV_ARGUMENT_ERROR; - } - - if (!f_force && (state->serial != 0)) { - if (p_serial) *p_serial = state->serial; - return YKPIV_OK; - } - - /* this function does not use ykpiv_transfer_data because it requires two apdus and selects a different app */ - - memset(apdu.raw, 0, sizeof(apdu)); - apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; - apdu.st.p1 = 0x04; - apdu.st.lc = sizeof(yk_applet); - memcpy(apdu.st.data, yk_applet, sizeof(yk_applet)); - - if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { - if (state->verbose) { - fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); - } - goto Cleanup; - } - else if (sw != SW_SUCCESS) { - if (state->verbose) { - fprintf(stderr, "Failed selecting yk application: %04x\n", sw); - } - res = YKPIV_GENERIC_ERROR; - goto Cleanup; - } - - recv_len = sizeof(data); - memset(apdu.raw, 0, sizeof(apdu)); - apdu.st.ins = 0x01; - apdu.st.p1 = 0x10; - apdu.st.lc = 0x00; - - if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { - if (state->verbose) { - fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); - } - goto Cleanup; - } - else if (sw != SW_SUCCESS) { - if (state->verbose) { - fprintf(stderr, "Failed retrieving serial number: %04x\n", sw); - } - res = YKPIV_GENERIC_ERROR; - goto Cleanup; - } - - p_temp = (uint8_t*)(&state->serial); - - *p_temp++ = data[3]; - *p_temp++ = data[2]; - *p_temp++ = data[1]; - *p_temp++ = data[0]; - - if (p_serial) *p_serial = state->serial; - -Cleanup: - - return res; + return (uint32_t)object_id; } static ykpiv_rc _read_certificate(ykpiv_state *state, uint8_t slot, uint8_t *buf, size_t *buf_len) { ykpiv_rc res = YKPIV_OK; uint8_t *ptr = NULL; - int object_id = ykpiv_util_slot_object(slot); + int object_id = (int)ykpiv_util_slot_object(slot); size_t len = 0; if (-1 == object_id) return YKPIV_INVALID_OBJECT; @@ -1423,7 +1366,7 @@ ptr += _ykpiv_get_length(ptr, &len); // check that decoded length represents object contents - if (len > (*buf_len - (ptr - buf))) { + if (len > (*buf_len - (size_t)(ptr - buf))) { *buf_len = 0; return YKPIV_OK; } @@ -1441,7 +1384,7 @@ static ykpiv_rc _write_certificate(ykpiv_state *state, uint8_t slot, uint8_t *data, size_t data_len, uint8_t certinfo) { uint8_t buf[CB_OBJ_MAX]; - int object_id = ykpiv_util_slot_object(slot); + int object_id = (int)ykpiv_util_slot_object(slot); size_t offset = 0; size_t req_len = 0; @@ -1464,8 +1407,10 @@ // calculate the required length of the encoded object req_len = 1 /* cert tag */ + 3 /* compression tag + data*/ + 2 /* lrc */; req_len += _ykpiv_set_length(buf, data_len); + req_len += data_len; - if (req_len > _obj_size_max(state)) return YKPIV_SIZE_ERROR; + if (req_len < data_len) return YKPIV_SIZE_ERROR; /* detect overflow of unsigned size_t */ + if (req_len > _obj_size_max(state)) return YKPIV_SIZE_ERROR; /* obj_size_max includes limits for TLV encoding */ buf[offset++] = TAG_CERT; offset += _ykpiv_set_length(buf + offset, data_len); @@ -1512,6 +1457,11 @@ while (p_temp < (data + cb_data)) { tag_temp = *p_temp++; + + if (!_ykpiv_has_valid_length(p_temp, (data + cb_data - p_temp))) { + return YKPIV_SIZE_ERROR; + } + p_temp += _ykpiv_get_length(p_temp, &cb_temp); if (tag_temp == tag) { @@ -1579,16 +1529,24 @@ /* length doesn't match, expand/shrink to fit */ p_next = p_temp + cb_temp; - cb_moved = (long)cb_item - (long)cb_temp + ((long)(cb_item != 0 ? _get_length_size(cb_item) : -1 /* for tag, if deleting */) - (long)cb_len); /* accounts for different length encoding */ + cb_moved = (long)cb_item - (long)cb_temp + + ((long)(cb_item != 0 ? _get_length_size(cb_item) : -1 /* for tag, if deleting */) - + (long)cb_len); /* accounts for different length encoding */ /* length would cause buffer overflow, return error */ - if (*pcb_data + cb_moved > cb_data_max) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" + if ((size_t)(*pcb_data + cb_moved) > cb_data_max) { return YKPIV_GENERIC_ERROR; } +#pragma GCC diagnostic pop /* move remaining data */ - memmove(p_next + cb_moved, p_next, *pcb_data - (p_next - data)); + memmove(p_next + cb_moved, p_next, *pcb_data - (size_t)(p_next - data)); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" *pcb_data += cb_moved; +#pragma GCC diagnostic pop /* re-encode item and insert */ if (cb_item != 0) { @@ -1598,7 +1556,7 @@ } return YKPIV_OK; - } //if tag found + } /* if tag found */ p_temp += cb_temp; } @@ -1610,7 +1568,7 @@ // we did not find an existing tag, append p_temp = data + *pcb_data; - cb_len = _get_length_size(cb_item); + cb_len = (size_t)_get_length_size(cb_item); // length would cause buffer overflow, return error if (*pcb_data + cb_len + cb_item > cb_data_max) { @@ -1666,7 +1624,7 @@ p_temp += _ykpiv_get_length(p_temp, pcb_data); - if (*pcb_data > ((size_t)cb_temp - (p_temp - data))) { + if (*pcb_data > (cb_temp - (size_t)(p_temp - data))) { *pcb_data = 0; return YKPIV_GENERIC_ERROR; } @@ -1712,7 +1670,7 @@ memcpy(pTemp, data, cb_data); pTemp += cb_data; - res = _ykpiv_save_object(state, obj_id, buf, pTemp - buf); + res = _ykpiv_save_object(state, obj_id, buf, (size_t)(pTemp - buf)); } return res; diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.c yubico-piv-tool-1.7.0/lib/ykpiv.c --- yubico-piv-tool-1.6.2/lib/ykpiv.c 2018-09-07 14:18:43.000000000 +0200 +++ yubico-piv-tool-1.7.0/lib/ykpiv.c 2019-04-03 09:47:54.000000000 +0200 @@ -76,11 +76,36 @@ #define ENABLE_APPLICATION_RESELECTION 0 #endif + +/** + * ENABLE_IMPLICIT_TRANSACTIONS - call SCardBeginTransaction for all public API calls + * + * If this is enabled, every public call (prefixed with \r ykpiv_) will call + * SCardBeginTransaction on entry and SCardEndTransaction on exit. + * + * For applications that do not do their own transaction management, like the piv tool + * itself, retaining the default setting of enabled can allow other applications and + * threads to make calls to CCID that can interfere with multi-block data sent to the + * card via SCardTransmitData. + */ +#ifndef ENABLE_IMPLICIT_TRANSACTIONS +#define ENABLE_IMPLICIT_TRANSACTIONS 1 +#endif + +/** + * Platform specific definitions + */ +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#endif + #define YKPIV_MGM_DEFAULT "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len); +static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool force); +static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version); -unsigned const char aid[] = { +static unsigned const char aid[] = { 0xa0, 0x00, 0x00, 0x03, 0x08 }; @@ -130,7 +155,7 @@ } } -int _ykpiv_set_length(unsigned char *buffer, size_t length) { +unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length) { if(length < 0x80) { *buffer++ = (unsigned char)length; return 1; @@ -146,7 +171,7 @@ } } -int _ykpiv_get_length(const unsigned char *buffer, size_t *len) { +unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len) { if(buffer[0] < 0x81) { *len = buffer[0]; return 1; @@ -161,6 +186,19 @@ return 0; } +bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len) { + if ((buffer[0] < 0x81) && (len > 0)) { + return true; + } + else if (((*buffer & 0x7f) == 1) && (len > 1)) { + return true; + } + else if (((*buffer & 0x7f) == 2) && (len > 2)) { + return true; + } + return false; +} + static unsigned char *set_object(int object_id, unsigned char *buffer) { *buffer++ = 0x5c; if(object_id == YKPIV_OBJ_DISCOVERY) { @@ -193,7 +231,7 @@ s->pin = NULL; s->allocator = *allocator; s->verbose = verbose; - s->context = SCARD_E_INVALID_HANDLE; + s->context = (SCARDCONTEXT)-1; *state = s; return YKPIV_OK; } @@ -226,7 +264,7 @@ if(SCardIsValidContext(state->context) == SCARD_S_SUCCESS) { SCardReleaseContext(state->context); - state->context = SCARD_E_INVALID_HANDLE; + state->context = (SCARDCONTEXT)-1; } return YKPIV_OK; @@ -239,8 +277,6 @@ int sw; ykpiv_rc res = YKPIV_OK; - _ykpiv_util_get_serial(state, NULL, false); - memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; @@ -260,7 +296,16 @@ return YKPIV_GENERIC_ERROR; } - _ykpiv_get_version(state, NULL); + /* now that the PIV application is selected, retrieve the version + * and serial number. Previously the NEO/YK4 required switching + * to the yk applet to retrieve the serial, YK5 implements this + * as a PIV applet command. Unfortunately, this change requires + * that we retrieve the version number first, so that get_serial + * can determine how to get the serial number, which for the NEO/Yk4 + * will result in another selection of the PIV applet. */ + + res = _ykpiv_get_version(state, NULL); + if (res == YKPIV_OK) res = _ykpiv_get_serial(state, NULL, false); return res; } @@ -284,6 +329,7 @@ return res; #else + (void)state; return res; #endif } @@ -456,7 +502,7 @@ fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); } SCardReleaseContext(state->context); - state->context = SCARD_E_INVALID_HANDLE; + state->context = (SCARDCONTEXT)-1; return YKPIV_PCSC_ERROR; } @@ -471,7 +517,7 @@ fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); } SCardReleaseContext(state->context); - state->context = SCARD_E_INVALID_HANDLE; + state->context = (SCARDCONTEXT)-1; return YKPIV_PCSC_ERROR; } @@ -481,12 +527,13 @@ } ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state) { +#if ENABLE_IMPLICIT_TRANSACTIONS long rc; - ykpiv_rc res; rc = SCardBeginTransaction(state->card); - if((rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) { - if((res = reconnect(state)) != YKPIV_OK) { + if((long)((unsigned long)rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) { + ykpiv_rc res = YKPIV_OK; + if((res = reconnect(state)) != YKPIV_OK) { return res; } rc = SCardBeginTransaction(state->card); @@ -497,27 +544,33 @@ } return YKPIV_PCSC_ERROR; } +#endif /* ENABLE_IMPLICIT_TRANSACTIONS */ + return YKPIV_OK; } ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state) { +#if ENABLE_IMPLICIT_TRANSACTIONS long rc = SCardEndTransaction(state->card, SCARD_LEAVE_CARD); if(rc != SCARD_S_SUCCESS && state->verbose) { fprintf(stderr, "error: Failed to end pcsc transaction, rc=%08lx\n", rc); return YKPIV_PCSC_ERROR; } +#endif /* ENABLE_IMPLICIT_TRANSACTIONS */ return YKPIV_OK; } -ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, - const unsigned char *in_data, long in_len, - unsigned char *out_data, unsigned long *out_len, int *sw) { +ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, + const unsigned char *in_data, + long in_len, + unsigned char *out_data, + unsigned long *out_len, + int *sw) { const unsigned char *in_ptr = in_data; unsigned long max_out = *out_len; ykpiv_rc res; *out_len = 0; - if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; do { size_t this_size = 0xff; unsigned char data[261]; @@ -587,6 +640,19 @@ } } Cleanup: + return res; +} + +ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, + const unsigned char *in_data, long in_len, + unsigned char *out_data, unsigned long *out_len, int *sw) { + ykpiv_rc res; + + if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) { + *out_len = 0; + return YKPIV_PCSC_ERROR; + } + res = _ykpiv_transfer_data(state, templ, in_data, in_len, out_data, out_len, sw); _ykpiv_end_transaction(state); return res; } @@ -631,6 +697,7 @@ uint32_t recv_len = sizeof(data); int sw; ykpiv_rc res; + des_rc drc = DES_OK; des_key* mgm_key = NULL; size_t out_len = 0; @@ -675,7 +742,12 @@ unsigned char *dataptr = apdu.st.data; unsigned char response[8]; out_len = sizeof(response); - des_decrypt(mgm_key, challenge, sizeof(challenge), response, &out_len); + drc = des_decrypt(mgm_key, challenge, sizeof(challenge), response, &out_len); + + if (drc != DES_OK) { + res = YKPIV_AUTHENTICATION_ERROR; + goto Cleanup; + } recv_len = sizeof(data); memset(apdu.raw, 0, sizeof(apdu)); @@ -713,7 +785,13 @@ { unsigned char response[8]; out_len = sizeof(response); - des_encrypt(mgm_key, challenge, sizeof(challenge), response, &out_len); + drc = des_encrypt(mgm_key, challenge, sizeof(challenge), response, &out_len); + + if (drc != DES_OK) { + res = YKPIV_AUTHENTICATION_ERROR; + goto Cleanup; + } + if (memcmp(response, data + 4, 8) == 0) { res = YKPIV_OK; } @@ -785,6 +863,7 @@ res = YKPIV_GENERIC_ERROR; Cleanup: + yc_memzero(&apdu, sizeof(APDU)); _ykpiv_end_transaction(state); return res; } @@ -838,24 +917,26 @@ switch(algorithm) { case YKPIV_ALGO_RSA1024: key_len = 128; + // fall through case YKPIV_ALGO_RSA2048: if(key_len == 0) { - key_len = 256; + key_len = 256; } if(in_len != key_len) { - return YKPIV_SIZE_ERROR; + return YKPIV_SIZE_ERROR; } break; case YKPIV_ALGO_ECCP256: key_len = 32; + // fall through case YKPIV_ALGO_ECCP384: if(key_len == 0) { - key_len = 48; + key_len = 48; } if(!decipher && in_len > key_len) { - return YKPIV_SIZE_ERROR; + return YKPIV_SIZE_ERROR; } else if(decipher && in_len != (key_len * 2) + 1) { - return YKPIV_SIZE_ERROR; + return YKPIV_SIZE_ERROR; } break; default: @@ -932,11 +1013,12 @@ if (NULL == state) return YKPIV_GENERIC_ERROR; if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; - if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; + /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */ + /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/ res = _general_authenticate(state, raw_in, in_len, sign_out, out_len, algorithm, key, false); -Cleanup: +/* Cleanup: */ _ykpiv_end_transaction(state); return res; } @@ -949,19 +1031,19 @@ if (NULL == state) return YKPIV_GENERIC_ERROR; if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; - if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; - + /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */ + /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/ res = _general_authenticate(state, in, in_len, out, out_len, algorithm, key, true); -Cleanup: +/* Cleanup: */ _ykpiv_end_transaction(state); return res; } -ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version) { +static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version) { APDU apdu; unsigned char data[261]; uint32_t recv_len = sizeof(data); @@ -988,6 +1070,12 @@ if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { return res; } else if(sw == SW_SUCCESS) { + + /* check that we received enough data for the verson number */ + if (recv_len < 3) { + return YKPIV_SIZE_ERROR; + } + state->ver.major = data[0]; state->ver.minor = data[1]; state->ver.patch = data[2]; @@ -1022,6 +1110,143 @@ return res; } +/* caller must make sure that this is wrapped in a transaction for synchronized operation */ +static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force) { + ykpiv_rc res = YKPIV_OK; + APDU apdu; + const uint8_t yk_applet[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 }; + unsigned char data[0xff]; + uint32_t recv_len = sizeof(data); + int sw; + uint8_t *p_temp = NULL; + + if (!state) { + return YKPIV_ARGUMENT_ERROR; + } + + if (!f_force && (state->serial != 0)) { + if (p_serial) *p_serial = state->serial; + return YKPIV_OK; + } + + if (state->ver.major < 5) { + /* get serial from neo/yk4 devices using the otp applet */ + uint8_t temp[0xff]; + + recv_len = sizeof(temp); + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; + apdu.st.p1 = 0x04; + apdu.st.lc = sizeof(yk_applet); + memcpy(apdu.st.data, yk_applet, sizeof(yk_applet)); + + if ((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) { + if (state->verbose) { + fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); + } + goto Cleanup; + } + else if (sw != SW_SUCCESS) { + if (state->verbose) { + fprintf(stderr, "Failed selecting yk application: %04x\n", sw); + } + res = YKPIV_GENERIC_ERROR; + goto Cleanup; + } + + recv_len = sizeof(data); + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = 0x01; + apdu.st.p1 = 0x10; + apdu.st.lc = 0x00; + + if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { + if (state->verbose) { + fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); + } + goto Cleanup; + } + else if (sw != SW_SUCCESS) { + if (state->verbose) { + fprintf(stderr, "Failed retrieving serial number: %04x\n", sw); + } + res = YKPIV_GENERIC_ERROR; + goto Cleanup; + } + + recv_len = sizeof(temp); + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; + apdu.st.p1 = 0x04; + apdu.st.lc = (unsigned char)sizeof(aid); + memcpy(apdu.st.data, aid, sizeof(aid)); + + if((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) { + if(state->verbose) { + fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); + } + return res; + } + else if(sw != SW_SUCCESS) { + if(state->verbose) { + fprintf(stderr, "Failed selecting application: %04x\n", sw); + } + return YKPIV_GENERIC_ERROR; + } + } + else { + /* get serial from yk5 and later devices using the f8 command */ + + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_GET_SERIAL; + + if ((res = _send_data(state, &apdu, data, &recv_len, &sw) != YKPIV_OK)) { + if(state->verbose) { + fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); + } + return res; + } + else if(sw != SW_SUCCESS) { + if(state->verbose) { + fprintf(stderr, "Failed retrieving serial number: %04x\n", sw); + } + return YKPIV_GENERIC_ERROR; + } + } + + /* check that we received enough data for the serial number */ + if (recv_len < 4) { + return YKPIV_SIZE_ERROR; + } + + p_temp = (uint8_t*)(&state->serial); + + *p_temp++ = data[3]; + *p_temp++ = data[2]; + *p_temp++ = data[1]; + *p_temp++ = data[0]; + + if (p_serial) *p_serial = state->serial; + +Cleanup: + + return res; +} + +ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial) { + ykpiv_rc res = YKPIV_OK; + + if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) return YKPIV_PCSC_ERROR; + if ((res = _ykpiv_ensure_application_selected(state)) != YKPIV_OK) goto Cleanup; + + res = _ykpiv_get_serial(state, p_serial, false); + +Cleanup: + + _ykpiv_end_transaction(state); + return res; +} + static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len) { #if DISABLE_PIN_CACHE // Some embedded applications of this library may not want to keep the PIN @@ -1034,6 +1259,7 @@ return YKPIV_OK; } if (state->pin) { + yc_memzero(state->pin, strnlen(state->pin, CB_PIN_MAX)); _ykpiv_free(state, state->pin); state->pin = NULL; } @@ -1056,7 +1282,7 @@ int sw; ykpiv_rc res; - if (pin_len > 8) { + if (pin_len > CB_PIN_MAX) { return YKPIV_SIZE_ERROR; } @@ -1067,27 +1293,36 @@ apdu.st.lc = pin ? 0x08 : 0; if (pin) { memcpy(apdu.st.data, pin, pin_len); - if (pin_len < 8) { - memset(apdu.st.data + pin_len, 0xff, 8 - pin_len); + if (pin_len < CB_PIN_MAX) { + memset(apdu.st.data + pin_len, 0xff, CB_PIN_MAX - pin_len); } } - if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { + + res = _send_data(state, &apdu, data, &recv_len, &sw); + yc_memzero(&apdu, sizeof(apdu)); + + if (res != YKPIV_OK) { return res; - } else if (sw == SW_SUCCESS) { + } + else if (sw == SW_SUCCESS) { if (pin && pin_len) { // Intentionally ignore errors. If the PIN fails to save, it will only // be a problem if a reconnect is attempted. Failure deferred until then. _cache_pin(state, pin, pin_len); } + if (tries) *tries = (sw & 0xf); return YKPIV_OK; - } else if ((sw >> 8) == 0x63) { + } + else if ((sw >> 8) == 0x63) { if (tries) *tries = (sw & 0xf); return YKPIV_WRONG_PIN; - } else if (sw == SW_ERR_AUTH_BLOCKED) { + } + else if (sw == SW_ERR_AUTH_BLOCKED) { if (tries) *tries = 0; return YKPIV_WRONG_PIN; - } else { + } + else { return YKPIV_GENERIC_ERROR; } } @@ -1173,10 +1408,10 @@ unsigned char data[0xff]; unsigned long recv_len = sizeof(data); ykpiv_rc res; - if (current_pin_len > 8) { + if (current_pin_len > CB_PIN_MAX) { return YKPIV_SIZE_ERROR; } - if (new_pin_len > 8) { + if (new_pin_len > CB_PIN_MAX) { return YKPIV_SIZE_ERROR; } if(action == CHREF_ACT_UNBLOCK_PIN) { @@ -1186,14 +1421,17 @@ templ[3] = 0x81; } memcpy(indata, current_pin, current_pin_len); - if(current_pin_len < 8) { - memset(indata + current_pin_len, 0xff, 8 - current_pin_len); + if(current_pin_len < CB_PIN_MAX) { + memset(indata + current_pin_len, 0xff, CB_PIN_MAX - current_pin_len); } - memcpy(indata + 8, new_pin, new_pin_len); - if(new_pin_len < 8) { - memset(indata + 8 + new_pin_len, 0xff, 8 - new_pin_len); + memcpy(indata + CB_PIN_MAX, new_pin, new_pin_len); + if(new_pin_len < CB_PIN_MAX) { + memset(indata + CB_PIN_MAX + new_pin_len, 0xff, CB_PIN_MAX - new_pin_len); } + res = ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw); + yc_memzero(indata, sizeof(indata)); + if(res != YKPIV_OK) { return res; } else if(sw != SW_SUCCESS) { @@ -1289,14 +1527,20 @@ } if(sw == SW_SUCCESS) { - size_t outlen; - int offs = _ykpiv_get_length(data + 1, &outlen); + size_t outlen = 0; + unsigned int offs = 0; + + if ((*len < 2) || !_ykpiv_has_valid_length(data + 1, *len - 1)) { + return YKPIV_SIZE_ERROR; + } + + offs = _ykpiv_get_length(data + 1, &outlen); if(offs == 0) { return YKPIV_SIZE_ERROR; } if(outlen + offs + 1 != *len) { if(state->verbose) { - fprintf(stderr, "Invalid length indicated in object, total objlen is %lu, indicated length is %lu.", *len, outlen); + fprintf(stderr, "Invalid length indicated in object, total objlen is %lu, indicated length is %lu.", *len, (unsigned long)outlen); } return YKPIV_SIZE_ERROR; } @@ -1322,8 +1566,11 @@ return res; } -ykpiv_rc _ykpiv_save_object(ykpiv_state *state, int object_id, - unsigned char *indata, size_t len) { +ykpiv_rc _ykpiv_save_object( + ykpiv_state *state, + int object_id, + unsigned char *indata, + size_t len) { unsigned char data[CB_BUF_MAX]; unsigned char *dataptr = data; unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff}; @@ -1343,7 +1590,7 @@ memcpy(dataptr, indata, len); dataptr += len; - if((res = ykpiv_transfer_data(state, templ, data, (long)(dataptr - data), NULL, &outlen, + if((res = _ykpiv_transfer_data(state, templ, data, (long)(dataptr - data), NULL, &outlen, &sw)) != YKPIV_OK) { return res; } @@ -1436,10 +1683,13 @@ } else if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" if ((size_t)ec_data_len >= sizeof(key_data)) { - // This can never be true, but check to be explicit. + /* This can never be true, but check to be explicit. */ return YKPIV_SIZE_ERROR; } +#pragma GCC diagnostic pop if (algorithm == YKPIV_ALGO_ECCP256) elem_len = 32; @@ -1464,7 +1714,8 @@ padding = elem_len - lens[i]; remaining = (uintptr_t)key_data + sizeof(key_data) - (uintptr_t)in_ptr; if (padding > remaining) { - return YKPIV_ALGORITHM_ERROR; + res = YKPIV_ALGORITHM_ERROR; + goto Cleanup; } memset(in_ptr, 0, padding); in_ptr += padding; @@ -1499,6 +1750,7 @@ } Cleanup: + yc_memzero(key_data, sizeof(key_data)); _ykpiv_end_transaction(state); return res; } @@ -1617,15 +1869,50 @@ Cleanup: + yc_memzero(&apdu, sizeof(apdu)); _ykpiv_end_transaction(state); return res; } +static const uint8_t MGMT_AID[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 }; + +/* deauthenticates the user pin and mgm key */ ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state) { ykpiv_rc res = YKPIV_OK; + APDU apdu; + unsigned char data[0xff]; + uint32_t recv_len = sizeof(data); + int sw; + if (!state) { + return YKPIV_ARGUMENT_ERROR; + } + + /* this function does not use ykpiv_transfer_data because it selects a different app */ if ((res = _ykpiv_begin_transaction(state)) < YKPIV_OK) return res; - _ykpiv_util_get_serial(state, NULL, true); + + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; + apdu.st.p1 = 0x04; + apdu.st.lc = sizeof(MGMT_AID); + memcpy(apdu.st.data, MGMT_AID, sizeof(MGMT_AID)); + + if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { + if (state->verbose) { + fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res)); + } + goto Cleanup; + } + else if (sw != SW_SUCCESS) { + if (state->verbose) { + fprintf(stderr, "Failed selecting mgmt application: %04x\n", sw); + } + res = YKPIV_GENERIC_ERROR; + goto Cleanup; + } + +Cleanup: + _ykpiv_end_transaction(state); return res; } diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.h yubico-piv-tool-1.7.0/lib/ykpiv.h --- yubico-piv-tool-1.6.2/lib/ykpiv.h 2017-11-29 09:42:14.000000000 +0100 +++ yubico-piv-tool-1.7.0/lib/ykpiv.h 2018-10-25 15:27:06.000000000 +0200 @@ -194,6 +194,19 @@ */ ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select); + /** + * Get serial number + * + * The card must be connected to call this function. + * + * @param state [in] State handle + * @param p_serial [out] uint32 to store retrieved serial number + * + * @return ykpiv_rc error code + * + */ + ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t* p_serial); + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -492,7 +505,7 @@ * @param state state * @param ccc Unique Card ID to set. If NULL, randomly generate. * - * @return ypiv_rc error code + * @return ykpiv_rc error code * */ ykpiv_rc ykpiv_util_set_cccid(ykpiv_state *state, const ykpiv_cccid *ccc); @@ -647,6 +660,7 @@ #define YKPIV_INS_RESET 0xfb #define YKPIV_INS_SET_PIN_RETRIES 0xfa #define YKPIV_INS_ATTEST 0xf9 +#define YKPIV_INS_GET_SERIAL 0xf8 #define YKPIV_PINPOLICY_TAG 0xaa #define YKPIV_PINPOLICY_DEFAULT 0 @@ -671,12 +685,15 @@ #define YKPIV_ATR_NEO_R3 "\x3b\xfc\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x4e\x45\x4f\x72\x33\xe1" #define YKPIV_ATR_YK4 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x34\xd4" +#define YKPIV_ATR_YK5_P1 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x01\x59\x75\x62\x69\x4b\x65\x79\xc1" +#define YKPIV_ATR_YK5 "\x3b\xfd\x13\x00\x00\x81\x31\xfe\x15\x80\x73\xc0\x21\xc0\x57\x59\x75\x62\x69\x4b\x65\x79\x40" #define DEVTYPE_UNKNOWN 0x00000000 #define DEVTYPE_NEO 0x4E450000 //"NE" #define DEVTYPE_YK 0x594B0000 //"YK" #define DEVTYPE_NEOr3 (DEVTYPE_NEO | 0x00007233) //"r3" #define DEVTYPE_YK4 (DEVTYPE_YK | 0x00000034) // "4" +#define DEVYTPE_YK5 (DEVTYPE_YK | 0x00000035) // "5" #ifdef __cplusplus } diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.map yubico-piv-tool-1.7.0/lib/ykpiv.map --- yubico-piv-tool-1.6.2/lib/ykpiv.map 2017-11-29 09:42:14.000000000 +0100 +++ yubico-piv-tool-1.7.0/lib/ykpiv.map 2018-10-25 15:27:06.000000000 +0200 @@ -113,3 +113,9 @@ ykpiv_util_write_msroots; ykpiv_verify_select; } YKPIV_1.3.0; + +YKPIV_1.6.0 +{ +global: + ykpiv_get_serial; +} YKPIV_1.5.0; diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv-version.h yubico-piv-tool-1.7.0/lib/ykpiv-version.h --- yubico-piv-tool-1.6.2/lib/ykpiv-version.h 2018-09-14 09:33:13.000000000 +0200 +++ yubico-piv-tool-1.7.0/lib/ykpiv-version.h 2019-04-03 09:53:52.000000000 +0200 @@ -43,7 +43,7 @@ * version number. Used together with ykneomgr_check_version() to verify * header file and run-time library consistency. */ -#define YKPIV_VERSION_STRING "1.6.2" +#define YKPIV_VERSION_STRING "1.7.0" /** * YKPIV_VERSION_NUMBER @@ -53,7 +53,7 @@ * this symbol will have the value 0x01020300. The last two digits * are only used between public releases, and will otherwise be 00. */ -#define YKPIV_VERSION_NUMBER 0x010602 +#define YKPIV_VERSION_NUMBER 0x010700 /** * YKPIV_VERSION_MAJOR @@ -71,7 +71,7 @@ * level of the header file version number. For example, when the * header version is 1.2.3 this symbol will be 2. */ -#define YKPIV_VERSION_MINOR 6 +#define YKPIV_VERSION_MINOR 7 /** * YKPIV_VERSION_PATCH @@ -80,7 +80,7 @@ * level of the header file version number. For example, when the * header version is 1.2.3 this symbol will be 3. */ -#define YKPIV_VERSION_PATCH 2 +#define YKPIV_VERSION_PATCH 0 const char *ykpiv_check_version (const char *req_version); diff -Nru yubico-piv-tool-1.6.2/Makefile.in yubico-piv-tool-1.7.0/Makefile.in --- yubico-piv-tool-1.6.2/Makefile.in 2018-09-14 09:21:39.000000000 +0200 +++ yubico-piv-tool-1.7.0/Makefile.in 2019-04-03 09:53:50.000000000 +0200 @@ -197,7 +197,7 @@ $(top_srcdir)/build-aux/ltmain.sh \ $(top_srcdir)/build-aux/missing COPYING ChangeLog NEWS README \ build-aux/ar-lib build-aux/compile build-aux/config.guess \ - build-aux/config.rpath build-aux/config.sub \ + build-aux/config.rpath build-aux/config.sub build-aux/depcomp \ build-aux/install-sh build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) diff -Nru yubico-piv-tool-1.6.2/NEWS yubico-piv-tool-1.7.0/NEWS --- yubico-piv-tool-1.6.2/NEWS 2018-09-14 09:23:34.000000000 +0200 +++ yubico-piv-tool-1.7.0/NEWS 2019-04-03 09:53:25.000000000 +0200 @@ -1,5 +1,23 @@ yubico-piv-tool NEWS -- History of user-visible changes. -*- outline -*- +* Version 1.7.0 (released 2019-04-03) + +** Add ykpiv_get_serial() to API. + +** Add version and serial to status output. + +** FASC-N fixes for CHUID. + +** ykcs11: Fix ECDSA signatures. + +** Make selfsigned X.509 extensions have correct extensions to match openssl. + +** Security fixes. + +** Documentation fixes. + +** Try to clear memory that might contain secrets. + * Version 1.6.2 (released 2018-09-14) ** Compare reader names case insensitive. diff -Nru yubico-piv-tool-1.6.2/tool/yubico-piv-tool.1 yubico-piv-tool-1.7.0/tool/yubico-piv-tool.1 --- yubico-piv-tool-1.6.2/tool/yubico-piv-tool.1 2018-09-10 10:19:44.000000000 +0200 +++ yubico-piv-tool-1.7.0/tool/yubico-piv-tool.1 2019-04-03 09:53:55.000000000 +0200 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH YUBICO-PIV-TOOL "1" "September 2018" "yubico-piv-tool 1.6.2" "User Commands" +.TH YUBICO-PIV-TOOL "1" "April 2019" "yubico-piv-tool 1.7.0" "User Commands" .SH NAME yubico-piv-tool \- Yubico PIV tool .SH SYNOPSIS .B yubico-piv-tool [\fI\,OPTIONS\/\fR]... .SH DESCRIPTION -yubico\-piv\-tool 1.6.2 +yubico\-piv\-tool 1.7.0 .TP \fB\-h\fR, \fB\-\-help\fR Print help and exit diff -Nru yubico-piv-tool-1.6.2/tool/yubico-piv-tool.c yubico-piv-tool-1.7.0/tool/yubico-piv-tool.c --- yubico-piv-tool-1.6.2/tool/yubico-piv-tool.c 2018-09-10 10:19:42.000000000 +0200 +++ yubico-piv-tool-1.7.0/tool/yubico-piv-tool.c 2019-04-03 09:44:44.000000000 +0200 @@ -49,12 +49,12 @@ #include <openssl/pkcs12.h> #include <openssl/rand.h> #include <openssl/rsa.h> +#include <openssl/x509v3.h> #include "cmdline.h" #include "util.h" #define MAX(a,b) (a) > (b) ? (a) : (b) -#define MIN(a,b) (a) < (b) ? (a) : (b) #define CHUID 0 #define CCC 1 @@ -450,11 +450,11 @@ } rc = ykpiv_import_private_key(state, key, algorithm, - p, element_len, - q, element_len, - dmp1, element_len, - dmq1, element_len, - iqmp, element_len, + p, (size_t)element_len, + q, (size_t)element_len, + dmp1, (size_t)element_len, + dmq1, (size_t)element_len, + iqmp, (size_t)element_len, NULL, 0, pp, tp); } @@ -586,7 +586,7 @@ } else { i2d_X509(cert, &certptr); } - if ((res = ykpiv_util_write_cert(state, get_slot_hex(slot), certdata, cert_len, compress)) != YKPIV_OK) { + if ((res = ykpiv_util_write_cert(state, get_slot_hex(slot), certdata, (size_t)cert_len, compress)) != YKPIV_OK) { fprintf(stderr, "Failed commands with device: %s\n", ykpiv_strerror(res)); } else { ret = true; @@ -797,6 +797,16 @@ return ret; } +static const struct { + int nid; + const char *ext; + int critical; +} selfsign_extensions[] = { + {NID_subject_key_identifier, "hash", 0}, + {NID_authority_key_identifier, "keyid", 0}, + {NID_basic_constraints, "CA:true", 1}, +}; + static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_format, const char *input_file_name, enum enum_slot slot, char *subject, enum enum_hash hash, const int *serial, int validDays, const char *output_file_name) { @@ -921,6 +931,48 @@ if(nid == 0) { goto selfsign_out; } + + { + X509V3_CTX ctx; + int i; + X509V3_set_ctx(&ctx, x509, x509, NULL, NULL, 0); + + for(i = 0; i < sizeof(selfsign_extensions) / sizeof(selfsign_extensions[0]); i++) { + X509_EXTENSION *ext = NULL; + void *ext_struc; + const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(selfsign_extensions[i].nid); + + if(!method) { + fprintf(stderr, "Failed to get extension method for nid %d.\n", selfsign_extensions[i].nid); + goto selfsign_out; + } + if(method->v2i) { + STACK_OF(CONF_VALUE) *nval = X509V3_parse_list(selfsign_extensions[i].ext); + if(!nval) { + fprintf(stderr, "Failed parsing extension value for nid %d.\n", selfsign_extensions[i].nid); + goto selfsign_out; + } + ext_struc = method->v2i(method, &ctx, nval); + } else if(method->s2i) { + ext_struc = method->s2i(method, &ctx, selfsign_extensions[i].ext); + } else { + fprintf(stderr, "Unknown way to construct extension for nid %d.\n", selfsign_extensions[i].nid); + goto selfsign_out; + } + + if(!ext_struc) { + fprintf(stderr, "Failed constructing extension value for nid %d.\n", selfsign_extensions[i].nid); + goto selfsign_out; + } + + ext = X509V3_EXT_i2d(selfsign_extensions[i].nid, selfsign_extensions[i].critical, ext_struc); + if(!X509_add_ext(x509, ext, -1)) { + fprintf(stderr, "Failed adding extension %d (%d).\n", i, selfsign_extensions[i].nid); + goto selfsign_out; + } + } + } + #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) null_parameter.type = V_ASN1_NULL; null_parameter.value.ptr = NULL; @@ -1067,6 +1119,9 @@ op = ykpiv_change_puk; } res = op(state, pin, pin_len, new_pin, new_len, &tries); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (res) { case YKPIV_OK: return true; @@ -1088,6 +1143,7 @@ fprintf(stderr, "Failed changing/unblocking code, error: %s\n", ykpiv_strerror(res)); return false; } +#pragma GCC diagnostic pop } static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) { @@ -1258,7 +1314,7 @@ static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_MD *md, FILE *output) { - int object = ykpiv_util_slot_object(get_slot_hex(slot)); + int object = (int)ykpiv_util_slot_object(get_slot_hex(slot)); int slot_name; unsigned char data[3072]; const unsigned char *ptr = data; @@ -1376,7 +1432,9 @@ unsigned char buf[3072]; long unsigned len = sizeof(buf); int i; + uint32_t serial = 0; FILE *output_file = open_file(output_file_name, OUTPUT_TEXT); + if(!output_file) { return false; } @@ -1386,6 +1444,20 @@ return false; } + fprintf(output_file, "Version:\t"); + if (ykpiv_get_version(state, (char*)buf, (size_t)len) != YKPIV_OK) { + fprintf(output_file, "No data available\n"); + } else { + fprintf(output_file, "%s\n", (char*)buf); + } + + fprintf(output_file, "Serial Number:\t"); + if (ykpiv_get_serial(state, &serial) != YKPIV_OK) { + fprintf(output_file, "No data available\n"); + } else { + fprintf(output_file, "%d\n", serial); + } + fprintf(output_file, "CHUID:\t"); if(ykpiv_fetch_object(state, YKPIV_OBJ_CHUID, buf, &len) != YKPIV_OK) { fprintf(output_file, "No data available\n"); @@ -1714,7 +1786,7 @@ static bool attest(ykpiv_state *state, enum enum_slot slot, enum enum_key_format key_format, const char *output_file_name) { unsigned char data[2048]; - unsigned long len = sizeof(data); + size_t len = sizeof(data); bool ret = false; X509 *x509 = NULL; int key; @@ -1736,7 +1808,7 @@ if(key_format == key_format_arg_PEM) { const unsigned char *ptr = data; - int len2 = len; + int len2 = (int)len; x509 = X509_new(); if(!x509) { fprintf(stderr, "Failed allocating x509 structure.\n"); @@ -1787,7 +1859,7 @@ } if(verbosity) { - fprintf(stderr, "Writing %lu bytes of data to object %x.\n", len, id); + fprintf(stderr, "Writing %lu bytes of data to object %x.\n", (long unsigned int)len, id); } if((res = ykpiv_save_object(state, id, data, len)) != YKPIV_OK) { @@ -1858,6 +1930,7 @@ cmdline_parser_action_values[action]); return EXIT_FAILURE; } + /* fall through */ case action_arg_generate: case action_arg_importMINUS_key: case action_arg_importMINUS_certificate: @@ -1929,6 +2002,7 @@ } password = pwbuf; } + /* fall through */ case action_arg_generate: case action_arg_setMINUS_mgmMINUS_key: case action_arg_pinMINUS_retries: diff -Nru yubico-piv-tool-1.6.2/tools/fasc.pl yubico-piv-tool-1.7.0/tools/fasc.pl --- yubico-piv-tool-1.6.2/tools/fasc.pl 2017-02-03 16:17:05.000000000 +0100 +++ yubico-piv-tool-1.7.0/tools/fasc.pl 2019-01-02 08:50:49.000000000 +0100 @@ -31,7 +31,7 @@ # S9999F9999F999999F0F1F0000000000300001E # and outputs that in hex, encoded in the 5-bit form described in # "Technical Implementation Guidance: Smart Card Enabled Physical Access -# Control Systems" +# Control Systems Version 2.2", Section 6.2, Figure 7. use strict; use Bit::Vector; @@ -39,16 +39,16 @@ my %encoding = ( 0 => "00001", 1 => "10000", - 2 => "00100", - 3 => "00111", - 4 => "01000", - 5 => "01011", + 2 => "01000", + 3 => "11001", + 4 => "00100", + 5 => "10101", 6 => "01101", - 7 => "01110", - 8 => "10000", + 7 => "11100", + 8 => "00010", 9 => "10011", - S => "11010", # the examples and definitions of S and F differ - F => "10110", # but we'll go with the examples here.. + S => "11010", + F => "10110", E => "11111", ); diff -Nru yubico-piv-tool-1.6.2/windows.mk yubico-piv-tool-1.7.0/windows.mk --- yubico-piv-tool-1.6.2/windows.mk 2018-08-17 09:24:46.000000000 +0200 +++ yubico-piv-tool-1.7.0/windows.mk 2019-04-03 09:44:44.000000000 +0200 @@ -26,7 +26,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PACKAGE=yubico-piv-tool -OPENSSLVERSION=1.0.2p +OPENSSLVERSION=1.0.2q CHECKVERSION=0.12.0 all: usage 32bit 64bit @@ -72,6 +72,9 @@ rm -rf $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/ && \ cp COPYING $(PWD)/tmp$(ARCH)/root/licenses/$(PACKAGE).txt && \ cd .. && \ + cd check-$(CHECKVERSION) && \ + make uninstall && \ + cd .. && \ cd root && \ zip -r ../../$(PACKAGE)-$(VERSION)-win$(ARCH).zip * diff -Nru yubico-piv-tool-1.6.2/ykcs11/Makefile.am yubico-piv-tool-1.7.0/ykcs11/Makefile.am --- yubico-piv-tool-1.6.2/ykcs11/Makefile.am 2017-02-03 16:17:05.000000000 +0100 +++ yubico-piv-tool-1.7.0/ykcs11/Makefile.am 2018-10-25 15:27:06.000000000 +0200 @@ -30,6 +30,7 @@ AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS += -I$(top_srcdir)/tool -I$(top_builddir)/tool lib_LTLIBRARIES = libykcs11.la diff -Nru yubico-piv-tool-1.6.2/ykcs11/Makefile.in yubico-piv-tool-1.7.0/ykcs11/Makefile.in --- yubico-piv-tool-1.6.2/ykcs11/Makefile.in 2018-09-14 09:21:39.000000000 +0200 +++ yubico-piv-tool-1.7.0/ykcs11/Makefile.in 2019-04-03 09:53:50.000000000 +0200 @@ -453,7 +453,8 @@ SUBDIRS = . tests AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) $(am__append_3) AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) -I$(top_srcdir)/lib \ - -I$(top_builddir)/lib + -I$(top_builddir)/lib -I$(top_srcdir)/tool \ + -I$(top_builddir)/tool lib_LTLIBRARIES = libykcs11.la libykcs11_la_SOURCES = ykcs11.c ykcs11.pc.in ykcs11.map ykcs11.h \ debug.h vendors.c vendors.h vendor_ids.h slot_vendors.c \ diff -Nru yubico-piv-tool-1.6.2/ykcs11/objects.c yubico-piv-tool-1.7.0/ykcs11/objects.c --- yubico-piv-tool-1.6.2/ykcs11/objects.c 2018-05-22 13:30:29.000000000 +0200 +++ yubico-piv-tool-1.7.0/ykcs11/objects.c 2019-04-03 09:44:44.000000000 +0200 @@ -306,7 +306,7 @@ buf[(*n)++] = 0x80 | (CK_BYTE)l; } -static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) { +static CK_RV asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) { CK_CHAR_PTR tmp = (CK_BYTE_PTR) strdup((char *)oid); CK_CHAR_PTR p = tmp; CK_BYTE_PTR q = NULL; @@ -315,6 +315,10 @@ CK_ULONG l = 0; CK_ULONG nodes; + if (tmp == NULL) { + return CKR_HOST_MEMORY; + } + q = p; *len = 0; nodes = 1; @@ -360,6 +364,8 @@ } free(tmp); + + return CKR_OK; } static CK_KEY_TYPE get_key_type(EVP_PKEY *key) { @@ -395,6 +401,7 @@ CK_BYTE_PTR data; CK_BYTE tmp[64]; CK_ULONG len = 0; + CK_RV rv; DBG("For data object %lu, get ", obj); switch (template->type) { @@ -439,7 +446,9 @@ case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ? DBG("OID"); memcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid, sizeof(tmp)); - asn1_encode_oid(tmp, tmp, &len); + if ((rv = asn1_encode_oid(tmp, tmp, &len)) != CKR_OK) { + return rv; + } data = tmp; break; diff -Nru yubico-piv-tool-1.6.2/ykcs11/ykcs11.c yubico-piv-tool-1.7.0/ykcs11/ykcs11.c --- yubico-piv-tool-1.6.2/ykcs11/ykcs11.c 2017-11-29 09:42:14.000000000 +0100 +++ yubico-piv-tool-1.7.0/ykcs11/ykcs11.c 2019-04-03 09:44:44.000000000 +0200 @@ -1695,7 +1695,7 @@ CK_KEY_TYPE type = 0; CK_ULONG key_len = 0; CK_BYTE exp[3]; - CK_BYTE buf[1024]; + CK_BYTE buf[1024] = {0}; CK_ATTRIBUTE template[] = { {CKA_KEY_TYPE, &type, sizeof(type)}, {CKA_MODULUS_BITS, &key_len, sizeof(key_len)}, @@ -1863,12 +1863,6 @@ goto sign_out; } - if (op_info.type != YKCS11_SIGN) { - DBG("Operation not initialized"); - rv = CKR_OPERATION_NOT_INITIALIZED; - goto sign_out; - } - if (session.info.state == CKS_RO_PUBLIC_SESSION || session.info.state == CKS_RW_PUBLIC_SESSION) { DBG("User is not logged in"); @@ -1942,7 +1936,7 @@ *pulSignatureLen = sizeof(op_info.buf); - piv_rv = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id); + piv_rv = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, op_info.buf, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id); if (piv_rv != YKPIV_OK) { if (piv_rv == YKPIV_AUTHENTICATION_ERROR) { DBG("Operation requires authentication or touch"); @@ -1958,13 +1952,13 @@ DBG("Got %lu bytes back", *pulSignatureLen); #if YKCS11_DBG == 1 - dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex); + dump_data(op_info.buf, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex); #endif if (!is_RSA_mechanism(op_info.mechanism.mechanism)) { // ECDSA, we must remove the DER encoding and only return R,S // as required by the specs - strip_DER_encoding_from_ECSIG(pSignature, pulSignatureLen); + strip_DER_encoding_from_ECSIG(op_info.buf, pulSignatureLen); DBG("After removing DER encoding %lu", *pulSignatureLen); #if YKCS11_DBG == 1 @@ -1972,7 +1966,7 @@ #endif } - op_info.type = YKCS11_NOOP; + memcpy(pSignature, op_info.buf, *pulSignatureLen); rv = CKR_OK; diff -Nru yubico-piv-tool-1.6.2/ykcs11/ykcs11-version.h yubico-piv-tool-1.7.0/ykcs11/ykcs11-version.h --- yubico-piv-tool-1.6.2/ykcs11/ykcs11-version.h 2018-09-14 09:33:13.000000000 +0200 +++ yubico-piv-tool-1.7.0/ykcs11/ykcs11-version.h 2019-04-03 09:53:52.000000000 +0200 @@ -43,7 +43,7 @@ * version number. Used together with ykneomgr_check_version() to verify * header file and run-time library consistency. */ -#define YKCS11_VERSION_STRING "1.6.2" +#define YKCS11_VERSION_STRING "1.7.0" /** * YKCS11_VERSION_NUMBER @@ -53,7 +53,7 @@ * this symbol will have the value 0x01020300. The last two digits * are only used between public releases, and will otherwise be 00. */ -#define YKCS11_VERSION_NUMBER 0x010602 +#define YKCS11_VERSION_NUMBER 0x010700 /** * YKCS11_VERSION_MAJOR @@ -71,7 +71,7 @@ * level of the header file version number. For example, when the * header version is 1.2.3 this symbol will be 2. */ -#define YKCS11_VERSION_MINOR 6 +#define YKCS11_VERSION_MINOR 7 /** * YKCS11_VERSION_PATCH @@ -80,7 +80,7 @@ * level of the header file version number. For example, when the * header version is 1.2.3 this symbol will be 3. */ -#define YKCS11_VERSION_PATCH 2 +#define YKCS11_VERSION_PATCH 0 #ifdef __cplusplus }