opencryptoki: Apply opencryptoki-tpm_stdll-sw_fallback-June012006.patch

This enables fallback operation mode for imported keys. Original patch
by Kent Yoder.

BUG=chromium-os:14440
TEST=none

Change-Id: I67fbfdaf18b0e34427aa54db534e4c9bda74d138
diff --git a/usr/lib/pkcs11/common/h_extern.h b/usr/lib/pkcs11/common/h_extern.h
index ade139c..e0f30db 100755
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -2383,20 +2383,20 @@
 
 /* Debug logging */
 #ifdef DEBUG
-#define LogDebug(fmt, ...)      LogMessage(stdout, "LOG_DEBUG", STDLL_NAME, fmt, ##__VA_ARGS__)
-#define LogDebug1(data)         LogMessage1(stdout, "LOG_DEBUG", STDLL_NAME, data)
+#define LogDebug(fmt, ...)      LogMessage(stderr, "LOG_DEBUG", STDLL_NAME, fmt, ##__VA_ARGS__)
+#define LogDebug1(data)         LogMessage1(stderr, "LOG_DEBUG", STDLL_NAME, data)
 
 /* Error logging */
 #define LogError(fmt, ...)      LogMessage(stderr, "LOG_ERR", STDLL_NAME, "ERROR: " fmt, ##__VA_ARGS__)
 #define LogError1(data)         LogMessage1(stderr, "LOG_ERR", STDLL_NAME, "ERROR: " data)
 
 /* Warn logging */
-#define LogWarn(fmt, ...)       LogMessage(stdout, "LOG_WARNING", STDLL_NAME, "WARNING: " fmt, ##__VA_ARGS__)
-#define LogWarn1(data)          LogMessage1(stdout, "LOG_WARNING", STDLL_NAME, "WARNING: " data)
+#define LogWarn(fmt, ...)       LogMessage(stderr, "LOG_WARNING", STDLL_NAME, "WARNING: " fmt, ##__VA_ARGS__)
+#define LogWarn1(data)          LogMessage1(stderr, "LOG_WARNING", STDLL_NAME, "WARNING: " data)
 
 /* Info Logging */
-#define LogInfo(fmt, ...)       LogMessage(stdout, "LOG_INFO", STDLL_NAME, fmt, ##__VA_ARGS__)
-#define LogInfo1(data)          LogMessage1(stdout, "LOG_INFO", STDLL_NAME, data)
+#define LogInfo(fmt, ...)       LogMessage(stderr, "LOG_INFO", STDLL_NAME, fmt, ##__VA_ARGS__)
+#define LogInfo1(data)          LogMessage1(stderr, "LOG_INFO", STDLL_NAME, data)
 
 #define st_err_log(num, ...)    LogMessage(stderr, "ERROR", STDLL_NAME, "%s", err_msg[num].msg)
 #else
diff --git a/usr/lib/pkcs11/tpm_stdll/h_extern.h b/usr/lib/pkcs11/tpm_stdll/h_extern.h
index 74ab197..d5a10a7 100644
--- a/usr/lib/pkcs11/tpm_stdll/h_extern.h
+++ b/usr/lib/pkcs11/tpm_stdll/h_extern.h
@@ -1996,20 +1996,20 @@
 
 /* Debug logging */
 #ifdef DEBUG
-#define LogDebug(fmt, ...)      LogMessage(stdout, "LOG_DEBUG", APPID, fmt, ##__VA_ARGS__)
-#define LogDebug1(data)         LogMessage1(stdout, "LOG_DEBUG", APPID, data)
+#define LogDebug(fmt, ...)      LogMessage(stderr, "LOG_DEBUG", APPID, fmt, ##__VA_ARGS__)
+#define LogDebug1(data)         LogMessage1(stderr, "LOG_DEBUG", APPID, data)
 
 /* Error logging */
 #define LogError(fmt, ...)      LogMessage(stderr, "LOG_ERR", APPID, "ERROR: " fmt, ##__VA_ARGS__)
 #define LogError1(data)         LogMessage1(stderr, "LOG_ERR", APPID, "ERROR: " data)
 
 /* Warn logging */
