Branch: master

4114606c 2016-09-06 02:23:32 Timothy Pearson
Gracefully handle lack of random data in early system startup
Speed up PC/SC launch
M src/cardpincheck.c
M usr/bin/cryptosmartcard.sh
diff --git a/src/cardpincheck.c b/src/cardpincheck.c
index e6c1cc4..f1e730f 100644
--- a/src/cardpincheck.c
+++ b/src/cardpincheck.c
@@ -192,13 +192,13 @@
 		file_to_decrypt = argv[2];
 	}
 
-	fprintf(stderr, "Initializing pkcs11-helper\n");
+	fprintf(stderr, "Initializing pkcs11-helper\n"); fflush(stderr);
 	if ((rv = pkcs11h_initialize()) != CKR_OK) {
 		fprintf(stderr, "pkcs11h_initialize failed: %s\n", pkcs11h_getMessage(rv));
 		return -1;
 	}
 
-	fprintf(stderr, "Registering pkcs11-helper hooks\n");
+	fprintf(stderr, "Registering pkcs11-helper hooks\n"); fflush(stderr);
 	if ((rv = pkcs11h_setLogHook(pkcs_log_hook, NULL)) != CKR_OK) {
 		fprintf(stderr, "pkcs11h_setLogHook failed: %s\n", pkcs11h_getMessage(rv));
 		return -1;
@@ -223,7 +223,7 @@
 		return -1;
 	}
 
-	fprintf(stderr, "Adding provider '%s'\n", opensc_provider_library);
+	fprintf(stderr, "Adding provider '%s'\n", opensc_provider_library); fflush(stderr);
 		if ((rv = pkcs11h_addProvider(opensc_provider_library, opensc_provider_library, FALSE, PKCS11H_PRIVATEMODE_MASK_AUTO, PKCS11H_SLOTEVENT_METHOD_AUTO, 0, FALSE)) != CKR_OK) {
 		fprintf(stderr, "pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv));
 		return -1;
@@ -284,7 +284,11 @@
 		// Check PIN
 		rv = pkcs11h_certificate_ensureKeyAccess(certificate);
 		if (rv != CKR_OK) {
-			if (rv == CKR_CANCEL) {
+			if (rv == CKR_GENERAL_ERROR) {
+				ret = -4;
+				break;
+			}
+			else if (rv == CKR_CANCEL) {
 				ret = -3;
 				break;
 			}
diff --git a/usr/bin/cryptosmartcard.sh b/usr/bin/cryptosmartcard.sh
index f7ca6d9..ac8c206 100755
--- a/usr/bin/cryptosmartcard.sh
+++ b/usr/bin/cryptosmartcard.sh
@@ -80,6 +80,9 @@
 # flag tracking key-file availability
 OPENED=$FALSE
 
+# Terminate the PC/SC subsystem
+killall -9 pcscd > /dev/null 2>&1 || true
+
 # Is the USB driver loaded?
 cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
 USBLOAD=0$?
@@ -88,11 +91,8 @@
 	modprobe usb_storage >/dev/null 2>&1
 fi
 
-# Terminate the PC/SC subsystem
-killall pcscd > /dev/null 2>&1 || true
-
-# Give the system time to settle and open the USB devices
-sleep 5
+# Make sure USB device nodes have loaded
+udevadm settle
 
 # Relaunch the PC/SC subsystem
 pcscd > /dev/null 2>&1
@@ -114,6 +114,35 @@
 			# Card present
 			CARD_INSERTED=$TRUE
 			msg "SmartCard inserted, attempting to authenticate"
+
+			if [ -e /dev/kmsg ]; then
+				# Linux specific!
+				# Wait for nonblocking random driver to start.
+				# Without waiting, the pincheck utility can stall
+				# for a very long time (forever?) waiting
+				# for enough random data to start PKCS11.
+				dmesg | grep -q "random: nonblocking pool is initialized" &> /dev/null
+				RET=$?
+				LOOPS=0
+				if [ $RET -ne 0 ]; then
+					msg "Waiting for nonblocking random pool to start..."
+					sleep 1
+					while [ $RET -ne 0 ]; do
+						dmesg | grep -q "random: nonblocking pool is initialized" &> /dev/null
+						RET=$?
+						if [ $RET -ne 0 ]; then
+							sleep 1
+							LOOPS=$((LOOPS+1))
+							if [ $LOOPS -eq 10 ]; then
+								msg "Random pool initialization is slow.  Try pressing keys or moving the mouse to speed it up..."
+							fi
+						fi
+					done
+					msg "Nonblocking pool started, continuing!"
+				fi
+				rm -f /tmp/kmsg
+			fi
+
 			PIN=$(cardpincheck /usr/lib/opensc-pkcs11.so)
 			RET=$?
 			if [ $RET -eq 0 ]; then
@@ -135,7 +164,7 @@
 	fi
 fi
 
-killall pcscd > /dev/null 2>&1 || true
+killall -9 pcscd > /dev/null 2>&1 || true
 
 if [ $OPENED -eq $FALSE ]; then
 	if [ $CARD_INSERTED -eq $TRUE ]; then