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

Bug#926555: marked as done (unblock: yubico-piv-tool/1.7.0-1)



Your message dated Thu, 9 May 2019 10:54:05 +0200
with message-id <484c522e-e183-c4a1-38d7-c75a94315036@debian.org>
and subject line Re: unblock: yubico-piv-tool/1.7.0-1
has caused the Debian Bug report #926555,
regarding unblock: yubico-piv-tool/1.7.0-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
926555: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=926555
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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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
+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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
+WqOom3uZAQ0EVAW4rQEIAKIkPXornlnakWPVhhpQZhdlEIhTfwJ2YoQjZQ+Cs5e5
+Dcidxv49SFYinJqjI6SUSCZHlM7mVhjAtYO4Ki/zNEYMrYMTlb/lmtXfjjb54Z/T
+cWqS0A7F9oSH1Ov2JRZx/S13va+pzYxzIgXCls2PRVbTCSQVE3nlu51HCpfqYgml
+KgZJfas9kLm9MXfQ3TVYaji1aL0nuRbfcoNq74KHz/evyHY3wcsfuDUGPdRKg2N+
+xoPxWHghFVQa2CdHVE/eI3u8Mxc33fHZkj4ifme8QkJUhbfKsRmy9/X2cdSDjl3Y
+liilw4Rb6LAQB7KHLZ3bAr8nE1Qfkj9KPHHSiayouCkAEQEAAbQhVG9tbWFzbyBE
+ZSBPcmNoaSA8dG9tQHl1Ymljby5jb20+iQE+BBMBAgAoBQJUBbitAhsDBQkDwmcA
+BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAc45JooJc5SLatB/4+t3/z6632
+NCAAnRAZvFLZgafUUGc8uR7/vm+75gAlBMWuN4xZSJoYW/yfxA3qDRoNUHCGqe2X
+pVvbosJUzYvrhgIwQl5zkW8vqVNJIFNpx/PI/BfjvVlFL3Ki4kiWnQjQT5bMx/s2
+NR1jWRPrBZGn1BqN4PmgPBKEUSwpebfCCrjZlpmPBIQYM1K22Mmoh8R5GNzAmCk8
+9NJdDKA1/16dOJfcLflWjM0VocVHrZjix4sWTmL5swlp105Nr0vUrYwDVhOm5Tsh
+1e4cTDORguM9p77zSU7bYmpkoQbMa60w8qGpwxvCjFr8duwYYgswq4Fz/LQ/IuJI
+RAlNFrg6Rep8mQENBFLP7UQBCACbOjmf0DRdtSjxFpTk+a5+Wa0syMbOc90IyRB9
+BXldK5FhMEStEuGw2uuXqzu45VRGslCl3h4Hyo2ogcyNT1dZQT9IcG/k/m15gZRR
+nyIiKftIqrTERvp3Kt5ykoVe1UuSh7jmc9W6YYBuaekOgCFdOZEdGQ6cdZ3+y4hy
+XDDnLikR+qFdAywxvw1V7+iN+mW72FnyMZ0ncPfjvn1czjQGZ2mH1fQ1e3hvganP
+KZ2296J9OsuvluQ2O31TSHpeH7xCIzDoctm7AiTo7xxsYzLQV8gG+aRwlg23uW1g
+4A0ef5cS3t7CoyNEjToB+ub2sODSAR4qvRwsTrYAOSTxCHzpABEBAAG0HkRhaW4g
+Tmlsc3NvbiA8ZGFpbkB5dWJpY28uY29tPokBPQQTAQgAJwIbAwYLCQgHAwIGFQgC
+CQoLAxYCAQIeAQIXgAUCWYhdFgUJCJmjUgAKCRDwQ2cJb7qV6Bn3B/4h5d3JqeE3
+vcoSxzN67K/rZ41jFT1mQZz7A5+QHb2lyhtwWC/IBC92A8oQyXt6Ces3NLXfVjJf
+svhLAoIAPmMoS+VEDo+sxOtcbsFaWDaf0wUrbmLXKVRcHT76xvYJg35gh9sa5WBR
+d0h2RUHB5VbjbG7nKkTkZ41HYLYOdfvbjVeb9Co0vF75V8n2FsOiz7Zek2rM1FKX
+PKY3oEaPJawNB8a7BufdCJLsL855N1+L8AwkBckGXihII1UMUFri2+V67M+qn4gC
+5j71tSZ4Hao1BjFPzPaW9du9Pyau2sp6DhpdhIFh4mF8BBe7pmDZkCZaYuD9/cdv
+sacw6gV8gwFT0TQzZW9wZW5wZ3BpZCt0b2tlbjpnZW5lcmljQGh0dHBzOi8vZGFp
+bi5zZS9wZ3BrZXkudHh0iQE2BBMBCAAgBAsJCAcCFQoCFgECGQACngECmwMFAlmI
+XRkFCQiZo1IACgkQ8ENnCW+6lejg7gf/fLTsqNyw+hq/VFcRODCiD1kUTMkE13VW
+NNJya5IWK0OgGFy+v8VHguZUooOMn81cqQBxnXSlNR5EDjUDqhC9heQnuRqCFie9
+uYnWLjcMXgc2MxzUbqTe3BJQo9Q59A2K60cVGNz0vPwA4r8eSm46ILprtMuM31tt
+L4rGMyE53zS132xsgTEWvJVnPm4tgBfRTFQhYbz93ztE8ozhzRH2BlNnPtZqT6j1
+P0FrvBORHrM0xRn0iQg6ecZoXnlZe6c8GAE/kKQ2fz9Dhqe2c6tWOFbwUzaBP4Ot
+J7pRAlpI8ATgLFDDjwJX3kvdfPQVfEd9ne5iA4U+9aVYJJElJn2rlNFLSmVvcGVu
+cGdwaWQrdG9rZW46QGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2RhaW5uaWxzc29u
+LzJlNTljM2IzNTUwOGM2NWY3NjBjiQE2BBMBCAAgBAsJCAcCFQoCFgECGQACngEC
+mwMFAlmIXRwFCQiZo1IACgkQ8ENnCW+6legb2Qf7BQRZxR7dMD58i6vwC2xNaPAb
+rsCzgrsYawaXvPnx1RgOcw890Z41P8Q5PAvbOuT8OCJ5H1PHr3xx6qkTf+wwq+fK
+NK+v6QQRSEk4qcWWseAQPCE7gmLqIZ29IWyh5BOLVpPRh/tknY2Be/j60v0feJeV
+UGLEdbsRu/8QTTOMiOjlVHhpYi274DXM/07EoXh4oG2nxd0jvhTWiihKPCkf+4J5
+1yjWPwbQuW79UQmyJJs4GglnFi/OVWapWFg1ELPAHHg0mLu0D+oZbUJgQUUykBQO
+5vUM66AzPn2ucc3CuOXnU5ZcEIX1/hRecHjn/J8ISm5VnrTOCZV7CZOT2SPwYJkC
+DQRal/UrARAA5wwRTrHKZDuNdDypal1j72DF0rbg+MuXbmqa9dJ9FVzHEe0FZVpL
+GscsuIdh+CzMzh+nMlUp1E2YcawJL1pfx3qL+QwgyZB2MGaQ++mLrBuxhf0Os+Te
+R+G9Beh0Z9/WaFNqvX50tFakgGYlbBrgrExEGz2wljZHPciVzIJe0kqwiIU19egf
+zkmBbOMlQgdSUVb50WjFvvMAJbC0osywV0g4dVRhfLlwmzXe//CoN2nmLwmedgiy
+3ORErPLFlUNwBDaBYbNqhyCKby2almV1foQorPJvNbRMWDOs1pMJ06LE0ck7LXQ9
+4OYQwu0Ar7UDtFnV4QO7IJ/+uxxvDKWrxuTzP5N5SkI22X+18xxPHavXj0+j8Coc
+HwqAUBddp3oa8WZTBd9Ts2vXR3gaGoX2adBquqwy5CygQ39MrgKK6cxvgdlnwNvi
+Gn7f72MXMKdN7KP39Ge/Z48yRqhw7n2sZKsSrS1G/BIuXPGW4dS+/iEu9oFTaYAj
+MsKK4IIVu7htIGhRmiHLsmJOGHDuGD8P+Lx46f7H9EoDj0yD3p/Pw9qcnLFa4lMA
+XWwuhOQz5bQ5x4rrEI24HpZieAZ/qYDIHh+rTCwrirQ8c1FeGNS+jYwUOzzGaQGk
+6uaqRL7YJplY0hjIS+QD/EpfqoeJvzFOBRviFGdZqTueRD2RUQiDqoMAEQEAAbQk
+cGVkcm8gbWFydGVsbGV0dG8gPHBlZHJvQHl1Ymljby5jb20+iQI9BBMBCAAnBQJa
+l/UrAhsDBQkB4TOABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJELQolJ73kUcY
+EsoQAJ87wPDNu2vZVlvmbdKEeTgJaFUM8G5osKISMw4m/upXHg6JoV/FoNJM+29J
+yQcLwuZQtuICrZOkgI7YZadJOSFyHdwAu6Y+WItGF1CwwfGALHWHRc8a/to4ycgA
+xqrU/oeh3hBj0pBO8IK+bhc9tcGHolmNdmpMawJTPYJwhmXzZfqRX1ukUUUGMzPT
+tIw3uFYFw//pMiqzuSc8/LAXuLgujtOoX6P8tPMYvjLzj9taIi1BsO6OGiZshUdr
+ABhQz5VXqvzswCrgTzgwMEv7k6IsLnt4Y7BQ69nHF+HtTeq4Jz6nTPwVBedV3Mns
+nV59qPo8W+C7hcsSYJb/qfefv0G8KMayGB7qrqgzvj/uVjoGxE/HVggBJoi3jiCZ
+qK/KlD61bJycBimiCF7D3Jf7cpHElqn5q9o1sgZVbxYHiG6FIF1FoIh9MslMVecb
+Cyv4s9YfKeyfD4DsEYOe+XhNalksfkywK1it39w1XJ39m5xOEirH12b1wuIm8T3J
+tmdoVvnHFsSddtu6f972dTFcXMxiaDtifLEt0DtbNBTPd7TMmr0RTv5vShDT3zax
+Ha8VqHq4UNcLdYqCk2TnYtBavEgIVVeQZicMWRGpM8kh1alKrHWGCvD3Cvt6xHsP
+lnauH63m8HSuzApMG27En8K4vAyWheDeTp+QJgh3jX407jF1uQENBFqX9e4BCADL
+R7fdX5vpoEAtNHd6w1YWDk3dpbQ8LLLoUJS8RqeYvOR3Um8QRThRMGliyGCy/7Bb
+IRHQ4JZqhDAki3HSw16ln3GF3ISpnOmLU5jrkRSeiGyj3dfjsmFLbNpZgxC5npS4
+Kmu5DaRV9j0AfPrN4sdc3wtV75wE9iaeIvEsJsGCgC3bCq9wy6bJ2eElLm/NWXQw
+7MJK6nGeUD9xySVKeuCAFLG5JRDd1jgbtUdORLm2j5PCwbNRYcKA8vOC8d1eHg10
+JCdDR74R04mj8BPSaukiMfZdeKqxJW4dzuVuVFlDXaF1KmKQnPFEEALuJSohR4lJ
+EG+bJHKBUY+Ac3uPZ+S5ABEBAAGJAiUEGAEIAA8FAlqX9e4CGyAFCQHhM4AACgkQ
+tCiUnveRRxhsZxAA4OBAZDhNpM/6c4N+IfGyGdcRLYziWFoAXik4EkS6HAt5LICm
+oqkocckeTJDhg1ZiOBzNuqDFvKp+1kCYBt96cJjU5RAolIyWt2XLknZQISChP4rU
+oE7hzKHkyxG1JcDgmsAX3m/lXecQFpQ5vq7kXYdP83Tkm+4FbZiw2g6ad0PFaGN0
+bw7kr0NA4cLrzIR/PzhwRX1xd3UY6RVJ6RfE29g7bF6ojYeoAsCAwFBa0GOtCwXZ
+Hzpm7dtp+WGFbBgAJzBIITYmQwLYO6sB848rbnJ92BtWEmg9BBztLEyRHavdv0yd
+obybgcFQFAuQ4ha9C4Bm34sZ8QMgDpsciVmojVoMmp80LMER0qnmpFhVVl3V5u7m
+DNybuvuHB5O61VQSZa5IxTFS90JM7jUI7SEoCHf/zS1lMPHyQ7CjhLXuOlnbbc0+
+BxL+AxSPBWzszyfKI0Qd/62y+pyvf9iMC/xmbAV8zCSrGfo74xEXKQBs38NVFgOy
+IT+urIld2l+JnkYEkhAK1zvQH3+9G5OxhnwQAGINFCdsobis0wnMKvsE7Hf/IjNS
+oar9utMW+Nt1BQE1/K52jLc7YeFY0U4ONY3/DyiC01gJg5QlgfBAPX0nOuE1Kgvp
+J7S3tGwUZLsMWZwTaIK0hNhveLgh6dK3EAc7QZOUf2B0pAUdjsdakbZfRcO5AQ0E
+Wpf2GwEIALQcBESYYjUrOI84EmqpItuZhqE/YmADuOop41d8OyJPb4yI5W4cOrMZ
+TcWmsHCxs8UaAfNuOgXtvgRcSP5yl5s5y6BoNsLJEukjXIFLacI7Qz0LshQWTwCp
+n58UEMYfqfjbAEEn8LYXOIxCTAu3W2PYji6gZnflRoT/WmxEzxBfDJknj3AAbF1P
+JOIG5fp5eWxcFwDVVmRJbF+MbwkYfHVCWoTD1LeCfS26CJTYRnc8d3IzQR7ZWhtu
+eWdQPyDPMnc/uT0H32cUHS/rc/Kq0vN9alj7QhDdbZ4a7EeoYTTDBjaDh5JsIXxD
+Xg28KZeYp7zVdtTQAwg+tuzfRmp2kYMAEQEAAYkCJQQYAQgADwUCWpf2GwIbDAUJ
+AeEzgAAKCRC0KJSe95FHGJVlEAC0PFVZL7h+1etstkbSi+l9YjLMNb2uhvXGCJgf
+qsiMx37TMB1a9fv5aKV0cIq+TiVwCM5chrSCRN++71pODMWocETDDIuGin+78Gbg
+f55Upp9k00D7UDSK5rNq5ykKXIAjRPuiF7MLKQr3FYc3bS2SGL/CVlkEjR8vsg1Q
+QIWEgJ+EVkKOg17P3t8/oIuHifYLVjz7FfvSlqU5PbMkei9EI9cYM1/42LqvrDjq
+XGqyV4EUyjcdonIkTvq62+OI6XNXa3cCiM1hahBZNKZN2gIwPoFMk0NsLDuQ4Ps9
+2h0JHbgsJdQEbNB0exiykf2qVLqFKX1gZTKU/NPKi5HoLL2FYoHhc33dLhXvkBeC
+LTVd0Z7w+3i9pKIM5HYIu6wm+sq1/jEB+BcU5l2iHVYJMppvr1opRLGfkvq9hvhQ
+bJ1/WU9lKcr4LEE/bV/Xj2yICqdj3AL7aMye+1k2iA7M6ykyb3Cy8ZAlYtedGZ+h
+3JaMbP23aft7CDaX1Ze4fv4WvEbLm4hMe+aYjM224HvEhTx8IzAM9NM9rlMviM/5
+hJTly3XeSzlAygJV6XqB1N4RXvUEKviuhpmq33wgUi43MxrN/UPGk2cNWkfPQ/aQ
+ItPKY9Dj3psewwNlUE0tyrb6o0kDlgBwTvh6LxbNZjZbhzxI3e9f+osRysNwXq3q
+B2K/F7kBDQRal/Y+AQgArRmjrFJGIa8SFdSopBvGK3HAuMP5iUeRY7fwDP/wAd85
+uigKZC6Yl7cMCvVK8nrqVSkqmVYrhN6P1If0aYjvfc9RLKpnzebhiJkLCJv8PxI5
+5RiSvmhiVW/rVFIG/EWll2UApFUkHKvPKQdHO6mN3WgoY7rkV5uBT6xskPIl2A+y
+YrLV9Sd4h3iJzUFC8voT9SKbAVJ/8rXnqo1SEQ/WtLLCo/uqzHBoq0n8BK6rN1w+
+XG4g/8iXKUO7/Pl6VsPbN+iyX8FuqsnMsg82HjlV0/DYRlx08NLuON0EFAitZKCM
+v4hvwT5wdylZY/lwnHmjeIyRfqwST9OkF8jRK/81HQARAQABiQNEBBgBCAAPBQJa
+l/Y+AhsCBQkB4TOAASkJELQolJ73kUcYwF0gBBkBCAAGBQJal/Y+AAoJEGM1qeUw
+sE0MHk8H/1jwQmo6nvSbCYJazcruOYGVVFMzoQNbOw9aczuQ6tuGxkWPB+XWvXyF
+Nj0QnBhgYqIpJbtYCH89FpbHGwXXAv5ACSjC3pD6nr92frJXMHMrWZjbYMzvyjis
+x+SZZIJQZO9JRdaLfdlkzxYldH/Ak6AAHEh7NMh1SOEa4msfd08Jl4pRPjurgoUN
+H9kk4vam3MM55lYdkH8XUEupAQWqqgC4wmGP9CgzQ9r3u/gOHaLtWsC4cwhlO+rw
+3EP70qDJ2B3K7VVRrfqvpKPXvoFeecrA5qGyCVWHYd4TsQEAPfQwyIrMyFGOnmpQ
+Atk2jS8hDrwKujSxEpzG51U+URL4GgXTRRAAt0iUhKocpZbIGWvnQA8bei6ib6py
+Kwp7zZrtekrEN5cGLCWizDPLJ6tHiItYPl4/3JIl6gD9Q/Bl8gHFZ7wRBmnvqa9o
+SK3htDA//ezTaFLbVb/40VgZ+jCmhnxG+BSquvr/PnXsjMZrOhi2R3t0MFiP7lFh
+lKgiw21YGqeryQuXE//S54bNEunG9EkSi1/8wKTqJYgnq2rNzn4ZonCld0kmJ7t0
+7V1+B0sUZGau2NrJbfgccmXyZpPQ5saXRYLd917FnT1xMY5QRjEKLLG0BR+j2Bdf
+6CTA4ZE5TnGNYwLFJyDeTJwsA8Vb4OYE8bSMZ8jTTxr53mgznOAyC3iWqlBmTrWx
+Pve8nKeWFAubuV6qDFi7dNX7e6k5CzV+jB0vutN0meH42Ci1tL9RiEwYwh9syWi6
+KTTrWVZsqM/+Ip05UUSO3W3N4sTTRMmMgIBkeeJaNN5HX8adbn0/SSn9610wRnLd
+cPFS3+p//jMtBEbid4WgN3MQy8xxWMnDmCuPPywO78LQLXZf0RtrSJrLajj0hlry
+fiBEoOzbL9MigJxxuBRdZTtVUMTC5sAc4r6edV3zvCNETpgL7MOe65Kjj0VtNWOT
+NMiMpgvHUhjPmNMQRQVCrB9rbKlRlR72ws0+zKX/fg7qUucpAYv0AXbPtMlUjWWr
+df3P4O4hfB3YkRQ=
+=D4Rg
 -----END PGP PUBLIC KEY BLOCK-----