-#define LogWarn(fmt, ...)       LogMessage(stdout, "LOG_WARNING", APPID, "WARNING: " fmt, ##__VA_ARGS__)
-#define LogWarn1(data)          LogMessage1(stdout, "LOG_WARNING", APPID, "WARNING: " data)
+#define LogWarn(fmt, ...)       LogMessage(stderr, "LOG_WARNING", APPID, "WARNING: " fmt, ##__VA_ARGS__)
+#define LogWarn1(data)          LogMessage1(stderr, "LOG_WARNING", APPID, "WARNING: " data)
 
 /* Info Logging */
-#define LogInfo(fmt, ...)       LogMessage(stdout, "LOG_INFO", APPID, fmt, ##__VA_ARGS__)
-#define LogInfo1(data)          LogMessage1(stdout, "LOG_INFO", APPID, data)
+#define LogInfo(fmt, ...)       LogMessage(stderr, "LOG_INFO", APPID, fmt, ##__VA_ARGS__)
+#define LogInfo1(data)          LogMessage1(stderr, "LOG_INFO", APPID, data)
 
 #define st_err_log(...)		LogMessage(stderr, "ST MSG", APPID, "whammy")
 #else
diff --git a/usr/lib/pkcs11/tpm_stdll/tpm_specific.c b/usr/lib/pkcs11/tpm_stdll/tpm_specific.c
index d5708c3..cc13299 100644
--- a/usr/lib/pkcs11/tpm_stdll/tpm_specific.c
+++ b/usr/lib/pkcs11/tpm_stdll/tpm_specific.c
@@ -34,6 +34,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <stdlib.h>
+#include <limits.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2338,7 +2339,7 @@
 
 	return CKR_OK;
 }
-
+#if 0
 // convert from the local PKCS11 template representation to
 // the underlying requirement
 // returns the pointer to the local key representation
@@ -2364,7 +2365,7 @@
 
 	return ret;
 }
-
+#endif
 CK_RV
 token_specific_rsa_generate_keypair( TEMPLATE  * publ_tmpl,
 		TEMPLATE  * priv_tmpl )
@@ -2598,6 +2599,288 @@
 	return CKR_OK;
 }
 
+/* Convert from the local PKCS11 template representation to the underlying requirement
+ * returns the pointer to the local key representation */
+void *
+rsa_convert_public_key( OBJECT    * key_obj )
+{
+	CK_BBOOL           rc;
+	CK_ATTRIBUTE      * modulus = NULL;
+	CK_ATTRIBUTE      * pub_exp = NULL;
+
+	RSA *rsa;
+	BIGNUM *bn_mod, *bn_exp;
+
+	rc  = template_attribute_find( key_obj->template, CKA_MODULUS,         &modulus );
+	rc &= template_attribute_find( key_obj->template, CKA_PUBLIC_EXPONENT, &pub_exp );
+
+	if (rc == FALSE) {
+		return NULL;
+	}
+
+	// Create an RSA key struct to return
+	rsa = RSA_new();
+	if (rsa == NULL)
+		return NULL;
+	RSA_blinding_off(rsa);
+
+	// Create and init BIGNUM structs to stick in the RSA struct
+	bn_mod = BN_new();
+	bn_exp = BN_new();
+
+	if (bn_exp == NULL || bn_mod == NULL) {
+		if (bn_mod) free(bn_mod);
+		if (bn_exp) free(bn_exp);
+		RSA_free(rsa);
+		return NULL;
+	}
+
+	// Convert from strings to BIGNUMs and stick them in the RSA struct
+	BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod);
+	rsa->n = bn_mod;
+	BN_bin2bn((unsigned char *)pub_exp->pValue, pub_exp->ulValueLen, bn_exp);
+	rsa->e = bn_exp;
+
+	return (void *)rsa;
+}
+
+void *
+rsa_convert_private_key(OBJECT *key_obj)
+{
+	CK_ATTRIBUTE      * attr     = NULL;
+	CK_ATTRIBUTE      * modulus  = NULL;
+	CK_ATTRIBUTE      * priv_exp = NULL;
+	CK_ATTRIBUTE      * prime1   = NULL;
+	CK_ATTRIBUTE      * prime2   = NULL;
+	CK_ATTRIBUTE      * exp1     = NULL;
+	CK_ATTRIBUTE      * exp2     = NULL;
+	CK_ATTRIBUTE      * coeff    = NULL;
+	CK_BBOOL          rc;
+
+	RSA *rsa;
+	BIGNUM *bn_mod, *bn_priv_exp, *bn_p1, *bn_p2, *bn_e1, *bn_e2, *bn_cf;
+
+
+	rc  = template_attribute_find( key_obj->template, CKA_MODULUS,          &modulus );
+	rc &= template_attribute_find( key_obj->template, CKA_PRIVATE_EXPONENT, &priv_exp );
+	rc &= template_attribute_find( key_obj->template, CKA_PRIME_1,          &prime1 );
+	rc &= template_attribute_find( key_obj->template, CKA_PRIME_2,          &prime2 );
+	rc &= template_attribute_find( key_obj->template, CKA_EXPONENT_1,       &exp1 );
+	rc &= template_attribute_find( key_obj->template, CKA_EXPONENT_2,       &exp2 );
+	rc &= template_attribute_find( key_obj->template, CKA_COEFFICIENT,      &coeff );
+
+	if ( !prime2 && !modulus ){
+		return NULL;
+	}
+
+	// Create and init all the RSA and BIGNUM structs we need.
+	rsa = RSA_new();
+	if (rsa == NULL)
+		return NULL;
+	RSA_blinding_off(rsa);
+
+	bn_mod = BN_new();
+	bn_priv_exp = BN_new();
+	bn_p1 = BN_new();
+	bn_p2 = BN_new();
+	bn_e1 = BN_new();
+	bn_e2 = BN_new();
+	bn_cf = BN_new();
+
+	if ((bn_cf == NULL) || (bn_e2 == NULL) || (bn_e1 == NULL) ||
+	    (bn_p2 == NULL) || (bn_p1 == NULL) || (bn_priv_exp == NULL) ||
+	    (bn_mod == NULL))
+	{
+		if (rsa)         RSA_free(rsa);
+		if (bn_mod)      BN_free(bn_mod);
+		if (bn_priv_exp) BN_free(bn_priv_exp);
+		if (bn_p1)       BN_free(bn_p1);
+		if (bn_p2)       BN_free(bn_p2);
+		if (bn_e1)       BN_free(bn_e1);
+		if (bn_e2)       BN_free(bn_e2);
+		if (bn_cf)       BN_free(bn_cf);
+		return NULL;
+	}
+
+	// CRT key?
+	if ( prime1){
+		if (!prime2 || !exp1 ||!exp2 || !coeff) {
+			return NULL;
+		}
+		// Even though this is CRT key, OpenSSL requires the
+		// modulus and exponents filled in or encrypt and decrypt will
+		// not work
+		BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod);
+		rsa->n = bn_mod;
+		BN_bin2bn((unsigned char *)priv_exp->pValue, priv_exp->ulValueLen, bn_priv_exp);
+		rsa->d = bn_priv_exp;
+		BN_bin2bn((unsigned char *)prime1->pValue, prime1->ulValueLen, bn_p1);
+		rsa->p = bn_p1;
+		BN_bin2bn((unsigned char *)prime2->pValue, prime2->ulValueLen, bn_p2);
+		rsa->q = bn_p2;
+		BN_bin2bn((unsigned char *)exp1->pValue, exp1->ulValueLen, bn_e1);
+		rsa->dmp1 = bn_e1;
+		BN_bin2bn((unsigned char *)exp2->pValue, exp2->ulValueLen, bn_e2);
+		rsa->dmq1 = bn_e2;
+		BN_bin2bn((unsigned char *)coeff->pValue, coeff->ulValueLen, bn_cf);
+		rsa->iqmp = bn_cf;
+
+		return rsa;
+	} else {   // must be a non-CRT key
+		if (!priv_exp) {
+			return NULL;
+		}
+		BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod);
+		rsa->n = bn_mod;
+		BN_bin2bn((unsigned char *)priv_exp->pValue, priv_exp->ulValueLen, bn_priv_exp);
+		rsa->d = bn_priv_exp;
+	}
+	return (void *)rsa;
+}
+
+CK_RV
+token_rsa_sw_encrypt(CK_BYTE   * in_data,
+		     CK_ULONG    in_data_len,
+		     CK_BYTE   * out_data,
+		     CK_ULONG  * out_data_len,
+		     OBJECT    * key_obj )
+{
+	CK_RV	rc;
+	RSA	*rsa;
+
+	// Convert the local representation to an OpenSSL representation
+	if ((rsa = (RSA *)rsa_convert_public_key(key_obj)) == NULL) {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		return CKR_HOST_MEMORY;
+	}
+
+	// Do an RSA public encryption
+	rc = RSA_public_encrypt(in_data_len, in_data, out_data, rsa, RSA_PKCS1_PADDING);
+
+	if (rc != 0) {
+		*out_data_len = rc;
+		rc = CKR_OK;
+	} else {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		DEBUG_openssl_print_errors();
+		rc = CKR_FUNCTION_FAILED;
+	}
+
+	RSA_free(rsa);
+	return rc;
+}
+
+CK_RV
+token_rsa_sw_decrypt(CK_BYTE   * in_data,
+		     CK_ULONG    in_data_len,
+		     CK_BYTE   * out_data,
+		     CK_ULONG  * out_data_len,
+		     OBJECT    * key_obj)
+{
+	CK_RV	rv;
+	int	rc;
+	RSA	*rsa;
+
+	// Convert the local key representation to an RSA key representaion
+	if ((rsa = (RSA *)rsa_convert_private_key(key_obj)) == NULL) {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		return CKR_HOST_MEMORY;
+	}
+
+	// Do the private decryption
+	rc = RSA_private_decrypt(in_data_len, in_data, out_data, rsa, RSA_PKCS1_PADDING);
+
+	if (rc > 0) {
+		*out_data_len = rc;
+		rv = CKR_OK;
+	} else {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		DEBUG_openssl_print_errors();
+		rv = CKR_FUNCTION_FAILED;
+	}
+
+	RSA_free(rsa);
+	return rv;
+}
+
+CK_RV
+token_rsa_sw_sign(CK_BYTE   * in_data,
+		  CK_ULONG    in_data_len,
+		  CK_BYTE   * out_data,
+		  CK_ULONG  * out_data_len,
+		  OBJECT    * key_obj)
+{
+	CK_RV	rv;
+	RSA	*rsa;
+	int	nid = 0, in_len, rc;
+
+	if (in_data_len > UINT_MAX || *out_data_len > UINT_MAX) {
+		in_len = UINT_MAX;
+	} else {
+		in_len = in_data_len;
+	}
+
+	// Convert the local key representation to an RSA key representaion
+	if ((rsa = (RSA *)rsa_convert_private_key(key_obj)) == NULL) {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		DEBUG_openssl_print_errors();
+		return CKR_HOST_MEMORY;
+	}
+
+	rc = RSA_private_encrypt(in_len, in_data, out_data, rsa, RSA_PKCS1_PADDING);
+
+	if (rc > *out_data_len) {
+		rv = CKR_BUFFER_TOO_SMALL;
+	} else if (rc != -1) {
+		*out_data_len = rc;
+		rv = CKR_OK;
+	} else {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		DEBUG_openssl_print_errors();
+		rv = CKR_FUNCTION_FAILED;
+	}
+
+	RSA_free(rsa);
+	return rv;
+}
+
+CK_RV
+token_rsa_sw_verify(CK_BYTE   * in_data,
+		    CK_ULONG    in_data_len,
+		    CK_BYTE   * sig,
+		    CK_ULONG    sig_len,
+		    OBJECT    * key_obj)
+{
+	CK_RV	rc;
+	RSA	*rsa;
+	int	nid = 0, in_len, out_len;
+	char	tmp[256];
+
+	if (in_data_len > UINT_MAX || sig_len > UINT_MAX) {
+		in_len = out_len = UINT_MAX;
+	} else {
+		in_len = in_data_len;
+		out_len = sig_len;
+	}
+
+
+	// Convert the local key representation to an RSA key representaion
+	if ((rsa = (RSA *)rsa_convert_public_key(key_obj)) == NULL) {
+		st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+		return CKR_HOST_MEMORY;
+	}
+
+	rc = RSA_public_decrypt(out_len, sig, tmp, rsa, RSA_PKCS1_PADDING);
+	if (rc == in_len && !memcmp(tmp, in_data, in_len)) {
+		rc = CKR_OK;
+	} else {
+		rc = CKR_SIGNATURE_INVALID;
+	}
+
+	RSA_free(rsa);
+	return rc;
+}
+
 CK_RV
 token_specific_rsa_decrypt( CK_BYTE   * in_data,
 		CK_ULONG    in_data_len,
@@ -2613,8 +2896,8 @@
 	BYTE            *buf = NULL;
 
 	if ((rc = token_rsa_load_key(key_obj, &hKey))) {
-		LogError("token_rsa_load_key failed. rc=0x%lx", rc);
-		return rc;
+		LogDebug("Not a TPM-based key. Falling back to software");
+		return token_rsa_sw_decrypt(in_data, in_data_len, out_data, out_data_len, key_obj);
 	}
 
 	/* push the data into the encrypted data object */
@@ -2663,8 +2946,8 @@
 	CK_RV		rc;
 
 	if ((rc = token_rsa_load_key(key_obj, &hKey))) {
-		LogError("token_rsa_load_key failed. rc=0x%lx", rc);
-		return rc;
+		LogDebug("Not a TPM-based key. Falling back to software");
+		return token_rsa_sw_verify(in_data, in_data_len, sig, sig_len, key_obj);
 	}
 
 	/* Create the hash object we'll use to sign */
@@ -2697,11 +2980,11 @@
 }
 
 CK_RV
