PSARC/2016/350 Update pkcs11_parse_uri() to conform to RFC 7512
authorMisaki Miyashita <Misaki.Miyashita@Oracle.COM>
Tue, 05 Jul 2016 14:34:01 -0700
changeset 6353 afaf9f444329
parent 6349 00824654920d
child 6354 71684abc33b6
PSARC/2016/350 Update pkcs11_parse_uri() to conform to RFC 7512 23293717 pkcs11 engine should use pkcs11_parse_uri() to conform to RFC 7512
components/openssl/common/engines/pkcs11/e_pk11_pub.c
components/openssl/common/engines/pkcs11/e_pk11_uri.c
components/openssl/common/engines/pkcs11/e_pk11_uri.h
components/openssl/common/patches/018-compiler_opts.patch
components/openssl/openssl-default/Makefile
components/openssl/openssl-default/files/openssl.7
components/openssl/openssl-fips-140/Makefile
--- a/components/openssl/common/engines/pkcs11/e_pk11_pub.c	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/common/engines/pkcs11/e_pk11_pub.c	Tue Jul 05 14:34:01 2016 -0700
@@ -252,7 +252,7 @@
 	if (h == CK_INVALID_HANDLE) {
 		PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
 		return (-1);
-		}
+	}
 
 	/* search for entry in the active list */
 	if ((entry = pk11_active_find(h, type)) != NULL) {
@@ -1190,138 +1190,185 @@
 	return (ret);
 }
 
-#define	MAXATTR	1024
+
 /*
- * Load RSA private key from a file or get its PKCS#11 handle if stored in the
- * PKCS#11 token.
+ * Get a key from a file whose name is 'keyid'.
+ * 'keyid' may or may not contain the file URI prefix, "file://".
  */
