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,