-token_specific_rsa_sign( CK_BYTE   * in_data,
-		CK_ULONG    in_data_len,
-		CK_BYTE   * out_data,
-		CK_ULONG  * out_data_len,
-		OBJECT    * key_obj )
+token_specific_rsa_sign(CK_BYTE   * in_data,
+			CK_ULONG    in_data_len,
+			CK_BYTE   * out_data,
+			CK_ULONG  * out_data_len,
+			OBJECT    * key_obj )
 {
 	TSS_RESULT	result;
 	TSS_HHASH	hHash;
@@ -2711,8 +2994,8 @@
 	CK_RV		rc;
 
 	if ((rc = token_rsa_load_key(key_obj, &hKey))) {
-		LogError("token_rsa_load_key failed. rc=0x%lx", rc);
-		return rc;
+		LogDebug("Not a TPM-based key. Falling back to software");
+		return token_rsa_sw_sign(in_data, in_data_len, out_data, out_data_len, key_obj);
 	}
 
 	/* Create the hash object we'll use to sign */
@@ -2763,8 +3046,8 @@
 	CK_RV		rc;
 
 	if ((rc = token_rsa_load_key(key_obj, &hKey))) {
-		LogError("token_rsa_load_key failed. rc=0x%lx", rc);
-		return rc;
+		LogDebug("Not a TPM-based key. Falling back to software");
+		return token_rsa_sw_encrypt(in_data, in_data_len, out_data, out_data_len, key_obj);
 	}
 
 	if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA,