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 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 * 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) 25190c85bf8Swyllys return (NULL); 25290c85bf8Swyllys 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 } 28690c85bf8Swyllys } 287431deaa0Shylee 288431deaa0Shylee ret = InitializePlugin(phead->entry->kstype, realpath, 289431deaa0Shylee &pluginrec); 290431deaa0Shylee goto out; 291431deaa0Shylee } 292431deaa0Shylee 293431deaa0Shylee out: 294431deaa0Shylee if (ret != KMF_OK || pluginrec == NULL) 295431deaa0Shylee /* No matching plugins found in the built-in list */ 296431deaa0Shylee return (NULL); 297431deaa0Shylee 298431deaa0Shylee ret = AddPlugin(handle, pluginrec); 299431deaa0Shylee if (ret != KMF_OK) { 300431deaa0Shylee DestroyPlugin(pluginrec); 301431deaa0Shylee pluginrec = NULL; 30290c85bf8Swyllys } 303431deaa0Shylee return (pluginrec); 30499ebb4caSwyllys } 30599ebb4caSwyllys 306431deaa0Shylee 30799ebb4caSwyllys static KMF_RETURN 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, 34230a5e8faSwyllys 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 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( 37430a5e8faSwyllys 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 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 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 42299ebb4caSwyllys Cleanup_PK11_Session(KMF_HANDLE_T handle) 42399ebb4caSwyllys { 42499ebb4caSwyllys if (handle != NULL) { 42599ebb4caSwyllys /* Close active session on a pkcs11 token */ 426*f810c7e5SToomas Soome if (handle->pk11handle != 0) { 42799ebb4caSwyllys (void) C_CloseSession(handle->pk11handle); 428*f810c7e5SToomas Soome handle->pk11handle = 0; 42999ebb4caSwyllys } 43099ebb4caSwyllys } 43199ebb4caSwyllys } 43299ebb4caSwyllys 43399ebb4caSwyllys KMF_RETURN 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 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); 56930a5e8faSwyllys } 57099ebb4caSwyllys } 57199ebb4caSwyllys 57299ebb4caSwyllys KMF_RETURN 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 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 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 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) { 6699b37d296Swyllys CLEAR_ERROR(handle, ret); 6709b37d296Swyllys if (ret != KMF_OK) 6719b37d296Swyllys 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 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 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 * 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 84808ec4bd3Shylee check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt) 84902744e81Swyllys { 8509b37d296Swyllys char *p; 851d00756ccSwyllys int i; 85202744e81Swyllys 85308ec4bd3Shylee if (buf == NULL) 85402744e81Swyllys return (FALSE); 85502744e81Swyllys 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"); 8689b37d296Swyllys while (p != NULL) { 8699b37d296Swyllys if (strstr(p, "-----BEGIN") != NULL) { 87008ec4bd3Shylee *fmt = KMF_FORMAT_PEM; 871d00756ccSwyllys /* Restore the buffer */ 872d00756ccSwyllys buf[strlen(p)] = '\n'; 8739b37d296Swyllys return (TRUE); 87402744e81Swyllys } 875d00756ccSwyllys buf[strlen(p)] = '\n'; 8769b37d296Swyllys 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 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 971d00756ccSwyllys KMF_RETURN 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 98999ebb4caSwyllys KMF_RETURN 99030a5e8faSwyllys kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt) 99199ebb4caSwyllys { 99299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 9936b35cb3cSRichard 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 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 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 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 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 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 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 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 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 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 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 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 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 124930a5e8faSwyllys kmf_free_str(char *pstr) 125099ebb4caSwyllys { 125199ebb4caSwyllys if (pstr != NULL) 125299ebb4caSwyllys free(pstr); 125399ebb4caSwyllys } 125499ebb4caSwyllys 125599ebb4caSwyllys void 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 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 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 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 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 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 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 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 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 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 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 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 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 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); 147099ebb4caSwyllys 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 }; 147899ebb4caSwyllys 147930a5e8faSwyllys int num_req_attrs = sizeof (required_attrs) / 148030a5e8faSwyllys sizeof (KMF_ATTRIBUTE_TESTER); 148199ebb4caSwyllys 148230a5e8faSwyllys if (handle == NULL) 148399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 148499ebb4caSwyllys 148530a5e8faSwyllys CLEAR_ERROR(handle, ret); 148630a5e8faSwyllys 148730a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs, 148830a5e8faSwyllys 0, NULL, num_args, attrlist); 148930a5e8faSwyllys 149030a5e8faSwyllys if (ret != KMF_OK) 149130a5e8faSwyllys return (ret); 149230a5e8faSwyllys 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 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); 154499ebb4caSwyllys 154530a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs, 154630a5e8faSwyllys 0, NULL, num_args, attrlist); 154799ebb4caSwyllys 154830a5e8faSwyllys if (ret != KMF_OK) 154930a5e8faSwyllys 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 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 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 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 1719d00756ccSwyllys static KMF_RETURN 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 173256664548SWyllys Ingersoll 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 */ 174856664548SWyllys Ingersoll 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) 176656664548SWyllys Ingersoll goto cleanup; 176756664548SWyllys Ingersoll 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) 177256664548SWyllys Ingersoll goto cleanup; 177356664548SWyllys Ingersoll if (kmfber_write(asn1, inst, strlen(inst), 0) != strlen(inst)) 177456664548SWyllys Ingersoll goto cleanup; 177556664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl", BER_GENERALSTRING, 177656664548SWyllys Ingersoll strlen(name)) == -1) 177756664548SWyllys Ingersoll goto cleanup; 177856664548SWyllys Ingersoll if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) 177956664548SWyllys Ingersoll 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 } 1787d00756ccSwyllys 178856664548SWyllys Ingersoll if (kmfber_printf(asn1, "}}") == -1) 1789d00756ccSwyllys goto cleanup; 179056664548SWyllys Ingersoll if (kmfber_flatten(asn1, &extdata) == -1) { 179156664548SWyllys Ingersoll rv = KMF_ERR_ENCODING; 179256664548SWyllys Ingersoll goto cleanup; 179356664548SWyllys Ingersoll } 179456664548SWyllys Ingersoll kmfber_free(asn1, 1); 179556664548SWyllys Ingersoll asn1 = NULL; 1796d00756ccSwyllys 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) 1805d00756ccSwyllys goto cleanup; 1806d00756ccSwyllys if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm)) 1807d00756ccSwyllys goto cleanup; 180856664548SWyllys Ingersoll if (kmfber_printf(asn1, "Tl", 0xA1, extdata->bv_len) == -1) 1809d00756ccSwyllys goto cleanup; 181056664548SWyllys Ingersoll if (kmfber_write(asn1, extdata->bv_val, 181156664548SWyllys Ingersoll extdata->bv_len, 0) != extdata->bv_len) 1812d00756ccSwyllys 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; 1819d00756ccSwyllys 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 */ 1835d00756ccSwyllys 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; 1851d00756ccSwyllys if (kmfber_flatten(asn1, &extdata) == -1) { 1852d00756ccSwyllys rv = KMF_ERR_ENCODING; 1853d00756ccSwyllys goto cleanup; 1854d00756ccSwyllys } 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 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 190999ebb4caSwyllys static KMF_RETURN 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 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, 202430a5e8faSwyllys 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 * 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 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 || 210030a5e8faSwyllys 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 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) * 214530a5e8faSwyllys (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, 215330a5e8faSwyllys 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 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; 21716b35cb3cSRichard 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( 219830a5e8faSwyllys (char *)foundextn->BERvalue.Data, 219930a5e8faSwyllys foundextn->BERvalue.Length, 220030a5e8faSwyllys &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 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 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 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 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 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 * 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 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 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 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 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 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 * 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 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 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 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