Bug#926555: unblock: yubico-piv-tool/1.7.0-1
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: 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 <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
-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
+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
-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
+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
-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
+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
@@ -782,183 +782,129 @@
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
-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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
}
Reply to: