/*
* The Initial Developer of the Original Code is International
* Business Machines Corporation. Portions created by IBM
* Corporation are Copyright (C) 2005 International Business
* Machines Corporation. All Rights Reserved.
*
* it under the terms of the Common Public License as published by
* IBM Corporation; either version 1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Common Public License for more details.
*
* You should have received a copy of the Common Public License
* along with this program; if not, a copy can be viewed at
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
*/
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <syslog.h>
#include <tss/platform.h>
#include <tss/tss_defines.h>
#include <tss/tss_typedef.h>
#include <tss/tss_structs.h>
#include <tss/tss_error.h>
#include <tss/tcs_error.h>
#include <trousers/trousers.h>
#include "tpmtok_int.h"
#include "tpmtok_defs.h"
int tok_slot2local(CK_SLOT_ID);
CK_BYTE *,
CK_BYTE *,
CK_ULONG *,
OBJECT *);
CK_BYTE *,
CK_BYTE *,
CK_ULONG *,
OBJECT *);
CK_BYTE *,
CK_BYTE *,
CK_ULONG *,
OBJECT *);
TEMPLATE *,
TEMPLATE *);
CK_BYTE *,
CK_ULONG);
CK_BYTE *,
CK_ULONG *);
static CK_RV
"TPM_Debug",
NULL,
NULL,
NULL,
NULL,
};
/* The context we'll use globally to connect to the TSP */
/* TSP key handles */
/* TSP policy handles */
/* PKCS#11 key handles */
int not_initialized = 0;
static CK_RV
static TSS_RESULT
static TSS_RESULT
static void
{
return;
}
/* convert from TSS_UUID to uuid_t */
static void
{
tmp >>= 8;
tmp >>= 8;
tmp >>= 8;
tmp >>= 8;
tmp >>= 8;
}
/* convert from uuid_t to TSS_UUID */
static void
{
}
static void
{
}
static void
{
}
static int
{
return (-1);
return (-1);
}
return (0);
}
static int
{
int ret = 0;
char *tmpfname;
char *p = get_tpm_keystore_path();
if (p == NULL)
return (-1);
"%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
return (-1);
}
return (-1);
}
}
}
return (ret);
}
static int
{
char *p = get_tpm_keystore_path();
if (p == NULL)
return (-1);
"%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
/* Open UUID Index file */
/* initialize the file */
}
return (-1);
}
if (ret == 0) {
found = 1;
uuid);
}
break;
}
}
}
if (!found)
ret = -1;
return (ret);
}
static int
{
int nulluuid;
return (nulluuid);
}
static int
{
char *p = get_tpm_keystore_path();
if (p == NULL)
return (-1);
if (uuid_is_null(uuid))
return (-1);
"%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
return (-1);
return (0);
}
static UINT32
{
switch (size) {
case 512:
return (TSS_KEY_SIZE_512);
case 1024:
return (TSS_KEY_SIZE_1024);
case 2048:
return (TSS_KEY_SIZE_2048);
default:
break;
}
return (0);
}
/* make sure the public exponent attribute is 65537 */
static CK_ULONG
{
if (!flag) {
LogError1("Couldn't find public exponent attribute");
return (CKR_TEMPLATE_INCOMPLETE);
}
switch (publ_exp_attr->ulValueLen) {
case 3:
break;
case sizeof (CK_ULONG):
if (publ_exp == 65537)
rc = 0;
break;
default:
break;
}
return (rc);
}
unsigned long size_n, unsigned char *n)
{
/* Get the TCPA_PUBKEY blob from the key object. */
if (result != TSS_SUCCESS) {
stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n",
return (result);
}
offset = 0;
if (result != TSS_SUCCESS) {
stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n",
return (result);
}
/* Free the first dangling reference, putting 'n' in its place */
offset = 0;
/* Free the second dangling reference */
/* set the public key data in the TSS object */
if (result != TSS_SUCCESS) {
stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n",
return (result);
}
return (result);
}
/*
* Get details about the TPM to put into the token_info structure.
*/
{
stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_Context_GetCapability: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
/*ARGSUSED*/
{
return (CKR_OK);
}
{
stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_TPM_GetRandom: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
{
stlogit("Tspi_Context_Create: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_Context_Connect: 0x%0x - %s",
*pContext = 0;
return (CKR_FUNCTION_FAILED);
}
return (result);
}
/*ARGSUSED*/
static CK_RV
{
if (result)
return (CKR_FUNCTION_FAILED);
&hDefaultPolicy))) {
stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (result);
}
/*
* Given a modulus and prime from an RSA key, create a TSS_HKEY object by
* wrapping the RSA key with a key from the TPM (SRK or other previously stored
* key).
*/
static CK_RV
int size_n,
unsigned char *n,
int size_p,
unsigned char *p,
{
if (initFlags == 0) {
return (CKR_FUNCTION_FAILED);
}
/* create the TSS key object */
if (result != TSS_SUCCESS) {
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
if (result != TSS_SUCCESS) {
return (CKR_FUNCTION_FAILED);
}
/* set the private key data in the TSS object */
if (result != TSS_SUCCESS) {
stlogit("Tspi_SetAttribData: 0x%x - %s",
return (CKR_FUNCTION_FAILED);
}
TSS_ES_RSAESPKCSV15))) {
stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
return (CKR_FUNCTION_FAILED);
}
}
if (result != TSS_SUCCESS) {
stlogit("Tspi_Key_WrapKey: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
/*
* Create a TPM key blob for an imported key. This function is only called when
* a key is in active use, so any failure should trickle through.
*/
static CK_RV
{
return (rc);
}
/* if the object isn't a key, fail */
return (CKR_TEMPLATE_INCOMPLETE);
}
return (CKR_TEMPLATE_INCONSISTENT);
}
return (CKR_TEMPLATE_INCOMPLETE);
}
if (class == CKO_PRIVATE_KEY) {
/*
* In order to create a full TSS key blob using a PKCS#11
* private key object, we need one of the two primes, the
* modulus and the private exponent and we need the public
* exponent to be correct.
*/
/*
* Check the least likely attribute to exist first, the
* primes.
*/
&prime_attr) == FALSE) {
return (CKR_TEMPLATE_INCOMPLETE);
}
}
/* Make sure the public exponent is usable */
return (CKR_TEMPLATE_INCONSISTENT);
}
/* get the modulus */
return (CKR_TEMPLATE_INCOMPLETE);
}
/* make sure the key size is usable */
if (initFlags == 0) {
return (CKR_TEMPLATE_INCONSISTENT);
}
/* generate the software based key */
phKey))) {
return (rc);
}
} else if (class == CKO_PUBLIC_KEY) {
/* Make sure the public exponent is usable */
return (CKR_TEMPLATE_INCONSISTENT);
}
/* grab the modulus to put into the TSS key object */
return (CKR_TEMPLATE_INCONSISTENT);
}
/* make sure the key size is usable */
if (initFlags == 0) {
return (CKR_TEMPLATE_INCONSISTENT);
}
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (result);
}
return (CKR_FUNCTION_FAILED);
}
if (result) {
return (CKR_FUNCTION_FAILED);
}
if (result) {
return (CKR_FUNCTION_FAILED);
}
} else {
return (CKR_FUNCTION_FAILED);
}
/* grab the entire key blob to put into the PKCS#11 object */
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* insert the key blob into the object */
&new_attr))) {
return (rc);
}
/*
* If this is a token object, save it with the new attribute
* so that we don't have to go down this path again.
*/
if (!object_is_session_object(obj)) {
}
return (rc);
}
static TSS_RESULT
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (result);
}
stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
goto done;
}
0, NULL);
} else {
}
if (result != TSS_SUCCESS) {
stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
goto done;
}
done:
if (result != TSS_SUCCESS)
return (result);
}
/*
* Take a key from the TSS store (on-disk) and load it into the TPM, wrapped
* by an already TPM-resident key and protected with a PIN (optional).
*/
static CK_RV
{
/*
* The key blob wasn't found, load the parts of the key
* from the object DB and create a new key object that
* gets loaded into the TPM, wrapped with the parent key.
*/
hParentKey, phKey))) {
return (rc);
}
/*
* Assign the PIN hash (optional) to the newly loaded key object,
* if this PIN is incorrect, the TPM will not be able to decrypt
* the private key and use it.
*/
return (result);
}
/*
* Load the SRK into the TPM by referencing its well-known UUID and using the
* default SRK PIN (20 bytes of 0x00).
*
* NOTE - if the SRK PIN is changed by an administrative tool, this code will
* fail because it assumes that the well-known PIN is still being used.
*/
static TSS_RESULT
{
stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* load the SRK */
stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s",
goto done;
}
&hPolicy))) {
stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
goto done;
}
stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
goto done;
}
done:
return (result);
}
static TSS_RESULT
{
if (local_uuid_is_null(uuid) &&
/* The UUID was not created or saved yet */
return (1);
}
if (result) {
stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s",
return (result);
}
if (result)
return (result);
}
if (result)
stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
return (result);
}
static TSS_RESULT
{
if (hPublicRootKey != NULL_HKEY)
return (TSS_SUCCESS);
return (result);
}
if (result)
return (result);
return (result);
}
static TSS_RESULT
{
TSS_ES_RSAESPKCSV15))) {
stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
return (result);
}
stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
return (result);
}
return (result);
}
static TSS_RESULT
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (result);
}
if (result) {
return (result);
}
&hMigPolicy))) {
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (result);
}
TSS_SECRET_MODE_NONE, 0, NULL);
} else {
}
if (result != TSS_SUCCESS) {
stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
return (result);
}
stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
return (result);
}
}
if (result) {
return (result);
}
}
stlogit("Tspi_Key_CreateKey: 0x%0x - %s",
}
return (result);
}
static TSS_RESULT
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (result);
}
SHA1_DIGEST_LENGTH, passHash))) {
stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
return (result);
}
hPolicy))) {
stlogit("Tspi_ChangeAuth: 0x%0x - %s",
}
/*
* Update the PS key by unregistering the key UUID and then
* re-registering with the same UUID. This forces the updated
* auth data associated with the key to be stored in PS so
* the new PIN can be used next time.
*/
stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s",
stlogit("Tspi_Context_RegisterKey: 0x%0x - %s",
return (result);
}
static CK_RV
{
char *keyid;
switch (key_type) {
case TPMTOK_PUBLIC_LEAF_KEY:
break;
case TPMTOK_PRIVATE_LEAF_KEY:
break;
default:
goto done;
}
hParentKey, phKey)) {
return (rc);
}
/*
* - generate newUUID
* - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
* USER, newUUID, USER, parentUUID);
* - store newUUID
*/
(void) local_uuid_generate(&newuuid);
if (result == TSS_SUCCESS) {
int ret;
/*
* Add the UUID to the token UUID index.
*/
if (ret)
else
}
done:
return (rc);
}
/*
* TPM resident key that has the PIN being tested assigned as its "secret".
* If the PIN is incorrect, the unbind operation will fail.
*/
static CK_RV
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
goto done;
}
/* Use some random data */
if (rc)
goto done;
stlogit("Tspi_Data_Bind: 0x%0x - %s",
goto done;
}
/* unbind the junk data to test the key's auth data */
if (result == TPM_E_AUTHFAIL) {
stlogit("Tspi_Data_Unbind: 0x%0x - %s",
goto done;
} else if (result != TSS_SUCCESS) {
stlogit("Tspi_Data_Unbind: 0x%0x - %s",
goto done;
}
else
done:
if (rgbUnboundData != NULL)
return (rc);
}
static CK_RV
{
int ret;
return (CKR_FUNCTION_FAILED);
/*
* - create UUID privateRootKeyUUID
* - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
* USER, privateRootKeyUUID, system, UUID_SRK);
* - store privateRootKeyUUID in users private token space.
*/
&hPrivateRootKey))) {
return (result);
}
if (result) {
return (result);
}
if (ret) {
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
return (CKR_FUNCTION_FAILED);
}
/* generate the private leaf key */
pinHash, &hPrivateLeafKey))) {
return (rc);
}
stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
(void) Tspi_Context_UnregisterKey(hContext,
(void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID);
(void) Tspi_Context_UnregisterKey(hContext,
(void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
return (CKR_FUNCTION_FAILED);
}
return (rc);
}
static CK_RV
{
int ret;
return (CKR_FUNCTION_FAILED);
/*
* - create publicRootKeyUUID
* - Tspi_Context_RegisterKey(hContext, hPublicRootKey,
* USER, publicRootKeyUUID, system, UUID_SRK);
* - store publicRootKeyUUID in users private token space.
*/
&hPublicRootKey))) {
return (CKR_FUNCTION_FAILED);
}
if (result) {
return (CKR_FUNCTION_FAILED);
}
if (ret) {
/* does result matter here? */
return (CKR_FUNCTION_FAILED);
}
/* Load the newly created publicRootKey into the TPM using the SRK */
return (CKR_FUNCTION_FAILED);
}
/* create the SO's leaf key */
pinHash, &hPublicLeafKey))) {
return (rc);
}
stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
/* Unregister keys and clear UUIDs */
(void) Tspi_Context_UnregisterKey(hContext,
(void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID);
(void) Tspi_Context_UnregisterKey(hContext,
(void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID);
return (CKR_FUNCTION_FAILED);
}
return (rc);
}
{
/* Make sure the SRK is loaded into the TPM */
return (CKR_FUNCTION_FAILED);
}
return (CKR_FUNCTION_FAILED);
}
/*
* If the public root key doesn't exist yet,
* the SO hasn't init'd the token.
*/
if (result == TPM_E_DECRYPT_ERROR) {
return (CKR_USER_PIN_NOT_INITIALIZED);
}
}
/*
* - find privateRootKeyUUID
* - load by UUID (SRK parent)
*/
if (local_uuid_is_null(&privateRootKeyUUID) &&
&privateRootKeyUUID)) {
return (CKR_PIN_INCORRECT);
not_initialized = 1;
return (CKR_OK);
}
return (rc);
}
(void) XProcUnLock(xproclock);
}
} else {
/*
* SO login logic:
*
* - find publicRootKey UUID
* - load by UUID wrap with hSRK from above
*/
if (local_uuid_is_null(&publicRootKeyUUID) &&
&publicRootKeyUUID)) {
return (CKR_PIN_INCORRECT);
not_initialized = 1;
return (CKR_OK);
}
if (hPublicRootKey == NULL_HKEY) {
if (result)
return (CKR_FUNCTION_FAILED);
}
/* find, load the public leaf key */
if (hPublicLeafKey == NULL_HKEY) {
if (result)
return (CKR_FUNCTION_FAILED);
}
return (rc);
}
}
return (rc);
}
{
if (hPrivateLeafKey != NULL_HKEY) {
} else if (hPublicLeafKey != NULL_HKEY) {
}
return (CKR_OK);
}
/*ARGSUSED*/
{
/*
* Since the SO must log in before calling C_InitPIN, we will
* be able to return (CKR_OK) automatically here.
* This is because the USER key structure is created at the
* time of her first login, not at C_InitPIN time.
*/
return (CKR_OK);
}
static CK_RV
{
/* make sure the new PIN is different */
LogError1("new PIN must not be the default");
return (CKR_PIN_INVALID);
}
} else {
LogError1("new PIN must not be the default");
return (CKR_PIN_INVALID);
}
}
LogError1("New PIN is out of size range");
return (CKR_PIN_LEN_RANGE);
}
return (CKR_OK);
}
/*
* This function is called from set_pin only, where a non-logged-in public
* session can provide the user pin which must be verified. This function
* assumes that the pin has already been set once, so there's no migration
* path option or checking of the default user pin.
*/
static CK_RV
{
return (CKR_FUNCTION_FAILED);
/*
* Verify the user by loading the privateLeafKey
* into the TPM (if it's not already) and then
* call the verify_pin operation.
*
* The hashed PIN is assigned to the private leaf key.
* If it is incorrect (not the same as the one originally
* used when the key was created), the verify operation
* will fail.
*/
if (hPrivateRootKey == NULL_HKEY) {
if (result)
return (CKR_FUNCTION_FAILED);
}
if (hPrivateLeafKey == NULL_HKEY) {
if (result)
return (CKR_FUNCTION_FAILED);
}
/*
* random data.
*/
return (rc);
}
return (CKR_OK);
}
{
if (!sess) {
return (CKR_SESSION_HANDLE_INVALID);
}
return (CKR_FUNCTION_FAILED);
}
return (CKR_FUNCTION_FAILED);
}
return (CKR_FUNCTION_FAILED);
}
/*
* From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of
* the user that is currently logged in, or the CKU_USER PIN
* if the session is not logged in."
* A non R/W session fails with CKR_SESSION_READ_ONLY.
*/
if (not_initialized) {
return (CKR_PIN_INCORRECT);
}
ulNewPinLen))) {
return (rc);
}
newpin_hash))) {
return (CKR_FUNCTION_FAILED);
}
return (save_token_data(nv_token_data));
}
/* if we're already logged in, just verify the hash */
return (CKR_PIN_INCORRECT);
}
} else {
oldpin_hash))) {
return (rc);
}
}
ulNewPinLen)))
return (rc);
/* change the auth on the TSS object */
return (CKR_FUNCTION_FAILED);
if (not_initialized) {
return (CKR_PIN_INCORRECT);
return (rc);
newpin_hash)))
return (CKR_FUNCTION_FAILED);
return (save_token_data(nv_token_data));
}
return (CKR_PIN_INCORRECT);
ulNewPinLen)))
return (rc);
/* change auth on the SO's leaf key */
return (CKR_FUNCTION_FAILED);
} else {
}
return (rc);
}
/* only called at token init time */
{
return (CKR_FUNCTION_FAILED);
}
return (CKR_FUNCTION_FAILED);
}
/*
* TRYME INSTEAD:
* - find publicRootKeyUUID
* - Load publicRootKey by UUID (SRK parent)
* - find publicLeafKeyUUID
* - Load publicLeafKey by UUID (publicRootKey parent)
* - set password policy on publicLeafKey
*/
if (local_uuid_is_null(&publicRootKeyUUID) &&
/*
* The SO hasn't set her PIN yet, compare the
* login pin with the hard-coded value.
*/
return (CKR_PIN_INCORRECT);
}
return (CKR_OK);
}
if (result)
return (CKR_FUNCTION_FAILED);
if (result)
return (CKR_FUNCTION_FAILED);
if (local_uuid_is_null(&publicLeafKeyUUID) &&
return (CKR_FUNCTION_FAILED);
if (result)
return (CKR_FUNCTION_FAILED);
if (result)
return (CKR_FUNCTION_FAILED);
if (result)
return (CKR_FUNCTION_FAILED);
/* If the hash given is wrong, the verify will fail */
return (rc);
}
return (CKR_OK);
}
{
if (hPublicRootKey != NULL_HKEY) {
}
if (hPublicLeafKey != NULL_HKEY) {
}
if (hPrivateRootKey != NULL_HKEY) {
}
if (hPrivateLeafKey != NULL_HKEY) {
}
return (CKR_OK);
}
/*
* Wrap the 20 bytes of auth data and store in an attribute of the two
* keys.
*/
static CK_RV
{
return (CKR_FUNCTION_FAILED);
} else if (hPublicLeafKey != NULL_HKEY) {
} else {
}
/* create the encrypted data object */
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
authData))) {
stlogit("Tspi_Data_Bind: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* pull the encrypted data out of the encrypted data object */
stlogit("Tspi_SetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
&new_attr))) {
return (rc);
}
return (rc);
}
return (rc);
}
static CK_RV
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
encAuthDataLen, encAuthData))) {
stlogit("Tspi_SetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* unbind the data, receiving the plaintext back */
stlogit("Tspi_Data_Unbind: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
if (buf_size != SHA1_DIGEST_LENGTH) {
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
{
/* Make sure the public exponent is usable */
if ((util_check_public_exponent(publ_tmpl))) {
return (CKR_TEMPLATE_INCONSISTENT);
}
if (!flag) {
return (CKR_TEMPLATE_INCOMPLETE);
}
return (CKR_KEY_SIZE_RANGE);
}
/*
* If we're not logged in, hPrivateLeafKey and hPublicLeafKey
* should be NULL.
*/
if ((hPrivateLeafKey == NULL_HKEY) &&
(hPublicLeafKey == NULL_HKEY)) {
/* public session, wrap key with the PRK */
return (CKR_FUNCTION_FAILED);
}
} else if (hPrivateLeafKey != NULL_HKEY) {
/* logged in USER session */
/* get a random SHA1 hash for the auth data */
return (CKR_FUNCTION_FAILED);
}
} else {
/* logged in SO session */
/* get a random SHA1 hash for the auth data */
return (CKR_FUNCTION_FAILED);
}
}
hParentKey, &hKey))) {
return (result);
}
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (rc);
}
return (rc);
}
/* grab the public key to put into the public key object */
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (result);
}
/* add the public key blob to the object template */
return (rc);
}
/* add the public key blob to the object template */
return (rc);
}
/* wrap the authdata and put it into an object */
}
return (rc);
}
static CK_RV
{
if (hPrivateLeafKey != NULL_HKEY) {
} else {
return (CKR_FUNCTION_FAILED);
}
return (CKR_TEMPLATE_INCOMPLETE);
}
CKA_IBM_OPAQUE, &attr);
/*
* A public key cannot use the OPAQUE data attribute so they
* must be created in software. A private key may not yet
* have its "opaque" data defined and needs to be created
* and loaded so it can be used inside the TPM.
*/
return (CKR_FUNCTION_FAILED);
return (rc);
}
}
/*
* If this is a private key, get the blob and load it in the TPM.
* If it is public, the key is already loaded in software.
*/
if (class == CKO_PRIVATE_KEY) {
/* If we already have a handle, just load it */
if (result) {
stlogit("Tspi_Context_LoadKeyByBlob: "
"0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
} else {
/* try again to get the CKA_IBM_OPAQUE attr */
return (rc);
}
phKey))) {
stlogit("Tspi_Context_LoadKeyByBlob: "
"0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
}
}
/* auth data may be required */
if ((hPrivateLeafKey == NULL_HKEY) &&
(hPublicLeafKey == NULL_HKEY)) {
return (CKR_FUNCTION_FAILED);
} else if (hPublicLeafKey != NULL_HKEY) {
} else {
}
hParentKey, &authData))) {
return (CKR_FUNCTION_FAILED);
}
TSS_POLICY_USAGE, &hPolicy))) {
stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/*
* If the policy handle returned is the same as the
* context's default policy, then a new policy must
* be created and assigned to the key. Otherwise, just set the
* secret in the policy.
*/
if (hPolicy == hDefaultPolicy) {
&hPolicy))) {
stlogit("Tspi_Context_CreateObject: "
"0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
SHA1_DIGEST_LENGTH, authData))) {
stlogit("Tspi_Policy_SetSecret: "
"0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
*phKey))) {
stlogit("Tspi_Policy_AssignToObject: "
"0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
}
return (CKR_OK);
}
{
/* push the data into the encrypted data object */
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/*
* Figure out the modulus size so we can break the data
* into smaller chunks if necessary.
*/
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (result);
}
/* we don't need the actual modulus */
outlen = 0;
while (remain > 0) {
stlogit("Tspi_SetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* unbind the data, receiving the plaintext back */
stlogit("Tspi_Data_Unbind: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (CKR_BUFFER_TOO_SMALL);
}
}
*out_data_len = outlen;
return (CKR_OK);
}
{
return (rc);
}
return (rc);
}
{
return (rc);
}
/* Create the hash object we'll use to sign */
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* Insert the data into the hash object */
in_data))) {
stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* Verify */
if (result != TSS_SUCCESS &&
stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s",
}
} else {
}
return (rc);
}
{
return (rc);
}
/* Create the hash object we'll use to sign */
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* Insert the data into the hash object */
in_data))) {
stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/* Sign */
stlogit("Tspi_Hash_Sign: 0x%0x - %s",
return (CKR_DATA_LEN_RANGE);
}
if (sig_len > *out_data_len) {
return (CKR_BUFFER_TOO_SMALL);
}
*out_data_len = sig_len;
return (CKR_OK);
}
{
stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
/*
* Figure out the modulus size so we can break the data
* into smaller chunks if necessary.
*/
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (result);
}
/* we don't need the actual modulus */
/*
* According to TSS spec for Tspi_Data_Bind (4.3.4.21.5),
* Max input data size varies depending on the key type and
* encryption scheme.
*/
stlogit("Cannot find USAGE: %s\n",
return (result);
}
stlogit("Cannot find ENCSCHEME: %s\n",
return (result);
}
switch (scheme) {
case TSS_ES_RSAESPKCSV15:
if (keyusage == TSS_KEYUSAGE_BIND)
maxsize = 16;
else /* legacy */
maxsize = 11;
break;
maxsize = 47;
break;
default:
maxsize = 0;
}
outlen = 0;
while (remain > 0) {
stlogit("Tspi_Data_Bind: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
&dataBlobSize, &dataBlob))) {
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
return (CKR_DATA_LEN_RANGE);
}
outlen += dataBlobSize;
}
*out_data_len = outlen;
return (CKR_OK);
}
{
return (rc);
}
return (rc);
}
/*
* RSA Verify Recover
*
* Public key crypto is done in software, not by the TPM.
* We bypass the TSPI library here in favor of calls directly
* to OpenSSL because we don't want to add any padding, the in_data (signature)
* already contains the data stream to be decrypted and is already
* padded and formatted correctly.
*/
{
int i;
return (rc);
}
stlogit("Tspi_GetAttribData: 0x%0x - %s",
return (CKR_FUNCTION_FAILED);
}
if (in_data_len != modLen) {
goto end;
}
goto end;
}
goto end;
}
/* use RSA_NO_PADDING because the data is already padded (PKCS1) */
if (sslrv == -1) {
goto end;
}
/* Strip leading 0's before stripping the padding */
for (i = 0; i < sslrv; i++)
if (outdata[i] != 0)
break;
/* Use OpenSSL function for stripping PKCS#1 padding */
if (sslrv < 0) {
goto end;
}
if (*out_data_len < sslrv) {
*out_data_len = 0;
goto end;
}
/* The return code indicates the number of bytes remaining */
*out_data_len = sslrv;
end:
if (rsa)
return (rc);
}