2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A *
2N/A * PKCS11 token KMF Plugin
2N/A *
2N/A * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdio.h> /* debugging only */
2N/A#include <errno.h>
2N/A#include <values.h>
2N/A
2N/A#include <kmfapiP.h>
2N/A#include <ber_der.h>
2N/A#include <fcntl.h>
2N/A#include <sha1.h>
2N/A#include <bignum.h>
2N/A
2N/A#include <cryptoutil.h>
2N/A#include <security/cryptoki.h>
2N/A#include <security/pkcs11.h>
2N/A
2N/A#define DEV_RANDOM "/dev/random"
2N/A
2N/A#define SETATTR(t, n, atype, value, size) \
2N/A t[n].type = atype; \
2N/A t[n].pValue = (CK_BYTE *)value; \
2N/A t[n].ulValueLen = (CK_ULONG)size;
2N/A
2N/A#define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; \
2N/A h->lasterr.errcode = c;
2N/A
2N/Atypedef struct _objlist {
2N/A CK_OBJECT_HANDLE handle;
2N/A struct _objlist *next;
2N/A} OBJLIST;
2N/A
2N/Astatic KMF_RETURN
2N/Asearch_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
2N/A boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
2N/A
2N/Astatic CK_RV
2N/AgetObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
2N/A
2N/Astatic KMF_RETURN
2N/AkeyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
2N/A
2N/Astatic KMF_RETURN
2N/Acreate_generic_secret_key(KMF_HANDLE_T,
2N/A int, KMF_ATTRIBUTE *, CK_OBJECT_HANDLE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/Avoid
2N/AKMFPK11_FreeKMFCert(KMF_HANDLE_T,
2N/A KMF_X509_DER_CERT *kmf_cert);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2N/A KMF_DATA *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_GetErrorString(KMF_HANDLE_T, char **);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
2N/A KMF_DATA *, KMF_DATA *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
2N/A
2N/A
2N/Astatic
2N/AKMF_PLUGIN_FUNCLIST pk11token_plugin_table =
2N/A{
2N/A 1, /* Version */
2N/A KMFPK11_ConfigureKeystore,
2N/A KMFPK11_FindCert,
2N/A KMFPK11_FreeKMFCert,
2N/A KMFPK11_StoreCert,
2N/A KMFPK11_ImportCert,
2N/A NULL, /* ImportCRL */
2N/A KMFPK11_DeleteCert,
2N/A NULL, /* DeleteCRL */
2N/A KMFPK11_CreateKeypair,
2N/A KMFPK11_FindKey,
2N/A KMFPK11_EncodePubKeyData,
2N/A KMFPK11_SignData,
2N/A KMFPK11_DeleteKey,
2N/A NULL, /* ListCRL */
2N/A NULL, /* FindCRL */
2N/A NULL, /* FindCertInCRL */
2N/A KMFPK11_GetErrorString,
2N/A KMFPK11_FindPrikeyByCert,
2N/A KMFPK11_DecryptData,
2N/A KMFPK11_ExportPK12,
2N/A KMFPK11_CreateSymKey,
2N/A KMFPK11_GetSymKeyValue,
2N/A KMFPK11_SetTokenPin,
2N/A KMFPK11_StoreKey,
2N/A NULL /* Finalize */
2N/A};
2N/A
2N/AKMF_PLUGIN_FUNCLIST *
2N/AKMF_Plugin_Initialize()
2N/A{
2N/A return (&pk11token_plugin_table);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ConfigureKeystore(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A char *label;
2N/A boolean_t readonly = B_TRUE;
2N/A
2N/A label = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
2N/A if (label == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A /* "readonly" is optional. Default is TRUE */
2N/A (void) kmf_get_attr(KMF_READONLY_ATTR, attrlist, numattr,
2N/A (void *)&readonly, NULL);
2N/A
2N/A rv = kmf_select_token(handle, label, readonly);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Apk11_authenticate(KMF_HANDLE_T handle,
2N/A KMF_CREDENTIAL *cred)
2N/A{
2N/A
2N/A CK_RV ck_rv = CKR_OK;
2N/A CK_SESSION_HANDLE hSession = (CK_SESSION_HANDLE)handle->pk11handle;
2N/A
2N/A if (hSession == NULL)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (cred == NULL || cred->cred == NULL) {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A if ((ck_rv = C_Login(hSession, CKU_USER, (uchar_t *)cred->cred,
2N/A cred->credlen)) != CKR_OK) {
2N/A if (ck_rv != CKR_USER_ALREADY_LOGGED_IN) {
2N/A handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A handle->lasterr.errcode = ck_rv;
2N/A return (KMF_ERR_AUTH_FAILED);
2N/A }
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/APK11Cert2KMFCert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE hObj,
2N/A KMF_X509_DER_CERT *kmfcert)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A CK_RV ckrv = CKR_OK;
2N/A
2N/A CK_CERTIFICATE_TYPE cktype;
2N/A CK_OBJECT_CLASS class;
2N/A CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
2N/A CK_BYTE *subject = NULL, *value = NULL;
2N/A char *label = NULL;
2N/A CK_ATTRIBUTE templ[10];
2N/A
2N/A (void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
2N/A SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
2N/A
2N/A /* Is this a certificate object ? */
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
2N/A if (ckrv != CKR_OK || class != CKO_CERTIFICATE) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
2N/A
2N/A if (ckrv != CKR_OK || cktype != CKC_X_509) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (ckrv);
2N/A } else {
2N/A int i = 0;
2N/A /* What attributes are available and how big are they? */
2N/A subject_len = issuer_len = serno_len = id_len = value_len = 0;
2N/A
2N/A SETATTR(templ, i, CKA_SUBJECT, NULL, subject_len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_ISSUER, NULL, issuer_len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_ID, NULL, id_len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_VALUE, NULL, value_len);
2N/A i++;
2N/A
2N/A /*
2N/A * Query the object with NULL values in the pValue spot
2N/A * so we know how much space to allocate for each field.
2N/A */
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
2N/A }
2N/A
2N/A subject_len = templ[0].ulValueLen;
2N/A issuer_len = templ[1].ulValueLen;
2N/A serno_len = templ[2].ulValueLen;
2N/A id_len = templ[3].ulValueLen;
2N/A value_len = templ[4].ulValueLen;
2N/A
2N/A /*
2N/A * For PKCS#11 CKC_X_509 certificate objects,
2N/A * the following attributes must be defined.
2N/A * CKA_SUBJECT, CKA_ID, CKA_ISSUER, CKA_SERIAL_NUMBER,
2N/A * CKA_VALUE.
2N/A */
2N/A if (subject_len == 0 || issuer_len == 0 ||
2N/A serno_len == 0 || value_len == 0) {
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A /* Only fetch the value field if we are saving the data */
2N/A if (kmfcert != NULL) {
2N/A int i = 0;
2N/A value = malloc(value_len);
2N/A if (value == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto errout;
2N/A }
2N/A
2N/A SETATTR(templ, i, CKA_VALUE, value, value_len);
2N/A i++;
2N/A
2N/A /* re-query the object with room for the value attr */
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
2N/A templ, i);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto errout;
2N/A }
2N/A
2N/A kmfcert->certificate.Data = value;
2N/A kmfcert->certificate.Length = value_len;
2N/A kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
2N/A kmfcert->kmf_private.keystore_type =
2N/A KMF_KEYSTORE_PK11TOKEN;
2N/A
2N/A ckrv = getObjectLabel(kmfh, hObj, &label);
2N/A if (ckrv == CKR_OK && label != NULL) {
2N/A kmfcert->kmf_private.label = (char *)label;
2N/A }
2N/A
2N/A rv = KMF_OK;
2N/A }
2N/A }
2N/A
2N/Aerrout:
2N/A if (rv != KMF_OK) {
2N/A if (subject)
2N/A free(subject);
2N/A if (value)
2N/A free(value);
2N/A
2N/A if (kmfcert) {
2N/A kmfcert->certificate.Data = NULL;
2N/A kmfcert->certificate.Length = 0;
2N/A }
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/Astatic void
2N/Afree_objlist(OBJLIST *head)
2N/A{
2N/A OBJLIST *temp = head;
2N/A
2N/A while (temp != NULL) {
2N/A head = head->next;
2N/A free(temp);
2N/A temp = head;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * The caller should make sure that the templ->pValue is NULL since
2N/A * it will be overwritten below.
2N/A */
2N/Astatic KMF_RETURN
2N/Aget_attr(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
2N/A CK_ATTRIBUTE *templ)
2N/A{
2N/A CK_RV rv;
2N/A
2N/A rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A if (templ->ulValueLen > 0) {
2N/A templ->pValue = malloc(templ->ulValueLen);
2N/A if (templ->pValue == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A rv = C_GetAttributeValue(kmfh->pk11handle, obj, templ, 1);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/A/*
2N/A * Match a certificate with an issuer and/or subject name.
2N/A * This is tricky because we cannot reliably compare DER encodings
2N/A * because RDNs may have their AV-pairs in different orders even
2N/A * if the values are the same. You must compare individual
2N/A * AV pairs for the RDNs.
2N/A *
2N/A * RETURN: 0 for a match, non-zero for a non-match.
2N/A */
2N/Astatic KMF_RETURN
2N/Amatchcert(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj,
2N/A KMF_X509_NAME *issuer, KMF_X509_NAME *subject)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_ATTRIBUTE certattr;
2N/A KMF_DATA name;
2N/A KMF_X509_NAME dn;
2N/A
2N/A if (issuer->numberOfRDNs > 0) {
2N/A certattr.type = CKA_ISSUER;
2N/A certattr.pValue = NULL;
2N/A certattr.ulValueLen = 0;
2N/A
2N/A rv = get_attr(kmfh, obj, &certattr);
2N/A
2N/A if (rv == KMF_OK) {
2N/A name.Data = certattr.pValue;
2N/A name.Length = certattr.ulValueLen;
2N/A rv = DerDecodeName(&name, &dn);
2N/A if (rv == KMF_OK) {
2N/A rv = kmf_compare_rdns(issuer, &dn);
2N/A kmf_free_dn(&dn);
2N/A }
2N/A free(certattr.pValue);
2N/A }
2N/A
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A if (subject->numberOfRDNs > 0) {
2N/A certattr.type = CKA_SUBJECT;
2N/A certattr.pValue = NULL;
2N/A certattr.ulValueLen = 0;
2N/A
2N/A rv = get_attr(kmfh, obj, &certattr);
2N/A
2N/A if (rv == KMF_OK) {
2N/A name.Data = certattr.pValue;
2N/A name.Length = certattr.ulValueLen;
2N/A rv = DerDecodeName(&name, &dn);
2N/A if (rv == KMF_OK) {
2N/A rv = kmf_compare_rdns(subject, &dn);
2N/A kmf_free_dn(&dn);
2N/A }
2N/A free(certattr.pValue);
2N/A }
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * delete "curr" node from the "newlist".
2N/A */
2N/Astatic void
2N/Apk11_delete_obj_from_list(OBJLIST **newlist,
2N/A OBJLIST **prev, OBJLIST **curr)
2N/A{
2N/A
2N/A if (*curr == *newlist) {
2N/A /* first node in the list */
2N/A *newlist = (*curr)->next;
2N/A *prev = (*curr)->next;
2N/A free(*curr);
2N/A *curr = *newlist;
2N/A } else {
2N/A (*prev)->next = (*curr)->next;
2N/A free(*curr);
2N/A *curr = (*prev)->next;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * search_certs
2N/A *
2N/A * Because this code is shared by the FindCert and
2N/A * DeleteCert functions, put it in a separate routine
2N/A * to save some work and make code easier to debug and
2N/A * read.
2N/A */
2N/Astatic KMF_RETURN
2N/Asearch_certs(KMF_HANDLE_T handle,
2N/A char *label, char *issuer, char *subject, KMF_BIGINT *serial,
2N/A boolean_t private, KMF_CERT_VALIDITY validity,
2N/A OBJLIST **objlist, uint32_t *numobj)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv = CKR_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_ATTRIBUTE templ[10];
2N/A CK_BBOOL true = TRUE;
2N/A CK_OBJECT_CLASS oclass = CKO_CERTIFICATE;
2N/A CK_CERTIFICATE_TYPE ctype = CKC_X_509;
2N/A KMF_X509_NAME subjectDN, issuerDN;
2N/A int i;
2N/A OBJLIST *newlist, *tail;
2N/A CK_ULONG num = 0;
2N/A uint32_t num_ok_certs = 0; /* number of non-expired or expired certs */
2N/A
2N/A (void) memset(&templ, 0, 10 * sizeof (CK_ATTRIBUTE));
2N/A (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
2N/A (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
2N/A i = 0;
2N/A SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
2N/A SETATTR(templ, i, CKA_CLASS, &oclass, sizeof (oclass)); i++;
2N/A SETATTR(templ, i, CKA_CERTIFICATE_TYPE, &ctype, sizeof (ctype)); i++;
2N/A
2N/A if (label != NULL && strlen(label)) {
2N/A SETATTR(templ, i, CKA_LABEL, label, strlen(label));
2N/A i++;
2N/A }
2N/A if (private) {
2N/A SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true)); i++;
2N/A }
2N/A
2N/A if (issuer != NULL && strlen(issuer)) {
2N/A if ((rv = kmf_dn_parser(issuer, &issuerDN)) != KMF_OK)
2N/A return (rv);
2N/A }
2N/A if (subject != NULL && strlen(subject)) {
2N/A if ((rv = kmf_dn_parser(subject, &subjectDN)) != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A if (serial != NULL && serial->val != NULL && serial->len > 0) {
2N/A SETATTR(templ, i, CKA_SERIAL_NUMBER, serial->val, serial->len);
2N/A i++;
2N/A }
2N/A
2N/A (*numobj) = 0;
2N/A *objlist = NULL;
2N/A newlist = NULL;
2N/A
2N/A ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, i);
2N/A if (ckrv != CKR_OK)
2N/A goto cleanup;
2N/A
2N/A tail = newlist = NULL;
2N/A while (ckrv == CKR_OK) {
2N/A CK_OBJECT_HANDLE tObj;
2N/A ckrv = C_FindObjects(kmfh->pk11handle, &tObj, 1, &num);
2N/A if (ckrv != CKR_OK || num == 0)
2N/A break;
2N/A
2N/A /*
2N/A * 'matchcert' returns 0 if subject/issuer match
2N/A *
2N/A * If no match, move on to the next one
2N/A */
2N/A if (matchcert(kmfh, tObj, &issuerDN, &subjectDN))
2N/A continue;
2N/A
2N/A if (newlist == NULL) {
2N/A newlist = malloc(sizeof (OBJLIST));
2N/A if (newlist == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A break;
2N/A }
2N/A newlist->handle = tObj;
2N/A newlist->next = NULL;
2N/A tail = newlist;
2N/A } else {
2N/A tail->next = malloc(sizeof (OBJLIST));
2N/A if (tail->next != NULL) {
2N/A tail = tail->next;
2N/A } else {
2N/A rv = KMF_ERR_MEMORY;
2N/A break;
2N/A }
2N/A tail->handle = tObj;
2N/A tail->next = NULL;
2N/A }
2N/A (*numobj)++;
2N/A }
2N/A ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2N/A
2N/Acleanup:
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A if (newlist != NULL) {
2N/A free_objlist(newlist);
2N/A *numobj = 0;
2N/A newlist = NULL;
2N/A }
2N/A } else {
2N/A if (validity == KMF_ALL_CERTS) {
2N/A *objlist = newlist;
2N/A } else {
2N/A OBJLIST *node, *prev;
2N/A KMF_X509_DER_CERT tmp_kmf_cert;
2N/A uint32_t i = 0;
2N/A
2N/A node = prev = newlist;
2N/A /*
2N/A * Now check to see if any found certificate is expired
2N/A * or valid.
2N/A */
2N/A while (node != NULL && i < (*numobj)) {
2N/A (void) memset(&tmp_kmf_cert, 0,
2N/A sizeof (KMF_X509_DER_CERT));
2N/A rv = PK11Cert2KMFCert(kmfh, node->handle,
2N/A &tmp_kmf_cert);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup1;
2N/A }
2N/A
2N/A rv = kmf_check_cert_date(handle,
2N/A &tmp_kmf_cert.certificate);
2N/A
2N/A if (validity == KMF_NONEXPIRED_CERTS) {
2N/A if (rv == KMF_OK) {
2N/A num_ok_certs++;
2N/A prev = node;
2N/A node = node->next;
2N/A } else if (rv ==
2N/A KMF_ERR_VALIDITY_PERIOD) {
2N/A /*
2N/A * expired - remove it from list
2N/A */
2N/A pk11_delete_obj_from_list(
2N/A &newlist, &prev, &node);
2N/A } else {
2N/A goto cleanup1;
2N/A }
2N/A }
2N/A
2N/A if (validity == KMF_EXPIRED_CERTS) {
2N/A if (rv == KMF_ERR_VALIDITY_PERIOD) {
2N/A num_ok_certs++;
2N/A prev = node;
2N/A node = node->next;
2N/A rv = KMF_OK;
2N/A } else if (rv == KMF_OK) {
2N/A /*
2N/A * valid - remove it from list
2N/A */
2N/A pk11_delete_obj_from_list(
2N/A &newlist, &prev, &node);
2N/A } else {
2N/A goto cleanup1;
2N/A }
2N/A }
2N/A i++;
2N/A kmf_free_kmf_cert(handle, &tmp_kmf_cert);
2N/A }
2N/A *numobj = num_ok_certs;
2N/A *objlist = newlist;
2N/A }
2N/A }
2N/A
2N/Acleanup1:
2N/A if (rv != KMF_OK && newlist != NULL) {
2N/A free_objlist(newlist);
2N/A *numobj = 0;
2N/A *objlist = NULL;
2N/A }
2N/A
2N/A if (issuer != NULL)
2N/A kmf_free_dn(&issuerDN);
2N/A
2N/A if (subject != NULL)
2N/A kmf_free_dn(&subjectDN);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * The caller may pass a NULL value for kmf_cert below and the function will
2N/A * just return the number of certs found (in num_certs).
2N/A */
2N/AKMF_RETURN
2N/AKMFPK11_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A uint32_t want_certs;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A OBJLIST *objlist = NULL;
2N/A uint32_t *num_certs;
2N/A KMF_X509_DER_CERT *kmf_cert = NULL;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A KMF_CERT_VALIDITY validity;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A boolean_t private;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2N/A if (num_certs == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (*num_certs > 0)
2N/A want_certs = *num_certs;
2N/A else
2N/A want_certs = MAXINT; /* count them all */
2N/A
2N/A *num_certs = 0;
2N/A
2N/A /* Get the optional returned certificate list */
2N/A kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
2N/A numattr);
2N/A
2N/A /* Get optional search criteria attributes */
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A
2N/A rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
2N/A &validity, NULL);
2N/A if (rv != KMF_OK) {
2N/A validity = KMF_ALL_CERTS;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&private, NULL);
2N/A if (rv != KMF_OK) {
2N/A private = B_FALSE;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred != NULL) {
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A /* Start searching */
2N/A rv = search_certs(handle, certlabel, issuer, subject, serial, private,
2N/A validity, &objlist, num_certs);
2N/A
2N/A if (rv == KMF_OK && objlist != NULL && kmf_cert != NULL) {
2N/A OBJLIST *node = objlist;
2N/A int i = 0;
2N/A while (node != NULL && i < want_certs) {
2N/A rv = PK11Cert2KMFCert(kmfh, node->handle,
2N/A &kmf_cert[i]);
2N/A i++;
2N/A node = node->next;
2N/A }
2N/A }
2N/A
2N/A if (objlist != NULL)
2N/A free_objlist(objlist);
2N/A
2N/A if (*num_certs == 0)
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A/*ARGSUSED*/
2N/Avoid
2N/AKMFPK11_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
2N/A{
2N/A if (kmf_cert != NULL && kmf_cert->certificate.Data != NULL) {
2N/A free(kmf_cert->certificate.Data);
2N/A kmf_cert->certificate.Data = NULL;
2N/A kmf_cert->certificate.Length = 0;
2N/A
2N/A if (kmf_cert->kmf_private.label != NULL) {
2N/A free(kmf_cert->kmf_private.label);
2N/A kmf_cert->kmf_private.label = NULL;
2N/A }
2N/A }
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
2N/A KMF_DATA *eData)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A CK_RV rv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY;
2N/A CK_KEY_TYPE ckKeyType;
2N/A KMF_DATA Modulus, Exponent, Prime, Subprime, Base, Value;
2N/A KMF_OID *Algorithm;
2N/A BerElement *asn1 = NULL;
2N/A BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
2N/A KMF_X509_SPKI spki;
2N/A CK_BYTE ec_params[256], ec_point[256];
2N/A
2N/A CK_ATTRIBUTE rsaTemplate[4];
2N/A CK_ATTRIBUTE dsaTemplate[6];
2N/A CK_ATTRIBUTE ecdsaTemplate[6];
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (pKey == NULL || pKey->keyp == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(&Modulus, 0, sizeof (Modulus));
2N/A (void) memset(&Exponent, 0, sizeof (Exponent));
2N/A (void) memset(&Prime, 0, sizeof (Prime));
2N/A (void) memset(&Subprime, 0, sizeof (Subprime));
2N/A (void) memset(&Base, 0, sizeof (Base));
2N/A (void) memset(&Value, 0, sizeof (Value));
2N/A
2N/A switch (pKey->keyalg) {
2N/A case KMF_RSA:
2N/A SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass,
2N/A sizeof (ckObjClass));
2N/A SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
2N/A sizeof (ckKeyType));
2N/A SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
2N/A Modulus.Length);
2N/A SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
2N/A Exponent.Data, Exponent.Length);
2N/A /* Get the length of the fields */
2N/A rv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A Modulus.Length = rsaTemplate[2].ulValueLen;
2N/A Modulus.Data = malloc(Modulus.Length);
2N/A if (Modulus.Data == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A Exponent.Length = rsaTemplate[3].ulValueLen;
2N/A Exponent.Data = malloc(Exponent.Length);
2N/A if (Exponent.Data == NULL) {
2N/A free(Modulus.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
2N/A Modulus.Length);
2N/A SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
2N/A Exponent.Data, Exponent.Length);
2N/A /* Now get the values */
2N/A rv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A free(Modulus.Data);
2N/A free(Exponent.Data);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A /*
2N/A * This is the KEY algorithm, not the
2N/A * signature algorithm.
2N/A */
2N/A Algorithm = x509_algid_to_algoid(KMF_ALGID_RSA);
2N/A if (Algorithm != NULL) {
2N/A
2N/A /* Encode the RSA Key Data */
2N/A if ((asn1 = kmfder_alloc()) == NULL) {
2N/A free(Modulus.Data);
2N/A free(Exponent.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A if (kmfber_printf(asn1, "{II}", Modulus.Data,
2N/A Modulus.Length, Exponent.Data,
2N/A Exponent.Length) == -1) {
2N/A kmfber_free(asn1, 1);
2N/A free(Modulus.Data);
2N/A free(Exponent.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A if (kmfber_flatten(asn1, &EncodedKey) == -1) {
2N/A kmfber_free(asn1, 1);
2N/A free(Modulus.Data);
2N/A free(Exponent.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A kmfber_free(asn1, 1);
2N/A }
2N/A
2N/A free(Exponent.Data);
2N/A free(Modulus.Data);
2N/A
2N/A break;
2N/A case KMF_DSA:
2N/A SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass,
2N/A sizeof (ckObjClass));
2N/A SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
2N/A sizeof (ckKeyType));
2N/A SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
2N/A Prime.Length);
2N/A SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
2N/A Subprime.Length);
2N/A SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
2N/A Base.Length);
2N/A SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
2N/A Value.Length);
2N/A
2N/A /* Get the length of the fields */
2N/A rv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A Prime.Length = dsaTemplate[2].ulValueLen;
2N/A Prime.Data = malloc(Prime.Length);
2N/A if (Prime.Data == NULL) {
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A Subprime.Length = dsaTemplate[3].ulValueLen;
2N/A Subprime.Data = malloc(Subprime.Length);
2N/A if (Subprime.Data == NULL) {
2N/A free(Prime.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A Base.Length = dsaTemplate[4].ulValueLen;
2N/A Base.Data = malloc(Base.Length);
2N/A if (Base.Data == NULL) {
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A Value.Length = dsaTemplate[5].ulValueLen;
2N/A Value.Data = malloc(Value.Length);
2N/A if (Value.Data == NULL) {
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
2N/A Prime.Length);
2N/A SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
2N/A Subprime.Length);
2N/A SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
2N/A Base.Length);
2N/A SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
2N/A Value.Length);
2N/A
2N/A /* Now get the values */
2N/A rv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6);
2N/A if (rv != CKR_OK) {
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A free(Value.Data);
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A /*
2N/A * This is the KEY algorithm, not the
2N/A * signature algorithm.
2N/A */
2N/A Algorithm = x509_algid_to_algoid(KMF_ALGID_DSA);
2N/A
2N/A /* Encode the DSA Algorithm Parameters */
2N/A if ((asn1 = kmfder_alloc()) == NULL) {
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A free(Value.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A if (kmfber_printf(asn1, "{III}", Prime.Data,
2N/A Prime.Length, Subprime.Data, Subprime.Length,
2N/A Base.Data, Base.Length) == -1) {
2N/A
2N/A kmfber_free(asn1, 1);
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A free(Value.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A if (kmfber_flatten(asn1, &PubKeyParams) == -1) {
2N/A kmfber_free(asn1, 1);
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A free(Value.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A kmfber_free(asn1, 1);
2N/A free(Prime.Data);
2N/A free(Subprime.Data);
2N/A free(Base.Data);
2N/A
2N/A /* Encode the DSA Key Value */
2N/A if ((asn1 = kmfder_alloc()) == NULL) {
2N/A free(Value.Data);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A if (kmfber_printf(asn1, "I",
2N/A Value.Data, Value.Length) == -1) {
2N/A kmfber_free(asn1, 1);
2N/A free(Value.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A if (kmfber_flatten(asn1, &EncodedKey) == -1) {
2N/A kmfber_free(asn1, 1);
2N/A free(Value.Data);
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A kmfber_free(asn1, 1);
2N/A free(Value.Data);
2N/A break;
2N/A case KMF_ECDSA:
2N/A /* The EC_PARAMS are the PubKey algorithm parameters */
2N/A PubKeyParams = calloc(1, sizeof (BerValue));
2N/A if (PubKeyParams == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A EncodedKey = calloc(1, sizeof (BerValue));
2N/A if (EncodedKey == NULL) {
2N/A free(PubKeyParams);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A SETATTR(ecdsaTemplate, 0, CKA_EC_PARAMS,
2N/A &ec_params, sizeof (ec_params));
2N/A SETATTR(ecdsaTemplate, 1, CKA_EC_POINT,
2N/A &ec_point, sizeof (ec_point));
2N/A
2N/A /* Get the length of the fields */
2N/A rv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pKey->keyp,
2N/A ecdsaTemplate, 2);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A /* The params are to be used as algorithm parameters */
2N/A PubKeyParams->bv_val = (char *)ec_params;
2N/A PubKeyParams->bv_len = ecdsaTemplate[0].ulValueLen;
2N/A /*
2N/A * The EC_POINT is to be used as the subject pub key.
2N/A */
2N/A EncodedKey->bv_val = (char *)ec_point;
2N/A EncodedKey->bv_len = ecdsaTemplate[1].ulValueLen;
2N/A
2N/A /* Use the EC_PUBLIC_KEY OID */
2N/A Algorithm = (KMF_OID *)&KMFOID_EC_PUBLIC_KEY;
2N/A break;
2N/A default:
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A /* Now, build an SPKI structure for the final encoding step */
2N/A spki.algorithm.algorithm = *Algorithm;
2N/A if (PubKeyParams != NULL) {
2N/A spki.algorithm.parameters.Data =
2N/A (uchar_t *)PubKeyParams->bv_val;
2N/A spki.algorithm.parameters.Length = PubKeyParams->bv_len;
2N/A } else {
2N/A spki.algorithm.parameters.Data = NULL;
2N/A spki.algorithm.parameters.Length = 0;
2N/A }
2N/A
2N/A if (EncodedKey != NULL) {
2N/A spki.subjectPublicKey.Data = (uchar_t *)EncodedKey->bv_val;
2N/A spki.subjectPublicKey.Length = EncodedKey->bv_len;
2N/A } else {
2N/A spki.subjectPublicKey.Data = NULL;
2N/A spki.subjectPublicKey.Length = 0;
2N/A }
2N/A
2N/A /* Finally, encode the entire SPKI record */
2N/A ret = DerEncodeSPKI(&spki, eData);
2N/A
2N/Acleanup:
2N/A if (EncodedKey) {
2N/A if (pKey->keyalg != KMF_ECDSA)
2N/A free(EncodedKey->bv_val);
2N/A free(EncodedKey);
2N/A }
2N/A
2N/A if (PubKeyParams) {
2N/A if (pKey->keyalg != KMF_ECDSA)
2N/A free(PubKeyParams->bv_val);
2N/A free(PubKeyParams);
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/ACreateCertObject(KMF_HANDLE_T handle, char *label, KMF_DATA *pcert)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A KMF_X509_CERTIFICATE *signed_cert_ptr = NULL;
2N/A KMF_DATA data;
2N/A KMF_DATA Id;
2N/A
2N/A CK_RV ckrv;
2N/A CK_ULONG subject_len, issuer_len, serno_len;
2N/A CK_BYTE *subject, *issuer, *serial, nullserno;
2N/A CK_BBOOL true = TRUE;
2N/A CK_CERTIFICATE_TYPE certtype = CKC_X_509;
2N/A CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
2N/A CK_ATTRIBUTE x509templ[11];
2N/A CK_OBJECT_HANDLE hCert = NULL;
2N/A int i;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_INTERNAL); /* should not happen */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_INTERNAL); /* should not happen */
2N/A
2N/A if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0)
2N/A return (KMF_ERR_INTERNAL); /* should not happen */
2N/A
2N/A /*
2N/A * The data *must* be a DER encoded X.509 certificate.
2N/A * Convert it to a CSSM cert and then parse the fields so
2N/A * the PKCS#11 attributes can be filled in correctly.
2N/A */
2N/A rv = DerDecodeSignedCertificate((const KMF_DATA *)pcert,
2N/A &signed_cert_ptr);
2N/A if (rv != KMF_OK) {
2N/A return (KMF_ERR_ENCODING);
2N/A }
2N/A
2N/A /*
2N/A * Encode fields into PKCS#11 attributes.
2N/A */
2N/A
2N/A /* Get the subject name */
2N/A rv = DerEncodeName(&signed_cert_ptr->certificate.subject, &data);
2N/A if (rv == KMF_OK) {
2N/A subject = data.Data;
2N/A subject_len = data.Length;
2N/A } else {
2N/A rv = KMF_ERR_ENCODING;
2N/A goto cleanup;
2N/A }
2N/A
2N/A /* Encode the issuer */
2N/A rv = DerEncodeName(&signed_cert_ptr->certificate.issuer, &data);
2N/A if (rv == KMF_OK) {
2N/A issuer = data.Data;
2N/A issuer_len = data.Length;
2N/A } else {
2N/A rv = KMF_ERR_ENCODING;
2N/A goto cleanup;
2N/A }
2N/A
2N/A /* Encode serial number */
2N/A if (signed_cert_ptr->certificate.serialNumber.len > 0 &&
2N/A signed_cert_ptr->certificate.serialNumber.val != NULL) {
2N/A serial = signed_cert_ptr->certificate.serialNumber.val;
2N/A serno_len = signed_cert_ptr->certificate.serialNumber.len;
2N/A } else {
2N/A /*
2N/A * RFC3280 says to gracefully handle certs with serial numbers
2N/A * of 0.
2N/A */
2N/A nullserno = '\0';
2N/A serial = &nullserno;
2N/A serno_len = 1;
2N/A }
2N/A
2N/A /* Generate an ID from the SPKI data */
2N/A rv = GetIDFromSPKI(&signed_cert_ptr->certificate.subjectPublicKeyInfo,
2N/A &Id);
2N/A
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A
2N/A i = 0;
2N/A SETATTR(x509templ, i, CKA_CLASS, &certClass, sizeof (certClass)); i++;
2N/A SETATTR(x509templ, i, CKA_CERTIFICATE_TYPE, &certtype,
2N/A sizeof (certtype));
2N/A i++;
2N/A SETATTR(x509templ, i, CKA_TOKEN, &true, sizeof (true)); i++;
2N/A SETATTR(x509templ, i, CKA_SUBJECT, subject, subject_len); i++;
2N/A SETATTR(x509templ, i, CKA_ISSUER, issuer, issuer_len); i++;
2N/A SETATTR(x509templ, i, CKA_SERIAL_NUMBER, serial, serno_len); i++;
2N/A SETATTR(x509templ, i, CKA_VALUE, pcert->Data, pcert->Length); i++;
2N/A SETATTR(x509templ, i, CKA_ID, Id.Data, Id.Length); i++;
2N/A if (label != NULL && strlen(label)) {
2N/A SETATTR(x509templ, i, CKA_LABEL, label, strlen(label)); i++;
2N/A }
2N/A /*
2N/A * The cert object handle is actually "leaked" here. If the app
2N/A * really wants to clean up the data space, it will have to call
2N/A * KMF_DeleteCert and specify the softtoken keystore.
2N/A */
2N/A ckrv = C_CreateObject(kmfh->pk11handle, x509templ, i, &hCert);
2N/A if (ckrv != CKR_OK) {
2N/A /* Report authentication failures to the caller */
2N/A if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2N/A ckrv == CKR_PIN_INCORRECT ||
2N/A ckrv == CKR_PIN_INVALID ||
2N/A ckrv == CKR_PIN_EXPIRED ||
2N/A ckrv == CKR_PIN_LOCKED ||
2N/A ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_INTERNAL;
2N/A SET_ERROR(kmfh, ckrv);
2N/A }
2N/A free(subject);
2N/A free(issuer);
2N/A
2N/Acleanup:
2N/A if (Id.Data != NULL)
2N/A free(Id.Data);
2N/A
2N/A if (signed_cert_ptr) {
2N/A kmf_free_signed_cert(signed_cert_ptr);
2N/A free(signed_cert_ptr);
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A KMF_DATA *cert = NULL;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A char *label = NULL;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert == NULL || cert->Data == NULL || cert->Length == 0)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* label attribute is optional */
2N/A label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred != NULL) {
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A rv = CreateCertObject(handle, label, cert);
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A char *certfile = NULL;
2N/A char *label = NULL;
2N/A KMF_ENCODE_FORMAT format;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A KMF_DATA cert1 = { NULL, 0};
2N/A KMF_DATA cert2 = { NULL, 0};
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A /*
2N/A * Get the input cert filename attribute, check if it is a valid
2N/A * certificate and auto-detect the file format of it.
2N/A */
2N/A certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2N/A if (certfile == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_is_cert_file(handle, certfile, &format);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* Read in the CERT file */
2N/A rv = kmf_read_input_file(handle, certfile, &cert1);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* The label attribute is optional */
2N/A label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A
2N/A /*
2N/A * If the input certificate is in PEM format, we need to convert
2N/A * it to DER first.
2N/A */
2N/A if (format == KMF_FORMAT_PEM) {
2N/A int derlen;
2N/A rv = kmf_pem_to_der(cert1.Data, cert1.Length,
2N/A &cert2.Data, &derlen);
2N/A if (rv != KMF_OK) {
2N/A goto out;
2N/A }
2N/A cert2.Length = (size_t)derlen;
2N/A }
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred != NULL) {
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A rv = CreateCertObject(handle, label,
2N/A format == KMF_FORMAT_ASN1 ? &cert1 : &cert2);
2N/A
2N/Aout:
2N/A if (cert1.Data != NULL) {
2N/A free(cert1.Data);
2N/A }
2N/A
2N/A if (cert2.Data != NULL) {
2N/A free(cert2.Data);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = 0;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A OBJLIST *objlist;
2N/A uint32_t numObjects = 0;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A KMF_CERT_VALIDITY validity;
2N/A boolean_t private;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A
2N/A /* Get the search criteria attributes. They are all optional. */
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A
2N/A rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
2N/A &validity, NULL);
2N/A if (rv != KMF_OK) {
2N/A validity = KMF_ALL_CERTS;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&private, NULL);
2N/A if (rv != KMF_OK) {
2N/A private = B_FALSE;
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A /*
2N/A * Start searching for certificates that match the criteria and
2N/A * delete them.
2N/A */
2N/A objlist = NULL;
2N/A rv = search_certs(handle, certlabel, issuer, subject, serial,
2N/A private, validity, &objlist, &numObjects);
2N/A
2N/A if (rv == KMF_OK && objlist != NULL) {
2N/A OBJLIST *node = objlist;
2N/A
2N/A while (node != NULL) {
2N/A CK_RV ckrv;
2N/A ckrv = C_DestroyObject(kmfh->pk11handle, node->handle);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A break;
2N/A }
2N/A node = node->next;
2N/A }
2N/A free_objlist(objlist);
2N/A }
2N/A
2N/A if (rv == KMF_OK && numObjects == 0)
2N/A rv = KMF_ERR_CERT_NOT_FOUND;
2N/A
2N/Aout:
2N/A return (rv);
2N/A}
2N/A
2N/Astatic CK_RV
2N/Agendsa_keypair(KMF_HANDLE *kmfh, boolean_t storekey,
2N/A CK_OBJECT_HANDLE *pubKey,
2N/A CK_OBJECT_HANDLE *priKey)
2N/A{
2N/A CK_RV ckrv = CKR_OK;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A static CK_ULONG dsaKeyType = CKK_DSA;
2N/A static CK_BBOOL true = TRUE;
2N/A static CK_BBOOL false = FALSE;
2N/A static CK_OBJECT_CLASS priClass = CKO_PRIVATE_KEY;
2N/A static CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
2N/A
2N/A static CK_BYTE ckDsaPrime[128] = {
2N/A 0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
2N/A 0xcf, 0xdd, 0xf9, 0xae, 0x3e, 0x39, 0x7f, 0x9c,
2N/A 0xa7, 0x73, 0xc3, 0x00, 0xa3, 0x50, 0x67, 0xc3,
2N/A 0xab, 0x49, 0x2c, 0xea, 0x59, 0x10, 0xa4, 0xbc,
2N/A 0x09, 0x94, 0xa9, 0x05, 0x3b, 0x0d, 0x35, 0x3c,
2N/A 0x55, 0x52, 0x47, 0xf0, 0xe3, 0x72, 0x5b, 0xe8,
2N/A 0x72, 0xa0, 0x71, 0x1c, 0x23, 0x4f, 0x6d, 0xe8,
2N/A 0xac, 0xe5, 0x21, 0x1b, 0xc0, 0xd8, 0x42, 0xd3,
2N/A 0x87, 0xae, 0x83, 0x5e, 0x52, 0x7e, 0x46, 0x09,
2N/A 0xb5, 0xc7, 0x3d, 0xd6, 0x00, 0xf5, 0xf2, 0x9c,
2N/A 0x84, 0x30, 0x81, 0x7e, 0x7b, 0x30, 0x5b, 0xd5,
2N/A 0xab, 0xd0, 0x2f, 0x21, 0xb3, 0xd8, 0xed, 0xdb,
2N/A 0x97, 0x77, 0xe4, 0x7e, 0x6c, 0xcc, 0xb9, 0x6b,
2N/A 0xdd, 0xaa, 0x96, 0x04, 0xe7, 0xd4, 0x55, 0x11,
2N/A 0x53, 0xab, 0xba, 0x95, 0x9a, 0xa2, 0x8c, 0x27,
2N/A 0xd9, 0xcf, 0xad, 0xf3, 0xcf, 0x3a, 0x0c, 0x4b};
2N/A
2N/A static CK_BYTE ckDsaSubPrime[20] = {
2N/A 0xa4, 0x5f, 0x2a, 0x27, 0x09, 0x49, 0xb6, 0xfe,
2N/A 0x73, 0xeb, 0x95, 0x7d, 0x00, 0xf3, 0x42, 0xfc,
2N/A 0x78, 0x47, 0xb0, 0xd5};
2N/A
2N/A static CK_BYTE ckDsaBase[128] = {
2N/A 0x5c, 0x57, 0x16, 0x49, 0xef, 0xc8, 0xfb, 0x4b,
2N/A 0xee, 0x07, 0x45, 0x3b, 0x6a, 0x1d, 0xf3, 0xe5,
2N/A 0xeb, 0xee, 0xad, 0x11, 0x13, 0xe3, 0x52, 0xe3,
2N/A 0x0d, 0xc0, 0x21, 0x25, 0xfa, 0xf0, 0x93, 0x1c,
2N/A 0x53, 0x4d, 0xdc, 0x0d, 0x76, 0xd2, 0xfe, 0xc2,
2N/A 0xd7, 0x72, 0x64, 0x69, 0x53, 0x3d, 0x33, 0xbd,
2N/A 0xe1, 0x34, 0xf2, 0x5a, 0x67, 0x83, 0xe0, 0xd3,
2N/A 0x1c, 0xd6, 0x41, 0x4d, 0x16, 0xe8, 0x6c, 0x5a,
2N/A 0x07, 0x95, 0x21, 0x9a, 0xa3, 0xc4, 0xb9, 0x05,
2N/A 0x9d, 0x11, 0xcb, 0xc8, 0xc4, 0x9d, 0x00, 0x1a,
2N/A 0xf4, 0x85, 0x2a, 0xa9, 0x20, 0x3c, 0xba, 0x67,
2N/A 0xe5, 0xed, 0x31, 0xb2, 0x11, 0xfb, 0x1f, 0x73,
2N/A 0xec, 0x61, 0x29, 0xad, 0xc7, 0x68, 0xb2, 0x3f,
2N/A 0x38, 0xea, 0xd9, 0x87, 0x83, 0x9e, 0x7e, 0x19,
2N/A 0x18, 0xdd, 0xc2, 0xc3, 0x5b, 0x16, 0x6d, 0xce,
2N/A 0xcf, 0x88, 0x91, 0x07, 0xe0, 0x2b, 0xa8, 0x54 };
2N/A
2N/A static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
2N/A { CKA_CLASS, &pubClass, sizeof (pubClass) },
2N/A { CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
2N/A { CKA_TOKEN, &true, sizeof (true)},
2N/A { CKA_PRIVATE, &true, sizeof (true)},
2N/A { CKA_VERIFY, &true, sizeof (true) },
2N/A { CKA_PRIME, ckDsaPrime, sizeof (ckDsaPrime) },
2N/A { CKA_SUBPRIME, ckDsaSubPrime, sizeof (ckDsaSubPrime)},
2N/A { CKA_BASE, ckDsaBase, sizeof (ckDsaBase) },
2N/A };
2N/A
2N/A#define NUMBER_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
2N/A sizeof (CK_ATTRIBUTE))
2N/A#define MAX_DSA_PUB_TEMPLATES (sizeof (ckDsaPubKeyTemplate) / \
2N/A sizeof (CK_ATTRIBUTE))
2N/A
2N/A static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
2N/A {CKA_CLASS, &priClass, sizeof (priClass)},
2N/A {CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
2N/A {CKA_TOKEN, &true, sizeof (true)},
2N/A {CKA_PRIVATE, &true, sizeof (true)},
2N/A {CKA_SENSITIVE, &false, sizeof (false)},
2N/A {CKA_SIGN, &true, sizeof (true)},
2N/A };
2N/A
2N/A#define NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
2N/A sizeof (CK_ATTRIBUTE))
2N/A#define MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
2N/A sizeof (CK_ATTRIBUTE))
2N/A CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
2N/A
2N/A SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
2N/A (storekey ? &true : &false), sizeof (CK_BBOOL));
2N/A
2N/A ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
2N/A ckDsaPubKeyTemplate,
2N/A (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
2N/A ckDsaPriKeyTemplate,
2N/A (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
2N/A pubKey, priKey);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_KEYGEN_FAILED);
2N/A }
2N/A
2N/A return (ckrv);
2N/A}
2N/A
2N/Astatic CK_RV
2N/Agenrsa_keypair(KMF_HANDLE *kmfh, CK_ULONG modulusBits,
2N/A boolean_t storekey, KMF_BIGINT *rsaexp,
2N/A CK_OBJECT_HANDLE *pubKey,
2N/A CK_OBJECT_HANDLE *priKey)
2N/A{
2N/A CK_RV ckrv = CKR_OK;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_ATTRIBUTE rsaPubKeyTemplate[16];
2N/A CK_ATTRIBUTE rsaPriKeyTemplate[16];
2N/A CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0};
2N/A int numpubattr = 0, numpriattr = 0;
2N/A static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
2N/A static CK_BBOOL true = TRUE;
2N/A static CK_BBOOL false = FALSE;
2N/A
2N/A SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN,
2N/A (storekey ? &true : &false), sizeof (CK_BBOOL));
2N/A numpubattr++;
2N/A
2N/A SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS,
2N/A &modulusBits, sizeof (modulusBits));
2N/A numpubattr++;
2N/A
2N/A if (rsaexp != NULL && (rsaexp->len > 0 && rsaexp->val != NULL)) {
2N/A SETATTR(rsaPubKeyTemplate, numpubattr,
2N/A CKA_PUBLIC_EXPONENT,
2N/A rsaexp->val, rsaexp->len);
2N/A numpubattr++;
2N/A } else {
2N/A SETATTR(rsaPubKeyTemplate, numpubattr,
2N/A CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo));
2N/A numpubattr++;
2N/A }
2N/A SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT,
2N/A &true, sizeof (true));
2N/A numpubattr++;
2N/A SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY,
2N/A &true, sizeof (true));
2N/A numpubattr++;
2N/A SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP,
2N/A &true, sizeof (true));
2N/A numpubattr++;
2N/A
2N/A SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN,
2N/A (storekey ? &true : &false), sizeof (CK_BBOOL));
2N/A numpriattr++;
2N/A SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true,
2N/A sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true,
2N/A sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true,
2N/A sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true,
2N/A sizeof (true));
2N/A numpriattr++;
2N/A
2N/A ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
2N/A rsaPubKeyTemplate, numpubattr,
2N/A rsaPriKeyTemplate, numpriattr,
2N/A pubKey, priKey);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (ckrv);
2N/A }
2N/A
2N/A return (ckrv);
2N/A}
2N/A
2N/Astatic CK_RV
2N/Agenecc_keypair(KMF_HANDLE *kmfh,
2N/A boolean_t ontoken,
2N/A KMF_OID *curveoid,
2N/A CK_OBJECT_HANDLE *pubKey,
2N/A CK_OBJECT_HANDLE *priKey)
2N/A{
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_MECHANISM keyGenMech = {CKM_EC_KEY_PAIR_GEN, NULL, 0};
2N/A const ulong_t publicKey = CKO_PUBLIC_KEY;
2N/A const ulong_t privateKey = CKO_PRIVATE_KEY;
2N/A const ulong_t keytype = CKK_EC;
2N/A static CK_BBOOL true = TRUE;
2N/A static CK_BBOOL false = FALSE;
2N/A CK_ATTRIBUTE public_template[6];
2N/A CK_ATTRIBUTE private_template[6];
2N/A int numpubattr, numpriattr;
2N/A
2N/A numpubattr = 0;
2N/A SETATTR(public_template, numpubattr, CKA_CLASS,
2N/A &publicKey, sizeof (publicKey));
2N/A numpubattr++;
2N/A SETATTR(public_template, numpubattr, CKA_KEY_TYPE,
2N/A &keytype, sizeof (keytype));
2N/A numpubattr++;
2N/A SETATTR(public_template, numpubattr, CKA_EC_PARAMS,
2N/A curveoid->Data, curveoid->Length);
2N/A numpubattr++;
2N/A SETATTR(public_template, numpubattr, CKA_TOKEN,
2N/A ontoken ? &true : &false, sizeof (true));
2N/A numpubattr++;
2N/A SETATTR(public_template, numpubattr, CKA_VERIFY,
2N/A &true, sizeof (true));
2N/A numpubattr++;
2N/A SETATTR(public_template, numpubattr, CKA_PRIVATE,
2N/A &false, sizeof (false));
2N/A numpubattr++;
2N/A
2N/A numpriattr = 0;
2N/A SETATTR(private_template, numpriattr, CKA_CLASS,
2N/A &privateKey, sizeof (privateKey));
2N/A numpriattr++;
2N/A SETATTR(private_template, numpriattr, CKA_KEY_TYPE,
2N/A &keytype, sizeof (keytype));
2N/A numpriattr++;
2N/A SETATTR(private_template, numpriattr, CKA_TOKEN,
2N/A ontoken ? &true : &false, sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(private_template, numpriattr, CKA_PRIVATE,
2N/A &true, sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(private_template, numpriattr, CKA_SIGN,
2N/A &true, sizeof (true));
2N/A numpriattr++;
2N/A SETATTR(private_template, numpriattr, CKA_DERIVE,
2N/A &true, sizeof (true));
2N/A numpriattr++;
2N/A
2N/A ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
2N/A public_template, numpubattr,
2N/A private_template, numpriattr,
2N/A pubKey, priKey);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (ckrv);
2N/A }
2N/A
2N/A return (ckrv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_CreateKeypair(KMF_HANDLE_T handle,
2N/A int numattr,
2N/A KMF_ATTRIBUTE *attlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A KMF_DATA IDInput, IDOutput;
2N/A KMF_CREDENTIAL *cred;
2N/A KMF_KEY_ALG keytype = KMF_RSA;
2N/A KMF_KEY_HANDLE *pubkey, *privkey;
2N/A
2N/A CK_RV ckrv = 0;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_ATTRIBUTE labelattr[1];
2N/A CK_ATTRIBUTE idattr[1];
2N/A CK_OBJECT_HANDLE pubKey, priKey;
2N/A
2N/A char IDHashData[SHA1_HASH_LENGTH];
2N/A static CK_ULONG modulusBits = 1024;
2N/A uint32_t modulusBits_size = sizeof (CK_ULONG);
2N/A SHA1_CTX ctx;
2N/A boolean_t storekey = TRUE;
2N/A char *keylabel = NULL;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A /* "storekey" is optional. Default is TRUE */
2N/A (void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attlist, numattr,
2N/A &storekey, NULL);
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attlist, numattr);
2N/A if (cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* keytype is optional. KMF_RSA is default */
2N/A (void) kmf_get_attr(KMF_KEYALG_ATTR, attlist, numattr,
2N/A (void *)&keytype, NULL);
2N/A
2N/A pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
2N/A if (pubkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist, numattr);
2N/A if (privkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
2N/A (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
2N/A if (keytype == KMF_RSA) {
2N/A CK_BYTE *modulus = NULL;
2N/A CK_ULONG modulusLength = 0;
2N/A KMF_BIGINT *rsaexp = NULL;
2N/A CK_ATTRIBUTE modattr[1];
2N/A
2N/A rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attlist, numattr,
2N/A &modulusBits, &modulusBits_size);
2N/A if (rv == KMF_ERR_ATTR_NOT_FOUND)
2N/A /* Default modulusBits = 1024 */
2N/A rv = KMF_OK;
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist, numattr);
2N/A
2N/A /* Generate the RSA keypair */
2N/A ckrv = genrsa_keypair(kmfh, modulusBits, storekey,
2N/A rsaexp, &pubKey, &priKey);
2N/A
2N/A if (ckrv != CKR_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A privkey->keyalg = KMF_RSA;
2N/A privkey->keyclass = KMF_ASYM_PRI;
2N/A privkey->keyp = (void *)priKey;
2N/A
2N/A pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A pubkey->keyalg = KMF_RSA;
2N/A pubkey->keyclass = KMF_ASYM_PUB;
2N/A pubkey->keyp = (void *)pubKey;
2N/A
2N/A SETATTR(modattr, 0, CKA_MODULUS, NULL, modulusLength);
2N/A /* Get the Modulus field to use as input for creating the ID */
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pubKey, modattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A modulusLength = modattr[0].ulValueLen;
2N/A modulus = malloc(modulusLength);
2N/A if (modulus == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A modattr[0].pValue = modulus;
2N/A ckrv = C_GetAttributeValue(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)pubKey, modattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A free(modulus);
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A IDInput.Data = modulus;
2N/A IDInput.Length = modulusLength;
2N/A
2N/A } else if (keytype == KMF_DSA) {
2N/A CK_BYTE *keyvalue;
2N/A CK_ULONG valueLen = 0;
2N/A CK_ATTRIBUTE valattr[1];
2N/A
2N/A /* Generate the DSA keypair */
2N/A ckrv = gendsa_keypair(kmfh, storekey, &pubKey, &priKey);
2N/A if (ckrv != CKR_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A privkey->keyalg = KMF_DSA;
2N/A privkey->keyclass = KMF_ASYM_PRI;
2N/A privkey->keyp = (void *)priKey;
2N/A
2N/A pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A pubkey->keyalg = KMF_DSA;
2N/A pubkey->keyclass = KMF_ASYM_PUB;
2N/A pubkey->keyp = (void *)pubKey;
2N/A
2N/A /* Get the Public Value to use as input for creating the ID */
2N/A SETATTR(valattr, 0, CKA_VALUE, NULL, valueLen);
2N/A
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)pubKey, valattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A goto cleanup;
2N/A }
2N/A
2N/A valueLen = valattr[0].ulValueLen;
2N/A keyvalue = malloc(valueLen);
2N/A if (keyvalue == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A valattr[0].pValue = keyvalue;
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)pubKey, valattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A free(keyvalue);
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A goto cleanup;
2N/A }
2N/A
2N/A IDInput.Data = keyvalue;
2N/A IDInput.Length = valueLen;
2N/A } else if (keytype == KMF_ECDSA) {
2N/A CK_BYTE *keyvalue;
2N/A CK_ULONG valueLen;
2N/A CK_ATTRIBUTE valattr[1];
2N/A KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
2N/A attlist, numattr);
2N/A
2N/A if (eccoid == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A ckrv = genecc_keypair(kmfh, storekey, eccoid,
2N/A &pubKey, &priKey);
2N/A if (ckrv != CKR_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A privkey->keyalg = KMF_ECDSA;
2N/A privkey->keyclass = KMF_ASYM_PRI;
2N/A privkey->keyp = (void *)priKey;
2N/A
2N/A pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A pubkey->keyalg = KMF_ECDSA;
2N/A pubkey->keyclass = KMF_ASYM_PUB;
2N/A pubkey->keyp = (void *)pubKey;
2N/A
2N/A /* Get the EC_POINT to use as input for creating the ID */
2N/A SETATTR(valattr, 0, CKA_EC_POINT, NULL, &valueLen);
2N/A
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)pubKey, valattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A goto cleanup;
2N/A }
2N/A
2N/A valueLen = valattr[0].ulValueLen;
2N/A keyvalue = malloc(valueLen);
2N/A if (keyvalue == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto cleanup;
2N/A }
2N/A
2N/A valattr[0].pValue = keyvalue;
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)pubKey, valattr, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A free(keyvalue);
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A goto cleanup;
2N/A }
2N/A
2N/A IDInput.Data = keyvalue;
2N/A IDInput.Length = valueLen;
2N/A } else {
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attlist, numattr);
2N/A if (keylabel != NULL && strlen(keylabel)) {
2N/A SETATTR(labelattr, 0, CKA_LABEL, keylabel, strlen(keylabel));
2N/A
2N/A /* Set the CKA_LABEL if one was indicated */
2N/A if ((ckrv = C_SetAttributeValue(hSession, pubKey,
2N/A labelattr, 1)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto cleanup;
2N/A }
2N/A pubkey->keylabel = (char *)strdup(keylabel);
2N/A if (pubkey->keylabel == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto cleanup;
2N/A }
2N/A if ((ckrv = C_SetAttributeValue(hSession, priKey,
2N/A labelattr, 1)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto cleanup;
2N/A }
2N/A privkey->keylabel = (char *)strdup(keylabel);
2N/A if (privkey->keylabel == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto cleanup;
2N/A }
2N/A } else {
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A /* Now, assign a CKA_ID value so it can be searched */
2N/A /* ID_Input was assigned above in the RSA or DSA keygen section */
2N/A IDOutput.Data = (uchar_t *)IDHashData;
2N/A IDOutput.Length = sizeof (IDHashData);
2N/A
2N/A SHA1Init(&ctx);
2N/A SHA1Update(&ctx, IDInput.Data, IDInput.Length);
2N/A SHA1Final(IDOutput.Data, &ctx);
2N/A
2N/A IDOutput.Length = SHA1_DIGEST_LENGTH;
2N/A
2N/A free(IDInput.Data);
2N/A
2N/A if (rv != CKR_OK) {
2N/A goto cleanup;
2N/A }
2N/A SETATTR(idattr, 0, CKA_ID, IDOutput.Data, IDOutput.Length);
2N/A if ((ckrv = C_SetAttributeValue(hSession, pubKey,
2N/A idattr, 1)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto cleanup;
2N/A }
2N/A if ((ckrv = C_SetAttributeValue(hSession, priKey,
2N/A idattr, 1)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto cleanup;
2N/A }
2N/A
2N/Acleanup:
2N/A if (rv != KMF_OK) {
2N/A if (pubKey != CK_INVALID_HANDLE)
2N/A (void) C_DestroyObject(hSession, pubKey);
2N/A if (priKey != CK_INVALID_HANDLE)
2N/A (void) C_DestroyObject(hSession, priKey);
2N/A
2N/A if (privkey->keylabel)
2N/A free(privkey->keylabel);
2N/A if (pubkey->keylabel)
2N/A free(pubkey->keylabel);
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DeleteKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_RV ckrv = CKR_OK;
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_KEY_HANDLE *key;
2N/A KMF_CREDENTIAL cred;
2N/A boolean_t destroy = B_TRUE;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (key == NULL || key->keyp == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (key->keyclass != KMF_ASYM_PUB &&
2N/A key->keyclass != KMF_ASYM_PRI &&
2N/A key->keyclass != KMF_SYMMETRIC)
2N/A return (KMF_ERR_BAD_KEY_CLASS);
2N/A
2N/A /* "destroy" is optional. Default is TRUE */
2N/A (void) kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&destroy, NULL);
2N/A
2N/A if (destroy) {
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = pk11_authenticate(handle, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A }
2N/A
2N/A if (!key->israw && destroy)
2N/A ckrv = C_DestroyObject(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)key->keyp);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A /* Report authentication failures to the caller */
2N/A if (ckrv == CKR_PIN_EXPIRED || ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
2N/A KMF_OID *algOID,
2N/A KMF_DATA *tobesigned,
2N/A KMF_DATA *output)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_SESSION_HANDLE hSession;
2N/A CK_MECHANISM mechanism;
2N/A CK_MECHANISM_TYPE mechtype, hashmech;
2N/A CK_KEY_TYPE keytype;
2N/A KMF_ALGORITHM_INDEX AlgId;
2N/A KMF_DATA hashData = {NULL, 0};
2N/A uchar_t digest[1024];
2N/A CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 };
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (keyp == NULL || algOID == NULL ||
2N/A tobesigned == NULL || output == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* These functions are available to the plugin from libkmf */
2N/A AlgId = x509_algoid_to_algid(algOID);
2N/A if (AlgId == KMF_ALGID_NONE)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Get the PKCS11 signing key type and mechtype */
2N/A if (get_pk11_data(AlgId, &keytype, &mechtype, &hashmech, 0))
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /*
2N/A * Create a new session for doing the digest operation.
2N/A * This insures that we find a slot that supports the
2N/A * hash algorithm. Some hardware devices have limited
2N/A * support for hashing.
2N/A */
2N/A if (hashmech != 0) {
2N/A rv = kmf_create_pk11_session(&hSession, hashmech, CKF_DIGEST);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A (void) memset(digest, 0, sizeof (digest));
2N/A hashData.Data = digest;
2N/A hashData.Length = sizeof (digest);
2N/A rv = PKCS_DigestData(handle, hSession, hashmech, tobesigned,
2N/A &hashData, (mechtype == CKM_RSA_PKCS));
2N/A (void) C_CloseSession(hSession);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A } else {
2N/A /* No hash alg specified, just sign the data we were given */
2N/A hashData.Data = tobesigned->Data;
2N/A hashData.Length = tobesigned->Length;
2N/A }
2N/A
2N/A /*
2N/A * Now use the original handle to sign the hash with the
2N/A * private key.
2N/A */
2N/A hSession = kmfh->pk11handle;
2N/A if (mechtype == CKM_DSA && hashmech == CKM_SHA256) {
2N/A /*
2N/A * FIPS 186-3 says that when signing with DSA
2N/A * the hash must be truncated to the size of the
2N/A * subprime.
2N/A */
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)keyp->keyp,
2N/A &subprime, 1);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A hashData.Length = subprime.ulValueLen;
2N/A }
2N/A
2N/A /* the mechtype from the 'get_pk11_info' refers to the signing */
2N/A mechanism.mechanism = mechtype;
2N/A mechanism.pParameter = NULL;
2N/A mechanism.ulParameterLen = 0;
2N/A
2N/A ckrv = C_SignInit(hSession, &mechanism, (CK_OBJECT_HANDLE)keyp->keyp);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A ckrv = C_Sign(hSession, hashData.Data, hashData.Length,
2N/A output->Data, (CK_ULONG *)&output->Length);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
2N/A{
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A *msgstr = NULL;
2N/A if (kmfh->lasterr.errcode != 0) {
2N/A char *e = pkcs11_strerror(kmfh->lasterr.errcode);
2N/A if (e == NULL || (*msgstr = (char *)strdup(e)) == NULL) {
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic CK_RV
2N/AgetObjectKeytype(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2N/A CK_ULONG *keytype)
2N/A{
2N/A CK_RV rv = CKR_OK;
2N/A CK_ATTRIBUTE templ;
2N/A CK_ULONG len = sizeof (CK_ULONG);
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A templ.type = CKA_KEY_TYPE;
2N/A templ.pValue = keytype;
2N/A templ.ulValueLen = len;
2N/A
2N/A rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2N/A
2N/A return (rv);
2N/A
2N/A}
2N/A
2N/Astatic CK_RV
2N/AgetObjectLabel(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2N/A char **outlabel)
2N/A{
2N/A CK_RV rv = CKR_OK;
2N/A CK_ATTRIBUTE templ;
2N/A char Label[BUFSIZ];
2N/A CK_ULONG len = sizeof (Label);
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A (void) memset(Label, 0, len);
2N/A templ.type = CKA_LABEL;
2N/A templ.pValue = Label;
2N/A templ.ulValueLen = len;
2N/A
2N/A rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2N/A if (rv == CKR_OK) {
2N/A *outlabel = (char *)strdup(Label);
2N/A } else {
2N/A *outlabel = NULL;
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/Astatic CK_RV
2N/AgetObjectKeyclass(KMF_HANDLE_T handle, CK_OBJECT_HANDLE obj,
2N/A KMF_KEY_CLASS *keyclass)
2N/A{
2N/A CK_RV rv = CKR_OK;
2N/A CK_ATTRIBUTE templ;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_OBJECT_CLASS class;
2N/A
2N/A templ.type = CKA_CLASS;
2N/A templ.pValue = &class;
2N/A templ.ulValueLen = sizeof (CK_OBJECT_CLASS);
2N/A
2N/A rv = C_GetAttributeValue(kmfh->pk11handle, obj, &templ, 1);
2N/A if (rv == CKR_OK) {
2N/A if (class == CKO_PUBLIC_KEY) {
2N/A *keyclass = KMF_ASYM_PUB;
2N/A } else if (class == CKO_PRIVATE_KEY) {
2N/A *keyclass = KMF_ASYM_PRI;
2N/A } else if (class == CKO_SECRET_KEY) {
2N/A *keyclass = KMF_SYMMETRIC;
2N/A }
2N/A } else {
2N/A *keyclass = KMF_KEYCLASS_NONE;
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2N/A KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_X509_SPKI *pubkey;
2N/A KMF_X509_CERTIFICATE *SignerCert = NULL;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv = CKR_OK;
2N/A CK_ATTRIBUTE templ[4];
2N/A CK_OBJECT_HANDLE pri_obj = CK_INVALID_HANDLE;
2N/A CK_ULONG obj_count;
2N/A CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
2N/A CK_BBOOL true = TRUE;
2N/A KMF_DATA Id = { NULL, 0 };
2N/A KMF_KEY_HANDLE *key = NULL;
2N/A KMF_DATA *cert = NULL;
2N/A KMF_CREDENTIAL cred;
2N/A KMF_ENCODE_FORMAT format = KMF_FORMAT_UNDEF;
2N/A CK_ULONG keytype;
2N/A
2N/A /* Get the key handle */
2N/A key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (key == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Get the optional encoded format */
2N/A (void) kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
2N/A (void *)&format, NULL);
2N/A
2N/A /* Decode the signer cert so we can get the SPKI data */
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert == NULL || cert->Data == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if ((rv = DerDecodeSignedCertificate(cert,
2N/A &SignerCert)) != KMF_OK)
2N/A return (rv);
2N/A
2N/A /* Get the public key info from the signer certificate */
2N/A pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
2N/A
2N/A /* Generate an ID from the SPKI data */
2N/A rv = GetIDFromSPKI(pubkey, &Id);
2N/A if (rv != KMF_OK) {
2N/A goto errout;
2N/A }
2N/A
2N/A /* Get the credential and login */
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = pk11_authenticate(handle, &cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* Start searching */
2N/A SETATTR(templ, 0, CKA_CLASS, &objClass, sizeof (objClass));
2N/A SETATTR(templ, 1, CKA_TOKEN, &true, sizeof (true));
2N/A SETATTR(templ, 2, CKA_PRIVATE, &true, sizeof (true));
2N/A SETATTR(templ, 3, CKA_ID, Id.Data, Id.Length);
2N/A
2N/A if ((ckrv = C_FindObjectsInit(kmfh->pk11handle, templ, 4)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto errout;
2N/A }
2N/A
2N/A if ((ckrv = C_FindObjects(kmfh->pk11handle, &pri_obj, 1,
2N/A &obj_count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto errout;
2N/A }
2N/A
2N/A if (obj_count == 0) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A goto errout;
2N/A }
2N/A
2N/A key->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A key->keyclass = KMF_ASYM_PRI;
2N/A key->keyp = (void *)pri_obj;
2N/A key->israw = FALSE;
2N/A
2N/A (void) C_FindObjectsFinal(kmfh->pk11handle);
2N/A
2N/A ckrv = getObjectLabel(handle, (CK_OBJECT_HANDLE)key->keyp,
2N/A &key->keylabel);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(handle, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A } else {
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A /*
2N/A * The key->keyalg value is needed if we need to convert the key
2N/A * to raw key. However, the key->keyalg value will not be set if
2N/A * this function is not called thru the kmf_find_prikey_by_cert()
2N/A * framework function. To be safe, we will get the keytype from
2N/A * the key object and set key->keyalg value here.
2N/A */
2N/A ckrv = getObjectKeytype(handle, (CK_OBJECT_HANDLE)key->keyp,
2N/A &keytype);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(handle, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A } else {
2N/A rv = KMF_OK;
2N/A }
2N/A
2N/A if (keytype == CKK_RSA)
2N/A key->keyalg = KMF_RSA;
2N/A else if (keytype == CKK_DSA)
2N/A key->keyalg = KMF_DSA;
2N/A else if (keytype == CKK_EC)
2N/A key->keyalg = KMF_ECDSA;
2N/A else {
2N/A /* For asymmetric keys, we only support RSA and DSA */
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A goto errout;
2N/A }
2N/A
2N/A if (rv == KMF_OK && format == KMF_FORMAT_RAWKEY) {
2N/A KMF_RAW_KEY_DATA *rkey = NULL;
2N/A rv = keyObj2RawKey(handle, key, &rkey);
2N/A if (rv == KMF_OK) {
2N/A key->keyp = rkey;
2N/A key->israw = TRUE;
2N/A }
2N/A }
2N/A
2N/Aerrout:
2N/A if (Id.Data != NULL)
2N/A free(Id.Data);
2N/A
2N/A if (SignerCert != NULL) {
2N/A kmf_free_signed_cert(SignerCert);
2N/A free(SignerCert);
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2N/A KMF_OID *algOID, KMF_DATA *ciphertext,
2N/A KMF_DATA *output)
2N/A{
2N/A CK_RV ckrv;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_MECHANISM mechanism;
2N/A CK_MECHANISM_TYPE mechtype;
2N/A CK_KEY_TYPE keytype;
2N/A KMF_ALGORITHM_INDEX AlgId;
2N/A CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
2N/A uint8_t *in_data, *out_data;
2N/A int i, blocks;
2N/A CK_ATTRIBUTE ckTemplate[1];
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (key == NULL || algOID == NULL ||
2N/A ciphertext == NULL || output == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A AlgId = x509_algoid_to_algid(algOID);
2N/A if (AlgId == KMF_ALGID_NONE)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Map the Algorithm ID to a PKCS#11 mechanism */
2N/A if (get_pk11_data(AlgId, &keytype, &mechtype, NULL, 0))
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A mechanism.mechanism = mechtype;
2N/A mechanism.pParameter = NULL;
2N/A mechanism.ulParameterLen = 0;
2N/A
2N/A SETATTR(ckTemplate, 0, CKA_MODULUS, (CK_BYTE *)NULL,
2N/A sizeof (CK_ULONG));
2N/A
2N/A /* Get the modulus length */
2N/A ckrv = C_GetAttributeValue(hSession,
2N/A (CK_OBJECT_HANDLE)key->keyp, ckTemplate, 1);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A block_len = ckTemplate[0].ulValueLen;
2N/A
2N/A /* Compute the number of times to do single-part decryption */
2N/A blocks = ciphertext->Length/block_len;
2N/A
2N/A out_data = output->Data;
2N/A in_data = ciphertext->Data;
2N/A out_len = block_len - 11;
2N/A
2N/A for (i = 0; i < blocks; i++) {
2N/A ckrv = C_DecryptInit(hSession, &mechanism,
2N/A (CK_OBJECT_HANDLE)key->keyp);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A ckrv = C_Decrypt(hSession, in_data, block_len,
2N/A out_data, (CK_ULONG *)&out_len);
2N/A
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A out_data += out_len;
2N/A total_decrypted += out_len;
2N/A in_data += block_len;
2N/A
2N/A }
2N/A
2N/A output->Length = total_decrypted;
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic void
2N/Aattr2bigint(CK_ATTRIBUTE_PTR attr, KMF_BIGINT *big)
2N/A{
2N/A big->val = attr->pValue;
2N/A big->len = attr->ulValueLen;
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Aget_bigint_attr(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
2N/A CK_ATTRIBUTE_TYPE attrtype, KMF_BIGINT *bigint)
2N/A{
2N/A CK_RV ckrv;
2N/A CK_ATTRIBUTE attr;
2N/A
2N/A attr.type = attrtype;
2N/A attr.pValue = NULL;
2N/A attr.ulValueLen = 0;
2N/A
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A &attr, 1)) != CKR_OK) {
2N/A /* Mask this error so the caller can continue */
2N/A if (ckrv == CKR_ATTRIBUTE_TYPE_INVALID)
2N/A return (KMF_OK);
2N/A else
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A if (attr.ulValueLen > 0 && bigint != NULL) {
2N/A attr.pValue = malloc(attr.ulValueLen);
2N/A if (attr.pValue == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A &attr, 1)) != CKR_OK)
2N/A if (ckrv != CKR_OK) {
2N/A free(attr.pValue);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A bigint->val = attr.pValue;
2N/A bigint->len = attr.ulValueLen;
2N/A }
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Aget_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE sess = kmfh->pk11handle;
2N/A CK_ATTRIBUTE rsa_pri_attrs[2] = {
2N/A { CKA_MODULUS, NULL, 0 },
2N/A { CKA_PUBLIC_EXPONENT, NULL, 0 }
2N/A };
2N/A CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2N/A int i;
2N/A
2N/A if (rawrsa == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A (void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A rsa_pri_attrs, count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A /* Tell the caller know why the key data cannot be retrieved. */
2N/A if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2N/A return (KMF_ERR_SENSITIVE_KEY);
2N/A else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2N/A return (KMF_ERR_UNEXTRACTABLE_KEY);
2N/A else
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A /* Allocate memory for each attribute. */
2N/A for (i = 0; i < count; i++) {
2N/A if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2N/A rsa_pri_attrs[i].ulValueLen == 0) {
2N/A rsa_pri_attrs[i].ulValueLen = 0;
2N/A continue;
2N/A }
2N/A if ((rsa_pri_attrs[i].pValue =
2N/A malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto end;
2N/A }
2N/A }
2N/A /* Now that we have space, really get the attributes */
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A rsa_pri_attrs, count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto end;
2N/A }
2N/A i = 0;
2N/A attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->mod);
2N/A attr2bigint(&(rsa_pri_attrs[i++]), &rawrsa->pubexp);
2N/A
2N/A /* Now get the optional parameters */
2N/A rv = get_bigint_attr(sess, obj, CKA_PRIVATE_EXPONENT, &rawrsa->priexp);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A rv = get_bigint_attr(sess, obj, CKA_PRIME_1, &rawrsa->prime1);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A rv = get_bigint_attr(sess, obj, CKA_PRIME_2, &rawrsa->prime2);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A rv = get_bigint_attr(sess, obj, CKA_EXPONENT_1, &rawrsa->exp1);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A rv = get_bigint_attr(sess, obj, CKA_EXPONENT_2, &rawrsa->exp2);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A rv = get_bigint_attr(sess, obj, CKA_COEFFICIENT, &rawrsa->coef);
2N/A if (rv != KMF_OK)
2N/A goto end;
2N/A
2N/Aend:
2N/A if (rv != KMF_OK) {
2N/A for (i = 0; i < count; i++) {
2N/A if (rsa_pri_attrs[i].pValue != NULL)
2N/A free(rsa_pri_attrs[i].pValue);
2N/A }
2N/A if (rawrsa->priexp.val)
2N/A free(rawrsa->priexp.val);
2N/A if (rawrsa->prime1.val)
2N/A free(rawrsa->prime1.val);
2N/A if (rawrsa->prime2.val)
2N/A free(rawrsa->prime2.val);
2N/A if (rawrsa->exp1.val)
2N/A free(rawrsa->exp1.val);
2N/A if (rawrsa->exp2.val)
2N/A free(rawrsa->exp2.val);
2N/A if (rawrsa->coef.val)
2N/A free(rawrsa->coef.val);
2N/A (void) memset(rawrsa, 0, sizeof (KMF_RAW_RSA_KEY));
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/A/* DSA-1024, known as DSA 1024-160 in FIPS 186-3: */
2N/A#define DSA_PRIME_BUFSIZE BITLEN2BIGNUMLEN(1024) /* L = 1024 bits */
2N/A#define DSA_PRIVATE_BUFSIZE BITLEN2BIGNUMLEN(160) /* N = 160 bits */
2N/A
2N/A/*
2N/A * This function calculates the pubkey value from the prime,
2N/A * base and private key values of a DSA key.
2N/A */
2N/Astatic KMF_RETURN
2N/Acompute_dsa_pubvalue(KMF_RAW_DSA_KEY *rawdsa)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A BIGNUM p, g, x, y;
2N/A BIG_ERR_CODE err;
2N/A uchar_t *pubvalue;
2N/A uint32_t pubvalue_len;
2N/A
2N/A if ((err = big_init1(&p, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2N/A rv = KMF_ERR_MEMORY;
2N/A return (rv);
2N/A }
2N/A bytestring2bignum(&p, rawdsa->prime.val, rawdsa->prime.len);
2N/A
2N/A if ((err = big_init1(&g, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto ret1;
2N/A }
2N/A bytestring2bignum(&g, rawdsa->base.val, rawdsa->base.len);
2N/A
2N/A if ((err = big_init1(&x, DSA_PRIVATE_BUFSIZE, NULL, 0)) != BIG_OK) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto ret2;
2N/A }
2N/A bytestring2bignum(&x, rawdsa->value.val, rawdsa->value.len);
2N/A
2N/A if ((err = big_init1(&y, DSA_PRIME_BUFSIZE, NULL, 0)) != BIG_OK) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto ret3;
2N/A }
2N/A
2N/A err = big_modexp(&y, &g, &x, &p, NULL);
2N/A if (err != BIG_OK) {
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto ret3;
2N/A }
2N/A
2N/A pubvalue_len = y.len * (int)sizeof (BIG_CHUNK_TYPE);
2N/A if ((pubvalue = malloc(pubvalue_len)) == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto ret4;
2N/A }
2N/A bignum2bytestring(pubvalue, &y, pubvalue_len);
2N/A
2N/A rawdsa->pubvalue.val = pubvalue;
2N/A rawdsa->pubvalue.len = pubvalue_len;
2N/A
2N/Aret4:
2N/A big_finish(&y);
2N/Aret3:
2N/A big_finish(&x);
2N/Aret2:
2N/A big_finish(&g);
2N/Aret1:
2N/A big_finish(&p);
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Aget_raw_ec(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_EC_KEY *rawec)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE sess = kmfh->pk11handle;
2N/A CK_ATTRIBUTE ec_attrs[2] = {
2N/A { CKA_EC_PARAMS, NULL, 0},
2N/A { CKA_VALUE, NULL, 0}
2N/A };
2N/A CK_ULONG count = sizeof (ec_attrs) / sizeof (CK_ATTRIBUTE);
2N/A int i;
2N/A
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A ec_attrs, 2)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A
2N/A /* Tell the caller know why the key data cannot be retrieved. */
2N/A if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2N/A return (KMF_ERR_SENSITIVE_KEY);
2N/A else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2N/A return (KMF_ERR_UNEXTRACTABLE_KEY);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A for (i = 0; i < count; i++) {
2N/A if (ec_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2N/A ec_attrs[i].ulValueLen == 0) {
2N/A ec_attrs[i].ulValueLen = 0;
2N/A continue;
2N/A }
2N/A if ((ec_attrs[i].pValue =
2N/A malloc(ec_attrs[i].ulValueLen)) == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto end;
2N/A }
2N/A }
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A ec_attrs, count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto end;
2N/A }
2N/A
2N/A rawec->params.Data = ec_attrs[0].pValue;
2N/A rawec->params.Length = ec_attrs[0].ulValueLen;
2N/A rawec->value.val = ec_attrs[1].pValue;
2N/A rawec->value.len = ec_attrs[1].ulValueLen;
2N/A
2N/Aend:
2N/A if (rv != KMF_OK) {
2N/A for (i = 0; i < count; i++) {
2N/A if (ec_attrs[i].pValue != NULL)
2N/A free(ec_attrs[i].pValue);
2N/A }
2N/A (void) memset(rawec, 0, sizeof (KMF_RAW_EC_KEY));
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Aget_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE sess = kmfh->pk11handle;
2N/A CK_ATTRIBUTE dsa_pri_attrs[8] = {
2N/A { CKA_PRIME, NULL, 0 },
2N/A { CKA_SUBPRIME, NULL, 0 },
2N/A { CKA_BASE, NULL, 0 },
2N/A { CKA_VALUE, NULL, 0 }
2N/A };
2N/A CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
2N/A int i;
2N/A
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A dsa_pri_attrs, count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A
2N/A /* Tell the caller know why the key data cannot be retrieved. */
2N/A if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
2N/A return (KMF_ERR_SENSITIVE_KEY);
2N/A else if (ckrv == CKR_KEY_UNEXTRACTABLE)
2N/A return (KMF_ERR_UNEXTRACTABLE_KEY);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A /* Allocate memory for each attribute. */
2N/A for (i = 0; i < count; i++) {
2N/A if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
2N/A dsa_pri_attrs[i].ulValueLen == 0) {
2N/A dsa_pri_attrs[i].ulValueLen = 0;
2N/A continue;
2N/A }
2N/A if ((dsa_pri_attrs[i].pValue =
2N/A malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto end;
2N/A }
2N/A }
2N/A if ((ckrv = C_GetAttributeValue(sess, obj,
2N/A dsa_pri_attrs, count)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A rv = KMF_ERR_INTERNAL;
2N/A goto end;
2N/A }
2N/A
2N/A /* Fill in all the temp variables. They are all required. */
2N/A i = 0;
2N/A attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->prime);
2N/A attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->subprime);
2N/A attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->base);
2N/A attr2bigint(&(dsa_pri_attrs[i++]), &rawdsa->value);
2N/A
2N/A /* Compute the public key value and store it */
2N/A rv = compute_dsa_pubvalue(rawdsa);
2N/A
2N/Aend:
2N/A if (rv != KMF_OK) {
2N/A for (i = 0; i < count; i++) {
2N/A if (dsa_pri_attrs[i].pValue != NULL)
2N/A free(dsa_pri_attrs[i].pValue);
2N/A }
2N/A (void) memset(rawdsa, 0, sizeof (KMF_RAW_DSA_KEY));
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Aget_raw_sym(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_SYM_KEY *rawsym)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE sess = kmfh->pk11handle;
2N/A CK_ATTRIBUTE sym_attr[1];
2N/A CK_ULONG value_len = 0;
2N/A
2N/A /* find the key length first */
2N/A sym_attr[0].type = CKA_VALUE;
2N/A sym_attr[0].pValue = NULL;
2N/A sym_attr[0].ulValueLen = value_len;
2N/A if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2N/A rawsym->keydata.val = NULL;
2N/A rawsym->keydata.len = 0;
2N/A if (ckrv == CKR_ATTRIBUTE_SENSITIVE) {
2N/A return (KMF_ERR_SENSITIVE_KEY);
2N/A } else if (ckrv == CKR_KEY_UNEXTRACTABLE) {
2N/A return (KMF_ERR_UNEXTRACTABLE_KEY);
2N/A } else {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A }
2N/A
2N/A /* Allocate memory for pValue */
2N/A sym_attr[0].pValue = malloc(sym_attr[0].ulValueLen);
2N/A if (sym_attr[0].pValue == NULL) {
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A
2N/A /* get the key data */
2N/A if ((ckrv = C_GetAttributeValue(sess, obj, sym_attr, 1)) != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A free(sym_attr[0].pValue);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A rawsym->keydata.val = sym_attr[0].pValue;
2N/A rawsym->keydata.len = sym_attr[0].ulValueLen;
2N/A return (rv);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/AkeyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
2N/A KMF_RAW_KEY_DATA **outkey)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_RAW_KEY_DATA *rkey;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A rkey = malloc(sizeof (KMF_RAW_KEY_DATA));
2N/A if (rkey == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A (void) memset(rkey, 0, sizeof (KMF_RAW_KEY_DATA));
2N/A
2N/A rkey->keytype = inkey->keyalg;
2N/A
2N/A if (inkey->keyalg == KMF_RSA) {
2N/A rv = get_raw_rsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2N/A &rkey->rawdata.rsa);
2N/A } else if (inkey->keyalg == KMF_DSA) {
2N/A rv = get_raw_dsa(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2N/A &rkey->rawdata.dsa);
2N/A } else if (inkey->keyalg == KMF_AES ||
2N/A inkey->keyalg == KMF_RC4 ||
2N/A inkey->keyalg == KMF_DES ||
2N/A inkey->keyalg == KMF_DES3 ||
2N/A inkey->keyalg == KMF_GENERIC_SECRET) {
2N/A rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2N/A &rkey->rawdata.sym);
2N/A /*
2N/A * If sensitive or non-extractable, mark them as such
2N/A * but return "OK" status so the keys get counted
2N/A * when doing FindKey operations.
2N/A */
2N/A if (rv == KMF_ERR_SENSITIVE_KEY) {
2N/A rkey->sensitive = B_TRUE;
2N/A rv = KMF_OK;
2N/A } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
2N/A rkey->not_extractable = B_TRUE;
2N/A rv = KMF_OK;
2N/A }
2N/A } else if (inkey->keyalg == KMF_ECDSA) {
2N/A rv = get_raw_ec(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
2N/A &rkey->rawdata.ec);
2N/A } else {
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A }
2N/A
2N/A if (rv == KMF_OK) {
2N/A *outkey = rkey;
2N/A } else if (rkey != NULL) {
2N/A free(rkey);
2N/A *outkey = NULL;
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A
2N/Astatic KMF_RETURN
2N/Akmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
2N/A{
2N/A switch (keyalg) {
2N/A case KMF_RSA:
2N/A *type = CKK_RSA;
2N/A break;
2N/A case KMF_DSA:
2N/A *type = CKK_DSA;
2N/A break;
2N/A case KMF_ECDSA:
2N/A *type = CKK_EC;
2N/A break;
2N/A case KMF_AES:
2N/A *type = CKK_AES;
2N/A break;
2N/A case KMF_RC4:
2N/A *type = CKK_RC4;
2N/A break;
2N/A case KMF_DES:
2N/A *type = CKK_DES;
2N/A break;
2N/A case KMF_DES3:
2N/A *type = CKK_DES3;
2N/A break;
2N/A case KMF_GENERIC_SECRET:
2N/A *type = CKK_GENERIC_SECRET;
2N/A break;
2N/A default:
2N/A return (KMF_ERR_BAD_KEY_TYPE);
2N/A }
2N/A
2N/A return (KMF_OK);
2N/A}
2N/A
2N/Astatic int
2N/AIDStringToData(char *idstr, KMF_DATA *iddata)
2N/A{
2N/A int len, i;
2N/A char *iddup, *byte;
2N/A uint_t lvalue;
2N/A
2N/A if (idstr == NULL || !strlen(idstr))
2N/A return (-1);
2N/A
2N/A iddup = (char *)strdup(idstr);
2N/A if (iddup == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A len = strlen(iddup) / 3 + 1;
2N/A iddata->Data = malloc(len);
2N/A if (iddata->Data == NULL) {
2N/A free(iddup);
2N/A return (KMF_ERR_MEMORY);
2N/A }
2N/A (void) memset(iddata->Data, 0, len);
2N/A iddata->Length = len;
2N/A
2N/A byte = strtok(iddup, ":");
2N/A if (byte == NULL) {
2N/A free(iddup);
2N/A free(iddata->Data);
2N/A iddata->Data = NULL;
2N/A iddata->Length = 0;
2N/A return (-1);
2N/A }
2N/A
2N/A i = 0;
2N/A do {
2N/A (void) sscanf(byte, "%x", &lvalue);
2N/A iddata->Data[i++] = (uchar_t)(lvalue & 0x000000FF);
2N/A byte = strtok(NULL, ":");
2N/A } while (byte != NULL && i < len);
2N/A
2N/A iddata->Length = i;
2N/A free(iddup);
2N/A return (0);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_FindKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A uint32_t want_keys, i;
2N/A CK_RV ckrv;
2N/A CK_ATTRIBUTE pTmpl[10];
2N/A CK_OBJECT_CLASS class;
2N/A CK_BBOOL true = TRUE;
2N/A CK_ULONG alg;
2N/A boolean_t is_token = B_TRUE, is_private = B_FALSE;
2N/A KMF_KEY_HANDLE *keys;
2N/A uint32_t *numkeys;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A KMF_KEY_CLASS keyclass = KMF_KEYCLASS_NONE;
2N/A char *findLabel, *idstr;
2N/A KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
2N/A KMF_ENCODE_FORMAT format;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2N/A if (numkeys == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A if (*numkeys > 0)
2N/A want_keys = *numkeys;
2N/A else
2N/A want_keys = MAXINT; /* count them all */
2N/A
2N/A /* keyclass is optional */
2N/A (void) kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2N/A (void *)&keyclass, NULL);
2N/A
2N/A if (keyclass == KMF_ASYM_PUB) {
2N/A class = CKO_PUBLIC_KEY;
2N/A } else if (keyclass == KMF_ASYM_PRI) {
2N/A class = CKO_PRIVATE_KEY;
2N/A } else if (keyclass == KMF_SYMMETRIC) {
2N/A class = CKO_SECRET_KEY;
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_TOKEN_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_token, NULL);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A i = 0;
2N/A if (is_token) {
2N/A SETATTR(pTmpl, i, CKA_TOKEN, &true, sizeof (true));
2N/A i++;
2N/A }
2N/A
2N/A if (keyclass != KMF_KEYCLASS_NONE) {
2N/A SETATTR(pTmpl, i, CKA_CLASS, &class, sizeof (class));
2N/A i++;
2N/A }
2N/A
2N/A findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A
2N/A if (findLabel != NULL && strlen(findLabel)) {
2N/A SETATTR(pTmpl, i, CKA_LABEL, findLabel, strlen(findLabel));
2N/A i++;
2N/A }
2N/A /* keytype is optional */
2N/A (void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2N/A (void *)&keytype, NULL);
2N/A
2N/A if (keytype != 0) {
2N/A rv = kmf2pk11keytype(keytype, &alg);
2N/A if (rv != KMF_OK) {
2N/A return (KMF_ERR_BAD_KEY_TYPE);
2N/A }
2N/A SETATTR(pTmpl, i, CKA_KEY_TYPE, &alg, sizeof (alg));
2N/A i++;
2N/A }
2N/A
2N/A idstr = kmf_get_attr_ptr(KMF_IDSTR_ATTR, attrlist, numattr);
2N/A
2N/A if (idstr != NULL) {
2N/A KMF_DATA iddata = { NULL, 0 };
2N/A
2N/A /*
2N/A * ID String parameter is assumed to be of form:
2N/A * XX:XX:XX:XX:XX ... :XX
2N/A * where XX is a hex number.
2N/A *
2N/A * We must convert this back to binary in order to
2N/A * use it in a search.
2N/A */
2N/A rv = IDStringToData(idstr, &iddata);
2N/A if (rv == KMF_OK) {
2N/A SETATTR(pTmpl, i, CKA_ID, iddata.Data, iddata.Length);
2N/A i++;
2N/A } else {
2N/A return (rv);
2N/A }
2N/A }
2N/A
2N/A /* is_private is optional */
2N/A (void) kmf_get_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_private, NULL);
2N/A
2N/A if (is_private) {
2N/A SETATTR(pTmpl, i, CKA_PRIVATE, &true, sizeof (true));
2N/A i++;
2N/A }
2N/A
2N/A /*
2N/A * Authenticate if the object is a token object,
2N/A * a private or secred key, or if the user passed in credentials.
2N/A */
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred != NULL) {
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A /* it is okay to have "keys" contains NULL */
2N/A
2N/A ckrv = C_FindObjectsInit(kmfh->pk11handle, pTmpl, i);
2N/A if (ckrv == CKR_OK) {
2N/A CK_ULONG obj_count, n = 0;
2N/A while (ckrv == CKR_OK && n < want_keys) {
2N/A CK_OBJECT_HANDLE hObj;
2N/A
2N/A ckrv = C_FindObjects(kmfh->pk11handle, &hObj,
2N/A 1, &obj_count);
2N/A if (ckrv == CKR_OK && obj_count == 1) {
2N/A if (keys != NULL) {
2N/A CK_ULONG keytype;
2N/A keys[n].kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A keys[n].israw = FALSE;
2N/A keys[n].keyp = (void *)hObj;
2N/A
2N/A ckrv = getObjectKeytype(handle,
2N/A (CK_OBJECT_HANDLE)keys[n].keyp,
2N/A &keytype);
2N/A if (ckrv != CKR_OK)
2N/A goto end;
2N/A
2N/A ckrv = getObjectLabel(handle,
2N/A (CK_OBJECT_HANDLE)keys[n].keyp,
2N/A &(keys[n].keylabel));
2N/A if (ckrv != CKR_OK)
2N/A goto end;
2N/A
2N/A if (keyclass == KMF_KEYCLASS_NONE) {
2N/A ckrv = getObjectKeyclass(handle,
2N/A (CK_OBJECT_HANDLE)
2N/A keys[n].keyp,
2N/A &(keys[n].keyclass));
2N/A if (ckrv != CKR_OK)
2N/A goto end;
2N/A } else {
2N/A keys[n].keyclass = keyclass;
2N/A }
2N/A if (keytype == CKK_RSA) {
2N/A keys[n].keyalg = KMF_RSA;
2N/A } else if (keytype == CKK_DSA) {
2N/A keys[n].keyalg = KMF_DSA;
2N/A } else if (keytype == CKK_EC) {
2N/A keys[n].keyalg = KMF_ECDSA;
2N/A } else if (keytype == CKK_AES) {
2N/A keys[n].keyalg = KMF_AES;
2N/A keys[n].keyclass =
2N/A KMF_SYMMETRIC;
2N/A } else if (keytype == CKK_RC4) {
2N/A keys[n].keyalg = KMF_RC4;
2N/A keys[n].keyclass =
2N/A KMF_SYMMETRIC;
2N/A } else if (keytype == CKK_DES) {
2N/A keys[n].keyalg = KMF_DES;
2N/A keys[n].keyclass =
2N/A KMF_SYMMETRIC;
2N/A } else if (keytype == CKK_DES3) {
2N/A keys[n].keyalg = KMF_DES3;
2N/A keys[n].keyclass =
2N/A KMF_SYMMETRIC;
2N/A } else if (keytype ==
2N/A CKK_GENERIC_SECRET) {
2N/A keys[n].keyalg =
2N/A KMF_GENERIC_SECRET;
2N/A keys[n].keyclass =
2N/A KMF_SYMMETRIC;
2N/A }
2N/A
2N/A }
2N/A n++;
2N/A } else {
2N/A break;
2N/A }
2N/A }
2N/A ckrv = C_FindObjectsFinal(kmfh->pk11handle);
2N/A
2N/A /* "numkeys" indicates the number that were actually found */
2N/A *numkeys = n;
2N/A }
2N/A
2N/A if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
2N/A if ((rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
2N/A numattr, (void *)&format, NULL)) == KMF_OK) {
2N/A if (format == KMF_FORMAT_RAWKEY ||
2N/A format == KMF_FORMAT_PEM) {
2N/A /* Convert keys to "rawkey" format */
2N/A for (i = 0; i < (*numkeys); i++) {
2N/A KMF_RAW_KEY_DATA *rkey = NULL;
2N/A rv = keyObj2RawKey(handle, &keys[i],
2N/A &rkey);
2N/A if (rv == KMF_OK) {
2N/A keys[i].keyp = rkey;
2N/A keys[i].israw = TRUE;
2N/A } else {
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A } else {
2N/A rv = KMF_OK; /* format is optional */
2N/A }
2N/A }
2N/A
2N/Aend:
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A /* Report authentication failures to the caller */
2N/A if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2N/A ckrv == CKR_PIN_INCORRECT ||
2N/A ckrv == CKR_PIN_INVALID ||
2N/A ckrv == CKR_PIN_EXPIRED ||
2N/A ckrv == CKR_PIN_LOCKED ||
2N/A ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_INTERNAL;
2N/A } else if ((*numkeys) == 0) {
2N/A rv = KMF_ERR_KEY_NOT_FOUND;
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/Astatic char *
2N/AconvertDate(char *fulldate)
2N/A{
2N/A struct tm tms;
2N/A char newtime[9];
2N/A
2N/A (void) strptime(fulldate, "%b %d %T %Y %Z", &tms);
2N/A
2N/A if (tms.tm_year < 69)
2N/A tms.tm_year += 100;
2N/A
2N/A (void) strftime(newtime, sizeof (newtime), "m%d", &tms);
2N/A
2N/A newtime[8] = 0;
2N/A
2N/A /* memory returned must be freed by the caller */
2N/A return ((char *)strdup(newtime));
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Astore_raw_key(KMF_HANDLE_T handle,
2N/A KMF_ATTRIBUTE *attrlist, int numattr,
2N/A KMF_RAW_KEY_DATA *rawkey)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A int i;
2N/A CK_RV ckrv = CKR_OK;
2N/A CK_ATTRIBUTE templ[32];
2N/A CK_OBJECT_HANDLE keyobj;
2N/A CK_KEY_TYPE keytype;
2N/A CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
2N/A CK_BBOOL cktrue = TRUE;
2N/A CK_DATE startdate, enddate;
2N/A KMF_DATA id = {NULL, 0};
2N/A KMF_DATA subject = {NULL, 0};
2N/A KMF_X509EXT_KEY_USAGE kuext;
2N/A KMF_X509_CERTIFICATE *x509 = NULL;
2N/A CK_BBOOL kufound = B_FALSE;
2N/A KMF_DATA *cert = NULL;
2N/A char *notbefore = NULL, *start = NULL;
2N/A char *notafter = NULL, *end = NULL;
2N/A char *keylabel = NULL;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (rawkey->keytype == KMF_RSA)
2N/A keytype = CKK_RSA;
2N/A else if (rawkey->keytype == KMF_DSA)
2N/A keytype = CKK_DSA;
2N/A else if (rawkey->keytype == KMF_ECDSA)
2N/A keytype = CKK_EC;
2N/A else
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred != NULL) {
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A /*
2N/A * If the caller did not specify a label, see if the raw key
2N/A * came with one (possible if it came from a PKCS#12 file).
2N/A */
2N/A if (keylabel == NULL) {
2N/A keylabel = rawkey->label;
2N/A }
2N/A
2N/A i = 0;
2N/A SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++;
2N/A SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
2N/A SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
2N/A SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
2N/A if (keytype != CKK_EC)
2N/A SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
2N/A
2N/A cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2N/A if (cert != NULL) {
2N/A id.Data = NULL;
2N/A id.Length = 0;
2N/A rv = kmf_get_cert_id_data(cert, &id);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A
2N/A rv = DerDecodeSignedCertificate((const KMF_DATA *)cert, &x509);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A
2N/A rv = DerEncodeName(&x509->certificate.subject, &subject);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length);
2N/A i++;
2N/A
2N/A rv = kmf_get_cert_start_date_str(handle, cert, &notbefore);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A start = convertDate(notbefore);
2N/A free(notbefore);
2N/A
2N/A rv = kmf_get_cert_end_date_str(handle, cert, &notafter);
2N/A if (rv != KMF_OK) {
2N/A goto cleanup;
2N/A }
2N/A end = convertDate(notafter);
2N/A free(notafter);
2N/A if (id.Data != NULL && id.Data != NULL && id.Length > 0) {
2N/A SETATTR(templ, i, CKA_ID, id.Data, id.Length);
2N/A i++;
2N/A }
2N/A if (start != NULL) {
2N/A /*
2N/A * This makes some potentially dangerous assumptions:
2N/A * 1. that the startdate in the parameter block is
2N/A * properly formatted as YYYYMMDD
2N/A * 2. That the CK_DATE structure is always the same.
2N/A */
2N/A (void) memcpy(&startdate, start, sizeof (CK_DATE));
2N/A SETATTR(templ, i, CKA_START_DATE, &startdate,
2N/A sizeof (startdate));
2N/A i++;
2N/A }
2N/A if (end != NULL) {
2N/A (void) memcpy(&enddate, end, sizeof (CK_DATE));
2N/A SETATTR(templ, i, CKA_END_DATE, &enddate,
2N/A sizeof (enddate));
2N/A i++;
2N/A }
2N/A
2N/A if ((rv = kmf_get_cert_ku(cert, &kuext)) != KMF_OK &&
2N/A rv != KMF_ERR_EXTENSION_NOT_FOUND)
2N/A goto cleanup;
2N/A
2N/A kufound = (rv == KMF_OK);
2N/A rv = KMF_OK; /* reset if we got KMF_ERR_EXTENSION_NOT_FOUND */
2N/A }
2N/A
2N/A /*
2N/A * Only set the KeyUsage stuff if the KU extension was present.
2N/A */
2N/A if (kufound) {
2N/A CK_BBOOL condition;
2N/A
2N/A condition = (kuext.KeyUsageBits & KMF_keyEncipherment) ?
2N/A B_TRUE : B_FALSE;
2N/A SETATTR(templ, i, CKA_UNWRAP, &condition, sizeof (CK_BBOOL));
2N/A i++;
2N/A condition = (kuext.KeyUsageBits & KMF_dataEncipherment) ?
2N/A B_TRUE : B_FALSE;
2N/A SETATTR(templ, i, CKA_DECRYPT, &condition, sizeof (CK_BBOOL));
2N/A i++;
2N/A condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2N/A B_TRUE : B_FALSE;
2N/A SETATTR(templ, i, CKA_SIGN, &condition, sizeof (CK_BBOOL));
2N/A i++;
2N/A condition = (kuext.KeyUsageBits & KMF_digitalSignature) ?
2N/A B_TRUE : B_FALSE;
2N/A SETATTR(templ, i, CKA_SIGN_RECOVER, &condition,
2N/A sizeof (CK_BBOOL));
2N/A i++;
2N/A
2N/A }
2N/A
2N/A if (keylabel != NULL) {
2N/A SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
2N/A i++;
2N/A }
2N/A if (id.Data == NULL && rawkey->id.Data != NULL) {
2N/A SETATTR(templ, i, CKA_ID, rawkey->id.Data,
2N/A rawkey->id.Length);
2N/A i++;
2N/A }
2N/A if (keytype == CKK_RSA) {
2N/A SETATTR(templ, i, CKA_MODULUS,
2N/A rawkey->rawdata.rsa.mod.val,
2N/A rawkey->rawdata.rsa.mod.len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_PUBLIC_EXPONENT,
2N/A rawkey->rawdata.rsa.pubexp.val,
2N/A rawkey->rawdata.rsa.pubexp.len);
2N/A i++;
2N/A if (rawkey->rawdata.rsa.priexp.val != NULL) {
2N/A SETATTR(templ, i, CKA_PRIVATE_EXPONENT,
2N/A rawkey->rawdata.rsa.priexp.val,
2N/A rawkey->rawdata.rsa.priexp.len);
2N/A i++;
2N/A }
2N/A if (rawkey->rawdata.rsa.prime1.val != NULL) {
2N/A SETATTR(templ, i, CKA_PRIME_1,
2N/A rawkey->rawdata.rsa.prime1.val,
2N/A rawkey->rawdata.rsa.prime1.len);
2N/A i++;
2N/A }
2N/A if (rawkey->rawdata.rsa.prime2.val != NULL) {
2N/A SETATTR(templ, i, CKA_PRIME_2,
2N/A rawkey->rawdata.rsa.prime2.val,
2N/A rawkey->rawdata.rsa.prime2.len);
2N/A i++;
2N/A }
2N/A if (rawkey->rawdata.rsa.exp1.val != NULL) {
2N/A SETATTR(templ, i, CKA_EXPONENT_1,
2N/A rawkey->rawdata.rsa.exp1.val,
2N/A rawkey->rawdata.rsa.exp1.len);
2N/A i++;
2N/A }
2N/A if (rawkey->rawdata.rsa.exp2.val != NULL) {
2N/A SETATTR(templ, i, CKA_EXPONENT_2,
2N/A rawkey->rawdata.rsa.exp2.val,
2N/A rawkey->rawdata.rsa.exp2.len);
2N/A i++;
2N/A }
2N/A if (rawkey->rawdata.rsa.coef.val != NULL) {
2N/A SETATTR(templ, i, CKA_COEFFICIENT,
2N/A rawkey->rawdata.rsa.coef.val,
2N/A rawkey->rawdata.rsa.coef.len);
2N/A i++;
2N/A }
2N/A } else if (keytype == CKK_DSA) {
2N/A SETATTR(templ, i, CKA_PRIME,
2N/A rawkey->rawdata.dsa.prime.val,
2N/A rawkey->rawdata.dsa.prime.len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_SUBPRIME,
2N/A rawkey->rawdata.dsa.subprime.val,
2N/A rawkey->rawdata.dsa.subprime.len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_BASE,
2N/A rawkey->rawdata.dsa.base.val,
2N/A rawkey->rawdata.dsa.base.len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_VALUE,
2N/A rawkey->rawdata.dsa.value.val,
2N/A rawkey->rawdata.dsa.value.len);
2N/A i++;
2N/A } else if (keytype == CKK_EC) {
2N/A SETATTR(templ, i, CKA_SIGN, &cktrue, sizeof (cktrue));
2N/A i++;
2N/A SETATTR(templ, i, CKA_DERIVE, &cktrue, sizeof (cktrue));
2N/A i++;
2N/A SETATTR(templ, i, CKA_VALUE,
2N/A rawkey->rawdata.ec.value.val,
2N/A rawkey->rawdata.ec.value.len);
2N/A i++;
2N/A SETATTR(templ, i, CKA_EC_PARAMS,
2N/A rawkey->rawdata.ec.params.Data,
2N/A rawkey->rawdata.ec.params.Length);
2N/A i++;
2N/A }
2N/A
2N/A ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A
2N/A /* Report authentication failures to the caller */
2N/A if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2N/A ckrv == CKR_PIN_INCORRECT ||
2N/A ckrv == CKR_PIN_INVALID ||
2N/A ckrv == CKR_PIN_EXPIRED ||
2N/A ckrv == CKR_PIN_LOCKED ||
2N/A ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_INTERNAL;
2N/A }
2N/Acleanup:
2N/A if (start != NULL)
2N/A free(start);
2N/A if (end != NULL)
2N/A free(end);
2N/A kmf_free_data(&id);
2N/A kmf_free_data(&subject);
2N/A kmf_free_signed_cert(x509);
2N/A free(x509);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_CreateSymKey(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_OBJECT_HANDLE keyhandle;
2N/A CK_MECHANISM keyGenMech;
2N/A CK_OBJECT_CLASS class = CKO_SECRET_KEY;
2N/A CK_ULONG secKeyType;
2N/A CK_ULONG secKeyLen; /* for RC4 and AES */
2N/A CK_BBOOL true = TRUE;
2N/A CK_BBOOL false = FALSE;
2N/A CK_ATTRIBUTE templ[15];
2N/A CK_BYTE *keydata = NULL;
2N/A int i = 0;
2N/A KMF_KEY_HANDLE *symkey;
2N/A KMF_KEY_ALG keytype;
2N/A uint32_t keylen = 0;
2N/A uint32_t attrkeylen = 0;
2N/A uint32_t keylen_size = sizeof (uint32_t);
2N/A char *keylabel = NULL;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A uint32_t is_sensitive = B_FALSE;
2N/A uint32_t is_not_extractable = B_FALSE;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2N/A if (symkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
2N/A (void *)&keytype, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A if (keylabel == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_sensitive, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_not_extractable, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /*
2N/A * For AES, RC4, DES and 3DES, call C_GenerateKey() to create a key.
2N/A *
2N/A * For a generic secret key, because it may not be supported in
2N/A * C_GenerateKey() for some PKCS11 providers, we will handle it
2N/A * differently.
2N/A */
2N/A if (keytype == KMF_GENERIC_SECRET) {
2N/A rv = create_generic_secret_key(handle, numattr,
2N/A attrlist, &keyhandle);
2N/A if (rv != KMF_OK)
2N/A goto out;
2N/A else
2N/A goto setup;
2N/A }
2N/A
2N/A rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
2N/A NULL, &attrkeylen);
2N/A if (rv == KMF_OK && attrkeylen > 0) {
2N/A keydata = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
2N/A numattr);
2N/A } else {
2N/A keydata = NULL;
2N/A attrkeylen = 0;
2N/A rv = KMF_OK;
2N/A }
2N/A if (keydata != NULL) {
2N/A if (keytype == KMF_DES && attrkeylen != 8) {
2N/A rv = KMF_ERR_BAD_KEY_SIZE;
2N/A goto out;
2N/A }
2N/A if (keytype == KMF_DES3 && attrkeylen != 24) {
2N/A rv = KMF_ERR_BAD_KEY_SIZE;
2N/A goto out;
2N/A }
2N/A /*
2N/A * This may override what the user gave on the
2N/A * command line.
2N/A */
2N/A keylen = attrkeylen * 8; /* bytes to bits */
2N/A } else {
2N/A /*
2N/A * If keydata was not given, key length must be
2N/A * provided.
2N/A */
2N/A rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
2N/A &keylen, &keylen_size);
2N/A if (rv == KMF_ERR_ATTR_NOT_FOUND &&
2N/A (keytype == KMF_DES || keytype == KMF_DES3))
2N/A /* keylength is not required for DES and 3DES */
2N/A rv = KMF_OK;
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A }
2N/A
2N/A if ((keylen % 8) != 0) {
2N/A return (KMF_ERR_BAD_KEY_SIZE);
2N/A }
2N/A secKeyLen = keylen / 8; /* in bytes for RC4/AES */
2N/A
2N/A /*
2N/A * Only set CKA_VALUE_LEN if the key data was not given and
2N/A * we are creating an RC4 or AES key.
2N/A */
2N/A if (keydata == NULL &&
2N/A (keytype == KMF_AES || keytype == KMF_RC4)) {
2N/A SETATTR(templ, i, CKA_VALUE_LEN, &secKeyLen,
2N/A sizeof (secKeyLen));
2N/A i++;
2N/A }
2N/A
2N/A /* Other keytypes */
2N/A keyGenMech.pParameter = NULL_PTR;
2N/A keyGenMech.ulParameterLen = 0;
2N/A switch (keytype) {
2N/A case KMF_AES:
2N/A keyGenMech.mechanism = CKM_AES_KEY_GEN;
2N/A secKeyType = CKK_AES;
2N/A break;
2N/A case KMF_RC4:
2N/A keyGenMech.mechanism = CKM_RC4_KEY_GEN;
2N/A secKeyType = CKK_RC4;
2N/A break;
2N/A case KMF_DES:
2N/A keyGenMech.mechanism = CKM_DES_KEY_GEN;
2N/A secKeyType = CKK_DES;
2N/A break;
2N/A case KMF_DES3:
2N/A keyGenMech.mechanism = CKM_DES3_KEY_GEN;
2N/A secKeyType = CKK_DES3;
2N/A break;
2N/A default:
2N/A return (KMF_ERR_BAD_KEY_TYPE);
2N/A }
2N/A if (keydata != NULL) {
2N/A SETATTR(templ, i, CKA_VALUE, keydata, secKeyLen);
2N/A i++;
2N/A }
2N/A SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2N/A i++;
2N/A SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2N/A i++;
2N/A
2N/A if (keylabel != NULL) {
2N/A SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
2N/A i++;
2N/A }
2N/A
2N/A if (is_sensitive == B_TRUE) {
2N/A SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2N/A } else {
2N/A SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2N/A }
2N/A i++;
2N/A
2N/A if (is_not_extractable == B_TRUE) {
2N/A SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2N/A } else {
2N/A SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2N/A }
2N/A i++;
2N/A
2N/A SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_ENCRYPT, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_DECRYPT, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_VERIFY, &true, sizeof (true));
2N/A i++;
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A /* If the key data was given, use C_CreateObject */
2N/A if (keydata != NULL) {
2N/A ckrv = C_CreateObject(hSession, templ, i, &keyhandle);
2N/A } else {
2N/A ckrv = C_GenerateKey(hSession, &keyGenMech, templ, i,
2N/A &keyhandle);
2N/A }
2N/A if (ckrv != CKR_OK) {
2N/A if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2N/A ckrv == CKR_PIN_INCORRECT ||
2N/A ckrv == CKR_PIN_INVALID ||
2N/A ckrv == CKR_PIN_EXPIRED ||
2N/A ckrv == CKR_PIN_LOCKED ||
2N/A ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A SET_ERROR(kmfh, ckrv);
2N/A goto out;
2N/A }
2N/A
2N/Asetup:
2N/A symkey->kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A symkey->keyalg = keytype;
2N/A symkey->keyclass = KMF_SYMMETRIC;
2N/A symkey->israw = FALSE;
2N/A symkey->keyp = (void *)keyhandle;
2N/A
2N/Aout:
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2N/A KMF_RAW_SYM_KEY *rkey)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A if (symkey == NULL || rkey == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A else if (symkey->keyclass != KMF_SYMMETRIC)
2N/A return (KMF_ERR_BAD_KEY_CLASS);
2N/A
2N/A /*
2N/A * If the key is already in "raw" format, copy the data
2N/A * to the new record if possible.
2N/A */
2N/A if (symkey->israw) {
2N/A KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2N/A
2N/A if (rawkey == NULL)
2N/A return (KMF_ERR_BAD_KEYHANDLE);
2N/A if (rawkey->sensitive)
2N/A return (KMF_ERR_SENSITIVE_KEY);
2N/A if (rawkey->not_extractable)
2N/A return (KMF_ERR_UNEXTRACTABLE_KEY);
2N/A
2N/A if (rawkey->rawdata.sym.keydata.val == NULL ||
2N/A rawkey->rawdata.sym.keydata.len == 0)
2N/A return (KMF_ERR_GETKEYVALUE_FAILED);
2N/A
2N/A rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2N/A if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A (void) memcpy(rkey->keydata.val,
2N/A rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2N/A } else {
2N/A rv = get_raw_sym(kmfh, (CK_OBJECT_HANDLE)symkey->keyp, rkey);
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_SetTokenPin(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN ret = KMF_OK;
2N/A CK_RV rv = CKR_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_SESSION_HANDLE session = NULL;
2N/A KMF_CREDENTIAL *oldcred;
2N/A KMF_CREDENTIAL *newcred;
2N/A CK_SLOT_ID slotid;
2N/A CK_USER_TYPE user = CKU_USER;
2N/A
2N/A if (handle == NULL || attrlist == NULL || numattr == 0)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A oldcred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (oldcred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A newcred = kmf_get_attr_ptr(KMF_NEWPIN_ATTR, attrlist, numattr);
2N/A if (newcred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_SLOT_ID_ATTR, attrlist, numattr,
2N/A (void *)&slotid, NULL);
2N/A if (rv != KMF_OK) {
2N/A char *tokenlabel = NULL;
2N/A /*
2N/A * If a slot wasn't given, the user must pass
2N/A * a token label so we can find the slot here.
2N/A */
2N/A tokenlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist,
2N/A numattr);
2N/A if (tokenlabel == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_pk11_token_lookup(handle, tokenlabel, &slotid);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A }
2N/A rv = kmf_get_attr(KMF_PK11_USER_TYPE_ATTR, attrlist, numattr,
2N/A (void *)&user, NULL);
2N/A if (rv != CKR_OK)
2N/A user = CKU_USER;
2N/A
2N/A rv = C_OpenSession(slotid, CKF_SERIAL_SESSION | CKF_RW_SESSION,
2N/A NULL, NULL, &session);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A ret = KMF_ERR_UNINITIALIZED;
2N/A goto end;
2N/A }
2N/A
2N/A rv = C_Login(session, user, (CK_BYTE *)oldcred->cred,
2N/A oldcred->credlen);
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A if (rv == CKR_PIN_INCORRECT ||
2N/A rv == CKR_PIN_INVALID ||
2N/A rv == CKR_PIN_EXPIRED ||
2N/A rv == CKR_PIN_LOCKED)
2N/A ret = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A ret = KMF_ERR_INTERNAL;
2N/A
2N/A goto end;
2N/A }
2N/A
2N/A rv = C_SetPIN(session,
2N/A (CK_BYTE *)oldcred->cred, oldcred->credlen,
2N/A (CK_BYTE *)newcred->cred, newcred->credlen);
2N/A
2N/A if (rv != CKR_OK) {
2N/A SET_ERROR(kmfh, rv);
2N/A if (rv == CKR_PIN_INCORRECT ||
2N/A rv == CKR_PIN_INVALID ||
2N/A rv == CKR_PIN_EXPIRED ||
2N/A rv == CKR_PIN_LOCKED)
2N/A ret = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A ret = KMF_ERR_INTERNAL;
2N/A }
2N/Aend:
2N/A if (session != NULL)
2N/A (void) C_CloseSession(session);
2N/A return (ret);
2N/A}
2N/A
2N/Astatic KMF_RETURN
2N/Acreate_generic_secret_key(KMF_HANDLE_T handle,
2N/A int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A CK_RV ckrv;
2N/A CK_SESSION_HANDLE hSession = kmfh->pk11handle;
2N/A CK_OBJECT_CLASS class = CKO_SECRET_KEY;
2N/A CK_ULONG secKeyType = CKK_GENERIC_SECRET;
2N/A CK_ULONG secKeyLen;
2N/A CK_BBOOL true = TRUE;
2N/A CK_BBOOL false = FALSE;
2N/A CK_ATTRIBUTE templ[15];
2N/A int i;
2N/A int random_fd = -1;
2N/A int nread;
2N/A int freebuf = 0;
2N/A char *buf = NULL;
2N/A uint32_t keylen = 0, attrkeylen = 0;
2N/A char *keylabel = NULL;
2N/A KMF_CREDENTIAL *cred;
2N/A uint32_t is_sensitive, is_not_extractable;
2N/A
2N/A keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2N/A if (keylabel == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_SENSITIVE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_sensitive, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_NON_EXTRACTABLE_BOOL_ATTR, attrlist, numattr,
2N/A (void *)&is_not_extractable, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = kmf_get_attr(KMF_KEY_DATA_ATTR, attrlist, numattr,
2N/A NULL, &attrkeylen);
2N/A if (rv == KMF_OK && attrkeylen > 0) {
2N/A buf = kmf_get_attr_ptr(KMF_KEY_DATA_ATTR, attrlist,
2N/A numattr);
2N/A secKeyLen = attrkeylen;
2N/A } else {
2N/A buf = NULL;
2N/A rv = KMF_OK;
2N/A }
2N/A if (buf == NULL) {
2N/A /*
2N/A * If the key data was not given, key length must
2N/A * be provided.
2N/A */
2N/A rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
2N/A &keylen, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /*
2N/A * Check the key size.
2N/A */
2N/A if ((keylen % 8) != 0) {
2N/A return (KMF_ERR_BAD_KEY_SIZE);
2N/A } else {
2N/A secKeyLen = keylen/8; /* in bytes */
2N/A }
2N/A
2N/A /*
2N/A * Generate a random number with the key size first.
2N/A */
2N/A buf = malloc(secKeyLen);
2N/A if (buf == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A freebuf = 1;
2N/A while ((random_fd = open(DEV_RANDOM, O_RDONLY)) < 0) {
2N/A if (errno != EINTR)
2N/A break;
2N/A }
2N/A
2N/A if (random_fd < 0) {
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A goto out;
2N/A }
2N/A
2N/A nread = read(random_fd, buf, secKeyLen);
2N/A if (nread <= 0 || nread != secKeyLen) {
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A goto out;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * Authenticate into the token and call C_CreateObject to generate
2N/A * a generic secret token key.
2N/A */
2N/A rv = pk11_authenticate(handle, cred);
2N/A if (rv != KMF_OK) {
2N/A goto out;
2N/A }
2N/A
2N/A i = 0;
2N/A SETATTR(templ, i, CKA_CLASS, &class, sizeof (class));
2N/A i++;
2N/A SETATTR(templ, i, CKA_KEY_TYPE, &secKeyType, sizeof (secKeyType));
2N/A i++;
2N/A SETATTR(templ, i, CKA_VALUE, buf, secKeyLen);
2N/A i++;
2N/A
2N/A if (keylabel != NULL) {
2N/A SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel));
2N/A i++;
2N/A }
2N/A
2N/A if (is_sensitive == B_TRUE) {
2N/A SETATTR(templ, i, CKA_SENSITIVE, &true, sizeof (true));
2N/A } else {
2N/A SETATTR(templ, i, CKA_SENSITIVE, &false, sizeof (false));
2N/A }
2N/A i++;
2N/A
2N/A if (is_not_extractable == B_TRUE) {
2N/A SETATTR(templ, i, CKA_EXTRACTABLE, &false, sizeof (false));
2N/A } else {
2N/A SETATTR(templ, i, CKA_EXTRACTABLE, &true, sizeof (true));
2N/A }
2N/A i++;
2N/A
2N/A SETATTR(templ, i, CKA_TOKEN, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_PRIVATE, &true, sizeof (true));
2N/A i++;
2N/A SETATTR(templ, i, CKA_SIGN, &true, sizeof (true));
2N/A i++;
2N/A
2N/A ckrv = C_CreateObject(hSession, templ, i, key);
2N/A if (ckrv != CKR_OK) {
2N/A if (ckrv == CKR_USER_NOT_LOGGED_IN ||
2N/A ckrv == CKR_PIN_INCORRECT ||
2N/A ckrv == CKR_PIN_INVALID ||
2N/A ckrv == CKR_PIN_EXPIRED ||
2N/A ckrv == CKR_PIN_LOCKED ||
2N/A ckrv == CKR_SESSION_READ_ONLY)
2N/A rv = KMF_ERR_AUTH_FAILED;
2N/A else
2N/A rv = KMF_ERR_KEYGEN_FAILED;
2N/A SET_ERROR(kmfh, ckrv);
2N/A }
2N/A
2N/Aout:
2N/A if (buf != NULL && freebuf)
2N/A free(buf);
2N/A
2N/A if (random_fd != -1)
2N/A (void) close(random_fd);
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_StoreKey(KMF_HANDLE_T handle,
2N/A int numattr,
2N/A KMF_ATTRIBUTE *attlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A KMF_CREDENTIAL cred = {NULL, 0};
2N/A KMF_KEY_HANDLE *key;
2N/A KMF_RAW_KEY_DATA *rawkey = NULL;
2N/A CK_BBOOL btrue = TRUE;
2N/A CK_ATTRIBUTE tokenattr[1];
2N/A CK_OBJECT_HANDLE newobj;
2N/A CK_RV ckrv;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED);
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attlist, numattr,
2N/A (void *)&cred, NULL);
2N/A if (rv != KMF_OK)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A rv = pk11_authenticate(handle, &cred);
2N/A if (rv != KMF_OK)
2N/A return (rv);
2N/A
2N/A key = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attlist, numattr);
2N/A if (key == NULL) {
2N/A key = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attlist,
2N/A numattr);
2N/A if (key == NULL)
2N/A rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attlist,
2N/A numattr);
2N/A }
2N/A if (key == NULL && rawkey == NULL)
2N/A return (KMF_ERR_ATTR_NOT_FOUND);
2N/A
2N/A if (rawkey != NULL) {
2N/A rv = store_raw_key(handle, attlist, numattr, rawkey);
2N/A } else if (key && key->kstype == KMF_KEYSTORE_PK11TOKEN) {
2N/A
2N/A SETATTR(tokenattr, 0, CKA_TOKEN, &btrue, sizeof (btrue));
2N/A /* Copy the key object to the token */
2N/A ckrv = C_CopyObject(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)key->keyp, tokenattr, 1, &newobj);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A
2N/A /* Replace the object handle with the new token-based one */
2N/A ckrv = C_DestroyObject(kmfh->pk11handle,
2N/A (CK_OBJECT_HANDLE)key->keyp);
2N/A if (ckrv != CKR_OK) {
2N/A SET_ERROR(kmfh, ckrv);
2N/A return (KMF_ERR_INTERNAL);
2N/A }
2N/A key->keyp = (void *)newobj;
2N/A } else {
2N/A rv = KMF_ERR_BAD_PARAMETER;
2N/A }
2N/A
2N/A return (rv);
2N/A}
2N/A
2N/A
2N/AKMF_RETURN
2N/AKMFPK11_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2N/A{
2N/A KMF_RETURN rv = KMF_OK;
2N/A KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2N/A KMF_CREDENTIAL *cred = NULL;
2N/A KMF_CREDENTIAL *p12cred = NULL;
2N/A char *filename = NULL;
2N/A KMF_X509_DER_CERT *certlist = NULL;
2N/A KMF_KEY_HANDLE *keylist = NULL;
2N/A uint32_t numcerts;
2N/A uint32_t numkeys;
2N/A char *certlabel = NULL;
2N/A char *issuer = NULL;
2N/A char *subject = NULL;
2N/A KMF_BIGINT *serial = NULL;
2N/A KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
2N/A KMF_ATTRIBUTE fc_attrlist[16];
2N/A int i;
2N/A
2N/A if (kmfh == NULL)
2N/A return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
2N/A
2N/A if (kmfh->pk11handle == CK_INVALID_HANDLE)
2N/A return (KMF_ERR_NO_TOKEN_SELECTED);
2N/A
2N/A /* First get the required attributes */
2N/A cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
2N/A if (cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
2N/A if (p12cred == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
2N/A numattr);
2N/A if (filename == NULL)
2N/A return (KMF_ERR_BAD_PARAMETER);
2N/A
2N/A /* Find all the certificates that match the searching criteria */
2N/A i = 0;
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2N/A i++;
2N/A
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_COUNT_ATTR, &numcerts, sizeof (uint32_t));
2N/A i++;
2N/A
2N/A certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2N/A if (certlabel != NULL) {
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
2N/A i++;
2N/A }
2N/A
2N/A issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
2N/A if (issuer != NULL) {
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
2N/A i++;
2N/A }
2N/A
2N/A subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
2N/A if (subject != NULL) {
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
2N/A i++;
2N/A }
2N/A
2N/A serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
2N/A if (serial != NULL) {
2N/A kmf_set_attr_at_index(fc_attrlist, i,
2N/A KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
2N/A i++;
2N/A }
2N/A
2N/A rv = KMFPK11_FindCert(handle, i, fc_attrlist);
2N/A
2N/A if (rv == KMF_OK && numcerts > 0) {
2N/A certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
2N/A sizeof (KMF_X509_DER_CERT));
2N/A if (certlist == NULL)
2N/A return (KMF_ERR_MEMORY);
2N/A
2N/A (void) memset(certlist, 0, numcerts *
2N/A sizeof (KMF_X509_DER_CERT));
2N/A
2N/A kmf_set_attr_at_index(fc_attrlist, i, KMF_X509_DER_CERT_ATTR,
2N/A certlist, sizeof (KMF_X509_DER_CERT));
2N/A i++;
2N/A
2N/A rv = kmf_find_cert(handle, i, fc_attrlist);
2N/A if (rv != KMF_OK) {
2N/A free(certlist);
2N/A return (rv);
2N/A }
2N/A } else {
2N/A return (rv);
2N/A }
2N/A
2N/A /* For each certificate, find the matching private key */
2N/A numkeys = 0;
2N/A for (i = 0; i < numcerts; i++) {
2N/A KMF_ATTRIBUTE fk_attrlist[16];
2N/A int j = 0;
2N/A KMF_KEY_HANDLE newkey;
2N/A KMF_ENCODE_FORMAT format = KMF_FORMAT_RAWKEY;
2N/A
2N/A kmf_set_attr_at_index(fk_attrlist, j,
2N/A KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2N/A j++;
2N/A
2N/A kmf_set_attr_at_index(fk_attrlist, j,
2N/A KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
2N/A j++;
2N/A
2N/A kmf_set_attr_at_index(fk_attrlist, j,
2N/A KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
2N/A j++;
2N/A
2N/A kmf_set_attr_at_index(fk_attrlist, j,
2N/A KMF_CERT_DATA_ATTR, &certlist[i].certificate,
2N/A sizeof (KMF_DATA));
2N/A j++;
2N/A
2N/A kmf_set_attr_at_index(fk_attrlist, j,
2N/A KMF_KEY_HANDLE_ATTR, &newkey, sizeof (KMF_KEY_HANDLE));
2N/A j++;
2N/A
2N/A rv = KMFPK11_FindPrikeyByCert(handle, j, fk_attrlist);
2N/A if (rv == KMF_OK) {
2N/A numkeys++;
2N/A keylist = realloc(keylist,
2N/A numkeys * sizeof (KMF_KEY_HANDLE));
2N/A if (keylist == NULL) {
2N/A rv = KMF_ERR_MEMORY;
2N/A goto out;
2N/A }
2N/A keylist[numkeys - 1] = newkey;
2N/A } else if (rv == KMF_ERR_KEY_NOT_FOUND) {
2N/A /* it is OK if a key is not found */
2N/A rv = KMF_OK;
2N/A }
2N/A }
2N/A
2N/A if (rv != KMF_OK)
2N/A goto out;
2N/A
2N/A rv = kmf_build_pk12(handle, numcerts, certlist, numkeys, keylist,
2N/A p12cred, filename);
2N/A
2N/Aout:
2N/A if (certlist != NULL) {
2N/A for (i = 0; i < numcerts; i++)
2N/A kmf_free_kmf_cert(handle, &certlist[i]);
2N/A free(certlist);
2N/A }
2N/A if (keylist != NULL) {
2N/A for (i = 0; i < numkeys; i++)
2N/A kmf_free_kmf_key(handle, &keylist[i]);
2N/A free(keylist);
2N/A }
2N/A
2N/A return (rv);
2N/A}