-/* ARGSUSED */
-EVP_PKEY *
-pk11_load_privkey(ENGINE* e, const char *privkey_id,
-    UI_METHOD *ui_method, void *callback_data)
+static EVP_PKEY *
+common_get_key_from_file(PK11_SESSION *sp, const char *keyid,
+    CK_BBOOL is_private)
 {
-	EVP_PKEY *pkey = NULL;
-	FILE *privkey;
-	CK_OBJECT_HANDLE  h_priv_key = CK_INVALID_HANDLE;
-	RSA *rsa = NULL;
-	PK11_SESSION *sp;
-	/* Anything else below is needed for the key by reference extension. */
-	const char *file;
-	int ret;
-	pkcs11_uri uri_struct;
-	CK_RV rv;
-	CK_BBOOL is_token = CK_TRUE;
-	CK_BBOOL rollback = CK_FALSE;
-	CK_BYTE attr_data[8][MAXATTR];
-	CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
+	const char	*filename;
+	FILE		*fd;
+	RSA		*rsa = NULL;
+	EVP_PKEY	*pkey = NULL;
+	CK_OBJECT_HANDLE  h_key = CK_INVALID_HANDLE;
+
+	if (strncmp(keyid, FILE_URI_PREFIX, strlen(FILE_URI_PREFIX)) == 0) {
+		/* file URI: skip the "file://" prefix */
+		filename = keyid + strlen(FILE_URI_PREFIX);
+	} else {
+		/* assume keyid is a filename without file URI prefix */
+		filename = keyid;
+	}
+
+	if ((fd = fopen(filename, read_mode_flags)) == NULL) {
+		/* 'keyid' was not a file */
+		return (NULL);
+	}
+
+	if (is_private) {
+		pkey = PEM_read_PrivateKey(fd, NULL, NULL, NULL);
+	} else {
+		pkey = PEM_read_PUBKEY(fd, NULL, NULL, NULL);
+	}
+	(void) fclose(fd);
+	if (pkey == NULL) {
+		return (NULL);
+	}
+	rsa = EVP_PKEY_get1_RSA(pkey);
+	if (rsa == NULL) {
+		goto err;
+	}
+
+	/*
+	 * This will always destroy the RSA object since we have a new
+	 * RSA structure here.
+	 */
+	if (is_private) {
+		(void) pk11_check_new_rsa_key_priv(sp, rsa);
+		h_key = sp->opdata_rsa_priv_key =
+		    pk11_get_private_rsa_key(rsa, sp);
+	} else {
+		(void) pk11_check_new_rsa_key_pub(sp, rsa);
+		h_key = sp->opdata_rsa_pub_key =
+		    pk11_get_public_rsa_key(rsa, sp);
+	}
+	if (h_key == CK_INVALID_HANDLE) {
+		goto err;
+	}
+
+	return (pkey);
+
+err:
+	if (rsa != NULL) {
+		RSA_free(rsa);
+	}
+	if (pkey != NULL) {
+		EVP_PKEY_free(pkey);
+	}
+	return (NULL);
+}
+
+#define	MAXATTR	1024
+
+/*
+ * Get a key from a token.
+ * uri_struct->object is required.
+ */
+static EVP_PKEY *
+common_get_key_from_token(ENGINE *e, PK11_SESSION *sp,
+    pkcs11_uri_t *uri_struct, CK_BBOOL is_private)
+{
+	EVP_PKEY	*pkey = NULL;
+	RSA		*rsa = NULL;
+	CK_RV		rv;
+	CK_BBOOL	is_token = CK_TRUE;
+	CK_OBJECT_CLASS	key_class;
+	CK_BYTE		attr_data[2][MAXATTR];
+	CK_ATTRIBUTE	search_templ[] = {
+				{CKA_TOKEN, &is_token, sizeof (is_token)},
+				{CKA_CLASS, &key_class, sizeof (key_class)},
+				{CKA_LABEL, NULL, 0}
+			};
 	CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE;	/* key in keystore */
-
-	/* We look for private keys only. */
-	CK_ATTRIBUTE search_templ[] = {
-		{CKA_TOKEN, &is_token, sizeof (is_token)},
-		{CKA_CLASS, &key_class, sizeof (key_class)},
-		{CKA_LABEL, NULL, 0}
-	};
-
+	CK_BBOOL	rollback = CK_FALSE;
 	/*
 	 * These public attributes are needed to initialize the OpenSSL RSA
 	 * structure with something we can use to look up the key. Note that we
 	 * never ask for private components.
 	 */
-	CK_ATTRIBUTE get_templ[] = {
+	CK_ATTRIBUTE	get_templ[] = {
 		{CKA_MODULUS, (void *)attr_data[0], MAXATTR},		/* n */
 		{CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR},	/* e */
 	};
 
-	if ((sp = pk11_get_session(OP_RSA)) == NULL) {
+	/* make sure that the correct token was specified */
+	if (pk11_check_token_attrs(uri_struct) == 0) {
+		return (NULL);
+	}
+	/* The "object" token is mandatory in the PKCS#11 URI. */
+	if (uri_struct->object == NULL) {
+		PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MISSING_OBJECT_LABEL);
 		return (NULL);
 	}
 
+	/* login to the session */
+	if (pk11_token_login(sp->session, &pk11_login_done,
+	    uri_struct, is_private) == 0) {
+		return (NULL);
+	}
+
+	/* find a private/public object with the matching CKA_LABEL */
+	key_class = is_private ? CKO_PRIVATE_KEY: CKO_PUBLIC_KEY;
+	search_templ[2].pValue = uri_struct->object;
+	search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
+	if (find_one_object(OP_RSA, sp->session, search_templ, 3,
+	    &ks_key) == 0) {
+		goto err;
+	}
+
 	/*
-	 * The next function will decide whether we are going to access keys in
-	 * the token or read them from plain files. It all depends on what is in
-	 * the 'privkey_id' parameter.
+	 * Free the structure now. Note that we use uri_struct's field
+	 * directly in the template so we can't free until find is done.
 	 */
-	ret = pk11_process_pkcs11_uri(privkey_id, &uri_struct, &file);
-	if (ret == 0) {
+	pkcs11_free_uri(uri_struct);
+
+	/*
+	 * We might have a cache hit which we could confirm according to
+	 * the 'n'/'e' params. However, it is easier just to recreate
+	 * everything. We expect the keys to be loaded once and used
+	 * many times. We do not check the return value because even in
+	 * case of failure the sp structure will have both key pointer
+	 * and object handle cleaned and pk11_destroy_object() reports
+	 * the failure to the OpenSSL error message buffer.
+	 */
+	if (is_private) {
+		(void) pk11_destroy_rsa_object_priv(sp, CK_TRUE);
+		sp->opdata_rsa_priv_key = ks_key;
+		/* This object should not be deleted on a cache miss. */
+		sp->persistent = CK_TRUE;
+		rsa = sp->opdata_rsa_priv = RSA_new_method(e);
+	} else {
+		(void) pk11_destroy_rsa_object_pub(sp, CK_TRUE);
+		sp->opdata_rsa_pub_key = ks_key;
+		rsa = sp->opdata_rsa_pub = RSA_new_method(e);
+	}
+	if (rsa == NULL) {
 		goto err;
 	}
 
-	/* We will try to access a key from a PKCS#11 token. */
-	if (ret == 1) {
-		if (pk11_check_token_attrs(&uri_struct) == 0) {
-			goto err;
-		}
-
-		search_templ[2].pValue = uri_struct.object;
-		search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
-
-		if (pk11_token_login(sp->session, &pk11_login_done,
-		    &uri_struct, CK_TRUE) == 0) {
-			goto err;
-		}
-
-		/*
-		 * Now let's try to find the key in the token. It is a failure
-		 * if we can't find it.
-		 */
-		if (find_one_object(OP_RSA, sp->session, search_templ, 3,
-		    &ks_key) == 0) {
-			goto err;
-		}
-
-		/*
-		 * Free the structure now. Note that we use uri_struct's field
-		 * directly in the template so we cannot free it until the find
-		 * is done.
-		 */
-		pk11_free_pkcs11_uri(&uri_struct, 0);
-
-		/*
-		 * We might have a cache hit which we could confirm according to
-		 * the 'n'/'e' params, RSA public pointer as NULL, and non-NULL
-		 * RSA private pointer. However, it is easier just to recreate
-		 * everything. We expect the keys to be loaded once and used
-		 * many times. We do not check the return value because even in
-		 * case of failure the sp structure will have both key pointer
-		 * and object handle cleaned and pk11_destroy_object() reports
-		 * the failure to the OpenSSL error message buffer.
-		 */
-		(void) pk11_destroy_rsa_object_priv(sp, CK_TRUE);
-
-		sp->opdata_rsa_priv_key = ks_key;
-		/* This object shall not be deleted on a cache miss. */
-		sp->persistent = CK_TRUE;
-
-		if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) {
-			goto err;
-		}
-
-		if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
-		    get_templ, 2)) != CKR_OK) {
-			PK11err_add_data(PK11_F_LOAD_PRIVKEY,
-			    PK11_R_GETATTRIBUTVALUE, rv);
-			goto err;
-		}
-
-		/*
-		 * Cache the RSA private structure pointer. We do not use it now
-		 * for key-by-ref keys but let's do it for consistency reasons.
-		 */
+	if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
+	    get_templ, 2)) != CKR_OK) {
+		PK11err_add_data(
+		    is_private ? PK11_F_LOAD_PRIVKEY : PK11_F_LOAD_PUBKEY,
+		    PK11_R_GETATTRIBUTVALUE, rv);
+		goto err;
+	}
+
+	/* Cache the RSA structure pointer. */
+	if (is_private) {
 		sp->opdata_rsa_priv = rsa;
-
-		/*
-		 * We do not use pk11_get_private_rsa_key() here so we must take
-		 * care of handle management ourselves.
-		 */
-		KEY_HANDLE_REFHOLD(ks_key, OP_RSA, CK_FALSE, rollback, err);
-
-		/*
-		 * Those are the sensitive components we do not want to export
-		 * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
-		 */
-		attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
-		attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
+	} else {
+		sp->opdata_rsa_pub = rsa;
+	}
+
+	/* We only export the non-sensitive key components: n and e */
+	attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
+	attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
+
+	if (is_private) {
 		/*
 		 * Must have 'n'/'e' components in the session structure as
 		 * well. They serve as a public look-up key for the private key
@@ -1329,155 +1376,23 @@
 		 */
 		attr_to_BN(&get_templ[0], attr_data[0], &sp->opdata_rsa_n_num);
 		attr_to_BN(&get_templ[1], attr_data[1], &sp->opdata_rsa_e_num);
-
-		if ((pkey = EVP_PKEY_new()) == NULL) {
-			goto err;
-		}
-
-		if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
-			goto err;
-		}
-	} else {
-		if ((privkey = fopen(file, read_mode_flags)) != NULL) {
-			pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
-			(void) fclose(privkey);
-			if (pkey != NULL) {
-				rsa = EVP_PKEY_get1_RSA(pkey);
-				if (rsa != NULL) {
-					(void) pk11_check_new_rsa_key_priv(sp,
-					    rsa);
-
-					h_priv_key = sp->opdata_rsa_priv_key =
-					    pk11_get_private_rsa_key(rsa, sp);
-					if (h_priv_key == CK_INVALID_HANDLE) {
-						goto err;
-					}
-				} else {
-					goto err;
-				}
-			}
-		}
-	}
-
-	pk11_return_session(sp, OP_RSA);
-	return (pkey);
-err:
-	if (rsa != NULL) {
-		RSA_free(rsa);
-	}
-	if (pkey != NULL) {
-		EVP_PKEY_free(pkey);
-		pkey = NULL;
 	}
-	return (pkey);
-}
-
-/* Load RSA public key from a file or load it from the PKCS#11 token. */
-/* ARGSUSED */
-EVP_PKEY *
-pk11_load_pubkey(ENGINE* e, const char *pubkey_id,
-    UI_METHOD *ui_method, void *callback_data)
-{
-	EVP_PKEY *pkey = NULL;
-	FILE *pubkey;
-	CK_OBJECT_HANDLE  h_pub_key = CK_INVALID_HANDLE;
-	RSA *rsa = NULL;
-	PK11_SESSION *sp;
-	/* everything else below needed for key by reference extension */
-	int ret;
-	const char *file;
-	pkcs11_uri uri_struct;
-	CK_RV rv;
-	CK_BBOOL is_token = CK_TRUE;
-	CK_BYTE attr_data[2][MAXATTR];
-	CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
-	CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE;	/* key in keystore */
-
-	CK_ATTRIBUTE search_templ[] = {
-		{CKA_TOKEN, &is_token, sizeof (is_token)},
-		{CKA_CLASS, &key_class, sizeof (key_class)},
-		{CKA_LABEL, NULL, 0}
-	};
-
-	/*
-	 * These public attributes are needed to initialize OpenSSL RSA
-	 * structure with something we can use to look up the key.
-	 */
-	CK_ATTRIBUTE get_templ[] = {
-		{CKA_MODULUS, (void *)attr_data[0], MAXATTR},		/* n */
-		{CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR},	/* e */
-	};
-
-	if ((sp = pk11_get_session(OP_RSA)) == NULL) {
-		return (NULL);
+
+	if ((pkey = EVP_PKEY_new()) == NULL) {
+		goto err;
 	}
-
-	ret = pk11_process_pkcs11_uri(pubkey_id, &uri_struct, &file);
-
-	if (ret == 0) {
+	if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
 		goto err;
 	}
 
-	if (ret == 1) {
-		if (pk11_check_token_attrs(&uri_struct) == 0) {
-			goto err;
-		}
-
-		search_templ[2].pValue = uri_struct.object;
-		search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
-
-		if (pk11_token_login(sp->session, &pk11_login_done,
-		    &uri_struct, CK_FALSE) == 0) {
-			goto err;
-		}
-
-		if (find_one_object(OP_RSA, sp->session, search_templ, 3,
-		    &ks_key) == 0) {
-			goto err;
-		}
-
+	if (is_private) {
 		/*
-		 * Free the structure now. Note that we use uri_struct's field
-		 * directly in the template so we can't free until find is done.
-		 */
-		pk11_free_pkcs11_uri(&uri_struct, 0);
-		/*
-		 * We load a new public key so we will create a new RSA
-		 * structure. No cache hit is possible.
+		 * We do not use pk11_get_private_rsa_key() here so we must
+		 * take care of handle management ourselves.
 		 */
-		(void) pk11_destroy_rsa_object_pub(sp, CK_TRUE);
-		sp->opdata_rsa_pub_key = ks_key;
-
-		if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) {
-			goto err;
-		}
-
-		if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
-		    get_templ, 2)) != CKR_OK) {
-			PK11err_add_data(PK11_F_LOAD_PUBKEY,
-			    PK11_R_GETATTRIBUTVALUE, rv);
-			goto err;
-		}
-
-		/*
-		 * Cache the RSA public structure pointer.
-		 */
-		sp->opdata_rsa_pub = rsa;
-
-		/*
-		 * These are the sensitive components we do not want to export
-		 * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp).
-		 */
-		attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
-		attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
-
-		if ((pkey = EVP_PKEY_new()) == NULL) {
-			goto err;
-		}
-
-		if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
-			goto err;
-		}
+		KEY_HANDLE_REFHOLD(ks_key, OP_RSA, CK_FALSE, rollback, err);
+	} else {
+		CK_OBJECT_HANDLE h_pub_key;
 
 		/*
 		 * Create a session object from it so that when calling
@@ -1496,46 +1411,83 @@
 		if (h_pub_key == CK_INVALID_HANDLE) {
 			goto err;
 		}
+
+	}
+
+	return (pkey);
+
+err:
+	if (rsa != NULL) {
+		RSA_free(rsa);
+		sp->opdata_rsa_priv = NULL;
+		sp->opdata_rsa_pub = NULL;
+	}
+	if (pkey != NULL) {
+		EVP_PKEY_free(pkey);
+	}
+	return (NULL);
+}
+
+
+/*
+ * Load an RSA key from a file or get its PKCS#11 handle if stored in the
+ * PKCS#11 token.
+ */
+static EVP_PKEY *
+common_load_key(ENGINE *e, const char *keyid, CK_BBOOL is_private)
+{
+	EVP_PKEY	*pkey;
+	PK11_SESSION	*sp;
+	int		ret;
+	pkcs11_uri_t	uri_struct;
+
+	if ((sp = pk11_get_session(OP_RSA)) == NULL) {
+		return (NULL);
+	}
+
+	/*
+	 * pkcs11_parse_uri() returns
+	 * - PK11_URI_OK if keyid is a valid PKCS#11 URI
+	 * - PK11_NOT_PKCS11_URI if keyid is not a PKCS#11 URI
+	 * - other return code if keyid is badly formatted
+	 */
+	ret = pkcs11_parse_uri(keyid, &uri_struct);
+	if (ret == PK11_URI_OK) {
+		/* PKCS#11 URI: try to find a key from a PKCS#11 token */
+		pkey = common_get_key_from_token(e, sp, &uri_struct,
+		    is_private);
+	} else if (ret == PK11_NOT_PKCS11_URI) {
+		/* Not PKCS#11 URI: assume it is a file */
+		pkey = common_get_key_from_file(sp, keyid, is_private);
 	} else {
-		if ((pubkey = fopen(file, read_mode_flags)) != NULL) {
-			pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
-			(void) fclose(pubkey);
-			if (pkey != NULL) {
-				rsa = EVP_PKEY_get1_RSA(pkey);
-				if (rsa != NULL) {
-					/*
-					 * This will always destroy the RSA
-					 * object since we have a new RSA
-					 * structure here.
-					 */
-					(void) pk11_check_new_rsa_key_pub(sp,
-					    rsa);
-
-					h_pub_key = sp->opdata_rsa_pub_key =
-					    pk11_get_public_rsa_key(rsa, sp);
-					if (h_pub_key == CK_INVALID_HANDLE) {
-						EVP_PKEY_free(pkey);
-						pkey = NULL;
-					}
-				} else {
-					EVP_PKEY_free(pkey);
-					pkey = NULL;
-				}
-			}
-		}
+		/* hard failure */
+		pkey = NULL;
 	}
 
 	pk11_return_session(sp, OP_RSA);
+
 	return (pkey);
-err:
-	if (rsa != NULL) {
-		RSA_free(rsa);
-	}
-	if (pkey != NULL) {
-		EVP_PKEY_free(pkey);
-		pkey = NULL;
-	}
-	return (pkey);
+}
+
+/*
+ * Load RSA private key from a file or get its PKCS#11 handle if stored in the
+ * PKCS#11 token.
+ */
+/* ARGSUSED */
+EVP_PKEY *
+pk11_load_privkey(ENGINE* e, const char *privkey_id,
+    UI_METHOD *ui_method, void *callback_data)
+{
+	return (common_load_key(e, privkey_id, B_TRUE /* is_private */));
+}
+
+/* Load RSA public key from a file or load it from the PKCS#11 token. */
+/* ARGSUSED */
+EVP_PKEY *
+pk11_load_pubkey(ENGINE* e, const char *pubkey_id,
+    UI_METHOD *ui_method, void *callback_data)
+{
+	return (common_load_key(e, pubkey_id, B_FALSE /* is_private */));
 }
 
 /*
--- a/components/openssl/common/engines/pkcs11/e_pk11_uri.c	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/common/engines/pkcs11/e_pk11_uri.c	Tue Jul 05 14:34:01 2016 -0700
@@ -68,6 +68,7 @@
 
 #include <security/cryptoki.h>
 #include <security/pkcs11.h>
+#include <cryptoutil.h>
 #include "e_pk11.h"
 #include "e_pk11_uri.h"
 
@@ -114,7 +115,7 @@
 	/* Initialize as an error. */
 	*pin = NULL;
 
-	if (strcmp(dialog, BUILTIN_SPEC) == 0) {
+	if (dialog == PK11_URI_BUILTIN_DIALOG) {
 		/* The getpassphrase() function is not MT safe. */
 		(void) pthread_mutex_lock(uri_lock);
 		/* Note that OpenSSL is not localized at all. */
@@ -122,7 +123,7 @@
 		if (*pin == NULL) {
 			PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN);
 			(void) pthread_mutex_unlock(uri_lock);
-			goto err;
+			return (0);
 		} else {
 			char *pw;
 
@@ -134,7 +135,7 @@
 			if ((pw = strdup(*pin)) == NULL) {
 				PK11err(PK11_F_GET_PIN, PK11_R_MALLOC_FAILURE);
 				(void) pthread_mutex_unlock(uri_lock);
-				goto err;
+				return (0);
 			}
 			/* Zero the internal buffer to get rid of the PIN. */
 			memset(*pin, 0, strlen(*pin));
@@ -143,215 +144,48 @@
 		}
 	} else {
 		/*
-		 * This is the "exec:" case. We will get the PIN from the output
-		 * of an external command.
+		 * This is the command case: "<cmd>|". We will get the PIN from
+		 * the output of an external command.
 		 */
-		if (strncmp(dialog, EXEC_SPEC, strlen(EXEC_SPEC)) == 0) {
-			dialog += strlen(EXEC_SPEC);
-			if ((*pin = run_askpass(dialog)) == NULL) {
-				goto err;
+		if (dialog[strlen(dialog) - 1] == '|') {
+			char	*buf;
+
+			/* duplicate the command without tailing '|' */
+			buf = strndup(dialog, strlen(dialog) - 1);
+			if (buf == NULL) {
+				PK11err(PK11_F_GET_PIN, PK11_R_MALLOC_FAILURE);
+				return (0);
+			}
+			*pin = run_askpass(buf);
+			free(buf);
+			if (*pin == NULL) {
+				return (0);
 			}
 		} else {
 			/*
-			 * Invalid specification in the passphrasedialog
-			 * keyword.
+			 * Invalid specification in the pin-source keyword.
 			 */
 			PK11err(PK11_F_GET_PIN, PK11_R_BAD_PASSPHRASE_SPEC);
-			goto err;
+			return (0);
 		}
 	}
 
 	return (1);
-err:
-	return (0);
 }
 
+
 /*
- * Process the PKCS#11 URI and get the PIN. It uses information from the
- * passphrasedialog keyword to get the PIN. If passphrasedialog is not present
- * it is not considered an error since it depends on the token attributes
- * whether C_Login() is required. The function expects an allocated 'uri_struct'
- * structure.
- *
- * Returns:
- *	0 if URI is not valid at all, or if we could not get the PIN
- * 	1 if all is OK
- *	2 if the URI is not the PKCS#11 URI. In that case, put the string
- *	pointer to the filename to "*file". Note that the pointer just points
- *	inside of the "uristr", possibly skipping the file:// prefix if present.
+ * strncmp() the attributes given by PKCS#11 URI against tokenInfo.
+ * It return 0 if they match.  'len' is the length of each field enforced
+ * by PKCS#11 CK_TOKEN_INFO.
  */
-int
-pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct,
-	const char **file)
-{
-	char *uristr2, *l1, *l2, *tok, *name;
-
-	/* Check the "file://" case. */
-	if (strncmp(uristr, FILE_URI_PREFIX, strlen(FILE_URI_PREFIX)) == 0) {
-		*file = uristr + strlen(FILE_URI_PREFIX);
-		return (2);
-	}
-
-	/*  This is the "pkcs11:" case. */
-	if (strncmp(uristr, PK11_URI_PREFIX, strlen(PK11_URI_PREFIX)) != 0) {
-		/* Not PKCS#11 URI at all, could be a filename. */
-		*file = (const char *)uristr;
-		return (2);
-	} else {
-		/* Dup the string and skip over the pkcs11: prefix then. */
-		uristr2 = strdup(uristr + strlen(PK11_URI_PREFIX));
-		if (uristr2 == NULL) {
-			PK11err(PK11_F_CHECK_TOKEN_ATTRS,
-			    PK11_R_MALLOC_FAILURE);
-			goto err;
-		}
-	}
-
-	/* Initialize the structure. */
-	memset(uri_struct, 0, sizeof (*uri_struct));
-
-	/*
-	 * Using strtok_r() would silently skip over multiple semicolons. We
-	 * must check that before moving on. We must also avoid ';' as the first
-	 * and the last character in the URI.
-	 */
-	if (strstr(uristr2, ";;") != NULL || uristr2[0] == ';' ||
-	    (strlen(uristr2) > 0 && uristr2[strlen(uristr2) - 1] == ';')) {
-		goto bad_uri;
-	}
-
-	tok = strtok_r(uristr2, ";", &l1);
-	for (; tok != NULL; tok = strtok_r(NULL, ";", &l1)) {
-		/* "tok" is not empty so there will be something in "name". */
-		name = strtok_r(tok, "=", &l2);
-		/* Check whether there is '=' at all. */
-		if (l2 == NULL) {
-			goto bad_uri;
-		}
+#define	URI_MATCH_TOKENINFO(URI_name, tokenInfo_name, len) \
+	strncmp((char *)uri_struct->URI_name, \
+	    (char *)token_info->tokenInfo_name, \
+	    strlen((char *)uri_struct->URI_name) > (len) ? (len) : \
+	    strlen((char *)uri_struct->URI_name))
+#define	TOKEN_MODEL_SIZE	16
 
-		/*
-		 * Fill out the URI structure. We do not accept duplicit
-		 * attributes.
-		 */
-		if (strcmp(name, PK11_TOKEN) == 0) {
-			if (uri_struct->token == NULL) {
-				if ((uri_struct->token = strdup(l2)) == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_MANUF) == 0) {
-			if (uri_struct->manuf == NULL) {
-				if ((uri_struct->manuf = strdup(l2)) == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_SERIAL) == 0) {
-			if (uri_struct->serial == NULL) {
-				if ((uri_struct->serial = strdup(l2)) == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_MODEL) == 0) {
-			if (uri_struct->model == NULL) {
-				if ((uri_struct->model = strdup(l2)) == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_OBJECT) == 0) {
-			if (uri_struct->object == NULL) {
-				if ((uri_struct->object = strdup(l2)) == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_OBJECTTYPE) == 0) {
-			if (uri_struct->objecttype == NULL) {
-				uri_struct->objecttype = strdup(l2);
-				if (uri_struct->objecttype == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else if (strcmp(name, PK11_ASKPASS) == 0) {
-			if (uri_struct->askpass == NULL) {
-				uri_struct->askpass = strdup(l2);
-				if (uri_struct->askpass == NULL) {
-					goto no_mem;
-				}
-			} else {
-				goto bad_uri;
-			}
-		} else {
-			goto bad_uri;
-		}
-	}
-
-	/* The "object" token is mandatory in the PKCS#11 URI. */
-	if (uri_struct->object == NULL) {
-		PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MISSING_OBJECT_LABEL);
-		goto err;
-	}
-
-	free(uristr2);
-	return (1);
-bad_uri:
-	PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_INVALID_PKCS11_URI);
-	if (uristr2 != NULL) {
-		free(uristr2);
-	}
-	return (0);
-no_mem:
-	PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE);
-err:
-	pk11_free_pkcs11_uri(uri_struct, CK_FALSE);
-	if (uristr2 != NULL) {
-		free(uristr2);
-	}
-	return (0);
-}
-
-/*
- * Free the PKCS11 URI structure and anything that might be inside.
- */
-void
-pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself)
-{
-	if (uri_struct->token != NULL) {
-		free(uri_struct->token);
-	}
-	if (uri_struct->manuf != NULL) {
-		free(uri_struct->manuf);
-	}
-	if (uri_struct->serial != NULL) {
-		free(uri_struct->serial);
-	}
-	if (uri_struct->model != NULL) {
-		free(uri_struct->model);
-	}
-	if (uri_struct->object != NULL) {
-		free(uri_struct->object);
-	}
-	if (uri_struct->objecttype != NULL) {
-		free(uri_struct->objecttype);
-	}
-	if (uri_struct->askpass != NULL) {
-		free(uri_struct->askpass);
-	}
-
-	if (free_uri_itself == CK_TRUE) {
-		OPENSSL_free(uri_struct);
-	}
-}
 
 /*
  * While our keystore is always the one used by the pubkey slot (which is
@@ -367,7 +201,7 @@
  *	0 on failure
  */
 int
-pk11_check_token_attrs(pkcs11_uri *uri_struct)
+pk11_check_token_attrs(pkcs11_uri_t *uri_struct)
 {
 	CK_RV rv;
 	static CK_TOKEN_INFO_PTR token_info = NULL;
@@ -390,35 +224,27 @@
 	}
 
 	if (uri_struct->token != NULL) {
-		if (strncmp(uri_struct->token, (char *)token_info->label,
-		    strlen(uri_struct->token) > 32 ? 32 :
-		    strlen(uri_struct->token)) != 0) {
+		if (URI_MATCH_TOKENINFO(token, label, TOKEN_LABEL_SIZE) != 0) {
 			goto urierr;
 		}
 	}
 
 	if (uri_struct->manuf != NULL) {
-		if (strncmp(uri_struct->manuf,
-		    (char *)token_info->manufacturerID,
-		    strlen(uri_struct->manuf) > 32 ? 32 :
-		    strlen(uri_struct->manuf)) != 0) {
+		if (URI_MATCH_TOKENINFO(manuf, manufacturerID,
+		    TOKEN_MANUFACTURER_SIZE) != 0) {
 			goto urierr;
 		}
 	}
 
 	if (uri_struct->model != NULL) {
-		if (strncmp(uri_struct->model, (char *)token_info->model,
-		    strlen(uri_struct->model) > 16 ? 16 :
-		    strlen(uri_struct->model)) != 0) {
+		if (URI_MATCH_TOKENINFO(model, model, TOKEN_MODEL_SIZE) != 0) {
 			goto urierr;
 		}
 	}
 
 	if (uri_struct->serial != NULL) {
-		if (strncmp(uri_struct->serial,
-		    (char *)token_info->serialNumber,
-		    strlen(uri_struct->serial) > 16 ? 16 :
-		    strlen(uri_struct->serial)) != 0) {
+		if (URI_MATCH_TOKENINFO(serial, serialNumber,
+		    TOKEN_SERIAL_SIZE) != 0) {
 			goto urierr;
 		}
 	}
@@ -585,14 +411,16 @@
  */
 int
 pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
-    pkcs11_uri *uri_struct, CK_BBOOL is_private)
+    pkcs11_uri_t *uri_struct, CK_BBOOL is_private)
 {
-	CK_RV rv;
+	CK_RV	rv;
+	int	ret = 0;
+	char	*pin = NULL;
 
 	if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) {
 		PK11err(PK11_F_TOKEN_LOGIN,
 		    PK11_R_TOKEN_NOT_INITIALIZED);
-		goto err;
+		return (0);
 	}
 
 	/*
@@ -606,7 +434,16 @@
 	    is_private == CK_TRUE) && ~pubkey_token_flags &
 	    CKF_USER_PIN_INITIALIZED) {
 		PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET);
-		goto err;
+		return (0);
+	}
+
+	/*
+	 * If token does not require login we take it as the login was done.
+	 */
+	if (!(pubkey_token_flags & CKF_LOGIN_REQUIRED) &&
+	    (is_private == CK_FALSE)) {
+		*login_done = CK_TRUE;
+		return (1);
 	}
 
 	/*
@@ -619,109 +456,99 @@
 	 * lock, making future unlocking impossible. We lock right before
 	 * C_Login().
 	 */
-	if (pubkey_token_flags & CKF_LOGIN_REQUIRED || is_private == CK_TRUE) {
-		if (*login_done == CK_FALSE &&
-		    uri_struct->askpass == NULL) {
+	if (*login_done == CK_FALSE && uri_struct->pinfile == NULL) {
+		PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_PROVIDED);
+		return (0);
+	}
+
+	if (*login_done == CK_FALSE && uri_struct->pinfile != NULL) {
+		/*
+		 * 'pin' is allocated by pk11_get_pin().
+		 * Note: don't call pk11_get_pin() with uri_lock held.
+		 */
+		if (pk11_get_pin(uri_struct->pinfile, &pin) == 0) {
 			PK11err(PK11_F_TOKEN_LOGIN,
 			    PK11_R_TOKEN_PIN_NOT_PROVIDED);
-			goto err;
-		}
-
-		if (*login_done == CK_FALSE &&
-		    uri_struct->askpass != NULL) {
-			if (pk11_get_pin(uri_struct->askpass,
-			    &uri_struct->pin) == 0) {
-				PK11err(PK11_F_TOKEN_LOGIN,
-				    PK11_R_TOKEN_PIN_NOT_PROVIDED);
-				goto err;
-			}
+			return (0);
 		}
-
-		/*
-		 * Note that what we are logging into is the keystore from
-		 * pubkey_SLOTID because we work with OP_RSA session type here.
-		 * That also means that we can work with only one keystore in
-		 * the engine.
-		 *
-		 * We must make sure we do not try to login more than once.
-		 * Also, see the comment above on locking strategy.
-		 */
-		(void) pthread_mutex_lock(uri_lock);
-		if (*login_done == CK_FALSE) {
-			if ((rv = pFuncList->C_Login(session,
-			    CKU_USER, (CK_UTF8CHAR*)uri_struct->pin,
-			    strlen(uri_struct->pin))) != CKR_OK) {
-				PK11err_add_data(PK11_F_TOKEN_LOGIN,
-				    PK11_R_TOKEN_LOGIN_FAILED, rv);
-				goto err_locked;
-			}
-
-			*login_done = CK_TRUE;
-
-			/*
-			 * Cache the passphrasedialog for possible child (which
-			 * would need to relogin).
-			 */
-			if (passphrasedialog == NULL &&
-			    uri_struct->askpass != NULL) {
-				passphrasedialog =
-				    strdup(uri_struct->askpass);
-
-				if (passphrasedialog == NULL) {
-					PK11err_add_data(PK11_F_TOKEN_LOGIN,
-					    PK11_R_MALLOC_FAILURE, rv);
-					goto err_locked;
-				}
-			}
-
-			/*
-			 * Check the PIN caching policy. Note that user might
-			 * have provided a PIN even when no PIN was required -
-			 * in that case we always remove the PIN from memory.
-			 */
-			if (pk11_get_pin_caching_policy() ==
-			    POLICY_WRONG_VALUE) {
-				PK11err(PK11_F_TOKEN_LOGIN,
-				    PK11_R_PIN_CACHING_POLICY_INVALID);
-				goto err_locked;
-			}
-
-			if (pk11_get_pin_caching_policy() != POLICY_NONE) {
-				if (pk11_cache_pin(uri_struct->pin) == 0) {
-					goto err_locked;
-				}
-			}
-		}
-		(void) pthread_mutex_unlock(uri_lock);
-	} else {
-		/*
-		 * If token does not require login we take it as the
-		 * login was done.
-		 */
-		*login_done = CK_TRUE;
 	}
 
 	/*
-	 * If we raced at pk11_get_pin() we must make sure that all threads that
-	 * called pk11_get_pin() will erase the PIN from memory, not just the
-	 * one that called C_Login(). Note that if we were supposed to cache the
-	 * PIN it was already cached by now so filling "uri_struct.pin" with
-	 * zero bytes is always OK since pk11_cache_pin() makes a copy of it.
+	 * Note that what we are logging into is the keystore from
+	 * pubkey_SLOTID because we work with OP_RSA session type here.
+	 * That also means that we can work with only one keystore in
+	 * the engine.
+	 *
+	 * We must make sure we do not try to login more than once.
+	 * Also, see the comment above on locking strategy.
 	 */
-	if (uri_struct->pin != NULL) {
-		memset(uri_struct->pin, 0, strlen(uri_struct->pin));
+	(void) pthread_mutex_lock(uri_lock);
+	if (*login_done == CK_TRUE) {
+		ret = 1;
+		goto exit_locked;
+	}
+
+	if ((rv = pFuncList->C_Login(session, CKU_USER,
+	    (CK_UTF8CHAR *)pin, strlen(pin))) != CKR_OK) {
+		PK11err_add_data(PK11_F_TOKEN_LOGIN,
+		    PK11_R_TOKEN_LOGIN_FAILED, rv);
+		goto exit_locked;
 	}
 
-	return (1);
+	*login_done = CK_TRUE;
+
+	/*
+	 * Cache the passphrasedialog for possible child (which
+	 * would need to relogin).
+	 */
+	if (passphrasedialog == NULL) {
+		if (uri_struct->pinfile == PK11_URI_BUILTIN_DIALOG) {
+			passphrasedialog = PK11_URI_BUILTIN_DIALOG;
+		} else if (uri_struct->pinfile != NULL) {
+			passphrasedialog = strdup(uri_struct->pinfile);
+			if (passphrasedialog == NULL) {
+				PK11err_add_data(PK11_F_TOKEN_LOGIN,
+				    PK11_R_MALLOC_FAILURE, rv);
+				goto exit_locked;
+			}
+		}
+	}
 
-err_locked:
+	/*
+	 * Check the PIN caching policy. Note that user might
+	 * have provided a PIN even when no PIN was required -
+	 * in that case we always remove the PIN from memory.
+	 */
+	if (pk11_get_pin_caching_policy() == POLICY_WRONG_VALUE) {
+		PK11err(PK11_F_TOKEN_LOGIN, PK11_R_PIN_CACHING_POLICY_INVALID);
+		goto exit_locked;
+	}
+
+	if (pk11_get_pin_caching_policy() != POLICY_NONE) {
+		if (pk11_cache_pin(pin) == 0) {
+			goto exit_locked;
+		}
+	}
+
+	ret = 1;
+
+exit_locked:
 	(void) pthread_mutex_unlock(uri_lock);
-err:
-	/* Always get rid of the PIN. */
-	if (uri_struct->pin != NULL) {
-		memset(uri_struct->pin, 0, strlen(uri_struct->pin));
+
+	/*
+	 * If we raced at pk11_get_pin() we must make sure that all
+	 * threads that called pk11_get_pin() will erase the PIN from
+	 * memory, not just the one that called C_Login(). Note that if
+	 * we were supposed to cache the PIN it was already cached by
+	 * now so filling "uri_struct.pin" with zero bytes is always OK
+	 * since pk11_cache_pin() makes a copy of it.
+	 */
+	if (pin != NULL) {
+		memset(pin, 0, strlen(pin));
+		OPENSSL_free(pin);
 	}
-	return (0);
+
+	return (ret);
 }
 
 /*
@@ -754,7 +581,7 @@
 		if (token_pin != NULL) {
 			pin = token_pin;
 		} else if (pk11_get_pin(passphrasedialog, &pin) == 0) {
-			goto err;
+			return (0);
 		}
 
 		(void) pthread_mutex_lock(uri_lock);
@@ -763,7 +590,7 @@
 			PK11err_add_data(PK11_F_TOKEN_RELOGIN,
 			    PK11_R_TOKEN_LOGIN_FAILED, rv);
 			(void) pthread_mutex_unlock(uri_lock);
-			goto err;
+			return (0);
 		}
 		(void) pthread_mutex_unlock(uri_lock);
 
@@ -775,8 +602,6 @@
 	}
 
 	return (1);
-err:
-	return (0);
 }
 
 /*
--- a/components/openssl/common/engines/pkcs11/e_pk11_uri.h	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/common/engines/pkcs11/e_pk11_uri.h	Tue Jul 05 14:34:01 2016 -0700
@@ -52,12 +52,15 @@
 #define	E_PK11_URI_H
 
 #include <security/pkcs11t.h>
+#include <cryptoutil.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 /* PKCS#11 URI related prefixes and attributes. */
+/* define until cryptotuil.h is updated on the system */
+#ifndef	PK11_URI_PREFIX
 #define	PK11_URI_PREFIX		"pkcs11:"
 #define	FILE_URI_PREFIX		"file://"
 #define	PK11_TOKEN		"token"
@@ -66,8 +69,16 @@
 #define	PK11_MODEL		"model"
 #define	PK11_OBJECT		"object"
 #define	PK11_OBJECTTYPE		"objecttype"
+#endif
+
+/* OLD PKCS#11 URI supported by OpenSSL pkcs11 engine */
 #define	PK11_ASKPASS		"passphrasedialog"
 
+#ifndef	PK11_URI_BUILTIN_DIALOG
+/* Use buitin passphrase dialog as a PIN source */
+#define	PK11_URI_BUILTIN_DIALOG		((char *)-1)
+#endif
+
 /* PIN caching policy. */
 #define	POLICY_NOT_INITIALIZED	0
 #define	POLICY_NONE		1
@@ -80,31 +91,18 @@
  */
 #define	PK11_MAX_PIN_LEN	256
 
-/* Add new attributes of the PKCS#11 URI here. */
-typedef struct pkcs11_uri_struct {
-	char	*object;	/* object label, the only mandatory info */
-	char	*objecttype;	/* (private|public|cert), currently unused */
-	char	*token;		/* token label */
-	char	*manuf;		/* manufacturer label */
-	char	*serial;	/* serial number label */
-	char	*model;		/* model label */
-	char	*askpass;	/* full path to the command to get the PIN */
-	/* Not part of the PKCS11 URI itself. */
-	char	*pin;		/* token PIN */
-} pkcs11_uri;
-
 /* For URI processing. */
 extern pthread_mutex_t *uri_lock;
 
 int pk11_get_pin(char *dialog, char **pin);
 int pk11_get_pin_caching_policy(void);
-int pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct,
+int pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri_t *uri_struct,
 	const char **file);
-int pk11_check_token_attrs(pkcs11_uri *uri_struct);
-void pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself);
+int pk11_check_token_attrs(pkcs11_uri_t *uri_struct);
+void pk11_free_pkcs11_uri(pkcs11_uri_t *uri_struct, CK_BBOOL free_uri_itself);
 int pk11_cache_pin(char *pin);
 int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done,
-	pkcs11_uri *uri_struct, CK_BBOOL is_private);
+	pkcs11_uri_t *uri_struct, CK_BBOOL is_private);
 int pk11_token_relogin(CK_SESSION_HANDLE session);
 
 #ifdef	__cplusplus
--- a/components/openssl/common/patches/018-compiler_opts.patch	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/common/patches/018-compiler_opts.patch	Tue Jul 05 14:34:01 2016 -0700
@@ -17,14 +17,14 @@
  "sunos-gcc","gcc:-O3 -mcpu=v8 -Dssize_t=int::(unknown):SUNOS::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL DES_PTR DES_RISC1:${no_asm}::",
  
 +#### Solaris configs, used for OpenSSL as delivered by S11.
-+"solaris-x86-cc-sunw","cc:-m32 -xO3 -xspace -Xa::-D_REENTRANT::-lsocket -lnsl -lc:BN_LLONG RC4_CHUNK DES_PTR DES_UNROLL BF_PTR:${x86_elf_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"solaris-x86-cc-sunw","cc:-m32 -xO3 -xspace -Xa::-D_REENTRANT::-lsocket -lnsl -lc -lcryptoutil:BN_LLONG RC4_CHUNK DES_PTR DES_UNROLL BF_PTR:${x86_elf_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 +#
-+"solaris64-x86_64-cc-sunw","cc:-xO3 -m64 -xstrconst -Xa -DL_ENDIAN::-D_REENTRANT::-lsocket -lnsl -lc:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR DES_PTR DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"solaris64-x86_64-cc-sunw","cc:-xO3 -m64 -xstrconst -Xa -DL_ENDIAN::-D_REENTRANT::-lsocket -lnsl -lc -lcryptoutil:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR DES_PTR DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 +#
-+"solaris-sparcv9-cc-sunw","cc:-xtarget=ultra -m32 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc:BN_LLONG RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"solaris-sparcv9-cc-sunw","cc:-xtarget=ultra -m32 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -lcryptoutil:BN_LLONG RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 +#
-+"solaris64-sparcv9-cc-sunw","cc:-xtarget=ultra -m64 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -xspace -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc:BN_LLONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/bin/ar rs::/64",
-+"solaris-fips-sparcv9-cc-sunw","cc:-xtarget=ultra -m32 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc:BN_LLONG RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${fips_sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"solaris64-sparcv9-cc-sunw","cc:-xtarget=ultra -m64 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -xspace -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -lcryptoutil:BN_LLONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/bin/ar rs::/64",
++"solaris-fips-sparcv9-cc-sunw","cc:-xtarget=ultra -m32 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -lcryptoutil:BN_LLONG RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${fips_sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
 +"solaris64-fips-sparcv9-cc-sunw","cc:-xtarget=ultra -m64 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -xspace -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc:BN_LLONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${fips_sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/bin/ar rs::/64",
 +# Option -xF=%all instructs the compiler to place functions and data
 +# variables into separate section fragments. This enables the link editor
--- a/components/openssl/openssl-default/Makefile	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/openssl-default/Makefile	Tue Jul 05 14:34:01 2016 -0700
@@ -414,3 +414,4 @@
 REQUIRED_PACKAGES += developer/build/makedepend
 REQUIRED_PACKAGES += network/rsync
 REQUIRED_PACKAGES += system/library
+REQUIRED_PACKAGES += system/library/security/crypto
--- a/components/openssl/openssl-default/files/openssl.7	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/openssl-default/files/openssl.7	Tue Jul 05 14:34:01 2016 -0700
@@ -95,7 +95,7 @@
 Reboot is required to enforce the change system-wide.
 .sp
 .LP
-See \fIManaging Encryption and Certificates in Oracle Solaris 11.2\fR for more details.
+See \fIManaging Encryption and Certificates in Oracle Solaris\fR for more details.
 .sp
 .LP
 When the FIPS-140 version of OpenSSL is activated, an application can run in FIPS-140 mode or non-FIPS-140 mode. An application must explicitly call \fBFIPS_mode_set()\fR in order to activate FIPS-140 mode.
@@ -129,29 +129,18 @@
 
 .sp
 .LP
-\fBkey_id\fR, formerly for filenames only, can be now also set to a \fBPKCS#11 URI\fR. The \fBEVP_PKEY\fR structure is newly allocated and caller is responsible to free the structure later. To avoid clashes with existing filenames, \fBfile://\fR prefix for filenames is now also accepted but only when the PKCS#11 engine is in use. The PKCS#11 URI specification follows:
+\fBkey_id\fR, formerly for filenames only, can be now also set to a \fBPKCS#11 URI\fR. The \fBEVP_PKEY\fR structure is newly allocated and caller is responsible to free the structure later. See the \fBpkcs11_parse_uri\fR(7) man page for the PKCS#11 URI attributes supported by Solaris.
 .sp
-.in +2
-.nf
-pkcs11:[token=<label>][:manuf=<label>][;serial=<label>]
-   [;model=<label>][;object=<label>]
-   [;objecttype=(public|private|cert)]
-   [;passphrasedialog=(builtin|exec:<file>)]
-.fi
-.in -2
 
 .sp
 .LP
-The ordering of keywords is not significant. The PKCS#11 engine uses the keystore for the slot chosen for public key operations, which is \fBmetaslot\fR on a standard configured machine. Currently, the PKCS#11 engine ignores the \fBobjecttype\fR keyword. The only mandatory keyword is \fBobject\fR which is the key object label. For information on how to use a different, possibly hardware, keystore with \fBmetaslot\fR, see \fBlibpkcs11\fR(3LIB).
+The PKCS#11 engine uses the keystore for the slot chosen for public key operations, which is \fBmetaslot\fR on a standard configured machine. The only mandatory keyword is \fBobject\fR which is the key object label. For information on how to use a different, possibly hardware, keystore with \fBmetaslot\fR, see \fBlibpkcs11\fR(3LIB).
 .sp
 .LP
-The token PIN is provided by way of the \fBpassphrasedialog\fR keyword and is either read from the terminal (\fBbuiltin\fR) or from the output of an external command (\fBexec:<file>\fR). The PIN is used to log into the token and by default is deleted from the memory then. The keyword \fBpin\fR is intentionally not provided due to inherent security problems of possible use of a password in the process arguments.
+Due to fork safety issues the application must re-login if the child continues to use the PKCS#11 engine. It is done inside of the engine automatically if fork is detected.  Alternatively, an environment variable \fBOPENSSL_PKCS11_PIN_CACHING_POLICY\fR can be used to allow the PIN to be cached in memory and reused in the child. It can be set to \fBnone\fR which is the default, \fBmemory\fR to store the PIN in memory, and \fBmlocked-memory\fR to keep the PIN in a locked page using \fBmlock\fR(3C). \fBPRIV_PROC_LOCK_MEMORY\fR privilege is required in that case.
 .sp
 .LP
-Due to fork safety issues the application must re-login if the child continues to use the PKCS#11 engine. It is done inside of the engine automatically if fork is detected and in that case, \fBexec:<file>\fR option of the \fBpassphrasedialog\fR keyword can be used. Alternatively, an environment variable \fBOPENSSL_PKCS11_PIN_CACHING_POLICY\fR can be used to allow the PIN to be cached in memory and reused in the child. It can be set to \fBnone\fR which is the default, \fBmemory\fR to store the PIN in memory, and \fBmlocked-memory\fR to keep the PIN in a locked page using \fBmlock\fR(3C). \fBPRIV_PROC_LOCK_MEMORY\fR privilege is required in that case.
-.sp
-.LP
-Sensitive parts of private keys are never read from the token to the process memory no matter whether the key is tagged with sensitive flag or not. The PKCS#11 engine uses the public components as a search key to get a PKCS#11 object handle to the private key.
+The PKCS#11 engine uses the public components as a search key to get a PKCS#11 object handle to the private key.
 .sp
 .LP
 To use the RSA keys by reference, high level API functions such as \fBRSA_public_decrypt()\fR, \fBEVP_PKEY_set1_RSA()\fR, or \fBEVP_SignInit()\fR must be used. Low level functions might go around the engine and fail to make use of the feature.
@@ -174,7 +163,7 @@
 .nf
 $ \fBpktool gencert keystore=pkcs11 label=mykey \
    subject="CN=test" keytype=rsa keylen=1024 serial=01\fR
-$ \fBopenssl rsa -in "pkcs11:object=mykey;passphrasedialog=builtin"\
+$ \fBopenssl rsa -in "pkcs11:object=mykey?pin-source=builtin-dialog"\
    -pubout -text -engine pkcs11 -inform e\fR
 .fi
 .in -2
@@ -202,7 +191,7 @@
 .SH SEE ALSO
 .sp
 .LP
-\fBcrle\fR(1), \fBcryptoadm\fR(8), \fBlibpkcs11\fR(3LIB), \fBattributes\fR(7), \fBprivileges\fR(7)
+\fBcrle\fR(1), \fBcryptoadm\fR(8), \fBlibpkcs11\fR(3LIB), \fBpkcs11_parse_uri\fR(7), \fBattributes\fR(7), \fBprivileges\fR(7)
 .sp
 .LP
 \fB/usr/share/man/man1openssl/openssl.1openssl\fR, \fB/usr/share/man/man1openssl/CRYPTO_num_locks.3openssl\fR, \fB/usr/share/man/man3openssl/engine.3\fR, \fB/usr/share/man/man3openssl/evp.3\fR
--- a/components/openssl/openssl-fips-140/Makefile	Tue Jul 05 13:55:03 2016 -0700
+++ b/components/openssl/openssl-fips-140/Makefile	Tue Jul 05 14:34:01 2016 -0700
@@ -210,3 +210,4 @@
 REQUIRED_PACKAGES += developer/build/makedepend
 REQUIRED_PACKAGES += network/rsync
 REQUIRED_PACKAGES += system/library
+REQUIRED_PACKAGES += system/library/security/crypto