199ebb4caSwyllys /*
299ebb4caSwyllys * CDDL HEADER START
399ebb4caSwyllys *
499ebb4caSwyllys * The contents of this file are subject to the terms of the
599ebb4caSwyllys * Common Development and Distribution License (the "License").
699ebb4caSwyllys * You may not use this file except in compliance with the License.
799ebb4caSwyllys *
899ebb4caSwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys * See the License for the specific language governing permissions
1199ebb4caSwyllys * and limitations under the License.
1299ebb4caSwyllys *
1399ebb4caSwyllys * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys *
1999ebb4caSwyllys * CDDL HEADER END
209f0bc604SWyllys Ingersoll *
21269e59f9SJan Pechanec * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2299ebb4caSwyllys */
2399ebb4caSwyllys
2499ebb4caSwyllys #include <stdio.h>
2599ebb4caSwyllys #include <dlfcn.h>
2699ebb4caSwyllys #include <link.h>
2799ebb4caSwyllys #include <fcntl.h>
2899ebb4caSwyllys #include <ctype.h>
2999ebb4caSwyllys #include <sys/param.h>
3099ebb4caSwyllys #include <sys/types.h>
3199ebb4caSwyllys #include <sys/stat.h>
3299ebb4caSwyllys #include <errno.h>
3399ebb4caSwyllys #include <sys/socket.h>
3499ebb4caSwyllys #include <netinet/in.h>
3599ebb4caSwyllys #include <arpa/inet.h>
3699ebb4caSwyllys #include <thread.h>
3799ebb4caSwyllys
3899ebb4caSwyllys #include <ber_der.h>
3999ebb4caSwyllys #include <kmfapiP.h>
4099ebb4caSwyllys
4199ebb4caSwyllys #include <pem_encode.h>
4299ebb4caSwyllys #include <rdn_parser.h>
4399ebb4caSwyllys #include <libxml2/libxml/uri.h>
4499ebb4caSwyllys #include <libgen.h>
4599ebb4caSwyllys #include <cryptoutil.h>
4699ebb4caSwyllys
4799ebb4caSwyllys static uchar_t pkcs11_initialized = 0;
4899ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
4999ebb4caSwyllys extern int errno;
5099ebb4caSwyllys
5199ebb4caSwyllys typedef struct {
5299ebb4caSwyllys KMF_RETURN code;
5399ebb4caSwyllys char *message;
5499ebb4caSwyllys } kmf_error_map;
5599ebb4caSwyllys
5699ebb4caSwyllys static kmf_error_map kmf_errcodes[] = {
5799ebb4caSwyllys {KMF_OK, "KMF_OK"},
5899ebb4caSwyllys {KMF_ERR_BAD_PARAMETER, "KMF_ERR_BAD_PARAMETER"},
5999ebb4caSwyllys {KMF_ERR_BAD_KEY_FORMAT, "KMF_ERR_BAD_KEY_FORMAT"},
6099ebb4caSwyllys {KMF_ERR_BAD_ALGORITHM, "KMF_ERR_BAD_ALGORITHM"},
6199ebb4caSwyllys {KMF_ERR_MEMORY, "KMF_ERR_MEMORY"},
6299ebb4caSwyllys {KMF_ERR_ENCODING, "KMF_ERR_ENCODING"},
6399ebb4caSwyllys {KMF_ERR_PLUGIN_INIT, "KMF_ERR_PLUGIN_INIT"},
6499ebb4caSwyllys {KMF_ERR_PLUGIN_NOTFOUND, "KMF_ERR_PLUGIN_NOTFOUND"},
6599ebb4caSwyllys {KMF_ERR_INTERNAL, "KMF_ERR_INTERNAL"},
6699ebb4caSwyllys {KMF_ERR_BAD_CERT_FORMAT, "KMF_ERR_BAD_CERT_FORMAT"},
6799ebb4caSwyllys {KMF_ERR_KEYGEN_FAILED, "KMF_ERR_KEYGEN_FAILED"},
6899ebb4caSwyllys {KMF_ERR_UNINITIALIZED, "KMF_ERR_UNINITIALIZED"},
6999ebb4caSwyllys {KMF_ERR_ISSUER, "KMF_ERR_ISSUER"},
7099ebb4caSwyllys {KMF_ERR_NOT_REVOKED, "KMF_ERR_NOT_REVOKED"},
7199ebb4caSwyllys {KMF_ERR_CERT_NOT_FOUND, "KMF_ERR_CERT_NOT_FOUND"},
7299ebb4caSwyllys {KMF_ERR_CRL_NOT_FOUND, "KMF_ERR_CRL_NOT_FOUND"},
7399ebb4caSwyllys {KMF_ERR_RDN_PARSER, "KMF_ERR_RDN_PARSER"},
7499ebb4caSwyllys {KMF_ERR_RDN_ATTR, "KMF_ERR_RDN_ATTR"},
7599ebb4caSwyllys {KMF_ERR_SLOTNAME, "KMF_ERR_SLOTNAME"},
7699ebb4caSwyllys {KMF_ERR_EMPTY_CRL, "KMF_ERR_EMPTY_CRL"},
7799ebb4caSwyllys {KMF_ERR_BUFFER_SIZE, "KMF_ERR_BUFFER_SIZE"},
7899ebb4caSwyllys {KMF_ERR_AUTH_FAILED, "KMF_ERR_AUTH_FAILED"},
7999ebb4caSwyllys {KMF_ERR_TOKEN_SELECTED, "KMF_ERR_TOKEN_SELECTED"},
8099ebb4caSwyllys {KMF_ERR_NO_TOKEN_SELECTED, "KMF_ERR_NO_TOKEN_SELECTED"},
8199ebb4caSwyllys {KMF_ERR_TOKEN_NOT_PRESENT, "KMF_ERR_TOKEN_NOT_PRESENT"},
8299ebb4caSwyllys {KMF_ERR_EXTENSION_NOT_FOUND, "KMF_ERR_EXTENSION_NOT_FOUND"},
8399ebb4caSwyllys {KMF_ERR_POLICY_ENGINE, "KMF_ERR_POLICY_ENGINE"},
8499ebb4caSwyllys {KMF_ERR_POLICY_DB_FORMAT, "KMF_ERR_POLICY_DB_FORMAT"},
8599ebb4caSwyllys {KMF_ERR_POLICY_NOT_FOUND, "KMF_ERR_POLICY_NOT_FOUND"},
8699ebb4caSwyllys {KMF_ERR_POLICY_DB_FILE, "KMF_ERR_POLICY_DB_FILE"},
8799ebb4caSwyllys {KMF_ERR_POLICY_NAME, "KMF_ERR_POLICY_NAME"},
8899ebb4caSwyllys {KMF_ERR_OCSP_POLICY, "KMF_ERR_OCSP_POLICY"},
8999ebb4caSwyllys {KMF_ERR_TA_POLICY, "KMF_ERR_TA_POLICY"},
9099ebb4caSwyllys {KMF_ERR_KEY_NOT_FOUND, "KMF_ERR_KEY_NOT_FOUND"},
9199ebb4caSwyllys {KMF_ERR_OPEN_FILE, "KMF_ERR_OPEN_FILE"},
9299ebb4caSwyllys {KMF_ERR_OCSP_BAD_ISSUER, "KMF_ERR_OCSP_BAD_ISSUER"},
9399ebb4caSwyllys {KMF_ERR_OCSP_BAD_CERT, "KMF_ERR_OCSP_BAD_CERT"},
9499ebb4caSwyllys {KMF_ERR_OCSP_CREATE_REQUEST, "KMF_ERR_OCSP_CREATE_REQUEST"},
9599ebb4caSwyllys {KMF_ERR_CONNECT_SERVER, "KMF_ERR_CONNECT_SERVER"},
9699ebb4caSwyllys {KMF_ERR_SEND_REQUEST, "KMF_ERR_SEND_REQUEST"},
9799ebb4caSwyllys {KMF_ERR_OCSP_CERTID, "KMF_ERR_OCSP_CERTID"},
9899ebb4caSwyllys {KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
9999ebb4caSwyllys {KMF_ERR_OCSP_RESPONSE_STATUS, "KMF_ERR_OCSP_RESPONSE_STATUS"},
10099ebb4caSwyllys {KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
10199ebb4caSwyllys {KMF_ERR_OCSP_BAD_SIGNER, "KMF_ERR_OCSP_BAD_SIGNER"},
10299ebb4caSwyllys {KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
10399ebb4caSwyllys {KMF_ERR_OCSP_UNKNOWN_CERT, "KMF_ERR_OCSP_UNKNOWN_CERT"},
10499ebb4caSwyllys {KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
10599ebb4caSwyllys {KMF_ERR_BAD_HTTP_RESPONSE, "KMF_ERR_BAD_HTTP_RESPONSE"},
10699ebb4caSwyllys {KMF_ERR_RECV_RESPONSE, "KMF_ERR_RECV_RESPONSE"},
10799ebb4caSwyllys {KMF_ERR_RECV_TIMEOUT, "KMF_ERR_RECV_TIMEOUT"},
10899ebb4caSwyllys {KMF_ERR_DUPLICATE_KEYFILE, "KMF_ERR_DUPLICATE_KEYFILE"},
10999ebb4caSwyllys {KMF_ERR_AMBIGUOUS_PATHNAME, "KMF_ERR_AMBIGUOUS_PATHNAME"},
11099ebb4caSwyllys {KMF_ERR_FUNCTION_NOT_FOUND, "KMF_ERR_FUNCTION_NOT_FOUND"},
11199ebb4caSwyllys {KMF_ERR_PKCS12_FORMAT, "KMF_ERR_PKCS12_FORMAT"},
11299ebb4caSwyllys {KMF_ERR_BAD_KEY_TYPE, "KMF_ERR_BAD_KEY_TYPE"},
11399ebb4caSwyllys {KMF_ERR_BAD_KEY_CLASS, "KMF_ERR_BAD_KEY_CLASS"},
11499ebb4caSwyllys {KMF_ERR_BAD_KEY_SIZE, "KMF_ERR_BAD_KEY_SIZE"},
11599ebb4caSwyllys {KMF_ERR_BAD_HEX_STRING, "KMF_ERR_BAD_HEX_STRING"},
11699ebb4caSwyllys {KMF_ERR_KEYUSAGE, "KMF_ERR_KEYUSAGE"},
11799ebb4caSwyllys {KMF_ERR_VALIDITY_PERIOD, "KMF_ERR_VALIDITY_PERIOD"},
11899ebb4caSwyllys {KMF_ERR_OCSP_REVOKED, "KMF_ERR_OCSP_REVOKED"},
11999ebb4caSwyllys {KMF_ERR_CERT_MULTIPLE_FOUND, "KMF_ERR_CERT_MULTIPLE_FOUND"},
12099ebb4caSwyllys {KMF_ERR_WRITE_FILE, "KMF_ERR_WRITE_FILE"},
12199ebb4caSwyllys {KMF_ERR_BAD_URI, "KMF_ERR_BAD_URI"},
12299ebb4caSwyllys {KMF_ERR_BAD_CRLFILE, "KMF_ERR_BAD_CRLFILE"},
12399ebb4caSwyllys {KMF_ERR_BAD_CERTFILE, "KMF_ERR_BAD_CERTFILE"},
12499ebb4caSwyllys {KMF_ERR_GETKEYVALUE_FAILED, "KMF_ERR_GETKEYVALUE_FAILED"},
12599ebb4caSwyllys {KMF_ERR_BAD_KEYHANDLE, "KMF_ERR_BAD_KEYHANDLE"},
12699ebb4caSwyllys {KMF_ERR_BAD_OBJECT_TYPE, "KMF_ERR_BAD_OBJECT_TYPE"},
12799ebb4caSwyllys {KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
12899ebb4caSwyllys {KMF_ERR_UNKNOWN_CSR_ATTRIBUTE, "KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
12999ebb4caSwyllys {KMF_ERR_UNINITIALIZED_TOKEN, "KMF_ERR_UNINITIALIZED_TOKEN"},
13099ebb4caSwyllys {KMF_ERR_INCOMPLETE_TBS_CERT, "KMF_ERR_INCOMPLETE_TBS_CERT"},
13199ebb4caSwyllys {KMF_ERR_MISSING_ERRCODE, "KMF_ERR_MISSING_ERRCODE"},
13271593db2Swyllys {KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
13371593db2Swyllys {KMF_ERR_SENSITIVE_KEY, "KMF_ERR_SENSITIVE_KEY"},
13471593db2Swyllys {KMF_ERR_UNEXTRACTABLE_KEY, "KMF_ERR_UNEXTRACTABLE_KEY"},
135d00756ccSwyllys {KMF_ERR_KEY_MISMATCH, "KMF_ERR_KEY_MISMATCH"},
136d00756ccSwyllys {KMF_ERR_ATTR_NOT_FOUND, "KMF_ERR_ATTR_NOT_FOUND"},
137269e59f9SJan Pechanec {KMF_ERR_KMF_CONF, "KMF_ERR_KMF_CONF"},
138269e59f9SJan Pechanec {KMF_ERR_NAME_NOT_MATCHED, "KMF_ERR_NAME_NOT_MATCHED"},
139269e59f9SJan Pechanec {KMF_ERR_MAPPER_OPEN, "KMF_ERR_MAPPER_OPEN"},
140269e59f9SJan Pechanec {KMF_ERR_MAPPER_NOT_FOUND, "KMF_ERR_MAPPER_NOT_FOUND"},
141fc2613b0SWyllys Ingersoll {KMF_ERR_MAPPING_FAILED, "KMF_ERR_MAPPING_FAILED"},
142fc2613b0SWyllys Ingersoll {KMF_ERR_CERT_VALIDATION, "KMF_ERR_CERT_VALIDATION"}
14399ebb4caSwyllys };
14499ebb4caSwyllys
14585b65b39Swyllys typedef struct {
14685b65b39Swyllys KMF_KEYSTORE_TYPE kstype;
14785b65b39Swyllys char *path;
14885b65b39Swyllys boolean_t critical;
14985b65b39Swyllys } KMF_PLUGIN_ITEM;
15085b65b39Swyllys
15185b65b39Swyllys KMF_PLUGIN_ITEM plugin_list[] = {
15285b65b39Swyllys {KMF_KEYSTORE_OPENSSL, KMF_PLUGIN_PATH "kmf_openssl.so.1", TRUE},
15385b65b39Swyllys {KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1", TRUE},
15485b65b39Swyllys {KMF_KEYSTORE_NSS, KMF_PLUGIN_PATH "kmf_nss.so.1", FALSE}
15585b65b39Swyllys };
15699ebb4caSwyllys
15730a5e8faSwyllys
15830a5e8faSwyllys
15990c85bf8Swyllys static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
16090c85bf8Swyllys static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
16199ebb4caSwyllys static void free_extensions(KMF_X509_EXTENSIONS *extns);
16290c85bf8Swyllys static void DestroyPlugin(KMF_PLUGIN *);
16399ebb4caSwyllys
164431deaa0Shylee #if defined(__sparcv9)
165431deaa0Shylee #define ISA_PATH "/sparcv9"
166431deaa0Shylee #elif defined(__sparc)
167431deaa0Shylee #define ISA_PATH "/"
168431deaa0Shylee #elif defined(__i386)
169431deaa0Shylee #define ISA_PATH "/"
170431deaa0Shylee #elif defined(__amd64)
171431deaa0Shylee #define ISA_PATH "/amd64"
172431deaa0Shylee #endif
173431deaa0Shylee
174431deaa0Shylee #define DEFAULT_KEYSTORE_NUM 3
175431deaa0Shylee static int kstore_num = DEFAULT_KEYSTORE_NUM;
176431deaa0Shylee conf_entrylist_t *extra_plugin_list = NULL;
177431deaa0Shylee static boolean_t check_extra_plugin = B_FALSE;
178431deaa0Shylee mutex_t extra_plugin_lock = DEFAULTMUTEX;
179431deaa0Shylee
1809b37d296Swyllys KMF_RETURN
init_pk11()1819b37d296Swyllys init_pk11()
18299ebb4caSwyllys {
1839b37d296Swyllys (void) mutex_lock(&init_lock);
1849b37d296Swyllys if (!pkcs11_initialized) {
1859b37d296Swyllys CK_RV rv = C_Initialize(NULL);
1869b37d296Swyllys if ((rv != CKR_OK) &&
1879b37d296Swyllys (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
1889b37d296Swyllys (void) mutex_unlock(&init_lock);
1899b37d296Swyllys return (KMF_ERR_UNINITIALIZED);
1909b37d296Swyllys } else {
1919b37d296Swyllys pkcs11_initialized = 1;
1929b37d296Swyllys }
1939b37d296Swyllys }
1949b37d296Swyllys (void) mutex_unlock(&init_lock);
1959b37d296Swyllys return (KMF_OK);
19699ebb4caSwyllys }
19799ebb4caSwyllys
19899ebb4caSwyllys /*
19999ebb4caSwyllys * Private method for searching the plugin list for the correct
20099ebb4caSwyllys * Plugin to use.
20199ebb4caSwyllys */
20299ebb4caSwyllys KMF_PLUGIN *
FindPlugin(KMF_HANDLE_T handle,KMF_KEYSTORE_TYPE kstype)20399ebb4caSwyllys FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
20499ebb4caSwyllys {
20599ebb4caSwyllys KMF_PLUGIN_LIST *node;
20690c85bf8Swyllys KMF_RETURN ret = KMF_OK;
207431deaa0Shylee KMF_PLUGIN *pluginrec = NULL;
20899ebb4caSwyllys
20999ebb4caSwyllys if (handle == NULL)
21099ebb4caSwyllys return (NULL);
21199ebb4caSwyllys
21299ebb4caSwyllys node = handle->plugins;
21399ebb4caSwyllys
21490c85bf8Swyllys /* See if the desired plugin was already initialized. */
21599ebb4caSwyllys while (node != NULL && node->plugin->type != kstype)
21699ebb4caSwyllys node = node->next;
21799ebb4caSwyllys
218431deaa0Shylee if (node != NULL)
219431deaa0Shylee return (node->plugin);
220431deaa0Shylee
221431deaa0Shylee /* The plugin was not found, try to initialize it here. */
222431deaa0Shylee if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
22390c85bf8Swyllys int i;
22490c85bf8Swyllys int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
22590c85bf8Swyllys for (i = 0; i < numitems; i++) {
22690c85bf8Swyllys if (plugin_list[i].kstype == kstype) {
22790c85bf8Swyllys ret = InitializePlugin(plugin_list[i].kstype,
22890c85bf8Swyllys plugin_list[i].path, &pluginrec);
22990c85bf8Swyllys break;
23090c85bf8Swyllys }
23190c85bf8Swyllys }
23290c85bf8Swyllys
233431deaa0Shylee goto out;
234431deaa0Shylee
235431deaa0Shylee } else {
236431deaa0Shylee /*
237431deaa0Shylee * Not a built-in plugin. Check if it is in the
238431deaa0Shylee * extra_plugin_list. If it is, try to initialize it here.
239431deaa0Shylee */
240431deaa0Shylee conf_entrylist_t *phead = extra_plugin_list;
241431deaa0Shylee char realpath[MAXPATHLEN];
242431deaa0Shylee
243431deaa0Shylee while (phead != NULL) {
244431deaa0Shylee if (phead->entry->kstype == kstype)
245431deaa0Shylee break;
246431deaa0Shylee else
247431deaa0Shylee phead = phead->next;
248431deaa0Shylee }
249431deaa0Shylee
250431deaa0Shylee if (phead == NULL)
251431deaa0Shylee return (NULL);
252431deaa0Shylee
253431deaa0Shylee /*
254431deaa0Shylee * Get the absolute path of the module.
255431deaa0Shylee * - If modulepath is not a full path, then prepend it
256431deaa0Shylee * with KMF_PLUGIN_PATH.
257431deaa0Shylee * - If modulepath is a full path and contain $ISA, then
258431deaa0Shylee * subsitute the architecture dependent path.
259431deaa0Shylee */
260431deaa0Shylee (void) memset(realpath, 0, sizeof (realpath));
261431deaa0Shylee if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
262431deaa0Shylee (void) snprintf(realpath, MAXPATHLEN, "%s%s",
263431deaa0Shylee KMF_PLUGIN_PATH, phead->entry->modulepath);
264431deaa0Shylee } else {
265431deaa0Shylee char *buf = phead->entry->modulepath;
266431deaa0Shylee char *isa;
267431deaa0Shylee
268431deaa0Shylee if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
269431deaa0Shylee char *isa_str;
270431deaa0Shylee
271431deaa0Shylee (void) strncpy(realpath, buf, isa - buf);
272431deaa0Shylee isa_str = strdup(ISA_PATH);
273431deaa0Shylee if (isa_str == NULL) /* not enough memory */
274431deaa0Shylee return (NULL);
275431deaa0Shylee
276431deaa0Shylee (void) strncat(realpath, isa_str,
277431deaa0Shylee strlen(isa_str));
278431deaa0Shylee free(isa_str);
279431deaa0Shylee
280431deaa0Shylee isa += strlen(PKCS11_ISA);
281431deaa0Shylee (void) strlcat(realpath, isa, MAXPATHLEN);
282431deaa0Shylee } else {
283431deaa0Shylee (void) snprintf(realpath, MAXPATHLEN, "%s",
284431deaa0Shylee phead->entry->modulepath);
285431deaa0Shylee }
286431deaa0Shylee }
287431deaa0Shylee
288431deaa0Shylee ret = InitializePlugin(phead->entry->kstype, realpath,
289431deaa0Shylee &pluginrec);
290431deaa0Shylee goto out;
291431deaa0Shylee }
292431deaa0Shylee
293431deaa0Shylee out:
29490c85bf8Swyllys if (ret != KMF_OK || pluginrec == NULL)
295431deaa0Shylee /* No matching plugins found in the built-in list */
29690c85bf8Swyllys return (NULL);
29790c85bf8Swyllys
29890c85bf8Swyllys ret = AddPlugin(handle, pluginrec);
29990c85bf8Swyllys if (ret != KMF_OK) {
30090c85bf8Swyllys DestroyPlugin(pluginrec);
30190c85bf8Swyllys pluginrec = NULL;
30290c85bf8Swyllys }
30390c85bf8Swyllys return (pluginrec);
30490c85bf8Swyllys }
305431deaa0Shylee
30699ebb4caSwyllys
30799ebb4caSwyllys static KMF_RETURN
InitializePlugin(KMF_KEYSTORE_TYPE kstype,char * path,KMF_PLUGIN ** plugin)30899ebb4caSwyllys InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
30999ebb4caSwyllys {
31099ebb4caSwyllys KMF_PLUGIN *p = NULL;
31199ebb4caSwyllys KMF_PLUGIN_FUNCLIST *(*sym)();
31299ebb4caSwyllys
31399ebb4caSwyllys if (path == NULL || plugin == NULL)
31499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
31599ebb4caSwyllys
31699ebb4caSwyllys *plugin = NULL;
31799ebb4caSwyllys
31899ebb4caSwyllys p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
31999ebb4caSwyllys if (p == NULL)
32099ebb4caSwyllys return (KMF_ERR_MEMORY);
32199ebb4caSwyllys
32299ebb4caSwyllys p->type = kstype;
32399ebb4caSwyllys p->path = strdup(path);
32499ebb4caSwyllys if (p->path == NULL) {
32599ebb4caSwyllys free(p);
32699ebb4caSwyllys return (KMF_ERR_MEMORY);
32799ebb4caSwyllys }
3282225707cSValerie Bubb Fenwick /*
3292225707cSValerie Bubb Fenwick * Do not use RTLD_GROUP here, or this will cause a circular
3302225707cSValerie Bubb Fenwick * dependency when kmf_pkcs11.so.1 gets its PKCS#11 functions
3312225707cSValerie Bubb Fenwick * from libpkcs11.so.1 when kmf is used via libelfsign.so.1
3322225707cSValerie Bubb Fenwick * called from kcfd.
3332225707cSValerie Bubb Fenwick */
3342225707cSValerie Bubb Fenwick p->dldesc = dlopen(path, RTLD_LAZY | RTLD_PARENT);
33599ebb4caSwyllys if (p->dldesc == NULL) {
33699ebb4caSwyllys free(p->path);
33799ebb4caSwyllys free(p);
33899ebb4caSwyllys return (KMF_ERR_PLUGIN_INIT);
33999ebb4caSwyllys }
34099ebb4caSwyllys
34199ebb4caSwyllys sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
34299ebb4caSwyllys KMF_PLUGIN_INIT_SYMBOL);
34399ebb4caSwyllys if (sym == NULL) {
34499ebb4caSwyllys (void) dlclose(p->dldesc);
34599ebb4caSwyllys free(p->path);
34699ebb4caSwyllys free(p);
34799ebb4caSwyllys return (KMF_ERR_PLUGIN_INIT);
34899ebb4caSwyllys }
34999ebb4caSwyllys
35099ebb4caSwyllys /* Get the function list */
35199ebb4caSwyllys if ((p->funclist = (*sym)()) == NULL) {
35299ebb4caSwyllys (void) dlclose(p->dldesc);
35399ebb4caSwyllys free(p->path);
35499ebb4caSwyllys free(p);
35599ebb4caSwyllys return (KMF_ERR_PLUGIN_INIT);
35699ebb4caSwyllys }
35799ebb4caSwyllys
35899ebb4caSwyllys *plugin = p;
35999ebb4caSwyllys
36099ebb4caSwyllys return (KMF_OK);
36199ebb4caSwyllys }
36299ebb4caSwyllys
36399ebb4caSwyllys static KMF_RETURN
AddPlugin(KMF_HANDLE_T handle,KMF_PLUGIN * plugin)36499ebb4caSwyllys AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
36599ebb4caSwyllys {
36699ebb4caSwyllys KMF_PLUGIN_LIST *n;
36799ebb4caSwyllys
36899ebb4caSwyllys if (handle == NULL || plugin == NULL)
36999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
37099ebb4caSwyllys
37199ebb4caSwyllys /* If the head is NULL, create it */
37299ebb4caSwyllys if (handle->plugins == NULL) {
37399ebb4caSwyllys handle->plugins = (KMF_PLUGIN_LIST *)malloc(
37499ebb4caSwyllys sizeof (KMF_PLUGIN_LIST));
37599ebb4caSwyllys if (handle->plugins == NULL)
37699ebb4caSwyllys return (KMF_ERR_MEMORY);
37799ebb4caSwyllys handle->plugins->plugin = plugin;
37899ebb4caSwyllys handle->plugins->next = NULL;
37999ebb4caSwyllys } else {
38099ebb4caSwyllys /* walk the list to find the tail */
38199ebb4caSwyllys n = handle->plugins;
38299ebb4caSwyllys while (n->next != NULL)
38399ebb4caSwyllys n = n->next;
38499ebb4caSwyllys n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
38599ebb4caSwyllys if (n->next == NULL)
38699ebb4caSwyllys return (KMF_ERR_MEMORY);
38799ebb4caSwyllys
38899ebb4caSwyllys n->next->plugin = plugin;
38999ebb4caSwyllys n->next->next = NULL;
39099ebb4caSwyllys }
39199ebb4caSwyllys return (0);
39299ebb4caSwyllys }
39399ebb4caSwyllys
39499ebb4caSwyllys static void
DestroyPlugin(KMF_PLUGIN * plugin)39599ebb4caSwyllys DestroyPlugin(KMF_PLUGIN *plugin)
39699ebb4caSwyllys {
39799ebb4caSwyllys if (plugin) {
39899ebb4caSwyllys if (plugin->path)
39999ebb4caSwyllys free(plugin->path);
40099ebb4caSwyllys free(plugin);
40199ebb4caSwyllys }
40299ebb4caSwyllys }
40399ebb4caSwyllys
40499ebb4caSwyllys static void
Cleanup_KMF_Handle(KMF_HANDLE_T handle)40599ebb4caSwyllys Cleanup_KMF_Handle(KMF_HANDLE_T handle)
40699ebb4caSwyllys {
40799ebb4caSwyllys if (handle != NULL) {
40899ebb4caSwyllys while (handle->plugins != NULL) {
40999ebb4caSwyllys KMF_PLUGIN_LIST *next = handle->plugins->next;
41099ebb4caSwyllys
41199ebb4caSwyllys DestroyPlugin(handle->plugins->plugin);
41299ebb4caSwyllys free(handle->plugins);
41399ebb4caSwyllys handle->plugins = next;
41499ebb4caSwyllys }
41530a5e8faSwyllys kmf_free_policy_record(handle->policy);
41699ebb4caSwyllys free(handle->policy);
41799ebb4caSwyllys }
41899ebb4caSwyllys free(handle);
41999ebb4caSwyllys }
42099ebb4caSwyllys
42199ebb4caSwyllys void
Cleanup_PK11_Session(KMF_HANDLE_T handle)42299ebb4caSwyllys Cleanup_PK11_Session(KMF_HANDLE_T handle)
42399ebb4caSwyllys {
42499ebb4caSwyllys if (handle != NULL) {
42599ebb4caSwyllys /* Close active session on a pkcs11 token */
42699ebb4caSwyllys if (handle->pk11handle != NULL) {
42799ebb4caSwyllys (void) C_CloseSession(handle->pk11handle);
42899ebb4caSwyllys handle->pk11handle = NULL;
42999ebb4caSwyllys }
43099ebb4caSwyllys }
43199ebb4caSwyllys }
43299ebb4caSwyllys
43399ebb4caSwyllys KMF_RETURN
kmf_initialize(KMF_HANDLE_T * outhandle,char * policyfile,char * policyname)43430a5e8faSwyllys kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
43599ebb4caSwyllys {
43699ebb4caSwyllys KMF_RETURN ret = KMF_OK;
43799ebb4caSwyllys KMF_HANDLE *handle = NULL;
43899ebb4caSwyllys
43999ebb4caSwyllys if (outhandle == NULL)
44099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
44199ebb4caSwyllys
44299ebb4caSwyllys *outhandle = NULL;
44399ebb4caSwyllys handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
44499ebb4caSwyllys if (handle == NULL)
44599ebb4caSwyllys return (KMF_ERR_MEMORY);
44699ebb4caSwyllys
44799ebb4caSwyllys (void) memset(handle, 0, sizeof (KMF_HANDLE));
44899ebb4caSwyllys handle->plugins = NULL;
44999ebb4caSwyllys
450431deaa0Shylee /*
451431deaa0Shylee * When this function is called the first time, get the additional
452431deaa0Shylee * plugins from the config file.
453431deaa0Shylee */
454431deaa0Shylee (void) mutex_lock(&extra_plugin_lock);
455431deaa0Shylee if (!check_extra_plugin) {
456431deaa0Shylee
457431deaa0Shylee ret = get_entrylist(&extra_plugin_list);
458431deaa0Shylee check_extra_plugin = B_TRUE;
459431deaa0Shylee
460431deaa0Shylee /*
461431deaa0Shylee * Assign the kstype number to the additional plugins here.
462431deaa0Shylee * The global kstore_num will be protected by the mutex lock.
463431deaa0Shylee */
464431deaa0Shylee if (ret == KMF_OK) {
465431deaa0Shylee conf_entrylist_t *phead = extra_plugin_list;
466431deaa0Shylee while (phead != NULL) {
467431deaa0Shylee phead->entry->kstype = ++kstore_num;
468431deaa0Shylee phead = phead->next;
469431deaa0Shylee }
470431deaa0Shylee }
471431deaa0Shylee
472431deaa0Shylee /*
473431deaa0Shylee * If the KMF configuration file does not exist or cannot be
474431deaa0Shylee * parsed correctly, we will give a warning in syslog and
475431deaa0Shylee * continue on as there is no extra plugins in the system.
476431deaa0Shylee */
477431deaa0Shylee if (ret == KMF_ERR_KMF_CONF) {
478431deaa0Shylee cryptoerror(LOG_WARNING, "KMF was unable to parse "
479431deaa0Shylee "the private KMF config file.\n");
480431deaa0Shylee ret = KMF_OK;
481431deaa0Shylee }
482431deaa0Shylee
483431deaa0Shylee if (ret != KMF_OK) {
484431deaa0Shylee (void) mutex_unlock(&extra_plugin_lock);
485431deaa0Shylee goto errout;
486431deaa0Shylee }
487431deaa0Shylee }
488431deaa0Shylee (void) mutex_unlock(&extra_plugin_lock);
489431deaa0Shylee
49099ebb4caSwyllys /* Initialize the handle with the policy */
49130a5e8faSwyllys ret = kmf_set_policy((void *)handle,
49299ebb4caSwyllys policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
49399ebb4caSwyllys policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
49499ebb4caSwyllys if (ret != KMF_OK)
49599ebb4caSwyllys goto errout;
49699ebb4caSwyllys
497269e59f9SJan Pechanec /*
498269e59f9SJan Pechanec * Let's have the mapper status structure even if no cert-to-name
499269e59f9SJan Pechanec * mapping is initialized. It's better not to coredump in the
500269e59f9SJan Pechanec * kmf_get_mapper_lasterror function, for example, when there is no
501269e59f9SJan Pechanec * mapping initialized.
502269e59f9SJan Pechanec */
503269e59f9SJan Pechanec handle->mapstate = malloc(sizeof (KMF_MAPPER_STATE));
504269e59f9SJan Pechanec if (handle->mapstate == NULL) {
505269e59f9SJan Pechanec ret = KMF_ERR_MEMORY;
506269e59f9SJan Pechanec goto errout;
507269e59f9SJan Pechanec }
508269e59f9SJan Pechanec handle->mapstate->lastmappererr = KMF_OK;
509269e59f9SJan Pechanec handle->mapstate->options = NULL;
510269e59f9SJan Pechanec
511269e59f9SJan Pechanec /*
512269e59f9SJan Pechanec * Initialize the mapping scheme according to the policy. If no mapping
513269e59f9SJan Pechanec * is set in the policy database we silently ignore the error.
514269e59f9SJan Pechanec */
515269e59f9SJan Pechanec (void) kmf_cert_to_name_mapping_initialize(handle, 0, NULL);
516269e59f9SJan Pechanec
51799ebb4caSwyllys CLEAR_ERROR(handle, ret);
51899ebb4caSwyllys errout:
51999ebb4caSwyllys if (ret != KMF_OK) {
52099ebb4caSwyllys Cleanup_KMF_Handle(handle);
52199ebb4caSwyllys handle = NULL;
52299ebb4caSwyllys }
52399ebb4caSwyllys
52499ebb4caSwyllys *outhandle = (KMF_HANDLE_T)handle;
52599ebb4caSwyllys return (ret);
52699ebb4caSwyllys }
52799ebb4caSwyllys
52899ebb4caSwyllys KMF_RETURN
kmf_configure_keystore(KMF_HANDLE_T handle,int num_args,KMF_ATTRIBUTE * attrlist)52930a5e8faSwyllys kmf_configure_keystore(KMF_HANDLE_T handle,
53030a5e8faSwyllys int num_args,
53130a5e8faSwyllys KMF_ATTRIBUTE *attrlist)
53299ebb4caSwyllys {
53330a5e8faSwyllys KMF_RETURN ret = KMF_OK;
53499ebb4caSwyllys KMF_PLUGIN *plugin;
53530a5e8faSwyllys KMF_KEYSTORE_TYPE kstype;
53630a5e8faSwyllys uint32_t len;
53730a5e8faSwyllys
53830a5e8faSwyllys KMF_ATTRIBUTE_TESTER required_attrs[] = {
53930a5e8faSwyllys {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
54030a5e8faSwyllys };
54130a5e8faSwyllys
54230a5e8faSwyllys int num_req_attrs = sizeof (required_attrs) /
54330a5e8faSwyllys sizeof (KMF_ATTRIBUTE_TESTER);
54430a5e8faSwyllys
54530a5e8faSwyllys if (handle == NULL)
54630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
54799ebb4caSwyllys
54899ebb4caSwyllys CLEAR_ERROR(handle, ret);
54930a5e8faSwyllys
55030a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs,
55130a5e8faSwyllys 0, NULL, num_args, attrlist);
55230a5e8faSwyllys
55399ebb4caSwyllys if (ret != KMF_OK)
55499ebb4caSwyllys return (ret);
55599ebb4caSwyllys
55630a5e8faSwyllys len = sizeof (kstype);
55730a5e8faSwyllys ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
55830a5e8faSwyllys &kstype, &len);
55930a5e8faSwyllys if (ret != KMF_OK)
56030a5e8faSwyllys return (ret);
56199ebb4caSwyllys
56230a5e8faSwyllys plugin = FindPlugin(handle, kstype);
56330a5e8faSwyllys if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
56430a5e8faSwyllys return (plugin->funclist->ConfigureKeystore(handle, num_args,
56530a5e8faSwyllys attrlist));
56630a5e8faSwyllys } else {
56799ebb4caSwyllys /* return KMF_OK, if the plugin does not have an entry */
56899ebb4caSwyllys return (KMF_OK);
56999ebb4caSwyllys }
57030a5e8faSwyllys }
57199ebb4caSwyllys
57299ebb4caSwyllys KMF_RETURN
kmf_finalize(KMF_HANDLE_T handle)57330a5e8faSwyllys kmf_finalize(KMF_HANDLE_T handle)
57499ebb4caSwyllys {
57599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
57699ebb4caSwyllys
57799ebb4caSwyllys CLEAR_ERROR(handle, ret);
57899ebb4caSwyllys if (ret != KMF_OK)
57999ebb4caSwyllys return (ret);
58099ebb4caSwyllys
58199ebb4caSwyllys if (pkcs11_initialized) {
58299ebb4caSwyllys Cleanup_PK11_Session(handle);
58399ebb4caSwyllys }
58499ebb4caSwyllys Cleanup_KMF_Handle(handle);
58599ebb4caSwyllys
58699ebb4caSwyllys return (ret);
58799ebb4caSwyllys }
58899ebb4caSwyllys
58999ebb4caSwyllys KMF_RETURN
kmf_get_kmf_error_str(KMF_RETURN errcode,char ** errmsg)59030a5e8faSwyllys kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
59199ebb4caSwyllys {
59299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
59399ebb4caSwyllys int i, maxerr;
59499ebb4caSwyllys
59599ebb4caSwyllys if (errmsg == NULL)
59699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
59799ebb4caSwyllys
59899ebb4caSwyllys *errmsg = NULL;
59999ebb4caSwyllys maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
60099ebb4caSwyllys
60130a5e8faSwyllys for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
60230a5e8faSwyllys /* empty body */
60330a5e8faSwyllys ;
60499ebb4caSwyllys
60599ebb4caSwyllys if (i == maxerr)
60699ebb4caSwyllys return (KMF_ERR_MISSING_ERRCODE);
60799ebb4caSwyllys else {
60899ebb4caSwyllys *errmsg = strdup(kmf_errcodes[i].message);
60999ebb4caSwyllys if ((*errmsg) == NULL)
61099ebb4caSwyllys return (KMF_ERR_MEMORY);
61199ebb4caSwyllys }
61299ebb4caSwyllys return (ret);
61399ebb4caSwyllys }
61499ebb4caSwyllys
61599ebb4caSwyllys KMF_RETURN
kmf_get_plugin_error_str(KMF_HANDLE_T handle,char ** msgstr)61630a5e8faSwyllys kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
61799ebb4caSwyllys {
61899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
61999ebb4caSwyllys KMF_PLUGIN *plugin;
62099ebb4caSwyllys
62199ebb4caSwyllys if (handle == NULL || msgstr == NULL)
62299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
62399ebb4caSwyllys
62499ebb4caSwyllys *msgstr = NULL;
62599ebb4caSwyllys
62699ebb4caSwyllys if (handle->lasterr.errcode == 0) {
62799ebb4caSwyllys return (KMF_ERR_MISSING_ERRCODE);
62899ebb4caSwyllys }
62999ebb4caSwyllys
63099ebb4caSwyllys if (handle->lasterr.kstype == -1) { /* System error */
63199ebb4caSwyllys char *str = strerror(handle->lasterr.errcode);
63299ebb4caSwyllys if (str != NULL) {
63399ebb4caSwyllys *msgstr = strdup(str);
63499ebb4caSwyllys if ((*msgstr) == NULL)
63599ebb4caSwyllys return (KMF_ERR_MEMORY);
63699ebb4caSwyllys }
63799ebb4caSwyllys return (KMF_OK);
63899ebb4caSwyllys }
63999ebb4caSwyllys
64099ebb4caSwyllys plugin = FindPlugin(handle, handle->lasterr.kstype);
64199ebb4caSwyllys if (plugin == NULL)
64299ebb4caSwyllys return (KMF_ERR_PLUGIN_NOTFOUND);
64399ebb4caSwyllys
64499ebb4caSwyllys if (plugin->funclist->GetErrorString != NULL) {
64599ebb4caSwyllys ret = plugin->funclist->GetErrorString(handle, msgstr);
64699ebb4caSwyllys } else {
64799ebb4caSwyllys return (KMF_ERR_FUNCTION_NOT_FOUND);
64899ebb4caSwyllys }
64999ebb4caSwyllys
65099ebb4caSwyllys return (ret);
65199ebb4caSwyllys }
65299ebb4caSwyllys
65399ebb4caSwyllys
6549b37d296Swyllys #define SET_SYS_ERROR(h, c) if (h) {\
6559b37d296Swyllys h->lasterr.kstype = -1;\
6569b37d296Swyllys h->lasterr.errcode = c;\
6579b37d296Swyllys }
65899ebb4caSwyllys
65999ebb4caSwyllys KMF_RETURN
kmf_read_input_file(KMF_HANDLE_T handle,char * filename,KMF_DATA * pdata)66030a5e8faSwyllys kmf_read_input_file(KMF_HANDLE_T handle, char *filename, KMF_DATA *pdata)
66199ebb4caSwyllys {
66299ebb4caSwyllys struct stat s;
66399ebb4caSwyllys long nread, total = 0;
66499ebb4caSwyllys int fd;
66599ebb4caSwyllys unsigned char *buf = NULL;
66699ebb4caSwyllys KMF_RETURN ret;
66799ebb4caSwyllys
6689b37d296Swyllys if (handle) {
66999ebb4caSwyllys CLEAR_ERROR(handle, ret);
67099ebb4caSwyllys if (ret != KMF_OK)
67199ebb4caSwyllys return (ret);
6729b37d296Swyllys }
67399ebb4caSwyllys
67499ebb4caSwyllys if (filename == NULL || pdata == NULL) {
67599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
67699ebb4caSwyllys }
67799ebb4caSwyllys
67899ebb4caSwyllys if ((fd = open(filename, O_RDONLY)) < 0) {
67999ebb4caSwyllys SET_SYS_ERROR(handle, errno);
68099ebb4caSwyllys return (KMF_ERR_OPEN_FILE);
68199ebb4caSwyllys }
68299ebb4caSwyllys
68399ebb4caSwyllys if (fstat(fd, &s) < 0) {
68499ebb4caSwyllys SET_SYS_ERROR(handle, errno);
68599ebb4caSwyllys (void) close(fd);
68699ebb4caSwyllys return (KMF_ERR_OPEN_FILE);
68799ebb4caSwyllys }
68899ebb4caSwyllys
68999ebb4caSwyllys if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
69099ebb4caSwyllys (void) close(fd);
69199ebb4caSwyllys return (KMF_ERR_MEMORY);
69299ebb4caSwyllys }
69399ebb4caSwyllys
69499ebb4caSwyllys do {
69599ebb4caSwyllys nread = read(fd, buf+total, s.st_size-total);
69699ebb4caSwyllys if (nread < 0) {
69799ebb4caSwyllys SET_SYS_ERROR(handle, errno);
69899ebb4caSwyllys (void) close(fd);
69999ebb4caSwyllys free(buf);
70099ebb4caSwyllys return (KMF_ERR_INTERNAL);
70199ebb4caSwyllys }
70299ebb4caSwyllys total += nread;
70399ebb4caSwyllys } while (total < s.st_size);
70499ebb4caSwyllys
70599ebb4caSwyllys pdata->Data = buf;
70699ebb4caSwyllys pdata->Length = s.st_size;
70799ebb4caSwyllys (void) close(fd);
70899ebb4caSwyllys return (KMF_OK);
70999ebb4caSwyllys }
71099ebb4caSwyllys
71199ebb4caSwyllys /*
71299ebb4caSwyllys *
71330a5e8faSwyllys * Name: kmf_der_to_pem
71499ebb4caSwyllys *
71599ebb4caSwyllys * Description:
71699ebb4caSwyllys * Function for converting DER encoded format to PEM encoded format
71799ebb4caSwyllys *
71899ebb4caSwyllys * Parameters:
71999ebb4caSwyllys * type(input) - CERTIFICATE or CSR
72099ebb4caSwyllys * data(input) - pointer to the DER encoded data
72199ebb4caSwyllys * len(input) - length of input data
72299ebb4caSwyllys * out(output) - contains the output buffer address to be returned
72399ebb4caSwyllys * outlen(output) - pointer to the returned output length
72499ebb4caSwyllys *
72599ebb4caSwyllys * Returns:
72699ebb4caSwyllys * A KMF_RETURN value indicating success or specifying a particular
72799ebb4caSwyllys * error condition.
72899ebb4caSwyllys * The value KMF_OK indicates success. All other values represent
72999ebb4caSwyllys * an error condition.
73099ebb4caSwyllys *
73199ebb4caSwyllys */
73299ebb4caSwyllys KMF_RETURN
kmf_der_to_pem(KMF_OBJECT_TYPE type,unsigned char * data,int len,unsigned char ** out,int * outlen)73330a5e8faSwyllys kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
73499ebb4caSwyllys int len, unsigned char **out, int *outlen)
73599ebb4caSwyllys {
73699ebb4caSwyllys
73799ebb4caSwyllys KMF_RETURN err;
73899ebb4caSwyllys if (data == NULL || out == NULL || outlen == NULL)
73999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
74099ebb4caSwyllys
74199ebb4caSwyllys err = Der2Pem(type, data, len, out, outlen);
74299ebb4caSwyllys return (err);
74399ebb4caSwyllys
74499ebb4caSwyllys }
74599ebb4caSwyllys
74699ebb4caSwyllys /*
74799ebb4caSwyllys *
74830a5e8faSwyllys * Name: kmf_pem_to_der
74999ebb4caSwyllys *
75099ebb4caSwyllys * Description:
75199ebb4caSwyllys * Function for converting PEM encoded format to DER encoded format
75299ebb4caSwyllys *
75399ebb4caSwyllys * Parameters:
75499ebb4caSwyllys * in(input) - pointer to the PEM encoded data
75599ebb4caSwyllys * inlen(input) - length of input data
75699ebb4caSwyllys * out(output) - contains the output buffer address to be returned
75799ebb4caSwyllys * outlen(output) - pointer to the returned output length
75899ebb4caSwyllys *
75999ebb4caSwyllys * Returns:
76099ebb4caSwyllys * A KMF_RETURN value indicating success or specifying a particular
76199ebb4caSwyllys * error condition.
76299ebb4caSwyllys * The value KMF_OK indicates success. All other values represent
76399ebb4caSwyllys * an error condition.
76499ebb4caSwyllys *
76599ebb4caSwyllys */
76699ebb4caSwyllys KMF_RETURN
kmf_pem_to_der(unsigned char * in,int inlen,unsigned char ** out,int * outlen)76730a5e8faSwyllys kmf_pem_to_der(unsigned char *in, int inlen,
76899ebb4caSwyllys unsigned char **out, int *outlen)
76999ebb4caSwyllys {
77099ebb4caSwyllys KMF_RETURN err;
77199ebb4caSwyllys if (in == NULL || out == NULL || outlen == NULL)
77299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
77399ebb4caSwyllys
77499ebb4caSwyllys err = Pem2Der(in, inlen, out, outlen);
77599ebb4caSwyllys return (err);
77699ebb4caSwyllys }
77799ebb4caSwyllys
77899ebb4caSwyllys char *
kmf_oid_to_string(KMF_OID * oid)77930a5e8faSwyllys kmf_oid_to_string(KMF_OID *oid)
78099ebb4caSwyllys {
78199ebb4caSwyllys char numstr[128];
78299ebb4caSwyllys uint32_t number;
78399ebb4caSwyllys int numshift;
78499ebb4caSwyllys uint32_t i, string_length;
78599ebb4caSwyllys uchar_t *cp;
78699ebb4caSwyllys char *bp;
78799ebb4caSwyllys
78899ebb4caSwyllys /* First determine the size of the string */
78999ebb4caSwyllys string_length = 0;
79099ebb4caSwyllys number = 0;
79199ebb4caSwyllys numshift = 0;
79299ebb4caSwyllys cp = (unsigned char *)oid->Data;
79399ebb4caSwyllys
79499ebb4caSwyllys number = (uint32_t)cp[0];
79599ebb4caSwyllys (void) sprintf(numstr, "%d ", number/40);
79699ebb4caSwyllys
79799ebb4caSwyllys string_length += strlen(numstr);
79899ebb4caSwyllys (void) sprintf(numstr, "%d ", number%40);
79999ebb4caSwyllys
80099ebb4caSwyllys string_length += strlen(numstr);
80199ebb4caSwyllys
80299ebb4caSwyllys for (i = 1; i < oid->Length; i++) {
80399ebb4caSwyllys if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
80499ebb4caSwyllys number = (number << 7) | (cp[i] & 0x7f);
80599ebb4caSwyllys numshift += 7;
80699ebb4caSwyllys } else {
80799ebb4caSwyllys return (NULL);
80899ebb4caSwyllys }
80999ebb4caSwyllys
81099ebb4caSwyllys if ((cp[i] & 0x80) == 0) {
81199ebb4caSwyllys (void) sprintf(numstr, "%d ", number);
81299ebb4caSwyllys string_length += strlen(numstr);
81399ebb4caSwyllys number = 0;
81499ebb4caSwyllys numshift = 0;
81599ebb4caSwyllys }
81699ebb4caSwyllys }
81799ebb4caSwyllys /*
81899ebb4caSwyllys * If we get here, we've calculated the length of "n n n ... n ". Add 4
81999ebb4caSwyllys * here for "{ " and "}\0".
82099ebb4caSwyllys */
82199ebb4caSwyllys string_length += 4;
82299ebb4caSwyllys if ((bp = (char *)malloc(string_length))) {
82399ebb4caSwyllys number = (uint32_t)cp[0];
82499ebb4caSwyllys
82599ebb4caSwyllys (void) sprintf(numstr, "%d.", number/40);
82699ebb4caSwyllys (void) strcpy(bp, numstr);
82799ebb4caSwyllys
82899ebb4caSwyllys (void) sprintf(numstr, "%d.", number%40);
82999ebb4caSwyllys (void) strcat(bp, numstr);
83099ebb4caSwyllys
83199ebb4caSwyllys number = 0;
83299ebb4caSwyllys cp = (unsigned char *) oid->Data;
83399ebb4caSwyllys for (i = 1; i < oid->Length; i++) {
83499ebb4caSwyllys number = (number << 7) | (cp[i] & 0x7f);
83599ebb4caSwyllys if ((cp[i] & 0x80) == 0) {
83699ebb4caSwyllys (void) sprintf(numstr, "%d", number);
83799ebb4caSwyllys (void) strcat(bp, numstr);
83899ebb4caSwyllys number = 0;
83999ebb4caSwyllys if (i+1 < oid->Length)
84099ebb4caSwyllys (void) strcat(bp, ".");
84199ebb4caSwyllys }
84299ebb4caSwyllys }
84399ebb4caSwyllys }
84499ebb4caSwyllys return (bp);
84599ebb4caSwyllys }
84699ebb4caSwyllys
84702744e81Swyllys static boolean_t
check_for_pem(uchar_t * buf,KMF_ENCODE_FORMAT * fmt)84808ec4bd3Shylee check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
84902744e81Swyllys {
85002744e81Swyllys char *p;
851d00756ccSwyllys int i;
85202744e81Swyllys
85308ec4bd3Shylee if (buf == NULL)
8549b37d296Swyllys return (FALSE);
8559b37d296Swyllys
856d00756ccSwyllys for (i = 0; i < 8 && isascii(buf[i]); i++)
857d00756ccSwyllys /* loop to make sure this is ascii */;
858d00756ccSwyllys if (i != 8)
859d00756ccSwyllys return (FALSE);
860d00756ccSwyllys
86108ec4bd3Shylee if (memcmp(buf, "Bag Attr", 8) == 0) {
86208ec4bd3Shylee *fmt = KMF_FORMAT_PEM_KEYPAIR;
86308ec4bd3Shylee return (TRUE);
86408ec4bd3Shylee }
86508ec4bd3Shylee
8669b37d296Swyllys /* Look for "-----BEGIN" right after a newline */
86708ec4bd3Shylee p = strtok((char *)buf, "\n");
86802744e81Swyllys while (p != NULL) {
86902744e81Swyllys if (strstr(p, "-----BEGIN") != NULL) {
87008ec4bd3Shylee *fmt = KMF_FORMAT_PEM;
871d00756ccSwyllys /* Restore the buffer */
872d00756ccSwyllys buf[strlen(p)] = '\n';
87302744e81Swyllys return (TRUE);
87402744e81Swyllys }
875d00756ccSwyllys buf[strlen(p)] = '\n';
87602744e81Swyllys p = strtok(NULL, "\n");
87702744e81Swyllys }
87802744e81Swyllys return (FALSE);
87902744e81Swyllys }
88002744e81Swyllys
88108ec4bd3Shylee
88208ec4bd3Shylee static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
88308ec4bd3Shylee static unsigned char pkcs12_oid[11] =
88408ec4bd3Shylee {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
88508ec4bd3Shylee
88608ec4bd3Shylee /*
88708ec4bd3Shylee * This function takes a BER encoded string as input and checks the version
88808ec4bd3Shylee * and the oid in the the top-level ASN.1 structure to see if it complies to
88908ec4bd3Shylee * the PKCS#12 Syntax.
89008ec4bd3Shylee */
89108ec4bd3Shylee static boolean_t
check_for_pkcs12(uchar_t * buf,int buf_len)89208ec4bd3Shylee check_for_pkcs12(uchar_t *buf, int buf_len)
89308ec4bd3Shylee {
89408ec4bd3Shylee int index = 0;
89508ec4bd3Shylee int length_octets;
89608ec4bd3Shylee
89708ec4bd3Shylee if (buf == NULL || buf_len <= 0)
89808ec4bd3Shylee return (FALSE);
89908ec4bd3Shylee
90008ec4bd3Shylee /*
90108ec4bd3Shylee * The top level structure for a PKCS12 string:
90208ec4bd3Shylee *
90308ec4bd3Shylee * PFX ::= SEQUENCE {
90408ec4bd3Shylee * version INTEGER {v3(3)}(v3,...)
90508ec4bd3Shylee * authSafe ContentInfo
90608ec4bd3Shylee * macData MacData OPTIONAL
90708ec4bd3Shylee * }
90808ec4bd3Shylee *
90908ec4bd3Shylee * ContentInfo
91008ec4bd3Shylee * FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
91108ec4bd3Shylee * pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
91208ec4bd3Shylee *
91308ec4bd3Shylee * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
91408ec4bd3Shylee * sequences up to the oid part is as following:
91508ec4bd3Shylee *
91608ec4bd3Shylee * SEQUENCE {
91708ec4bd3Shylee * INTEGER 3
91808ec4bd3Shylee * SEQUENCE {
91908ec4bd3Shylee * OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
92008ec4bd3Shylee */
92108ec4bd3Shylee
92208ec4bd3Shylee /*
92308ec4bd3Shylee * Check the first sequence and calculate the number of bytes used
92408ec4bd3Shylee * to store the length.
92508ec4bd3Shylee */
92608ec4bd3Shylee if (buf[index++] != 0x30)
92708ec4bd3Shylee return (FALSE);
92808ec4bd3Shylee
92908ec4bd3Shylee if (buf[index] & 0x80) {
93008ec4bd3Shylee length_octets = buf[index++] & 0x0F; /* long form */
93108ec4bd3Shylee } else {
93208ec4bd3Shylee length_octets = 1; /* short form */
93308ec4bd3Shylee }
93408ec4bd3Shylee
93508ec4bd3Shylee index += length_octets;
93608ec4bd3Shylee if (index >= buf_len)
93708ec4bd3Shylee return (FALSE);
93808ec4bd3Shylee
93908ec4bd3Shylee /* Skip the length octets and check the pkcs12 version */
94008ec4bd3Shylee if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
94108ec4bd3Shylee return (FALSE);
94208ec4bd3Shylee
94308ec4bd3Shylee index += sizeof (pkcs12_version);
94408ec4bd3Shylee if (index >= buf_len)
94508ec4bd3Shylee return (FALSE);
94608ec4bd3Shylee
94708ec4bd3Shylee /*
94808ec4bd3Shylee * Check the 2nd sequence and calculate the number of bytes used
94908ec4bd3Shylee * to store the length.
95008ec4bd3Shylee */
95108ec4bd3Shylee if ((buf[index++] & 0xFF) != 0x30)
95208ec4bd3Shylee return (FALSE);
95308ec4bd3Shylee
95408ec4bd3Shylee if (buf[index] & 0x80) {
95508ec4bd3Shylee length_octets = buf[index++] & 0x0F;
95608ec4bd3Shylee } else {
95708ec4bd3Shylee length_octets = 1;
95808ec4bd3Shylee }
95908ec4bd3Shylee
96008ec4bd3Shylee index += length_octets;
96108ec4bd3Shylee if (index + sizeof (pkcs12_oid) >= buf_len)
96208ec4bd3Shylee return (FALSE);
96308ec4bd3Shylee
96408ec4bd3Shylee /* Skip the length octets and check the oid */
96508ec4bd3Shylee if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
96608ec4bd3Shylee return (FALSE);
96708ec4bd3Shylee else
96808ec4bd3Shylee return (TRUE);
96908ec4bd3Shylee }
97008ec4bd3Shylee
97199ebb4caSwyllys KMF_RETURN
kmf_get_data_format(KMF_DATA * data,KMF_ENCODE_FORMAT * fmt)972d00756ccSwyllys kmf_get_data_format(KMF_DATA *data, KMF_ENCODE_FORMAT *fmt)
973d00756ccSwyllys {
974d00756ccSwyllys uchar_t *buf = data->Data;
975d00756ccSwyllys
976d00756ccSwyllys if (check_for_pkcs12(buf, data->Length) == TRUE) {
977d00756ccSwyllys *fmt = KMF_FORMAT_PKCS12;
978d00756ccSwyllys } else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
979d00756ccSwyllys /* It is most likely a generic ASN.1 encoded file */
980d00756ccSwyllys *fmt = KMF_FORMAT_ASN1;
981d00756ccSwyllys } else if (check_for_pem(buf, fmt) != TRUE) {
982d00756ccSwyllys /* Cannot determine this file format */
983d00756ccSwyllys *fmt = KMF_FORMAT_UNDEF;
984d00756ccSwyllys return (KMF_ERR_ENCODING);
985d00756ccSwyllys }
986d00756ccSwyllys return (KMF_OK);
987d00756ccSwyllys }
988d00756ccSwyllys
989d00756ccSwyllys KMF_RETURN
kmf_get_file_format(char * filename,KMF_ENCODE_FORMAT * fmt)99030a5e8faSwyllys kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
99199ebb4caSwyllys {
99299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
993*6b35cb3cSRichard PALO KMF_DATA filebuf = { 0, NULL };
99499ebb4caSwyllys
99599ebb4caSwyllys if (filename == NULL || !strlen(filename) || fmt == NULL)
99699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
99799ebb4caSwyllys
99899ebb4caSwyllys *fmt = 0;
99930a5e8faSwyllys ret = kmf_read_input_file(NULL, filename, &filebuf);
100008ec4bd3Shylee if (ret != KMF_OK)
100108ec4bd3Shylee return (ret);
100299ebb4caSwyllys
100308ec4bd3Shylee if (filebuf.Length < 8) {
100408ec4bd3Shylee ret = KMF_ERR_ENCODING; /* too small */
100599ebb4caSwyllys goto end;
100699ebb4caSwyllys }
100799ebb4caSwyllys
1008d00756ccSwyllys ret = kmf_get_data_format(&filebuf, fmt);
100999ebb4caSwyllys end:
101030a5e8faSwyllys kmf_free_data(&filebuf);
101199ebb4caSwyllys return (ret);
101299ebb4caSwyllys }
101399ebb4caSwyllys
101499ebb4caSwyllys KMF_RETURN
kmf_hexstr_to_bytes(unsigned char * hexstr,unsigned char ** bytes,size_t * outlen)101530a5e8faSwyllys kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
101699ebb4caSwyllys size_t *outlen)
101799ebb4caSwyllys {
101899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
101999ebb4caSwyllys unsigned char *buf = NULL;
102099ebb4caSwyllys int len, stringlen;
102199ebb4caSwyllys int i;
102299ebb4caSwyllys unsigned char ch;
102399ebb4caSwyllys
102499ebb4caSwyllys if (hexstr == NULL) {
102599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
102699ebb4caSwyllys }
102799ebb4caSwyllys
102830a5e8faSwyllys if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
102999ebb4caSwyllys hexstr += 2;
103099ebb4caSwyllys
103130a5e8faSwyllys for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
103230a5e8faSwyllys /* empty body */
103330a5e8faSwyllys ;
103499ebb4caSwyllys /*
103599ebb4caSwyllys * If all the characters are not legitimate hex chars,
103699ebb4caSwyllys * return an error.
103799ebb4caSwyllys */
103899ebb4caSwyllys if (i != strlen((char *)hexstr))
103999ebb4caSwyllys return (KMF_ERR_BAD_HEX_STRING);
104099ebb4caSwyllys stringlen = i;
104199ebb4caSwyllys len = (i / 2) + (i % 2);
104299ebb4caSwyllys
104399ebb4caSwyllys buf = malloc(len);
104499ebb4caSwyllys if (buf == NULL) {
104599ebb4caSwyllys return (KMF_ERR_MEMORY);
104699ebb4caSwyllys }
104799ebb4caSwyllys (void) memset(buf, 0, len);
104899ebb4caSwyllys
104999ebb4caSwyllys for (i = 0; i < stringlen; i++) {
105099ebb4caSwyllys ch = (unsigned char) *hexstr;
105199ebb4caSwyllys hexstr++;
105299ebb4caSwyllys if ((ch >= '0') && (ch <= '9'))
105399ebb4caSwyllys ch -= '0';
105499ebb4caSwyllys else if ((ch >= 'A') && (ch <= 'F'))
105599ebb4caSwyllys ch = ch - 'A' + 10;
105699ebb4caSwyllys else if ((ch >= 'a') && (ch <= 'f'))
105799ebb4caSwyllys ch = ch - 'a' + 10;
105899ebb4caSwyllys else {
105999ebb4caSwyllys ret = KMF_ERR_BAD_HEX_STRING;
106099ebb4caSwyllys goto out;
106199ebb4caSwyllys }
106299ebb4caSwyllys
106399ebb4caSwyllys if (i & 1) {
106499ebb4caSwyllys buf[i/2] |= ch;
106599ebb4caSwyllys } else {
106699ebb4caSwyllys buf[i/2] = (ch << 4);
106799ebb4caSwyllys }
106899ebb4caSwyllys }
106999ebb4caSwyllys
107099ebb4caSwyllys *bytes = buf;
107199ebb4caSwyllys *outlen = len;
107299ebb4caSwyllys out:
107399ebb4caSwyllys if (buf != NULL && ret != KMF_OK) {
107499ebb4caSwyllys free(buf);
107599ebb4caSwyllys }
107699ebb4caSwyllys return (ret);
107799ebb4caSwyllys }
107899ebb4caSwyllys
107999ebb4caSwyllys void
kmf_free_dn(KMF_X509_NAME * name)108030a5e8faSwyllys kmf_free_dn(KMF_X509_NAME *name)
108199ebb4caSwyllys {
108299ebb4caSwyllys KMF_X509_RDN *newrdn = NULL;
108399ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *av = NULL;
108499ebb4caSwyllys int i, j;
108599ebb4caSwyllys
108699ebb4caSwyllys if (name && name->numberOfRDNs) {
108799ebb4caSwyllys for (i = 0; i < name->numberOfRDNs; i++) {
108899ebb4caSwyllys newrdn = &name->RelativeDistinguishedName[i];
108999ebb4caSwyllys for (j = 0; j < newrdn->numberOfPairs; j++) {
109099ebb4caSwyllys av = &newrdn->AttributeTypeAndValue[j];
109130a5e8faSwyllys kmf_free_data(&av->type);
109230a5e8faSwyllys kmf_free_data(&av->value);
109399ebb4caSwyllys }
109499ebb4caSwyllys free(newrdn->AttributeTypeAndValue);
109599ebb4caSwyllys newrdn->numberOfPairs = 0;
109699ebb4caSwyllys newrdn->AttributeTypeAndValue = NULL;
109799ebb4caSwyllys }
109899ebb4caSwyllys free(name->RelativeDistinguishedName);
109999ebb4caSwyllys name->numberOfRDNs = 0;
110099ebb4caSwyllys name->RelativeDistinguishedName = NULL;
110199ebb4caSwyllys }
110299ebb4caSwyllys }
110399ebb4caSwyllys
110499ebb4caSwyllys void
kmf_free_kmf_cert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)110530a5e8faSwyllys kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
110699ebb4caSwyllys {
110799ebb4caSwyllys KMF_PLUGIN *plugin;
110899ebb4caSwyllys KMF_RETURN ret;
110999ebb4caSwyllys
111099ebb4caSwyllys CLEAR_ERROR(handle, ret);
111199ebb4caSwyllys if (ret != KMF_OK)
111299ebb4caSwyllys return;
111399ebb4caSwyllys
111499ebb4caSwyllys if (kmf_cert == NULL)
111599ebb4caSwyllys return;
111699ebb4caSwyllys
111799ebb4caSwyllys plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
111899ebb4caSwyllys
111999ebb4caSwyllys if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
112099ebb4caSwyllys plugin->funclist->FreeKMFCert(handle, kmf_cert);
112199ebb4caSwyllys }
112299ebb4caSwyllys }
112399ebb4caSwyllys
112499ebb4caSwyllys void
kmf_free_data(KMF_DATA * datablock)112530a5e8faSwyllys kmf_free_data(KMF_DATA *datablock)
112699ebb4caSwyllys {
112799ebb4caSwyllys if (datablock != NULL && datablock->Data != NULL) {
112899ebb4caSwyllys free(datablock->Data);
112999ebb4caSwyllys datablock->Data = NULL;
113099ebb4caSwyllys datablock->Length = 0;
113199ebb4caSwyllys }
113299ebb4caSwyllys }
113399ebb4caSwyllys
113499ebb4caSwyllys void
kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER * algoid)113530a5e8faSwyllys kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
113699ebb4caSwyllys {
113799ebb4caSwyllys if (algoid == NULL)
113899ebb4caSwyllys return;
113930a5e8faSwyllys kmf_free_data(&algoid->algorithm);
114030a5e8faSwyllys kmf_free_data(&algoid->parameters);
114199ebb4caSwyllys }
114299ebb4caSwyllys
114399ebb4caSwyllys void
kmf_free_extn(KMF_X509_EXTENSION * exptr)114430a5e8faSwyllys kmf_free_extn(KMF_X509_EXTENSION *exptr)
114599ebb4caSwyllys {
114699ebb4caSwyllys if (exptr == NULL)
114799ebb4caSwyllys return;
114899ebb4caSwyllys
114930a5e8faSwyllys kmf_free_data((KMF_DATA *)&exptr->extnId);
115030a5e8faSwyllys kmf_free_data(&exptr->BERvalue);
115199ebb4caSwyllys
115299ebb4caSwyllys if (exptr->value.tagAndValue) {
115330a5e8faSwyllys kmf_free_data(&exptr->value.tagAndValue->value);
115499ebb4caSwyllys free(exptr->value.tagAndValue);
115599ebb4caSwyllys }
115699ebb4caSwyllys }
115799ebb4caSwyllys
115899ebb4caSwyllys void
kmf_free_tbs_csr(KMF_TBS_CSR * tbscsr)115930a5e8faSwyllys kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
116099ebb4caSwyllys {
116199ebb4caSwyllys if (tbscsr) {
116230a5e8faSwyllys kmf_free_data(&tbscsr->version);
116399ebb4caSwyllys
116430a5e8faSwyllys kmf_free_dn(&tbscsr->subject);
116599ebb4caSwyllys
116630a5e8faSwyllys kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
116730a5e8faSwyllys kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
116899ebb4caSwyllys
116999ebb4caSwyllys free_extensions(&tbscsr->extensions);
117099ebb4caSwyllys }
117199ebb4caSwyllys }
117299ebb4caSwyllys
117399ebb4caSwyllys void
kmf_free_signed_csr(KMF_CSR_DATA * csr)117430a5e8faSwyllys kmf_free_signed_csr(KMF_CSR_DATA *csr)
117599ebb4caSwyllys {
117699ebb4caSwyllys if (csr) {
117730a5e8faSwyllys kmf_free_tbs_csr(&csr->csr);
117899ebb4caSwyllys
117930a5e8faSwyllys kmf_free_algoid(&csr->signature.algorithmIdentifier);
118030a5e8faSwyllys kmf_free_data(&csr->signature.encrypted);
118199ebb4caSwyllys }
118299ebb4caSwyllys }
118399ebb4caSwyllys
118499ebb4caSwyllys static void
free_validity(KMF_X509_VALIDITY * validity)118599ebb4caSwyllys free_validity(KMF_X509_VALIDITY *validity)
118699ebb4caSwyllys {
118799ebb4caSwyllys if (validity == NULL)
118899ebb4caSwyllys return;
118930a5e8faSwyllys kmf_free_data(&validity->notBefore.time);
119030a5e8faSwyllys kmf_free_data(&validity->notAfter.time);
119199ebb4caSwyllys }
119299ebb4caSwyllys
119399ebb4caSwyllys static void
free_extensions(KMF_X509_EXTENSIONS * extns)119499ebb4caSwyllys free_extensions(KMF_X509_EXTENSIONS *extns)
119599ebb4caSwyllys {
119699ebb4caSwyllys int i;
119799ebb4caSwyllys KMF_X509_EXTENSION *exptr;
119899ebb4caSwyllys
119999ebb4caSwyllys if (extns && extns->numberOfExtensions > 0) {
120099ebb4caSwyllys for (i = 0; i < extns->numberOfExtensions; i++) {
120199ebb4caSwyllys exptr = &extns->extensions[i];
120230a5e8faSwyllys kmf_free_extn(exptr);
120399ebb4caSwyllys }
120499ebb4caSwyllys free(extns->extensions);
120599ebb4caSwyllys extns->numberOfExtensions = 0;
120699ebb4caSwyllys extns->extensions = NULL;
120799ebb4caSwyllys }
120899ebb4caSwyllys }
120999ebb4caSwyllys
121099ebb4caSwyllys void
kmf_free_tbs_cert(KMF_X509_TBS_CERT * tbscert)121130a5e8faSwyllys kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
121299ebb4caSwyllys {
121399ebb4caSwyllys if (tbscert) {
121430a5e8faSwyllys kmf_free_data(&tbscert->version);
121530a5e8faSwyllys kmf_free_bigint(&tbscert->serialNumber);
121630a5e8faSwyllys kmf_free_algoid(&tbscert->signature);
121799ebb4caSwyllys
121830a5e8faSwyllys kmf_free_dn(&tbscert->issuer);
121930a5e8faSwyllys kmf_free_dn(&tbscert->subject);
122099ebb4caSwyllys
122199ebb4caSwyllys free_validity(&tbscert->validity);
122299ebb4caSwyllys
122330a5e8faSwyllys kmf_free_data(&tbscert->issuerUniqueIdentifier);
122430a5e8faSwyllys kmf_free_data(&tbscert->subjectUniqueIdentifier);
122599ebb4caSwyllys
122630a5e8faSwyllys kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
122730a5e8faSwyllys kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
122899ebb4caSwyllys
122999ebb4caSwyllys free_extensions(&tbscert->extensions);
123099ebb4caSwyllys
123130a5e8faSwyllys kmf_free_data(&tbscert->issuerUniqueIdentifier);
123230a5e8faSwyllys kmf_free_data(&tbscert->subjectUniqueIdentifier);
123399ebb4caSwyllys }
123499ebb4caSwyllys }
123599ebb4caSwyllys
123699ebb4caSwyllys void
kmf_free_signed_cert(KMF_X509_CERTIFICATE * certptr)123730a5e8faSwyllys kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
123899ebb4caSwyllys {
123999ebb4caSwyllys if (!certptr)
124099ebb4caSwyllys return;
124199ebb4caSwyllys
124230a5e8faSwyllys kmf_free_tbs_cert(&certptr->certificate);
124399ebb4caSwyllys
124430a5e8faSwyllys kmf_free_algoid(&certptr->signature.algorithmIdentifier);
124530a5e8faSwyllys kmf_free_data(&certptr->signature.encrypted);
124699ebb4caSwyllys }
124799ebb4caSwyllys
124899ebb4caSwyllys void
kmf_free_str(char * pstr)124930a5e8faSwyllys kmf_free_str(char *pstr)
125099ebb4caSwyllys {
125199ebb4caSwyllys if (pstr != NULL)
125299ebb4caSwyllys free(pstr);
125399ebb4caSwyllys }
125499ebb4caSwyllys
125599ebb4caSwyllys void
free_keyidlist(KMF_OID * oidlist,int len)125699ebb4caSwyllys free_keyidlist(KMF_OID *oidlist, int len)
125799ebb4caSwyllys {
125899ebb4caSwyllys int i;
125999ebb4caSwyllys for (i = 0; i < len; i++) {
126030a5e8faSwyllys kmf_free_data((KMF_DATA *)&oidlist[i]);
126199ebb4caSwyllys }
126299ebb4caSwyllys free(oidlist);
126399ebb4caSwyllys }
126499ebb4caSwyllys
126599ebb4caSwyllys void
kmf_free_eku(KMF_X509EXT_EKU * eptr)126630a5e8faSwyllys kmf_free_eku(KMF_X509EXT_EKU *eptr)
126799ebb4caSwyllys {
126830a5e8faSwyllys if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
126999ebb4caSwyllys free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
127099ebb4caSwyllys }
127199ebb4caSwyllys
127299ebb4caSwyllys void
kmf_free_spki(KMF_X509_SPKI * spki)127330a5e8faSwyllys kmf_free_spki(KMF_X509_SPKI *spki)
127499ebb4caSwyllys {
127599ebb4caSwyllys if (spki != NULL) {
127630a5e8faSwyllys kmf_free_algoid(&spki->algorithm);
127730a5e8faSwyllys kmf_free_data(&spki->subjectPublicKey);
127899ebb4caSwyllys }
127999ebb4caSwyllys }
128099ebb4caSwyllys
128199ebb4caSwyllys void
kmf_free_kmf_key(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key)128230a5e8faSwyllys kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
128399ebb4caSwyllys {
128499ebb4caSwyllys KMF_PLUGIN *plugin;
128599ebb4caSwyllys KMF_RETURN ret;
128630a5e8faSwyllys KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
128730a5e8faSwyllys int i = 0;
128830a5e8faSwyllys boolean_t token_destroy = B_FALSE;
128930a5e8faSwyllys
129030a5e8faSwyllys if (key == NULL)
129130a5e8faSwyllys return;
129299ebb4caSwyllys
129399ebb4caSwyllys CLEAR_ERROR(handle, ret);
129499ebb4caSwyllys if (ret != KMF_OK)
129599ebb4caSwyllys return;
129699ebb4caSwyllys
129730a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
129830a5e8faSwyllys KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
129930a5e8faSwyllys i++;
130030a5e8faSwyllys
130130a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
130230a5e8faSwyllys KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
130330a5e8faSwyllys i++;
130499ebb4caSwyllys
130599ebb4caSwyllys plugin = FindPlugin(handle, key->kstype);
130699ebb4caSwyllys if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
130730a5e8faSwyllys (void) plugin->funclist->DeleteKey(handle, i, attlist);
130899ebb4caSwyllys }
130999ebb4caSwyllys
131099ebb4caSwyllys if (key->keylabel)
131199ebb4caSwyllys free(key->keylabel);
131299ebb4caSwyllys
131399ebb4caSwyllys if (key->israw) {
131430a5e8faSwyllys kmf_free_raw_key(key->keyp);
131599ebb4caSwyllys free(key->keyp);
131699ebb4caSwyllys }
131799ebb4caSwyllys
131899ebb4caSwyllys (void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
131999ebb4caSwyllys }
132099ebb4caSwyllys
132199ebb4caSwyllys void
kmf_free_bigint(KMF_BIGINT * big)132230a5e8faSwyllys kmf_free_bigint(KMF_BIGINT *big)
132399ebb4caSwyllys {
132499ebb4caSwyllys if (big != NULL && big->val != NULL) {
132502744e81Swyllys /* Clear it out before returning it to the pool */
132602744e81Swyllys (void) memset(big->val, 0x00, big->len);
132799ebb4caSwyllys free(big->val);
132899ebb4caSwyllys big->val = NULL;
132999ebb4caSwyllys big->len = 0;
133099ebb4caSwyllys }
133199ebb4caSwyllys }
133299ebb4caSwyllys
133399ebb4caSwyllys static void
free_raw_rsa(KMF_RAW_RSA_KEY * key)133499ebb4caSwyllys free_raw_rsa(KMF_RAW_RSA_KEY *key)
133599ebb4caSwyllys {
133699ebb4caSwyllys if (key == NULL)
133799ebb4caSwyllys return;
133830a5e8faSwyllys kmf_free_bigint(&key->mod);
133930a5e8faSwyllys kmf_free_bigint(&key->pubexp);
134030a5e8faSwyllys kmf_free_bigint(&key->priexp);
134130a5e8faSwyllys kmf_free_bigint(&key->prime1);
134230a5e8faSwyllys kmf_free_bigint(&key->prime2);
134330a5e8faSwyllys kmf_free_bigint(&key->exp1);
134430a5e8faSwyllys kmf_free_bigint(&key->exp2);
134530a5e8faSwyllys kmf_free_bigint(&key->coef);
134699ebb4caSwyllys }
134799ebb4caSwyllys
134899ebb4caSwyllys static void
free_raw_dsa(KMF_RAW_DSA_KEY * key)134999ebb4caSwyllys free_raw_dsa(KMF_RAW_DSA_KEY *key)
135099ebb4caSwyllys {
135199ebb4caSwyllys if (key == NULL)
135299ebb4caSwyllys return;
135330a5e8faSwyllys kmf_free_bigint(&key->prime);
135430a5e8faSwyllys kmf_free_bigint(&key->subprime);
135530a5e8faSwyllys kmf_free_bigint(&key->base);
135630a5e8faSwyllys kmf_free_bigint(&key->value);
135799ebb4caSwyllys }
135899ebb4caSwyllys
135999ebb4caSwyllys static void
free_raw_sym(KMF_RAW_SYM_KEY * key)136099ebb4caSwyllys free_raw_sym(KMF_RAW_SYM_KEY *key)
136199ebb4caSwyllys {
136299ebb4caSwyllys if (key == NULL)
136399ebb4caSwyllys return;
136430a5e8faSwyllys kmf_free_bigint(&key->keydata);
136599ebb4caSwyllys }
136699ebb4caSwyllys
136799ebb4caSwyllys void
kmf_free_raw_key(KMF_RAW_KEY_DATA * key)136830a5e8faSwyllys kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
136999ebb4caSwyllys {
137099ebb4caSwyllys if (key == NULL)
137199ebb4caSwyllys return;
137299ebb4caSwyllys
137399ebb4caSwyllys switch (key->keytype) {
137499ebb4caSwyllys case KMF_RSA:
137599ebb4caSwyllys free_raw_rsa(&key->rawdata.rsa);
137699ebb4caSwyllys break;
137799ebb4caSwyllys case KMF_DSA:
137899ebb4caSwyllys free_raw_dsa(&key->rawdata.dsa);
137999ebb4caSwyllys break;
138099ebb4caSwyllys case KMF_AES:
138199ebb4caSwyllys case KMF_RC4:
138299ebb4caSwyllys case KMF_DES:
138399ebb4caSwyllys case KMF_DES3:
138499ebb4caSwyllys free_raw_sym(&key->rawdata.sym);
138599ebb4caSwyllys break;
138699ebb4caSwyllys }
13875b3e1433Swyllys if (key->label) {
13885b3e1433Swyllys free(key->label);
13895b3e1433Swyllys key->label = NULL;
13905b3e1433Swyllys }
13915b3e1433Swyllys kmf_free_data(&key->id);
139299ebb4caSwyllys }
139399ebb4caSwyllys
139499ebb4caSwyllys void
kmf_free_raw_sym_key(KMF_RAW_SYM_KEY * key)139530a5e8faSwyllys kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
139699ebb4caSwyllys {
139799ebb4caSwyllys if (key == NULL)
139899ebb4caSwyllys return;
139930a5e8faSwyllys kmf_free_bigint(&key->keydata);
140099ebb4caSwyllys free(key);
140199ebb4caSwyllys }
140299ebb4caSwyllys
140399ebb4caSwyllys /*
140499ebb4caSwyllys * This function frees the space allocated for the name portion of a
140599ebb4caSwyllys * KMF_CRL_DIST_POINT.
140699ebb4caSwyllys */
140799ebb4caSwyllys void
free_dp_name(KMF_CRL_DIST_POINT * dp)140899ebb4caSwyllys free_dp_name(KMF_CRL_DIST_POINT *dp)
140999ebb4caSwyllys {
141099ebb4caSwyllys KMF_GENERALNAMES *fullname;
141199ebb4caSwyllys KMF_DATA *urldata;
141299ebb4caSwyllys int i;
141399ebb4caSwyllys
141499ebb4caSwyllys if (dp == NULL)
141599ebb4caSwyllys return;
141699ebb4caSwyllys
141799ebb4caSwyllys /* For phase 1, we only need to free the fullname space. */
141899ebb4caSwyllys fullname = &(dp->name.full_name);
141999ebb4caSwyllys if (fullname->number == 0)
142099ebb4caSwyllys return;
142199ebb4caSwyllys
142299ebb4caSwyllys for (i = 0; i < fullname->number; i++) {
142399ebb4caSwyllys urldata = &(fullname->namelist[fullname->number - 1].name);
142430a5e8faSwyllys kmf_free_data(urldata);
142599ebb4caSwyllys }
142699ebb4caSwyllys
142799ebb4caSwyllys free(fullname->namelist);
142899ebb4caSwyllys }
142999ebb4caSwyllys
143099ebb4caSwyllys /*
143199ebb4caSwyllys * This function frees the space allocated for a KMF_CRL_DIST_POINT.
143299ebb4caSwyllys */
143399ebb4caSwyllys void
free_dp(KMF_CRL_DIST_POINT * dp)143499ebb4caSwyllys free_dp(KMF_CRL_DIST_POINT *dp)
143599ebb4caSwyllys {
143699ebb4caSwyllys if (dp == NULL)
143799ebb4caSwyllys return;
143899ebb4caSwyllys
143999ebb4caSwyllys free_dp_name(dp);
144030a5e8faSwyllys kmf_free_data(&(dp->reasons));
144199ebb4caSwyllys /* Need not to free crl_issuer space at phase 1 */
144299ebb4caSwyllys }
144399ebb4caSwyllys
144499ebb4caSwyllys /*
144599ebb4caSwyllys * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
144699ebb4caSwyllys */
144799ebb4caSwyllys void
kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS * crl_dps)144830a5e8faSwyllys kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
144999ebb4caSwyllys {
145099ebb4caSwyllys int i;
145199ebb4caSwyllys
145299ebb4caSwyllys if (crl_dps == NULL)
145399ebb4caSwyllys return;
145499ebb4caSwyllys
145599ebb4caSwyllys for (i = 0; i < crl_dps->number; i++)
145699ebb4caSwyllys free_dp(&(crl_dps->dplist[i]));
145799ebb4caSwyllys
145899ebb4caSwyllys free(crl_dps->dplist);
145999ebb4caSwyllys }
146099ebb4caSwyllys
146199ebb4caSwyllys KMF_RETURN
kmf_create_ocsp_request(KMF_HANDLE_T handle,int num_args,KMF_ATTRIBUTE * attrlist)146230a5e8faSwyllys kmf_create_ocsp_request(KMF_HANDLE_T handle,
146330a5e8faSwyllys int num_args,
146430a5e8faSwyllys KMF_ATTRIBUTE *attrlist)
146599ebb4caSwyllys {
146630a5e8faSwyllys KMF_RETURN ret = KMF_OK;
146799ebb4caSwyllys KMF_PLUGIN *plugin;
146830a5e8faSwyllys KMF_RETURN (*createReqFn)(void *, int num_args,
146930a5e8faSwyllys KMF_ATTRIBUTE *attrlist);
147030a5e8faSwyllys
147130a5e8faSwyllys KMF_ATTRIBUTE_TESTER required_attrs[] = {
147230a5e8faSwyllys {KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
147330a5e8faSwyllys {KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
147430a5e8faSwyllys sizeof (KMF_DATA)},
147530a5e8faSwyllys {KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
147630a5e8faSwyllys sizeof (KMF_DATA)},
147730a5e8faSwyllys };
147830a5e8faSwyllys
147930a5e8faSwyllys int num_req_attrs = sizeof (required_attrs) /
148030a5e8faSwyllys sizeof (KMF_ATTRIBUTE_TESTER);
148130a5e8faSwyllys
148230a5e8faSwyllys if (handle == NULL)
148330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
148499ebb4caSwyllys
148599ebb4caSwyllys CLEAR_ERROR(handle, ret);
148630a5e8faSwyllys
148730a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs,
148830a5e8faSwyllys 0, NULL, num_args, attrlist);
148930a5e8faSwyllys
149099ebb4caSwyllys if (ret != KMF_OK)
149199ebb4caSwyllys return (ret);
149299ebb4caSwyllys
149399ebb4caSwyllys /*
149499ebb4caSwyllys * This framework function is actually implemented in the openssl
149599ebb4caSwyllys * plugin library, so we find the function address and call it.
149699ebb4caSwyllys */
149799ebb4caSwyllys plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
149899ebb4caSwyllys if (plugin == NULL || plugin->dldesc == NULL) {
149999ebb4caSwyllys return (KMF_ERR_PLUGIN_NOTFOUND);
150099ebb4caSwyllys }
150199ebb4caSwyllys
150299ebb4caSwyllys createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
150399ebb4caSwyllys "OpenSSL_CreateOCSPRequest");
150499ebb4caSwyllys if (createReqFn == NULL) {
150599ebb4caSwyllys return (KMF_ERR_FUNCTION_NOT_FOUND);
150699ebb4caSwyllys }
150799ebb4caSwyllys
150830a5e8faSwyllys return (createReqFn(handle, num_args, attrlist));
150930a5e8faSwyllys
151099ebb4caSwyllys }
151199ebb4caSwyllys
151299ebb4caSwyllys KMF_RETURN
kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,int num_args,KMF_ATTRIBUTE * attrlist)151330a5e8faSwyllys kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
151430a5e8faSwyllys int num_args,
151530a5e8faSwyllys KMF_ATTRIBUTE *attrlist)
151699ebb4caSwyllys {
151730a5e8faSwyllys KMF_RETURN ret = KMF_OK;
151899ebb4caSwyllys KMF_PLUGIN *plugin;
151930a5e8faSwyllys KMF_RETURN (*getCertStatusFn)(void *, int num_args,
152030a5e8faSwyllys KMF_ATTRIBUTE *attrlist);
152130a5e8faSwyllys
152230a5e8faSwyllys KMF_ATTRIBUTE_TESTER required_attrs[] = {
152330a5e8faSwyllys {KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
152430a5e8faSwyllys sizeof (KMF_DATA)},
152530a5e8faSwyllys {KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
152630a5e8faSwyllys sizeof (KMF_DATA)},
152730a5e8faSwyllys {KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
152830a5e8faSwyllys sizeof (KMF_DATA)},
152930a5e8faSwyllys {KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
153030a5e8faSwyllys sizeof (uint32_t)},
153130a5e8faSwyllys {KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
153230a5e8faSwyllys sizeof (uint32_t)},
153330a5e8faSwyllys {KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
153430a5e8faSwyllys sizeof (uint32_t)},
153530a5e8faSwyllys };
153630a5e8faSwyllys
153730a5e8faSwyllys int num_req_attrs = sizeof (required_attrs) /
153830a5e8faSwyllys sizeof (KMF_ATTRIBUTE_TESTER);
153930a5e8faSwyllys
154030a5e8faSwyllys if (handle == NULL)
154130a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
154299ebb4caSwyllys
154399ebb4caSwyllys CLEAR_ERROR(handle, ret);
154430a5e8faSwyllys
154530a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs,
154630a5e8faSwyllys 0, NULL, num_args, attrlist);
154730a5e8faSwyllys
154899ebb4caSwyllys if (ret != KMF_OK)
154999ebb4caSwyllys return (ret);
155099ebb4caSwyllys
155199ebb4caSwyllys /*
155299ebb4caSwyllys * This framework function is actually implemented in the openssl
155399ebb4caSwyllys * plugin library, so we find the function address and call it.
155499ebb4caSwyllys */
155599ebb4caSwyllys plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
155699ebb4caSwyllys if (plugin == NULL || plugin->dldesc == NULL) {
155799ebb4caSwyllys return (KMF_ERR_INTERNAL);
155899ebb4caSwyllys }
155999ebb4caSwyllys
156099ebb4caSwyllys getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
156199ebb4caSwyllys "OpenSSL_GetOCSPStatusForCert");
156299ebb4caSwyllys if (getCertStatusFn == NULL) {
156399ebb4caSwyllys return (KMF_ERR_INTERNAL);
156499ebb4caSwyllys }
156599ebb4caSwyllys
156630a5e8faSwyllys return (getCertStatusFn(handle, num_args, attrlist));
156730a5e8faSwyllys
156899ebb4caSwyllys }
156999ebb4caSwyllys
157099ebb4caSwyllys KMF_RETURN
kmf_string_to_oid(char * oidstring,KMF_OID * oid)157130a5e8faSwyllys kmf_string_to_oid(char *oidstring, KMF_OID *oid)
157299ebb4caSwyllys {
157399ebb4caSwyllys KMF_RETURN rv = KMF_OK;
157499ebb4caSwyllys char *cp, *bp, *startp;
157599ebb4caSwyllys int numbuf;
157699ebb4caSwyllys int onumbuf;
157799ebb4caSwyllys int nbytes, index;
157899ebb4caSwyllys int len;
157999ebb4caSwyllys unsigned char *op;
158099ebb4caSwyllys
158199ebb4caSwyllys if (oidstring == NULL || oid == NULL)
158299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
158399ebb4caSwyllys
158499ebb4caSwyllys len = strlen(oidstring);
158599ebb4caSwyllys
158699ebb4caSwyllys bp = oidstring;
158799ebb4caSwyllys cp = bp;
158899ebb4caSwyllys /* Skip over leading space */
158999ebb4caSwyllys while ((bp < &cp[len]) && isspace(*bp))
159099ebb4caSwyllys bp++;
159199ebb4caSwyllys
159299ebb4caSwyllys startp = bp;
159399ebb4caSwyllys nbytes = 0;
159499ebb4caSwyllys
159599ebb4caSwyllys /*
159699ebb4caSwyllys * The first two numbers are chewed up by the first octet.
159799ebb4caSwyllys */
159899ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1)
159999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
160099ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp))
160199ebb4caSwyllys bp++;
160299ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
160399ebb4caSwyllys bp++;
160499ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1)
160599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
160699ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp))
160799ebb4caSwyllys bp++;
160899ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
160999ebb4caSwyllys bp++;
161099ebb4caSwyllys nbytes++;
161199ebb4caSwyllys
161299ebb4caSwyllys while (isdigit(*bp)) {
161399ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1)
161499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
161599ebb4caSwyllys while (numbuf) {
161699ebb4caSwyllys nbytes++;
161799ebb4caSwyllys numbuf >>= 7;
161899ebb4caSwyllys }
161999ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp))
162099ebb4caSwyllys bp++;
162199ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
162299ebb4caSwyllys bp++;
162399ebb4caSwyllys }
162499ebb4caSwyllys
162599ebb4caSwyllys oid->Length = nbytes;
162699ebb4caSwyllys oid->Data = malloc(oid->Length);
162799ebb4caSwyllys if (oid->Data == NULL) {
162899ebb4caSwyllys return (KMF_ERR_MEMORY);
162999ebb4caSwyllys }
163099ebb4caSwyllys (void) memset(oid->Data, 0, oid->Length);
163199ebb4caSwyllys
163299ebb4caSwyllys op = oid->Data;
163399ebb4caSwyllys
163499ebb4caSwyllys bp = startp;
163599ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf);
163699ebb4caSwyllys
163799ebb4caSwyllys while (isdigit(*bp)) bp++;
163899ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++;
163999ebb4caSwyllys
164099ebb4caSwyllys onumbuf = 40 * numbuf;
164199ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf);
164299ebb4caSwyllys onumbuf += numbuf;
164399ebb4caSwyllys *op = (unsigned char) onumbuf;
164499ebb4caSwyllys op++;
164599ebb4caSwyllys
164699ebb4caSwyllys while (isdigit(*bp)) bp++;
164799ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++;
164899ebb4caSwyllys while (isdigit(*bp)) {
164999ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf);
165099ebb4caSwyllys nbytes = 0;
165199ebb4caSwyllys /* Have to fill in the bytes msb-first */
165299ebb4caSwyllys onumbuf = numbuf;
165399ebb4caSwyllys while (numbuf) {
165499ebb4caSwyllys nbytes++;
165599ebb4caSwyllys numbuf >>= 7;
165699ebb4caSwyllys }
165799ebb4caSwyllys numbuf = onumbuf;
165899ebb4caSwyllys op += nbytes;
165999ebb4caSwyllys index = -1;
166099ebb4caSwyllys while (numbuf) {
166199ebb4caSwyllys op[index] = (unsigned char)numbuf & 0x7f;
166299ebb4caSwyllys if (index != -1)
166399ebb4caSwyllys op[index] |= 0x80;
166499ebb4caSwyllys index--;
166599ebb4caSwyllys numbuf >>= 7;
166699ebb4caSwyllys }
166799ebb4caSwyllys while (isdigit(*bp)) bp++;
166899ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++;
166999ebb4caSwyllys }
167099ebb4caSwyllys
167199ebb4caSwyllys return (rv);
167299ebb4caSwyllys }
167399ebb4caSwyllys
167499ebb4caSwyllys static KMF_RETURN
encode_rid(char * name,KMF_DATA * derdata)167599ebb4caSwyllys encode_rid(char *name, KMF_DATA *derdata)
167699ebb4caSwyllys {
167799ebb4caSwyllys KMF_RETURN rv = KMF_OK;
167899ebb4caSwyllys
167999ebb4caSwyllys if (name == NULL || derdata == NULL)
168099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
168199ebb4caSwyllys
168230a5e8faSwyllys rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
168399ebb4caSwyllys
168499ebb4caSwyllys return (rv);
168599ebb4caSwyllys }
168699ebb4caSwyllys
168799ebb4caSwyllys static KMF_RETURN
encode_ipaddr(char * name,KMF_DATA * derdata)168899ebb4caSwyllys encode_ipaddr(char *name, KMF_DATA *derdata)
168999ebb4caSwyllys {
169099ebb4caSwyllys KMF_RETURN rv = KMF_OK;
169199ebb4caSwyllys size_t len;
169299ebb4caSwyllys in_addr_t v4;
169399ebb4caSwyllys in6_addr_t v6;
169499ebb4caSwyllys uint8_t *ptr;
169599ebb4caSwyllys
169699ebb4caSwyllys if (name == NULL || derdata == NULL)
169799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
169899ebb4caSwyllys
169999ebb4caSwyllys v4 = inet_addr(name);
170099ebb4caSwyllys if (v4 == (in_addr_t)-1) {
170199ebb4caSwyllys ptr = (uint8_t *)&v6;
170299ebb4caSwyllys if (inet_pton(AF_INET6, name, ptr) != 1)
170399ebb4caSwyllys return (KMF_ERR_ENCODING);
170499ebb4caSwyllys len = sizeof (v6);
170599ebb4caSwyllys } else {
170699ebb4caSwyllys ptr = (uint8_t *)&v4;
170799ebb4caSwyllys len = sizeof (v4);
170899ebb4caSwyllys }
170999ebb4caSwyllys
171099ebb4caSwyllys derdata->Data = malloc(len);
171199ebb4caSwyllys if (derdata->Data == NULL)
171299ebb4caSwyllys return (KMF_ERR_MEMORY);
171399ebb4caSwyllys (void) memcpy(derdata->Data, ptr, len);
171499ebb4caSwyllys derdata->Length = len;
171599ebb4caSwyllys
171699ebb4caSwyllys return (rv);
171799ebb4caSwyllys }
171899ebb4caSwyllys
171999ebb4caSwyllys static KMF_RETURN
encode_krb5(char * name,KMF_DATA * derdata)1720d00756ccSwyllys encode_krb5(char *name, KMF_DATA *derdata)
1721d00756ccSwyllys {
1722d00756ccSwyllys KMF_RETURN rv = KMF_OK;
1723d00756ccSwyllys char *at, *realm;
172456664548SWyllys Ingersoll char *slash, *inst = NULL;
1725d00756ccSwyllys BerElement *asn1 = NULL;
1726d00756ccSwyllys BerValue *extdata = NULL;
1727d00756ccSwyllys
1728d00756ccSwyllys at = strchr(name, '@');
1729d00756ccSwyllys if (at == NULL)
1730d00756ccSwyllys return (KMF_ERR_ENCODING);
1731d00756ccSwyllys
1732d00756ccSwyllys realm = at + 1;
1733d00756ccSwyllys *at = 0;
1734d00756ccSwyllys
173556664548SWyllys Ingersoll /*
173656664548SWyllys Ingersoll * KRB5PrincipalName ::= SEQUENCE {
173756664548SWyllys Ingersoll * realm [0] Realm,
173856664548SWyllys Ingersoll * principalName [1] PrincipalName
173956664548SWyllys Ingersoll * }
174056664548SWyllys Ingersoll *
174156664548SWyllys Ingersoll * KerberosString ::= GeneralString (IA5String)
174256664548SWyllys Ingersoll * Realm ::= KerberosString
174356664548SWyllys Ingersoll * PrincipalName ::= SEQUENCE {
174456664548SWyllys Ingersoll * name-type [0] Int32,
174556664548SWyllys Ingersoll * name-string [1] SEQUENCE OF KerberosString
174656664548SWyllys Ingersoll * }
174756664548SWyllys Ingersoll */
1748d00756ccSwyllys
174956664548SWyllys Ingersoll /*
175056664548SWyllys Ingersoll * Construct the "principalName" first.
175156664548SWyllys Ingersoll *
175256664548SWyllys Ingersoll * The name may be split with a "/" to indicate a new instance.
175356664548SWyllys Ingersoll * This must be separated in the ASN.1
175456664548SWyllys Ingersoll */
175556664548SWyllys Ingersoll slash = strchr(name, '/');
175656664548SWyllys Ingersoll if (slash != NULL) {
175756664548SWyllys Ingersoll inst = name;
175856664548SWyllys Ingersoll name = slash + 1;
175956664548SWyllys Ingersoll *slash = 0;
176056664548SWyllys Ingersoll }
176156664548SWyllys Ingersoll if ((asn1 = kmfder_alloc()) == NULL) {
176256664548SWyllys Ingersoll rv = KMF_ERR_MEMORY;
176356664548SWyllys Ingersoll goto cleanup;
176456664548SWyllys Ingersoll }
176556664548SWyllys Ingersoll if (kmfber_printf(asn1, "{Tli", 0xa0, 3, 0x01) == -1)
1766d00756ccSwyllys goto cleanup;
1767d00756ccSwyllys
176856664548SWyllys Ingersoll if (inst != NULL) {
176956664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl{Tl", 0xA1,
177056664548SWyllys Ingersoll strlen(inst) + strlen(name) + 6,
177156664548SWyllys Ingersoll BER_GENERALSTRING, strlen(inst)) == -1)
1772d00756ccSwyllys goto cleanup;
177356664548SWyllys Ingersoll if (kmfber_write(asn1, inst, strlen(inst), 0) != strlen(inst))
1774d00756ccSwyllys goto cleanup;
177556664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl", BER_GENERALSTRING,
177656664548SWyllys Ingersoll strlen(name)) == -1)
1777d00756ccSwyllys goto cleanup;
1778d00756ccSwyllys if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name))
1779d00756ccSwyllys goto cleanup;
178056664548SWyllys Ingersoll } else {
178156664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl{Tl", 0xA1,
178256664548SWyllys Ingersoll strlen(name) + 4, BER_GENERALSTRING, strlen(name)) == -1)
178356664548SWyllys Ingersoll goto cleanup;
178456664548SWyllys Ingersoll if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name))
178556664548SWyllys Ingersoll goto cleanup;
178656664548SWyllys Ingersoll }
178756664548SWyllys Ingersoll
1788d00756ccSwyllys if (kmfber_printf(asn1, "}}") == -1)
1789d00756ccSwyllys goto cleanup;
1790d00756ccSwyllys if (kmfber_flatten(asn1, &extdata) == -1) {
1791d00756ccSwyllys rv = KMF_ERR_ENCODING;
1792d00756ccSwyllys goto cleanup;
1793d00756ccSwyllys }
179456664548SWyllys Ingersoll kmfber_free(asn1, 1);
179556664548SWyllys Ingersoll asn1 = NULL;
179656664548SWyllys Ingersoll
179756664548SWyllys Ingersoll /* Next construct the KRB5PrincipalNameSeq */
179856664548SWyllys Ingersoll if ((asn1 = kmfder_alloc()) == NULL) {
179956664548SWyllys Ingersoll kmfber_bvfree(extdata);
180056664548SWyllys Ingersoll rv = KMF_ERR_MEMORY;
180156664548SWyllys Ingersoll goto cleanup;
180256664548SWyllys Ingersoll }
180356664548SWyllys Ingersoll if (kmfber_printf(asn1, "{TlTl", 0xA0, strlen(realm) + 2,
180456664548SWyllys Ingersoll BER_GENERALSTRING, strlen(realm)) == -1)
180556664548SWyllys Ingersoll goto cleanup;
180656664548SWyllys Ingersoll if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm))
180756664548SWyllys Ingersoll goto cleanup;
180856664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl", 0xA1, extdata->bv_len) == -1)
180956664548SWyllys Ingersoll goto cleanup;
181056664548SWyllys Ingersoll if (kmfber_write(asn1, extdata->bv_val,
181156664548SWyllys Ingersoll extdata->bv_len, 0) != extdata->bv_len)
181256664548SWyllys Ingersoll goto cleanup;
181356664548SWyllys Ingersoll if (kmfber_printf(asn1, "}") == -1)
181456664548SWyllys Ingersoll goto cleanup;
181556664548SWyllys Ingersoll kmfber_bvfree(extdata);
181656664548SWyllys Ingersoll extdata = NULL;
181756664548SWyllys Ingersoll if (kmfber_flatten(asn1, &extdata) == -1) {
181856664548SWyllys Ingersoll rv = KMF_ERR_ENCODING;
181956664548SWyllys Ingersoll goto cleanup;
182056664548SWyllys Ingersoll }
182156664548SWyllys Ingersoll kmfber_free(asn1, 1);
182256664548SWyllys Ingersoll asn1 = NULL;
182356664548SWyllys Ingersoll
182456664548SWyllys Ingersoll /*
182556664548SWyllys Ingersoll * GeneralName ::= CHOICE {
182656664548SWyllys Ingersoll * otherName [0] OtherName,
182756664548SWyllys Ingersoll * ...
182856664548SWyllys Ingersoll * }
182956664548SWyllys Ingersoll *
183056664548SWyllys Ingersoll * OtherName ::= SEQUENCE {
183156664548SWyllys Ingersoll * type-id OBJECT IDENTIFIER,
183256664548SWyllys Ingersoll * value [0] EXPLICIT ANY DEFINED BY type-id
183356664548SWyllys Ingersoll * }
183456664548SWyllys Ingersoll */
183556664548SWyllys Ingersoll
183656664548SWyllys Ingersoll /* Now construct the SAN: OID + typed data. */
183756664548SWyllys Ingersoll if ((asn1 = kmfder_alloc()) == NULL) {
183856664548SWyllys Ingersoll kmfber_bvfree(extdata);
183956664548SWyllys Ingersoll rv = KMF_ERR_MEMORY;
184056664548SWyllys Ingersoll goto cleanup;
184156664548SWyllys Ingersoll }
184256664548SWyllys Ingersoll if (kmfber_printf(asn1, "D", &KMFOID_PKINIT_san) == -1)
184356664548SWyllys Ingersoll goto cleanup;
184456664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl", 0xA0, extdata->bv_len) == -1)
184556664548SWyllys Ingersoll goto cleanup;
184656664548SWyllys Ingersoll if (kmfber_write(asn1, extdata->bv_val,
184756664548SWyllys Ingersoll extdata->bv_len, 0) != extdata->bv_len)
184856664548SWyllys Ingersoll goto cleanup;
184956664548SWyllys Ingersoll kmfber_bvfree(extdata);
185056664548SWyllys Ingersoll extdata = NULL;
185156664548SWyllys Ingersoll if (kmfber_flatten(asn1, &extdata) == -1) {
185256664548SWyllys Ingersoll rv = KMF_ERR_ENCODING;
185356664548SWyllys Ingersoll goto cleanup;
185456664548SWyllys Ingersoll }
185556664548SWyllys Ingersoll kmfber_free(asn1, 1);
185656664548SWyllys Ingersoll asn1 = NULL;
1857d00756ccSwyllys
1858d00756ccSwyllys derdata->Data = (uchar_t *)extdata->bv_val;
185956664548SWyllys Ingersoll extdata->bv_val = NULL; /* clear it so it is not freed later */
1860d00756ccSwyllys derdata->Length = extdata->bv_len;
1861d00756ccSwyllys
1862d00756ccSwyllys cleanup:
1863d00756ccSwyllys if (asn1 != NULL)
1864d00756ccSwyllys kmfber_free(asn1, 1);
1865d00756ccSwyllys
186656664548SWyllys Ingersoll if (extdata != NULL)
186756664548SWyllys Ingersoll kmfber_bvfree(extdata);
186856664548SWyllys Ingersoll
1869d00756ccSwyllys if (*at == 0)
1870d00756ccSwyllys *at = '@';
1871d00756ccSwyllys
187256664548SWyllys Ingersoll if (inst != NULL)
187356664548SWyllys Ingersoll *slash = '/';
187456664548SWyllys Ingersoll
1875d00756ccSwyllys return (rv);
1876d00756ccSwyllys }
1877d00756ccSwyllys
1878d00756ccSwyllys static KMF_RETURN
encode_sclogon(char * name,KMF_DATA * derdata)1879d00756ccSwyllys encode_sclogon(char *name, KMF_DATA *derdata)
1880d00756ccSwyllys {
1881d00756ccSwyllys KMF_RETURN rv = KMF_OK;
1882d00756ccSwyllys BerElement *asn1 = NULL;
1883d00756ccSwyllys BerValue *extdata = NULL;
1884d00756ccSwyllys
1885d00756ccSwyllys if ((asn1 = kmfder_alloc()) == NULL)
1886d00756ccSwyllys return (KMF_ERR_MEMORY);
1887d00756ccSwyllys
1888d00756ccSwyllys /* The name is encoded as a KerberosString (IA5STRING) */
1889d00756ccSwyllys if (kmfber_printf(asn1, "{Ds}",
1890d00756ccSwyllys &KMFOID_MS_KP_SCLogon, name) == -1)
1891d00756ccSwyllys goto cleanup;
1892d00756ccSwyllys
1893d00756ccSwyllys if (kmfber_flatten(asn1, &extdata) == -1) {
1894d00756ccSwyllys rv = KMF_ERR_ENCODING;
1895d00756ccSwyllys goto cleanup;
1896d00756ccSwyllys }
1897d00756ccSwyllys
1898d00756ccSwyllys derdata->Data = (uchar_t *)extdata->bv_val;
1899d00756ccSwyllys derdata->Length = extdata->bv_len;
1900d00756ccSwyllys
1901d00756ccSwyllys free(extdata);
1902d00756ccSwyllys cleanup:
1903d00756ccSwyllys if (asn1 != NULL)
1904d00756ccSwyllys kmfber_free(asn1, 1);
1905d00756ccSwyllys
1906d00756ccSwyllys return (rv);
1907d00756ccSwyllys }
1908d00756ccSwyllys
1909d00756ccSwyllys static KMF_RETURN
verify_uri_format(char * uristring)191099ebb4caSwyllys verify_uri_format(char *uristring)
191199ebb4caSwyllys {
191299ebb4caSwyllys KMF_RETURN ret = KMF_OK;
191399ebb4caSwyllys xmlURIPtr uriptr = NULL;
191499ebb4caSwyllys
191599ebb4caSwyllys /* Parse the URI string; get the hostname and port */
191699ebb4caSwyllys uriptr = xmlParseURI(uristring);
191799ebb4caSwyllys if (uriptr == NULL) {
191899ebb4caSwyllys ret = KMF_ERR_BAD_URI;
191999ebb4caSwyllys goto out;
192099ebb4caSwyllys }
192199ebb4caSwyllys
192299ebb4caSwyllys if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
192399ebb4caSwyllys ret = KMF_ERR_BAD_URI;
192499ebb4caSwyllys goto out;
192599ebb4caSwyllys }
192699ebb4caSwyllys
192799ebb4caSwyllys if (uriptr->server == NULL || !strlen(uriptr->server)) {
192899ebb4caSwyllys ret = KMF_ERR_BAD_URI;
192999ebb4caSwyllys goto out;
193099ebb4caSwyllys }
193199ebb4caSwyllys out:
193299ebb4caSwyllys if (uriptr != NULL)
193399ebb4caSwyllys xmlFreeURI(uriptr);
193499ebb4caSwyllys return (ret);
193599ebb4caSwyllys }
193699ebb4caSwyllys
193799ebb4caSwyllys static KMF_RETURN
encode_altname(char * namedata,KMF_GENERALNAMECHOICES nametype,KMF_DATA * encodedname)193899ebb4caSwyllys encode_altname(char *namedata,
193999ebb4caSwyllys KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
194099ebb4caSwyllys {
194199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
194299ebb4caSwyllys KMF_X509_NAME dnname;
194399ebb4caSwyllys uchar_t tagval;
194499ebb4caSwyllys BerElement *asn1 = NULL;
194599ebb4caSwyllys BerValue *extdata;
194699ebb4caSwyllys
194799ebb4caSwyllys if (namedata == NULL || encodedname == NULL)
194899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
194999ebb4caSwyllys
195099ebb4caSwyllys /*
195199ebb4caSwyllys * Encode the namedata according to rules in RFC 3280 for GeneralName.
195299ebb4caSwyllys * The input "namedata" is assumed to be an ASCII string representation
195399ebb4caSwyllys * of the AltName, we need to convert it to correct ASN.1 here before
195499ebb4caSwyllys * adding it to the cert.
195599ebb4caSwyllys */
195699ebb4caSwyllys switch (nametype) {
195799ebb4caSwyllys case GENNAME_RFC822NAME: /* rfc 822 */
195899ebb4caSwyllys /* IA5String, no encoding needed */
195999ebb4caSwyllys encodedname->Data = (uchar_t *)strdup(namedata);
196099ebb4caSwyllys if (encodedname->Data == NULL)
196199ebb4caSwyllys return (KMF_ERR_MEMORY);
196299ebb4caSwyllys encodedname->Length = strlen(namedata);
196399ebb4caSwyllys tagval = (0x80 | nametype);
196499ebb4caSwyllys break;
196599ebb4caSwyllys case GENNAME_DNSNAME: /* rfc 1034 */
196699ebb4caSwyllys encodedname->Data = (uchar_t *)strdup(namedata);
196799ebb4caSwyllys if (encodedname->Data == NULL)
196899ebb4caSwyllys return (KMF_ERR_MEMORY);
196999ebb4caSwyllys encodedname->Length = strlen(namedata);
197099ebb4caSwyllys tagval = (0x80 | nametype);
197199ebb4caSwyllys break;
197299ebb4caSwyllys case GENNAME_URI: /* rfc 1738 */
197399ebb4caSwyllys ret = verify_uri_format(namedata);
197499ebb4caSwyllys if (ret != KMF_OK)
197599ebb4caSwyllys return (ret);
197699ebb4caSwyllys /* IA5String, no encoding needed */
197799ebb4caSwyllys encodedname->Data = (uchar_t *)strdup(namedata);
197899ebb4caSwyllys if (encodedname->Data == NULL)
197999ebb4caSwyllys return (KMF_ERR_MEMORY);
198099ebb4caSwyllys encodedname->Length = strlen(namedata);
198199ebb4caSwyllys tagval = (0x80 | nametype);
198299ebb4caSwyllys break;
198399ebb4caSwyllys case GENNAME_IPADDRESS:
198499ebb4caSwyllys ret = encode_ipaddr(namedata, encodedname);
198599ebb4caSwyllys tagval = (0x80 | nametype);
198699ebb4caSwyllys break;
198799ebb4caSwyllys case GENNAME_REGISTEREDID:
198899ebb4caSwyllys ret = encode_rid(namedata, encodedname);
198999ebb4caSwyllys tagval = (0x80 | nametype);
199099ebb4caSwyllys break;
199199ebb4caSwyllys case GENNAME_DIRECTORYNAME:
199230a5e8faSwyllys ret = kmf_dn_parser(namedata, &dnname);
199399ebb4caSwyllys if (ret == KMF_OK) {
199430a5e8faSwyllys ret = DerEncodeName(&dnname, encodedname);
199599ebb4caSwyllys }
199630a5e8faSwyllys (void) kmf_free_dn(&dnname);
199756664548SWyllys Ingersoll tagval = (0x80 | nametype);
199899ebb4caSwyllys break;
1999d00756ccSwyllys case GENNAME_KRB5PRINC:
200056664548SWyllys Ingersoll tagval = (0xA0 | GENNAME_OTHERNAME);
2001d00756ccSwyllys ret = encode_krb5(namedata, encodedname);
2002d00756ccSwyllys break;
2003d00756ccSwyllys case GENNAME_SCLOGON_UPN:
200456664548SWyllys Ingersoll tagval = (0xA0 | GENNAME_OTHERNAME);
2005d00756ccSwyllys ret = encode_sclogon(namedata, encodedname);
2006d00756ccSwyllys break;
200799ebb4caSwyllys default:
200899ebb4caSwyllys /* unsupported */
200999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
201099ebb4caSwyllys
201199ebb4caSwyllys }
201299ebb4caSwyllys if (ret != KMF_OK) {
201330a5e8faSwyllys kmf_free_data(encodedname);
201499ebb4caSwyllys return (ret);
201599ebb4caSwyllys }
201699ebb4caSwyllys
201799ebb4caSwyllys if ((asn1 = kmfder_alloc()) == NULL)
201899ebb4caSwyllys return (KMF_ERR_MEMORY);
201999ebb4caSwyllys
202030a5e8faSwyllys if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
202199ebb4caSwyllys goto cleanup;
202299ebb4caSwyllys
202399ebb4caSwyllys if (kmfber_write(asn1, (char *)encodedname->Data,
202499ebb4caSwyllys encodedname->Length, 0) == -1) {
202599ebb4caSwyllys ret = KMF_ERR_ENCODING;
202699ebb4caSwyllys goto cleanup;
202799ebb4caSwyllys }
202899ebb4caSwyllys if (kmfber_flatten(asn1, &extdata) == -1) {
202999ebb4caSwyllys ret = KMF_ERR_ENCODING;
203099ebb4caSwyllys goto cleanup;
203199ebb4caSwyllys }
203299ebb4caSwyllys
203330a5e8faSwyllys kmf_free_data(encodedname);
203499ebb4caSwyllys encodedname->Data = (uchar_t *)extdata->bv_val;
203599ebb4caSwyllys encodedname->Length = extdata->bv_len;
203699ebb4caSwyllys
203799ebb4caSwyllys free(extdata);
203899ebb4caSwyllys
203999ebb4caSwyllys cleanup:
204099ebb4caSwyllys if (asn1)
204199ebb4caSwyllys kmfber_free(asn1, 1);
204299ebb4caSwyllys
204399ebb4caSwyllys if (ret != KMF_OK)
204430a5e8faSwyllys kmf_free_data(encodedname);
204599ebb4caSwyllys
204699ebb4caSwyllys return (ret);
204799ebb4caSwyllys }
204899ebb4caSwyllys
204999ebb4caSwyllys KMF_X509_EXTENSION *
FindExtn(KMF_X509_EXTENSIONS * exts,KMF_OID * oid)205099ebb4caSwyllys FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
205199ebb4caSwyllys {
205299ebb4caSwyllys KMF_X509_EXTENSION *foundextn = NULL;
205399ebb4caSwyllys int i;
205499ebb4caSwyllys
205599ebb4caSwyllys if (exts == NULL || oid == NULL)
205699ebb4caSwyllys return (NULL);
205799ebb4caSwyllys
205899ebb4caSwyllys for (i = 0; i < exts->numberOfExtensions; i++) {
205999ebb4caSwyllys if (IsEqualOid(oid, &exts->extensions[i].extnId)) {
206099ebb4caSwyllys foundextn = &exts->extensions[i];
206199ebb4caSwyllys break;
206299ebb4caSwyllys }
206399ebb4caSwyllys }
206499ebb4caSwyllys return (foundextn);
206599ebb4caSwyllys }
206699ebb4caSwyllys
206799ebb4caSwyllys KMF_RETURN
GetSequenceContents(char * data,size_t len,char ** contents,size_t * outlen)206899ebb4caSwyllys GetSequenceContents(char *data, size_t len,
206999ebb4caSwyllys char **contents, size_t *outlen)
207099ebb4caSwyllys {
207199ebb4caSwyllys KMF_RETURN ret = KMF_OK;
207299ebb4caSwyllys BerElement *exasn1 = NULL;
207399ebb4caSwyllys BerValue oldextn;
207499ebb4caSwyllys int tag;
207599ebb4caSwyllys size_t oldsize;
207699ebb4caSwyllys char *olddata = NULL;
207799ebb4caSwyllys
207899ebb4caSwyllys if (data == NULL || contents == NULL || outlen == NULL)
207999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
208099ebb4caSwyllys
208199ebb4caSwyllys /*
208299ebb4caSwyllys * Decode the sequence of general names
208399ebb4caSwyllys */
208499ebb4caSwyllys oldextn.bv_val = data;
208599ebb4caSwyllys oldextn.bv_len = len;
208699ebb4caSwyllys
208799ebb4caSwyllys if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
208899ebb4caSwyllys ret = KMF_ERR_MEMORY;
208999ebb4caSwyllys goto out;
209099ebb4caSwyllys }
209199ebb4caSwyllys
209299ebb4caSwyllys /*
209399ebb4caSwyllys * Unwrap the sequence to find the size of the block
209499ebb4caSwyllys * of GeneralName items in the set.
209599ebb4caSwyllys *
209699ebb4caSwyllys * Peek at the tag and length ("tl"),
209799ebb4caSwyllys * then consume them ("{").
209899ebb4caSwyllys */
209999ebb4caSwyllys if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
210099ebb4caSwyllys oldsize == 0) {
210199ebb4caSwyllys ret = KMF_ERR_ENCODING;
210299ebb4caSwyllys goto out;
210399ebb4caSwyllys }
210499ebb4caSwyllys
210599ebb4caSwyllys olddata = malloc(oldsize);
210699ebb4caSwyllys if (olddata == NULL) {
210799ebb4caSwyllys ret = KMF_ERR_MEMORY;
210899ebb4caSwyllys goto out;
210999ebb4caSwyllys }
211099ebb4caSwyllys (void) memset(olddata, 0, oldsize);
211199ebb4caSwyllys /*
211299ebb4caSwyllys * Read the entire blob of GeneralNames, we don't
211399ebb4caSwyllys * need to interpret them now.
211499ebb4caSwyllys */
211599ebb4caSwyllys if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
211699ebb4caSwyllys ret = KMF_ERR_ENCODING;
211799ebb4caSwyllys goto out;
211899ebb4caSwyllys }
211999ebb4caSwyllys out:
212099ebb4caSwyllys if (exasn1 != NULL)
212199ebb4caSwyllys kmfber_free(exasn1, 1);
212299ebb4caSwyllys
212399ebb4caSwyllys if (ret != KMF_OK) {
212499ebb4caSwyllys *contents = NULL;
212599ebb4caSwyllys *outlen = 0;
212699ebb4caSwyllys if (olddata != NULL)
212799ebb4caSwyllys free(olddata);
212899ebb4caSwyllys } else {
212999ebb4caSwyllys *contents = olddata;
213099ebb4caSwyllys *outlen = oldsize;
213199ebb4caSwyllys }
213299ebb4caSwyllys return (ret);
213399ebb4caSwyllys }
213499ebb4caSwyllys
213599ebb4caSwyllys KMF_RETURN
add_an_extension(KMF_X509_EXTENSIONS * exts,KMF_X509_EXTENSION * newextn)213699ebb4caSwyllys add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
213799ebb4caSwyllys {
213899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
213999ebb4caSwyllys KMF_X509_EXTENSION *extlist;
214099ebb4caSwyllys
214199ebb4caSwyllys if (exts == NULL || newextn == NULL)
214299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
214399ebb4caSwyllys
214499ebb4caSwyllys extlist = malloc(sizeof (KMF_X509_EXTENSION) *
214599ebb4caSwyllys (exts->numberOfExtensions + 1));
214699ebb4caSwyllys if (extlist == NULL)
214799ebb4caSwyllys return (KMF_ERR_MEMORY);
214899ebb4caSwyllys
214999ebb4caSwyllys (void) memcpy(extlist, exts->extensions,
215099ebb4caSwyllys exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
215199ebb4caSwyllys
215299ebb4caSwyllys (void) memcpy(&extlist[exts->numberOfExtensions], newextn,
215399ebb4caSwyllys sizeof (KMF_X509_EXTENSION));
215499ebb4caSwyllys
215599ebb4caSwyllys free(exts->extensions);
215699ebb4caSwyllys exts->numberOfExtensions++;
215799ebb4caSwyllys exts->extensions = extlist;
215899ebb4caSwyllys
215999ebb4caSwyllys return (ret);
216099ebb4caSwyllys }
216199ebb4caSwyllys
216299ebb4caSwyllys KMF_RETURN
kmf_set_altname(KMF_X509_EXTENSIONS * extensions,KMF_OID * oid,int critical,KMF_GENERALNAMECHOICES nametype,char * namedata)216330a5e8faSwyllys kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
216499ebb4caSwyllys KMF_OID *oid,
216599ebb4caSwyllys int critical,
216699ebb4caSwyllys KMF_GENERALNAMECHOICES nametype,
216799ebb4caSwyllys char *namedata)
216899ebb4caSwyllys {
216999ebb4caSwyllys KMF_RETURN ret = KMF_OK;
217099ebb4caSwyllys KMF_X509_EXTENSION subjAltName;
2171*6b35cb3cSRichard PALO KMF_DATA dername = { 0, NULL };
217299ebb4caSwyllys BerElement *asn1 = NULL;
217399ebb4caSwyllys BerValue *extdata;
217499ebb4caSwyllys char *olddata = NULL;
217599ebb4caSwyllys KMF_X509_EXTENSION *foundextn = NULL;
217699ebb4caSwyllys size_t oldsize = 0;
217799ebb4caSwyllys
217899ebb4caSwyllys if (extensions == NULL || oid == NULL || namedata == NULL)
217999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
218099ebb4caSwyllys
218199ebb4caSwyllys ret = encode_altname(namedata, nametype, &dername);
218299ebb4caSwyllys
218399ebb4caSwyllys if (ret != KMF_OK)
218499ebb4caSwyllys return (ret);
218599ebb4caSwyllys
218699ebb4caSwyllys (void) memset(&subjAltName, 0, sizeof (subjAltName));
218799ebb4caSwyllys
218899ebb4caSwyllys ret = copy_data(&subjAltName.extnId, oid);
218999ebb4caSwyllys if (ret != KMF_OK)
219099ebb4caSwyllys goto out;
219199ebb4caSwyllys /*
219299ebb4caSwyllys * Check to see if this cert already has a subjectAltName.
219399ebb4caSwyllys */
219499ebb4caSwyllys foundextn = FindExtn(extensions, oid);
219599ebb4caSwyllys
219699ebb4caSwyllys if (foundextn != NULL) {
219799ebb4caSwyllys ret = GetSequenceContents(
219899ebb4caSwyllys (char *)foundextn->BERvalue.Data,
219999ebb4caSwyllys foundextn->BERvalue.Length,
220099ebb4caSwyllys &olddata, &oldsize);
220199ebb4caSwyllys if (ret != KMF_OK)
220299ebb4caSwyllys goto out;
220399ebb4caSwyllys }
220499ebb4caSwyllys
220599ebb4caSwyllys /*
220699ebb4caSwyllys * Assume (!!) that the namedata given is already properly encoded.
220799ebb4caSwyllys */
220899ebb4caSwyllys if ((asn1 = kmfder_alloc()) == NULL)
220999ebb4caSwyllys return (KMF_ERR_MEMORY);
221099ebb4caSwyllys
221199ebb4caSwyllys if (kmfber_printf(asn1, "{") == -1) {
221299ebb4caSwyllys ret = KMF_ERR_ENCODING;
221399ebb4caSwyllys goto out;
221499ebb4caSwyllys }
221599ebb4caSwyllys
221699ebb4caSwyllys /* Write the old extension data first */
221799ebb4caSwyllys if (olddata != NULL && oldsize > 0) {
221899ebb4caSwyllys if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
221999ebb4caSwyllys ret = KMF_ERR_ENCODING;
222099ebb4caSwyllys goto out;
222199ebb4caSwyllys }
222299ebb4caSwyllys }
222399ebb4caSwyllys
222499ebb4caSwyllys /* Now add the new name to the list */
222599ebb4caSwyllys if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
222699ebb4caSwyllys ret = KMF_ERR_ENCODING;
222799ebb4caSwyllys goto out;
222899ebb4caSwyllys }
222999ebb4caSwyllys
223099ebb4caSwyllys /* Now close the sequence */
223199ebb4caSwyllys if (kmfber_printf(asn1, "}") == -1) {
223299ebb4caSwyllys ret = KMF_ERR_ENCODING;
223399ebb4caSwyllys goto out;
223499ebb4caSwyllys }
223599ebb4caSwyllys if (kmfber_flatten(asn1, &extdata) == -1) {
223699ebb4caSwyllys ret = KMF_ERR_ENCODING;
223799ebb4caSwyllys goto out;
223899ebb4caSwyllys }
223999ebb4caSwyllys
224099ebb4caSwyllys /*
224199ebb4caSwyllys * If we are just adding to an existing list of altNames,
224299ebb4caSwyllys * just replace the BER data associated with the found extension.
224399ebb4caSwyllys */
224499ebb4caSwyllys if (foundextn != NULL) {
224599ebb4caSwyllys free(foundextn->BERvalue.Data);
224699ebb4caSwyllys foundextn->critical = critical;
224799ebb4caSwyllys foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
224899ebb4caSwyllys foundextn->BERvalue.Length = extdata->bv_len;
224999ebb4caSwyllys } else {
225099ebb4caSwyllys subjAltName.critical = critical;
225199ebb4caSwyllys subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
225299ebb4caSwyllys subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
225399ebb4caSwyllys subjAltName.BERvalue.Length = extdata->bv_len;
225499ebb4caSwyllys ret = add_an_extension(extensions, &subjAltName);
225599ebb4caSwyllys if (ret != KMF_OK)
225699ebb4caSwyllys free(subjAltName.BERvalue.Data);
225799ebb4caSwyllys }
225899ebb4caSwyllys
225999ebb4caSwyllys free(extdata);
226099ebb4caSwyllys out:
226199ebb4caSwyllys if (olddata != NULL)
226299ebb4caSwyllys free(olddata);
226399ebb4caSwyllys
226430a5e8faSwyllys kmf_free_data(&dername);
226599ebb4caSwyllys if (ret != KMF_OK)
226630a5e8faSwyllys kmf_free_data(&subjAltName.extnId);
226799ebb4caSwyllys if (asn1 != NULL)
226899ebb4caSwyllys kmfber_free(asn1, 1);
226999ebb4caSwyllys return (ret);
227099ebb4caSwyllys }
227130a5e8faSwyllys
227230a5e8faSwyllys /*
227330a5e8faSwyllys * Search a list of attributes for one that matches the given type.
227430a5e8faSwyllys * Return a pointer into the attribute list. This does not
227530a5e8faSwyllys * return a copy of the value, it returns a reference into the
227630a5e8faSwyllys * given list.
227730a5e8faSwyllys */
227830a5e8faSwyllys int
kmf_find_attr(KMF_ATTR_TYPE type,KMF_ATTRIBUTE * attlist,int numattrs)227930a5e8faSwyllys kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
228030a5e8faSwyllys {
228130a5e8faSwyllys int i;
228230a5e8faSwyllys for (i = 0; i < numattrs; i++) {
228330a5e8faSwyllys if (attlist[i].type == type)
228430a5e8faSwyllys return (i);
228530a5e8faSwyllys }
228630a5e8faSwyllys return (-1);
228730a5e8faSwyllys }
228830a5e8faSwyllys
228930a5e8faSwyllys /*
229030a5e8faSwyllys * Verify that a given attribute is consistent with the
229130a5e8faSwyllys * "test" attribute.
229230a5e8faSwyllys */
229330a5e8faSwyllys static KMF_RETURN
verify_attribute(KMF_ATTRIBUTE * givenattr,KMF_ATTRIBUTE_TESTER * testattr)229430a5e8faSwyllys verify_attribute(KMF_ATTRIBUTE *givenattr,
229530a5e8faSwyllys KMF_ATTRIBUTE_TESTER *testattr)
229630a5e8faSwyllys {
229730a5e8faSwyllys /* A NULL pValue was found where one is required */
229830a5e8faSwyllys if (testattr->null_value_ok == FALSE &&
229930a5e8faSwyllys givenattr->pValue == NULL)
230030a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
230130a5e8faSwyllys
230230a5e8faSwyllys /* If the given valueLen is too small, return error */
230330a5e8faSwyllys if (givenattr->pValue != NULL &&
230430a5e8faSwyllys testattr->minlen > 0 &&
230530a5e8faSwyllys (givenattr->valueLen < testattr->minlen))
230630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
230730a5e8faSwyllys
230830a5e8faSwyllys /* If the given valueLen is too big, return error */
230930a5e8faSwyllys if (givenattr->pValue != NULL &&
231030a5e8faSwyllys testattr->maxlen > 0 &&
231130a5e8faSwyllys (givenattr->valueLen > testattr->maxlen))
231230a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
231330a5e8faSwyllys
231430a5e8faSwyllys return (KMF_OK);
231530a5e8faSwyllys }
231630a5e8faSwyllys
231730a5e8faSwyllys /*
231830a5e8faSwyllys * Given a set of required attribute tests and optional
231930a5e8faSwyllys * attributes, make sure that the actual attributes
232030a5e8faSwyllys * being tested (attrlist below) are allowed and are
232130a5e8faSwyllys * properly specified.
232230a5e8faSwyllys */
232330a5e8faSwyllys KMF_RETURN
test_attributes(int reqnum,KMF_ATTRIBUTE_TESTER * reqattrs,int optnum,KMF_ATTRIBUTE_TESTER * optattrs,int numattrs,KMF_ATTRIBUTE * attrlist)232430a5e8faSwyllys test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
232530a5e8faSwyllys int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
232630a5e8faSwyllys int numattrs, KMF_ATTRIBUTE *attrlist)
232730a5e8faSwyllys {
232830a5e8faSwyllys KMF_RETURN ret = KMF_OK;
232930a5e8faSwyllys int i, idx;
233030a5e8faSwyllys
233130a5e8faSwyllys /*
233230a5e8faSwyllys * If the caller didn't supply enough attributes,
233330a5e8faSwyllys * return an error.
233430a5e8faSwyllys */
233530a5e8faSwyllys if (numattrs < reqnum || attrlist == NULL)
233630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
233730a5e8faSwyllys
233830a5e8faSwyllys /*
233930a5e8faSwyllys * Make sure all required attrs are present and
234030a5e8faSwyllys * correct.
234130a5e8faSwyllys */
234230a5e8faSwyllys for (i = 0; i < reqnum && ret == KMF_OK; i++) {
234330a5e8faSwyllys idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
234430a5e8faSwyllys /* If a required attr is not found, return error */
234530a5e8faSwyllys if (idx == -1) {
234630a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
234730a5e8faSwyllys }
234830a5e8faSwyllys
234930a5e8faSwyllys ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
235030a5e8faSwyllys }
235130a5e8faSwyllys /*
235230a5e8faSwyllys * Now test the optional parameters.
235330a5e8faSwyllys */
235430a5e8faSwyllys for (i = 0; i < optnum && ret == KMF_OK; i++) {
235530a5e8faSwyllys idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
235630a5e8faSwyllys /* If a optional attr is not found, continue. */
235730a5e8faSwyllys if (idx == -1) {
235830a5e8faSwyllys continue;
235930a5e8faSwyllys }
236030a5e8faSwyllys
236130a5e8faSwyllys ret = verify_attribute(&attrlist[idx], &optattrs[i]);
236230a5e8faSwyllys }
236330a5e8faSwyllys
236430a5e8faSwyllys return (ret);
236530a5e8faSwyllys }
236630a5e8faSwyllys
236730a5e8faSwyllys /*
236830a5e8faSwyllys * Given an already allocated attribute list, insert
236930a5e8faSwyllys * the given attribute information at a specific index
237030a5e8faSwyllys * in the list.
237130a5e8faSwyllys */
237230a5e8faSwyllys void
kmf_set_attr_at_index(KMF_ATTRIBUTE * attlist,int index,KMF_ATTR_TYPE type,void * pValue,uint32_t len)237330a5e8faSwyllys kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
237430a5e8faSwyllys KMF_ATTR_TYPE type, void *pValue, uint32_t len)
237530a5e8faSwyllys {
237630a5e8faSwyllys if (attlist == NULL)
237730a5e8faSwyllys return;
237830a5e8faSwyllys
237930a5e8faSwyllys attlist[index].type = type;
238030a5e8faSwyllys attlist[index].pValue = pValue;
238130a5e8faSwyllys attlist[index].valueLen = len;
238230a5e8faSwyllys }
238330a5e8faSwyllys
238430a5e8faSwyllys /*
238530a5e8faSwyllys * Find an attribute matching a particular type and set
238630a5e8faSwyllys * the pValue and length fields to the given values.
238730a5e8faSwyllys */
238830a5e8faSwyllys KMF_RETURN
kmf_set_attr(KMF_ATTRIBUTE * attlist,int numattr,KMF_ATTR_TYPE type,void * pValue,uint32_t len)238930a5e8faSwyllys kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
239030a5e8faSwyllys KMF_ATTR_TYPE type, void *pValue, uint32_t len)
239130a5e8faSwyllys {
239230a5e8faSwyllys int idx;
239330a5e8faSwyllys if (attlist == NULL)
239430a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
239530a5e8faSwyllys
239630a5e8faSwyllys idx = kmf_find_attr(type, attlist, numattr);
239730a5e8faSwyllys if (idx == -1)
239830a5e8faSwyllys return (KMF_ERR_ATTR_NOT_FOUND);
239930a5e8faSwyllys
240030a5e8faSwyllys attlist[idx].type = type;
240130a5e8faSwyllys /* Assumes the attribute pValue can hold the result */
240230a5e8faSwyllys if (attlist[idx].pValue != NULL) {
240330a5e8faSwyllys if (attlist[idx].valueLen >= len)
240430a5e8faSwyllys (void) memcpy(attlist[idx].pValue, pValue, len);
240530a5e8faSwyllys else
240630a5e8faSwyllys return (KMF_ERR_BUFFER_SIZE);
240730a5e8faSwyllys }
240830a5e8faSwyllys attlist[idx].valueLen = len;
240930a5e8faSwyllys return (KMF_OK);
241030a5e8faSwyllys }
241130a5e8faSwyllys
241230a5e8faSwyllys /*
241330a5e8faSwyllys * Find a particular attribute in a list and return
241430a5e8faSwyllys * a pointer to its value.
241530a5e8faSwyllys */
241630a5e8faSwyllys void *
kmf_get_attr_ptr(KMF_ATTR_TYPE type,KMF_ATTRIBUTE * attlist,int numattrs)241730a5e8faSwyllys kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
241830a5e8faSwyllys int numattrs)
241930a5e8faSwyllys {
242030a5e8faSwyllys int i;
242130a5e8faSwyllys
242230a5e8faSwyllys i = kmf_find_attr(type, attlist, numattrs);
242330a5e8faSwyllys if (i == -1)
242430a5e8faSwyllys return (NULL);
242530a5e8faSwyllys
242630a5e8faSwyllys return (attlist[i].pValue);
242730a5e8faSwyllys }
242830a5e8faSwyllys
242930a5e8faSwyllys /*
243030a5e8faSwyllys * Find a particular attribute in a list and return
243130a5e8faSwyllys * the value and length values. Value and length
243230a5e8faSwyllys * may be NULL if the caller doesn't want their values
243330a5e8faSwyllys * to be filled in.
243430a5e8faSwyllys */
243530a5e8faSwyllys KMF_RETURN
kmf_get_attr(KMF_ATTR_TYPE type,KMF_ATTRIBUTE * attlist,int numattrs,void * outValue,uint32_t * outlen)243630a5e8faSwyllys kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
243730a5e8faSwyllys int numattrs, void *outValue, uint32_t *outlen)
243830a5e8faSwyllys {
243930a5e8faSwyllys int i;
244030a5e8faSwyllys uint32_t len = 0;
244130a5e8faSwyllys uint32_t *lenptr = outlen;
244230a5e8faSwyllys
244330a5e8faSwyllys if (lenptr == NULL)
244430a5e8faSwyllys lenptr = &len;
244530a5e8faSwyllys
244630a5e8faSwyllys i = kmf_find_attr(type, attlist, numattrs);
244730a5e8faSwyllys if (i == -1)
244830a5e8faSwyllys return (KMF_ERR_ATTR_NOT_FOUND);
244930a5e8faSwyllys
245030a5e8faSwyllys /* This assumes that the ptr passed in is pre-allocated space */
245130a5e8faSwyllys if (attlist[i].pValue != NULL && outValue != NULL) {
245230a5e8faSwyllys /*
245330a5e8faSwyllys * If the caller did not specify a length,
245430a5e8faSwyllys * assume "outValue" is big enough.
245530a5e8faSwyllys */
245630a5e8faSwyllys if (outlen != NULL) {
245730a5e8faSwyllys if (*outlen >= attlist[i].valueLen)
245830a5e8faSwyllys (void) memcpy(outValue, attlist[i].pValue,
245930a5e8faSwyllys attlist[i].valueLen);
246030a5e8faSwyllys else
246130a5e8faSwyllys return (KMF_ERR_BUFFER_SIZE);
246230a5e8faSwyllys } else {
246330a5e8faSwyllys (void) memcpy(outValue, attlist[i].pValue,
246430a5e8faSwyllys attlist[i].valueLen);
246530a5e8faSwyllys }
246630a5e8faSwyllys }
246730a5e8faSwyllys
246830a5e8faSwyllys if (outlen != NULL)
246930a5e8faSwyllys *outlen = attlist[i].valueLen;
247030a5e8faSwyllys return (KMF_OK);
247130a5e8faSwyllys }
247230a5e8faSwyllys
247330a5e8faSwyllys /*
247430a5e8faSwyllys * Utility routine to find a string type attribute, allocate it
247530a5e8faSwyllys * and return the value to the caller. This simplifies the
247630a5e8faSwyllys * operation by doing both "kmf_get_attr" calls and avoids
247730a5e8faSwyllys * duplicating this block of code in lots of places.
247830a5e8faSwyllys */
247930a5e8faSwyllys KMF_RETURN
kmf_get_string_attr(KMF_ATTR_TYPE type,KMF_ATTRIBUTE * attrlist,int numattrs,char ** outstr)248030a5e8faSwyllys kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
248130a5e8faSwyllys int numattrs, char **outstr)
248230a5e8faSwyllys {
248330a5e8faSwyllys KMF_RETURN rv;
248430a5e8faSwyllys uint32_t len;
248530a5e8faSwyllys
248630a5e8faSwyllys if (outstr == NULL)
248730a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
248830a5e8faSwyllys
248930a5e8faSwyllys if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
249030a5e8faSwyllys KMF_OK) {
249130a5e8faSwyllys *outstr = malloc(len + 1);
249230a5e8faSwyllys if ((*outstr) == NULL)
249330a5e8faSwyllys return (KMF_ERR_MEMORY);
249430a5e8faSwyllys (void) memset((*outstr), 0, len + 1);
249530a5e8faSwyllys rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
249630a5e8faSwyllys if (rv != KMF_OK) {
249730a5e8faSwyllys free(*outstr);
249830a5e8faSwyllys *outstr = NULL;
249930a5e8faSwyllys }
250030a5e8faSwyllys }
250130a5e8faSwyllys
250230a5e8faSwyllys return (rv);
250330a5e8faSwyllys }
250430a5e8faSwyllys
2505431deaa0Shylee
2506431deaa0Shylee void
free_entry(conf_entry_t * entry)2507431deaa0Shylee free_entry(conf_entry_t *entry)
2508431deaa0Shylee {
2509431deaa0Shylee if (entry == NULL)
2510431deaa0Shylee return;
2511431deaa0Shylee free(entry->keystore);
2512431deaa0Shylee free(entry->modulepath);
2513431deaa0Shylee free(entry->option);
2514431deaa0Shylee }
2515431deaa0Shylee
2516431deaa0Shylee void
free_entrylist(conf_entrylist_t * list)2517431deaa0Shylee free_entrylist(conf_entrylist_t *list)
2518431deaa0Shylee {
2519431deaa0Shylee conf_entrylist_t *next;
2520431deaa0Shylee
2521431deaa0Shylee while (list != NULL) {
2522431deaa0Shylee next = list->next;
2523431deaa0Shylee free_entry(list->entry);
2524431deaa0Shylee free(list);
2525431deaa0Shylee list = next;
2526431deaa0Shylee }
2527431deaa0Shylee }
2528431deaa0Shylee
2529431deaa0Shylee static KMF_RETURN
parse_entry(char * buf,conf_entry_t ** entry)2530431deaa0Shylee parse_entry(char *buf, conf_entry_t **entry)
2531431deaa0Shylee {
2532431deaa0Shylee KMF_RETURN ret = KMF_OK;
2533431deaa0Shylee conf_entry_t *tmp = NULL;
2534431deaa0Shylee char *token1;
2535431deaa0Shylee char *token2;
2536431deaa0Shylee char *token3;
2537431deaa0Shylee char *lasts;
2538431deaa0Shylee char *value;
2539431deaa0Shylee
2540431deaa0Shylee if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL)
2541431deaa0Shylee return (KMF_ERR_KMF_CONF);
2542431deaa0Shylee
2543431deaa0Shylee if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL)
2544431deaa0Shylee return (KMF_ERR_MEMORY);
2545431deaa0Shylee
2546431deaa0Shylee if ((tmp->keystore = strdup(token1)) == NULL) {
2547431deaa0Shylee ret = KMF_ERR_MEMORY;
2548431deaa0Shylee goto end;
2549431deaa0Shylee }
2550431deaa0Shylee
2551431deaa0Shylee if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) {
2552431deaa0Shylee ret = KMF_ERR_KMF_CONF;
2553431deaa0Shylee goto end;
2554431deaa0Shylee }
2555431deaa0Shylee
2556431deaa0Shylee /* need to get token3 first to satisfy nested strtok invocations */
2557431deaa0Shylee token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts);
2558431deaa0Shylee
2559431deaa0Shylee /* parse token2 */
2560431deaa0Shylee if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) {
2561431deaa0Shylee ret = KMF_ERR_KMF_CONF;
2562431deaa0Shylee goto end;
2563431deaa0Shylee }
2564431deaa0Shylee
2565431deaa0Shylee if (value = strpbrk(token2, SEP_EQUAL)) {
2566431deaa0Shylee value++; /* get rid of = */
2567431deaa0Shylee } else {
2568431deaa0Shylee ret = KMF_ERR_KMF_CONF;
2569431deaa0Shylee goto end;
2570431deaa0Shylee }
2571431deaa0Shylee
2572431deaa0Shylee if ((tmp->modulepath = strdup(value)) == NULL) {
2573431deaa0Shylee ret = KMF_ERR_MEMORY;
2574431deaa0Shylee goto end;
2575431deaa0Shylee }
2576431deaa0Shylee
2577431deaa0Shylee /* parse token3, if it exists */
2578431deaa0Shylee if (token3 != NULL) {
2579431deaa0Shylee if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION))
2580431deaa0Shylee != 0) {
2581431deaa0Shylee ret = KMF_ERR_KMF_CONF;
2582431deaa0Shylee goto end;
2583431deaa0Shylee }
2584431deaa0Shylee
2585431deaa0Shylee if (value = strpbrk(token3, SEP_EQUAL)) {
2586431deaa0Shylee value++; /* get rid of = */
2587431deaa0Shylee } else {
2588431deaa0Shylee ret = KMF_ERR_KMF_CONF;
2589431deaa0Shylee goto end;
2590431deaa0Shylee }
2591431deaa0Shylee
2592431deaa0Shylee if ((tmp->option = strdup(value)) == NULL) {
2593431deaa0Shylee ret = KMF_ERR_MEMORY;
2594431deaa0Shylee goto end;
2595431deaa0Shylee }
2596431deaa0Shylee }
2597431deaa0Shylee
2598431deaa0Shylee *entry = tmp;
2599431deaa0Shylee
2600431deaa0Shylee end:
2601431deaa0Shylee if (ret != KMF_OK) {
2602431deaa0Shylee free_entry(tmp);
2603431deaa0Shylee free(tmp);
2604431deaa0Shylee }
2605431deaa0Shylee return (ret);
2606431deaa0Shylee }
2607431deaa0Shylee
2608431deaa0Shylee
2609431deaa0Shylee conf_entry_t *
dup_entry(conf_entry_t * entry)2610431deaa0Shylee dup_entry(conf_entry_t *entry)
2611431deaa0Shylee {
2612431deaa0Shylee conf_entry_t *rtn_entry;
2613431deaa0Shylee
2614431deaa0Shylee if (entry == NULL)
2615431deaa0Shylee return (NULL);
2616431deaa0Shylee
2617431deaa0Shylee rtn_entry = malloc(sizeof (conf_entry_t));
2618431deaa0Shylee if (rtn_entry == NULL)
2619431deaa0Shylee return (NULL);
2620431deaa0Shylee
2621431deaa0Shylee if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL)
2622431deaa0Shylee goto out;
2623431deaa0Shylee
2624431deaa0Shylee if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL)
2625431deaa0Shylee goto out;
2626431deaa0Shylee
2627431deaa0Shylee if (entry->option != NULL &&
2628431deaa0Shylee (rtn_entry->option = strdup(entry->modulepath)) == NULL)
2629431deaa0Shylee goto out;
2630431deaa0Shylee
2631431deaa0Shylee return (rtn_entry);
2632431deaa0Shylee
2633431deaa0Shylee out:
2634431deaa0Shylee free_entry(rtn_entry);
2635431deaa0Shylee return (NULL);
2636431deaa0Shylee }
2637431deaa0Shylee
2638431deaa0Shylee
2639431deaa0Shylee /*
2640431deaa0Shylee * This function takes a keystore_name as input and returns
2641431deaa0Shylee * the KMF_KEYSTORE_TYPE value assigned to it. If the "option"
2642431deaa0Shylee * argument is not NULL, this function also returns the option string
2643431deaa0Shylee * if there is an option string for the plugin module.
2644431deaa0Shylee */
2645431deaa0Shylee KMF_RETURN
kmf_get_plugin_info(KMF_HANDLE_T handle,char * keystore_name,KMF_KEYSTORE_TYPE * kstype,char ** option)2646431deaa0Shylee kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name,
2647431deaa0Shylee KMF_KEYSTORE_TYPE *kstype, char **option)
2648431deaa0Shylee {
2649431deaa0Shylee KMF_RETURN ret = KMF_OK;
2650431deaa0Shylee conf_entrylist_t *phead = extra_plugin_list;
2651431deaa0Shylee boolean_t is_default = B_TRUE;
2652431deaa0Shylee
2653431deaa0Shylee /*
2654431deaa0Shylee * Although handle is not really used in the function, we will
2655431deaa0Shylee * check the handle to make sure that kmf_intialize() is called
2656431deaa0Shylee * before this function.
2657431deaa0Shylee */
2658431deaa0Shylee if (handle == NULL || keystore_name == NULL || kstype == NULL)
2659431deaa0Shylee return (KMF_ERR_BAD_PARAMETER);
2660431deaa0Shylee
2661431deaa0Shylee if (strcmp(keystore_name, "pkcs11") == 0) {
2662431deaa0Shylee *kstype = KMF_KEYSTORE_PK11TOKEN;
2663431deaa0Shylee } else if (strcmp(keystore_name, "file") == 0) {
2664431deaa0Shylee *kstype = KMF_KEYSTORE_OPENSSL;
2665431deaa0Shylee } else if (strcmp(keystore_name, "nss") == 0) {
2666431deaa0Shylee *kstype = KMF_KEYSTORE_NSS;
2667431deaa0Shylee } else {
2668431deaa0Shylee is_default = B_FALSE;
2669431deaa0Shylee }
2670431deaa0Shylee
2671431deaa0Shylee if (is_default) {
2672431deaa0Shylee if (option != NULL)
2673431deaa0Shylee *option = NULL;
2674431deaa0Shylee goto out;
2675431deaa0Shylee }
2676431deaa0Shylee
2677431deaa0Shylee /* Not a built-in plugin; check if it is in extra_plugin_list. */
2678431deaa0Shylee while (phead != NULL) {
2679431deaa0Shylee if (strcmp(phead->entry->keystore, keystore_name) == 0)
2680431deaa0Shylee break;
2681431deaa0Shylee phead = phead->next;
2682431deaa0Shylee }
2683431deaa0Shylee
2684431deaa0Shylee if (phead == NULL) {
2685431deaa0Shylee ret = KMF_ERR_PLUGIN_NOTFOUND;
2686431deaa0Shylee goto out;
2687431deaa0Shylee }
2688431deaa0Shylee
2689431deaa0Shylee /* found it */
2690431deaa0Shylee *kstype = phead->entry->kstype;
2691431deaa0Shylee if (option != NULL) {
2692431deaa0Shylee if (phead->entry->option == NULL)
2693431deaa0Shylee *option = NULL;
2694431deaa0Shylee else {
2695431deaa0Shylee *option = strdup(phead->entry->option);
2696431deaa0Shylee if (*option == NULL) {
2697431deaa0Shylee ret = KMF_ERR_MEMORY;
2698431deaa0Shylee goto out;
2699431deaa0Shylee }
2700431deaa0Shylee }
2701431deaa0Shylee }
2702431deaa0Shylee
2703431deaa0Shylee out:
2704431deaa0Shylee return (ret);
2705431deaa0Shylee }
2706431deaa0Shylee
2707431deaa0Shylee /*
2708431deaa0Shylee * Retrieve the non-default plugin list from the kmf.conf file.
2709431deaa0Shylee */
2710431deaa0Shylee KMF_RETURN
get_entrylist(conf_entrylist_t ** entlist)2711431deaa0Shylee get_entrylist(conf_entrylist_t **entlist)
2712431deaa0Shylee {
2713431deaa0Shylee KMF_RETURN rv = KMF_OK;
2714431deaa0Shylee FILE *pfile;
2715431deaa0Shylee conf_entry_t *entry;
2716431deaa0Shylee conf_entrylist_t *rtnlist = NULL;
2717431deaa0Shylee conf_entrylist_t *ptmp;
2718431deaa0Shylee conf_entrylist_t *pcur;
2719431deaa0Shylee char buffer[MAXPATHLEN];
2720431deaa0Shylee size_t len;
2721431deaa0Shylee
2722431deaa0Shylee if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) {
2723431deaa0Shylee cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF);
2724431deaa0Shylee return (KMF_ERR_KMF_CONF);
2725431deaa0Shylee }
2726431deaa0Shylee
2727431deaa0Shylee while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
2728431deaa0Shylee if (buffer[0] == '#' || buffer[0] == ' ' ||
2729431deaa0Shylee buffer[0] == '\n'|| buffer[0] == '\t') {
2730431deaa0Shylee continue; /* ignore comment lines */
2731431deaa0Shylee }
2732431deaa0Shylee
2733431deaa0Shylee len = strlen(buffer);
2734431deaa0Shylee if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
2735431deaa0Shylee len--;
2736431deaa0Shylee }
2737431deaa0Shylee buffer[len] = '\0';
2738431deaa0Shylee
2739431deaa0Shylee rv = parse_entry(buffer, &entry);
2740431deaa0Shylee if (rv != KMF_OK) {
2741431deaa0Shylee goto end;
2742431deaa0Shylee }
2743431deaa0Shylee
2744431deaa0Shylee if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) {
2745431deaa0Shylee rv = KMF_ERR_MEMORY;
2746431deaa0Shylee goto end;
2747431deaa0Shylee }
2748431deaa0Shylee ptmp->entry = entry;
2749431deaa0Shylee ptmp->next = NULL;
2750431deaa0Shylee
2751431deaa0Shylee if (rtnlist == NULL) {
2752431deaa0Shylee rtnlist = pcur = ptmp;
2753431deaa0Shylee } else {
2754431deaa0Shylee pcur->next = ptmp;
2755431deaa0Shylee pcur = ptmp;
2756431deaa0Shylee }
2757431deaa0Shylee }
2758431deaa0Shylee
2759431deaa0Shylee end:
2760431deaa0Shylee (void) fclose(pfile);
2761431deaa0Shylee
2762431deaa0Shylee if (rv == KMF_OK) {
2763431deaa0Shylee *entlist = rtnlist;
2764431deaa0Shylee } else if (rtnlist != NULL) {
2765431deaa0Shylee free_entrylist(rtnlist);
2766431deaa0Shylee *entlist = NULL;
2767431deaa0Shylee kstore_num = DEFAULT_KEYSTORE_NUM;
2768431deaa0Shylee }
2769431deaa0Shylee
2770431deaa0Shylee return (rv);
2771431deaa0Shylee }
2772431deaa0Shylee
2773431deaa0Shylee
2774431deaa0Shylee boolean_t
is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)2775431deaa0Shylee is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)
2776431deaa0Shylee {
2777431deaa0Shylee
2778431deaa0Shylee if (kstype > 0 && kstype <= kstore_num)
2779431deaa0Shylee return (B_TRUE);
2780431deaa0Shylee else
2781431deaa0Shylee return (B_FALSE);
2782431deaa0Shylee }
2783