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