[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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 @@
 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
-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
+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
-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
+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
-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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: