summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorwyllys <none@none>2007-03-03 05:56:22 -0800
committerwyllys <none@none>2007-03-03 05:56:22 -0800
commit02744e811b15322c5f109827a116c33bfe3438b5 (patch)
treeb148880f0bcec1897d728c7e93c81233cd394131 /usr
parent3779d2d24dac3a9a84c5eefdeee36f7559299b2c (diff)
downloadillumos-gate-02744e811b15322c5f109827a116c33bfe3438b5.tar.gz
6523959 KMF needs keystore specific Verify operations
--HG-- rename : usr/src/lib/libkmf/include/oidsalg.h => deleted_files/usr/src/lib/libkmf/include/oidsalg.h
Diffstat (limited to 'usr')
-rw-r--r--usr/src/lib/libkmf/include/kmfapi.h5
-rw-r--r--usr/src/lib/libkmf/include/kmfapiP.h33
-rw-r--r--usr/src/lib/libkmf/include/kmftypes.h47
-rw-r--r--usr/src/lib/libkmf/include/oidsalg.h52
-rw-r--r--usr/src/lib/libkmf/libkmf/common/algoid.c19
-rw-r--r--usr/src/lib/libkmf/libkmf/common/certop.c201
-rw-r--r--usr/src/lib/libkmf/libkmf/common/generalop.c47
-rw-r--r--usr/src/lib/libkmf/libkmf/common/kmfoids.c25
-rw-r--r--usr/src/lib/libkmf/libkmf/common/mapfile-vers12
-rw-r--r--usr/src/lib/libkmf/libkmf/common/pk11keys.c2
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c2
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c491
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c179
13 files changed, 867 insertions, 248 deletions
diff --git a/usr/src/lib/libkmf/include/kmfapi.h b/usr/src/lib/libkmf/include/kmfapi.h
index c7506ab9e6..fd29b0733c 100644
--- a/usr/src/lib/libkmf/include/kmfapi.h
+++ b/usr/src/lib/libkmf/include/kmfapi.h
@@ -85,6 +85,8 @@ extern KMF_RETURN KMF_FindCert(KMF_HANDLE_T, KMF_FINDCERT_PARAMS *,
extern KMF_RETURN KMF_EncodeCertRecord(KMF_X509_CERTIFICATE *,
KMF_DATA *);
+extern KMF_RETURN KMF_DecodeCertData(KMF_DATA *, KMF_X509_CERTIFICATE **);
+
extern KMF_RETURN KMF_SignCertWithKey(KMF_HANDLE_T, const KMF_DATA *,
KMF_KEY_HANDLE *, KMF_DATA *);
extern KMF_RETURN KMF_SignCertWithCert(KMF_HANDLE_T,
@@ -98,7 +100,8 @@ extern KMF_RETURN KMF_VerifyCertWithKey(KMF_HANDLE_T, KMF_KEY_HANDLE *,
const KMF_DATA *);
extern KMF_RETURN KMF_VerifyCertWithCert(KMF_HANDLE_T, const KMF_DATA *,
const KMF_DATA *);
-extern KMF_RETURN KMF_VerifyDataWithCert(KMF_HANDLE_T, KMF_DATA *, KMF_DATA *,
+extern KMF_RETURN KMF_VerifyDataWithCert(KMF_HANDLE_T,
+ KMF_KEYSTORE_TYPE, KMF_ALGORITHM_INDEX, KMF_DATA *, KMF_DATA *,
const KMF_DATA *);
extern KMF_RETURN KMF_EncryptWithCert(KMF_HANDLE_T, KMF_DATA *,
diff --git a/usr/src/lib/libkmf/include/kmfapiP.h b/usr/src/lib/libkmf/include/kmfapiP.h
index 64b524b6a7..e20df89348 100644
--- a/usr/src/lib/libkmf/include/kmfapiP.h
+++ b/usr/src/lib/libkmf/include/kmfapiP.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _KMFAPIP_H
@@ -162,6 +162,13 @@ typedef struct {
KMF_SETPIN_PARAMS *,
KMF_CREDENTIAL *);
+ KMF_RETURN (*VerifyDataWithCert) (
+ KMF_HANDLE_T,
+ KMF_ALGORITHM_INDEX,
+ KMF_DATA *,
+ KMF_DATA *,
+ KMF_DATA *);
+
void (*Finalize) ();
} KMF_PLUGIN_FUNCLIST;
@@ -218,29 +225,10 @@ typedef struct _kmf_handle {
KMF_PLUGIN_FUNCLIST *KMF_Plugin_Initialize();
KMF_RETURN
-SignCert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *, KMF_DATA *);
-
-KMF_RETURN
-VerifyCertWithKey(KMF_HANDLE_T, KMF_DATA *, const KMF_DATA *);
-
-KMF_RETURN
-VerifyCertWithCert(KMF_HANDLE_T, const KMF_DATA *, const KMF_DATA *);
-
-KMF_RETURN
-VerifyDataWithCert(KMF_HANDLE_T, KMF_DATA *, KMF_DATA *, const KMF_DATA *);
-
-KMF_RETURN
VerifyDataWithKey(KMF_HANDLE_T, KMF_DATA *, KMF_ALGORITHM_INDEX, KMF_DATA *,
KMF_DATA *);
KMF_RETURN
-EncryptWithCert(KMF_HANDLE_T, KMF_DATA *, KMF_DATA *, KMF_DATA *);
-
-KMF_RETURN
-DecryptWithCert(KMF_HANDLE_T, KMF_DATA *, KMF_KEY_HANDLE *, KMF_DATA *,
- KMF_DATA *);
-
-KMF_RETURN
SignCsr(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *,
KMF_X509_ALGORITHM_IDENTIFIER *, KMF_DATA *);
@@ -265,8 +253,11 @@ KMF_PLUGIN *FindPlugin(KMF_HANDLE_T, KMF_KEYSTORE_TYPE);
KMF_BOOL IsEqualOid(KMF_OID *, KMF_OID *);
KMF_OID *X509_AlgIdToAlgorithmOid(KMF_ALGORITHM_INDEX);
-
KMF_ALGORITHM_INDEX X509_AlgorithmOidToAlgId(KMF_OID *);
+KMF_RETURN PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
+ const KMF_X509_SPKI *, CK_KEY_TYPE, CK_OBJECT_HANDLE *,
+ KMF_BOOL *);
+
KMF_RETURN GetIDFromSPKI(KMF_X509_SPKI *, KMF_DATA *);
CK_RV DigestData(CK_SESSION_HANDLE, KMF_DATA *, KMF_DATA *);
diff --git a/usr/src/lib/libkmf/include/kmftypes.h b/usr/src/lib/libkmf/include/kmftypes.h
index c2e954c981..dc4a1f2b33 100644
--- a/usr/src/lib/libkmf/include/kmftypes.h
+++ b/usr/src/lib/libkmf/include/kmftypes.h
@@ -106,6 +106,22 @@ typedef enum {
KMF_KU_ENCRYPT_DATA = 2
} KMF_KU_PURPOSE;
+/*
+ * Algorithms
+ * This type defines a set of constants used to identify cryptographic
+ * algorithms.
+ */
+typedef enum {
+ KMF_ALGID_NONE = 0,
+ KMF_ALGID_CUSTOM,
+ KMF_ALGID_SHA1,
+ KMF_ALGID_RSA,
+ KMF_ALGID_DSA,
+ KMF_ALGID_MD5WithRSA,
+ KMF_ALGID_MD2WithRSA,
+ KMF_ALGID_SHA1WithRSA,
+ KMF_ALGID_SHA1WithDSA
+} KMF_ALGORITHM_INDEX;
/* Keystore Configuration */
typedef struct {
@@ -204,6 +220,7 @@ typedef struct {
typedef struct {
KMF_KEYSTORE_TYPE kstype;
KMF_DATA *certificate;
+ KMF_BIGINT *serial;
KMF_DATA *ocsp_response;
union {
@@ -353,6 +370,7 @@ typedef struct {
KMF_CREDENTIAL cred;
KMF_ENCODE_FORMAT format; /* for key */
char *certLabel;
+ KMF_ALGORITHM_INDEX algid;
union {
KMF_NSS_PARAMS nss_opts;
KMF_OPENSSL_PARAMS openssl_opts;
@@ -625,23 +643,6 @@ typedef enum {
KMF_ALGCLASS_DERIVEKEY
} KMF_ALGCLASS;
-/*
- * Algorithms
- * This type defines a set of constants used to identify cryptographic
- * algorithms.
- */
-typedef enum {
- KMF_ALGID_NONE = 0,
- KMF_ALGID_CUSTOM,
- KMF_ALGID_SHA1,
- KMF_ALGID_RSA,
- KMF_ALGID_DSA,
- KMF_ALGID_MD5WithRSA,
- KMF_ALGID_MD2WithRSA,
- KMF_ALGID_SHA1WithRSA,
- KMF_ALGID_SHA1WithDSA
-} KMF_ALGORITHM_INDEX;
-
typedef enum {
KMF_CERT_ISSUER = 1,
KMF_CERT_SUBJECT,
@@ -1303,7 +1304,17 @@ KMFOID_PKIX_KP_IPSecEndSystem,
KMFOID_PKIX_KP_IPSecTunnel,
KMFOID_PKIX_KP_IPSecUser,
KMFOID_PKIX_KP_TimeStamping,
-KMFOID_PKIX_KP_OCSPSigning;
+KMFOID_PKIX_KP_OCSPSigning,
+KMFOID_SHA1,
+KMFOID_RSA,
+KMFOID_DSA,
+KMFOID_MD5WithRSA,
+KMFOID_MD2WithRSA,
+KMFOID_SHA1WithRSA,
+KMFOID_SHA1WithDSA,
+KMFOID_OIW_DSAWithSHA1,
+KMFOID_X9CM_DSA,
+KMFOID_X9CM_DSAWithSHA1;
/*
* KMF Certificate validation codes. These may be masked together.
diff --git a/usr/src/lib/libkmf/include/oidsalg.h b/usr/src/lib/libkmf/include/oidsalg.h
deleted file mode 100644
index b0283f2ece..0000000000
--- a/usr/src/lib/libkmf/include/oidsalg.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
- *
- */
-
-#ifndef _OIDSALG_H
-#define _OIDSALG_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <kmftypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-uint8_t
- OID_OIW_SHA1[] = { OID_OIW_ALGORITHM, 26},
- OID_OIW_DSA[] = { OID_OIW_ALGORITHM, 12 },
- OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 27 },
- OID_RSAEncryption[] = { OID_PKCS_1, 1 },
- OID_MD2WithRSA[] = { OID_PKCS_1, 2 },
- OID_MD5WithRSA[] = { OID_PKCS_1, 4 },
- OID_SHA1WithRSA[] = { OID_PKCS_1, 5 },
- OID_X9CM_DSA[] = { OID_X9CM_X9ALGORITHM, 1 },
- OID_X9CM_DSAWithSHA1[] = { OID_X9CM_X9ALGORITHM, 3}
-;
-
-KMF_OID
- KMFOID_SHA1 = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_SHA1},
- KMFOID_RSA = {OID_PKCS_1_LENGTH+1, OID_RSAEncryption},
- KMFOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSA},
- KMFOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD5WithRSA},
- KMFOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD2WithRSA},
- KMFOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA1WithRSA},
- KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1},
- KMFOID_OIW_DSAWithSHA1 = {OID_OIW_ALGORITHM_LENGTH+1,
- OID_OIW_DSAWithSHA1},
- KMFOID_X9CM_DSA = {OID_X9CM_X9ALGORITHM_LENGTH+1, OID_X9CM_DSA},
- KMFOID_X9CM_DSAWithSHA1 = {OID_X9CM_X9ALGORITHM_LENGTH+1,
- OID_X9CM_DSAWithSHA1}
-
-;
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _OIDSALG_H */
diff --git a/usr/src/lib/libkmf/libkmf/common/algoid.c b/usr/src/lib/libkmf/libkmf/common/algoid.c
index 536e020474..d78541d1f0 100644
--- a/usr/src/lib/libkmf/libkmf/common/algoid.c
+++ b/usr/src/lib/libkmf/libkmf/common/algoid.c
@@ -12,7 +12,6 @@
#include <string.h>
#include <kmfapiP.h>
-#include <oidsalg.h>
typedef struct {
KMF_OID * AlgOID;
@@ -23,15 +22,15 @@ typedef struct {
* The following table defines the mapping of AlgOID's to AlgID's.
*/
static KMF_OID_ID ALGOID_ID_Table[] = {
- {&KMFOID_X9CM_DSA, KMF_ALGID_DSA},
- {&KMFOID_X9CM_DSAWithSHA1, KMF_ALGID_SHA1WithDSA},
- {&KMFOID_SHA1, KMF_ALGID_SHA1},
- {&KMFOID_RSA, KMF_ALGID_RSA},
- {&KMFOID_DSA, KMF_ALGID_DSA},
- {&KMFOID_MD5WithRSA, KMF_ALGID_MD5WithRSA},
- {&KMFOID_MD2WithRSA, KMF_ALGID_MD2WithRSA},
- {&KMFOID_SHA1WithRSA, KMF_ALGID_SHA1WithRSA},
- {&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA}
+ {(KMF_OID *)&KMFOID_X9CM_DSA, KMF_ALGID_DSA},
+ {(KMF_OID *)&KMFOID_X9CM_DSAWithSHA1, KMF_ALGID_SHA1WithDSA},
+ {(KMF_OID *)&KMFOID_SHA1, KMF_ALGID_SHA1},
+ {(KMF_OID *)&KMFOID_RSA, KMF_ALGID_RSA},
+ {(KMF_OID *)&KMFOID_DSA, KMF_ALGID_DSA},
+ {(KMF_OID *)&KMFOID_MD5WithRSA, KMF_ALGID_MD5WithRSA},
+ {(KMF_OID *)&KMFOID_MD2WithRSA, KMF_ALGID_MD2WithRSA},
+ {(KMF_OID *)&KMFOID_SHA1WithRSA, KMF_ALGID_SHA1WithRSA},
+ {(KMF_OID *)&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA}
};
#define NUM_ALGOIDS ((sizeof (ALGOID_ID_Table))/(sizeof (ALGOID_ID_Table[0])))
diff --git a/usr/src/lib/libkmf/libkmf/common/certop.c b/usr/src/lib/libkmf/libkmf/common/certop.c
index 16d17bfa16..508293785f 100644
--- a/usr/src/lib/libkmf/libkmf/common/certop.c
+++ b/usr/src/lib/libkmf/libkmf/common/certop.c
@@ -44,6 +44,15 @@
#define X509_FORMAT_VERSION 2
static KMF_RETURN
+SignCert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *, KMF_DATA *);
+
+static KMF_RETURN
+VerifyCertWithKey(KMF_HANDLE_T, KMF_DATA *, const KMF_DATA *);
+
+static KMF_RETURN
+VerifyCertWithCert(KMF_HANDLE_T, const KMF_DATA *, const KMF_DATA *);
+
+static KMF_RETURN
get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg)
{
KMF_RETURN rv;
@@ -273,6 +282,20 @@ KMF_EncodeCertRecord(KMF_X509_CERTIFICATE *CertData, KMF_DATA *encodedCert)
return (ret);
}
+KMF_RETURN
+KMF_DecodeCertData(KMF_DATA *rawcert, KMF_X509_CERTIFICATE **certrec)
+{
+ KMF_RETURN ret = KMF_OK;
+
+ if (rawcert == NULL || rawcert->Data == NULL ||
+ rawcert->Length == 0 || certrec == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ ret = DerDecodeSignedCertificate(rawcert, certrec);
+
+ return (ret);
+}
+
/*
*
* Name: KMF_SignCertWithKey
@@ -449,8 +472,15 @@ KMF_SignDataWithCert(KMF_HANDLE_T handle,
plugin = FindPlugin(handle, Signkey.kstype);
if (plugin != NULL && plugin->funclist->SignData != NULL) {
+ KMF_OID *oid;
+
+ if (params->algid != KMF_ALGID_NONE)
+ oid = X509_AlgIdToAlgorithmOid(params->algid);
+ else
+ oid = CERT_ALG_OID(SignerCert);
+
ret = plugin->funclist->SignData(handle, &Signkey,
- CERT_ALG_OID(SignerCert), tobesigned, output);
+ oid, tobesigned, output);
if (ret != KMF_OK)
goto cleanup;
@@ -612,11 +642,14 @@ KMF_VerifyCertWithCert(KMF_HANDLE_T handle,
*/
KMF_RETURN
KMF_VerifyDataWithCert(KMF_HANDLE_T handle,
+ KMF_KEYSTORE_TYPE kstype,
+ KMF_ALGORITHM_INDEX algid,
KMF_DATA *indata,
KMF_DATA *insig,
const KMF_DATA *SignerCert)
{
KMF_RETURN ret;
+ KMF_PLUGIN *plugin;
CLEAR_ERROR(handle, ret);
if (ret != KMF_OK)
@@ -631,7 +664,27 @@ KMF_VerifyDataWithCert(KMF_HANDLE_T handle,
if (ret != KMF_OK)
return (ret);
- return (VerifyDataWithCert(handle, indata, insig, SignerCert));
+ /*
+ * If NSS, use PKCS#11, we are not accessing the database(s),
+ * we just prefer the "verify" operation from the crypto framework.
+ * The OpenSSL version is unique in order to avoid a dependency loop
+ * with the kcfd(1M) process.
+ */
+ if (kstype == KMF_KEYSTORE_NSS)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ plugin = FindPlugin(handle, kstype);
+ if (plugin == NULL)
+ return (KMF_ERR_PLUGIN_NOTFOUND);
+
+ if (plugin->funclist->VerifyDataWithCert == NULL)
+ return (KMF_ERR_FUNCTION_NOT_FOUND);
+
+ CLEAR_ERROR(handle, ret);
+ ret = (plugin->funclist->VerifyDataWithCert(handle,
+ algid, indata, insig, (KMF_DATA *)SignerCert));
+
+ return (ret);
}
/*
@@ -663,6 +716,10 @@ KMF_EncryptWithCert(KMF_HANDLE_T handle,
KMF_DATA *ciphertext)
{
KMF_RETURN ret;
+ KMF_X509_CERTIFICATE *x509cert = NULL;
+ KMF_X509_SPKI *pubkey;
+ KMF_OID *alg;
+ KMF_ALGORITHM_INDEX algid;
CLEAR_ERROR(handle, ret);
if (ret != KMF_OK)
@@ -677,7 +734,31 @@ KMF_EncryptWithCert(KMF_HANDLE_T handle,
if (ret != KMF_OK)
return (ret);
- return (EncryptWithCert(handle, cert, plaintext, ciphertext));
+ /* Decode the cert so we can get the SPKI data */
+ if ((ret = DerDecodeSignedCertificate(cert, &x509cert)) != KMF_OK)
+ return (ret);
+
+ /* Get the public key info from the certificate */
+ pubkey = &x509cert->certificate.subjectPublicKeyInfo;
+
+ /* Use the algorithm in SPKI to encrypt data */
+ alg = &pubkey->algorithm.algorithm;
+
+ algid = X509_AlgorithmOidToAlgId(alg);
+
+ /* DSA does not support encrypt */
+ if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) {
+ KMF_FreeSignedCert(x509cert);
+ free(x509cert);
+ return (KMF_ERR_BAD_ALGORITHM);
+ }
+
+ ret = PKCS_EncryptData(handle, algid, pubkey, plaintext, ciphertext);
+
+ KMF_FreeSignedCert(x509cert);
+ free(x509cert);
+
+ return (ret);
}
/*
@@ -1775,8 +1856,6 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
goto out;
}
-
- (void) memset(&user_issuerDN, 0, sizeof (user_issuerDN));
if ((ret = KMF_DNParser(user_issuer, &user_issuerDN)) != KMF_OK) {
*result |= KMF_CERT_VALIDATE_ERR_USER;
goto out;
@@ -1808,7 +1887,7 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
KMF_FreeDN(&user_subjectDN);
/*
- * Check KeyUsage extension.
+ * Check KeyUsage extension of the subscriber's certificate
*/
ret = cert_ku_check(handle, pcert);
if (ret != KMF_OK) {
@@ -1817,7 +1896,7 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
}
/*
- * Validate Extended KeyUsage extension.
+ * Validate Extended KeyUsage extension
*/
ret = cert_eku_check(handle, pcert);
if (ret != KMF_OK) {
@@ -1826,7 +1905,7 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
}
/*
- * Check the certificate's validity period.
+ * Check the certificate's validity period
*
* This step is needed when "ignore_date" in policy is set
* to false.
@@ -1861,11 +1940,10 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
* TA certificate.
*/
if (self_signed) {
- ret = KMF_VerifyCertWithCert(handle,
- pcert, pcert);
+ ret = KMF_VerifyCertWithCert(handle, pcert, pcert);
} else {
ret = kmf_find_ta_cert(handle, params, &ta_cert,
- &user_issuerDN);
+ &user_issuerDN);
if (ret != KMF_OK) {
*result |= KMF_CERT_VALIDATE_ERR_TA;
goto out;
@@ -1873,7 +1951,6 @@ KMF_ValidateCert(KMF_HANDLE_T handle,
ret = KMF_VerifyCertWithCert(handle, pcert, &ta_cert);
}
-
if (ret != KMF_OK) {
*result |= KMF_CERT_VALIDATE_ERR_SIGNATURE;
goto out;
@@ -1924,7 +2001,6 @@ check_revocation:
goto out;
}
}
-
out:
if (user_issuer) {
KMF_FreeDN(&user_issuerDN);
@@ -2327,7 +2403,7 @@ copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
return (ret);
}
-KMF_RETURN
+static KMF_RETURN
SignCert(KMF_HANDLE_T handle,
const KMF_DATA *SubjectCert,
KMF_KEY_HANDLE *Signkey,
@@ -2436,7 +2512,7 @@ cleanup:
return (ret);
}
-KMF_RETURN
+static KMF_RETURN
VerifyCertWithKey(KMF_HANDLE_T handle,
KMF_DATA *derkey,
const KMF_DATA *CertToBeVerified)
@@ -2509,6 +2585,9 @@ cleanup:
return (ret);
}
+/*
+ * The key must be an ASN.1/DER encoded PKCS#1 key.
+ */
KMF_RETURN
VerifyDataWithKey(KMF_HANDLE_T handle,
KMF_DATA *derkey,
@@ -2535,7 +2614,7 @@ cleanup:
return (ret);
}
-KMF_RETURN
+static KMF_RETURN
VerifyCertWithCert(KMF_HANDLE_T handle,
const KMF_DATA *CertToBeVerifiedData,
const KMF_DATA *SignerCertData)
@@ -2623,58 +2702,6 @@ cleanup:
}
KMF_RETURN
-VerifyDataWithCert(KMF_HANDLE_T handle,
- KMF_DATA *indata,
- KMF_DATA *insig,
- const KMF_DATA *SignerCertData)
-{
- KMF_RETURN ret = KMF_OK;
- KMF_X509_CERTIFICATE *SignerCert = NULL;
- KMF_X509_SPKI *pubkey;
- KMF_ALGORITHM_INDEX algid;
-
- if (!indata ||
- !indata->Data ||
- !indata->Length)
- return (KMF_ERR_BAD_PARAMETER);
-
- if (!insig ||
- !insig->Data ||
- !insig->Length)
- return (KMF_ERR_BAD_PARAMETER);
-
-
- if (!SignerCertData ||
- !SignerCertData->Data ||
- !SignerCertData->Length)
- return (KMF_ERR_BAD_PARAMETER);
-
- /* Decode the signer cert so we can get the SPKI data */
- ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
- if (ret != KMF_OK)
- goto cleanup;
-
- /* Get the public key info from the signer certificate */
- pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
-
- algid = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert));
- if (algid == KMF_ALGID_NONE) {
- ret = KMF_ERR_BAD_ALGORITHM;
- } else {
- ret = PKCS_VerifyData(handle, algid,
- pubkey, indata, insig);
- }
-
-cleanup:
- if (SignerCert) {
- KMF_FreeSignedCert(SignerCert);
- free(SignerCert);
- }
-
- return (ret);
-}
-
-KMF_RETURN
SignCsr(KMF_HANDLE_T handle,
const KMF_DATA *SubjectCsr,
KMF_KEY_HANDLE *Signkey,
@@ -2749,41 +2776,3 @@ cleanup:
return (ret);
}
-
-KMF_RETURN
-EncryptWithCert(KMF_HANDLE_T handle,
- KMF_DATA *cert,
- KMF_DATA *plaintext,
- KMF_DATA *ciphertext)
-{
- KMF_RETURN ret = KMF_OK;
- KMF_X509_CERTIFICATE *x509cert = NULL;
- KMF_X509_SPKI *pubkey;
- KMF_OID *alg;
- KMF_ALGORITHM_INDEX algid;
-
- /* Decode the cert so we can get the SPKI data */
- if ((ret = DerDecodeSignedCertificate(cert, &x509cert)) != KMF_OK)
- return (ret);
-
- /* Get the public key info from the certificate */
- pubkey = &x509cert->certificate.subjectPublicKeyInfo;
-
- /* Use the algorithm in SPKI to encrypt data */
- alg = &pubkey->algorithm.algorithm;
-
- algid = X509_AlgorithmOidToAlgId(alg);
-
- /* DSA does not support encrypt */
- if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) {
- KMF_FreeSignedCert(x509cert);
- free(x509cert);
- return (KMF_ERR_BAD_ALGORITHM);
- }
-
- ret = PKCS_EncryptData(handle, algid, pubkey, plaintext, ciphertext);
- KMF_FreeSignedCert(x509cert);
- free(x509cert);
-
- return (ret);
-}
diff --git a/usr/src/lib/libkmf/libkmf/common/generalop.c b/usr/src/lib/libkmf/libkmf/common/generalop.c
index ad596856b1..a9bf418ed3 100644
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c
+++ b/usr/src/lib/libkmf/libkmf/common/generalop.c
@@ -687,6 +687,34 @@ KMF_OID2String(KMF_OID *oid)
return (bp);
}
+static boolean_t
+check_for_pem(char *filename)
+{
+ char buf[BUFSIZ];
+ int len, f;
+
+ if ((f = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
+ return (FALSE);
+
+ while ((len = read(f, buf, sizeof (buf))) > 0) {
+ /* Look for "-----BEGIN" right after a newline */
+ char *p;
+
+ p = strtok(buf, "\n");
+ while (p != NULL) {
+ if (p < (buf + len)) {
+ if (strstr(p, "-----BEGIN") != NULL) {
+ (void) close(f);
+ return (TRUE);
+ }
+ }
+ p = strtok(NULL, "\n");
+ }
+ }
+ (void) close(f);
+ return (FALSE);
+}
+
KMF_RETURN
KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
{
@@ -707,9 +735,8 @@ KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
goto end;
}
- if (memcmp(buf, "-----BEG", 8) == 0) {
- *fmt = KMF_FORMAT_PEM;
- } else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
+ (void) close(f);
+ if (buf[0] == 0x30 && (buf[1] & 0x80)) {
if ((buf[1] & 0xFF) == 0x80 &&
(buf[2] & 0xFF) == 0x02 &&
(buf[5] & 0xFF) == 0x30) {
@@ -725,12 +752,16 @@ KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
} else if (memcmp(buf, "Bag Attr", 8) == 0) {
*fmt = KMF_FORMAT_PEM_KEYPAIR;
} else {
- /* Cannot determine this file format */
- *fmt = 0;
- ret = KMF_ERR_ENCODING;
+ /* Try PEM */
+ if (check_for_pem(filename) == TRUE) {
+ *fmt = KMF_FORMAT_PEM;
+ } else {
+ /* Cannot determine this file format */
+ *fmt = 0;
+ ret = KMF_ERR_ENCODING;
+ }
}
end:
- (void) close(f);
return (ret);
}
@@ -1037,6 +1068,8 @@ void
KMF_FreeBigint(KMF_BIGINT *big)
{
if (big != NULL && big->val != NULL) {
+ /* Clear it out before returning it to the pool */
+ (void) memset(big->val, 0x00, big->len);
free(big->val);
big->val = NULL;
big->len = 0;
diff --git a/usr/src/lib/libkmf/libkmf/common/kmfoids.c b/usr/src/lib/libkmf/libkmf/common/kmfoids.c
index 8bad4388f0..75b5bad7e0 100644
--- a/usr/src/lib/libkmf/libkmf/common/kmfoids.c
+++ b/usr/src/lib/libkmf/libkmf/common/kmfoids.c
@@ -354,3 +354,28 @@ KMFOID_PKIX_KP_IPSecUser = {OID_PKIX_KP_LENGTH + 1, OID_KP_IPSecUser},
KMFOID_PKIX_KP_TimeStamping = {OID_PKIX_KP_LENGTH + 1, OID_KP_TimeStamping},
KMFOID_PKIX_KP_OCSPSigning = {OID_PKIX_KP_LENGTH + 1, OID_KP_OCSPSigning};
+
+static uint8_t
+OID_OIW_SHA1[] = { OID_OIW_ALGORITHM, 26},
+OID_OIW_DSA[] = { OID_OIW_ALGORITHM, 12 },
+OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 27 },
+OID_RSAEncryption[] = { OID_PKCS_1, 1 },
+OID_MD2WithRSA[] = { OID_PKCS_1, 2 },
+OID_MD5WithRSA[] = { OID_PKCS_1, 4 },
+OID_SHA1WithRSA[] = { OID_PKCS_1, 5 },
+OID_X9CM_DSA[] = { OID_X9CM_X9ALGORITHM, 1 },
+OID_X9CM_DSAWithSHA1[] = { OID_X9CM_X9ALGORITHM, 3};
+
+const KMF_OID
+KMFOID_SHA1 = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_SHA1},
+KMFOID_RSA = {OID_PKCS_1_LENGTH+1, OID_RSAEncryption},
+KMFOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSA},
+KMFOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD5WithRSA},
+KMFOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD2WithRSA},
+KMFOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA1WithRSA},
+KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1},
+KMFOID_OIW_DSAWithSHA1 = {OID_OIW_ALGORITHM_LENGTH+1,
+ OID_OIW_DSAWithSHA1},
+KMFOID_X9CM_DSA = {OID_X9CM_X9ALGORITHM_LENGTH+1, OID_X9CM_DSA},
+KMFOID_X9CM_DSAWithSHA1 = {OID_X9CM_X9ALGORITHM_LENGTH+1,
+ OID_X9CM_DSAWithSHA1};
diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
index 044a945d26..fec0c2cee7 100644
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
@@ -41,6 +41,7 @@ SUNWprivate_1.1 {
KMF_CreateSymKey;
KMF_DN2Der;
KMF_DNParser;
+ KMF_DecodeCertData;
KMF_DecryptWithCert;
KMF_DeleteCRL;
KMF_DeleteCertFromKeystore;
@@ -276,8 +277,19 @@ SUNWprivate_1.1 {
KMFOID_X_121Address;
KMFOID_domainComponent;
KMFOID_userid;
+ KMFOID_SHA1;
+ KMFOID_RSA;
+ KMFOID_DSA;
+ KMFOID_MD5WithRSA;
+ KMFOID_MD2WithRSA;
+ KMFOID_SHA1WithRSA;
+ KMFOID_SHA1WithDSA;
+ KMFOID_OIW_DSAWithSHA1;
+ KMFOID_X9CM_DSA;
+ KMFOID_X9CM_DSAWithSHA1;
PKCS_GetDefaultSignatureMode;
PKCS_GetAlgorithmMap;
+ PKCS_AcquirePublicKeyHandle;
X509_AlgIdToAlgorithmOid;
X509_AlgorithmOidToAlgId;
kmf_ekuname2oid;
diff --git a/usr/src/lib/libkmf/libkmf/common/pk11keys.c b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
index 90b32053fb..05dded86ea 100644
--- a/usr/src/lib/libkmf/libkmf/common/pk11keys.c
+++ b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
@@ -316,7 +316,7 @@ cleanup:
* - Public Key with label:
* Attempts to find a public key with the corresponding label.
*/
-static KMF_RETURN
+KMF_RETURN
PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
const KMF_X509_SPKI *pKey,
CK_KEY_TYPE ckRequestedKeyType,
diff --git a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
index 84af5ad7cd..fc6621e536 100644
--- a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
@@ -35,7 +35,6 @@
#include <kmfapiP.h>
#include <ber_der.h>
-#include <oidsalg.h>
/* NSS related headers */
#include <mps/nss.h>
@@ -170,6 +169,7 @@ KMF_PLUGIN_FUNCLIST nss_plugin_table =
NSS_CreateSymKey,
NSS_GetSymKeyValue,
NSS_SetTokenPin,
+ NULL, /* VerifyData */
NULL /* Finalize */
};
diff --git a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
index dea9bd52d6..8a9fd64815 100644
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
@@ -66,7 +66,6 @@
#include <stdlib.h>
#include <kmfapiP.h>
#include <ber_der.h>
-#include <oidsalg.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -138,12 +137,18 @@ mutex_t init_lock = DEFAULTMUTEX;
static int ssl_initialized = 0;
static KMF_RETURN
-extract_objects(KMF_HANDLE *, char *, CK_UTF8CHAR *, CK_ULONG,
- EVP_PKEY **, KMF_DATA **, int *);
+extract_objects(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *,
+ CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
static KMF_RETURN
kmf_load_cert(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *, KMF_DATA *);
+static KMF_RETURN
+sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
+
+static EVP_PKEY *
+ImportRawRSAKey(KMF_RAW_RSA_KEY *);
+
KMF_RETURN
OpenSSL_FindCert(KMF_HANDLE_T,
KMF_FINDCERT_PARAMS *,
@@ -237,6 +242,10 @@ OpenSSL_VerifyCRLFile(KMF_HANDLE_T, KMF_VERIFYCRL_PARAMS *);
KMF_RETURN
OpenSSL_CheckCRLDate(KMF_HANDLE_T, KMF_CHECKCRLDATE_PARAMS *);
+KMF_RETURN
+OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
+ KMF_DATA *, KMF_DATA *, KMF_DATA *);
+
static
KMF_PLUGIN_FUNCLIST openssl_plugin_table =
{
@@ -265,6 +274,7 @@ KMF_PLUGIN_FUNCLIST openssl_plugin_table =
OpenSSL_CreateSymKey,
OpenSSL_GetSymKeyValue,
NULL, /* SetTokenPin */
+ OpenSSL_VerifyDataWithCert,
NULL /* Finalize */
};
@@ -661,7 +671,7 @@ load_certs(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, char *pathname,
format != KMF_FORMAT_PEM_KEYPAIR) {
/* This function only works on PEM files */
- rv = extract_objects(kmfh, pathname,
+ rv = extract_objects(kmfh, params, pathname,
(uchar_t *)NULL, 0, NULL,
&certs, &nc);
} else {
@@ -747,6 +757,162 @@ cleanup:
return (rv);
}
+static KMF_RETURN
+readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
+{
+ KMF_RETURN ret = KMF_OK;
+ KMF_RAW_RSA_KEY rsa;
+ BerElement *asn1 = NULL;
+ BerValue filebuf;
+ BerValue OID = { NULL, 0 };
+ BerValue *Mod = NULL, *PubExp = NULL;
+ BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
+ BerValue *Coef = NULL;
+ BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
+ BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
+ BIGNUM *qminus1 = NULL;
+ BN_CTX *ctx = NULL;
+
+ *pkey = NULL;
+
+ filebuf.bv_val = (char *)filedata->Data;
+ filebuf.bv_len = filedata->Length;
+
+ asn1 = kmfder_init(&filebuf);
+ if (asn1 == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
+ &OID, &Mod, &PubExp, &PriExp, &Prime1,
+ &Prime2, &Coef) == -1) {
+ ret = KMF_ERR_ENCODING;
+ goto out;
+ }
+
+ /*
+ * We have to derive the 2 Exponents using Bignumber math.
+ * Exp1 = PriExp mod (Prime1 - 1)
+ * Exp2 = PriExp mod (Prime2 - 1)
+ */
+
+ /* D = PrivateExponent */
+ D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
+ if (D == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ /* P = Prime1 (first prime factor of Modulus) */
+ P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
+ if (D == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ /* Q = Prime2 (second prime factor of Modulus) */
+ Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
+
+ if ((ctx = BN_CTX_new()) == NULL) {
+ ret = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ /* Compute (P - 1) */
+ pminus1 = BN_new();
+ (void) BN_sub(pminus1, P, BN_value_one());
+
+ /* Exponent1 = D mod (P - 1) */
+ Exp1 = BN_new();
+ (void) BN_mod(Exp1, D, pminus1, ctx);
+
+ /* Compute (Q - 1) */
+ qminus1 = BN_new();
+ (void) BN_sub(qminus1, Q, BN_value_one());
+
+ /* Exponent2 = D mod (Q - 1) */
+ Exp2 = BN_new();
+ (void) BN_mod(Exp2, D, qminus1, ctx);
+
+ /* Coef = (Inverse Q) mod P */
+ COEF = BN_new();
+ (void) BN_mod_inverse(COEF, Q, P, ctx);
+
+ /* Convert back to KMF format */
+ (void) memset(&rsa, 0, sizeof (rsa));
+
+ if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
+ goto out;
+ if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
+ goto out;
+ if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
+ goto out;
+
+ rsa.mod.val = (uchar_t *)Mod->bv_val;
+ rsa.mod.len = Mod->bv_len;
+
+ rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
+ rsa.pubexp.len = PubExp->bv_len;
+
+ rsa.priexp.val = (uchar_t *)PriExp->bv_val;
+ rsa.priexp.len = PriExp->bv_len;
+
+ rsa.prime1.val = (uchar_t *)Prime1->bv_val;
+ rsa.prime1.len = Prime1->bv_len;
+
+ rsa.prime2.val = (uchar_t *)Prime2->bv_val;
+ rsa.prime2.len = Prime2->bv_len;
+
+ *pkey = ImportRawRSAKey(&rsa);
+out:
+ if (asn1 != NULL)
+ kmfber_free(asn1, 1);
+
+ if (OID.bv_val) {
+ free(OID.bv_val);
+ }
+ if (PriExp)
+ free(PriExp);
+
+ if (Mod)
+ free(Mod);
+
+ if (PubExp)
+ free(PubExp);
+
+ if (Coef) {
+ (void) memset(Coef->bv_val, 0, Coef->bv_len);
+ free(Coef->bv_val);
+ free(Coef);
+ }
+ if (Prime1)
+ free(Prime1);
+ if (Prime2)
+ free(Prime2);
+
+ if (ctx != NULL)
+ BN_CTX_free(ctx);
+
+ if (D)
+ BN_clear_free(D);
+ if (P)
+ BN_clear_free(P);
+ if (Q)
+ BN_clear_free(Q);
+ if (pminus1)
+ BN_clear_free(pminus1);
+ if (qminus1)
+ BN_clear_free(qminus1);
+ if (Exp1)
+ BN_clear_free(Exp1);
+ if (Exp2)
+ BN_clear_free(Exp2);
+
+ return (ret);
+
+}
+
static EVP_PKEY *
openssl_load_key(KMF_HANDLE_T handle, const char *file)
{
@@ -754,6 +920,8 @@ openssl_load_key(KMF_HANDLE_T handle, const char *file)
EVP_PKEY *pkey = NULL;
KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
KMF_ENCODE_FORMAT format;
+ KMF_RETURN rv;
+ KMF_DATA filedata;
if (file == NULL) {
return (NULL);
@@ -767,11 +935,48 @@ openssl_load_key(KMF_HANDLE_T handle, const char *file)
goto end;
}
- if (format == KMF_FORMAT_ASN1)
+ if (format == KMF_FORMAT_ASN1) {
pkey = d2i_PrivateKey_bio(keyfile, NULL);
- else if (format == KMF_FORMAT_PEM ||
- format == KMF_FORMAT_PEM_KEYPAIR)
+ if (pkey == NULL) {
+
+ (void) BIO_free(keyfile);
+ keyfile = NULL;
+ /* Try odd ASN.1 variations */
+ rv = KMF_ReadInputFile(kmfh, (char *)file,
+ &filedata);
+ if (rv == KMF_OK) {
+ (void) readAltFormatPrivateKey(&filedata,
+ &pkey);
+ KMF_FreeData(&filedata);
+ }
+ }
+ } else if (format == KMF_FORMAT_PEM ||
+ format == KMF_FORMAT_PEM_KEYPAIR) {
pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
+ if (pkey == NULL) {
+ KMF_DATA derdata;
+ /*
+ * Check if this is the alt. format
+ * RSA private key file.
+ */
+ rv = KMF_ReadInputFile(kmfh, (char *)file,
+ &filedata);
+ if (rv == KMF_OK) {
+ uchar_t *d = NULL;
+ int len;
+ rv = KMF_Pem2Der(filedata.Data,
+ filedata.Length, &d, &len);
+ if (rv == KMF_OK && d != NULL) {
+ derdata.Data = d;
+ derdata.Length = (size_t)len;
+ (void) readAltFormatPrivateKey(
+ &derdata, &pkey);
+ free(d);
+ }
+ KMF_FreeData(&filedata);
+ }
+ }
+ }
end:
if (pkey == NULL)
@@ -1468,6 +1673,7 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
KMF_ALGORITHM_INDEX AlgId;
EVP_MD_CTX ctx;
const EVP_MD *md;
+
if (key == NULL || AlgOID == NULL ||
tobesigned == NULL || output == NULL ||
tobesigned->Data == NULL ||
@@ -1482,33 +1688,44 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
if (key->keyalg == KMF_RSA) {
EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
uchar_t *p;
- uint32_t len;
+ int len;
if (AlgId == KMF_ALGID_MD5WithRSA)
md = EVP_md5();
else if (AlgId == KMF_ALGID_MD2WithRSA)
md = EVP_md2();
else if (AlgId == KMF_ALGID_SHA1WithRSA)
md = EVP_sha1();
+ else if (AlgId == KMF_ALGID_RSA)
+ md = NULL;
else
return (KMF_ERR_BAD_PARAMETER);
- if (md == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- return (KMF_ERR_MEMORY);
- }
+ if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
+ RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
- (void) EVP_MD_CTX_init(&ctx);
- (void) EVP_SignInit_ex(&ctx, md, NULL);
- (void) EVP_SignUpdate(&ctx, tobesigned->Data,
- (uint32_t)tobesigned->Length);
- len = (uint32_t)output->Length;
- p = output->Data;
- if (!EVP_SignFinal(&ctx, p, &len, pkey)) {
- SET_ERROR(kmfh, ERR_get_error());
- output->Length = 0;
+ p = output->Data;
+ if ((len = RSA_private_encrypt(tobesigned->Length,
+ tobesigned->Data, p, rsa,
+ RSA_PKCS1_PADDING)) <= 0) {
+ SET_ERROR(kmfh, ERR_get_error());
+ ret = KMF_ERR_INTERNAL;
+ }
+ output->Length = len;
+ } else {
+ (void) EVP_MD_CTX_init(&ctx);
+ (void) EVP_SignInit_ex(&ctx, md, NULL);
+ (void) EVP_SignUpdate(&ctx, tobesigned->Data,
+ (uint32_t)tobesigned->Length);
+ len = (uint32_t)output->Length;
+ p = output->Data;
+ if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
+ SET_ERROR(kmfh, ERR_get_error());
+ len = 0;
+ ret = KMF_ERR_INTERNAL;
+ }
+ output->Length = len;
+ (void) EVP_MD_CTX_cleanup(&ctx);
}
- output->Length = len;
- (void) EVP_MD_CTX_cleanup(&ctx);
} else if (key->keyalg == KMF_DSA) {
DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
@@ -2274,7 +2491,7 @@ OpenSSL_GetPrikeyByCert(KMF_HANDLE_T handle,
KMF_FINDKEY_PARAMS fkparms;
uint32_t numkeys = 0;
- if (params == NULL && params->sslparms.keyfile == NULL)
+ if (params == NULL || params->sslparms.keyfile == NULL)
return (KMF_ERR_BAD_PARAMETER);
/*
@@ -3433,7 +3650,8 @@ end:
* However, the file may be just a list of X509 certs with no keys.
*/
static KMF_RETURN
-extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin,
+extract_objects(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params,
+ char *filename, CK_UTF8CHAR *pin,
CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
int *numcerts)
/* ARGSUSED */
@@ -3441,7 +3659,7 @@ extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin,
KMF_RETURN rv = KMF_OK;
FILE *fp;
STACK_OF(X509_INFO) *x509_info_stack;
- int i, ncerts = 0;
+ int i, ncerts = 0, matchcerts = 0;
EVP_PKEY *pkey = NULL;
X509_INFO *info;
X509 *x;
@@ -3500,21 +3718,34 @@ extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin,
/*
* Convert all of the certs to DER format.
*/
+ matchcerts = 0;
for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
+ boolean_t match = FALSE;
info = cert_infos[ncerts - 1 - i];
- rv = ssl_cert2KMFDATA(kmfh, info->x509, &certlist[i]);
+ if (params != NULL) {
+ rv = check_cert(info->x509, params, &match);
+ if (rv != KMF_OK || match != TRUE) {
+ X509_INFO_free(info);
+ rv = KMF_OK;
+ continue;
+ }
+ }
+
+ rv = ssl_cert2KMFDATA(kmfh, info->x509,
+ &certlist[matchcerts++]);
if (rv != KMF_OK) {
free(certlist);
certlist = NULL;
- ncerts = 0;
+ ncerts = matchcerts = 0;
}
+
X509_INFO_free(info);
}
if (numcerts != NULL)
- *numcerts = ncerts;
+ *numcerts = matchcerts;
if (certs != NULL)
*certs = certlist;
@@ -3891,7 +4122,7 @@ openssl_import_keypair(KMF_HANDLE *kmfh,
*keylist = NULL;
*ncerts = 0;
*nkeys = 0;
- rv = extract_objects(kmfh, filename,
+ rv = extract_objects(kmfh, NULL, filename,
(uchar_t *)cred->cred,
(uint32_t)cred->credlen,
&privkey, certlist, ncerts);
@@ -4508,3 +4739,203 @@ OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
return (rv);
}
+
+/*
+ * id-sha1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) oiw(14) secsig(3)
+ * algorithms(2) 26
+ * }
+ */
+#define ASN1_SHA1_OID_PREFIX_LEN 15
+static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
+ 0x30, 0x21, 0x30, 0x09,
+ 0x06, 0x05, 0x2b, 0x0e,
+ 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14
+};
+
+/*
+ * id-md2 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
+ * }
+ */
+#define ASN1_MD2_OID_PREFIX_LEN 18
+static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
+ 0x30, 0x20, 0x30, 0x0c,
+ 0x06, 0x08, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x02, 0x05, 0x00,
+ 0x04, 0x10
+};
+
+/*
+ * id-md5 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
+ * }
+ */
+#define ASN1_MD5_OID_PREFIX_LEN 18
+static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
+ 0x30, 0x20, 0x30, 0x0c,
+ 0x06, 0x08, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00,
+ 0x04, 0x10
+};
+
+KMF_RETURN
+OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
+ KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
+ KMF_DATA *insig, KMF_DATA *cert)
+{
+ KMF_RETURN ret = KMF_OK;
+ KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
+ X509 *xcert = NULL;
+ EVP_PKEY *pkey = NULL;
+ uchar_t *p;
+ uchar_t *rsaout = NULL;
+ uchar_t *pfx = NULL;
+ const EVP_MD *md;
+ int pfxlen = 0, len;
+
+ if (handle == NULL || indata == NULL ||
+ indata->Data == NULL || indata->Length == 0 ||
+ insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
+ cert == NULL || cert->Data == NULL || cert->Length == 0)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ p = cert->Data;
+ xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
+ if (xcert == NULL) {
+ SET_ERROR(kmfh, ERR_get_error());
+ ret = KMF_ERR_BAD_CERT_FORMAT;
+ goto cleanup;
+ }
+
+ pkey = X509_get_pubkey(xcert);
+ if (!pkey) {
+ SET_ERROR(kmfh, ERR_get_error());
+ ret = KMF_ERR_BAD_CERT_FORMAT;
+ goto cleanup;
+ }
+
+ if (algid != KMF_ALGID_NONE) {
+ switch (algid) {
+ case KMF_ALGID_MD5WithRSA:
+ md = EVP_md5();
+ break;
+ case KMF_ALGID_MD2WithRSA:
+ md = EVP_md2();
+ break;
+ case KMF_ALGID_SHA1WithRSA:
+ md = EVP_sha1();
+ break;
+ case KMF_ALGID_RSA:
+ md = NULL;
+ break;
+ default:
+ ret = KMF_ERR_BAD_PARAMETER;
+ goto cleanup;
+ }
+ } else {
+ /* Get the hash type from the cert signature */
+ md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
+ if (md == NULL) {
+ SET_ERROR(kmfh, ERR_get_error());
+ ret = KMF_ERR_BAD_PARAMETER;
+ goto cleanup;
+ }
+ }
+ switch (EVP_MD_type(md)) {
+ case NID_md2:
+ case NID_md2WithRSAEncryption:
+ pfxlen = ASN1_MD2_OID_PREFIX_LEN;
+ pfx = MD2_DER_PREFIX;
+ break;
+ case NID_md5:
+ case NID_md5WithRSAEncryption:
+ pfxlen = ASN1_MD5_OID_PREFIX_LEN;
+ pfx = MD5_DER_PREFIX;
+ break;
+ case NID_sha1:
+ case NID_sha1WithRSAEncryption:
+ pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
+ pfx = SHA1_DER_PREFIX;
+ break;
+ default: /* Unsupported */
+ pfxlen = 0;
+ pfx = NULL;
+ break;
+ }
+
+ /* RSA with no hash is a special case */
+ rsaout = malloc(RSA_size(pkey->pkey.rsa));
+ if (rsaout == NULL)
+ return (KMF_ERR_MEMORY);
+
+ /* Decrypt the input signature */
+ len = RSA_public_decrypt(insig->Length,
+ insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
+ if (len < 1) {
+ SET_ERROR(kmfh, ERR_get_error());
+ ret = KMF_ERR_BAD_PARAMETER;
+ } else {
+ size_t hashlen = 0;
+ uint32_t dlen;
+ char *digest = NULL;
+
+ /*
+ * If the AlgId requires it, hash the input data before
+ * comparing it to the decrypted signature.
+ */
+ if (md) {
+ EVP_MD_CTX ctx;
+
+ hashlen = md->md_size;
+
+ digest = malloc(hashlen + pfxlen);
+ if (digest == NULL)
+ return (KMF_ERR_MEMORY);
+ /* Add the prefix to the comparison buffer. */
+ if (pfx && pfxlen > 0) {
+ (void) memcpy(digest, pfx, pfxlen);
+ }
+ (void) EVP_DigestInit(&ctx, md);
+ (void) EVP_DigestUpdate(&ctx, indata->Data,
+ indata->Length);
+
+ /* Add the digest AFTER the ASN1 prefix */
+ (void) EVP_DigestFinal(&ctx,
+ (uchar_t *)digest + pfxlen, &dlen);
+
+ dlen += pfxlen;
+ } else {
+ digest = (char *)indata->Data;
+ dlen = indata->Length;
+ }
+
+ /*
+ * The result of the RSA decryption should be ASN1(OID | Hash).
+ * Compare the output hash to the input data for the final
+ * result.
+ */
+ if (memcmp(rsaout, digest, dlen))
+ ret = KMF_ERR_INTERNAL;
+ else
+ ret = KMF_OK;
+
+ /* If we had to allocate space for the digest, free it now */
+ if (hashlen)
+ free(digest);
+ }
+cleanup:
+ if (pkey)
+ EVP_PKEY_free(pkey);
+
+ if (xcert)
+ X509_free(xcert);
+
+ if (rsaout)
+ free(rsaout);
+
+ return (ret);
+}
diff --git a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
index cc8a0afc0f..7689574e0c 100644
--- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
@@ -32,7 +32,6 @@
#include <values.h>
#include <kmfapiP.h>
-#include <oidsalg.h>
#include <ber_der.h>
#include <algorithm.h>
@@ -129,6 +128,10 @@ KMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
KMF_RETURN
KMFPK11_SetTokenPin(KMF_HANDLE_T, KMF_SETPIN_PARAMS *, KMF_CREDENTIAL *);
+KMF_RETURN
+KMFPK11_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, KMF_DATA *,
+ KMF_DATA *, KMF_DATA *);
+
static
KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
{
@@ -157,6 +160,7 @@ KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
KMFPK11_CreateSymKey,
KMFPK11_GetSymKeyValue,
KMFPK11_SetTokenPin,
+ KMFPK11_VerifyDataWithCert,
NULL /* Finalize */
};
@@ -2953,3 +2957,176 @@ end:
(void) C_CloseSession(session);
return (ret);
}
+
+static KMF_RETURN
+create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
+ CK_FLAGS wanted_flags)
+{
+ CK_RV rv;
+ KMF_RETURN kmf_rv = KMF_OK;
+ CK_SLOT_ID_PTR pSlotList;
+ CK_ULONG pulCount;
+ CK_MECHANISM_INFO info;
+ int i;
+
+ rv = C_Initialize(NULL);
+ if ((rv != CKR_OK) &&
+ (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+
+ rv = C_GetSlotList(0, NULL, &pulCount);
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+
+ pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
+ if (pSlotList == NULL) {
+ kmf_rv = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ rv = C_GetSlotList(0, pSlotList, &pulCount);
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ goto out;
+ }
+
+ for (i = 0; i < pulCount; i++) {
+ rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
+ if (rv == CKR_OK && (info.flags & wanted_flags))
+ break;
+ }
+ if (i < pulCount) {
+ rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
+ NULL, NULL, sessionp);
+
+ if (rv != CKR_OK) {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ }
+ } else {
+ kmf_rv = KMF_ERR_UNINITIALIZED;
+ }
+
+out:
+ if (pSlotList != NULL)
+ free(pSlotList);
+ return (kmf_rv);
+
+}
+static KMF_RETURN
+verify_data(KMF_HANDLE_T handle,
+ KMF_ALGORITHM_INDEX AlgorithmId,
+ KMF_X509_SPKI *keyp,
+ KMF_DATA *data,
+ KMF_DATA *signed_data)
+{
+ KMF_RETURN ret;
+ PKCS_ALGORITHM_MAP *pAlgMap = NULL;
+ CK_RV ckRv;
+ CK_MECHANISM ckMechanism;
+ CK_OBJECT_HANDLE ckKeyHandle;
+ KMF_BOOL bTempKey;
+ KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
+ CK_SESSION_HANDLE ckSession = NULL;
+
+ if (AlgorithmId == KMF_ALGID_NONE)
+ return (KMF_ERR_BAD_ALGORITHM);
+
+ pAlgMap = PKCS_GetAlgorithmMap(KMF_ALGCLASS_SIGNATURE,
+ AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
+
+ if (!pAlgMap)
+ return (KMF_ERR_BAD_ALGORITHM);
+
+ ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
+ CKF_VERIFY);
+ if (ret != KMF_OK)
+ return (ret);
+
+ /* Fetch the verifying key */
+ ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
+ pAlgMap->key_type, &ckKeyHandle, &bTempKey);
+
+ if (ret != KMF_OK) {
+ return (ret);
+ }
+
+ ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
+ ckMechanism.pParameter = NULL;
+ ckMechanism.ulParameterLen = 0;
+
+ ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
+ if (ckRv != CKR_OK) {
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+ SET_ERROR(kmfh, ckRv);
+ ret = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+
+ ckRv = C_Verify(ckSession,
+ (CK_BYTE *)data->Data,
+ (CK_ULONG)data->Length,
+ (CK_BYTE *)signed_data->Data,
+ (CK_ULONG)signed_data->Length);
+
+ if (ckRv != CKR_OK) {
+ SET_ERROR(kmfh, ckRv);
+ ret = KMF_ERR_INTERNAL;
+ }
+
+cleanup:
+ if (bTempKey)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
+
+ (void) C_CloseSession(ckSession);
+
+ return (ret);
+}
+
+KMF_RETURN
+KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle,
+ KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
+ KMF_DATA *insig, KMF_DATA *SignerCertData)
+{
+ KMF_RETURN ret = KMF_OK;
+ KMF_X509_CERTIFICATE *SignerCert = NULL;
+ KMF_X509_SPKI *pubkey;
+
+ if (handle == NULL || indata == NULL ||
+ indata->Data == NULL || indata->Length == 0 ||
+ insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
+ SignerCertData == NULL || SignerCertData->Data == NULL ||
+ SignerCertData->Length == 0)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ /* Decode the signer cert so we can get the SPKI data */
+ ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
+ if (ret != KMF_OK)
+ goto cleanup;
+
+ /* Get the public key info from the signer certificate */
+ pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
+
+ /* If no algorithm specified, use the certs signature algorithm */
+ if (algid == KMF_ALGID_NONE) {
+ algid = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert));
+ }
+
+ if (algid == KMF_ALGID_NONE) {
+ ret = KMF_ERR_BAD_ALGORITHM;
+ } else {
+ ret = verify_data(handle, algid, pubkey, indata, insig);
+ }
+
+cleanup:
+ if (SignerCert) {
+ KMF_FreeSignedCert(SignerCert);
+ free(SignerCert);
+ }
+
+ return (ret);
+}