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