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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright(c) 1995-2000 Intel Corporation. All rights reserved. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <stdio.h> 31 #include <dlfcn.h> 32 #include <link.h> 33 #include <fcntl.h> 34 #include <ctype.h> 35 #include <sys/param.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <errno.h> 39 #include <sys/socket.h> 40 #include <netinet/in.h> 41 #include <arpa/inet.h> 42 #include <thread.h> 43 44 #include <ber_der.h> 45 #include <kmfapiP.h> 46 47 #include <pem_encode.h> 48 #include <rdn_parser.h> 49 #include <libxml2/libxml/uri.h> 50 #include <libgen.h> 51 #include <cryptoutil.h> 52 53 static uchar_t pkcs11_initialized = 0; 54 mutex_t init_lock = DEFAULTMUTEX; 55 extern int errno; 56 57 typedef struct { 58 KMF_RETURN code; 59 char *message; 60 } kmf_error_map; 61 62 static kmf_error_map kmf_errcodes[] = { 63 {KMF_OK, "KMF_OK"}, 64 {KMF_ERR_BAD_PARAMETER, "KMF_ERR_BAD_PARAMETER"}, 65 {KMF_ERR_BAD_KEY_FORMAT, "KMF_ERR_BAD_KEY_FORMAT"}, 66 {KMF_ERR_BAD_ALGORITHM, "KMF_ERR_BAD_ALGORITHM"}, 67 {KMF_ERR_MEMORY, "KMF_ERR_MEMORY"}, 68 {KMF_ERR_ENCODING, "KMF_ERR_ENCODING"}, 69 {KMF_ERR_PLUGIN_INIT, "KMF_ERR_PLUGIN_INIT"}, 70 {KMF_ERR_PLUGIN_NOTFOUND, "KMF_ERR_PLUGIN_NOTFOUND"}, 71 {KMF_ERR_INTERNAL, "KMF_ERR_INTERNAL"}, 72 {KMF_ERR_BAD_CERT_FORMAT, "KMF_ERR_BAD_CERT_FORMAT"}, 73 {KMF_ERR_KEYGEN_FAILED, "KMF_ERR_KEYGEN_FAILED"}, 74 {KMF_ERR_UNINITIALIZED, "KMF_ERR_UNINITIALIZED"}, 75 {KMF_ERR_ISSUER, "KMF_ERR_ISSUER"}, 76 {KMF_ERR_NOT_REVOKED, "KMF_ERR_NOT_REVOKED"}, 77 {KMF_ERR_CERT_NOT_FOUND, "KMF_ERR_CERT_NOT_FOUND"}, 78 {KMF_ERR_CRL_NOT_FOUND, "KMF_ERR_CRL_NOT_FOUND"}, 79 {KMF_ERR_RDN_PARSER, "KMF_ERR_RDN_PARSER"}, 80 {KMF_ERR_RDN_ATTR, "KMF_ERR_RDN_ATTR"}, 81 {KMF_ERR_SLOTNAME, "KMF_ERR_SLOTNAME"}, 82 {KMF_ERR_EMPTY_CRL, "KMF_ERR_EMPTY_CRL"}, 83 {KMF_ERR_BUFFER_SIZE, "KMF_ERR_BUFFER_SIZE"}, 84 {KMF_ERR_AUTH_FAILED, "KMF_ERR_AUTH_FAILED"}, 85 {KMF_ERR_TOKEN_SELECTED, "KMF_ERR_TOKEN_SELECTED"}, 86 {KMF_ERR_NO_TOKEN_SELECTED, "KMF_ERR_NO_TOKEN_SELECTED"}, 87 {KMF_ERR_TOKEN_NOT_PRESENT, "KMF_ERR_TOKEN_NOT_PRESENT"}, 88 {KMF_ERR_EXTENSION_NOT_FOUND, "KMF_ERR_EXTENSION_NOT_FOUND"}, 89 {KMF_ERR_POLICY_ENGINE, "KMF_ERR_POLICY_ENGINE"}, 90 {KMF_ERR_POLICY_DB_FORMAT, "KMF_ERR_POLICY_DB_FORMAT"}, 91 {KMF_ERR_POLICY_NOT_FOUND, "KMF_ERR_POLICY_NOT_FOUND"}, 92 {KMF_ERR_POLICY_DB_FILE, "KMF_ERR_POLICY_DB_FILE"}, 93 {KMF_ERR_POLICY_NAME, "KMF_ERR_POLICY_NAME"}, 94 {KMF_ERR_OCSP_POLICY, "KMF_ERR_OCSP_POLICY"}, 95 {KMF_ERR_TA_POLICY, "KMF_ERR_TA_POLICY"}, 96 {KMF_ERR_KEY_NOT_FOUND, "KMF_ERR_KEY_NOT_FOUND"}, 97 {KMF_ERR_OPEN_FILE, "KMF_ERR_OPEN_FILE"}, 98 {KMF_ERR_OCSP_BAD_ISSUER, "KMF_ERR_OCSP_BAD_ISSUER"}, 99 {KMF_ERR_OCSP_BAD_CERT, "KMF_ERR_OCSP_BAD_CERT"}, 100 {KMF_ERR_OCSP_CREATE_REQUEST, "KMF_ERR_OCSP_CREATE_REQUEST"}, 101 {KMF_ERR_CONNECT_SERVER, "KMF_ERR_CONNECT_SERVER"}, 102 {KMF_ERR_SEND_REQUEST, "KMF_ERR_SEND_REQUEST"}, 103 {KMF_ERR_OCSP_CERTID, "KMF_ERR_OCSP_CERTID"}, 104 {KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"}, 105 {KMF_ERR_OCSP_RESPONSE_STATUS, "KMF_ERR_OCSP_RESPONSE_STATUS"}, 106 {KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"}, 107 {KMF_ERR_OCSP_BAD_SIGNER, "KMF_ERR_OCSP_BAD_SIGNER"}, 108 {KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"}, 109 {KMF_ERR_OCSP_UNKNOWN_CERT, "KMF_ERR_OCSP_UNKNOWN_CERT"}, 110 {KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"}, 111 {KMF_ERR_BAD_HTTP_RESPONSE, "KMF_ERR_BAD_HTTP_RESPONSE"}, 112 {KMF_ERR_RECV_RESPONSE, "KMF_ERR_RECV_RESPONSE"}, 113 {KMF_ERR_RECV_TIMEOUT, "KMF_ERR_RECV_TIMEOUT"}, 114 {KMF_ERR_DUPLICATE_KEYFILE, "KMF_ERR_DUPLICATE_KEYFILE"}, 115 {KMF_ERR_AMBIGUOUS_PATHNAME, "KMF_ERR_AMBIGUOUS_PATHNAME"}, 116 {KMF_ERR_FUNCTION_NOT_FOUND, "KMF_ERR_FUNCTION_NOT_FOUND"}, 117 {KMF_ERR_PKCS12_FORMAT, "KMF_ERR_PKCS12_FORMAT"}, 118 {KMF_ERR_BAD_KEY_TYPE, "KMF_ERR_BAD_KEY_TYPE"}, 119 {KMF_ERR_BAD_KEY_CLASS, "KMF_ERR_BAD_KEY_CLASS"}, 120 {KMF_ERR_BAD_KEY_SIZE, "KMF_ERR_BAD_KEY_SIZE"}, 121 {KMF_ERR_BAD_HEX_STRING, "KMF_ERR_BAD_HEX_STRING"}, 122 {KMF_ERR_KEYUSAGE, "KMF_ERR_KEYUSAGE"}, 123 {KMF_ERR_VALIDITY_PERIOD, "KMF_ERR_VALIDITY_PERIOD"}, 124 {KMF_ERR_OCSP_REVOKED, "KMF_ERR_OCSP_REVOKED"}, 125 {KMF_ERR_CERT_MULTIPLE_FOUND, "KMF_ERR_CERT_MULTIPLE_FOUND"}, 126 {KMF_ERR_WRITE_FILE, "KMF_ERR_WRITE_FILE"}, 127 {KMF_ERR_BAD_URI, "KMF_ERR_BAD_URI"}, 128 {KMF_ERR_BAD_CRLFILE, "KMF_ERR_BAD_CRLFILE"}, 129 {KMF_ERR_BAD_CERTFILE, "KMF_ERR_BAD_CERTFILE"}, 130 {KMF_ERR_GETKEYVALUE_FAILED, "KMF_ERR_GETKEYVALUE_FAILED"}, 131 {KMF_ERR_BAD_KEYHANDLE, "KMF_ERR_BAD_KEYHANDLE"}, 132 {KMF_ERR_BAD_OBJECT_TYPE, "KMF_ERR_BAD_OBJECT_TYPE"}, 133 {KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"}, 134 {KMF_ERR_UNKNOWN_CSR_ATTRIBUTE, "KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"}, 135 {KMF_ERR_UNINITIALIZED_TOKEN, "KMF_ERR_UNINITIALIZED_TOKEN"}, 136 {KMF_ERR_INCOMPLETE_TBS_CERT, "KMF_ERR_INCOMPLETE_TBS_CERT"}, 137 {KMF_ERR_MISSING_ERRCODE, "KMF_ERR_MISSING_ERRCODE"}, 138 {KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"} 139 }; 140 141 142 static void free_extensions(KMF_X509_EXTENSIONS *extns); 143 144 int 145 is_pk11_ready() 146 { 147 return (pkcs11_initialized); 148 } 149 150 /* 151 * Private method for searching the plugin list for the correct 152 * Plugin to use. 153 */ 154 KMF_PLUGIN * 155 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype) 156 { 157 KMF_PLUGIN_LIST *node; 158 159 if (handle == NULL) 160 return (NULL); 161 162 node = handle->plugins; 163 164 while (node != NULL && node->plugin->type != kstype) 165 node = node->next; 166 167 /* If it is NULL, that is indication enough of an error */ 168 return (node ? node->plugin : NULL); 169 } 170 171 static KMF_RETURN 172 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin) 173 { 174 KMF_PLUGIN *p = NULL; 175 KMF_PLUGIN_FUNCLIST *(*sym)(); 176 177 if (path == NULL || plugin == NULL) 178 return (KMF_ERR_BAD_PARAMETER); 179 180 *plugin = NULL; 181 182 p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN)); 183 if (p == NULL) 184 return (KMF_ERR_MEMORY); 185 186 p->type = kstype; 187 p->path = strdup(path); 188 if (p->path == NULL) { 189 free(p); 190 return (KMF_ERR_MEMORY); 191 } 192 p->dldesc = dlopen(path, RTLD_NOW | RTLD_GROUP | RTLD_PARENT); 193 if (p->dldesc == NULL) { 194 free(p->path); 195 free(p); 196 return (KMF_ERR_PLUGIN_INIT); 197 } 198 199 sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc, 200 KMF_PLUGIN_INIT_SYMBOL); 201 if (sym == NULL) { 202 (void) dlclose(p->dldesc); 203 free(p->path); 204 free(p); 205 return (KMF_ERR_PLUGIN_INIT); 206 } 207 208 /* Get the function list */ 209 if ((p->funclist = (*sym)()) == NULL) { 210 (void) dlclose(p->dldesc); 211 free(p->path); 212 free(p); 213 return (KMF_ERR_PLUGIN_INIT); 214 } 215 216 *plugin = p; 217 218 return (KMF_OK); 219 } 220 221 static KMF_RETURN 222 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin) 223 { 224 KMF_PLUGIN_LIST *n; 225 226 if (handle == NULL || plugin == NULL) 227 return (KMF_ERR_BAD_PARAMETER); 228 229 /* If the head is NULL, create it */ 230 if (handle->plugins == NULL) { 231 handle->plugins = (KMF_PLUGIN_LIST *)malloc( 232 sizeof (KMF_PLUGIN_LIST)); 233 if (handle->plugins == NULL) 234 return (KMF_ERR_MEMORY); 235 handle->plugins->plugin = plugin; 236 handle->plugins->next = NULL; 237 } else { 238 /* walk the list to find the tail */ 239 n = handle->plugins; 240 while (n->next != NULL) 241 n = n->next; 242 n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST)); 243 if (n->next == NULL) 244 return (KMF_ERR_MEMORY); 245 246 n->next->plugin = plugin; 247 n->next->next = NULL; 248 } 249 return (0); 250 } 251 252 static void 253 DestroyPlugin(KMF_PLUGIN *plugin) 254 { 255 if (plugin) { 256 if (plugin->path) 257 free(plugin->path); 258 free(plugin); 259 } 260 } 261 262 static void 263 Cleanup_KMF_Handle(KMF_HANDLE_T handle) 264 { 265 if (handle != NULL) { 266 while (handle->plugins != NULL) { 267 KMF_PLUGIN_LIST *next = handle->plugins->next; 268 269 DestroyPlugin(handle->plugins->plugin); 270 271 free(handle->plugins); 272 273 handle->plugins = next; 274 } 275 276 KMF_FreePolicyRecord(handle->policy); 277 free(handle->policy); 278 } 279 free(handle); 280 } 281 282 void 283 Cleanup_PK11_Session(KMF_HANDLE_T handle) 284 { 285 if (handle != NULL) { 286 /* Close active session on a pkcs11 token */ 287 if (handle->pk11handle != NULL) { 288 (void) C_CloseSession(handle->pk11handle); 289 handle->pk11handle = NULL; 290 } 291 } 292 } 293 294 KMF_RETURN 295 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname) 296 { 297 KMF_RETURN ret = KMF_OK; 298 KMF_HANDLE *handle = NULL; 299 KMF_PLUGIN *pluginrec = NULL; 300 301 if (outhandle == NULL) 302 return (KMF_ERR_BAD_PARAMETER); 303 304 *outhandle = NULL; 305 handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE)); 306 if (handle == NULL) 307 return (KMF_ERR_MEMORY); 308 309 (void) memset(handle, 0, sizeof (KMF_HANDLE)); 310 handle->plugins = NULL; 311 312 (void) mutex_lock(&init_lock); 313 if (!pkcs11_initialized) { 314 CK_RV rv = C_Initialize(NULL); 315 if ((rv != CKR_OK) && 316 (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 317 ret = KMF_ERR_UNINITIALIZED; 318 (void) mutex_unlock(&init_lock); 319 goto errout; 320 } else { 321 pkcs11_initialized = 1; 322 } 323 } 324 (void) mutex_unlock(&init_lock); 325 326 /* Initialize the handle with the policy */ 327 ret = KMF_SetPolicy((void *)handle, 328 policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile, 329 policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname); 330 if (ret != KMF_OK) 331 goto errout; 332 333 /* Create a record for the plugin */ 334 if ((ret = InitializePlugin(KMF_KEYSTORE_NSS, 335 KMF_PLUGIN_PATH "kmf_nss.so.1", &pluginrec)) != KMF_OK) 336 goto errout; 337 338 /* Add it to the handle */ 339 if (pluginrec != NULL) { 340 if ((ret = AddPlugin(handle, pluginrec))) 341 goto errout; 342 } 343 if ((ret = InitializePlugin(KMF_KEYSTORE_OPENSSL, 344 KMF_PLUGIN_PATH "kmf_openssl.so.1", &pluginrec)) != KMF_OK) 345 goto errout; 346 347 /* Add it to the handle */ 348 if (pluginrec != NULL) 349 if ((ret = AddPlugin(handle, pluginrec))) 350 goto errout; 351 352 if ((ret = InitializePlugin(KMF_KEYSTORE_PK11TOKEN, 353 KMF_PLUGIN_PATH "kmf_pkcs11.so.1", &pluginrec)) != KMF_OK) 354 goto errout; 355 356 /* Add it to the handle */ 357 if (pluginrec != NULL) 358 if ((ret = AddPlugin(handle, pluginrec))) 359 goto errout; 360 361 CLEAR_ERROR(handle, ret); 362 errout: 363 if (ret != KMF_OK) { 364 Cleanup_KMF_Handle(handle); 365 handle = NULL; 366 } 367 368 *outhandle = (KMF_HANDLE_T)handle; 369 return (ret); 370 } 371 372 KMF_RETURN 373 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params) 374 { 375 KMF_PLUGIN *plugin; 376 KMF_RETURN ret; 377 378 CLEAR_ERROR(handle, ret); 379 if (ret != KMF_OK) 380 return (ret); 381 382 if (params == NULL) 383 return (KMF_ERR_BAD_PARAMETER); 384 385 plugin = FindPlugin(handle, params->kstype); 386 if (plugin == NULL) 387 return (KMF_ERR_PLUGIN_NOTFOUND); 388 389 if (plugin->funclist->ConfigureKeystore != NULL) 390 return (plugin->funclist->ConfigureKeystore(handle, params)); 391 else 392 /* return KMF_OK, if the plugin does not have an entry */ 393 return (KMF_OK); 394 } 395 396 KMF_RETURN 397 KMF_Finalize(KMF_HANDLE_T handle) 398 { 399 KMF_RETURN ret = KMF_OK; 400 401 CLEAR_ERROR(handle, ret); 402 if (ret != KMF_OK) 403 return (ret); 404 405 if (pkcs11_initialized) { 406 Cleanup_PK11_Session(handle); 407 } 408 Cleanup_KMF_Handle(handle); 409 410 return (ret); 411 } 412 413 KMF_RETURN 414 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg) 415 { 416 KMF_RETURN ret = KMF_OK; 417 int i, maxerr; 418 419 if (errmsg == NULL) 420 return (KMF_ERR_BAD_PARAMETER); 421 422 *errmsg = NULL; 423 maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map); 424 425 for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++); 426 427 if (i == maxerr) 428 return (KMF_ERR_MISSING_ERRCODE); 429 else { 430 *errmsg = strdup(kmf_errcodes[i].message); 431 if ((*errmsg) == NULL) 432 return (KMF_ERR_MEMORY); 433 } 434 return (ret); 435 } 436 437 KMF_RETURN 438 KMF_GetPluginErrorString(KMF_HANDLE_T handle, char **msgstr) 439 { 440 KMF_RETURN ret = KMF_OK; 441 KMF_PLUGIN *plugin; 442 443 if (handle == NULL || msgstr == NULL) 444 return (KMF_ERR_BAD_PARAMETER); 445 446 *msgstr = NULL; 447 448 if (handle->lasterr.errcode == 0) { 449 return (KMF_ERR_MISSING_ERRCODE); 450 } 451 452 if (handle->lasterr.kstype == -1) { /* System error */ 453 char *str = strerror(handle->lasterr.errcode); 454 if (str != NULL) { 455 *msgstr = strdup(str); 456 if ((*msgstr) == NULL) 457 return (KMF_ERR_MEMORY); 458 } 459 return (KMF_OK); 460 } 461 462 plugin = FindPlugin(handle, handle->lasterr.kstype); 463 if (plugin == NULL) 464 return (KMF_ERR_PLUGIN_NOTFOUND); 465 466 if (plugin->funclist->GetErrorString != NULL) { 467 ret = plugin->funclist->GetErrorString(handle, msgstr); 468 } else { 469 return (KMF_ERR_FUNCTION_NOT_FOUND); 470 } 471 472 return (ret); 473 } 474 475 KMF_RETURN 476 KMF_DNParser(char *string, KMF_X509_NAME *name) 477 { 478 KMF_RETURN err; 479 480 if (string == NULL || name == NULL) 481 return (KMF_ERR_BAD_PARAMETER); 482 483 err = ParseDistinguishedName(string, (int)strlen(string), name); 484 return (err); 485 } 486 487 KMF_RETURN 488 KMF_DN2Der(KMF_X509_NAME *dn, KMF_DATA *der) 489 { 490 KMF_RETURN rv; 491 492 if (dn == NULL || der == NULL) 493 return (KMF_ERR_BAD_PARAMETER); 494 495 rv = DerEncodeName(dn, der); 496 return (rv); 497 } 498 499 #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c; 500 501 KMF_RETURN 502 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename, KMF_DATA *pdata) 503 { 504 struct stat s; 505 long nread, total = 0; 506 int fd; 507 unsigned char *buf = NULL; 508 KMF_RETURN ret; 509 510 CLEAR_ERROR(handle, ret); 511 if (ret != KMF_OK) 512 return (ret); 513 514 515 if (filename == NULL || pdata == NULL) { 516 return (KMF_ERR_BAD_PARAMETER); 517 } 518 519 if ((fd = open(filename, O_RDONLY)) < 0) { 520 SET_SYS_ERROR(handle, errno); 521 return (KMF_ERR_OPEN_FILE); 522 } 523 524 if (fstat(fd, &s) < 0) { 525 SET_SYS_ERROR(handle, errno); 526 (void) close(fd); 527 return (KMF_ERR_OPEN_FILE); 528 } 529 530 if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) { 531 (void) close(fd); 532 return (KMF_ERR_MEMORY); 533 } 534 535 do { 536 nread = read(fd, buf+total, s.st_size-total); 537 if (nread < 0) { 538 SET_SYS_ERROR(handle, errno); 539 (void) close(fd); 540 free(buf); 541 return (KMF_ERR_INTERNAL); 542 } 543 total += nread; 544 } while (total < s.st_size); 545 546 pdata->Data = buf; 547 pdata->Length = s.st_size; 548 (void) close(fd); 549 return (KMF_OK); 550 } 551 552 /* 553 * 554 * Name: KMF_Der2Pem 555 * 556 * Description: 557 * Function for converting DER encoded format to PEM encoded format 558 * 559 * Parameters: 560 * type(input) - CERTIFICATE or CSR 561 * data(input) - pointer to the DER encoded data 562 * len(input) - length of input data 563 * out(output) - contains the output buffer address to be returned 564 * outlen(output) - pointer to the returned output length 565 * 566 * Returns: 567 * A KMF_RETURN value indicating success or specifying a particular 568 * error condition. 569 * The value KMF_OK indicates success. All other values represent 570 * an error condition. 571 * 572 */ 573 KMF_RETURN 574 KMF_Der2Pem(KMF_OBJECT_TYPE type, unsigned char *data, 575 int len, unsigned char **out, int *outlen) 576 { 577 578 KMF_RETURN err; 579 if (data == NULL || out == NULL || outlen == NULL) 580 return (KMF_ERR_BAD_PARAMETER); 581 582 err = Der2Pem(type, data, len, out, outlen); 583 return (err); 584 585 } 586 587 /* 588 * 589 * Name: KMF_Pem2Der 590 * 591 * Description: 592 * Function for converting PEM encoded format to DER encoded format 593 * 594 * Parameters: 595 * in(input) - pointer to the PEM encoded data 596 * inlen(input) - length of input data 597 * out(output) - contains the output buffer address to be returned 598 * outlen(output) - pointer to the returned output length 599 * 600 * Returns: 601 * A KMF_RETURN value indicating success or specifying a particular 602 * error condition. 603 * The value KMF_OK indicates success. All other values represent 604 * an error condition. 605 * 606 */ 607 KMF_RETURN 608 KMF_Pem2Der(unsigned char *in, int inlen, 609 unsigned char **out, int *outlen) 610 { 611 KMF_RETURN err; 612 if (in == NULL || out == NULL || outlen == NULL) 613 return (KMF_ERR_BAD_PARAMETER); 614 615 err = Pem2Der(in, inlen, out, outlen); 616 return (err); 617 } 618 619 char * 620 KMF_OID2String(KMF_OID *oid) 621 { 622 char numstr[128]; 623 uint32_t number; 624 int numshift; 625 uint32_t i, string_length; 626 uchar_t *cp; 627 char *bp; 628 629 /* First determine the size of the string */ 630 string_length = 0; 631 number = 0; 632 numshift = 0; 633 cp = (unsigned char *)oid->Data; 634 635 number = (uint32_t)cp[0]; 636 (void) sprintf(numstr, "%d ", number/40); 637 638 string_length += strlen(numstr); 639 (void) sprintf(numstr, "%d ", number%40); 640 641 string_length += strlen(numstr); 642 643 for (i = 1; i < oid->Length; i++) { 644 if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) { 645 number = (number << 7) | (cp[i] & 0x7f); 646 numshift += 7; 647 } else { 648 return (NULL); 649 } 650 651 if ((cp[i] & 0x80) == 0) { 652 (void) sprintf(numstr, "%d ", number); 653 string_length += strlen(numstr); 654 number = 0; 655 numshift = 0; 656 } 657 } 658 /* 659 * If we get here, we've calculated the length of "n n n ... n ". Add 4 660 * here for "{ " and "}\0". 661 */ 662 string_length += 4; 663 if ((bp = (char *)malloc(string_length))) { 664 number = (uint32_t)cp[0]; 665 666 (void) sprintf(numstr, "%d.", number/40); 667 (void) strcpy(bp, numstr); 668 669 (void) sprintf(numstr, "%d.", number%40); 670 (void) strcat(bp, numstr); 671 672 number = 0; 673 cp = (unsigned char *) oid->Data; 674 for (i = 1; i < oid->Length; i++) { 675 number = (number << 7) | (cp[i] & 0x7f); 676 if ((cp[i] & 0x80) == 0) { 677 (void) sprintf(numstr, "%d", number); 678 (void) strcat(bp, numstr); 679 number = 0; 680 if (i+1 < oid->Length) 681 (void) strcat(bp, "."); 682 } 683 } 684 } 685 return (bp); 686 } 687 688 KMF_RETURN 689 KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt) 690 { 691 int f; 692 KMF_RETURN ret = KMF_OK; 693 uchar_t buf[16]; 694 695 if (filename == NULL || !strlen(filename) || fmt == NULL) 696 return (KMF_ERR_BAD_PARAMETER); 697 698 *fmt = 0; 699 if ((f = open(filename, O_RDONLY)) == -1) { 700 return (KMF_ERR_OPEN_FILE); 701 } 702 703 if (read(f, buf, 8) != 8) { 704 ret = KMF_ERR_OPEN_FILE; 705 goto end; 706 } 707 708 if (memcmp(buf, "-----BEG", 8) == 0) { 709 *fmt = KMF_FORMAT_PEM; 710 } else if (buf[0] == 0x30 && (buf[1] & 0x80)) { 711 if ((buf[1] & 0xFF) == 0x80 && 712 (buf[2] & 0xFF) == 0x02 && 713 (buf[5] & 0xFF) == 0x30) { 714 *fmt = KMF_FORMAT_PKCS12; 715 } else if ((buf[1] & 0xFF) == 0x82 && 716 (buf[4] & 0xFF) == 0x02 && 717 (buf[7] & 0xFF) == 0x30) { 718 *fmt = KMF_FORMAT_PKCS12; 719 /* It is most likely a generic ASN.1 encoded file */ 720 } else { 721 *fmt = KMF_FORMAT_ASN1; 722 } 723 } else { 724 /* Cannot determine this file format */ 725 *fmt = 0; 726 ret = KMF_ERR_ENCODING; 727 } 728 end: 729 (void) close(f); 730 return (ret); 731 } 732 733 KMF_RETURN 734 KMF_HexString2Bytes(unsigned char *hexstr, unsigned char **bytes, 735 size_t *outlen) 736 { 737 KMF_RETURN ret = KMF_OK; 738 unsigned char *buf = NULL; 739 int len, stringlen; 740 int i; 741 unsigned char ch; 742 743 if (hexstr == NULL) { 744 return (KMF_ERR_BAD_PARAMETER); 745 } 746 747 if (hexstr[0] == '0' && 748 ((hexstr[1] == 'x') || (hexstr[1] == 'X'))) 749 hexstr += 2; 750 751 for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++); 752 /* 753 * If all the characters are not legitimate hex chars, 754 * return an error. 755 */ 756 if (i != strlen((char *)hexstr)) 757 return (KMF_ERR_BAD_HEX_STRING); 758 stringlen = i; 759 len = (i / 2) + (i % 2); 760 761 buf = malloc(len); 762 if (buf == NULL) { 763 return (KMF_ERR_MEMORY); 764 } 765 (void) memset(buf, 0, len); 766 767 for (i = 0; i < stringlen; i++) { 768 ch = (unsigned char) *hexstr; 769 hexstr++; 770 if ((ch >= '0') && (ch <= '9')) 771 ch -= '0'; 772 else if ((ch >= 'A') && (ch <= 'F')) 773 ch = ch - 'A' + 10; 774 else if ((ch >= 'a') && (ch <= 'f')) 775 ch = ch - 'a' + 10; 776 else { 777 ret = KMF_ERR_BAD_HEX_STRING; 778 goto out; 779 } 780 781 if (i & 1) { 782 buf[i/2] |= ch; 783 } else { 784 buf[i/2] = (ch << 4); 785 } 786 } 787 788 *bytes = buf; 789 *outlen = len; 790 out: 791 if (buf != NULL && ret != KMF_OK) { 792 free(buf); 793 } 794 return (ret); 795 } 796 797 void 798 KMF_FreeDN(KMF_X509_NAME *name) 799 { 800 KMF_X509_RDN *newrdn = NULL; 801 KMF_X509_TYPE_VALUE_PAIR *av = NULL; 802 int i, j; 803 804 if (name && name->numberOfRDNs) { 805 for (i = 0; i < name->numberOfRDNs; i++) { 806 newrdn = &name->RelativeDistinguishedName[i]; 807 for (j = 0; j < newrdn->numberOfPairs; j++) { 808 av = &newrdn->AttributeTypeAndValue[j]; 809 KMF_FreeData(&av->type); 810 KMF_FreeData(&av->value); 811 } 812 free(newrdn->AttributeTypeAndValue); 813 newrdn->numberOfPairs = 0; 814 newrdn->AttributeTypeAndValue = NULL; 815 } 816 free(name->RelativeDistinguishedName); 817 name->numberOfRDNs = 0; 818 name->RelativeDistinguishedName = NULL; 819 } 820 } 821 822 void 823 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert) 824 { 825 KMF_PLUGIN *plugin; 826 KMF_RETURN ret; 827 828 CLEAR_ERROR(handle, ret); 829 if (ret != KMF_OK) 830 return; 831 832 if (kmf_cert == NULL) 833 return; 834 835 plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type); 836 837 if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) { 838 plugin->funclist->FreeKMFCert(handle, kmf_cert); 839 } 840 } 841 842 void 843 KMF_FreeData(KMF_DATA *datablock) 844 { 845 if (datablock != NULL && datablock->Data != NULL) { 846 free(datablock->Data); 847 datablock->Data = NULL; 848 datablock->Length = 0; 849 } 850 } 851 852 void 853 KMF_FreeAlgOID(KMF_X509_ALGORITHM_IDENTIFIER *algoid) 854 { 855 if (algoid == NULL) 856 return; 857 KMF_FreeData(&algoid->algorithm); 858 KMF_FreeData(&algoid->parameters); 859 } 860 861 void 862 KMF_FreeExtension(KMF_X509_EXTENSION *exptr) 863 { 864 if (exptr == NULL) 865 return; 866 867 KMF_FreeData((KMF_DATA *)&exptr->extnId); 868 KMF_FreeData(&exptr->BERvalue); 869 870 if (exptr->value.tagAndValue) { 871 KMF_FreeData(&exptr->value.tagAndValue->value); 872 free(exptr->value.tagAndValue); 873 } 874 } 875 876 void 877 KMF_FreeTBSCSR(KMF_TBS_CSR *tbscsr) 878 { 879 if (tbscsr) { 880 KMF_FreeData(&tbscsr->version); 881 882 KMF_FreeDN(&tbscsr->subject); 883 884 KMF_FreeAlgOID(&tbscsr->subjectPublicKeyInfo.algorithm); 885 KMF_FreeData(&tbscsr->subjectPublicKeyInfo.subjectPublicKey); 886 887 free_extensions(&tbscsr->extensions); 888 } 889 } 890 891 void 892 KMF_FreeSignedCSR(KMF_CSR_DATA *csr) 893 { 894 if (csr) { 895 KMF_FreeTBSCSR(&csr->csr); 896 897 KMF_FreeAlgOID(&csr->signature.algorithmIdentifier); 898 KMF_FreeData(&csr->signature.encrypted); 899 } 900 } 901 902 static void 903 free_validity(KMF_X509_VALIDITY *validity) 904 { 905 if (validity == NULL) 906 return; 907 KMF_FreeData(&validity->notBefore.time); 908 KMF_FreeData(&validity->notAfter.time); 909 } 910 911 static void 912 free_extensions(KMF_X509_EXTENSIONS *extns) 913 { 914 int i; 915 KMF_X509_EXTENSION *exptr; 916 917 if (extns && extns->numberOfExtensions > 0) { 918 for (i = 0; i < extns->numberOfExtensions; i++) { 919 exptr = &extns->extensions[i]; 920 KMF_FreeExtension(exptr); 921 } 922 free(extns->extensions); 923 extns->numberOfExtensions = 0; 924 extns->extensions = NULL; 925 } 926 } 927 928 void 929 KMF_FreeTBSCert(KMF_X509_TBS_CERT *tbscert) 930 { 931 if (tbscert) { 932 KMF_FreeData(&tbscert->version); 933 KMF_FreeBigint(&tbscert->serialNumber); 934 KMF_FreeAlgOID(&tbscert->signature); 935 936 KMF_FreeDN(&tbscert->issuer); 937 KMF_FreeDN(&tbscert->subject); 938 939 free_validity(&tbscert->validity); 940 941 KMF_FreeData(&tbscert->issuerUniqueIdentifier); 942 KMF_FreeData(&tbscert->subjectUniqueIdentifier); 943 944 KMF_FreeAlgOID(&tbscert->subjectPublicKeyInfo.algorithm); 945 KMF_FreeData(&tbscert->subjectPublicKeyInfo.subjectPublicKey); 946 947 free_extensions(&tbscert->extensions); 948 949 KMF_FreeData(&tbscert->issuerUniqueIdentifier); 950 KMF_FreeData(&tbscert->subjectUniqueIdentifier); 951 } 952 } 953 954 void 955 KMF_FreeSignedCert(KMF_X509_CERTIFICATE *certptr) 956 { 957 if (!certptr) 958 return; 959 960 KMF_FreeTBSCert(&certptr->certificate); 961 962 KMF_FreeAlgOID(&certptr->signature.algorithmIdentifier); 963 KMF_FreeData(&certptr->signature.encrypted); 964 } 965 966 void 967 KMF_FreeString(char *pstr) 968 { 969 if (pstr != NULL) 970 free(pstr); 971 } 972 973 void 974 free_keyidlist(KMF_OID *oidlist, int len) 975 { 976 int i; 977 for (i = 0; i < len; i++) { 978 KMF_FreeData((KMF_DATA *)&oidlist[i]); 979 } 980 free(oidlist); 981 } 982 983 void 984 KMF_FreeEKU(KMF_X509EXT_EKU *eptr) 985 { 986 if (eptr && eptr->nEKUs > 0 && 987 eptr->keyPurposeIdList != NULL) 988 free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs); 989 } 990 991 void 992 KMF_FreeSPKI(KMF_X509_SPKI *spki) 993 { 994 if (spki != NULL) { 995 KMF_FreeAlgOID(&spki->algorithm); 996 KMF_FreeData(&spki->subjectPublicKey); 997 } 998 } 999 1000 void 1001 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key) 1002 { 1003 KMF_PLUGIN *plugin; 1004 KMF_RETURN ret; 1005 1006 CLEAR_ERROR(handle, ret); 1007 if (ret != KMF_OK) 1008 return; 1009 1010 if (key == NULL) 1011 return; 1012 1013 plugin = FindPlugin(handle, key->kstype); 1014 if (plugin != NULL && plugin->funclist->DeleteKey != NULL) { 1015 (void) plugin->funclist->DeleteKey(handle, NULL, key, FALSE); 1016 } 1017 1018 if (key == NULL) 1019 return; 1020 1021 if (key->keylabel) 1022 free(key->keylabel); 1023 1024 if (key->israw) { 1025 KMF_FreeRawKey(key->keyp); 1026 free(key->keyp); 1027 } 1028 1029 (void) memset(key, 0, sizeof (KMF_KEY_HANDLE)); 1030 } 1031 1032 void 1033 KMF_FreeBigint(KMF_BIGINT *big) 1034 { 1035 if (big != NULL && big->val != NULL) { 1036 free(big->val); 1037 big->val = NULL; 1038 big->len = 0; 1039 } 1040 } 1041 1042 static void 1043 free_raw_rsa(KMF_RAW_RSA_KEY *key) 1044 { 1045 if (key == NULL) 1046 return; 1047 KMF_FreeBigint(&key->mod); 1048 KMF_FreeBigint(&key->pubexp); 1049 KMF_FreeBigint(&key->priexp); 1050 KMF_FreeBigint(&key->prime1); 1051 KMF_FreeBigint(&key->prime2); 1052 KMF_FreeBigint(&key->exp1); 1053 KMF_FreeBigint(&key->exp2); 1054 KMF_FreeBigint(&key->coef); 1055 } 1056 1057 static void 1058 free_raw_dsa(KMF_RAW_DSA_KEY *key) 1059 { 1060 if (key == NULL) 1061 return; 1062 KMF_FreeBigint(&key->prime); 1063 KMF_FreeBigint(&key->subprime); 1064 KMF_FreeBigint(&key->base); 1065 KMF_FreeBigint(&key->value); 1066 } 1067 1068 static void 1069 free_raw_sym(KMF_RAW_SYM_KEY *key) 1070 { 1071 if (key == NULL) 1072 return; 1073 KMF_FreeBigint(&key->keydata); 1074 } 1075 1076 void 1077 KMF_FreeRawKey(KMF_RAW_KEY_DATA *key) 1078 { 1079 if (key == NULL) 1080 return; 1081 1082 switch (key->keytype) { 1083 case KMF_RSA: 1084 free_raw_rsa(&key->rawdata.rsa); 1085 break; 1086 case KMF_DSA: 1087 free_raw_dsa(&key->rawdata.dsa); 1088 break; 1089 case KMF_AES: 1090 case KMF_RC4: 1091 case KMF_DES: 1092 case KMF_DES3: 1093 free_raw_sym(&key->rawdata.sym); 1094 break; 1095 } 1096 } 1097 1098 void 1099 KMF_FreeRawSymKey(KMF_RAW_SYM_KEY *key) 1100 { 1101 if (key == NULL) 1102 return; 1103 KMF_FreeBigint(&key->keydata); 1104 free(key); 1105 } 1106 1107 /* 1108 * This function frees the space allocated for the name portion of a 1109 * KMF_CRL_DIST_POINT. 1110 */ 1111 void 1112 free_dp_name(KMF_CRL_DIST_POINT *dp) 1113 { 1114 KMF_GENERALNAMES *fullname; 1115 KMF_DATA *urldata; 1116 int i; 1117 1118 if (dp == NULL) 1119 return; 1120 1121 /* For phase 1, we only need to free the fullname space. */ 1122 fullname = &(dp->name.full_name); 1123 if (fullname->number == 0) 1124 return; 1125 1126 for (i = 0; i < fullname->number; i++) { 1127 urldata = &(fullname->namelist[fullname->number - 1].name); 1128 KMF_FreeData(urldata); 1129 } 1130 1131 free(fullname->namelist); 1132 } 1133 1134 /* 1135 * This function frees the space allocated for a KMF_CRL_DIST_POINT. 1136 */ 1137 void 1138 free_dp(KMF_CRL_DIST_POINT *dp) 1139 { 1140 if (dp == NULL) 1141 return; 1142 1143 free_dp_name(dp); 1144 KMF_FreeData(&(dp->reasons)); 1145 /* Need not to free crl_issuer space at phase 1 */ 1146 } 1147 1148 /* 1149 * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally. 1150 */ 1151 void 1152 KMF_FreeCRLDistributionPoints(KMF_X509EXT_CRLDISTPOINTS *crl_dps) 1153 { 1154 int i; 1155 1156 if (crl_dps == NULL) 1157 return; 1158 1159 for (i = 0; i < crl_dps->number; i++) 1160 free_dp(&(crl_dps->dplist[i])); 1161 1162 free(crl_dps->dplist); 1163 } 1164 1165 KMF_RETURN 1166 KMF_CreateOCSPRequest(KMF_HANDLE_T handle, KMF_OCSPREQUEST_PARAMS *params, 1167 char *reqfile) 1168 { 1169 KMF_PLUGIN *plugin; 1170 KMF_RETURN (*createReqFn)(void *, KMF_OCSPREQUEST_PARAMS *params, 1171 char *reqfile); 1172 KMF_RETURN ret; 1173 1174 CLEAR_ERROR(handle, ret); 1175 if (ret != KMF_OK) 1176 return (ret); 1177 1178 1179 if (params == NULL || 1180 reqfile == NULL) 1181 return (KMF_ERR_BAD_PARAMETER); 1182 1183 /* 1184 * This framework function is actually implemented in the openssl 1185 * plugin library, so we find the function address and call it. 1186 */ 1187 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 1188 if (plugin == NULL || plugin->dldesc == NULL) { 1189 return (KMF_ERR_PLUGIN_NOTFOUND); 1190 } 1191 1192 createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc, 1193 "OpenSSL_CreateOCSPRequest"); 1194 if (createReqFn == NULL) { 1195 return (KMF_ERR_FUNCTION_NOT_FOUND); 1196 } 1197 1198 return (createReqFn(handle, params, reqfile)); 1199 } 1200 1201 KMF_RETURN 1202 KMF_GetOCSPStatusForCert(KMF_HANDLE_T handle, 1203 KMF_OCSPRESPONSE_PARAMS_INPUT *params_in, 1204 KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out) 1205 { 1206 KMF_PLUGIN *plugin; 1207 KMF_RETURN (*getCertStatusFn)(void *, 1208 KMF_OCSPRESPONSE_PARAMS_INPUT *params_in, 1209 KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out); 1210 KMF_RETURN ret; 1211 1212 CLEAR_ERROR(handle, ret); 1213 if (ret != KMF_OK) 1214 return (ret); 1215 1216 1217 if (params_in == NULL || 1218 params_out == NULL) 1219 return (KMF_ERR_BAD_PARAMETER); 1220 1221 /* 1222 * This framework function is actually implemented in the openssl 1223 * plugin library, so we find the function address and call it. 1224 */ 1225 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 1226 if (plugin == NULL || plugin->dldesc == NULL) { 1227 return (KMF_ERR_INTERNAL); 1228 } 1229 1230 getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc, 1231 "OpenSSL_GetOCSPStatusForCert"); 1232 if (getCertStatusFn == NULL) { 1233 return (KMF_ERR_INTERNAL); 1234 } 1235 1236 return (getCertStatusFn(handle, params_in, params_out)); 1237 } 1238 1239 KMF_RETURN 1240 KMF_String2OID(char *oidstring, KMF_OID *oid) 1241 { 1242 KMF_RETURN rv = KMF_OK; 1243 char *cp, *bp, *startp; 1244 int numbuf; 1245 int onumbuf; 1246 int nbytes, index; 1247 int len; 1248 unsigned char *op; 1249 1250 if (oidstring == NULL || oid == NULL) 1251 return (KMF_ERR_BAD_PARAMETER); 1252 1253 len = strlen(oidstring); 1254 1255 bp = oidstring; 1256 cp = bp; 1257 /* Skip over leading space */ 1258 while ((bp < &cp[len]) && isspace(*bp)) 1259 bp++; 1260 1261 startp = bp; 1262 nbytes = 0; 1263 1264 /* 1265 * The first two numbers are chewed up by the first octet. 1266 */ 1267 if (sscanf(bp, "%d", &numbuf) != 1) 1268 return (KMF_ERR_BAD_PARAMETER); 1269 while ((bp < &cp[len]) && isdigit(*bp)) 1270 bp++; 1271 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1272 bp++; 1273 if (sscanf(bp, "%d", &numbuf) != 1) 1274 return (KMF_ERR_BAD_PARAMETER); 1275 while ((bp < &cp[len]) && isdigit(*bp)) 1276 bp++; 1277 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1278 bp++; 1279 nbytes++; 1280 1281 while (isdigit(*bp)) { 1282 if (sscanf(bp, "%d", &numbuf) != 1) 1283 return (KMF_ERR_BAD_PARAMETER); 1284 while (numbuf) { 1285 nbytes++; 1286 numbuf >>= 7; 1287 } 1288 while ((bp < &cp[len]) && isdigit(*bp)) 1289 bp++; 1290 while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 1291 bp++; 1292 } 1293 1294 oid->Length = nbytes; 1295 oid->Data = malloc(oid->Length); 1296 if (oid->Data == NULL) { 1297 return (KMF_ERR_MEMORY); 1298 } 1299 (void) memset(oid->Data, 0, oid->Length); 1300 1301 op = oid->Data; 1302 1303 bp = startp; 1304 (void) sscanf(bp, "%d", &numbuf); 1305 1306 while (isdigit(*bp)) bp++; 1307 while (isspace(*bp) || *bp == '.') bp++; 1308 1309 onumbuf = 40 * numbuf; 1310 (void) sscanf(bp, "%d", &numbuf); 1311 onumbuf += numbuf; 1312 *op = (unsigned char) onumbuf; 1313 op++; 1314 1315 while (isdigit(*bp)) bp++; 1316 while (isspace(*bp) || *bp == '.') bp++; 1317 while (isdigit(*bp)) { 1318 (void) sscanf(bp, "%d", &numbuf); 1319 nbytes = 0; 1320 /* Have to fill in the bytes msb-first */ 1321 onumbuf = numbuf; 1322 while (numbuf) { 1323 nbytes++; 1324 numbuf >>= 7; 1325 } 1326 numbuf = onumbuf; 1327 op += nbytes; 1328 index = -1; 1329 while (numbuf) { 1330 op[index] = (unsigned char)numbuf & 0x7f; 1331 if (index != -1) 1332 op[index] |= 0x80; 1333 index--; 1334 numbuf >>= 7; 1335 } 1336 while (isdigit(*bp)) bp++; 1337 while (isspace(*bp) || *bp == '.') bp++; 1338 } 1339 1340 return (rv); 1341 } 1342 1343 static KMF_RETURN 1344 encode_rid(char *name, KMF_DATA *derdata) 1345 { 1346 KMF_RETURN rv = KMF_OK; 1347 1348 if (name == NULL || derdata == NULL) 1349 return (KMF_ERR_BAD_PARAMETER); 1350 1351 rv = KMF_String2OID(name, (KMF_OID *)derdata); 1352 1353 return (rv); 1354 } 1355 1356 static KMF_RETURN 1357 encode_ipaddr(char *name, KMF_DATA *derdata) 1358 { 1359 KMF_RETURN rv = KMF_OK; 1360 size_t len; 1361 in_addr_t v4; 1362 in6_addr_t v6; 1363 uint8_t *ptr; 1364 1365 if (name == NULL || derdata == NULL) 1366 return (KMF_ERR_BAD_PARAMETER); 1367 1368 v4 = inet_addr(name); 1369 if (v4 == (in_addr_t)-1) { 1370 ptr = (uint8_t *)&v6; 1371 if (inet_pton(AF_INET6, name, ptr) != 1) 1372 return (KMF_ERR_ENCODING); 1373 len = sizeof (v6); 1374 } else { 1375 ptr = (uint8_t *)&v4; 1376 len = sizeof (v4); 1377 } 1378 1379 derdata->Data = malloc(len); 1380 if (derdata->Data == NULL) 1381 return (KMF_ERR_MEMORY); 1382 (void) memcpy(derdata->Data, ptr, len); 1383 derdata->Length = len; 1384 1385 return (rv); 1386 } 1387 1388 static KMF_RETURN 1389 verify_uri_format(char *uristring) 1390 { 1391 KMF_RETURN ret = KMF_OK; 1392 xmlURIPtr uriptr = NULL; 1393 1394 /* Parse the URI string; get the hostname and port */ 1395 uriptr = xmlParseURI(uristring); 1396 if (uriptr == NULL) { 1397 ret = KMF_ERR_BAD_URI; 1398 goto out; 1399 } 1400 1401 if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) { 1402 ret = KMF_ERR_BAD_URI; 1403 goto out; 1404 } 1405 1406 if (uriptr->server == NULL || !strlen(uriptr->server)) { 1407 ret = KMF_ERR_BAD_URI; 1408 goto out; 1409 } 1410 out: 1411 if (uriptr != NULL) 1412 xmlFreeURI(uriptr); 1413 return (ret); 1414 } 1415 1416 static KMF_RETURN 1417 encode_altname(char *namedata, 1418 KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname) 1419 { 1420 KMF_RETURN ret = KMF_OK; 1421 KMF_X509_NAME dnname; 1422 uchar_t tagval; 1423 BerElement *asn1 = NULL; 1424 BerValue *extdata; 1425 1426 if (namedata == NULL || encodedname == NULL) 1427 return (KMF_ERR_BAD_PARAMETER); 1428 1429 /* 1430 * Encode the namedata according to rules in RFC 3280 for GeneralName. 1431 * The input "namedata" is assumed to be an ASCII string representation 1432 * of the AltName, we need to convert it to correct ASN.1 here before 1433 * adding it to the cert. 1434 */ 1435 switch (nametype) { 1436 case GENNAME_RFC822NAME: /* rfc 822 */ 1437 /* IA5String, no encoding needed */ 1438 encodedname->Data = (uchar_t *)strdup(namedata); 1439 if (encodedname->Data == NULL) 1440 return (KMF_ERR_MEMORY); 1441 encodedname->Length = strlen(namedata); 1442 tagval = (0x80 | nametype); 1443 break; 1444 case GENNAME_DNSNAME: /* rfc 1034 */ 1445 encodedname->Data = (uchar_t *)strdup(namedata); 1446 if (encodedname->Data == NULL) 1447 return (KMF_ERR_MEMORY); 1448 encodedname->Length = strlen(namedata); 1449 tagval = (0x80 | nametype); 1450 break; 1451 case GENNAME_URI: /* rfc 1738 */ 1452 ret = verify_uri_format(namedata); 1453 if (ret != KMF_OK) 1454 return (ret); 1455 /* IA5String, no encoding needed */ 1456 encodedname->Data = (uchar_t *)strdup(namedata); 1457 if (encodedname->Data == NULL) 1458 return (KMF_ERR_MEMORY); 1459 encodedname->Length = strlen(namedata); 1460 tagval = (0x80 | nametype); 1461 break; 1462 case GENNAME_IPADDRESS: 1463 ret = encode_ipaddr(namedata, encodedname); 1464 tagval = (0x80 | nametype); 1465 break; 1466 case GENNAME_REGISTEREDID: 1467 ret = encode_rid(namedata, encodedname); 1468 tagval = (0x80 | nametype); 1469 break; 1470 case GENNAME_DIRECTORYNAME: 1471 ret = KMF_DNParser(namedata, &dnname); 1472 if (ret == KMF_OK) { 1473 ret = KMF_DN2Der(&dnname, encodedname); 1474 } 1475 (void) KMF_FreeDN(&dnname); 1476 tagval = (0xA0 | nametype); 1477 break; 1478 default: 1479 /* unsupported */ 1480 return (KMF_ERR_BAD_PARAMETER); 1481 1482 } 1483 if (ret != KMF_OK) { 1484 KMF_FreeData(encodedname); 1485 return (ret); 1486 } 1487 1488 if ((asn1 = kmfder_alloc()) == NULL) 1489 return (KMF_ERR_MEMORY); 1490 1491 if (kmfber_printf(asn1, "Tl", 1492 tagval, encodedname->Length) == -1) 1493 goto cleanup; 1494 1495 if (kmfber_write(asn1, (char *)encodedname->Data, 1496 encodedname->Length, 0) == -1) { 1497 ret = KMF_ERR_ENCODING; 1498 goto cleanup; 1499 } 1500 if (kmfber_flatten(asn1, &extdata) == -1) { 1501 ret = KMF_ERR_ENCODING; 1502 goto cleanup; 1503 } 1504 1505 KMF_FreeData(encodedname); 1506 encodedname->Data = (uchar_t *)extdata->bv_val; 1507 encodedname->Length = extdata->bv_len; 1508 1509 free(extdata); 1510 1511 cleanup: 1512 if (asn1) 1513 kmfber_free(asn1, 1); 1514 1515 if (ret != KMF_OK) 1516 KMF_FreeData(encodedname); 1517 1518 return (ret); 1519 } 1520 1521 KMF_X509_EXTENSION * 1522 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid) 1523 { 1524 KMF_X509_EXTENSION *foundextn = NULL; 1525 int i; 1526 1527 if (exts == NULL || oid == NULL) 1528 return (NULL); 1529 1530 for (i = 0; i < exts->numberOfExtensions; i++) { 1531 if (IsEqualOid(oid, &exts->extensions[i].extnId)) { 1532 foundextn = &exts->extensions[i]; 1533 break; 1534 } 1535 } 1536 return (foundextn); 1537 } 1538 1539 KMF_RETURN 1540 GetSequenceContents(char *data, size_t len, 1541 char **contents, size_t *outlen) 1542 { 1543 KMF_RETURN ret = KMF_OK; 1544 BerElement *exasn1 = NULL; 1545 BerValue oldextn; 1546 int tag; 1547 size_t oldsize; 1548 char *olddata = NULL; 1549 1550 if (data == NULL || contents == NULL || outlen == NULL) 1551 return (KMF_ERR_BAD_PARAMETER); 1552 1553 /* 1554 * Decode the sequence of general names 1555 */ 1556 oldextn.bv_val = data; 1557 oldextn.bv_len = len; 1558 1559 if ((exasn1 = kmfder_init(&oldextn)) == NULL) { 1560 ret = KMF_ERR_MEMORY; 1561 goto out; 1562 } 1563 1564 /* 1565 * Unwrap the sequence to find the size of the block 1566 * of GeneralName items in the set. 1567 * 1568 * Peek at the tag and length ("tl"), 1569 * then consume them ("{"). 1570 */ 1571 if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT || 1572 oldsize == 0) { 1573 ret = KMF_ERR_ENCODING; 1574 goto out; 1575 } 1576 1577 olddata = malloc(oldsize); 1578 if (olddata == NULL) { 1579 ret = KMF_ERR_MEMORY; 1580 goto out; 1581 } 1582 (void) memset(olddata, 0, oldsize); 1583 /* 1584 * Read the entire blob of GeneralNames, we don't 1585 * need to interpret them now. 1586 */ 1587 if (kmfber_read(exasn1, olddata, oldsize) != oldsize) { 1588 ret = KMF_ERR_ENCODING; 1589 goto out; 1590 } 1591 out: 1592 if (exasn1 != NULL) 1593 kmfber_free(exasn1, 1); 1594 1595 if (ret != KMF_OK) { 1596 *contents = NULL; 1597 *outlen = 0; 1598 if (olddata != NULL) 1599 free(olddata); 1600 } else { 1601 *contents = olddata; 1602 *outlen = oldsize; 1603 } 1604 return (ret); 1605 } 1606 1607 KMF_RETURN 1608 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn) 1609 { 1610 KMF_RETURN ret = KMF_OK; 1611 KMF_X509_EXTENSION *extlist; 1612 1613 if (exts == NULL || newextn == NULL) 1614 return (KMF_ERR_BAD_PARAMETER); 1615 1616 extlist = malloc(sizeof (KMF_X509_EXTENSION) * 1617 (exts->numberOfExtensions + 1)); 1618 if (extlist == NULL) 1619 return (KMF_ERR_MEMORY); 1620 1621 (void) memcpy(extlist, exts->extensions, 1622 exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION)); 1623 1624 (void) memcpy(&extlist[exts->numberOfExtensions], newextn, 1625 sizeof (KMF_X509_EXTENSION)); 1626 1627 free(exts->extensions); 1628 exts->numberOfExtensions++; 1629 exts->extensions = extlist; 1630 1631 return (ret); 1632 } 1633 1634 KMF_RETURN 1635 KMF_SetAltName(KMF_X509_EXTENSIONS *extensions, 1636 KMF_OID *oid, 1637 int critical, 1638 KMF_GENERALNAMECHOICES nametype, 1639 char *namedata) 1640 { 1641 KMF_RETURN ret = KMF_OK; 1642 KMF_X509_EXTENSION subjAltName; 1643 KMF_DATA dername = { NULL, 0 }; 1644 BerElement *asn1 = NULL; 1645 BerValue *extdata; 1646 char *olddata = NULL; 1647 KMF_X509_EXTENSION *foundextn = NULL; 1648 size_t oldsize = 0; 1649 1650 if (extensions == NULL || oid == NULL || namedata == NULL) 1651 return (KMF_ERR_BAD_PARAMETER); 1652 1653 ret = encode_altname(namedata, nametype, &dername); 1654 1655 if (ret != KMF_OK) 1656 return (ret); 1657 1658 (void) memset(&subjAltName, 0, sizeof (subjAltName)); 1659 1660 ret = copy_data(&subjAltName.extnId, oid); 1661 if (ret != KMF_OK) 1662 goto out; 1663 /* 1664 * Check to see if this cert already has a subjectAltName. 1665 */ 1666 foundextn = FindExtn(extensions, oid); 1667 1668 if (foundextn != NULL) { 1669 ret = GetSequenceContents( 1670 (char *)foundextn->BERvalue.Data, 1671 foundextn->BERvalue.Length, 1672 &olddata, &oldsize); 1673 if (ret != KMF_OK) 1674 goto out; 1675 } 1676 1677 /* 1678 * Assume (!!) that the namedata given is already properly encoded. 1679 */ 1680 if ((asn1 = kmfder_alloc()) == NULL) 1681 return (KMF_ERR_MEMORY); 1682 1683 if (kmfber_printf(asn1, "{") == -1) { 1684 ret = KMF_ERR_ENCODING; 1685 goto out; 1686 } 1687 1688 /* Write the old extension data first */ 1689 if (olddata != NULL && oldsize > 0) { 1690 if (kmfber_write(asn1, olddata, oldsize, 0) == -1) { 1691 ret = KMF_ERR_ENCODING; 1692 goto out; 1693 } 1694 } 1695 1696 /* Now add the new name to the list */ 1697 if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) { 1698 ret = KMF_ERR_ENCODING; 1699 goto out; 1700 } 1701 1702 /* Now close the sequence */ 1703 if (kmfber_printf(asn1, "}") == -1) { 1704 ret = KMF_ERR_ENCODING; 1705 goto out; 1706 } 1707 if (kmfber_flatten(asn1, &extdata) == -1) { 1708 ret = KMF_ERR_ENCODING; 1709 goto out; 1710 } 1711 1712 /* 1713 * If we are just adding to an existing list of altNames, 1714 * just replace the BER data associated with the found extension. 1715 */ 1716 if (foundextn != NULL) { 1717 free(foundextn->BERvalue.Data); 1718 foundextn->critical = critical; 1719 foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val; 1720 foundextn->BERvalue.Length = extdata->bv_len; 1721 } else { 1722 subjAltName.critical = critical; 1723 subjAltName.format = KMF_X509_DATAFORMAT_ENCODED; 1724 subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val; 1725 subjAltName.BERvalue.Length = extdata->bv_len; 1726 ret = add_an_extension(extensions, &subjAltName); 1727 if (ret != KMF_OK) 1728 free(subjAltName.BERvalue.Data); 1729 } 1730 1731 free(extdata); 1732 out: 1733 if (olddata != NULL) 1734 free(olddata); 1735 1736 KMF_FreeData(&dername); 1737 if (ret != KMF_OK) 1738 KMF_FreeData(&subjAltName.extnId); 1739 if (asn1 != NULL) 1740 kmfber_free(asn1, 1); 1741 return (ret); 1742 } 1743