1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 * 24 */ 25 26 #include <stdio.h> 27 #include <dlfcn.h> 28 #include <link.h> 29 #include <fcntl.h> 30 #include <ctype.h> 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 #include <errno.h> 35 #include <sys/socket.h> 36 #include <netinet/in.h> 37 #include <arpa/inet.h> 38 #include <thread.h> 39 40 #include <ber_der.h> 41 #include <kmfapiP.h> 42 43 #include <pem_encode.h> 44 #include <rdn_parser.h> 45 #include <libxml2/libxml/uri.h> 46 #include <libgen.h> 47 #include <cryptoutil.h> 48 49 static uchar_t pkcs11_initialized = 0; 50 mutex_t init_lock = DEFAULTMUTEX; 51 extern int errno; 52 53 typedef struct { 54 KMF_RETURN code; 55 char *message; 56 } kmf_error_map; 57 58 static kmf_error_map kmf_errcodes[] = { 59 {KMF_OK, "KMF_OK"}, 60 {KMF_ERR_BAD_PARAMETER, "KMF_ERR_BAD_PARAMETER"}, 61 {KMF_ERR_BAD_KEY_FORMAT, "KMF_ERR_BAD_KEY_FORMAT"}, 62 {KMF_ERR_BAD_ALGORITHM, "KMF_ERR_BAD_ALGORITHM"}, 63 {KMF_ERR_MEMORY, "KMF_ERR_MEMORY"}, 64 {KMF_ERR_ENCODING, "KMF_ERR_ENCODING"}, 65 {KMF_ERR_PLUGIN_INIT, "KMF_ERR_PLUGIN_INIT"}, 66 {KMF_ERR_PLUGIN_NOTFOUND, "KMF_ERR_PLUGIN_NOTFOUND"}, 67 {KMF_ERR_INTERNAL, "KMF_ERR_INTERNAL"}, 68 {KMF_ERR_BAD_CERT_FORMAT, "KMF_ERR_BAD_CERT_FORMAT"}, 69 {KMF_ERR_KEYGEN_FAILED, "KMF_ERR_KEYGEN_FAILED"}, 70 {KMF_ERR_UNINITIALIZED, "KMF_ERR_UNINITIALIZED"}, 71 {KMF_ERR_ISSUER, "KMF_ERR_ISSUER"}, 72 {KMF_ERR_NOT_REVOKED, "KMF_ERR_NOT_REVOKED"}, 73 {KMF_ERR_CERT_NOT_FOUND, "KMF_ERR_CERT_NOT_FOUND"}, 74 {KMF_ERR_CRL_NOT_FOUND, "KMF_ERR_CRL_NOT_FOUND"}, 75 {KMF_ERR_RDN_PARSER, "KMF_ERR_RDN_PARSER"}, 76 {KMF_ERR_RDN_ATTR, "KMF_ERR_RDN_ATTR"}, 77 {KMF_ERR_SLOTNAME, "KMF_ERR_SLOTNAME"}, 78 {KMF_ERR_EMPTY_CRL, "KMF_ERR_EMPTY_CRL"}, 79 {KMF_ERR_BUFFER_SIZE, "KMF_ERR_BUFFER_SIZE"}, 80 {KMF_ERR_AUTH_FAILED, "KMF_ERR_AUTH_FAILED"}, 81 {KMF_ERR_TOKEN_SELECTED, "KMF_ERR_TOKEN_SELECTED"}, 82 {KMF_ERR_NO_TOKEN_SELECTED, "KMF_ERR_NO_TOKEN_SELECTED"}, 83 {KMF_ERR_TOKEN_NOT_PRESENT, "KMF_ERR_TOKEN_NOT_PRESENT"}, 84 {KMF_ERR_EXTENSION_NOT_FOUND, "KMF_ERR_EXTENSION_NOT_FOUND"}, 85 {KMF_ERR_POLICY_ENGINE, "KMF_ERR_POLICY_ENGINE"}, 86 {KMF_ERR_POLICY_DB_FORMAT, "KMF_ERR_POLICY_DB_FORMAT"}, 87 {KMF_ERR_POLICY_NOT_FOUND, "KMF_ERR_POLICY_NOT_FOUND"}, 88 {KMF_ERR_POLICY_DB_FILE, "KMF_ERR_POLICY_DB_FILE"}, 89 {KMF_ERR_POLICY_NAME, "KMF_ERR_POLICY_NAME"}, 90 {KMF_ERR_OCSP_POLICY, "KMF_ERR_OCSP_POLICY"}, 91 {KMF_ERR_TA_POLICY, "KMF_ERR_TA_POLICY"}, 92 {KMF_ERR_KEY_NOT_FOUND, "KMF_ERR_KEY_NOT_FOUND"}, 93 {KMF_ERR_OPEN_FILE, "KMF_ERR_OPEN_FILE"}, 94 {KMF_ERR_OCSP_BAD_ISSUER, "KMF_ERR_OCSP_BAD_ISSUER"}, 95 {KMF_ERR_OCSP_BAD_CERT, "KMF_ERR_OCSP_BAD_CERT"}, 96 {KMF_ERR_OCSP_CREATE_REQUEST, "KMF_ERR_OCSP_CREATE_REQUEST"}, 97 {KMF_ERR_CONNECT_SERVER, "KMF_ERR_CONNECT_SERVER"}, 98 {KMF_ERR_SEND_REQUEST, "KMF_ERR_SEND_REQUEST"}, 99 {KMF_ERR_OCSP_CERTID, "KMF_ERR_OCSP_CERTID"}, 100 {KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"}, 101 {KMF_ERR_OCSP_RESPONSE_STATUS, "KMF_ERR_OCSP_RESPONSE_STATUS"}, 102 {KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"}, 103 {KMF_ERR_OCSP_BAD_SIGNER, "KMF_ERR_OCSP_BAD_SIGNER"}, 104 {KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"}, 105 {KMF_ERR_OCSP_UNKNOWN_CERT, "KMF_ERR_OCSP_UNKNOWN_CERT"}, 106 {KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"}, 107 {KMF_ERR_BAD_HTTP_RESPONSE, "KMF_ERR_BAD_HTTP_RESPONSE"}, 108 {KMF_ERR_RECV_RESPONSE, "KMF_ERR_RECV_RESPONSE"}, 109 {KMF_ERR_RECV_TIMEOUT, "KMF_ERR_RECV_TIMEOUT"}, 110 {KMF_ERR_DUPLICATE_KEYFILE, "KMF_ERR_DUPLICATE_KEYFILE"}, 111 {KMF_ERR_AMBIGUOUS_PATHNAME, "KMF_ERR_AMBIGUOUS_PATHNAME"}, 112 {KMF_ERR_FUNCTION_NOT_FOUND, "KMF_ERR_FUNCTION_NOT_FOUND"}, 113 {KMF_ERR_PKCS12_FORMAT, "KMF_ERR_PKCS12_FORMAT"}, 114 {KMF_ERR_BAD_KEY_TYPE, "KMF_ERR_BAD_KEY_TYPE"}, 115 {KMF_ERR_BAD_KEY_CLASS, "KMF_ERR_BAD_KEY_CLASS"}, 116 {KMF_ERR_BAD_KEY_SIZE, "KMF_ERR_BAD_KEY_SIZE"}, 117 {KMF_ERR_BAD_HEX_STRING, "KMF_ERR_BAD_HEX_STRING"}, 118 {KMF_ERR_KEYUSAGE, "KMF_ERR_KEYUSAGE"}, 119 {KMF_ERR_VALIDITY_PERIOD, "KMF_ERR_VALIDITY_PERIOD"}, 120 {KMF_ERR_OCSP_REVOKED, "KMF_ERR_OCSP_REVOKED"}, 121 {KMF_ERR_CERT_MULTIPLE_FOUND, "KMF_ERR_CERT_MULTIPLE_FOUND"}, 122 {KMF_ERR_WRITE_FILE, "KMF_ERR_WRITE_FILE"}, 123 {KMF_ERR_BAD_URI, "KMF_ERR_BAD_URI"}, 124 {KMF_ERR_BAD_CRLFILE, "KMF_ERR_BAD_CRLFILE"}, 125 {KMF_ERR_BAD_CERTFILE, "KMF_ERR_BAD_CERTFILE"}, 126 {KMF_ERR_GETKEYVALUE_FAILED, "KMF_ERR_GETKEYVALUE_FAILED"}, 127 {KMF_ERR_BAD_KEYHANDLE, "KMF_ERR_BAD_KEYHANDLE"}, 128 {KMF_ERR_BAD_OBJECT_TYPE, "KMF_ERR_BAD_OBJECT_TYPE"}, 129 {KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"}, 130 {KMF_ERR_UNKNOWN_CSR_ATTRIBUTE, "KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"}, 131 {KMF_ERR_UNINITIALIZED_TOKEN, "KMF_ERR_UNINITIALIZED_TOKEN"}, 132 {KMF_ERR_INCOMPLETE_TBS_CERT, "KMF_ERR_INCOMPLETE_TBS_CERT"}, 133 {KMF_ERR_MISSING_ERRCODE, "KMF_ERR_MISSING_ERRCODE"}, 134 {KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"}, 135 {KMF_ERR_SENSITIVE_KEY, "KMF_ERR_SENSITIVE_KEY"}, 136 {KMF_ERR_UNEXTRACTABLE_KEY, "KMF_ERR_UNEXTRACTABLE_KEY"}, 137 {KMF_ERR_KEY_MISMATCH, "KMF_ERR_KEY_MISMATCH"}, 138 {KMF_ERR_ATTR_NOT_FOUND, "KMF_ERR_ATTR_NOT_FOUND"}, 139 {KMF_ERR_KMF_CONF, "KMF_ERR_KMF_CONF"} 140 }; 141 142 typedef struct { 143 KMF_KEYSTORE_TYPE kstype; 144 char *path; 145 boolean_t critical; 146 } KMF_PLUGIN_ITEM; 147 148 KMF_PLUGIN_ITEM plugin_list[] = { 149 {KMF_KEYSTORE_OPENSSL, KMF_PLUGIN_PATH "kmf_openssl.so.1", TRUE}, 150 {KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1", TRUE}, 151 {KMF_KEYSTORE_NSS, KMF_PLUGIN_PATH "kmf_nss.so.1", FALSE} 152 }; 153 154 155 156 static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **); 157 static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *); 158 static void free_extensions(KMF_X509_EXTENSIONS *extns); 159 static void DestroyPlugin(KMF_PLUGIN *); 160 161 #if defined(__sparcv9) 162 #define ISA_PATH "/sparcv9" 163 #elif defined(__sparc) 164 #define ISA_PATH "/" 165 #elif defined(__i386) 166 #define ISA_PATH "/" 167 #elif defined(__amd64) 168 #define ISA_PATH "/amd64" 169 #endif 170 171 #define DEFAULT_KEYSTORE_NUM 3 172 static int kstore_num = DEFAULT_KEYSTORE_NUM; 173 conf_entrylist_t *extra_plugin_list = NULL; 174 static boolean_t check_extra_plugin = B_FALSE; 175 mutex_t extra_plugin_lock = DEFAULTMUTEX; 176 177 KMF_RETURN 178 init_pk11() 179 { 180 (void) mutex_lock(&init_lock); 181 if (!pkcs11_initialized) { 182 CK_RV rv = C_Initialize(NULL); 183 if ((rv != CKR_OK) && 184 (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 185 (void) mutex_unlock(&init_lock); 186 return (KMF_ERR_UNINITIALIZED); 187 } else { 188 pkcs11_initialized = 1; 189 } 190 } 191 (void) mutex_unlock(&init_lock); 192 return (KMF_OK); 193 } 194 195 /* 196 * Private method for searching the plugin list for the correct 197 * Plugin to use. 198 */ 199 KMF_PLUGIN * 200 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype) 201 { 202 KMF_PLUGIN_LIST *node; 203 KMF_RETURN ret = KMF_OK; 204 KMF_PLUGIN *pluginrec = NULL; 205 206 if (handle == NULL) 207 return (NULL); 208 209 node = handle->plugins; 210 211 /* See if the desired plugin was already initialized. */ 212 while (node != NULL && node->plugin->type != kstype) 213 node = node->next; 214 215 if (node != NULL) 216 return (node->plugin); 217 218 /* The plugin was not found, try to initialize it here. */ 219 if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) { 220 int i; 221 int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM); 222 for (i = 0; i < numitems; i++) { 223 if (plugin_list[i].kstype == kstype) { 224 ret = InitializePlugin(plugin_list[i].kstype, 225 plugin_list[i].path, &pluginrec); 226 break; 227 } 228 } 229 230 goto out; 231 232 } else { 233 /* 234 * Not a built-in plugin. Check if it is in the 235 * extra_plugin_list. If it is, try to initialize it here. 236 */ 237 conf_entrylist_t *phead = extra_plugin_list; 238 char realpath[MAXPATHLEN]; 239 240 while (phead != NULL) { 241 if (phead->entry->kstype == kstype) 242 break; 243 else 244 phead = phead->next; 245 } 246 247 if (phead == NULL) 248 return (NULL); 249 250 /* 251 * Get the absolute path of the module. 252 * - If modulepath is not a full path, then prepend it 253 * with KMF_PLUGIN_PATH. 254 * - If modulepath is a full path and contain $ISA, then 255 * subsitute the architecture dependent path. 256 */ 257 (void) memset(realpath, 0, sizeof (realpath)); 258 if (strncmp(phead->entry->modulepath, "/", 1) != 0) { 259 (void) snprintf(realpath, MAXPATHLEN, "%s%s", 260 KMF_PLUGIN_PATH, phead->entry->modulepath); 261 } else { 262 char *buf = phead->entry->modulepath; 263 char *isa; 264 265 if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { 266 char *isa_str; 267 268 (void) strncpy(realpath, buf, isa - buf); 269 isa_str = strdup(ISA_PATH); 270 if (isa_str == NULL) /* not enough memory */ 271 return (NULL); 272 273 (void) strncat(realpath, isa_str, 274 strlen(isa_str)); 275 free(isa_str); 276 277 isa += strlen(PKCS11_ISA); 278 (void) strlcat(realpath, isa, MAXPATHLEN); 279 } else { 280 (void) snprintf(realpath, MAXPATHLEN, "%s", 281 phead->entry->modulepath); 282 } 283 } 284 285 ret = InitializePlugin(phead->entry->kstype, realpath, 286 &pluginrec); 287 goto out; 288 } 289 290 out: 291 if (ret != KMF_OK || pluginrec == NULL) 292 /* No matching plugins found in the built-in list */ 293 return (NULL); 294 295 ret = AddPlugin(handle, pluginrec); 296 if (ret != KMF_OK) { 297 DestroyPlugin(pluginrec); 298 pluginrec = NULL; 299 } 300 return (pluginrec); 301 } 302 303 304 static KMF_RETURN 305 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin) 306 { 307 KMF_PLUGIN *p = NULL; 308 KMF_PLUGIN_FUNCLIST *(*sym)(); 309 310 if (path == NULL || plugin == NULL) 311 return (KMF_ERR_BAD_PARAMETER); 312 313 *plugin = NULL; 314 315 p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN)); 316 if (p == NULL) 317 return (KMF_ERR_MEMORY); 318 319 p->type = kstype; 320 p->path = strdup(path); 321 if (p->path == NULL) { 322 free(p); 323 return (KMF_ERR_MEMORY); 324 } 325 /* 326 * Do not use RTLD_GROUP here, or this will cause a circular 327 * dependency when kmf_pkcs11.so.1 gets its PKCS#11 functions 328 * from libpkcs11.so.1 when kmf is used via libelfsign.so.1 329 * called from kcfd. 330 */ 331 p->dldesc = dlopen(path, RTLD_LAZY | RTLD_PARENT); 332 if (p->dldesc == NULL) { 333 free(p->path); 334 free(p); 335 return (KMF_ERR_PLUGIN_INIT); 336 } 337 338 sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc, 339 KMF_PLUGIN_INIT_SYMBOL); 340 if (sym == NULL) { 341 (void) dlclose(p->dldesc); 342 free(p->path); 343 free(p); 344 return (KMF_ERR_PLUGIN_INIT); 345 } 346 347 /* Get the function list */ 348 if ((p->funclist = (*sym)()) == NULL) { 349 (void) dlclose(p->dldesc); 350 free(p->path); 351 free(p); 352 return (KMF_ERR_PLUGIN_INIT); 353 } 354 355 *plugin = p; 356 357 return (KMF_OK); 358 } 359 360 static KMF_RETURN 361 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin) 362 { 363 KMF_PLUGIN_LIST *n; 364 365 if (handle == NULL || plugin == NULL) 366 return (KMF_ERR_BAD_PARAMETER); 367 368 /* If the head is NULL, create it */ 369 if (handle->plugins == NULL) { 370 handle->plugins = (KMF_PLUGIN_LIST *)malloc( 371 sizeof (KMF_PLUGIN_LIST)); 372 if (handle->plugins == NULL) 373 return (KMF_ERR_MEMORY); 374 handle->plugins->plugin = plugin; 375 handle->plugins->next = NULL; 376 } else { 377 /* walk the list to find the tail */ 378 n = handle->plugins; 379 while (n->next != NULL) 380 n = n->next; 381 n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST)); 382 if (n->next == NULL) 383 return (KMF_ERR_MEMORY); 384 385 n->next->plugin = plugin; 386 n->next->next = NULL; 387 } 388 return (0); 389 } 390 391 static void 392 DestroyPlugin(KMF_PLUGIN *plugin) 393 { 394 if (plugin) { 395 if (plugin->path) 396 free(plugin->path); 397 free(plugin); 398 } 399 } 400 401 static void 402 Cleanup_KMF_Handle(KMF_HANDLE_T handle) 403 { 404 if (handle != NULL) { 405 while (handle->plugins != NULL) { 406 KMF_PLUGIN_LIST *next = handle->plugins->next; 407 408 DestroyPlugin(handle->plugins->plugin); 409 free(handle->plugins); 410 handle->plugins = next; 411 } 412 kmf_free_policy_record(handle->policy); 413 free(handle->policy); 414 } 415 free(handle); 416 } 417 418 void 419 Cleanup_PK11_Session(KMF_HANDLE_T handle) 420 { 421 if (handle != NULL) { 422 /* Close active session on a pkcs11 token */ 423 if (handle->pk11handle != NULL) { 424 (void) C_CloseSession(handle->pk11handle); 425 handle->pk11handle = NULL; 426 } 427 } 428 } 429 430 KMF_RETURN 431 kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname) 432 { 433 KMF_RETURN ret = KMF_OK; 434 KMF_HANDLE *handle = NULL; 435 436 if (outhandle == NULL) 437 return (KMF_ERR_BAD_PARAMETER); 438 439 *outhandle = NULL; 440 handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE)); 441 if (handle == NULL) 442 return (KMF_ERR_MEMORY); 443 444 (void) memset(handle, 0, sizeof (KMF_HANDLE)); 445 handle->plugins = NULL; 446 447 /* 448 * When this function is called the first time, get the additional 449 * plugins from the config file. 450 */ 451 (void) mutex_lock(&extra_plugin_lock); 452 if (!check_extra_plugin) { 453 454 ret = get_entrylist(&extra_plugin_list); 455 check_extra_plugin = B_TRUE; 456 457 /* 458 * Assign the kstype number to the additional plugins here. 459 * The global kstore_num will be protected by the mutex lock. 460 */ 461 if (ret == KMF_OK) { 462 conf_entrylist_t *phead = extra_plugin_list; 463 while (phead != NULL) { 464 phead->entry->kstype = ++kstore_num; 465 phead = phead->next; 466 } 467 } 468 469 /* 470 * If the KMF configuration file does not exist or cannot be 471 * parsed correctly, we will give a warning in syslog and 472 * continue on as there is no extra plugins in the system. 473 */ 474 if (ret == KMF_ERR_KMF_CONF) { 475 cryptoerror(LOG_WARNING, "KMF was unable to parse " 476 "the private KMF config file.\n"); 477 ret = KMF_OK; 478 } 479 480 if (ret != KMF_OK) { 481 (void) mutex_unlock(&extra_plugin_lock); 482 goto errout; 483 } 484 } 485 (void) mutex_unlock(&extra_plugin_lock); 486 487 /* Initialize the handle with the policy */ 488 ret = kmf_set_policy((void *)handle, 489 policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile, 490 policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname); 491 if (ret != KMF_OK) 492 goto errout; 493 494 CLEAR_ERROR(handle, ret); 495 errout: 496 if (ret != KMF_OK) { 497 Cleanup_KMF_Handle(handle); 498 handle = NULL; 499 } 500 501 *outhandle = (KMF_HANDLE_T)handle; 502 return (ret); 503 } 504 505 KMF_RETURN 506 kmf_configure_keystore(KMF_HANDLE_T handle, 507 int num_args, 508 KMF_ATTRIBUTE *attrlist) 509 { 510 KMF_RETURN ret = KMF_OK; 511 KMF_PLUGIN *plugin; 512 KMF_KEYSTORE_TYPE kstype; 513 uint32_t len; 514 515 KMF_ATTRIBUTE_TESTER required_attrs[] = { 516 {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}, 517 }; 518 519 int num_req_attrs = sizeof (required_attrs) / 520 sizeof (KMF_ATTRIBUTE_TESTER); 521 522 if (handle == NULL) 523 return (KMF_ERR_BAD_PARAMETER); 524 525 CLEAR_ERROR(handle, ret); 526 527 ret = test_attributes(num_req_attrs, required_attrs, 528 0, NULL, num_args, attrlist); 529 530 if (ret != KMF_OK) 531 return (ret); 532 533 len = sizeof (kstype); 534 ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args, 535 &kstype, &len); 536 if (ret != KMF_OK) 537 return (ret); 538 539 plugin = FindPlugin(handle, kstype); 540 if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) { 541 return (plugin->funclist->ConfigureKeystore(handle, num_args, 542 attrlist)); 543 } else { 544 /* return KMF_OK, if the plugin does not have an entry */ 545 return (KMF_OK); 546 } 547 } 548 549 KMF_RETURN 550 kmf_finalize(KMF_HANDLE_T handle) 551 { 552 KMF_RETURN ret = KMF_OK; 553 554 CLEAR_ERROR(handle, ret); 555 if (ret != KMF_OK) 556 return (ret); 557 558 if (pkcs11_initialized) { 559 Cleanup_PK11_Session(handle); 560 } 561 Cleanup_KMF_Handle(handle); 562 563 return (ret); 564 } 565 566 KMF_RETURN 567 kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg) 568 { 569 KMF_RETURN ret = KMF_OK; 570 int i, maxerr; 571 572 if (errmsg == NULL) 573 return (KMF_ERR_BAD_PARAMETER); 574 575 *errmsg = NULL; 576 maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map); 577 578 for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++) 579 /* empty body */ 580 ; 581 582 if (i == maxerr) 583 return (KMF_ERR_MISSING_ERRCODE); 584 else { 585 *errmsg = strdup(kmf_errcodes[i].message); 586 if ((*errmsg) == NULL) 587 return (KMF_ERR_MEMORY); 588 } 589 return (ret); 590 } 591 592 KMF_RETURN 593 kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr) 594 { 595 KMF_RETURN ret = KMF_OK; 596 KMF_PLUGIN *plugin; 597 598 if (handle == NULL || msgstr == NULL) 599 return (KMF_ERR_BAD_PARAMETER); 600 601 *msgstr = NULL; 602 603 if (handle->lasterr.errcode == 0) { 604 return (KMF_ERR_MISSING_ERRCODE); 605 } 606 607 if (handle->lasterr.kstype == -1) { /* System error */ 608 char *str = strerror(handle->lasterr.errcode); 609 if (str != NULL) { 610 *msgstr = strdup(str); 611 if ((*msgstr) == NULL) 612 return (KMF_ERR_MEMORY); 613 } 614 return (KMF_OK); 615 } 616 617 plugin = FindPlugin(handle, handle->lasterr.kstype); 618 if (plugin == NULL) 619 return (KMF_ERR_PLUGIN_NOTFOUND); 620 621 if (plugin->funclist->GetErrorString != NULL) { 622 ret = plugin->funclist->GetErrorString(handle, msgstr); 623 } else { 624 return (KMF_ERR_FUNCTION_NOT_FOUND); 625 } 626 627 return (ret); 628 } 629 630 631 #define SET_SYS_ERROR(h, c) if (h) {\ 632 h->lasterr.kstype = -1;\ 633 h->lasterr.errcode = c;\ 634 } 635 636 KMF_RETURN 637 kmf_read_input_file(KMF_HANDLE_T handle, char *filename, KMF_DATA *pdata) 638 { 639 struct stat s; 640 long nread, total = 0; 641 int fd; 642 unsigned char *buf = NULL; 643 KMF_RETURN ret; 644 645 if (handle) { 646 CLEAR_ERROR(handle, ret); 647 if (ret != KMF_OK) 648 return (ret); 649 } 650 651 if (filename == NULL || pdata == NULL) { 652 return (KMF_ERR_BAD_PARAMETER); 653 } 654 655 if ((fd = open(filename, O_RDONLY)) < 0) { 656 SET_SYS_ERROR(handle, errno); 657 return (KMF_ERR_OPEN_FILE); 658 } 659 660 if (fstat(fd, &s) < 0) { 661 SET_SYS_ERROR(handle, errno); 662 (void) close(fd); 663 return (KMF_ERR_OPEN_FILE); 664 } 665 666 if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) { 667 (void) close(fd); 668 return (KMF_ERR_MEMORY); 669 } 670 671 do { 672 nread = read(fd, buf+total, s.st_size-total); 673 if (nread < 0) { 674 SET_SYS_ERROR(handle, errno); 675 (void) close(fd); 676 free(buf); 677 return (KMF_ERR_INTERNAL); 678 } 679 total += nread; 680 } while (total < s.st_size); 681 682 pdata->Data = buf; 683 pdata->Length = s.st_size; 684 (void) close(fd); 685 return (KMF_OK); 686 } 687 688 /* 689 * 690 * Name: kmf_der_to_pem 691 * 692 * Description: 693 * Function for converting DER encoded format to PEM encoded format 694 * 695 * Parameters: 696 * type(input) - CERTIFICATE or CSR 697 * data(input) - pointer to the DER encoded data 698 * len(input) - length of input data 699 * out(output) - contains the output buffer address to be returned 700 * outlen(output) - pointer to the returned output length 701 * 702 * Returns: 703 * A KMF_RETURN value indicating success or specifying a particular 704 * error condition. 705 * The value KMF_OK indicates success. All other values represent 706 * an error condition. 707 * 708 */ 709 KMF_RETURN 710 kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data, 711 int len, unsigned char **out, int *outlen) 712 { 713 714 KMF_RETURN err; 715 if (data == NULL || out == NULL || outlen == NULL) 716 return (KMF_ERR_BAD_PARAMETER); 717 718 err = Der2Pem(type, data, len, out, outlen); 719 return (err); 720 721 } 722 723 /* 724 * 725 * Name: kmf_pem_to_der 726 * 727 * Description: 728 * Function for converting PEM encoded format to DER encoded format 729 * 730 * Parameters: 731 * in(input) - pointer to the PEM encoded data 732 * inlen(input) - length of input data 733 * out(output) - contains the output buffer address to be returned 734 * outlen(output) - pointer to the returned output length 735 * 736 * Returns: 737 * A KMF_RETURN value indicating success or specifying a particular 738 * error condition. 739 * The value KMF_OK indicates success. All other values represent 740 * an error condition. 741 * 742 */ 743 KMF_RETURN 744 kmf_pem_to_der(unsigned char *in, int inlen, 745 unsigned char **out, int *outlen) 746 { 747 KMF_RETURN err; 748 if (in == NULL || out == NULL || outlen == NULL) 749 return (KMF_ERR_BAD_PARAMETER); 750 751 err = Pem2Der(in, inlen, out, outlen); 752 return (err); 753 } 754 755 char * 756 kmf_oid_to_string(KMF_OID *oid) 757 { 758 char numstr[128]; 759 uint32_t number; 760 int numshift; 761 uint32_t i, string_length; 762 uchar_t *cp; 763 char *bp; 764 765 /* First determine the size of the string */ 766 string_length = 0; 767 number = 0; 768 numshift = 0; 769 cp = (unsigned char *)oid->Data; 770 771 number = (uint32_t)cp[0]; 772 (void) sprintf(numstr, "%d ", number/40); 773 774 string_length += strlen(numstr); 775 (void) sprintf(numstr, "%d ", number%40); 776 777 string_length += strlen(numstr); 778 779 for (i = 1; i < oid->Length; i++) { 780 if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) { 781 number = (number << 7) | (cp[i] & 0x7f); 782 numshift += 7; 783 } else { 784 return (NULL); 785 } 786 787 if ((cp[i] & 0x80) == 0) { 788 (void) sprintf(numstr, "%d ", number); 789 string_length += strlen(numstr); 790 number = 0; 791 numshift = 0; 792 } 793 } 794 /* 795 * If we get here, we've calculated the length of "n n n ... n ". Add 4 796 * here for "{ " and "}\0". 797 */ 798 string_length += 4; 799 if ((bp = (char *)malloc(string_length))) { 800 number = (uint32_t)cp[0]; 801 802 (void) sprintf(numstr, "%d.", number/40); 803 (void) strcpy(bp, numstr); 804 805 (void) sprintf(numstr, "%d.", number%40); 806 (void) strcat(bp, numstr); 807 808 number = 0; 809 cp = (unsigned char *) oid->Data; 810 for (i = 1; i < oid->Length; i++) { 811 number = (number << 7) | (cp[i] & 0x7f); 812 if ((cp[i] & 0x80) == 0) { 813 (void) sprintf(numstr, "%d", number); 814 (void) strcat(bp, numstr); 815 number = 0; 816 if (i+1 < oid->Length) 817 (void) strcat(bp, "."); 818 } 819 } 820 } 821 return (bp); 822 } 823 824 static boolean_t 825 check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt) 826 { 827 char *p; 828 int i; 829 830 if (buf == NULL) 831 return (FALSE); 832 833 for (i = 0; i < 8 && isascii(buf[i]); i++) 834 /* loop to make sure this is ascii */; 835 if (i != 8) 836 return (FALSE); 837 838 if (memcmp(buf, "Bag Attr", 8) == 0) { 839 *fmt = KMF_FORMAT_PEM_KEYPAIR; 840 return (TRUE); 841 } 842 843 /* Look for "-----BEGIN" right after a newline */ 844 p = strtok((char *)buf, "\n"); 845 while (p != NULL) { 846 if (strstr(p, "-----BEGIN") != NULL) { 847 *fmt = KMF_FORMAT_PEM; 848 /* Restore the buffer */ 849 buf[strlen(p)] = '\n'; 850 return (TRUE); 851 } 852 buf[strlen(p)] = '\n'; 853 p = strtok(NULL, "\n"); 854 } 855 return (FALSE); 856 } 857 858 859 static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03}; 860 static unsigned char pkcs12_oid[11] = 861 {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01}; 862 863 /* 864 * This function takes a BER encoded string as input and checks the version 865 * and the oid in the the top-level ASN.1 structure to see if it complies to 866 * the PKCS#12 Syntax. 867 */ 868 static boolean_t 869 check_for_pkcs12(uchar_t *buf, int buf_len) 870 { 871 int index = 0; 872 int length_octets; 873 874 if (buf == NULL || buf_len <= 0) 875 return (FALSE); 876 877 /* 878 * The top level structure for a PKCS12 string: 879 * 880 * PFX ::= SEQUENCE { 881 * version INTEGER {v3(3)}(v3,...) 882 * authSafe ContentInfo 883 * macData MacData OPTIONAL 884 * } 885 * 886 * ContentInfo 887 * FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549) 888 * pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)} 889 * 890 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2 891 * sequences up to the oid part is as following: 892 * 893 * SEQUENCE { 894 * INTEGER 3 895 * SEQUENCE { 896 * OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) 897 */ 898 899 /* 900 * Check the first sequence and calculate the number of bytes used 901 * to store the length. 902 */ 903 if (buf[index++] != 0x30) 904 return (FALSE); 905 906 if (buf[index] & 0x80) { 907 length_octets = buf[index++] & 0x0F; /* long form */ 908 } else { 909 length_octets = 1; /* short form */ 910 } 911 912 index += length_octets; 913 if (index >= buf_len) 914 return (FALSE); 915 916 /* Skip the length octets and check the pkcs12 version */ 917 if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0) 918 return (FALSE); 919 920 index += sizeof (pkcs12_version); 921 if (index >= buf_len) 922 return (FALSE); 923 924 /* 925 * Check the 2nd sequence and calculate the number of bytes used 926 * to store the length. 927 */ 928 if ((buf[index++] & 0xFF) != 0x30) 929 return (FALSE); 930 931 if (buf[index] & 0x80) { 932 length_octets = buf[index++] & 0x0F; 933 } else { 934 length_octets = 1; 935 } 936 937 index += length_octets; 938 if (index + sizeof (pkcs12_oid) >= buf_len) 939 return (FALSE); 940 941 /* Skip the length octets and check the oid */ 942 if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0) 943 return (FALSE); 944 else 945 return (TRUE); 946 } 947 948 KMF_RETURN 949 kmf_get_data_format(KMF_DATA *data, KMF_ENCODE_FORMAT *fmt) 950 { 951 uchar_t *buf = data->Data; 952 953 if (check_for_pkcs12(buf, data->Length) == TRUE) { 954 *fmt = KMF_FORMAT_PKCS12; 955 } else if (buf[0] == 0x30 && (buf[1] & 0x80)) { 956 /* It is most likely a generic ASN.1 encoded file */ 957 *fmt = KMF_FORMAT_ASN1; 958 } else if (check_for_pem(buf, fmt) != TRUE) { 959 /* Cannot determine this file format */ 960 *fmt = KMF_FORMAT_UNDEF; 961 return (KMF_ERR_ENCODING); 962 } 963 return (KMF_OK); 964 } 965 966 KMF_RETURN 967 kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt) 968 { 969 KMF_RETURN ret = KMF_OK; 970 KMF_DATA filebuf = {NULL, 0}; 971 972 if (filename == NULL || !strlen(filename) || fmt == NULL) 973 return (KMF_ERR_BAD_PARAMETER); 974 975 *fmt = 0; 976 ret = kmf_read_input_file(NULL, filename, &filebuf); 977 if (ret != KMF_OK) 978 return (ret); 979 980 if (filebuf.Length < 8) { 981 ret = KMF_ERR_ENCODING; /* too small */ 982 goto end; 983 } 984 985 ret = kmf_get_data_format(&filebuf, fmt); 986 end: 987 kmf_free_data(&filebuf); 988 return (ret); 989 } 990 991 KMF_RETURN 992 kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes, 993 size_t *outlen) 994 { 995 KMF_RETURN ret = KMF_OK; 996 unsigned char *buf = NULL; 997 int len, stringlen; 998 int i; 999 unsigned char ch; 1000 1001 if (hexstr == NULL) { 1002 return (KMF_ERR_BAD_PARAMETER); 1003 } 1004 1005 if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X'))) 1006 hexstr += 2; 1007 1008 for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++) 1009 /* empty body */ 1010 ; 1011 /* 1012 * If all the characters are not legitimate hex chars, 1013 * return an error. 1014 */ 1015 if (i != strlen((char *)hexstr)) 1016 return (KMF_ERR_BAD_HEX_STRING); 1017 stringlen = i; 1018 len = (i / 2) + (i % 2); 1019 1020 buf = malloc(len); 1021 if (buf == NULL) { 1022 return (KMF_ERR_MEMORY); 1023 } 1024 (void) memset(buf, 0, len); 1025 1026 for (i = 0; i < stringlen; i++) { 1027 ch = (unsigned char) *hexstr; 1028 hexstr++; 1029 if ((ch >= '0') && (ch <= '9')) 1030 ch -= '0'; 1031 else if ((ch >= 'A') && (ch <= 'F')) 1032 ch = ch - 'A' + 10; 1033 else if ((ch >= 'a') && (ch <= 'f')) 1034 ch = ch - 'a' + 10; 1035 else { 1036 ret = KMF_ERR_BAD_HEX_STRING; 1037 goto out; 1038 } 1039 1040 if (i & 1) { 1041 buf[i/2] |= ch; 1042 } else { 1043 buf[i/2] = (ch << 4); 1044 } 1045 } 1046 1047 *bytes = buf; 1048 *outlen = len; 1049 out: 1050 if (buf != NULL && ret != KMF_OK) { 1051 free(buf); 1052 } 1053 return (ret); 1054 } 1055 1056 void 1057 kmf_free_dn(KMF_X509_NAME *name) 1058 { 1059 KMF_X509_RDN *newrdn = NULL; 1060 KMF_X509_TYPE_VALUE_PAIR *av = NULL; 1061 int i, j; 1062 1063 if (name && name->numberOfRDNs) { 1064 for (i = 0; i < name->numberOfRDNs; i++) { 1065 newrdn = &name->RelativeDistinguishedName[i]; 1066 for (j = 0; j < newrdn->numberOfPairs; j++) { 1067 av = &newrdn->AttributeTypeAndValue[j]; 1068 kmf_free_data(&av->type); 1069 kmf_free_data(&av->value); 1070 } 1071 free(newrdn->AttributeTypeAndValue); 1072 newrdn->numberOfPairs = 0; 1073 newrdn->AttributeTypeAndValue = NULL; 1074 } 1075 free(name->RelativeDistinguishedName); 1076 name->numberOfRDNs = 0; 1077 name->RelativeDistinguishedName = NULL; 1078 } 1079 } 1080 1081 void 1082 kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert) 1083 { 1084 KMF_PLUGIN *plugin; 1085 KMF_RETURN ret; 1086 1087 CLEAR_ERROR(handle, ret); 1088 if (ret != KMF_OK) 1089 return; 1090 1091 if (kmf_cert == NULL) 1092 return; 1093 1094 plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type); 1095 1096 if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) { 1097 plugin->funclist->FreeKMFCert(handle, kmf_cert); 1098 } 1099 } 1100 1101 void 1102 kmf_free_data(KMF_DATA *datablock) 1103 { 1104 if (datablock != NULL && datablock->Data != NULL) { 1105 free(datablock->Data); 1106 datablock->Data = NULL; 1107 datablock->Length = 0; 1108 } 1109 } 1110 1111 void 1112 kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid) 1113 { 1114 if (algoid == NULL) 1115 return; 1116 kmf_free_data(&algoid->algorithm); 1117 kmf_free_data(&algoid->parameters); 1118 } 1119 1120 void 1121 kmf_free_extn(KMF_X509_EXTENSION *exptr) 1122 { 1123 if (exptr == NULL) 1124 return; 1125 1126 kmf_free_data((KMF_DATA *)&exptr->extnId); 1127 kmf_free_data(&exptr->BERvalue); 1128 1129 if (exptr->value.tagAndValue) { 1130 kmf_free_data(&exptr->value.tagAndValue->value); 1131 free(exptr->value.tagAndValue); 1132 } 1133 } 1134 1135 void 1136 kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr) 1137 { 1138 if (tbscsr) { 1139 kmf_free_data(&tbscsr->version); 1140 1141 kmf_free_dn(&tbscsr->subject); 1142 1143 kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm); 1144 kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey); 1145 1146 free_extensions(&tbscsr->extensions); 1147 } 1148 } 1149 1150 void 1151 kmf_free_signed_csr(KMF_CSR_DATA *csr) 1152 { 1153 if (csr) { 1154 kmf_free_tbs_csr(&csr->csr); 1155 1156 kmf_free_algoid(&csr->signature.algorithmIdentifier); 1157 kmf_free_data(&csr->signature.encrypted); 1158 } 1159 } 1160 1161 static void 1162 free_validity(KMF_X509_VALIDITY *validity) 1163 { 1164 if (validity == NULL) 1165 return; 1166 kmf_free_data(&validity->notBefore.time); 1167 kmf_free_data(&validity->notAfter.time); 1168 } 1169 1170 static void 1171 free_extensions(KMF_X509_EXTENSIONS *extns) 1172 { 1173 int i; 1174 KMF_X509_EXTENSION *exptr; 1175 1176 if (extns && extns->numberOfExtensions > 0) { 1177 for (i = 0; i < extns->numberOfExtensions; i++) { 1178 exptr = &extns->extensions[i]; 1179 kmf_free_extn(exptr); 1180 } 1181 free(extns->extensions); 1182 extns->numberOfExtensions = 0; 1183 extns->extensions = NULL; 1184 } 1185 } 1186 1187 void 1188 kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert) 1189 { 1190 if (tbscert) { 1191 kmf_free_data(&tbscert->version); 1192 kmf_free_bigint(&tbscert->serialNumber); 1193 kmf_free_algoid(&tbscert->signature); 1194 1195 kmf_free_dn(&tbscert->issuer); 1196 kmf_free_dn(&tbscert->subject); 1197 1198 free_validity(&tbscert->validity); 1199 1200 kmf_free_data(&tbscert->issuerUniqueIdentifier); 1201 kmf_free_data(&tbscert->subjectUniqueIdentifier); 1202 1203 kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm); 1204 kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey); 1205 1206 free_extensions(&tbscert->extensions); 1207 1208 kmf_free_data(&tbscert->issuerUniqueIdentifier); 1209 kmf_free_data(&tbscert->subjectUniqueIdentifier); 1210 } 1211 } 1212 1213 void 1214 kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr) 1215 { 1216 if (!certptr) 1217 return; 1218 1219 kmf_free_tbs_cert(&certptr->certificate); 1220 1221 kmf_free_algoid(&certptr->signature.algorithmIdentifier); 1222 kmf_free_data(&certptr->signature.encrypted); 1223 } 1224 1225 void 1226 kmf_free_str(char *pstr) 1227 { 1228 if (pstr != NULL) 1229 free(pstr); 1230 } 1231 1232 void 1233 free_keyidlist(KMF_OID *oidlist, int len) 1234 { 1235 int i; 1236 for (i = 0; i < len; i++) { 1237 kmf_free_data((KMF_DATA *)&oidlist[i]); 1238 } 1239 free(oidlist); 1240 } 1241 1242 void 1243 kmf_free_eku(KMF_X509EXT_EKU *eptr) 1244 { 1245 if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL) 1246 free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs); 1247 } 1248 1249 void 1250 kmf_free_spki(KMF_X509_SPKI *spki) 1251 { 1252 if (spki != NULL) { 1253 kmf_free_algoid(&spki->algorithm); 1254 kmf_free_data(&spki->subjectPublicKey); 1255 } 1256 } 1257 1258 void 1259 kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key) 1260 { 1261 KMF_PLUGIN *plugin; 1262 KMF_RETURN ret; 1263 KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */ 1264 int i = 0; 1265 boolean_t token_destroy = B_FALSE; 1266 1267 if (key == NULL) 1268 return; 1269 1270 CLEAR_ERROR(handle, ret); 1271 if (ret != KMF_OK) 1272 return; 1273 1274 kmf_set_attr_at_index(attlist, i, 1275 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE)); 1276 i++; 1277 1278 kmf_set_attr_at_index(attlist, i, 1279 KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t)); 1280 i++; 1281 1282 plugin = FindPlugin(handle, key->kstype); 1283 if (plugin != NULL && plugin->funclist->DeleteKey != NULL) { 1284 (void) plugin->funclist->DeleteKey(handle, i, attlist); 1285 } 1286 1287 if (key->keylabel) 1288 free(key->keylabel); 1289 1290 if (key->israw) { 1291 kmf_free_raw_key(key->keyp); 1292 free(key->keyp); 1293 } 1294 1295 (void) memset(key, 0, sizeof (KMF_KEY_HANDLE)); 1296 } 1297 1298 void 1299 kmf_free_bigint(KMF_BIGINT *big) 1300 { 1301 if (big != NULL && big->val != NULL) { 1302 /* Clear it out before returning it to the pool */ 1303 (void) memset(big->val, 0x00, big->len); 1304 free(big->val); 1305 big->val = NULL; 1306 big->len = 0; 1307 } 1308 } 1309 1310 static void 1311 free_raw_rsa(KMF_RAW_RSA_KEY *key) 1312 { 1313 if (key == NULL) 1314 return; 1315 kmf_free_bigint(&key->mod); 1316 kmf_free_bigint(&key->pubexp); 1317 kmf_free_bigint(&key->priexp); 1318 kmf_free_bigint(&key->prime1); 1319 kmf_free_bigint(&key->prime2); 1320 kmf_free_bigint(&key->exp1); 1321 kmf_free_bigint(&key->exp2); 1322 kmf_free_bigint(&key->coef); 1323 } 1324 1325 static void 1326 free_raw_dsa(KMF_RAW_DSA_KEY *key) 1327 { 1328 if (key == NULL) 1329 return; 1330 kmf_free_bigint(&key->prime); 1331 kmf_free_bigint(&key->subprime); 1332 kmf_free_bigint(&key->base); 1333 kmf_free_bigint(&key->value); 1334 } 1335 1336 static void 1337 free_raw_sym(KMF_RAW_SYM_KEY *key) 1338 { 1339 if (key == NULL) 1340 return; 1341 kmf_free_bigint(&key->keydata); 1342 } 1343 1344 void 1345 kmf_free_raw_key(KMF_RAW_KEY_DATA *key) 1346 { 1347 if (key == NULL) 1348 return; 1349 1350 switch (key->keytype) { 1351 case KMF_RSA: 1352 free_raw_rsa(&key->rawdata.rsa); 1353 break; 1354 case KMF_DSA: 1355 free_raw_dsa(&key->rawdata.dsa); 1356 break; 1357 case KMF_AES: 1358 case KMF_RC4: 1359 case KMF_DES: 1360 case KMF_DES3: 1361 free_raw_sym(&key->rawdata.sym); 1362 break; 1363 } 1364 if (key->label) { 1365 free(key->label); 1366 key->label = NULL; 1367 } 1368 kmf_free_data(&key->id); 1369 } 1370 1371 void 1372 kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key) 1373 { 1374 if (key == NULL) 1375 return; 1376 kmf_free_bigint(&key->keydata); 1377 free(key); 1378 } 1379 1380 /* 1381 * This function frees the space allocated for the name portion of a 1382 * KMF_CRL_DIST_POINT. 1383 */ 1384 void 1385 free_dp_name(KMF_CRL_DIST_POINT *dp) 1386 { 1387 KMF_GENERALNAMES *fullname; 1388 KMF_DATA *urldata; 1389 int i; 1390 1391 if (dp == NULL) 1392 return; 1393 1394 /* For phase 1, we only need to free the fullname space. */ 1395 fullname = &(dp->name.full_name); 1396 if (fullname->number == 0) 1397 return; 1398 1399 for (i = 0; i < fullname->number; i++) { 1400 urldata = &(fullname->namelist[fullname->number - 1].name); 1401 kmf_free_data(urldata); 1402 } 1403 1404 free(fullname->namelist); 1405 } 1406 1407 /* 1408 * This function frees the space allocated for a KMF_CRL_DIST_POINT. 1409 */ 1410 void 1411 free_dp(KMF_CRL_DIST_POINT *dp) 1412 { 1413 if (dp == NULL) 1414 return; 1415 1416 free_dp_name(dp); 1417 kmf_free_data(&(dp->reasons)); 1418 /* Need not to free crl_issuer space at phase 1 */ 1419 } 1420 1421 /* 1422 * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally. 1423 */ 1424 void 1425 kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps) 1426 { 1427 int i; 1428 1429 if (crl_dps == NULL) 1430 return; 1431 1432 for (i = 0; i < crl_dps->number; i++) 1433 free_dp(&(crl_dps->dplist[i])); 1434 1435 free(crl_dps->dplist); 1436 } 1437 1438 KMF_RETURN 1439 kmf_create_ocsp_request(KMF_HANDLE_T handle, 1440 int num_args, 1441 KMF_ATTRIBUTE *attrlist) 1442 { 1443 KMF_RETURN ret = KMF_OK; 1444 KMF_PLUGIN *plugin; 1445 KMF_RETURN (*createReqFn)(void *, int num_args, 1446 KMF_ATTRIBUTE *attrlist); 1447 1448 KMF_ATTRIBUTE_TESTER required_attrs[] = { 1449 {KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0}, 1450 {KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), 1451 sizeof (KMF_DATA)}, 1452 {KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), 1453 sizeof (KMF_DATA)}, 1454 }; 1455 1456 int num_req_attrs = sizeof (required_attrs) / 1457 sizeof (KMF_ATTRIBUTE_TESTER); 1458 1459 if (handle == NULL) 1460 return (KMF_ERR_BAD_PARAMETER); 1461 1462 CLEAR_ERROR(handle, ret); 1463 1464 ret = test_attributes(num_req_attrs, required_attrs, 1465 0, NULL, num_args, attrlist); 1466 1467 if (ret != KMF_OK) 1468 return (ret); 1469 1470 /* 1471 * This framework function is actually implemented in the openssl 1472 * plugin library, so we find the function address and call it. 1473 */ 1474 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 1475 if (plugin == NULL || plugin->dldesc == NULL) { 1476 return (KMF_ERR_PLUGIN_NOTFOUND); 1477 } 1478 1479 createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc, 1480 "OpenSSL_CreateOCSPRequest"); 1481 if (createReqFn == NULL) { 1482 return (KMF_ERR_FUNCTION_NOT_FOUND); 1483 } 1484 1485 return (createReqFn(handle, num_args, attrlist)); 1486 1487 } 1488 1489 KMF_RETURN 1490 kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle, 1491 int num_args, 1492 KMF_ATTRIBUTE *attrlist) 1493 { 1494 KMF_RETURN ret = KMF_OK; 1495 KMF_PLUGIN *plugin; 1496 KMF_RETURN (*getCertStatusFn)(void *, int num_args, 1497 KMF_ATTRIBUTE *attrlist); 1498 1499 KMF_ATTRIBUTE_TESTER required_attrs[] = { 1500 {KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), 1501 sizeof (KMF_DATA)}, 1502 {KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), 1503 sizeof (KMF_DATA)}, 1504 {KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA), 1505 sizeof (KMF_DATA)}, 1506 {KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int), 1507 sizeof (uint32_t)}, 1508 {KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int), 1509 sizeof (uint32_t)}, 1510 {KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int), 1511 sizeof (uint32_t)}, 1512 }; 1513 1514 int num_req_attrs = sizeof (required_attrs) / 1515 sizeof (KMF_ATTRIBUTE_TESTER); 1516 1517 if (handle == NULL) 1518 return (KMF_ERR_BAD_PARAMETER); 1519 1520 CLEAR_ERROR(handle, ret); 1521 1522 ret = test_attributes(num_req_attrs, required_attrs, 1523 0, NULL, num_args, attrlist); 1524 1525 if (ret != KMF_OK) 1526 return (ret); 1527 1528 /* 1529 * This framework function is actually implemented in the openssl 1530 * plugin library, so we find the function address and call it. 1531 */ 1532 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 1533 if (plugin == NULL || plugin->dldesc == NULL) { 1534 return (KMF_ERR_INTERNAL); 1535 } 1536 1537 getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc, 1538 "OpenSSL_GetOCSPStatusForCert"); 1539 if (getCertStatusFn == NULL) { 1540 return (KMF_ERR_INTERNAL); 1541 } 1542 1543 return (getCertStatusFn(handle, num_args, attrlist)); 1544 1545 } 1546 1547 KMF_RETURN 1548 kmf_string_to_oid(char *oidstring, KMF_OID *oid) 1549 { 1550 KMF_RETURN rv = KMF_OK; 1551 char *cp, *bp, *startp; 1552 int numbuf; 1553 int onumbuf; 1554 int nbytes, index; 1555 int len; 1556 unsigned char *op; 1557 1558 if (oidstring == NULL || oid == NULL) 1559 return (KMF_ERR_BAD_PARAMETER); 1560 1561 len = strlen(oidstring); 1562 1563 bp = oidstring; 1564 cp = bp; 1565 /* Skip over leading space */ 1566 while ((bp < &cp[len]) && isspace(*bp)) 1567 bp++; 1568 1569 startp = bp; 1570 nbytes = 0; 1571 1572 /* 1573 * The first two numbers are chewed up by the first octet. 1574 */ 1575 if (sscanf(bp, "%d", &numbuf) != 1) 1576 return (KMF_ERR_BAD_PARAMETER); 1577 while ((bp < &cp[len]) && isdigit(*bp)) 1578 bp++; 1579 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1580 bp++; 1581 if (sscanf(bp, "%d", &numbuf) != 1) 1582 return (KMF_ERR_BAD_PARAMETER); 1583 while ((bp < &cp[len]) && isdigit(*bp)) 1584 bp++; 1585 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1586 bp++; 1587 nbytes++; 1588 1589 while (isdigit(*bp)) { 1590 if (sscanf(bp, "%d", &numbuf) != 1) 1591 return (KMF_ERR_BAD_PARAMETER); 1592 while (numbuf) { 1593 nbytes++; 1594 numbuf >>= 7; 1595 } 1596 while ((bp < &cp[len]) && isdigit(*bp)) 1597 bp++; 1598 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1599 bp++; 1600 } 1601 1602 oid->Length = nbytes; 1603 oid->Data = malloc(oid->Length); 1604 if (oid->Data == NULL) { 1605 return (KMF_ERR_MEMORY); 1606 } 1607 (void) memset(oid->Data, 0, oid->Length); 1608 1609 op = oid->Data; 1610 1611 bp = startp; 1612 (void) sscanf(bp, "%d", &numbuf); 1613 1614 while (isdigit(*bp)) bp++; 1615 while (isspace(*bp) || *bp == '.') bp++; 1616 1617 onumbuf = 40 * numbuf; 1618 (void) sscanf(bp, "%d", &numbuf); 1619 onumbuf += numbuf; 1620 *op = (unsigned char) onumbuf; 1621 op++; 1622 1623 while (isdigit(*bp)) bp++; 1624 while (isspace(*bp) || *bp == '.') bp++; 1625 while (isdigit(*bp)) { 1626 (void) sscanf(bp, "%d", &numbuf); 1627 nbytes = 0; 1628 /* Have to fill in the bytes msb-first */ 1629 onumbuf = numbuf; 1630 while (numbuf) { 1631 nbytes++; 1632 numbuf >>= 7; 1633 } 1634 numbuf = onumbuf; 1635 op += nbytes; 1636 index = -1; 1637 while (numbuf) { 1638 op[index] = (unsigned char)numbuf & 0x7f; 1639 if (index != -1) 1640 op[index] |= 0x80; 1641 index--; 1642 numbuf >>= 7; 1643 } 1644 while (isdigit(*bp)) bp++; 1645 while (isspace(*bp) || *bp == '.') bp++; 1646 } 1647 1648 return (rv); 1649 } 1650 1651 static KMF_RETURN 1652 encode_rid(char *name, KMF_DATA *derdata) 1653 { 1654 KMF_RETURN rv = KMF_OK; 1655 1656 if (name == NULL || derdata == NULL) 1657 return (KMF_ERR_BAD_PARAMETER); 1658 1659 rv = kmf_string_to_oid(name, (KMF_OID *)derdata); 1660 1661 return (rv); 1662 } 1663 1664 static KMF_RETURN 1665 encode_ipaddr(char *name, KMF_DATA *derdata) 1666 { 1667 KMF_RETURN rv = KMF_OK; 1668 size_t len; 1669 in_addr_t v4; 1670 in6_addr_t v6; 1671 uint8_t *ptr; 1672 1673 if (name == NULL || derdata == NULL) 1674 return (KMF_ERR_BAD_PARAMETER); 1675 1676 v4 = inet_addr(name); 1677 if (v4 == (in_addr_t)-1) { 1678 ptr = (uint8_t *)&v6; 1679 if (inet_pton(AF_INET6, name, ptr) != 1) 1680 return (KMF_ERR_ENCODING); 1681 len = sizeof (v6); 1682 } else { 1683 ptr = (uint8_t *)&v4; 1684 len = sizeof (v4); 1685 } 1686 1687 derdata->Data = malloc(len); 1688 if (derdata->Data == NULL) 1689 return (KMF_ERR_MEMORY); 1690 (void) memcpy(derdata->Data, ptr, len); 1691 derdata->Length = len; 1692 1693 return (rv); 1694 } 1695 1696 static KMF_RETURN 1697 encode_krb5(char *name, KMF_DATA *derdata) 1698 { 1699 KMF_RETURN rv = KMF_OK; 1700 char *at, *realm; 1701 char *slash, *inst = NULL; 1702 BerElement *asn1 = NULL; 1703 BerValue *extdata = NULL; 1704 1705 at = strchr(name, '@'); 1706 if (at == NULL) 1707 return (KMF_ERR_ENCODING); 1708 1709 realm = at + 1; 1710 *at = 0; 1711 1712 /* 1713 * KRB5PrincipalName ::= SEQUENCE { 1714 * realm [0] Realm, 1715 * principalName [1] PrincipalName 1716 * } 1717 * 1718 * KerberosString ::= GeneralString (IA5String) 1719 * Realm ::= KerberosString 1720 * PrincipalName ::= SEQUENCE { 1721 * name-type [0] Int32, 1722 * name-string [1] SEQUENCE OF KerberosString 1723 * } 1724 */ 1725 1726 /* 1727 * Construct the "principalName" first. 1728 * 1729 * The name may be split with a "/" to indicate a new instance. 1730 * This must be separated in the ASN.1 1731 */ 1732 slash = strchr(name, '/'); 1733 if (slash != NULL) { 1734 inst = name; 1735 name = slash + 1; 1736 *slash = 0; 1737 } 1738 if ((asn1 = kmfder_alloc()) == NULL) { 1739 rv = KMF_ERR_MEMORY; 1740 goto cleanup; 1741 } 1742 if (kmfber_printf(asn1, "{Tli", 0xa0, 3, 0x01) == -1) 1743 goto cleanup; 1744 1745 if (inst != NULL) { 1746 if (kmfber_printf(asn1, "Tl{Tl", 0xA1, 1747 strlen(inst) + strlen(name) + 6, 1748 BER_GENERALSTRING, strlen(inst)) == -1) 1749 goto cleanup; 1750 if (kmfber_write(asn1, inst, strlen(inst), 0) != strlen(inst)) 1751 goto cleanup; 1752 if (kmfber_printf(asn1, "Tl", BER_GENERALSTRING, 1753 strlen(name)) == -1) 1754 goto cleanup; 1755 if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) 1756 goto cleanup; 1757 } else { 1758 if (kmfber_printf(asn1, "Tl{Tl", 0xA1, 1759 strlen(name) + 4, BER_GENERALSTRING, strlen(name)) == -1) 1760 goto cleanup; 1761 if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name)) 1762 goto cleanup; 1763 } 1764 1765 if (kmfber_printf(asn1, "}}") == -1) 1766 goto cleanup; 1767 if (kmfber_flatten(asn1, &extdata) == -1) { 1768 rv = KMF_ERR_ENCODING; 1769 goto cleanup; 1770 } 1771 kmfber_free(asn1, 1); 1772 asn1 = NULL; 1773 1774 /* Next construct the KRB5PrincipalNameSeq */ 1775 if ((asn1 = kmfder_alloc()) == NULL) { 1776 kmfber_bvfree(extdata); 1777 rv = KMF_ERR_MEMORY; 1778 goto cleanup; 1779 } 1780 if (kmfber_printf(asn1, "{TlTl", 0xA0, strlen(realm) + 2, 1781 BER_GENERALSTRING, strlen(realm)) == -1) 1782 goto cleanup; 1783 if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm)) 1784 goto cleanup; 1785 if (kmfber_printf(asn1, "Tl", 0xA1, extdata->bv_len) == -1) 1786 goto cleanup; 1787 if (kmfber_write(asn1, extdata->bv_val, 1788 extdata->bv_len, 0) != extdata->bv_len) 1789 goto cleanup; 1790 if (kmfber_printf(asn1, "}") == -1) 1791 goto cleanup; 1792 kmfber_bvfree(extdata); 1793 extdata = NULL; 1794 if (kmfber_flatten(asn1, &extdata) == -1) { 1795 rv = KMF_ERR_ENCODING; 1796 goto cleanup; 1797 } 1798 kmfber_free(asn1, 1); 1799 asn1 = NULL; 1800 1801 /* 1802 * GeneralName ::= CHOICE { 1803 * otherName [0] OtherName, 1804 * ... 1805 * } 1806 * 1807 * OtherName ::= SEQUENCE { 1808 * type-id OBJECT IDENTIFIER, 1809 * value [0] EXPLICIT ANY DEFINED BY type-id 1810 * } 1811 */ 1812 1813 /* Now construct the SAN: OID + typed data. */ 1814 if ((asn1 = kmfder_alloc()) == NULL) { 1815 kmfber_bvfree(extdata); 1816 rv = KMF_ERR_MEMORY; 1817 goto cleanup; 1818 } 1819 if (kmfber_printf(asn1, "D", &KMFOID_PKINIT_san) == -1) 1820 goto cleanup; 1821 if (kmfber_printf(asn1, "Tl", 0xA0, extdata->bv_len) == -1) 1822 goto cleanup; 1823 if (kmfber_write(asn1, extdata->bv_val, 1824 extdata->bv_len, 0) != extdata->bv_len) 1825 goto cleanup; 1826 kmfber_bvfree(extdata); 1827 extdata = NULL; 1828 if (kmfber_flatten(asn1, &extdata) == -1) { 1829 rv = KMF_ERR_ENCODING; 1830 goto cleanup; 1831 } 1832 kmfber_free(asn1, 1); 1833 asn1 = NULL; 1834 1835 derdata->Data = (uchar_t *)extdata->bv_val; 1836 extdata->bv_val = NULL; /* clear it so it is not freed later */ 1837 derdata->Length = extdata->bv_len; 1838 1839 cleanup: 1840 if (asn1 != NULL) 1841 kmfber_free(asn1, 1); 1842 1843 if (extdata != NULL) 1844 kmfber_bvfree(extdata); 1845 1846 if (*at == 0) 1847 *at = '@'; 1848 1849 if (inst != NULL) 1850 *slash = '/'; 1851 1852 return (rv); 1853 } 1854 1855 static KMF_RETURN 1856 encode_sclogon(char *name, KMF_DATA *derdata) 1857 { 1858 KMF_RETURN rv = KMF_OK; 1859 BerElement *asn1 = NULL; 1860 BerValue *extdata = NULL; 1861 1862 if ((asn1 = kmfder_alloc()) == NULL) 1863 return (KMF_ERR_MEMORY); 1864 1865 /* The name is encoded as a KerberosString (IA5STRING) */ 1866 if (kmfber_printf(asn1, "{Ds}", 1867 &KMFOID_MS_KP_SCLogon, name) == -1) 1868 goto cleanup; 1869 1870 if (kmfber_flatten(asn1, &extdata) == -1) { 1871 rv = KMF_ERR_ENCODING; 1872 goto cleanup; 1873 } 1874 1875 derdata->Data = (uchar_t *)extdata->bv_val; 1876 derdata->Length = extdata->bv_len; 1877 1878 free(extdata); 1879 cleanup: 1880 if (asn1 != NULL) 1881 kmfber_free(asn1, 1); 1882 1883 return (rv); 1884 } 1885 1886 static KMF_RETURN 1887 verify_uri_format(char *uristring) 1888 { 1889 KMF_RETURN ret = KMF_OK; 1890 xmlURIPtr uriptr = NULL; 1891 1892 /* Parse the URI string; get the hostname and port */ 1893 uriptr = xmlParseURI(uristring); 1894 if (uriptr == NULL) { 1895 ret = KMF_ERR_BAD_URI; 1896 goto out; 1897 } 1898 1899 if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) { 1900 ret = KMF_ERR_BAD_URI; 1901 goto out; 1902 } 1903 1904 if (uriptr->server == NULL || !strlen(uriptr->server)) { 1905 ret = KMF_ERR_BAD_URI; 1906 goto out; 1907 } 1908 out: 1909 if (uriptr != NULL) 1910 xmlFreeURI(uriptr); 1911 return (ret); 1912 } 1913 1914 static KMF_RETURN 1915 encode_altname(char *namedata, 1916 KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname) 1917 { 1918 KMF_RETURN ret = KMF_OK; 1919 KMF_X509_NAME dnname; 1920 uchar_t tagval; 1921 BerElement *asn1 = NULL; 1922 BerValue *extdata; 1923 1924 if (namedata == NULL || encodedname == NULL) 1925 return (KMF_ERR_BAD_PARAMETER); 1926 1927 /* 1928 * Encode the namedata according to rules in RFC 3280 for GeneralName. 1929 * The input "namedata" is assumed to be an ASCII string representation 1930 * of the AltName, we need to convert it to correct ASN.1 here before 1931 * adding it to the cert. 1932 */ 1933 switch (nametype) { 1934 case GENNAME_RFC822NAME: /* rfc 822 */ 1935 /* IA5String, no encoding needed */ 1936 encodedname->Data = (uchar_t *)strdup(namedata); 1937 if (encodedname->Data == NULL) 1938 return (KMF_ERR_MEMORY); 1939 encodedname->Length = strlen(namedata); 1940 tagval = (0x80 | nametype); 1941 break; 1942 case GENNAME_DNSNAME: /* rfc 1034 */ 1943 encodedname->Data = (uchar_t *)strdup(namedata); 1944 if (encodedname->Data == NULL) 1945 return (KMF_ERR_MEMORY); 1946 encodedname->Length = strlen(namedata); 1947 tagval = (0x80 | nametype); 1948 break; 1949 case GENNAME_URI: /* rfc 1738 */ 1950 ret = verify_uri_format(namedata); 1951 if (ret != KMF_OK) 1952 return (ret); 1953 /* IA5String, no encoding needed */ 1954 encodedname->Data = (uchar_t *)strdup(namedata); 1955 if (encodedname->Data == NULL) 1956 return (KMF_ERR_MEMORY); 1957 encodedname->Length = strlen(namedata); 1958 tagval = (0x80 | nametype); 1959 break; 1960 case GENNAME_IPADDRESS: 1961 ret = encode_ipaddr(namedata, encodedname); 1962 tagval = (0x80 | nametype); 1963 break; 1964 case GENNAME_REGISTEREDID: 1965 ret = encode_rid(namedata, encodedname); 1966 tagval = (0x80 | nametype); 1967 break; 1968 case GENNAME_DIRECTORYNAME: 1969 ret = kmf_dn_parser(namedata, &dnname); 1970 if (ret == KMF_OK) { 1971 ret = DerEncodeName(&dnname, encodedname); 1972 } 1973 (void) kmf_free_dn(&dnname); 1974 tagval = (0x80 | nametype); 1975 break; 1976 case GENNAME_KRB5PRINC: 1977 tagval = (0xA0 | GENNAME_OTHERNAME); 1978 ret = encode_krb5(namedata, encodedname); 1979 break; 1980 case GENNAME_SCLOGON_UPN: 1981 tagval = (0xA0 | GENNAME_OTHERNAME); 1982 ret = encode_sclogon(namedata, encodedname); 1983 break; 1984 default: 1985 /* unsupported */ 1986 return (KMF_ERR_BAD_PARAMETER); 1987 1988 } 1989 if (ret != KMF_OK) { 1990 kmf_free_data(encodedname); 1991 return (ret); 1992 } 1993 1994 if ((asn1 = kmfder_alloc()) == NULL) 1995 return (KMF_ERR_MEMORY); 1996 1997 if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1) 1998 goto cleanup; 1999 2000 if (kmfber_write(asn1, (char *)encodedname->Data, 2001 encodedname->Length, 0) == -1) { 2002 ret = KMF_ERR_ENCODING; 2003 goto cleanup; 2004 } 2005 if (kmfber_flatten(asn1, &extdata) == -1) { 2006 ret = KMF_ERR_ENCODING; 2007 goto cleanup; 2008 } 2009 2010 kmf_free_data(encodedname); 2011 encodedname->Data = (uchar_t *)extdata->bv_val; 2012 encodedname->Length = extdata->bv_len; 2013 2014 free(extdata); 2015 2016 cleanup: 2017 if (asn1) 2018 kmfber_free(asn1, 1); 2019 2020 if (ret != KMF_OK) 2021 kmf_free_data(encodedname); 2022 2023 return (ret); 2024 } 2025 2026 KMF_X509_EXTENSION * 2027 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid) 2028 { 2029 KMF_X509_EXTENSION *foundextn = NULL; 2030 int i; 2031 2032 if (exts == NULL || oid == NULL) 2033 return (NULL); 2034 2035 for (i = 0; i < exts->numberOfExtensions; i++) { 2036 if (IsEqualOid(oid, &exts->extensions[i].extnId)) { 2037 foundextn = &exts->extensions[i]; 2038 break; 2039 } 2040 } 2041 return (foundextn); 2042 } 2043 2044 KMF_RETURN 2045 GetSequenceContents(char *data, size_t len, 2046 char **contents, size_t *outlen) 2047 { 2048 KMF_RETURN ret = KMF_OK; 2049 BerElement *exasn1 = NULL; 2050 BerValue oldextn; 2051 int tag; 2052 size_t oldsize; 2053 char *olddata = NULL; 2054 2055 if (data == NULL || contents == NULL || outlen == NULL) 2056 return (KMF_ERR_BAD_PARAMETER); 2057 2058 /* 2059 * Decode the sequence of general names 2060 */ 2061 oldextn.bv_val = data; 2062 oldextn.bv_len = len; 2063 2064 if ((exasn1 = kmfder_init(&oldextn)) == NULL) { 2065 ret = KMF_ERR_MEMORY; 2066 goto out; 2067 } 2068 2069 /* 2070 * Unwrap the sequence to find the size of the block 2071 * of GeneralName items in the set. 2072 * 2073 * Peek at the tag and length ("tl"), 2074 * then consume them ("{"). 2075 */ 2076 if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT || 2077 oldsize == 0) { 2078 ret = KMF_ERR_ENCODING; 2079 goto out; 2080 } 2081 2082 olddata = malloc(oldsize); 2083 if (olddata == NULL) { 2084 ret = KMF_ERR_MEMORY; 2085 goto out; 2086 } 2087 (void) memset(olddata, 0, oldsize); 2088 /* 2089 * Read the entire blob of GeneralNames, we don't 2090 * need to interpret them now. 2091 */ 2092 if (kmfber_read(exasn1, olddata, oldsize) != oldsize) { 2093 ret = KMF_ERR_ENCODING; 2094 goto out; 2095 } 2096 out: 2097 if (exasn1 != NULL) 2098 kmfber_free(exasn1, 1); 2099 2100 if (ret != KMF_OK) { 2101 *contents = NULL; 2102 *outlen = 0; 2103 if (olddata != NULL) 2104 free(olddata); 2105 } else { 2106 *contents = olddata; 2107 *outlen = oldsize; 2108 } 2109 return (ret); 2110 } 2111 2112 KMF_RETURN 2113 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn) 2114 { 2115 KMF_RETURN ret = KMF_OK; 2116 KMF_X509_EXTENSION *extlist; 2117 2118 if (exts == NULL || newextn == NULL) 2119 return (KMF_ERR_BAD_PARAMETER); 2120 2121 extlist = malloc(sizeof (KMF_X509_EXTENSION) * 2122 (exts->numberOfExtensions + 1)); 2123 if (extlist == NULL) 2124 return (KMF_ERR_MEMORY); 2125 2126 (void) memcpy(extlist, exts->extensions, 2127 exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION)); 2128 2129 (void) memcpy(&extlist[exts->numberOfExtensions], newextn, 2130 sizeof (KMF_X509_EXTENSION)); 2131 2132 free(exts->extensions); 2133 exts->numberOfExtensions++; 2134 exts->extensions = extlist; 2135 2136 return (ret); 2137 } 2138 2139 KMF_RETURN 2140 kmf_set_altname(KMF_X509_EXTENSIONS *extensions, 2141 KMF_OID *oid, 2142 int critical, 2143 KMF_GENERALNAMECHOICES nametype, 2144 char *namedata) 2145 { 2146 KMF_RETURN ret = KMF_OK; 2147 KMF_X509_EXTENSION subjAltName; 2148 KMF_DATA dername = { NULL, 0 }; 2149 BerElement *asn1 = NULL; 2150 BerValue *extdata; 2151 char *olddata = NULL; 2152 KMF_X509_EXTENSION *foundextn = NULL; 2153 size_t oldsize = 0; 2154 2155 if (extensions == NULL || oid == NULL || namedata == NULL) 2156 return (KMF_ERR_BAD_PARAMETER); 2157 2158 ret = encode_altname(namedata, nametype, &dername); 2159 2160 if (ret != KMF_OK) 2161 return (ret); 2162 2163 (void) memset(&subjAltName, 0, sizeof (subjAltName)); 2164 2165 ret = copy_data(&subjAltName.extnId, oid); 2166 if (ret != KMF_OK) 2167 goto out; 2168 /* 2169 * Check to see if this cert already has a subjectAltName. 2170 */ 2171 foundextn = FindExtn(extensions, oid); 2172 2173 if (foundextn != NULL) { 2174 ret = GetSequenceContents( 2175 (char *)foundextn->BERvalue.Data, 2176 foundextn->BERvalue.Length, 2177 &olddata, &oldsize); 2178 if (ret != KMF_OK) 2179 goto out; 2180 } 2181 2182 /* 2183 * Assume (!!) that the namedata given is already properly encoded. 2184 */ 2185 if ((asn1 = kmfder_alloc()) == NULL) 2186 return (KMF_ERR_MEMORY); 2187 2188 if (kmfber_printf(asn1, "{") == -1) { 2189 ret = KMF_ERR_ENCODING; 2190 goto out; 2191 } 2192 2193 /* Write the old extension data first */ 2194 if (olddata != NULL && oldsize > 0) { 2195 if (kmfber_write(asn1, olddata, oldsize, 0) == -1) { 2196 ret = KMF_ERR_ENCODING; 2197 goto out; 2198 } 2199 } 2200 2201 /* Now add the new name to the list */ 2202 if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) { 2203 ret = KMF_ERR_ENCODING; 2204 goto out; 2205 } 2206 2207 /* Now close the sequence */ 2208 if (kmfber_printf(asn1, "}") == -1) { 2209 ret = KMF_ERR_ENCODING; 2210 goto out; 2211 } 2212 if (kmfber_flatten(asn1, &extdata) == -1) { 2213 ret = KMF_ERR_ENCODING; 2214 goto out; 2215 } 2216 2217 /* 2218 * If we are just adding to an existing list of altNames, 2219 * just replace the BER data associated with the found extension. 2220 */ 2221 if (foundextn != NULL) { 2222 free(foundextn->BERvalue.Data); 2223 foundextn->critical = critical; 2224 foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val; 2225 foundextn->BERvalue.Length = extdata->bv_len; 2226 } else { 2227 subjAltName.critical = critical; 2228 subjAltName.format = KMF_X509_DATAFORMAT_ENCODED; 2229 subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val; 2230 subjAltName.BERvalue.Length = extdata->bv_len; 2231 ret = add_an_extension(extensions, &subjAltName); 2232 if (ret != KMF_OK) 2233 free(subjAltName.BERvalue.Data); 2234 } 2235 2236 free(extdata); 2237 out: 2238 if (olddata != NULL) 2239 free(olddata); 2240 2241 kmf_free_data(&dername); 2242 if (ret != KMF_OK) 2243 kmf_free_data(&subjAltName.extnId); 2244 if (asn1 != NULL) 2245 kmfber_free(asn1, 1); 2246 return (ret); 2247 } 2248 2249 /* 2250 * Search a list of attributes for one that matches the given type. 2251 * Return a pointer into the attribute list. This does not 2252 * return a copy of the value, it returns a reference into the 2253 * given list. 2254 */ 2255 int 2256 kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs) 2257 { 2258 int i; 2259 for (i = 0; i < numattrs; i++) { 2260 if (attlist[i].type == type) 2261 return (i); 2262 } 2263 return (-1); 2264 } 2265 2266 /* 2267 * Verify that a given attribute is consistent with the 2268 * "test" attribute. 2269 */ 2270 static KMF_RETURN 2271 verify_attribute(KMF_ATTRIBUTE *givenattr, 2272 KMF_ATTRIBUTE_TESTER *testattr) 2273 { 2274 /* A NULL pValue was found where one is required */ 2275 if (testattr->null_value_ok == FALSE && 2276 givenattr->pValue == NULL) 2277 return (KMF_ERR_BAD_PARAMETER); 2278 2279 /* If the given valueLen is too small, return error */ 2280 if (givenattr->pValue != NULL && 2281 testattr->minlen > 0 && 2282 (givenattr->valueLen < testattr->minlen)) 2283 return (KMF_ERR_BAD_PARAMETER); 2284 2285 /* If the given valueLen is too big, return error */ 2286 if (givenattr->pValue != NULL && 2287 testattr->maxlen > 0 && 2288 (givenattr->valueLen > testattr->maxlen)) 2289 return (KMF_ERR_BAD_PARAMETER); 2290 2291 return (KMF_OK); 2292 } 2293 2294 /* 2295 * Given a set of required attribute tests and optional 2296 * attributes, make sure that the actual attributes 2297 * being tested (attrlist below) are allowed and are 2298 * properly specified. 2299 */ 2300 KMF_RETURN 2301 test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs, 2302 int optnum, KMF_ATTRIBUTE_TESTER *optattrs, 2303 int numattrs, KMF_ATTRIBUTE *attrlist) 2304 { 2305 KMF_RETURN ret = KMF_OK; 2306 int i, idx; 2307 2308 /* 2309 * If the caller didn't supply enough attributes, 2310 * return an error. 2311 */ 2312 if (numattrs < reqnum || attrlist == NULL) 2313 return (KMF_ERR_BAD_PARAMETER); 2314 2315 /* 2316 * Make sure all required attrs are present and 2317 * correct. 2318 */ 2319 for (i = 0; i < reqnum && ret == KMF_OK; i++) { 2320 idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs); 2321 /* If a required attr is not found, return error */ 2322 if (idx == -1) { 2323 return (KMF_ERR_BAD_PARAMETER); 2324 } 2325 2326 ret = verify_attribute(&attrlist[idx], &reqattrs[i]); 2327 } 2328 /* 2329 * Now test the optional parameters. 2330 */ 2331 for (i = 0; i < optnum && ret == KMF_OK; i++) { 2332 idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs); 2333 /* If a optional attr is not found, continue. */ 2334 if (idx == -1) { 2335 continue; 2336 } 2337 2338 ret = verify_attribute(&attrlist[idx], &optattrs[i]); 2339 } 2340 2341 return (ret); 2342 } 2343 2344 /* 2345 * Given an already allocated attribute list, insert 2346 * the given attribute information at a specific index 2347 * in the list. 2348 */ 2349 void 2350 kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index, 2351 KMF_ATTR_TYPE type, void *pValue, uint32_t len) 2352 { 2353 if (attlist == NULL) 2354 return; 2355 2356 attlist[index].type = type; 2357 attlist[index].pValue = pValue; 2358 attlist[index].valueLen = len; 2359 } 2360 2361 /* 2362 * Find an attribute matching a particular type and set 2363 * the pValue and length fields to the given values. 2364 */ 2365 KMF_RETURN 2366 kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr, 2367 KMF_ATTR_TYPE type, void *pValue, uint32_t len) 2368 { 2369 int idx; 2370 if (attlist == NULL) 2371 return (KMF_ERR_BAD_PARAMETER); 2372 2373 idx = kmf_find_attr(type, attlist, numattr); 2374 if (idx == -1) 2375 return (KMF_ERR_ATTR_NOT_FOUND); 2376 2377 attlist[idx].type = type; 2378 /* Assumes the attribute pValue can hold the result */ 2379 if (attlist[idx].pValue != NULL) { 2380 if (attlist[idx].valueLen >= len) 2381 (void) memcpy(attlist[idx].pValue, pValue, len); 2382 else 2383 return (KMF_ERR_BUFFER_SIZE); 2384 } 2385 attlist[idx].valueLen = len; 2386 return (KMF_OK); 2387 } 2388 2389 /* 2390 * Find a particular attribute in a list and return 2391 * a pointer to its value. 2392 */ 2393 void * 2394 kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, 2395 int numattrs) 2396 { 2397 int i; 2398 2399 i = kmf_find_attr(type, attlist, numattrs); 2400 if (i == -1) 2401 return (NULL); 2402 2403 return (attlist[i].pValue); 2404 } 2405 2406 /* 2407 * Find a particular attribute in a list and return 2408 * the value and length values. Value and length 2409 * may be NULL if the caller doesn't want their values 2410 * to be filled in. 2411 */ 2412 KMF_RETURN 2413 kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, 2414 int numattrs, void *outValue, uint32_t *outlen) 2415 { 2416 int i; 2417 uint32_t len = 0; 2418 uint32_t *lenptr = outlen; 2419 2420 if (lenptr == NULL) 2421 lenptr = &len; 2422 2423 i = kmf_find_attr(type, attlist, numattrs); 2424 if (i == -1) 2425 return (KMF_ERR_ATTR_NOT_FOUND); 2426 2427 /* This assumes that the ptr passed in is pre-allocated space */ 2428 if (attlist[i].pValue != NULL && outValue != NULL) { 2429 /* 2430 * If the caller did not specify a length, 2431 * assume "outValue" is big enough. 2432 */ 2433 if (outlen != NULL) { 2434 if (*outlen >= attlist[i].valueLen) 2435 (void) memcpy(outValue, attlist[i].pValue, 2436 attlist[i].valueLen); 2437 else 2438 return (KMF_ERR_BUFFER_SIZE); 2439 } else { 2440 (void) memcpy(outValue, attlist[i].pValue, 2441 attlist[i].valueLen); 2442 } 2443 } 2444 2445 if (outlen != NULL) 2446 *outlen = attlist[i].valueLen; 2447 return (KMF_OK); 2448 } 2449 2450 /* 2451 * Utility routine to find a string type attribute, allocate it 2452 * and return the value to the caller. This simplifies the 2453 * operation by doing both "kmf_get_attr" calls and avoids 2454 * duplicating this block of code in lots of places. 2455 */ 2456 KMF_RETURN 2457 kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist, 2458 int numattrs, char **outstr) 2459 { 2460 KMF_RETURN rv; 2461 uint32_t len; 2462 2463 if (outstr == NULL) 2464 return (KMF_ERR_BAD_PARAMETER); 2465 2466 if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) == 2467 KMF_OK) { 2468 *outstr = malloc(len + 1); 2469 if ((*outstr) == NULL) 2470 return (KMF_ERR_MEMORY); 2471 (void) memset((*outstr), 0, len + 1); 2472 rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len); 2473 if (rv != KMF_OK) { 2474 free(*outstr); 2475 *outstr = NULL; 2476 } 2477 } 2478 2479 return (rv); 2480 } 2481 2482 2483 void 2484 free_entry(conf_entry_t *entry) 2485 { 2486 if (entry == NULL) 2487 return; 2488 free(entry->keystore); 2489 free(entry->modulepath); 2490 free(entry->option); 2491 } 2492 2493 void 2494 free_entrylist(conf_entrylist_t *list) 2495 { 2496 conf_entrylist_t *next; 2497 2498 while (list != NULL) { 2499 next = list->next; 2500 free_entry(list->entry); 2501 free(list); 2502 list = next; 2503 } 2504 } 2505 2506 static KMF_RETURN 2507 parse_entry(char *buf, conf_entry_t **entry) 2508 { 2509 KMF_RETURN ret = KMF_OK; 2510 conf_entry_t *tmp = NULL; 2511 char *token1; 2512 char *token2; 2513 char *token3; 2514 char *lasts; 2515 char *value; 2516 2517 if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) 2518 return (KMF_ERR_KMF_CONF); 2519 2520 if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL) 2521 return (KMF_ERR_MEMORY); 2522 2523 if ((tmp->keystore = strdup(token1)) == NULL) { 2524 ret = KMF_ERR_MEMORY; 2525 goto end; 2526 } 2527 2528 if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) { 2529 ret = KMF_ERR_KMF_CONF; 2530 goto end; 2531 } 2532 2533 /* need to get token3 first to satisfy nested strtok invocations */ 2534 token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts); 2535 2536 /* parse token2 */ 2537 if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) { 2538 ret = KMF_ERR_KMF_CONF; 2539 goto end; 2540 } 2541 2542 if (value = strpbrk(token2, SEP_EQUAL)) { 2543 value++; /* get rid of = */ 2544 } else { 2545 ret = KMF_ERR_KMF_CONF; 2546 goto end; 2547 } 2548 2549 if ((tmp->modulepath = strdup(value)) == NULL) { 2550 ret = KMF_ERR_MEMORY; 2551 goto end; 2552 } 2553 2554 /* parse token3, if it exists */ 2555 if (token3 != NULL) { 2556 if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION)) 2557 != 0) { 2558 ret = KMF_ERR_KMF_CONF; 2559 goto end; 2560 } 2561 2562 if (value = strpbrk(token3, SEP_EQUAL)) { 2563 value++; /* get rid of = */ 2564 } else { 2565 ret = KMF_ERR_KMF_CONF; 2566 goto end; 2567 } 2568 2569 if ((tmp->option = strdup(value)) == NULL) { 2570 ret = KMF_ERR_MEMORY; 2571 goto end; 2572 } 2573 } 2574 2575 *entry = tmp; 2576 2577 end: 2578 if (ret != KMF_OK) { 2579 free_entry(tmp); 2580 free(tmp); 2581 } 2582 return (ret); 2583 } 2584 2585 2586 conf_entry_t * 2587 dup_entry(conf_entry_t *entry) 2588 { 2589 conf_entry_t *rtn_entry; 2590 2591 if (entry == NULL) 2592 return (NULL); 2593 2594 rtn_entry = malloc(sizeof (conf_entry_t)); 2595 if (rtn_entry == NULL) 2596 return (NULL); 2597 2598 if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL) 2599 goto out; 2600 2601 if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL) 2602 goto out; 2603 2604 if (entry->option != NULL && 2605 (rtn_entry->option = strdup(entry->modulepath)) == NULL) 2606 goto out; 2607 2608 return (rtn_entry); 2609 2610 out: 2611 free_entry(rtn_entry); 2612 return (NULL); 2613 } 2614 2615 2616 /* 2617 * This function takes a keystore_name as input and returns 2618 * the KMF_KEYSTORE_TYPE value assigned to it. If the "option" 2619 * argument is not NULL, this function also returns the option string 2620 * if there is an option string for the plugin module. 2621 */ 2622 KMF_RETURN 2623 kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name, 2624 KMF_KEYSTORE_TYPE *kstype, char **option) 2625 { 2626 KMF_RETURN ret = KMF_OK; 2627 conf_entrylist_t *phead = extra_plugin_list; 2628 boolean_t is_default = B_TRUE; 2629 2630 /* 2631 * Although handle is not really used in the function, we will 2632 * check the handle to make sure that kmf_intialize() is called 2633 * before this function. 2634 */ 2635 if (handle == NULL || keystore_name == NULL || kstype == NULL) 2636 return (KMF_ERR_BAD_PARAMETER); 2637 2638 if (strcmp(keystore_name, "pkcs11") == 0) { 2639 *kstype = KMF_KEYSTORE_PK11TOKEN; 2640 } else if (strcmp(keystore_name, "file") == 0) { 2641 *kstype = KMF_KEYSTORE_OPENSSL; 2642 } else if (strcmp(keystore_name, "nss") == 0) { 2643 *kstype = KMF_KEYSTORE_NSS; 2644 } else { 2645 is_default = B_FALSE; 2646 } 2647 2648 if (is_default) { 2649 if (option != NULL) 2650 *option = NULL; 2651 goto out; 2652 } 2653 2654 /* Not a built-in plugin; check if it is in extra_plugin_list. */ 2655 while (phead != NULL) { 2656 if (strcmp(phead->entry->keystore, keystore_name) == 0) 2657 break; 2658 phead = phead->next; 2659 } 2660 2661 if (phead == NULL) { 2662 ret = KMF_ERR_PLUGIN_NOTFOUND; 2663 goto out; 2664 } 2665 2666 /* found it */ 2667 *kstype = phead->entry->kstype; 2668 if (option != NULL) { 2669 if (phead->entry->option == NULL) 2670 *option = NULL; 2671 else { 2672 *option = strdup(phead->entry->option); 2673 if (*option == NULL) { 2674 ret = KMF_ERR_MEMORY; 2675 goto out; 2676 } 2677 } 2678 } 2679 2680 out: 2681 return (ret); 2682 } 2683 2684 /* 2685 * Retrieve the non-default plugin list from the kmf.conf file. 2686 */ 2687 KMF_RETURN 2688 get_entrylist(conf_entrylist_t **entlist) 2689 { 2690 KMF_RETURN rv = KMF_OK; 2691 FILE *pfile; 2692 conf_entry_t *entry; 2693 conf_entrylist_t *rtnlist = NULL; 2694 conf_entrylist_t *ptmp; 2695 conf_entrylist_t *pcur; 2696 char buffer[MAXPATHLEN]; 2697 size_t len; 2698 2699 if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) { 2700 cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF); 2701 return (KMF_ERR_KMF_CONF); 2702 } 2703 2704 while (fgets(buffer, MAXPATHLEN, pfile) != NULL) { 2705 if (buffer[0] == '#' || buffer[0] == ' ' || 2706 buffer[0] == '\n'|| buffer[0] == '\t') { 2707 continue; /* ignore comment lines */ 2708 } 2709 2710 len = strlen(buffer); 2711 if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */ 2712 len--; 2713 } 2714 buffer[len] = '\0'; 2715 2716 rv = parse_entry(buffer, &entry); 2717 if (rv != KMF_OK) { 2718 goto end; 2719 } 2720 2721 if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) { 2722 rv = KMF_ERR_MEMORY; 2723 goto end; 2724 } 2725 ptmp->entry = entry; 2726 ptmp->next = NULL; 2727 2728 if (rtnlist == NULL) { 2729 rtnlist = pcur = ptmp; 2730 } else { 2731 pcur->next = ptmp; 2732 pcur = ptmp; 2733 } 2734 } 2735 2736 end: 2737 (void) fclose(pfile); 2738 2739 if (rv == KMF_OK) { 2740 *entlist = rtnlist; 2741 } else if (rtnlist != NULL) { 2742 free_entrylist(rtnlist); 2743 *entlist = NULL; 2744 kstore_num = DEFAULT_KEYSTORE_NUM; 2745 } 2746 2747 return (rv); 2748 } 2749 2750 2751 boolean_t 2752 is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype) 2753 { 2754 2755 if (kstype > 0 && kstype <= kstore_num) 2756 return (B_TRUE); 2757 else 2758 return (B_FALSE); 2759 } 2760