#include <strings.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include <sys/crypto/common.h>
#include <arcfour.h>
#include "softGlobal.h"
#include "softSession.h"
#include <aes_impl.h>
#include <blowfish_impl.h>
#include <des_impl.h>
#include <ecc_impl.h>
#include "softDH.h"
#include "softObject.h"
#include "softKeystore.h"
#include "softKeystoreUtil.h"
static CK_MECHANISM_TYPE soft_mechanisms[] = {
CKM_DES_CBC,
CKM_DES_CBC_PAD,
CKM_DES_ECB,
CKM_DES_KEY_GEN,
CKM_DES_MAC_GENERAL,
CKM_DES_MAC,
CKM_DES3_CBC,
CKM_DES3_CBC_PAD,
CKM_DES3_ECB,
CKM_DES2_KEY_GEN,
CKM_DES3_KEY_GEN,
CKM_AES_CBC,
CKM_AES_CBC_PAD,
CKM_AES_CTR,
CKM_AES_CMAC_GENERAL,
CKM_AES_CMAC,
CKM_AES_ECB,
CKM_AES_KEY_GEN,
CKM_AES_GCM,
CKM_AES_GMAC,
CKM_AES_CCM,
CKM_BLOWFISH_CBC,
CKM_BLOWFISH_KEY_GEN,
CKM_SHA_1,
CKM_SHA_1_HMAC,
CKM_SHA_1_HMAC_GENERAL,
CKM_SHA256,
CKM_SHA256_HMAC,
CKM_SHA256_HMAC_GENERAL,
CKM_SHA384,
CKM_SHA384_HMAC,
CKM_SHA384_HMAC_GENERAL,
CKM_SHA512,
CKM_SHA512_HMAC,
CKM_SHA512_HMAC_GENERAL,
CKM_SHA512_224,
CKM_SHA512_256,
CKM_SSL3_SHA1_MAC,
CKM_MD5,
CKM_MD5_HMAC,
CKM_MD5_HMAC_GENERAL,
CKM_SSL3_MD5_MAC,
CKM_RC4,
CKM_RC4_KEY_GEN,
CKM_DSA,
CKM_DSA_SHA1,
CKM_DSA_KEY_PAIR_GEN,
CKM_RSA_PKCS,
CKM_RSA_PKCS_KEY_PAIR_GEN,
CKM_RSA_X_509,
CKM_MD5_RSA_PKCS,
CKM_SHA1_RSA_PKCS,
CKM_SHA256_RSA_PKCS,
CKM_SHA384_RSA_PKCS,
CKM_SHA512_RSA_PKCS,
CKM_DH_PKCS_KEY_PAIR_GEN,
CKM_DH_PKCS_DERIVE,
CKM_MD5_KEY_DERIVATION,
CKM_SHA1_KEY_DERIVATION,
CKM_SHA256_KEY_DERIVATION,
CKM_SHA384_KEY_DERIVATION,
CKM_SHA512_KEY_DERIVATION,
CKM_SHA512_224_KEY_DERIVATION,
CKM_SHA512_256_KEY_DERIVATION,
CKM_PBE_SHA1_RC4_128,
CKM_PKCS5_PBKD2,
CKM_SSL3_PRE_MASTER_KEY_GEN,
CKM_TLS_PRE_MASTER_KEY_GEN,
CKM_SSL3_MASTER_KEY_DERIVE,
CKM_TLS_MASTER_KEY_DERIVE,
CKM_SSL3_MASTER_KEY_DERIVE_DH,
CKM_TLS_MASTER_KEY_DERIVE_DH,
CKM_SSL3_KEY_AND_MAC_DERIVE,
CKM_TLS_KEY_AND_MAC_DERIVE,
CKM_TLS_PRF,
CKM_EC_KEY_PAIR_GEN,
CKM_ECDSA,
CKM_ECDSA_SHA1,
CKM_ECDH1_DERIVE
};
static CK_MECHANISM_INFO soft_mechanism_info[] = {
{DES_MINBYTES, DES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES_MINBYTES, DES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES_MINBYTES, DES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES_MINBYTES, DES_MAXBYTES,
CKF_GENERATE},
{DES_MINBYTES, DES_MAXBYTES,
CKF_SIGN|CKF_VERIFY},
{DES_MINBYTES, DES_MAXBYTES,
CKF_SIGN|CKF_VERIFY},
{DES3_MINBYTES, DES3_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES3_MINBYTES, DES3_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES3_MINBYTES, DES3_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{DES2_MAXBYTES, DES2_MAXBYTES,
CKF_GENERATE},
{DES3_MAXBYTES, DES3_MAXBYTES,
CKF_GENERATE},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{AES_MINBYTES, AES_MAXBYTES,
CKF_SIGN|CKF_VERIFY},
{AES_MINBYTES, AES_MAXBYTES,
CKF_SIGN|CKF_VERIFY},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{AES_MINBYTES, AES_MAXBYTES,
CKF_GENERATE},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_SIGN|CKF_VERIFY},
{AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{BLOWFISH_MINBYTES, BLOWFISH_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP},
{BLOWFISH_MINBYTES, BLOWFISH_MAXBYTES,
CKF_GENERATE},
{0, 0, CKF_DIGEST},
{1, 64, CKF_SIGN|CKF_VERIFY},
{1, 64, CKF_SIGN|CKF_VERIFY},
{0, 0, CKF_DIGEST},
{1, 64, CKF_SIGN|CKF_VERIFY},
{1, 64, CKF_SIGN|CKF_VERIFY},
{0, 0, CKF_DIGEST},
{1, 128, CKF_SIGN|CKF_VERIFY},
{1, 128, CKF_SIGN|CKF_VERIFY},
{0, 0, CKF_DIGEST},
{1, 128, CKF_SIGN|CKF_VERIFY},
{1, 128, CKF_SIGN|CKF_VERIFY},
{0, 0, CKF_DIGEST},
{0, 0, CKF_DIGEST},
{1, 512, CKF_SIGN|CKF_VERIFY},
{0, 0, CKF_DIGEST},
{1, 64, CKF_SIGN|CKF_VERIFY},
{1, 64, CKF_SIGN|CKF_VERIFY},
{1, 512, CKF_SIGN|CKF_VERIFY},
{8, ARCFOUR_MAX_KEY_BITS, CKF_ENCRYPT|CKF_DECRYPT},
{8, ARCFOUR_MAX_KEY_BITS, CKF_GENERATE },
{512, 1024, CKF_SIGN|CKF_VERIFY},
{512, 1024, CKF_SIGN|CKF_VERIFY},
{512, 1024, CKF_GENERATE_KEY_PAIR},
{256, 4096, CKF_ENCRYPT|CKF_DECRYPT|
CKF_SIGN|CKF_SIGN_RECOVER|
CKF_WRAP|CKF_UNWRAP|
CKF_VERIFY|CKF_VERIFY_RECOVER},
{256, 4096, CKF_GENERATE_KEY_PAIR},
{256, 4096, CKF_ENCRYPT|CKF_DECRYPT|
CKF_SIGN|CKF_SIGN_RECOVER|
CKF_WRAP|CKF_UNWRAP|
CKF_VERIFY|CKF_VERIFY_RECOVER},
{256, 4096, CKF_SIGN|CKF_VERIFY},
{256, 4096, CKF_SIGN|CKF_VERIFY},
{256, 4096, CKF_SIGN|CKF_VERIFY},
{256, 4096, CKF_SIGN|CKF_VERIFY},
{256, 4096, CKF_SIGN|CKF_VERIFY},
{DH_MIN_KEY_LEN, DH_MAX_KEY_LEN, CKF_GENERATE_KEY_PAIR},
{DH_MIN_KEY_LEN, DH_MAX_KEY_LEN, CKF_DERIVE},
{1, 16, CKF_DERIVE},
{1, 20, CKF_DERIVE},
{1, 32, CKF_DERIVE},
{1, 48, CKF_DERIVE},
{1, 64, CKF_DERIVE},
{1, 28, CKF_DERIVE},
{1, 32, CKF_DERIVE},
{0, 0, CKF_GENERATE},
{0, 0, CKF_GENERATE},
{48, 48, CKF_GENERATE},
{48, 48, CKF_GENERATE},
{48, 48, CKF_DERIVE},
{48, 48, CKF_DERIVE},
{48, 48, CKF_DERIVE},
{48, 48, CKF_DERIVE},
{0, 0, CKF_DERIVE},
{0, 0, CKF_DERIVE},
{0, 0, CKF_DERIVE},
{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_GENERATE_KEY_PAIR},
{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_SIGN|CKF_VERIFY},
{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_SIGN|CKF_VERIFY},
{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_DERIVE}
};
CK_RV
C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount)
{
CK_RV rv;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (pulCount == NULL) {
return (CKR_ARGUMENTS_BAD);
}
if (pSlotList == NULL) {
*pulCount = 1;
return (CKR_OK);
}
if ((*pulCount < 1) && (pSlotList != NULL)) {
rv = CKR_BUFFER_TOO_SMALL;
} else {
pSlotList[0] = SOFTTOKEN_SLOTID;
rv = CKR_OK;
}
*pulCount = 1;
return (rv);
}
CK_RV
C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (pInfo == NULL)
return (CKR_ARGUMENTS_BAD);
if (slotID != SOFTTOKEN_SLOTID)
return (CKR_SLOT_ID_INVALID);
(void) strncpy((char *)pInfo->slotDescription, SOFT_SLOT_DESCRIPTION,
64);
(void) strncpy((char *)pInfo->manufacturerID, SOFT_MANUFACTURER_ID, 32);
pInfo->flags = CKF_TOKEN_PRESENT;
pInfo->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
pInfo->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
pInfo->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
pInfo->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
return (CKR_OK);
}
CK_RV
C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
{
boolean_t pin_initialized = B_FALSE;
char *ks_cryptpin = NULL;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (slotID != SOFTTOKEN_SLOTID)
return (CKR_SLOT_ID_INVALID);
if (pInfo == NULL)
return (CKR_ARGUMENTS_BAD);
pInfo->flags = SOFT_TOKEN_FLAGS;
if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE) {
pInfo->flags |= CKF_WRITE_PROTECTED;
} else {
if ((soft_keystore_pin_initialized(&pin_initialized,
&ks_cryptpin, B_FALSE) == CKR_OK) && !pin_initialized)
pInfo->flags |= CKF_USER_PIN_TO_BE_CHANGED;
}
if (ks_cryptpin != NULL) {
size_t cplen = strlen(ks_cryptpin) + 1;
freezero(ks_cryptpin, cplen);
}
(void) strncpy((char *)pInfo->label, SOFT_TOKEN_LABEL, 32);
(void) strncpy((char *)pInfo->manufacturerID, SOFT_MANUFACTURER_ID, 32);
(void) strncpy((char *)pInfo->model, TOKEN_MODEL, 16);
(void) strncpy((char *)pInfo->serialNumber, SOFT_TOKEN_SERIAL, 16);
pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
pInfo->ulSessionCount = soft_session_cnt;
pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
pInfo->ulRwSessionCount = soft_session_rw_cnt;
pInfo->ulMaxPinLen = MAX_PIN_LEN;
pInfo->ulMinPinLen = MIN_PIN_LEN;
pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
pInfo->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
pInfo->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
pInfo->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
pInfo->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
(void) memset(pInfo->utcTime, ' ', 16);
return (CKR_OK);
}
CK_RV
C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
{
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_FUNCTION_NOT_SUPPORTED);
}
CK_RV
C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
CK_ULONG_PTR pulCount)
{
ulong_t i;
ulong_t mechnum;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (slotID != SOFTTOKEN_SLOTID)
return (CKR_SLOT_ID_INVALID);
if (pulCount == NULL)
return (CKR_ARGUMENTS_BAD);
mechnum = sizeof (soft_mechanisms) / sizeof (CK_MECHANISM_TYPE);
if (pMechanismList == NULL) {
*pulCount = mechnum;
return (CKR_OK);
}
if (*pulCount < mechnum) {
*pulCount = mechnum;
return (CKR_BUFFER_TOO_SMALL);
}
for (i = 0; i < mechnum; i++) {
pMechanismList[i] = soft_mechanisms[i];
}
*pulCount = mechnum;
return (CKR_OK);
}
CK_RV
C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo)
{
ulong_t i;
ulong_t mechnum;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (slotID != SOFTTOKEN_SLOTID)
return (CKR_SLOT_ID_INVALID);
if (pInfo == NULL) {
return (CKR_ARGUMENTS_BAD);
}
mechnum = sizeof (soft_mechanisms) / sizeof (CK_MECHANISM_TYPE);
for (i = 0; i < mechnum; i++) {
if (soft_mechanisms[i] == type)
break;
}
if (i == mechnum)
return (CKR_MECHANISM_INVALID);
pInfo->ulMinKeySize = soft_mechanism_info[i].ulMinKeySize;
pInfo->ulMaxKeySize = soft_mechanism_info[i].ulMaxKeySize;
pInfo->flags = soft_mechanism_info[i].flags;
return (CKR_OK);
}
CK_RV
C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
CK_UTF8CHAR_PTR pLabel)
{
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
if (create_keystore() != 0)
return (CKR_FUNCTION_FAILED);
return (CKR_OK);
}
CK_RV
C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
{
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_FUNCTION_NOT_SUPPORTED);
}
CK_RV
C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
{
soft_session_t *session_p;
CK_RV rv;
boolean_t lock_held = B_FALSE;
if (!softtoken_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
rv = handle2session(hSession, &session_p);
if (rv != CKR_OK)
return (rv);
if (!soft_keystore_status(KEYSTORE_LOAD)) {
SES_REFRELE(session_p, lock_held);
return (CKR_DEVICE_REMOVED);
}
if ((ulOldPinLen < MIN_PIN_LEN) || (ulOldPinLen > MAX_PIN_LEN) ||
(ulNewPinLen < MIN_PIN_LEN) ||(ulNewPinLen > MAX_PIN_LEN)) {
SES_REFRELE(session_p, lock_held);
return (CKR_PIN_LEN_RANGE);
}
if ((pOldPin == NULL_PTR) || (pNewPin == NULL_PTR)) {
SES_REFRELE(session_p, lock_held);
return (CKR_ARGUMENTS_BAD);
}
if ((session_p->state != CKS_RW_PUBLIC_SESSION) &&
(session_p->state != CKS_RW_USER_FUNCTIONS)) {
SES_REFRELE(session_p, lock_held);
return (CKR_SESSION_READ_ONLY);
}
rv = soft_setpin(pOldPin, ulOldPinLen, pNewPin, ulNewPinLen);
SES_REFRELE(session_p, lock_held);
return (rv);
}