diff -Nru yubico-piv-tool-1.6.2/debian/upstream/signing-key.sh yubico-piv-tool-1.7.0/debian/upstream/signing-key.sh
--- yubico-piv-tool-1.6.2/debian/upstream/signing-key.sh	2018-09-25 11:38:58.000000000 +0200
+++ yubico-piv-tool-1.7.0/debian/upstream/signing-key.sh	2019-04-06 20:21:30.000000000 +0200
@@ -2,16 +2,20 @@
 set -euo pipefail
 
 KEYS=(
-  0A3B0262BCA1705307D5FF06BCA00FD4B2168C0A # Klas Lindfors <klas@yubico.com>
-  20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <dain@yubico.com>
-  B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <alessio@yubico.com>
-  FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <tom@yubico.com>
-  B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanpaul@yubico.com>
-  8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <dag@yubico.com>
-  57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <emil@yubico.com>
-  268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <trevor@yubico.com>
-  EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pedro@yubico.com>
+	0A3B0262BCA1705307D5FF06BCA00FD4B2168C0A # Klas Lindfors <klas@yubico.com>
+	20EE325B86A81BCBD3E56798F04367096FBA95E8 # Dain Nilsson <dain@yubico.com>
+	B70D62AA6A31AD6B9E4F9F4BDC8888925D25CA7A # Alessio Di Mauro <alessio@yubico.com>
+	FF8AF719AE5828181B894D831CE39268A0973948 # Tommaso De Orchi <tom@yubico.com>
+	B6042E2BD1FDBC2BCA8588B2FF8D3B45B7B875A9 # Jean Paul Galea <jeanpaul@yubico.com>
+	8D0B4EBA9345254BCEC0E843514F078FF4AB24C3 # Dag Heyman <dag@yubico.com>
+	57A9DEED4C6D962A923BB691816F3ED99921835E # Emil Lundberg <emil@yubico.com>
+	268583B64786F50F807456DA8CED3A80D41C0DCB # Trevor Bentley <trevor@yubico.com>
+	EE90AE0D19774C8386628FAAB428949EF7914718 # Pedro Martelletto <pedro@yubico.com>
 )
 
-exec gpg --export --export-options export-minimal -a -o signing-key.asc --yes \
-    "${KEYS[@]}"
+if [ $# -gt 0 ]; then
+	exec gpg "$@" "${KEYS[@]}"
+else
+	exec gpg --export --export-options export-minimal -a --yes \
+		-o "$(dirname "$0")/signing-key.asc" "${KEYS[@]}"
+fi
diff -Nru yubico-piv-tool-1.6.2/debian/ykcs11.lintian-overrides yubico-piv-tool-1.7.0/debian/ykcs11.lintian-overrides
--- yubico-piv-tool-1.6.2/debian/ykcs11.lintian-overrides	1970-01-01 01:00:00.000000000 +0100
+++ yubico-piv-tool-1.7.0/debian/ykcs11.lintian-overrides	2019-04-06 20:21:30.000000000 +0200
@@ -0,0 +1,5 @@
+# Lintian overrides for quirks related to ykcs11 being a PKCS#11 provider
+#  (essentially a dlopen-able plugin)
+package-name-doesnt-match-sonames libykcs11-1
+non-dev-pkg-with-shlib-symlink usr/lib/x86_64-linux-gnu/libykcs11.so.* usr/lib/x86_64-linux-gnu/libykcs11.so
+no-symbols-control-file usr/lib/x86_64-linux-gnu/libykcs11.so.*
diff -Nru yubico-piv-tool-1.6.2/doc/YubiKey_PIV_introduction.adoc yubico-piv-tool-1.7.0/doc/YubiKey_PIV_introduction.adoc
--- yubico-piv-tool-1.6.2/doc/YubiKey_PIV_introduction.adoc	2017-10-17 10:17:18.000000000 +0200
+++ yubico-piv-tool-1.7.0/doc/YubiKey_PIV_introduction.adoc	2019-04-03 09:44:44.000000000 +0200
@@ -37,30 +37,30 @@
 software will ask for key/pin to be input. For the management key option (-k)
 this is achieved by leaving out the value but will specifying -k.
 
-  $ key=`dd if=/dev/random bs=1 count=24 2>/dev/null | hexdump -v -e '/1 "%02X"'`
-  $ echo $key
-  $ yubico-piv-tool -aset-mgm-key -n$key
+  $ key=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -d '[:lower:]' | tr -cd '[:xdigit:]' | fold -w48 | head -1)
+  $ echo ${key}
+  $ yubico-piv-tool -aset-mgm-key -n${key}
 
 The PIN and PUK should be changed as well.
 
-  $ pin=`dd if=/dev/random bs=1 count=6 2>/dev/null | hexdump -v -e '/1 "%u"'|cut -c1-6`
-  $ echo $pin
+  $ pin=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd '[:digit:]' | fold -w6 | head -1)
+  $ echo ${pin}
 
-  $ puk=`dd if=/dev/random bs=1 count=6 2>/dev/null | hexdump -v -e '/1 "%u"'|cut -c1-8`
-  $ echo $puk
+  $ puk=$(export LC_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd '[:digit:]' | fold -w8 | head -1)
+  $ echo ${puk}
 
-  $ yubico-piv-tool -achange-pin -P123456 -N$pin
-  $ yubico-piv-tool -achange-puk -P12345678 -N$puk
+  $ yubico-piv-tool -achange-pin -P123456 -N${pin}
+  $ yubico-piv-tool -achange-puk -P12345678 -N${puk}
 
 === Other useful commands
 To generate a new private key:
 
-  $ yubico-piv-tool -k$key -agenerate -s9c
+  $ yubico-piv-tool -k${key} -agenerate -s9c
 
 To reset PIN/PUK retry counter AND codes (default pin 123456 puk
 12345678):
 
