Your message dated Thu, 9 May 2019 10:54:05 +0200 with message-id <484c522e-e183-c4a1-38d7-c75a94315036@debian.org> and subject line Re: unblock: yubico-piv-tool/1.7.0-1 has caused the Debian Bug report #926555, regarding unblock: yubico-piv-tool/1.7.0-1 to be marked as done. This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact owner@bugs.debian.org immediately.) -- 926555: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=926555 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: unblock: yubico-piv-tool/1.7.0-1
- From: Nicolas Braud-Santoni <nicoo@debian.org>
- Date: Sat, 06 Apr 2019 22:59:16 +0200
- Message-id: <155458435652.22418.12201900583727287772.reportbug@neon.citronna.de>
Package: release.debian.org Severity: normal User: release.debian.org@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: enableddiff -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 <klas@yubico.com> + + * NEWS, configure.ac: NEWS for 1.7.0 + +2019-04-03 Klas Lindfors <klas@yubico.com> + + * : commit 7b64528cf7ba87e803a3ed29c8ca877e88796e24 Author: Dave + Pate <dpate@yubico.com> Date: Tue Jan 22 13:59:06 2019 -0800 + +2019-01-22 Dave Pate <dpate@yubico.com> + + * lib/internal.h, lib/ykpiv.c: lib: tlv length buffer checks + +2019-01-22 Dave Pate <dpate@yubico.com> + + * lib/util.c: lib: handle realloc failures safely + +2019-01-22 Dave Pate <dpate@yubico.com> + + * lib/util.c: lib: clear secrets in set_protected_mgm + +2019-01-22 Dave Pate <dpate@yubico.com> + + * lib/ykpiv.c: lib: clear secrets in ykpiv_import_private_key + +2019-01-21 Dave Pate <dpate@yubico.com> + + * lib/internal.h, lib/util.c: lib: correct zero memory defines, + correct overflow checks in _write_certificate + +2019-01-17 Dave Pate <dpate@yubico.com> + + * lib/ykpiv.c: lib: clear secrets in auth api + +2019-01-17 Dave Pate <dpate@yubico.com> + + * lib/ykpiv.c: lib: check that serial/version checks occur during + select + +2019-01-07 Dave Pate <dpate@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 <dpate@yubico.com> + + * lib/ykpiv.c: lib: check internal authentication crypt errors + +2019-01-07 Dave Pate <dpate@yubico.com> + + * lib/internal.c, lib/ykpiv.c: lib: clear buffers containing key + material + +2019-01-07 Dave Pate <dpate@yubico.com> + + * lib/internal.h, lib/util.c: lib: use secure zero memory platform + functions + +2019-01-07 Dave Pate <dpate@yubico.com> + + * lib/util.c, lib/ykpiv.c: lib: resolves potential reads of + uninitialized data + +2019-03-06 pedro martelletto <pedro@yubico.com> + + * doc/YubiKey_PIV_introduction.adoc: doc: set LC_CTYPE=C; fixes + ef81d164 on MacOS + +2019-03-06 Alessio Di Mauro <a-dma@users.noreply.github.com> + + * : Merge pull request #187 from Yubico/pvs_remove_warnings Remove some warnings + +2019-03-06 Gabriel Kihlman <g.kihlman@yubico.com> + + * ykcs11/ykcs11.c: Do not assign variable twice + +2019-03-06 Gabriel Kihlman <g.kihlman@yubico.com> + + * ykcs11/ykcs11.c: Remove duplicate check on op_info.type != + YKCS11_SIGN + +2019-03-05 Klas Lindfors <klas@yubico.com> + + * : commit ef81d1646536d5d9f2056cdc78a4a1052e8851a7 Author: pedro + martelletto <pedro@yubico.com> Date: Tue Mar 5 07:58:09 2019 +0100 + +2019-02-20 Alessio Di Mauro <alessio@yubico.com> + + * : Merge PR#184 + +2019-02-18 Klas Lindfors <klas@yubico.com> + + * windows.mk: bump openssl version and don't include check binaries + +2019-02-15 Alessio Di Mauro <alessio@yubico.com> + + * : Merge PR#183 + +2019-02-15 Alessio Di Mauro <alessio@yubico.com> + + * : Merge PR #182 + +2019-01-07 Alessio Di Mauro <alessio@yubico.com> + + * ykcs11/ykcs11.c: ykcs11: use a large enough buffer when writing EC + signatures + +2019-01-02 Klas Lindfors <klas@yubico.com> + + * : commit 811ddbb22d293aea6508d69bb7b98d8386fc8071 Author: Stacey + Sheldon <stac@solidgoldbomb.org> Date: Tue Jan 1 01:43:51 2019 + -0500 + +2019-01-01 Stacey Sheldon <stac@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 <klas@yubico.com> + + * tools/fasc.pl: fix fasc-n value of 1 relates #177 + +2018-09-21 Klas Lindfors <klas@yubico.com> + + * : commit 898b85821cbfa2c0b841e46d39a45b42e9891bfd Author: Klas + Lindfors <klas@yubico.com> Date: Tue Sep 18 08:38:57 2018 +0200 + +2018-09-14 Dave Pate <notdpate@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 <klas@yubico.com> + + * NEWS, configure.ac: bump version to 1.6.3 + 2018-09-14 Klas Lindfors <klas@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 <nicoo@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-maintainers@lists.alioth.debian.org> Uploaders: - Nicolas Braud-Santoni <nicolas@braud-santoni.eu>, + Nicolas Braud-Santoni <nicoo@debian.org>, Alessio Di Mauro <alessio@yubico.com>, - Simon Josefsson <simon@josefsson.org>, Klas Lindfors <klas@yubico.com>, Dain Nilsson <dain@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 @@ dSpsSIACixeiy2s20KgfF5TT0t3f092mGCZhTLAcGWDA3ZX+PGEg97cf87UKOFFm SUB+7pJM+ZzREJP0YoC56FSBHraJOROJFAFxABEBAAG0H0tsYXMgTGluZGZvcnMg PGtsYXNAeXViaWNvLmNvbT6JAT4EEwEIACgCGwMCHgECF4AGCwkIBwMCBRUKCQgL -BRYCAwEABQJaTh0+BQkI8kHsAAoJELygD9SyFowKc7QH/im7+bou5FTJRuHqQ+XA -yU6+HW+pFkOT/iTE6PbxEQWw8E1r1RiUqf8403GnW8x35m5pncCeRYFmbv6sCPT2 -/mywlQOrYZKGixQdxY1CSOfW+NSzfWI2TxCJhVC5e80MiFXOedxbi7H4B8gNG+pf -ieCF3TRS4UmaTJLOb5ScSO4sHS/80qzGNFzvsAVgx5q46QKWVnVN+UhwmznACu31 -Mo5njBXckzhfKr1VN+Kr9SA5KUtCjB1fB+YCTPHedq+UjeYzMfjQuuNX1xbme+a4 -ZN0daegtLH3CdoMjyO1+ozZjFi1apwYzpCoDzgjyqbZ4dYZp3yH/ZVDPEmPl8EZe -BJG5AQ0EUphDUgEIAOz+CplIAigQU4m+rvrbB/LoXz33WnsJxajQOU7T+bXyDlYm +BRYCAwEABQJbettMBQkJ6kP6AAoJELygD9SyFowK8dMH/1S2msgCyNHUHChsgemt +UoUuZASu0fuN/RPh4FLGgv/rrcb/8Z4gHqu/CVJdTa3cud4B9+Gafjm+IqfvW1lH +49nLZJtNeKYmrZr5vATCH6du3/Y6jtDWPJALquxvCdwU4r3sRSMcXk2PU4FR+WF1 +JJ+1KnlEzYymEJVqHh+butPU3lgCVVyObHub3WRB09mfmodPIDI/fpCJW2zvpJrY +dVYkI61NaZq2m9FWACxEuVV4NwEg+X67u1mZpL1CXsOwjI+HQPRFMrNWYgVKXbxJ +Yp5RHTgIJQbS6Syn2J/g6eLm+twDJ94lECxTKxfVxqej62hNM21IjBas8mCsNUBU +Zsm5AQ0EUphDUgEIAOz+CplIAigQU4m+rvrbB/LoXz33WnsJxajQOU7T+bXyDlYm Hh3MKtfwQoVTKC8ceB9ODfPXPoP9fumDU4cCQNHcNGnoznGgsLF+GyFuC6HrLRGx J3OGTNKgjLSZbUNSONgadMCjRZvn8tO285M5Gl3yfRhcGVqrMx2S95oLVKFNf1K/ DTy4+IPZYtiZBr5rCJe4ZeXd8bR7mO0vj9m9/vyTNpNhVr+gvp7ixHqaW14LzrG7 vR+arP4j+a82s827lHgE+geREUnKJha9dekX4/dSYDkBu0MGVT7KZ42dQhHYAe/f BHnA8fdux+oucp4z040dWmqxYl4TMPa6oknC/M0AEQEAAYkBJQQYAQgADwIbDAUC -Wk4dRwUJCPJB9QAKCRC8oA/UshaMCmJpB/9Ln/VuuhrFD3J4UdXYOEiUx59NVYe4 -e+5E+k0dsnIGwykS/PsdlghYvOx8Or+u4kwq/Ko6xy2bYMv3GymA6WYq+qIQ3hT3 -n0iBe/WeZ/+8IaMwfQl4eKPmFQd9LnV/hOhZnVnv8r57WT0umMjkr8MA++SDBNM7 -dlngcVrWk6/bkpyXaDv2PSK6h6t+ibePYnquxVMdDvcvjMGvGOpqe/5GM7Pwbtfi -wZH+6pw0Fv/634imiC4FGWeqHfnkJk+aIrjQ5kdPHb51qrxPTFm7U0Il3AYvYpKG -1H6IZQ+Cw1tyJ4lPbzp2T5LCATldYxcrQmXOPcm3fcwRE8L8LgiqAXxjuQENBFKY +W3rbVAUJCepEAgAKCRC8oA/UshaMCueuB/0WsGLAt0C7VqOeoH6esVRmni+Dt6aX +NNhNQXnl/ztc0Dm9eksiTYVv8ofn1RLNLwVkm5rcXMdB1EPrLX5757StC1TRWJJR +185oBY4BoEGiYwRA2yqS+VFcESEYFtPY2qSkOuwgQ3FQtTUufLW+gANFbP2LP6Ui +v5njZHrO2QnvDyke3rVwO3Hjv6ZtDHZBB/X42bv1oXCGVlyL1JJH/RYWJph+Y6v+ +uGJwebxlb4fqbarEtEqjpIaHO47GIOB+wNJ3BBUkHzvFx9C+Y+bEximOkAArcQFS +z48NNUGYV2cXOWv7+7MtTEcdwp4eF38ybtE7JsiLojvSbTwKfXHc1WAPuQENBFKY RIUBCADkkizoC8LI7peN87GszxKLxApuNHrY3nEXMbbC/25vkdC7V+Grhjk0gD/J bX+hUdZTxGmLHkX+mBfio+TigB2ViLnEmDrwThWOSxHvBCaV2NsT3k2ahvs6WM8D meiKrLbd8VZSHwLvKUxJuQQ7DeZjc/KJZ4WNLC1RqNi1g9q0WKeP1sB+LrwM2I95 Mat+x2xTHTDYVJEp9fK1PH1vvQ0x8me9eoT0eVCpE5eqDE4dYZKy3hCXZHv3j4v7 ZWf2YeMytmoDlg8yMShvibW5AvAINRPSkvP/gpN95foh4SusUhYs8hk/o+ntIf2e -Liood9fhZjNDPm2tmw/OOlUM6VzJABEBAAGJASUEGAEIAA8CGyAFAlpOHU8FCQjy -QMoACgkQvKAP1LIWjArAYAf/c/IZ9U4+rXFAhnIKCnBAX+ycDGdmvcgiXUmtg+Cb -AaQ6QnsTO6bDkSgKFmSjGCCEyvnHXbsaAua6pGkENG04hRSS43ABa+u1Df++iFWo -Fi19UYelmlAZ8dUK7xVYoW3+ub0jEMmrVnVRZJCWtlXrc6H2kEikft8Exxc+ZWa/ -ZR9QdS/+mn1K0RXJSkwEY3FjDzCcKcToY3hR8Z0jJfj35KgDM3gxxSBuBFStuxvZ -TSJz0mPFCkktJCr65Y5EUyOuiW/jb1Ua+Q2cZwImY2K5B4TAmsG+cNfI4AOkEayP -itsM882uDSE718uRSrQYV9hyInciLX8ZaRhmZ6619Gs1MZkCDQRWEt9xARAAr6T6 +Liood9fhZjNDPm2tmw/OOlUM6VzJABEBAAGJASUEGAEIAA8CGyAFAlt621wFCQnq +QtcACgkQvKAP1LIWjAr2Bgf/dO8Na0h0SKQfIy73IjlEoYovoxbIJ+8q7vJW6bMe +XNRHLucuxWGapskMxXbn+0kc8vDFiaYOLnIVk9IY2O/KBDrD+LAMAGIC9xn9l8y2 +XxUhkk9+SZ2CWQkav58FcbdB8rK3bQ58e4ai3hMRLRUbjtNpVvuFJxA+EtWsn34V +kRoIi/3+/Vhoqce9dKOipHcSoRIMrDMJgZo/fOeY9bpBdrTG1Wep05bLKSONNwIt +Mv8/xzjx6fkd1XgDBJKQ2BixVmPqROI5gCPPgSpShd4zQdZKWbZilc83gnZKBPxg +1Nd7By8QPPFil4HllQ9etfCRa/WTbRZELt8Nhu4QqwwJ95kCDQRWEt9xARAAr6T6 KIzzB3HbsI4VzGGyQDLgQVo+aiRkXVt92almDApiIKQjfn8i9Yj4uz2GgjObg3FZ f6mnwSxyJeDewEocmoaBgJYahWCQ1W1ZL0DV2eOMc+TiulfUjcBBouSASvcXGSze FK3gquu1AHYh4a8upWl/t23Asjwiq3DpWC26OGjNBUn8UUjLWlukzY0GBDV4wDe1 @@ -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 <klas@yubico.com> - 20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <dain@yubico.com> - B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <alessio@yubico.com> - FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <tom@yubico.com> - B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanpaul@yubico.com> - 8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <dag@yubico.com> - 57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <emil@yubico.com> - 268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <trevor@yubico.com> - EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pedro@yubico.com> + 0A3B0262BCA1705307D5FF06BCA00FD4B2168C0A # Klas Lindfors <klas@yubico.com> + 20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <dain@yubico.com> + B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <alessio@yubico.com> + FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <tom@yubico.com> + B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanpaul@yubico.com> + 8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <dag@yubico.com> + 57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <emil@yubico.com> + 268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <trevor@yubico.com> + EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pedro@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 }
--- End Message ---
--- Begin Message ---
- To: 926555-done@bugs.debian.org
- Cc: Debian bugs control server <control@bugs.debian.org>
- Subject: Re: unblock: yubico-piv-tool/1.7.0-1
- From: Paul Gevers <elbrus@debian.org>
- Date: Thu, 9 May 2019 10:54:05 +0200
- Message-id: <484c522e-e183-c4a1-38d7-c75a94315036@debian.org>
- In-reply-to: <[🔎] 2eb099f2-e73d-5b75-3838-fe6b8c65b028@debian.org>
- References: <155458435652.22418.12201900583727287772.reportbug@neon.citronna.de> <155458435652.22418.12201900583727287772.reportbug@neon.citronna.de> <[🔎] 2eb099f2-e73d-5b75-3838-fe6b8c65b028@debian.org> <[🔎] 2eb099f2-e73d-5b75-3838-fe6b8c65b028@debian.org>
tags -1 wontfix thanks On Thu, 2 May 2019 20:17:43 +0200 Paul Gevers <elbrus@debian.org> wrote: > Please be aware that without updates to that bug, your package will be > removed from buster soon. When that happens, your package will not be > allowed to migrate back in, so make sure you follow up, on that bug and > on this one. This happened, so closing this bug. PaulAttachment: signature.asc
Description: OpenPGP digital signature
--- End Message ---