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