-  $ yubico-piv-tool -k$key -averify -P$pin -apin-retries --pin-retries=3 --puk-retries=3
+  $ yubico-piv-tool -k${key} -averify -P${pin} -apin-retries --pin-retries=3 --puk-retries=3
 
 To reset the application (PIN/PUK need to be blocked hence trying a couple
 of times -- you need to modify this if you have changed the default
diff -Nru yubico-piv-tool-1.6.2/lib/internal.c yubico-piv-tool-1.7.0/lib/internal.c
--- yubico-piv-tool-1.6.2/lib/internal.c	2018-08-09 10:23:52.000000000 +0200
+++ yubico-piv-tool-1.7.0/lib/internal.c	2019-04-03 09:47:54.000000000 +0200
@@ -241,6 +241,7 @@
 EXIT:
 #ifdef _WINDOWS
   if (pbSessionBlob) {
+    yc_memzero(pbSessionBlob, cbSessionBlob);
     free(pbSessionBlob);
     pbSessionBlob = NULL;
   }
@@ -304,8 +305,11 @@
 
 #else
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
   /* openssl returns void */
   DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 1);
+#pragma GCC diagnostic pop
 
 #endif
 
@@ -336,8 +340,11 @@
 
 #else
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
   /* openssl returns void */
   DES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 0);
+#pragma GCC diagnostic pop
 
 #endif
 
@@ -347,6 +354,7 @@
 
 bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key) {
 #ifdef _WINDOWS
+  bool rv = false;
   /* defined weak keys, borrowed from openssl to be consistent across platforms */
   static const unsigned char weak_keys[][DES_LEN_DES] = {
     /* weak keys */
@@ -394,13 +402,20 @@
     if ((0 == memcmp(weak_keys[i], tmp, DES_LEN_DES)) ||
         (0 == memcmp(weak_keys[i], tmp + DES_LEN_DES, DES_LEN_DES)) ||
         (0 == memcmp(weak_keys[i], tmp + 2*DES_LEN_DES, DES_LEN_DES))) {
-      return true;
+      rv = true;
+      break;
     }
   }
 
-  return false;
+  yc_memzero(tmp, DES_LEN_3DES);
+  return rv;
 #else
+  (void)cb_key; /* unused */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
   return DES_is_weak_key((const_DES_cblock *)key);
+#pragma GCC diagnostic pop
 #endif
 }
 
@@ -431,7 +446,7 @@
   return rc;
 }
 
-pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key) {
+pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key) {
   pkcs5_rc rc = PKCS5_OK;
 
 #ifdef _WINDOWS
@@ -447,6 +462,8 @@
   */
 
   if (STATUS_SUCCESS == BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG)) {
+    /* suppress const qualifier warning b/c BCrypt doesn't take const input buffers */
+#pragma warning(suppress: 4090)
     if (STATUS_SUCCESS != BCryptDeriveKeyPBKDF2(hAlg, (PUCHAR)password, (ULONG)cb_password, (PUCHAR)salt, (ULONG)cb_salt, iterations, key, (ULONG)cb_key, 0)) {
       rc = PKCS5_GENERAL_ERROR;
     }
@@ -459,8 +476,11 @@
 
 #else
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
   /* for some reason openssl always returns 1 for PBKDF2 */
-  PKCS5_PBKDF2_HMAC_SHA1((const char*)password, cb_password, salt, cb_salt, iterations, cb_key, key);
+  PKCS5_PBKDF2_HMAC_SHA1((const char*)password, cb_password, salt, cb_salt, iterations, cb_key, (unsigned char*)key);
+#pragma GCC diagnostic pop
 
 #endif
 
@@ -491,7 +511,6 @@
 
 #ifdef _WIN32
   HKEY hKey = 0;
-  DWORD dwErr = 0;
   DWORD dwValue = 0;
   DWORD dwType = 0;
   DWORD cbValue = sizeof(dwValue);
diff -Nru yubico-piv-tool-1.6.2/lib/internal.h yubico-piv-tool-1.7.0/lib/internal.h
--- yubico-piv-tool-1.6.2/lib/internal.h	2018-05-08 09:52:22.000000000 +0200
+++ yubico-piv-tool-1.7.0/lib/internal.h	2019-04-03 09:47:54.000000000 +0200
@@ -126,6 +126,7 @@
 #define CB_OBJ_TAG_MIN      2                       // 1 byte tag + 1 byte len
 #define CB_OBJ_TAG_MAX      (CB_OBJ_TAG_MIN + 2)      // 1 byte tag + 3 bytes len
 
+#define CB_PIN_MAX          8
 #define member_size(type, member) sizeof(((type*)0)->member)
 
 typedef enum {
@@ -178,21 +179,21 @@
 typedef union u_APDU APDU;
 typedef struct des_key des_key;
 
-extern unsigned const char aid[];
-
 des_rc des_import_key(const int type, const unsigned char* keyraw, const size_t keyrawlen, des_key** key);
 des_rc des_destroy_key(des_key* key);
 des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen);
 des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen);
-pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key);
+pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key);
 bool   yk_des_is_weak_key(const unsigned char *key, const size_t cb_key);
 
 prng_rc _ykpiv_prng_generate(unsigned char *buffer, const size_t cb_req);
 ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state);
 ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state);
 ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state);
-int _ykpiv_set_length(unsigned char *buffer, size_t length);
-int _ykpiv_get_length(const unsigned char *buffer, size_t *len);
+ykpiv_rc _ykpiv_select_application(ykpiv_state *state);
+unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length);
+unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len);
+bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len);
 
 void* _ykpiv_alloc(ykpiv_state *state, size_t size);
 void* _ykpiv_realloc(ykpiv_state *state, void *address, size_t size);
@@ -200,8 +201,14 @@
 ykpiv_rc _ykpiv_save_object(ykpiv_state *state, int object_id, unsigned char *indata, size_t len);
 ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, unsigned char *data, unsigned long *len);
 ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu, unsigned char *data, uint32_t *recv_len, int *sw);
-ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version);
-ykpiv_rc _ykpiv_util_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force);
+ykpiv_rc _ykpiv_transfer_data(
+    ykpiv_state *state,
+    const unsigned char *templ,
+    const unsigned char *in_data,
+    long in_len,
+    unsigned char *out_data,
+    unsigned long *out_len,
+    int *sw);
 
 /* authentication functions not ready for public api */
 ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const size_t challenge_len);
@@ -231,6 +238,21 @@
 
 void yc_log_event(uint32_t id, yc_log_level_t level, const char *sz_format, ...);
 
+#ifdef _WIN32
+#include <windows.h>
+#define yc_memzero SecureZeroMemory
+#elif defined(BSD)
+#include <strings.h>
+#define yc_memzero explicit_bzero
+#elif defined(__linux__)
+#include <openssl/crypto.h>
+#define yc_memzero OPENSSL_cleanse
+#else
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#define yc_memzero(_p, _n) (void)memset_s(_p, (rsize_t)_n, 0, (rsize_t)_n)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff -Nru yubico-piv-tool-1.6.2/lib/util.c yubico-piv-tool-1.7.0/lib/util.c
--- yubico-piv-tool-1.6.2/lib/util.c	2018-08-09 10:23:52.000000000 +0200
+++ yubico-piv-tool-1.7.0/lib/util.c	2019-04-03 09:47:54.000000000 +0200
@@ -57,8 +57,8 @@
  */
 const uint8_t CHUID_TMPL[] = {
   0x30, 0x19, 0xd4, 0xe7, 0x39, 0xda, 0x73, 0x9c, 0xed, 0x39, 0xce, 0x73, 0x9d,
-  0x83, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0x38, 0x42, 0x10, 0xc3,
-  0xf5, 0x34, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x83, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0xc8, 0x42, 0x10, 0xc3,
+  0xeb, 0x34, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x08, 0x32, 0x30, 0x33, 0x30, 0x30,
   0x31, 0x30, 0x31, 0x3e, 0x00, 0xfe, 0x00,
 };
@@ -208,8 +208,9 @@
 }
 
 ykpiv_devmodel ykpiv_util_devicemodel(ykpiv_state *state) {
-  if (!state || state->context == SCARD_E_INVALID_HANDLE)
+  if (!state || !state->context || (state->context == (uintptr_t)-1)) {
     return DEVTYPE_UNKNOWN;
+  }
   return (state->isNEO ? DEVTYPE_NEOr3 : DEVTYPE_YK4);
 }
 
@@ -217,6 +218,7 @@
   ykpiv_rc res = YKPIV_OK;
   ykpiv_key *pKey = NULL;
   uint8_t *pData = NULL;
+  uint8_t *pTemp = NULL;
   size_t cbData = 0;
   size_t offset = 0;
   uint8_t buf[CB_BUF_MAX];
@@ -273,17 +275,21 @@
 
   for (i = 0; i < sizeof(SLOTS); i++) {
     cbBuf = sizeof(buf);
+    res = _read_certificate(state, SLOTS[i], buf, &cbBuf);
 
-    if (YKPIV_OK == (res = _read_certificate(state, SLOTS[i], buf, &cbBuf))) {
+    if ((res == YKPIV_OK) && (cbBuf > 0)) {
       // add current slot to result, grow result buffer if necessary
 
       cbRealloc = (sizeof(ykpiv_key) + cbBuf - 1) > (cbData - offset) ? MAX((sizeof(ykpiv_key) + cbBuf - 1) - (cbData - offset), CB_PAGE) : 0;
 
       if (0 != cbRealloc) {
-        if (NULL == (pData = _ykpiv_realloc(state, pData, cbData + cbRealloc))) {
+        if (!(pTemp = _ykpiv_realloc(state, pData, cbData + cbRealloc))) {
+          /* realloc failed, pData will be freed in cleanup */
           res = YKPIV_MEMORY_ERROR;
           goto Cleanup;
         }
+        pData = pTemp;
+        pTemp = NULL;
       }
 
       cbData += cbRealloc;
@@ -343,7 +349,15 @@
   *data_len = 0;
 
   if (YKPIV_OK == (res = _read_certificate(state, slot, buf, &cbBuf))) {
-    if (NULL == (*data = _ykpiv_alloc(state, cbBuf))) {
+
+    /* handle those who write empty certificate blobs to PIV objects */
+    if (cbBuf == 0) {
+      *data = NULL;
+      *data_len = 0;
+      goto Cleanup;
+    }
+
+    if (!(*data = _ykpiv_alloc(state, cbBuf))) {
       res = YKPIV_MEMORY_ERROR;
       goto Cleanup;
     }
@@ -415,7 +429,7 @@
         memcpy(&flags, p_item, cb_item);
       }
       else {
-        if (state->verbose) { fprintf(stderr, "admin flags exist, but are incorrect size = %zu", cb_item); }
+        if (state->verbose) { fprintf(stderr, "admin flags exist, but are incorrect size = %lu", (unsigned long)cb_item); }
       }
     }
   }
@@ -454,17 +468,17 @@
   if (YKPIV_OK == (res = _ykpiv_fetch_object(state, YKPIV_OBJ_MSCMAP, buf, (unsigned long*)&cbBuf))) {
     ptr = buf;
 
-    // check that object contents are at least large enough to read the header
+    /* check that object contents are at least large enough to read the header */
     if (cbBuf < CB_OBJ_TAG_MIN) {
       res = YKPIV_OK;
       goto Cleanup;
     }
 
     if (*ptr++ == TAG_MSCMAP) {
-      ptr += _ykpiv_get_length(ptr, &len);
+      ptr += (unsigned long)_ykpiv_get_length(ptr, &len);
 
-      // check that decoded length represents object contents
-      if (len > (cbBuf - (ptr - buf))) {
+      /* check that decoded length represents object contents */
+      if (len > (cbBuf - (size_t)(ptr - buf))) {
         res = YKPIV_OK;
         goto Cleanup;
       }
@@ -474,7 +488,7 @@
         goto Cleanup;
       }
 
-      // should check if container map isn't corrupt
+      /* should check if container map isn't corrupt */
 
       memcpy(*containers, ptr, len);
       *n_containers = len / sizeof(ykpiv_container);
@@ -516,7 +530,7 @@
   // encode object data for storage
 
   // calculate the required length of the encoded object
-  req_len = 1 /* data tag */ + _ykpiv_set_length(buf, data_len) + data_len;
+  req_len = 1 /* data tag */ + (unsigned long)_ykpiv_set_length(buf, data_len) + data_len;
 
   if (req_len > _obj_size_max(state)) {
     res = YKPIV_SIZE_ERROR;
@@ -546,6 +560,7 @@
   int object_id = 0;
   uint8_t tag = 0;
   uint8_t *pData = NULL;
+  uint8_t *pTemp = NULL;
   size_t cbData = 0;
   size_t cbRealloc = 0;
   size_t offset = 0;
@@ -588,7 +603,7 @@
     ptr += _ykpiv_get_length(ptr, &len);
 
     // check that decoded length represents object contents
-    if (len > (cbBuf - (ptr - buf))) {
+    if (len > (cbBuf - (size_t)(ptr - buf))) {
       res = YKPIV_OK;
       goto Cleanup;
     }
@@ -596,10 +611,13 @@
     cbRealloc = len > (cbData - offset) ? len - (cbData - offset) : 0;
 
     if (0 != cbRealloc) {
-      if (NULL == (pData = _ykpiv_realloc(state, pData, cbData + cbRealloc))) {
+      if (!(pTemp = _ykpiv_realloc(state, pData, cbData + cbRealloc))) {
+        /* realloc failed, pData will be freed in cleanup */
         res = YKPIV_MEMORY_ERROR;
         goto Cleanup;
       }
+      pData = pTemp;
+      pTemp = NULL;
     }
 
     cbData += cbRealloc;
@@ -671,14 +689,14 @@
     offset = 0;
     data_chunk = MIN(cb_obj_max - CB_OBJ_TAG_MAX, data_len - data_offset);
 
-    // encode object data for storage
+    /* encode object data for storage */
     buf[offset++] = (i == (n_objs - 1)) ? TAG_MSROOTS_END : TAG_MSROOTS_MID;
     offset += _ykpiv_set_length(buf + offset, data_chunk);
     memcpy(buf + offset, data + data_offset, data_chunk);
     offset += data_chunk;
 
-    // write onto device
-    res = _ykpiv_save_object(state, YKPIV_OBJ_MSROOTS1 + i, buf, offset);
+    /* write onto device */
+    res = _ykpiv_save_object(state, (int)(YKPIV_OBJ_MSROOTS1 + i), buf, offset);
 
     if (YKPIV_OK != res) {
       goto Cleanup;
@@ -811,7 +829,7 @@
     *in_ptr++ = touch_policy;
   }
 
-  if (YKPIV_OK != (res = ykpiv_transfer_data(state, templ, in_data, (long)(in_ptr - in_data), data, &recv_len, &sw))) {
+  if (YKPIV_OK != (res = _ykpiv_transfer_data(state, templ, in_data, (long)(in_ptr - in_data), data, &recv_len, &sw))) {
     if (state->verbose) { fprintf(stderr, "Failed to communicate.\n"); }
     goto Cleanup;
   }
@@ -1084,7 +1102,7 @@
   if (YKPIV_OK == (res = _read_metadata(state, TAG_ADMIN, data, &cb_data))) {
     if (YKPIV_OK == (res = _get_metadata_item(data, cb_data, TAG_ADMIN_SALT, &p_item, &cb_item))) {
       if (cb_item != CB_ADMIN_SALT) {
-        if (state->verbose) fprintf(stderr, "derived mgm salt exists, but is incorrect size = %zu\n", cb_item);
+        if (state->verbose) fprintf(stderr, "derived mgm salt exists, but is incorrect size = %lu\n", (unsigned long)cb_item);
         res = YKPIV_GENERIC_ERROR;
         goto Cleanup;
       }
@@ -1127,7 +1145,7 @@
   }
 
   if (cb_item != member_size(ykpiv_mgm, data)) {
-    if (state->verbose) fprintf(stderr, "protected data contains mgm, but is the wrong size = %zu\n", cb_item);
+    if (state->verbose) fprintf(stderr, "protected data contains mgm, but is the wrong size = %lu\n", (unsigned long)cb_item);
     res = YKPIV_AUTHENTICATION_ERROR;
     goto Cleanup;
   }
@@ -1136,7 +1154,7 @@
 
 Cleanup:
 
-  memset(data, 0, sizeof(data));
+  yc_memzero(data, sizeof(data));
 
   _ykpiv_end_transaction(state);
   return res;
@@ -1174,7 +1192,7 @@
     }
   }
 
-  if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR;
+  if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) { res = YKPIV_PCSC_ERROR; goto Cleanup; }
   if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
 
   /* try to set the mgm key as long as we don't encounter a fatal error */
@@ -1245,7 +1263,7 @@
       memcpy(&flags_1, p_item, cb_item);
     }
     else {
-      if (state->verbose) fprintf(stderr, "admin data flags are an incorrect size = %zu\n", cb_item);
+      if (state->verbose) fprintf(stderr, "admin data flags are an incorrect size = %lu\n", (unsigned long)cb_item);
     }
 
     /* remove any existing salt */
@@ -1269,8 +1287,8 @@
 
 Cleanup:
 
-  memset(data, 0, sizeof(data));
-  memset(mgm_key, 0, sizeof(mgm_key));
+  yc_memzero(data, sizeof(data));
+  yc_memzero(mgm_key, sizeof(mgm_key));
 
   _ykpiv_end_transaction(state);
   return res;
@@ -1303,7 +1321,7 @@
     object_id = YKPIV_OBJ_SIGNATURE;
     break;
 
-  case  YKPIV_KEY_KEYMGM:
+  case YKPIV_KEY_KEYMGM:
     object_id = YKPIV_OBJ_KEY_MANAGEMENT;
     break;
 
@@ -1322,88 +1340,13 @@
     break;
   }
 
-  return object_id;
-}
-
-/* caller must make sure that this is wrapped in a transaction for synchronized operation */
-ykpiv_rc _ykpiv_util_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force) {
-  ykpiv_rc res = YKPIV_OK;
-  APDU apdu;
-  const uint8_t yk_applet[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 };
-  unsigned char data[0xff];
-  uint32_t recv_len = sizeof(data);
-  int sw;
-  uint8_t *p_temp = NULL;
-
-  if (!state) {
-    return YKPIV_ARGUMENT_ERROR;
-  }
-
-  if (!f_force && (state->serial != 0)) {
-    if (p_serial) *p_serial = state->serial;
-    return YKPIV_OK;
-  }
-
-  /* this function does not use ykpiv_transfer_data because it requires two apdus and selects a different app */
-
-  memset(apdu.raw, 0, sizeof(apdu));
-  apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
-  apdu.st.p1 = 0x04;
-  apdu.st.lc = sizeof(yk_applet);
-  memcpy(apdu.st.data, yk_applet, sizeof(yk_applet));
-
-  if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
-    if (state->verbose) {
-      fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
-    }
-    goto Cleanup;
-  }
-  else if (sw != SW_SUCCESS) {
-    if (state->verbose) {
-      fprintf(stderr, "Failed selecting yk application: %04x\n", sw);
-    }
-    res = YKPIV_GENERIC_ERROR;
-    goto Cleanup;
-  }
-
-  recv_len = sizeof(data);
-  memset(apdu.raw, 0, sizeof(apdu));
-  apdu.st.ins = 0x01;
-  apdu.st.p1 = 0x10;
-  apdu.st.lc = 0x00;
-
-  if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
-    if (state->verbose) {
-      fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
-    }
-    goto Cleanup;
-  }
-  else if (sw != SW_SUCCESS) {
-    if (state->verbose) {
-      fprintf(stderr, "Failed retrieving serial number: %04x\n", sw);
-    }
-    res = YKPIV_GENERIC_ERROR;
-    goto Cleanup;
-  }
-
-  p_temp = (uint8_t*)(&state->serial);
-
-  *p_temp++ = data[3];
-  *p_temp++ = data[2];
-  *p_temp++ = data[1];
-  *p_temp++ = data[0];
-
-  if (p_serial) *p_serial = state->serial;
-
-Cleanup:
-
-  return res;
+  return (uint32_t)object_id;
 }
 
 static ykpiv_rc _read_certificate(ykpiv_state *state, uint8_t slot, uint8_t *buf, size_t *buf_len) {
   ykpiv_rc res = YKPIV_OK;
   uint8_t *ptr = NULL;
-  int object_id = ykpiv_util_slot_object(slot);
+  int object_id = (int)ykpiv_util_slot_object(slot);
   size_t len = 0;
 
   if (-1 == object_id) return YKPIV_INVALID_OBJECT;
@@ -1423,7 +1366,7 @@
       ptr += _ykpiv_get_length(ptr, &len);
 
       // check that decoded length represents object contents
-      if (len > (*buf_len - (ptr - buf))) {
+      if (len > (*buf_len - (size_t)(ptr - buf))) {
         *buf_len = 0;
         return YKPIV_OK;
       }
@@ -1441,7 +1384,7 @@
 
 static ykpiv_rc _write_certificate(ykpiv_state *state, uint8_t slot, uint8_t *data, size_t data_len, uint8_t certinfo) {
   uint8_t buf[CB_OBJ_MAX];
-  int object_id = ykpiv_util_slot_object(slot);
+  int object_id = (int)ykpiv_util_slot_object(slot);
   size_t offset = 0;
   size_t req_len = 0;
 
@@ -1464,8 +1407,10 @@
   // calculate the required length of the encoded object
   req_len = 1 /* cert tag */ + 3 /* compression tag + data*/ + 2 /* lrc */;
   req_len += _ykpiv_set_length(buf, data_len);
+  req_len += data_len;
 
-  if (req_len > _obj_size_max(state)) return YKPIV_SIZE_ERROR;
+  if (req_len < data_len) return YKPIV_SIZE_ERROR; /* detect overflow of unsigned size_t */
+  if (req_len > _obj_size_max(state)) return YKPIV_SIZE_ERROR; /* obj_size_max includes limits for TLV encoding */
 
   buf[offset++] = TAG_CERT;
   offset += _ykpiv_set_length(buf + offset, data_len);
@@ -1512,6 +1457,11 @@
 
   while (p_temp < (data + cb_data)) {
     tag_temp = *p_temp++;
+
+    if (!_ykpiv_has_valid_length(p_temp, (data + cb_data - p_temp))) {
+      return YKPIV_SIZE_ERROR;
+    }
+
     p_temp += _ykpiv_get_length(p_temp, &cb_temp);
 
     if (tag_temp == tag) {
@@ -1579,16 +1529,24 @@
 
       /* length doesn't match, expand/shrink to fit */
       p_next = p_temp + cb_temp;
-      cb_moved = (long)cb_item - (long)cb_temp + ((long)(cb_item != 0 ? _get_length_size(cb_item) : -1 /* for tag, if deleting */) - (long)cb_len); /* accounts for different length encoding */
+      cb_moved = (long)cb_item - (long)cb_temp +
+        ((long)(cb_item != 0 ? _get_length_size(cb_item) : -1 /* for tag, if deleting */) -
+        (long)cb_len); /* accounts for different length encoding */
 
       /* length would cause buffer overflow, return error */
-      if (*pcb_data + cb_moved > cb_data_max) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+      if ((size_t)(*pcb_data + cb_moved) > cb_data_max) {
         return YKPIV_GENERIC_ERROR;
       }
+#pragma GCC diagnostic pop
 
       /* move remaining data */
-      memmove(p_next + cb_moved, p_next, *pcb_data - (p_next - data));
+      memmove(p_next + cb_moved, p_next, *pcb_data - (size_t)(p_next - data));
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
       *pcb_data += cb_moved;
+#pragma GCC diagnostic pop
 
       /* re-encode item and insert */
       if (cb_item != 0) {
@@ -1598,7 +1556,7 @@
       }
 
       return YKPIV_OK;
-    } //if tag found
+    } /* if tag found */
 
     p_temp += cb_temp;
   }
@@ -1610,7 +1568,7 @@
 
   // we did not find an existing tag, append
   p_temp = data + *pcb_data;
-  cb_len = _get_length_size(cb_item);
+  cb_len = (size_t)_get_length_size(cb_item);
 
   // length would cause buffer overflow, return error
   if (*pcb_data + cb_len + cb_item > cb_data_max) {
@@ -1666,7 +1624,7 @@
 
   p_temp += _ykpiv_get_length(p_temp, pcb_data);
 
-  if (*pcb_data > ((size_t)cb_temp - (p_temp - data))) {
+  if (*pcb_data > (cb_temp - (size_t)(p_temp - data))) {
     *pcb_data = 0;
     return YKPIV_GENERIC_ERROR;
   }
@@ -1712,7 +1670,7 @@
     memcpy(pTemp, data, cb_data);
     pTemp += cb_data;
 
-    res = _ykpiv_save_object(state, obj_id, buf, pTemp - buf);
+    res = _ykpiv_save_object(state, obj_id, buf, (size_t)(pTemp - buf));
   }
 
   return res;
diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.c yubico-piv-tool-1.7.0/lib/ykpiv.c
--- yubico-piv-tool-1.6.2/lib/ykpiv.c	2018-09-07 14:18:43.000000000 +0200
+++ yubico-piv-tool-1.7.0/lib/ykpiv.c	2019-04-03 09:47:54.000000000 +0200
@@ -76,11 +76,36 @@
 #define ENABLE_APPLICATION_RESELECTION 0
 #endif
 
+
+/**
+ * ENABLE_IMPLICIT_TRANSACTIONS - call SCardBeginTransaction for all public API calls
+ *
+ * If this is enabled, every public call (prefixed with \r ykpiv_) will call
+ * SCardBeginTransaction on entry and SCardEndTransaction on exit.
+ *
+ * For applications that do not do their own transaction management, like the piv tool
+ * itself, retaining the default setting of enabled can allow other applications and
+ * threads to make calls to CCID that can interfere with multi-block data sent to the
+ * card via SCardTransmitData.
+ */
+#ifndef ENABLE_IMPLICIT_TRANSACTIONS
+#define ENABLE_IMPLICIT_TRANSACTIONS 1
+#endif
+
+/**
+ * Platform specific definitions
+ */
+#ifdef _MSC_VER
+#define strncasecmp _strnicmp
+#endif
+
 #define YKPIV_MGM_DEFAULT "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
 
 static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len);
+static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool force);
+static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version);
 
-unsigned const char aid[] = {
+static unsigned const char aid[] = {
 	0xa0, 0x00, 0x00, 0x03, 0x08
 };
 
@@ -130,7 +155,7 @@
   }
 }
 
