/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
*/
#include <kmfapiP.h>
#include <sha1.h>
#include <security/cryptoki.h>
#include <ber_der.h>
typedef struct
{
} ALG_INFO;
/*
* For RSA, the verify can be done using a single mechanism,
* but signing must be done separately because not all hardware
* tokens support the combined hash+key operations.
*/
};
{
sizeof (alg_info_map) / sizeof (ALG_INFO);
if (keytype)
if (hashmech)
if (signmech)
*signmech =
return (KMF_OK);
}
}
/* no match */
return (KMF_ERR_BAD_ALGORITHM);
}
{
int i;
return (ret);
goto out;
}
goto out;
}
goto out;
}
for (i = 0; i < pulCount; i++) {
break;
}
if (i < pulCount) {
}
} else {
}
out:
return (kmf_rv);
}
/*
* Name: PKCS_AddTemplate
*
* Description:
* Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will
* not expand the array beyond the maximum specified size.
*
* Returns:
* TRUE - Attribute value succesfully added.
* FALSE - Maximum array size would be exceded.
*/
static int
{
if (*ckNumTemplates >= ckMaxTemplates) {
return (FALSE);
}
(*ckNumTemplates)++;
return (TRUE);
}
/*
* Convert an SPKI data record to PKCS#11
* public key object.
*/
static KMF_RETURN
const KMF_X509_SPKI *pKey,
{
/* Common object attributes */
/* Common key attributes */
/* Common public key attributes */
/* Key part array */
/* Parse the keyblob */
if (AlgorithmId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
return (mrReturn);
/* Fill in the common object attributes */
sizeof (ckObjClass)) ||
sizeof (ckToken)) ||
sizeof (ckPrivate))) {
goto cleanup;
}
/* Fill in the common key attributes */
goto cleanup;
}
sizeof (ckKeyType)) ||
sizeof (ckDerive))) {
goto cleanup;
}
/* Add common public key attributes */
sizeof (ckEncrypt)) ||
sizeof (ckVerify)) ||
sizeof (ckWrap))) {
goto cleanup;
}
/* Add algorithm specific attributes */
switch (ckKeyType) {
case CKK_RSA:
goto cleanup;
}
break;
case CKK_DSA:
goto cleanup;
}
break;
case CKK_EC:
goto cleanup;
}
break;
default:
}
/* Instantiate the object */
}
for (i = 0; i < uNumKeyParts; i++) {
kmf_free_data(&KeyParts[i]);
}
return (mrReturn);
}
/*
* PKCS_AcquirePublicKeyHandle
*
* Given an assymetric key keyblob, attempts to find the appropriate
* public key.
*
* Methods of finding the public key:
* - Public Key with data present:
* Parses the key and creates a temporary session object.
* - Public Key with handle:
* The handle is type converted and returned. Validity of the handle is
* not checked.
* - Public Key with label:
* Attempts to find a public key with the corresponding label.
*/
static KMF_RETURN
const KMF_X509_SPKI *pKey,
{
/* Key searching variables */
sizeof (CK_ATTRIBUTE));
/* Extract the data from the SPKI into individual fields */
return (mrReturn);
/* Fetch the key class and algorithm from the object */
ckNumTemplates = 0;
sizeof (ckObjClass)) ||
sizeof (ckKeyType))) {
return (KMF_ERR_INTERNAL);
}
return (ckRv);
}
/* Make sure the results match the expected values */
if ((ckKeyType != ckRequestedKeyType) ||
(ckObjClass != CKO_PUBLIC_KEY)) {
return (KMF_ERR_BAD_KEY_FORMAT);
}
/* Set the return values */
return (KMF_OK);
}
/*
* Utility routine for verifying generic data using
* the cryptographic framework (PKCS#11).
* There are situations where we want to force this
* operation to happen in a specific keystore.
* For example:
* libelfsign.so.1 verifies signatures on crypto libraries.
* We must use pkcs11 functions to verify the pkcs11
* plugins in order to keep the validation within the
* Cryptographic Framework's FIPS-140 boundary. To avoid
* a circular dependency, pksc11_softtoken.so.1 is
* interposed by libkcfd.so.1 via kcfd, which prevents
* libpkcs11.so.1's interfaces from being used when libkmf.so.1
* is called from kcfd.
*
* This also saves code and time because verify operations
* only use public keys and do not need acccess to any
* keystore specific functions.
*/
{
if (AlgorithmId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
return (KMF_ERR_BAD_ALGORITHM);
/*
* mechanisms.
*/
return (rv);
/* Fetch the verifying key */
(void) C_CloseSession(ckSession);
return (rv);
}
/*
* For some mechanisms, we must compute the hash separately
* and then do the verify.
*/
if (hashmech != 0 &&
mechtype == CKM_RSA_PKCS)) {
(mechtype == CKM_RSA_PKCS));
if (rv)
goto cleanup;
}
hashmech == CKM_SHA256) {
/*
* FIPS 186-3 says that when using DSA
* the hash must be truncated to the size of the
* subprime.
*/
goto cleanup;
}
}
goto cleanup;
}
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (rv);
}
{
sizeof (CK_ATTRIBUTE));
return (KMF_ERR_BAD_ALGORITHM);
return (rv);
/* Get the public key used in encryption */
keytype, &ckKeyHandle);
(void) C_CloseSession(ckSession);
return (rv);
}
/* Get the modulus length */
ckNumTemplates = 0;
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_BUFFER_SIZE);
}
/* Compute the fixed input data length for single-part encryption */
for (i = 0; i < blocks; i++) {
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
in_data += block_size;
}
/* Encrypt the remaining data */
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
}
}
if (ckKeyHandle != 0)
(void) C_CloseSession(ckSession);
return (rv);
}
static void
{
}
{
int i;
return (KMF_ERR_BAD_PARAMETER);
return (KMF_ERR_MEMORY);
if (algId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
return (rv);
/* Check the KEY algorithm */
if (algId == KMF_ALGID_RSA) {
} else if (algId == KMF_ALGID_DSA) {
} else if (algId == KMF_ALGID_SHA1WithECDSA ||
algId == KMF_ALGID_ECDSA) {
} else {
/* We only support RSA and DSA keys for now */
}
for (i = 0; i < uNumKeyParts; i++) {
}
}
return (rv);
}
/*
* For PKCS1 encoding (necessary for RSA signatures), we
* must prepend the following prefixes before computing
* the digest.
*/
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
};
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
0x04, 0x10
};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
0x00, 0x04, 0x30};
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
0x00, 0x04, 0x40};
/*
* Compute hashes using metaslot (or softtoken).
* Signing operations so it is safer to separate the hashing
* from the signing. This function generates a hash using a
* separate session. The resulting digest can be signed later.
*/
{
sizeof (SHA512_DER_PREFIX)];
mechanism.ulParameterLen = 0;
goto end;
}
}
if (pkcs1_encoding) {
int pfxlen;
switch (mechtype) {
case CKM_MD5:
pfxlen = sizeof (MD5_DER_PREFIX);
break;
case CKM_SHA_1:
pfxlen = sizeof (SHA1_DER_PREFIX);
break;
case CKM_SHA256:
pfxlen = sizeof (SHA256_DER_PREFIX);
break;
case CKM_SHA384:
pfxlen = sizeof (SHA384_DER_PREFIX);
break;
case CKM_SHA512:
pfxlen = sizeof (SHA512_DER_PREFIX);
break;
default:
goto end;
}
} else {
}
end:
return (rv);
}