-int _ykpiv_set_length(unsigned char *buffer, size_t length) {
+unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length) {
   if(length < 0x80) {
     *buffer++ = (unsigned char)length;
     return 1;
@@ -146,7 +171,7 @@
   }
 }
 
-int _ykpiv_get_length(const unsigned char *buffer, size_t *len) {
+unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len) {
   if(buffer[0] < 0x81) {
     *len = buffer[0];
     return 1;
@@ -161,6 +186,19 @@
   return 0;
 }
 
+bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len) {
+  if ((buffer[0] < 0x81) && (len > 0)) {
+    return true;
+  }
+  else if (((*buffer & 0x7f) == 1) && (len > 1)) {
+    return true;
+  }
+  else if (((*buffer & 0x7f) == 2) && (len > 2)) {
+    return true;
+  }
+  return false;
+}
+
 static unsigned char *set_object(int object_id, unsigned char *buffer) {
   *buffer++ = 0x5c;
   if(object_id == YKPIV_OBJ_DISCOVERY) {
@@ -193,7 +231,7 @@
   s->pin = NULL;
   s->allocator = *allocator;
   s->verbose = verbose;
-  s->context = SCARD_E_INVALID_HANDLE;
+  s->context = (SCARDCONTEXT)-1;
   *state = s;
   return YKPIV_OK;
 }
@@ -226,7 +264,7 @@
 
   if(SCardIsValidContext(state->context) == SCARD_S_SUCCESS) {
     SCardReleaseContext(state->context);
-    state->context = SCARD_E_INVALID_HANDLE;
+    state->context = (SCARDCONTEXT)-1;
   }
 
   return YKPIV_OK;
@@ -239,8 +277,6 @@
   int sw;
   ykpiv_rc res = YKPIV_OK;
 
-  _ykpiv_util_get_serial(state, NULL, false);
-
   memset(apdu.raw, 0, sizeof(apdu));
   apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
   apdu.st.p1 = 0x04;
@@ -260,7 +296,16 @@
     return YKPIV_GENERIC_ERROR;
   }
 
-  _ykpiv_get_version(state, NULL);
+  /* now that the PIV application is selected, retrieve the version
+   * and serial number.  Previously the NEO/YK4 required switching
+   * to the yk applet to retrieve the serial, YK5 implements this
+   * as a PIV applet command.  Unfortunately, this change requires
+   * that we retrieve the version number first, so that get_serial
+   * can determine how to get the serial number, which for the NEO/Yk4
+   * will result in another selection of the PIV applet. */
+
+  res = _ykpiv_get_version(state, NULL);
+  if (res == YKPIV_OK) res = _ykpiv_get_serial(state, NULL, false);
 
   return res;
 }
@@ -284,6 +329,7 @@
 
   return res;
 #else
+  (void)state;
   return res;
 #endif
 }
@@ -456,7 +502,7 @@
       fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc);
     }
     SCardReleaseContext(state->context);
-    state->context = SCARD_E_INVALID_HANDLE;
+    state->context = (SCARDCONTEXT)-1;
     return YKPIV_PCSC_ERROR;
   }
 
@@ -471,7 +517,7 @@
       fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc);
     }
     SCardReleaseContext(state->context);
-    state->context = SCARD_E_INVALID_HANDLE;
+    state->context = (SCARDCONTEXT)-1;
     return YKPIV_PCSC_ERROR;
   }
 
@@ -481,12 +527,13 @@
 }
 
 ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state) {
+#if ENABLE_IMPLICIT_TRANSACTIONS
   long rc;
-  ykpiv_rc res;
 
   rc = SCardBeginTransaction(state->card);
-  if((rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) {
-    if((res = reconnect(state)) != YKPIV_OK) {
+  if((long)((unsigned long)rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) {
+   ykpiv_rc res = YKPIV_OK;
+   if((res = reconnect(state)) != YKPIV_OK) {
       return res;
     }
     rc = SCardBeginTransaction(state->card);
@@ -497,27 +544,33 @@
     }
     return YKPIV_PCSC_ERROR;
   }
+#endif /* ENABLE_IMPLICIT_TRANSACTIONS */
+
   return YKPIV_OK;
 }
 
 ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state) {
+#if ENABLE_IMPLICIT_TRANSACTIONS
   long rc = SCardEndTransaction(state->card, SCARD_LEAVE_CARD);
   if(rc != SCARD_S_SUCCESS && state->verbose) {
     fprintf(stderr, "error: Failed to end pcsc transaction, rc=%08lx\n", rc);
     return YKPIV_PCSC_ERROR;
   }
+#endif /* ENABLE_IMPLICIT_TRANSACTIONS */
   return YKPIV_OK;
 }
 
-ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
-    const unsigned char *in_data, long in_len,
-    unsigned char *out_data, unsigned long *out_len, int *sw) {
+ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
+    const unsigned char *in_data,
+    long in_len,
+    unsigned char *out_data,
+    unsigned long *out_len,
+    int *sw) {
   const unsigned char *in_ptr = in_data;
   unsigned long max_out = *out_len;
   ykpiv_rc res;
   *out_len = 0;
 
-  if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR;
   do {
     size_t this_size = 0xff;
     unsigned char data[261];
@@ -587,6 +640,19 @@
     }
   }
 Cleanup:
+  return res;
+}
+
+ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
+    const unsigned char *in_data, long in_len,
+    unsigned char *out_data, unsigned long *out_len, int *sw) {
+  ykpiv_rc res;
+
+  if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) {
+    *out_len = 0;
+    return YKPIV_PCSC_ERROR;
+  }
+  res = _ykpiv_transfer_data(state, templ, in_data, in_len, out_data, out_len, sw);
   _ykpiv_end_transaction(state);
   return res;
 }
@@ -631,6 +697,7 @@
   uint32_t recv_len = sizeof(data);
   int sw;
   ykpiv_rc res;
+  des_rc drc = DES_OK;
   des_key* mgm_key = NULL;
   size_t out_len = 0;
 
@@ -675,7 +742,12 @@
     unsigned char *dataptr = apdu.st.data;
     unsigned char response[8];
     out_len = sizeof(response);
-    des_decrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
+    drc = des_decrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
+
+    if (drc != DES_OK) {
+      res = YKPIV_AUTHENTICATION_ERROR;
+      goto Cleanup;
+    }
 
     recv_len = sizeof(data);
     memset(apdu.raw, 0, sizeof(apdu));
@@ -713,7 +785,13 @@
   {
     unsigned char response[8];
     out_len = sizeof(response);
-    des_encrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
+    drc = des_encrypt(mgm_key, challenge, sizeof(challenge), response, &out_len);
+
+    if (drc != DES_OK) {
+      res = YKPIV_AUTHENTICATION_ERROR;
+      goto Cleanup;
+    }
+
     if (memcmp(response, data + 4, 8) == 0) {
       res = YKPIV_OK;
     }
@@ -785,6 +863,7 @@
   res = YKPIV_GENERIC_ERROR;
 
 Cleanup:
+  yc_memzero(&apdu, sizeof(APDU));
   _ykpiv_end_transaction(state);
   return res;
 }
@@ -838,24 +917,26 @@
   switch(algorithm) {
     case YKPIV_ALGO_RSA1024:
       key_len = 128;
+      // fall through
     case YKPIV_ALGO_RSA2048:
       if(key_len == 0) {
-	key_len = 256;
+	      key_len = 256;
       }
       if(in_len != key_len) {
-	return YKPIV_SIZE_ERROR;
+	      return YKPIV_SIZE_ERROR;
       }
       break;
     case YKPIV_ALGO_ECCP256:
       key_len = 32;
+      // fall through
     case YKPIV_ALGO_ECCP384:
       if(key_len == 0) {
-	key_len = 48;
+	      key_len = 48;
       }
       if(!decipher && in_len > key_len) {
-	return YKPIV_SIZE_ERROR;
+	      return YKPIV_SIZE_ERROR;
       } else if(decipher && in_len != (key_len * 2) + 1) {
-	return YKPIV_SIZE_ERROR;
+	      return YKPIV_SIZE_ERROR;
       }
       break;
     default:
@@ -932,11 +1013,12 @@
   if (NULL == state) return YKPIV_GENERIC_ERROR;
 
   if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR;
-  if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
+  /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */
+  /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/
 
   res = _general_authenticate(state, raw_in, in_len, sign_out, out_len,
                               algorithm, key, false);
-Cleanup:
+/* Cleanup: */
   _ykpiv_end_transaction(state);
   return res;
 }
@@ -949,19 +1031,19 @@
   if (NULL == state) return YKPIV_GENERIC_ERROR;
 
   if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR;
-  if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;
-
+  /* don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS */
+  /*if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup;*/
 
   res = _general_authenticate(state, in, in_len, out, out_len,
      algorithm, key, true);
 
-Cleanup:
+/* Cleanup: */
 
   _ykpiv_end_transaction(state);
   return res;
 }
 
-ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version) {
+static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version) {
   APDU apdu;
   unsigned char data[261];
   uint32_t recv_len = sizeof(data);
@@ -988,6 +1070,12 @@
   if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
     return res;
   } else if(sw == SW_SUCCESS) {
+
+    /* check that we received enough data for the verson number */
+    if (recv_len < 3) {
+      return YKPIV_SIZE_ERROR;
+    }
+
     state->ver.major = data[0];
     state->ver.minor = data[1];
     state->ver.patch = data[2];
@@ -1022,6 +1110,143 @@
   return res;
 }
 
+/* caller must make sure that this is wrapped in a transaction for synchronized operation */
+static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force) {
+  ykpiv_rc res = YKPIV_OK;
+  APDU apdu;
+  const uint8_t yk_applet[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 };
+  unsigned char data[0xff];
+  uint32_t recv_len = sizeof(data);
+  int sw;
+  uint8_t *p_temp = NULL;
+
+  if (!state) {
+    return YKPIV_ARGUMENT_ERROR;
+  }
+
+  if (!f_force && (state->serial != 0)) {
+    if (p_serial) *p_serial = state->serial;
+    return YKPIV_OK;
+  }
+
+  if (state->ver.major < 5) {
+    /* get serial from neo/yk4 devices using the otp applet */
+    uint8_t temp[0xff];
+
+    recv_len = sizeof(temp);
+    memset(apdu.raw, 0, sizeof(apdu));
+    apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
+    apdu.st.p1 = 0x04;
+    apdu.st.lc = sizeof(yk_applet);
+    memcpy(apdu.st.data, yk_applet, sizeof(yk_applet));
+
+    if ((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) {
+      if (state->verbose) {
+        fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
+      }
+      goto Cleanup;
+    }
+    else if (sw != SW_SUCCESS) {
+      if (state->verbose) {
+        fprintf(stderr, "Failed selecting yk application: %04x\n", sw);
+      }
+      res = YKPIV_GENERIC_ERROR;
+      goto Cleanup;
+    }
+
+    recv_len = sizeof(data);
+    memset(apdu.raw, 0, sizeof(apdu));
+    apdu.st.ins = 0x01;
+    apdu.st.p1 = 0x10;
+    apdu.st.lc = 0x00;
+
+    if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
+      if (state->verbose) {
+        fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
+      }
+      goto Cleanup;
+    }
+    else if (sw != SW_SUCCESS) {
+      if (state->verbose) {
+        fprintf(stderr, "Failed retrieving serial number: %04x\n", sw);
+      }
+      res = YKPIV_GENERIC_ERROR;
+      goto Cleanup;
+    }
+
+    recv_len = sizeof(temp);
+    memset(apdu.raw, 0, sizeof(apdu));
+    apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
+    apdu.st.p1 = 0x04;
+    apdu.st.lc = (unsigned char)sizeof(aid);
+    memcpy(apdu.st.data, aid, sizeof(aid));
+
+    if((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) {
+      if(state->verbose) {
+        fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
+      }
+      return res;
+    }
+    else if(sw != SW_SUCCESS) {
+      if(state->verbose) {
+        fprintf(stderr, "Failed selecting application: %04x\n", sw);
+      }
+      return YKPIV_GENERIC_ERROR;
+    }
+  }
+  else {
+    /* get serial from yk5 and later devices using the f8 command */
+
+    memset(apdu.raw, 0, sizeof(apdu));
+    apdu.st.ins = YKPIV_INS_GET_SERIAL;
+
+    if ((res = _send_data(state, &apdu, data, &recv_len, &sw) != YKPIV_OK)) {
+      if(state->verbose) {
+        fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
+      }
+      return res;
+    }
+    else if(sw != SW_SUCCESS) {
+      if(state->verbose) {
+        fprintf(stderr, "Failed retrieving serial number: %04x\n", sw);
+      }
+      return YKPIV_GENERIC_ERROR;
+    }
+  }
+
+  /* check that we received enough data for the serial number */
+  if (recv_len < 4) {
+    return YKPIV_SIZE_ERROR;
+  }
+
+  p_temp = (uint8_t*)(&state->serial);
+
+  *p_temp++ = data[3];
+  *p_temp++ = data[2];
+  *p_temp++ = data[1];
+  *p_temp++ = data[0];
+
+  if (p_serial) *p_serial = state->serial;
+
+Cleanup:
+
+  return res;
+}
+
+ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial) {
+  ykpiv_rc res = YKPIV_OK;
+
+  if ((res = _ykpiv_begin_transaction(state)) != YKPIV_OK) return YKPIV_PCSC_ERROR;
+  if ((res = _ykpiv_ensure_application_selected(state)) != YKPIV_OK) goto Cleanup;
+
+  res = _ykpiv_get_serial(state, p_serial, false);
+
+Cleanup:
+
+  _ykpiv_end_transaction(state);
+  return res;
+}
+
 static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len) {
 #if DISABLE_PIN_CACHE
   // Some embedded applications of this library may not want to keep the PIN
@@ -1034,6 +1259,7 @@
     return YKPIV_OK;
   }
   if (state->pin) {
+    yc_memzero(state->pin, strnlen(state->pin, CB_PIN_MAX));
     _ykpiv_free(state, state->pin);
     state->pin = NULL;
   }
@@ -1056,7 +1282,7 @@
   int sw;
   ykpiv_rc res;
 
-  if (pin_len > 8) {
+  if (pin_len > CB_PIN_MAX) {
     return YKPIV_SIZE_ERROR;
   }
 
@@ -1067,27 +1293,36 @@
   apdu.st.lc = pin ? 0x08 : 0;
   if (pin) {
     memcpy(apdu.st.data, pin, pin_len);
-    if (pin_len < 8) {
-      memset(apdu.st.data + pin_len, 0xff, 8 - pin_len);
+    if (pin_len < CB_PIN_MAX) {
+      memset(apdu.st.data + pin_len, 0xff, CB_PIN_MAX - pin_len);
     }
   }
-  if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) {
+
+  res = _send_data(state, &apdu, data, &recv_len, &sw);
+  yc_memzero(&apdu, sizeof(apdu));
+
+  if (res != YKPIV_OK) {
     return res;
-  } else if (sw == SW_SUCCESS) {
+  }
+  else if (sw == SW_SUCCESS) {
     if (pin && pin_len) {
       // Intentionally ignore errors.  If the PIN fails to save, it will only
       // be a problem if a reconnect is attempted.  Failure deferred until then.
       _cache_pin(state, pin, pin_len);
     }
+
     if (tries) *tries = (sw & 0xf);
     return YKPIV_OK;
-  } else if ((sw >> 8) == 0x63) {
+  }
+  else if ((sw >> 8) == 0x63) {
     if (tries) *tries = (sw & 0xf);
     return YKPIV_WRONG_PIN;
-  } else if (sw == SW_ERR_AUTH_BLOCKED) {
+  }
+  else if (sw == SW_ERR_AUTH_BLOCKED) {
     if (tries) *tries = 0;
     return YKPIV_WRONG_PIN;
-  } else {
+  }
+  else {
     return YKPIV_GENERIC_ERROR;
   }
 }
@@ -1173,10 +1408,10 @@
   unsigned char data[0xff];
   unsigned long recv_len = sizeof(data);
   ykpiv_rc res;
-  if (current_pin_len > 8) {
+  if (current_pin_len > CB_PIN_MAX) {
     return YKPIV_SIZE_ERROR;
   }
-  if (new_pin_len > 8) {
+  if (new_pin_len > CB_PIN_MAX) {
     return YKPIV_SIZE_ERROR;
   }
   if(action == CHREF_ACT_UNBLOCK_PIN) {
@@ -1186,14 +1421,17 @@
     templ[3] = 0x81;
   }
   memcpy(indata, current_pin, current_pin_len);
-  if(current_pin_len < 8) {
-    memset(indata + current_pin_len, 0xff, 8 - current_pin_len);
+  if(current_pin_len < CB_PIN_MAX) {
+    memset(indata + current_pin_len, 0xff, CB_PIN_MAX - current_pin_len);
   }
-  memcpy(indata + 8, new_pin, new_pin_len);
-  if(new_pin_len < 8) {
-    memset(indata + 8 + new_pin_len, 0xff, 8 - new_pin_len);
+  memcpy(indata + CB_PIN_MAX, new_pin, new_pin_len);
+  if(new_pin_len < CB_PIN_MAX) {
+    memset(indata + CB_PIN_MAX + new_pin_len, 0xff, CB_PIN_MAX - new_pin_len);
   }
+
   res = ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw);
+  yc_memzero(indata, sizeof(indata));
+
   if(res != YKPIV_OK) {
     return res;
   } else if(sw != SW_SUCCESS) {
@@ -1289,14 +1527,20 @@
   }
 
   if(sw == SW_SUCCESS) {
-    size_t outlen;
-    int offs = _ykpiv_get_length(data + 1, &outlen);
+    size_t outlen = 0;
+    unsigned int offs = 0;
+    
+    if ((*len < 2) || !_ykpiv_has_valid_length(data + 1, *len - 1)) {
+      return YKPIV_SIZE_ERROR;
+    }
+
+    offs = _ykpiv_get_length(data + 1, &outlen);
     if(offs == 0) {
       return YKPIV_SIZE_ERROR;
     }
     if(outlen + offs + 1 != *len) {
       if(state->verbose) {
-        fprintf(stderr, "Invalid length indicated in object, total objlen is %lu, indicated length is %lu.", *len, outlen);
+        fprintf(stderr, "Invalid length indicated in object, total objlen is %lu, indicated length is %lu.", *len, (unsigned long)outlen);
       }
       return YKPIV_SIZE_ERROR;
     }
@@ -1322,8 +1566,11 @@
   return res;
 }
 
-ykpiv_rc _ykpiv_save_object(ykpiv_state *state, int object_id,
-    unsigned char *indata, size_t len) {
+ykpiv_rc _ykpiv_save_object(
+    ykpiv_state *state,
+    int object_id,
+    unsigned char *indata,
+    size_t len) {
   unsigned char data[CB_BUF_MAX];
   unsigned char *dataptr = data;
   unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff};
@@ -1343,7 +1590,7 @@
   memcpy(dataptr, indata, len);
   dataptr += len;
 
-  if((res = ykpiv_transfer_data(state, templ, data, (long)(dataptr - data), NULL, &outlen,
+  if((res = _ykpiv_transfer_data(state, templ, data, (long)(dataptr - data), NULL, &outlen,
     &sw)) != YKPIV_OK) {
     return res;
   }
@@ -1436,10 +1683,13 @@
   }
   else if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) {
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
     if ((size_t)ec_data_len >= sizeof(key_data)) {
-      // This can never be true, but check to be explicit.
+      /* This can never be true, but check to be explicit. */
       return YKPIV_SIZE_ERROR;
     }
+#pragma GCC diagnostic pop
 
     if (algorithm == YKPIV_ALGO_ECCP256)
       elem_len = 32;
@@ -1464,7 +1714,8 @@
     padding = elem_len - lens[i];
     remaining = (uintptr_t)key_data + sizeof(key_data) - (uintptr_t)in_ptr;
     if (padding > remaining) {
-      return YKPIV_ALGORITHM_ERROR;
+      res = YKPIV_ALGORITHM_ERROR;
+      goto Cleanup;
     }
     memset(in_ptr, 0, padding);
     in_ptr += padding;
@@ -1499,6 +1750,7 @@
   }
 
 Cleanup:
+  yc_memzero(key_data, sizeof(key_data));
   _ykpiv_end_transaction(state);
   return res;
 }
@@ -1617,15 +1869,50 @@
 
 Cleanup:
 
+  yc_memzero(&apdu, sizeof(apdu));
   _ykpiv_end_transaction(state);
   return res;
 }
 
+static const uint8_t MGMT_AID[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 };
+
+/* deauthenticates the user pin and mgm key */
 ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state) {
   ykpiv_rc res = YKPIV_OK;
+  APDU apdu;
+  unsigned char data[0xff];
+  uint32_t recv_len = sizeof(data);
+  int sw;
 
+  if (!state) {
+    return YKPIV_ARGUMENT_ERROR;
+  }
+
+  /* this function does not use ykpiv_transfer_data because it selects a different app */
   if ((res = _ykpiv_begin_transaction(state)) < YKPIV_OK) return res;
-  _ykpiv_util_get_serial(state, NULL, true);
+
+  memset(apdu.raw, 0, sizeof(apdu));
+  apdu.st.ins = YKPIV_INS_SELECT_APPLICATION;
+  apdu.st.p1 = 0x04;
+  apdu.st.lc = sizeof(MGMT_AID);
+  memcpy(apdu.st.data, MGMT_AID, sizeof(MGMT_AID));
+
+  if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) {
+    if (state->verbose) {
+      fprintf(stderr, "Failed communicating with card: '%s'\n", ykpiv_strerror(res));
+    }
+    goto Cleanup;
+  }
+  else if (sw != SW_SUCCESS) {
+    if (state->verbose) {
+      fprintf(stderr, "Failed selecting mgmt application: %04x\n", sw);
+    }
+    res = YKPIV_GENERIC_ERROR;
+    goto Cleanup;
+  }
+
+Cleanup:
+
   _ykpiv_end_transaction(state);
   return res;
 }
diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.h yubico-piv-tool-1.7.0/lib/ykpiv.h
--- yubico-piv-tool-1.6.2/lib/ykpiv.h	2017-11-29 09:42:14.000000000 +0100
+++ yubico-piv-tool-1.7.0/lib/ykpiv.h	2018-10-25 15:27:06.000000000 +0200
@@ -194,6 +194,19 @@
    */
   ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select);
 
+  /**
+   * Get serial number
+   *
+   * The card must be connected to call this function.
+   *
+   * @param state [in] State handle
+   * @param p_serial [out] uint32 to store retrieved serial number
+   *
+   * @return ykpiv_rc error code
+   *
+   */
+  ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t* p_serial);
+
 
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
@@ -492,7 +505,7 @@
    * @param state state
    * @param ccc Unique Card ID to set. If NULL, randomly generate.
    *
-   * @return ypiv_rc error code
+   * @return ykpiv_rc error code
    *
    */
   ykpiv_rc ykpiv_util_set_cccid(ykpiv_state *state, const ykpiv_cccid *ccc);
@@ -647,6 +660,7 @@
 #define YKPIV_INS_RESET 0xfb
 #define YKPIV_INS_SET_PIN_RETRIES 0xfa
 #define YKPIV_INS_ATTEST 0xf9
+#define YKPIV_INS_GET_SERIAL 0xf8
 
 #define YKPIV_PINPOLICY_TAG 0xaa
 #define YKPIV_PINPOLICY_DEFAULT 0
@@ -671,12 +685,15 @@
 
 #define YKPIV_ATR_NEO_R3 "\x3b\xfc\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x4e\x45\x4f\x72\x33\xe1"
 #define YKPIV_ATR_YK4    "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x34\xd4"
+#define YKPIV_ATR_YK5_P1 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x01\x59\x75\x62\x69\x4b\x65\x79\xc1"
+#define YKPIV_ATR_YK5    "\x3b\xfd\x13\x00\x00\x81\x31\xfe\x15\x80\x73\xc0\x21\xc0\x57\x59\x75\x62\x69\x4b\x65\x79\x40"
 
 #define DEVTYPE_UNKNOWN  0x00000000
 #define DEVTYPE_NEO      0x4E450000 //"NE"
 #define DEVTYPE_YK       0x594B0000 //"YK"
 #define DEVTYPE_NEOr3    (DEVTYPE_NEO | 0x00007233) //"r3"
 #define DEVTYPE_YK4      (DEVTYPE_YK  | 0x00000034) // "4"
+#define DEVYTPE_YK5      (DEVTYPE_YK  | 0x00000035) // "5"
 
 #ifdef __cplusplus
 }
diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv.map yubico-piv-tool-1.7.0/lib/ykpiv.map
--- yubico-piv-tool-1.6.2/lib/ykpiv.map	2017-11-29 09:42:14.000000000 +0100
+++ yubico-piv-tool-1.7.0/lib/ykpiv.map	2018-10-25 15:27:06.000000000 +0200
@@ -113,3 +113,9 @@
     ykpiv_util_write_msroots;
     ykpiv_verify_select;
 } YKPIV_1.3.0;
+
+YKPIV_1.6.0
+{
+global:
+    ykpiv_get_serial;
+} YKPIV_1.5.0;
diff -Nru yubico-piv-tool-1.6.2/lib/ykpiv-version.h yubico-piv-tool-1.7.0/lib/ykpiv-version.h
--- yubico-piv-tool-1.6.2/lib/ykpiv-version.h	2018-09-14 09:33:13.000000000 +0200
+++ yubico-piv-tool-1.7.0/lib/ykpiv-version.h	2019-04-03 09:53:52.000000000 +0200
@@ -43,7 +43,7 @@
 	 * version number.  Used together with ykneomgr_check_version() to verify
 	 * header file and run-time library consistency.
 	 */
-#define YKPIV_VERSION_STRING "1.6.2"
+#define YKPIV_VERSION_STRING "1.7.0"
 
 	/**
 	 * YKPIV_VERSION_NUMBER
@@ -53,7 +53,7 @@
 	 * this symbol will have the value 0x01020300.  The last two digits
 	 * are only used between public releases, and will otherwise be 00.
 	 */
-#define YKPIV_VERSION_NUMBER 0x010602
+#define YKPIV_VERSION_NUMBER 0x010700
 
 	/**
 	 * YKPIV_VERSION_MAJOR
@@ -71,7 +71,7 @@
 	 * level of the header file version number.  For example, when the
 	 * header version is 1.2.3 this symbol will be 2.
 	 */
-#define YKPIV_VERSION_MINOR 6
+#define YKPIV_VERSION_MINOR 7
 
 	/**
 	 * YKPIV_VERSION_PATCH
@@ -80,7 +80,7 @@
 	 * level of the header file version number.  For example, when the
 	 * header version is 1.2.3 this symbol will be 3.
 	 */
-#define YKPIV_VERSION_PATCH 2
+#define YKPIV_VERSION_PATCH 0
 
 	const char *ykpiv_check_version (const char *req_version);
 
diff -Nru yubico-piv-tool-1.6.2/Makefile.in yubico-piv-tool-1.7.0/Makefile.in
--- yubico-piv-tool-1.6.2/Makefile.in	2018-09-14 09:21:39.000000000 +0200
+++ yubico-piv-tool-1.7.0/Makefile.in	2019-04-03 09:53:50.000000000 +0200
@@ -197,7 +197,7 @@
 	$(top_srcdir)/build-aux/ltmain.sh \
 	$(top_srcdir)/build-aux/missing COPYING ChangeLog NEWS README \
 	build-aux/ar-lib build-aux/compile build-aux/config.guess \
-	build-aux/config.rpath build-aux/config.sub \
+	build-aux/config.rpath build-aux/config.sub build-aux/depcomp \
 	build-aux/install-sh build-aux/ltmain.sh build-aux/missing
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
diff -Nru yubico-piv-tool-1.6.2/NEWS yubico-piv-tool-1.7.0/NEWS
--- yubico-piv-tool-1.6.2/NEWS	2018-09-14 09:23:34.000000000 +0200
+++ yubico-piv-tool-1.7.0/NEWS	2019-04-03 09:53:25.000000000 +0200
@@ -1,5 +1,23 @@
 yubico-piv-tool NEWS -- History of user-visible changes.        -*- outline -*-
 
+* Version 1.7.0 (released 2019-04-03)
+
+** Add ykpiv_get_serial() to API.
+
+** Add version and serial to status output.
+
+** FASC-N fixes for CHUID.
+
+** ykcs11: Fix ECDSA signatures.
+
+** Make selfsigned X.509 extensions have correct extensions to match openssl.
+
+** Security fixes.
+
+** Documentation fixes.
+
+** Try to clear memory that might contain secrets.
+
 * Version 1.6.2 (released 2018-09-14)
 
 ** Compare reader names case insensitive.
diff -Nru yubico-piv-tool-1.6.2/tool/yubico-piv-tool.1 yubico-piv-tool-1.7.0/tool/yubico-piv-tool.1
--- yubico-piv-tool-1.6.2/tool/yubico-piv-tool.1	2018-09-10 10:19:44.000000000 +0200
+++ yubico-piv-tool-1.7.0/tool/yubico-piv-tool.1	2019-04-03 09:53:55.000000000 +0200
@@ -1,12 +1,12 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.6.
-.TH YUBICO-PIV-TOOL "1" "September 2018" "yubico-piv-tool 1.6.2" "User Commands"
+.TH YUBICO-PIV-TOOL "1" "April 2019" "yubico-piv-tool 1.7.0" "User Commands"
 .SH NAME
 yubico-piv-tool \- Yubico PIV tool
 .SH SYNOPSIS
 .B yubico-piv-tool
 [\fI\,OPTIONS\/\fR]...
 .SH DESCRIPTION
-yubico\-piv\-tool 1.6.2
+yubico\-piv\-tool 1.7.0
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 Print help and exit
diff -Nru yubico-piv-tool-1.6.2/tool/yubico-piv-tool.c yubico-piv-tool-1.7.0/tool/yubico-piv-tool.c
--- yubico-piv-tool-1.6.2/tool/yubico-piv-tool.c	2018-09-10 10:19:42.000000000 +0200
+++ yubico-piv-tool-1.7.0/tool/yubico-piv-tool.c	2019-04-03 09:44:44.000000000 +0200
@@ -49,12 +49,12 @@
 #include <openssl/pkcs12.h>
 #include <openssl/rand.h>
 #include <openssl/rsa.h>
+#include <openssl/x509v3.h>
 
 #include "cmdline.h"
 #include "util.h"
 
 #define MAX(a,b) (a) > (b) ? (a) : (b)
-#define MIN(a,b) (a) < (b) ? (a) : (b)
 
 #define CHUID 0
 #define CCC 1
@@ -450,11 +450,11 @@
       }
 
       rc = ykpiv_import_private_key(state, key, algorithm,
-                                    p, element_len,
-                                    q, element_len,
-                                    dmp1, element_len,
-                                    dmq1, element_len,
-                                    iqmp, element_len,
+                                    p, (size_t)element_len,
+                                    q, (size_t)element_len,
+                                    dmp1, (size_t)element_len,
+                                    dmq1, (size_t)element_len,
+                                    iqmp, (size_t)element_len,
                                     NULL, 0,
                                     pp, tp);
     }
@@ -586,7 +586,7 @@
     } else {
       i2d_X509(cert, &certptr);
     }
-    if ((res = ykpiv_util_write_cert(state, get_slot_hex(slot), certdata, cert_len, compress)) != YKPIV_OK) {
+    if ((res = ykpiv_util_write_cert(state, get_slot_hex(slot), certdata, (size_t)cert_len, compress)) != YKPIV_OK) {
       fprintf(stderr, "Failed commands with device: %s\n", ykpiv_strerror(res));
     } else {
       ret = true;
@@ -797,6 +797,16 @@
   return ret;
 }
 
+static const struct {
+  int nid;
+  const char *ext;
+  int critical;
+} selfsign_extensions[] = {
+  {NID_subject_key_identifier, "hash", 0},
+  {NID_authority_key_identifier, "keyid", 0},
+  {NID_basic_constraints, "CA:true", 1},
+};
+
 static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_format,
     const char *input_file_name, enum enum_slot slot, char *subject, enum enum_hash hash,
     const int *serial, int validDays, const char *output_file_name) {
@@ -921,6 +931,48 @@
   if(nid == 0) {
     goto selfsign_out;
   }
+
+  {
+    X509V3_CTX ctx;
+    int i;
+    X509V3_set_ctx(&ctx, x509, x509, NULL, NULL, 0);
+
+    for(i = 0; i < sizeof(selfsign_extensions) / sizeof(selfsign_extensions[0]); i++) {
+      X509_EXTENSION *ext = NULL;
+      void *ext_struc;
+      const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(selfsign_extensions[i].nid);
+
+      if(!method) {
+        fprintf(stderr, "Failed to get extension method for nid %d.\n", selfsign_extensions[i].nid);
+        goto selfsign_out;
+      }
+      if(method->v2i) {
+        STACK_OF(CONF_VALUE) *nval = X509V3_parse_list(selfsign_extensions[i].ext);
+        if(!nval) {
+          fprintf(stderr, "Failed parsing extension value for nid %d.\n", selfsign_extensions[i].nid);
+          goto selfsign_out;
+        }
+        ext_struc = method->v2i(method, &ctx, nval);
+      } else if(method->s2i) {
+        ext_struc = method->s2i(method, &ctx, selfsign_extensions[i].ext);
+      } else {
+        fprintf(stderr, "Unknown way to construct extension for nid %d.\n", selfsign_extensions[i].nid);
+        goto selfsign_out;
+      }
+
+      if(!ext_struc) {
+        fprintf(stderr, "Failed constructing extension value for nid %d.\n", selfsign_extensions[i].nid);
+        goto selfsign_out;
+      }
+
+      ext = X509V3_EXT_i2d(selfsign_extensions[i].nid, selfsign_extensions[i].critical, ext_struc);
+      if(!X509_add_ext(x509, ext, -1)) {
+        fprintf(stderr, "Failed adding extension %d (%d).\n", i, selfsign_extensions[i].nid);
+        goto selfsign_out;
+      }
+    }
+  }
+
 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
   null_parameter.type = V_ASN1_NULL;
   null_parameter.value.ptr = NULL;
@@ -1067,6 +1119,9 @@
     op = ykpiv_change_puk;
   }
   res = op(state, pin, pin_len, new_pin, new_len, &tries);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch-enum"
   switch (res) {
     case YKPIV_OK:
       return true;
@@ -1088,6 +1143,7 @@
       fprintf(stderr, "Failed changing/unblocking code, error: %s\n", ykpiv_strerror(res));
       return false;
   }
+#pragma GCC diagnostic pop
 }
 
 static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) {
@@ -1258,7 +1314,7 @@
 
 static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_MD *md,
     FILE *output) {
-  int object = ykpiv_util_slot_object(get_slot_hex(slot));
+  int object = (int)ykpiv_util_slot_object(get_slot_hex(slot));
   int slot_name;
   unsigned char data[3072];
   const unsigned char *ptr = data;
@@ -1376,7 +1432,9 @@
   unsigned char buf[3072];
   long unsigned len = sizeof(buf);
   int i;
+  uint32_t serial = 0;
   FILE *output_file = open_file(output_file_name, OUTPUT_TEXT);
+
   if(!output_file) {
     return false;
   }
@@ -1386,6 +1444,20 @@
     return false;
   }
 
+  fprintf(output_file, "Version:\t");
+  if (ykpiv_get_version(state, (char*)buf, (size_t)len) != YKPIV_OK) {
+    fprintf(output_file, "No data available\n");
+  } else {
+    fprintf(output_file, "%s\n", (char*)buf);
+  }
+
+  fprintf(output_file, "Serial Number:\t");
+  if (ykpiv_get_serial(state, &serial) != YKPIV_OK) {
+    fprintf(output_file, "No data available\n");
+  } else {
+    fprintf(output_file, "%d\n", serial);
+  }
+
   fprintf(output_file, "CHUID:\t");
   if(ykpiv_fetch_object(state, YKPIV_OBJ_CHUID, buf, &len) != YKPIV_OK) {
     fprintf(output_file, "No data available\n");
@@ -1714,7 +1786,7 @@
 static bool attest(ykpiv_state *state, enum enum_slot slot,
     enum enum_key_format key_format, const char *output_file_name) {
   unsigned char data[2048];
-  unsigned long len = sizeof(data);
+  size_t len = sizeof(data);
   bool ret = false;
   X509 *x509 = NULL;
   int key;
@@ -1736,7 +1808,7 @@
 
   if(key_format == key_format_arg_PEM) {
     const unsigned char *ptr = data;
-    int len2 = len;
+    int len2 = (int)len;
     x509 = X509_new();
     if(!x509) {
       fprintf(stderr, "Failed allocating x509 structure.\n");
@@ -1787,7 +1859,7 @@
   }
 
   if(verbosity) {
-    fprintf(stderr, "Writing %lu bytes of data to object %x.\n", len, id);
+    fprintf(stderr, "Writing %lu bytes of data to object %x.\n", (long unsigned int)len, id);
   }
 
   if((res = ykpiv_save_object(state, id, data, len)) != YKPIV_OK) {
@@ -1858,6 +1930,7 @@
               cmdline_parser_action_values[action]);
           return EXIT_FAILURE;
         }
+        /* fall through */
       case action_arg_generate:
       case action_arg_importMINUS_key:
       case action_arg_importMINUS_certificate:
@@ -1929,6 +2002,7 @@
           }
           password = pwbuf;
         }
+        /* fall through */
       case action_arg_generate:
       case action_arg_setMINUS_mgmMINUS_key:
       case action_arg_pinMINUS_retries:
diff -Nru yubico-piv-tool-1.6.2/tools/fasc.pl yubico-piv-tool-1.7.0/tools/fasc.pl
--- yubico-piv-tool-1.6.2/tools/fasc.pl	2017-02-03 16:17:05.000000000 +0100
+++ yubico-piv-tool-1.7.0/tools/fasc.pl	2019-01-02 08:50:49.000000000 +0100
@@ -31,7 +31,7 @@
 #  S9999F9999F999999F0F1F0000000000300001E
 # and outputs that in hex, encoded in the 5-bit form described in
 # "Technical Implementation Guidance: Smart Card Enabled Physical Access
-#  Control Systems"
+#  Control Systems Version 2.2", Section 6.2, Figure 7.
 
 use strict;
 use Bit::Vector;
@@ -39,16 +39,16 @@
 my %encoding = (
   0 => "00001",
   1 => "10000",
-  2 => "00100",
-  3 => "00111",
-  4 => "01000",
-  5 => "01011",
+  2 => "01000",
+  3 => "11001",
+  4 => "00100",
+  5 => "10101",
   6 => "01101",
-  7 => "01110",
-  8 => "10000",
+  7 => "11100",
+  8 => "00010",
   9 => "10011",
-  S => "11010", # the examples and definitions of S and F differ
-  F => "10110", # but we'll go with the examples here..
+  S => "11010",
+  F => "10110",
   E => "11111",
 );
 
diff -Nru yubico-piv-tool-1.6.2/windows.mk yubico-piv-tool-1.7.0/windows.mk
--- yubico-piv-tool-1.6.2/windows.mk	2018-08-17 09:24:46.000000000 +0200
+++ yubico-piv-tool-1.7.0/windows.mk	2019-04-03 09:44:44.000000000 +0200
@@ -26,7 +26,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 PACKAGE=yubico-piv-tool
-OPENSSLVERSION=1.0.2p
+OPENSSLVERSION=1.0.2q
 CHECKVERSION=0.12.0
 
 all: usage 32bit 64bit
@@ -72,6 +72,9 @@
 	rm -rf $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/ && \
 	cp COPYING $(PWD)/tmp$(ARCH)/root/licenses/$(PACKAGE).txt && \
 	cd .. && \
+	cd check-$(CHECKVERSION) && \
+	make uninstall && \
+	cd .. && \
 	cd root && \
 	zip -r ../../$(PACKAGE)-$(VERSION)-win$(ARCH).zip *
 
diff -Nru yubico-piv-tool-1.6.2/ykcs11/Makefile.am yubico-piv-tool-1.7.0/ykcs11/Makefile.am
--- yubico-piv-tool-1.6.2/ykcs11/Makefile.am	2017-02-03 16:17:05.000000000 +0100
+++ yubico-piv-tool-1.7.0/ykcs11/Makefile.am	2018-10-25 15:27:06.000000000 +0200
@@ -30,6 +30,7 @@
 AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS)
 AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS)
 AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib
+AM_CPPFLAGS += -I$(top_srcdir)/tool -I$(top_builddir)/tool
 
 lib_LTLIBRARIES = libykcs11.la
 
diff -Nru yubico-piv-tool-1.6.2/ykcs11/Makefile.in yubico-piv-tool-1.7.0/ykcs11/Makefile.in
--- yubico-piv-tool-1.6.2/ykcs11/Makefile.in	2018-09-14 09:21:39.000000000 +0200
+++ yubico-piv-tool-1.7.0/ykcs11/Makefile.in	2019-04-03 09:53:50.000000000 +0200
@@ -453,7 +453,8 @@
 SUBDIRS = . tests
 AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) $(am__append_3)
 AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS) -I$(top_srcdir)/lib \
-	-I$(top_builddir)/lib
+	-I$(top_builddir)/lib -I$(top_srcdir)/tool \
+	-I$(top_builddir)/tool
 lib_LTLIBRARIES = libykcs11.la
 libykcs11_la_SOURCES = ykcs11.c ykcs11.pc.in ykcs11.map ykcs11.h \
 	debug.h vendors.c vendors.h vendor_ids.h slot_vendors.c \
diff -Nru yubico-piv-tool-1.6.2/ykcs11/objects.c yubico-piv-tool-1.7.0/ykcs11/objects.c
--- yubico-piv-tool-1.6.2/ykcs11/objects.c	2018-05-22 13:30:29.000000000 +0200
+++ yubico-piv-tool-1.7.0/ykcs11/objects.c	2019-04-03 09:44:44.000000000 +0200
@@ -306,7 +306,7 @@
     buf[(*n)++] = 0x80 | (CK_BYTE)l;
 }
 
-static void asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) {
+static CK_RV asn1_encode_oid(CK_CHAR_PTR oid, CK_BYTE_PTR asn1_oid, CK_ULONG_PTR len) {
   CK_CHAR_PTR tmp = (CK_BYTE_PTR) strdup((char *)oid);
   CK_CHAR_PTR p = tmp;
   CK_BYTE_PTR q = NULL;
@@ -315,6 +315,10 @@
   CK_ULONG    l = 0;
   CK_ULONG    nodes;
 
+  if (tmp == NULL) {
+    return CKR_HOST_MEMORY;
+  }
+
   q = p;
   *len = 0;
   nodes = 1;
@@ -360,6 +364,8 @@
   }
 
   free(tmp);
+
+  return CKR_OK;
 }
 
 static CK_KEY_TYPE get_key_type(EVP_PKEY *key) {
@@ -395,6 +401,7 @@
   CK_BYTE_PTR data;
   CK_BYTE     tmp[64];
   CK_ULONG    len = 0;
+  CK_RV       rv;
   DBG("For data object %lu, get ", obj);
 
   switch (template->type) {
@@ -439,7 +446,9 @@
   case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ?
     DBG("OID");
     memcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid, sizeof(tmp));
-    asn1_encode_oid(tmp, tmp, &len);
+    if ((rv = asn1_encode_oid(tmp, tmp, &len)) != CKR_OK) {
+      return rv;
+    }
     data = tmp;
     break;
 
diff -Nru yubico-piv-tool-1.6.2/ykcs11/ykcs11.c yubico-piv-tool-1.7.0/ykcs11/ykcs11.c
--- yubico-piv-tool-1.6.2/ykcs11/ykcs11.c	2017-11-29 09:42:14.000000000 +0100
+++ yubico-piv-tool-1.7.0/ykcs11/ykcs11.c	2019-04-03 09:44:44.000000000 +0200
@@ -1695,7 +1695,7 @@
   CK_KEY_TYPE  type = 0;
   CK_ULONG     key_len = 0;
   CK_BYTE      exp[3];
-  CK_BYTE      buf[1024];
+  CK_BYTE      buf[1024] = {0};
   CK_ATTRIBUTE template[] = {
     {CKA_KEY_TYPE, &type, sizeof(type)},
     {CKA_MODULUS_BITS, &key_len, sizeof(key_len)},
@@ -1863,12 +1863,6 @@
     goto sign_out;
   }
 
-  if (op_info.type != YKCS11_SIGN) {
-    DBG("Operation not initialized");
-    rv = CKR_OPERATION_NOT_INITIALIZED;
-    goto sign_out;
-  }
-
   if (session.info.state == CKS_RO_PUBLIC_SESSION ||
       session.info.state == CKS_RW_PUBLIC_SESSION) {
     DBG("User is not logged in");
@@ -1942,7 +1936,7 @@
 
   *pulSignatureLen = sizeof(op_info.buf);
 
-  piv_rv = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id);
+  piv_rv = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, op_info.buf, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id);
   if (piv_rv != YKPIV_OK) {
     if (piv_rv == YKPIV_AUTHENTICATION_ERROR) {
       DBG("Operation requires authentication or touch");
@@ -1958,13 +1952,13 @@
 
   DBG("Got %lu bytes back", *pulSignatureLen);
 #if YKCS11_DBG == 1
-  dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
+  dump_data(op_info.buf, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
 #endif
 
   if (!is_RSA_mechanism(op_info.mechanism.mechanism)) {
     // ECDSA, we must remove the DER encoding and only return R,S
     // as required by the specs
-    strip_DER_encoding_from_ECSIG(pSignature, pulSignatureLen);
+    strip_DER_encoding_from_ECSIG(op_info.buf, pulSignatureLen);
 
     DBG("After removing DER encoding %lu", *pulSignatureLen);
 #if YKCS11_DBG == 1
@@ -1972,7 +1966,7 @@
 #endif
   }
 
-  op_info.type = YKCS11_NOOP;
+  memcpy(pSignature, op_info.buf, *pulSignatureLen);
 
   rv = CKR_OK;
 
diff -Nru yubico-piv-tool-1.6.2/ykcs11/ykcs11-version.h yubico-piv-tool-1.7.0/ykcs11/ykcs11-version.h
--- yubico-piv-tool-1.6.2/ykcs11/ykcs11-version.h	2018-09-14 09:33:13.000000000 +0200
+++ yubico-piv-tool-1.7.0/ykcs11/ykcs11-version.h	2019-04-03 09:53:52.000000000 +0200
@@ -43,7 +43,7 @@
 	 * version number.  Used together with ykneomgr_check_version() to verify
 	 * header file and run-time library consistency.
 	 */
-#define YKCS11_VERSION_STRING "1.6.2"
+#define YKCS11_VERSION_STRING "1.7.0"
 
 	/**
 	 * YKCS11_VERSION_NUMBER
@@ -53,7 +53,7 @@
 	 * this symbol will have the value 0x01020300.  The last two digits
 	 * are only used between public releases, and will otherwise be 00.
 	 */
-#define YKCS11_VERSION_NUMBER 0x010602
+#define YKCS11_VERSION_NUMBER 0x010700
 
 	/**
 	 * YKCS11_VERSION_MAJOR
@@ -71,7 +71,7 @@
 	 * level of the header file version number.  For example, when the
 	 * header version is 1.2.3 this symbol will be 2.
 	 */
-#define YKCS11_VERSION_MINOR 6
+#define YKCS11_VERSION_MINOR 7
 
 	/**
 	 * YKCS11_VERSION_PATCH
@@ -80,7 +80,7 @@
 	 * level of the header file version number.  For example, when the
 	 * header version is 1.2.3 this symbol will be 3.
 	 */
-#define YKCS11_VERSION_PATCH 2
+#define YKCS11_VERSION_PATCH 0
 
 #ifdef __cplusplus
 }

--- End Message ---
--- Begin Message ---
tags -1 wontfix
thanks

On Thu, 2 May 2019 20:17:43 +0200 Paul Gevers <elbrus@debian.org> wrote:
> Please be aware that without updates to that bug, your package will be
> removed from buster soon. When that happens, your package will not be
> allowed to migrate back in, so make sure you follow up, on that bug and
> on this one.

This happened, so closing this bug.

Paul

Attachment: signature.asc
Description: OpenPGP digital signature


--- End Message ---

Reply to: