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) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
22 */
23
24 /*
25 * This file contains the functions that are shared among
26 * the various services this tool will ultimately provide.
27 * The functions in this file return PKCS#11 CK_RV errors.
28 * Only one session and one login per token is supported
29 * at this time.
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <tzfile.h>
40 #include <cryptoutil.h>
41 #include <security/cryptoki.h>
42 #include <kmfapi.h>
43
44 #include "common.h"
45
46 /* Local status variables. */
47 static boolean_t initialized = B_FALSE;
48 static boolean_t session_opened = B_FALSE;
49 static boolean_t logged_in = B_FALSE;
50
51 /* Supporting structures and global variables for getopt_av(). */
52 typedef struct av_opts_s {
53 int shortnm; /* short name character */
54 char *longnm; /* long name string, NOT terminated */
55 int longnm_len; /* length of long name string */
56 boolean_t has_arg; /* takes optional argument */
57 } av_opts;
58 static av_opts *opts_av = NULL;
59 static const char *_save_optstr = NULL;
60 static int _save_numopts = 0;
61
62 int optind_av = 1;
63 char *optarg_av = NULL;
64
65 static void close_sess(CK_SESSION_HANDLE);
66 static void logout_token(CK_SESSION_HANDLE);
67
68 struct oid_table_entry {
69 const KMF_OID *oid;
70 char *name;
71 };
72
73 struct oid_table_entry oid_table[] = {
74 { &KMFOID_ECC_secp112r1, "secp112r1"},
75 { &KMFOID_ECC_secp112r2, "secp112r2"},
76 { &KMFOID_ECC_secp128r1, "secp128r1"},
77 { &KMFOID_ECC_secp128r2, "secp128r2"},
78 { &KMFOID_ECC_secp160k1, "secp160k1"},
79 { &KMFOID_ECC_secp160r1, "secp160r1"},
80 { &KMFOID_ECC_secp160r2, "secp160r2"},
81 { &KMFOID_ECC_secp192k1, "secp192k1"},
82 { &KMFOID_ECC_secp192r1, "secp192r1"},
83 { &KMFOID_ECC_secp224k1, "secp224k1"},
84 { &KMFOID_ECC_secp224r1, "secp224r1"},
85 { &KMFOID_ECC_secp256k1, "secp256k1"},
86 { &KMFOID_ECC_secp256r1, "secp256r1"},
87 { &KMFOID_ECC_secp384r1, "secp384r1"},
88 { &KMFOID_ECC_secp521r1, "secp521r1"},
89 { &KMFOID_ECC_sect113r1, "sect113r1"},
90 { &KMFOID_ECC_sect113r2, "sect113r2"},
91 { &KMFOID_ECC_sect131r1, "sect131r1"},
92 { &KMFOID_ECC_sect131r2, "sect131r2"},
93 { &KMFOID_ECC_sect163k1, "sect163k1"},
94 { &KMFOID_ECC_sect163r1, "sect163r1"},
95 { &KMFOID_ECC_sect163r2, "sect163r2"},
96 { &KMFOID_ECC_sect193r1, "sect193r1"},
97 { &KMFOID_ECC_sect193r2, "sect193r2"},
98 { &KMFOID_ECC_sect233k1, "sect233k1"},
99 { &KMFOID_ECC_sect233r1, "sect233r1"},
100 { &KMFOID_ECC_sect239k1, "sect239k1"},
101 { &KMFOID_ECC_sect283k1, "sect283k1"},
102 { &KMFOID_ECC_sect283r1, "sect283r1"},
103 { &KMFOID_ECC_sect409k1, "sect409k1"},
104 { &KMFOID_ECC_sect409r1, "sect409r1"},
105 { &KMFOID_ECC_sect571k1, "sect571k1"},
106 { &KMFOID_ECC_sect571r1, "sect571r1"},
107 { &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
108 { &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
109 { &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
110 { &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
111 { &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
112 { &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
113 { &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
114 { &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
115 { &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
116 { &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
117 { &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
118 { &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
119 { &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
120 { &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
121 { &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
122 { &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
123 { &KMFOID_ECC_prime192v2, "prime192v2"},
124 { &KMFOID_ECC_prime192v3, "prime192v3"},
125 { &KMFOID_MD5, "md5"},
126 { &KMFOID_SHA1, "sha1"},
127 { &KMFOID_SHA256, "sha256"},
128 { &KMFOID_SHA384, "sha384"},
129 { &KMFOID_SHA512, "sha512"}
130 };
131 int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
132 #define number_of_curves (number_of_oids - 5)
133
134 /*
135 * Perform PKCS#11 setup here. Currently only C_Initialize is required,
136 * along with setting/resetting state variables.
137 */
138 static CK_RV
init_pkcs11(void)139 init_pkcs11(void)
140 {
141 CK_RV rv = CKR_OK;
142
143 /* If C_Initialize() already called, nothing to do here. */
144 if (initialized == B_TRUE)
145 return (CKR_OK);
146
147 /* Reset state variables because C_Initialize() not yet done. */
148 session_opened = B_FALSE;
149 logged_in = B_FALSE;
150
151 /* Initialize PKCS#11 library. */
152 if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
153 rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
154 return (rv);
155 }
156
157 initialized = B_TRUE;
158 return (CKR_OK);
159 }
160
161 /*
162 * Finalize PKCS#11 library and reset state variables. Open sessions,
163 * if any, are closed, and thereby any logins are logged out also.
164 */
165 void
final_pk11(CK_SESSION_HANDLE sess)166 final_pk11(CK_SESSION_HANDLE sess)
167 {
168
169 /* If the library wasn't initialized, nothing to do here. */
170 if (!initialized)
171 return;
172
173 /* Make sure the sesion is closed first. */
174 close_sess(sess);
175
176 (void) C_Finalize(NULL);
177 initialized = B_FALSE;
178 }
179
180 /*
181 * Close PKCS#11 session and reset state variables. Any logins are
182 * logged out.
183 */
184 static void
close_sess(CK_SESSION_HANDLE sess)185 close_sess(CK_SESSION_HANDLE sess)
186 {
187
188 if (sess == 0) {
189 return;
190 }
191
192 /* If session is already closed, nothing to do here. */
193 if (!session_opened)
194 return;
195
196 /* Make sure user is logged out of token. */
197 logout_token(sess);
198
199 (void) C_CloseSession(sess);
200 session_opened = B_FALSE;
201 }
202
203 /*
204 * Log user out of token and reset status variable.
205 */
206 static void
logout_token(CK_SESSION_HANDLE sess)207 logout_token(CK_SESSION_HANDLE sess)
208 {
209
210 if (sess == 0) {
211 return;
212 }
213
214 /* If already logged out, nothing to do here. */
215 if (!logged_in)
216 return;
217
218 (void) C_Logout(sess);
219 logged_in = B_FALSE;
220 }
221
222 /*
223 * Gets PIN from user. Caller needs to free the returned PIN when done.
224 * If two prompts are given, the PIN is confirmed with second prompt.
225 * Note that getphassphrase() may return data in static memory area.
226 */
227 CK_RV
get_pin(char * prompt1,char * prompt2,CK_UTF8CHAR_PTR * pin,CK_ULONG * pinlen)228 get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
229 {
230 char *save_phrase, *phrase1, *phrase2;
231
232 /* Prompt user for a PIN. */
233 if (prompt1 == NULL) {
234 return (CKR_ARGUMENTS_BAD);
235 }
236 if ((phrase1 = getpassphrase(prompt1)) == NULL) {
237 return (CKR_FUNCTION_FAILED);
238 }
239
240 /* Duplicate 1st PIN in separate chunk of memory. */
241 if ((save_phrase = strdup(phrase1)) == NULL)
242 return (CKR_HOST_MEMORY);
243
244 /* If second prompt given, PIN confirmation is requested. */
245 if (prompt2 != NULL) {
246 if ((phrase2 = getpassphrase(prompt2)) == NULL) {
247 free(save_phrase);
248 return (CKR_FUNCTION_FAILED);
249 }
250 if (strcmp(save_phrase, phrase2) != 0) {
251 free(save_phrase);
252 return (CKR_PIN_INCORRECT);
253 }
254 }
255
256 *pin = (CK_UTF8CHAR_PTR)save_phrase;
257 *pinlen = strlen(save_phrase);
258 return (CKR_OK);
259 }
260
261 int
yn_to_int(char * ynstr)262 yn_to_int(char *ynstr)
263 {
264 char *y = gettext("yes");
265 char *n = gettext("no");
266 if (ynstr == NULL)
267 return (-1);
268
269 if (strncasecmp(ynstr, y, 1) == 0)
270 return (1);
271 else if (strncasecmp(ynstr, n, 1) == 0)
272 return (0);
273 else
274 return (-1);
275 }
276
277 /*
278 * Gets yes/no response from user. If either no prompt is supplied, a
279 * default prompt is used. If not message for invalid input is supplied,
280 * a default will not be provided. If the user provides no response,
281 * the input default B_TRUE == yes, B_FALSE == no is returned.
282 * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
283 */
284 boolean_t
yesno(char * prompt,char * invalid,boolean_t dflt)285 yesno(char *prompt, char *invalid, boolean_t dflt)
286 {
287 char *response, buf[1024];
288 int ans;
289
290 if (prompt == NULL)
291 prompt = gettext("Enter (y)es or (n)o? ");
292
293 for (;;) {
294 /* Prompt user. */
295 (void) printf("%s", prompt);
296 (void) fflush(stdout);
297
298 /* Get the response. */
299 if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
300 break; /* go to default response */
301
302 /* Skip any leading white space. */
303 while (isspace(*response))
304 response++;
305 if (*response == '\0')
306 break; /* go to default response */
307
308 ans = yn_to_int(response);
309 if (ans == 1)
310 return (B_TRUE);
311 else if (ans == 0)
312 return (B_FALSE);
313
314 /* Indicate invalid input, and try again. */
315 if (invalid != NULL)
316 (void) printf("%s", invalid);
317 }
318 return (dflt);
319 }
320
321 /*
322 * Gets the list of slots which have tokens in them. Keeps adjusting
323 * the size of the slot list buffer until the call is successful or an
324 * irrecoverable error occurs.
325 */
326 CK_RV
get_token_slots(CK_SLOT_ID_PTR * slot_list,CK_ULONG * slot_count)327 get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
328 {
329 CK_ULONG tmp_count = 0;
330 CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
331 int rv = CKR_OK;
332
333 if (!initialized)
334 if ((rv = init_pkcs11()) != CKR_OK)
335 return (rv);
336
337 /*
338 * Get the slot count first because we don't know how many
339 * slots there are and how many of those slots even have tokens.
340 * Don't specify an arbitrary buffer size for the slot list;
341 * it may be too small (see section 11.5 of PKCS#11 spec).
342 * Also select only those slots that have tokens in them,
343 * because this tool has no need to know about empty slots.
344 */
345 if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
346 return (rv);
347
348 if (tmp_count == 0) {
349 *slot_list = NULL_PTR;
350 *slot_count = 0;
351 return (CKR_OK);
352 }
353
354 /* Allocate initial space for the slot list. */
355 if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
356 sizeof (CK_SLOT_ID))) == NULL)
357 return (CKR_HOST_MEMORY);
358
359 /* Then get the slot list itself. */
360 for (;;) {
361 if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
362 *slot_list = tmp_list;
363 *slot_count = tmp_count;
364 break;
365 }
366
367 if (rv != CKR_BUFFER_TOO_SMALL) {
368 free(tmp_list);
369 break;
370 }
371
372 /* If the number of slots grew, try again. */
373 if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
374 tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
375 free(tmp_list);
376 rv = CKR_HOST_MEMORY;
377 break;
378 }
379 tmp_list = tmp2_list;
380 }
381
382 return (rv);
383 }
384
385 /*
386 * Breaks out the getopt-style option string into a structure that can be
387 * traversed later for calls to getopt_av(). Option string is NOT altered,
388 * but the struct fields point to locations within option string.
389 */
390 static int
populate_opts(char * optstring)391 populate_opts(char *optstring)
392 {
393 int i;
394 av_opts *temp;
395 char *marker;
396
397 if (optstring == NULL || *optstring == '\0')
398 return (0);
399
400 /*
401 * This tries to imitate getopt(3c) Each option must conform to:
402 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
403 * If long name is missing, the short name is used for long name.
404 */
405 for (i = 0; *optstring != '\0'; i++) {
406 if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
407 realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
408 if (opts_av != NULL)
409 free(opts_av);
410 opts_av = NULL;
411 return (0);
412 } else {
413 opts_av = (av_opts *)temp;
414 }
415
416 (void) memset(&opts_av[i], 0, sizeof (av_opts));
417 marker = optstring; /* may need optstring later */
418
419 opts_av[i].shortnm = *marker++; /* set short name */
420
421 if (*marker == ':') { /* check for opt arg */
422 marker++;
423 opts_av[i].has_arg = B_TRUE;
424 }
425
426 if (*marker == '(') { /* check and set long name */
427 marker++;
428 opts_av[i].longnm = marker;
429 opts_av[i].longnm_len = strcspn(marker, ")");
430 optstring = marker + opts_av[i].longnm_len + 1;
431 } else {
432 /* use short name option character */
433 opts_av[i].longnm = optstring;
434 opts_av[i].longnm_len = 1;
435 optstring = marker;
436 }
437 }
438
439 return (i);
440 }
441
442 /*
443 * getopt_av() is very similar to getopt(3c) in that the takes an option
444 * string, compares command line arguments for matches, and returns a single
445 * letter option when a match is found. However, getopt_av() differs from
446 * getopt(3c) by requiring that only longname options and values be found
447 * on the command line and all leading dashes are omitted. In other words,
448 * it tries to enforce only longname "option=value" arguments on the command
449 * line. Boolean options are not allowed either.
450 */
451 int
getopt_av(int argc,char * const * argv,const char * optstring)452 getopt_av(int argc, char * const *argv, const char *optstring)
453 {
454 int i;
455 int len;
456 char *cur_option;
457
458 if (optind_av >= argc)
459 return (EOF);
460
461 /* First time or when optstring changes from previous one */
462 if (_save_optstr != optstring) {
463 if (opts_av != NULL)
464 free(opts_av);
465 opts_av = NULL;
466 _save_optstr = optstring;
467 _save_numopts = populate_opts((char *)optstring);
468 }
469
470 for (i = 0; i < _save_numopts; i++) {
471 cur_option = argv[optind_av];
472
473 if (strcmp(cur_option, "--") == 0) {
474 optind_av++;
475 break;
476 }
477
478 if (cur_option[0] == '-' && strlen(cur_option) == 2) {
479 len = 1;
480 cur_option++; /* remove "-" */
481 } else {
482 len = strcspn(cur_option, "=");
483 }
484
485 if (len == opts_av[i].longnm_len && strncmp(cur_option,
486 opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
487 /* matched */
488 if (!opts_av[i].has_arg) {
489 optind_av++;
490 return (opts_av[i].shortnm);
491 }
492
493 /* needs optarg */
494 if (cur_option[len] == '=') {
495 optarg_av = &(cur_option[len+1]);
496 optind_av++;
497 return (opts_av[i].shortnm);
498 }
499
500 optarg_av = NULL;
501 optind_av++;
502 return ((int)'?');
503 }
504 }
505
506 return (EOF);
507 }
508
509 KMF_KEYSTORE_TYPE
KS2Int(char * keystore_str)510 KS2Int(char *keystore_str)
511 {
512 if (keystore_str == NULL)
513 return (0);
514 if (strcasecmp(keystore_str, "pkcs11") == 0)
515 return (KMF_KEYSTORE_PK11TOKEN);
516 else if (strcasecmp(keystore_str, "nss") == 0)
517 return (KMF_KEYSTORE_NSS);
518 else if (strcasecmp(keystore_str, "file") == 0)
519 return (KMF_KEYSTORE_OPENSSL);
520 else
521 return (0);
522 }
523
524 /*
525 * compare_oids
526 * return 1 if equal
527 */
528 boolean_t
compare_oids(KMF_OID * oid1,const KMF_OID * oid2)529 compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
530 {
531 return ((oid1->Length == oid2->Length) &&
532 !memcmp(oid1->Data, oid2->Data, oid1->Length));
533 }
534
535 int
Str2KeyType(char * algm,KMF_OID * hashoid,KMF_KEY_ALG * ktype,KMF_ALGORITHM_INDEX * sigAlg)536 Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
537 KMF_ALGORITHM_INDEX *sigAlg)
538 {
539 if (algm == NULL) {
540 /* Default to SHA1+RSA */
541 *sigAlg = KMF_ALGID_SHA1WithRSA;
542 *ktype = KMF_RSA;
543 } else if (strcasecmp(algm, "DSA") == 0) {
544 if (hashoid == NULL ||
545 compare_oids(hashoid, &KMFOID_SHA1))
546 *sigAlg = KMF_ALGID_SHA1WithDSA;
547 else if (compare_oids(hashoid, &KMFOID_SHA256))
548 *sigAlg = KMF_ALGID_SHA256WithDSA;
549 else
550 return (-1); /* unsupported hash/key combo */
551 *ktype = KMF_DSA;
552 } else if (strcasecmp(algm, "RSA") == 0) {
553 if (hashoid == NULL ||
554 compare_oids(hashoid, &KMFOID_SHA1))
555 *sigAlg = KMF_ALGID_SHA1WithRSA;
556 else if (compare_oids(hashoid, &KMFOID_SHA256))
557 *sigAlg = KMF_ALGID_SHA256WithRSA;
558 else if (compare_oids(hashoid, &KMFOID_SHA384))
559 *sigAlg = KMF_ALGID_SHA384WithRSA;
560 else if (compare_oids(hashoid, &KMFOID_SHA512))
561 *sigAlg = KMF_ALGID_SHA512WithRSA;
562 else if (compare_oids(hashoid, &KMFOID_MD5))
563 *sigAlg = KMF_ALGID_MD5WithRSA;
564 else
565 return (-1); /* unsupported hash/key combo */
566 *ktype = KMF_RSA;
567 } else if (strcasecmp(algm, "EC") == 0) {
568 /* EC keys may be used with some SHA2 hashes */
569 if (hashoid == NULL ||
570 compare_oids(hashoid, &KMFOID_SHA1))
571 *sigAlg = KMF_ALGID_SHA1WithECDSA;
572 else if (compare_oids(hashoid, &KMFOID_SHA256))
573 *sigAlg = KMF_ALGID_SHA256WithECDSA;
574 else if (compare_oids(hashoid, &KMFOID_SHA384))
575 *sigAlg = KMF_ALGID_SHA384WithECDSA;
576 else if (compare_oids(hashoid, &KMFOID_SHA512))
577 *sigAlg = KMF_ALGID_SHA512WithECDSA;
578 else
579 return (-1); /* unsupported hash/key combo */
580
581 *ktype = KMF_ECDSA;
582 } else {
583 return (-1);
584 }
585 return (0);
586 }
587
588 int
Str2SymKeyType(char * algm,KMF_KEY_ALG * ktype)589 Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
590 {
591 if (algm == NULL)
592 *ktype = KMF_AES;
593 else if (strcasecmp(algm, "aes") == 0)
594 *ktype = KMF_AES;
595 else if (strcasecmp(algm, "arcfour") == 0)
596 *ktype = KMF_RC4;
597 else if (strcasecmp(algm, "des") == 0)
598 *ktype = KMF_DES;
599 else if (strcasecmp(algm, "3des") == 0)
600 *ktype = KMF_DES3;
601 else if (strcasecmp(algm, "generic") == 0)
602 *ktype = KMF_GENERIC_SECRET;
603 else
604 return (-1);
605
606 return (0);
607 }
608
609 int
Str2Lifetime(char * ltimestr,uint32_t * ltime)610 Str2Lifetime(char *ltimestr, uint32_t *ltime)
611 {
612 int num;
613 char timetok[6];
614
615 if (ltimestr == NULL || strlen(ltimestr) == 0) {
616 /* default to 1 year lifetime */
617 *ltime = SECSPERDAY * DAYSPERNYEAR;
618 return (0);
619 }
620
621 (void) memset(timetok, 0, sizeof (timetok));
622 if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
623 return (-1);
624
625 if (strcasecmp(timetok, "day") == 0||
626 strcasecmp(timetok, "days") == 0) {
627 *ltime = num * SECSPERDAY;
628 } else if (strcasecmp(timetok, "hour") == 0||
629 strcasecmp(timetok, "hours") == 0) {
630 *ltime = num * SECSPERHOUR;
631 } else if (strcasecmp(timetok, "year") == 0 ||
632 strcasecmp(timetok, "years") == 0) {
633 *ltime = num * SECSPERDAY * DAYSPERNYEAR;
634 } else {
635 *ltime = 0;
636 return (-1);
637 }
638
639 return (0);
640 }
641
642 int
OT2Int(char * objclass)643 OT2Int(char *objclass)
644 {
645 char *c = NULL;
646 int retval = 0;
647
648 if (objclass == NULL)
649 return (-1);
650
651 c = strchr(objclass, ':');
652 if (c != NULL) {
653 if (strcasecmp(c, ":private") == 0)
654 retval = PK_PRIVATE_OBJ;
655 else if (strcasecmp(c, ":public") == 0)
656 retval = PK_PUBLIC_OBJ;
657 else if (strcasecmp(c, ":both") == 0)
658 retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
659 else /* unrecognized option */
660 return (-1);
661
662 *c = '\0';
663 }
664
665 if (strcasecmp(objclass, "public") == 0) {
666 if (retval)
667 return (-1);
668 return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
669 } else if (strcasecmp(objclass, "private") == 0) {
670 if (retval)
671 return (-1);
672 return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
673 } else if (strcasecmp(objclass, "both") == 0) {
674 if (retval)
675 return (-1);
676 return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
677 } else if (strcasecmp(objclass, "cert") == 0) {
678 return (retval | PK_CERT_OBJ);
679 } else if (strcasecmp(objclass, "key") == 0) {
680 if (retval == 0) /* return all keys */
681 return (retval | PK_KEY_OBJ);
682 else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
683 /* return all keys */
684 return (retval | PK_KEY_OBJ);
685 else if (retval & PK_PUBLIC_OBJ)
686 /* Only return public keys */
687 return (retval | PK_PUBKEY_OBJ);
688 else if (retval & PK_PRIVATE_OBJ)
689 /* Only return private keys */
690 return (retval | PK_PRIKEY_OBJ);
691 } else if (strcasecmp(objclass, "crl") == 0) {
692 if (retval)
693 return (-1);
694 return (retval | PK_CRL_OBJ);
695 }
696
697 if (retval == 0) /* No matches found */
698 retval = -1;
699 return (retval);
700 }
701
702 KMF_ENCODE_FORMAT
Str2Format(char * formstr)703 Str2Format(char *formstr)
704 {
705 if (formstr == NULL || strcasecmp(formstr, "der") == 0)
706 return (KMF_FORMAT_ASN1);
707 if (strcasecmp(formstr, "pem") == 0)
708 return (KMF_FORMAT_PEM);
709 if (strcasecmp(formstr, "pkcs12") == 0)
710 return (KMF_FORMAT_PKCS12);
711 if (strcasecmp(formstr, "raw") == 0)
712 return (KMF_FORMAT_RAWKEY);
713
714 return (KMF_FORMAT_UNDEF);
715 }
716
717 KMF_RETURN
select_token(void * kmfhandle,char * token,int readonly)718 select_token(void *kmfhandle, char *token, int readonly)
719 {
720 KMF_ATTRIBUTE attlist[10];
721 int i = 0;
722 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
723 KMF_RETURN rv = KMF_OK;
724
725 if (token == NULL)
726 return (KMF_ERR_BAD_PARAMETER);
727
728 kmf_set_attr_at_index(attlist, i,
729 KMF_KEYSTORE_TYPE_ATTR, &kstype,
730 sizeof (kstype));
731 i++;
732
733 if (token) {
734 kmf_set_attr_at_index(attlist, i,
735 KMF_TOKEN_LABEL_ATTR, token,
736 strlen(token));
737 i++;
738 }
739
740 kmf_set_attr_at_index(attlist, i,
741 KMF_READONLY_ATTR, &readonly,
742 sizeof (readonly));
743 i++;
744
745 rv = kmf_configure_keystore(kmfhandle, i, attlist);
746 if (rv == KMF_ERR_TOKEN_SELECTED)
747 rv = KMF_OK;
748 return (rv);
749 }
750
751 KMF_RETURN
configure_nss(void * kmfhandle,char * dir,char * prefix)752 configure_nss(void *kmfhandle, char *dir, char *prefix)
753 {
754 KMF_ATTRIBUTE attlist[10];
755 int i = 0;
756 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
757 KMF_RETURN rv = KMF_OK;
758
759 kmf_set_attr_at_index(attlist, i,
760 KMF_KEYSTORE_TYPE_ATTR, &kstype,
761 sizeof (kstype));
762 i++;
763
764 if (dir) {
765 kmf_set_attr_at_index(attlist, i,
766 KMF_DIRPATH_ATTR, dir,
767 strlen(dir));
768 i++;
769 }
770
771 if (prefix) {
772 kmf_set_attr_at_index(attlist, i,
773 KMF_CERTPREFIX_ATTR, prefix,
774 strlen(prefix));
775 i++;
776
777 kmf_set_attr_at_index(attlist, i,
778 KMF_KEYPREFIX_ATTR, prefix,
779 strlen(prefix));
780 i++;
781 }
782
783 rv = kmf_configure_keystore(kmfhandle, i, attlist);
784 if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
785 rv = KMF_OK;
786
787 return (rv);
788 }
789
790 KMF_RETURN
get_pk12_password(KMF_CREDENTIAL * cred)791 get_pk12_password(KMF_CREDENTIAL *cred)
792 {
793 KMF_RETURN rv = KMF_OK;
794 char prompt[1024];
795
796 /*
797 * Get the password to use for the PK12 encryption.
798 */
799 (void) strlcpy(prompt,
800 gettext("Enter password to use for "
801 "accessing the PKCS12 file: "), sizeof (prompt));
802
803 if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
804 (ulong_t *)&cred->credlen) != CKR_OK) {
805 cred->cred = NULL;
806 cred->credlen = 0;
807 }
808
809 return (rv);
810 }
811
812 #define FILENAME_PROMPT gettext("Filename:")
813 #define FILENAME_MINLEN 1
814 #define FILENAME_MAXLEN MAXPATHLEN
815
816 #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:")
817 #define STATE_PROMPT gettext("State or Province Name (full name) " \
818 "[Some-State]:")
819 #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:")
820 #define ORG_PROMPT gettext("Organization Name (eg, company) []:")
821 #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:")
822 #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:")
823 #define EMAIL_PROMPT gettext("Email Address []:")
824
825 #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \
826 "0x01020304):")
827 #define SERNO_MINLEN 3
828 #define SERNO_MAXLEN 42
829
830 #define LABEL_PROMPT gettext("Enter a label for the certificate:")
831 #define LABEL_MINLEN 1
832 #define LABEL_MAXLEN 1024
833
834 #define COUNTRY_DEFAULT "US"
835 #define STATE_DEFAULT NULL
836 #define INVALID_INPUT gettext("Invalid input; please re-enter ...")
837
838 #define SUBNAMESIZ 1024
839 #define RDN_MIN 1
840 #define RDN_MAX 64
841 #define COUNTRYNAME_MIN 2
842 #define COUNTRYNAME_MAX 2
843
844 static char *
get_input_string(char * prompt,char * default_str,int min_len,int max_len)845 get_input_string(char *prompt, char *default_str, int min_len, int max_len)
846 {
847 char buf[1024];
848 char *response = NULL;
849 char *ret = NULL;
850 int len;
851
852 for (;;) {
853 (void) printf("\t%s", prompt);
854 (void) fflush(stdout);
855
856 response = fgets(buf, sizeof (buf), stdin);
857 if (response == NULL) {
858 if (default_str != NULL) {
859 ret = strdup(default_str);
860 }
861 break;
862 }
863
864 /* Skip any leading white space. */
865 while (isspace(*response))
866 response++;
867 if (*response == '\0') {
868 if (default_str != NULL) {
869 ret = strdup(default_str);
870 }
871 break;
872 }
873
874 len = strlen(response);
875 response[len-1] = '\0'; /* get rid of "LF" */
876 len--;
877 if (len >= min_len && len <= max_len) {
878 ret = strdup(response);
879 break;
880 }
881
882 (void) printf("%s\n", INVALID_INPUT);
883
884 }
885
886 return (ret);
887 }
888
889 int
get_filename(char * txt,char ** result)890 get_filename(char *txt, char **result)
891 {
892 char prompt[1024];
893 char *fname = NULL;
894
895 (void) snprintf(prompt, sizeof (prompt),
896 gettext("Enter filename for the %s: "),
897 txt);
898 fname = get_input_string(prompt, NULL,
899 FILENAME_MINLEN, FILENAME_MAXLEN);
900 *result = fname;
901 return (0);
902 }
903
904 int
get_certlabel(char ** result)905 get_certlabel(char **result)
906 {
907 char *label = NULL;
908
909 label = get_input_string(LABEL_PROMPT, NULL,
910 LABEL_MINLEN, LABEL_MAXLEN);
911 *result = label;
912 return (0);
913 }
914
915 int
get_serial(char ** result)916 get_serial(char **result)
917 {
918 char *serial = NULL;
919
920 serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
921 SERNO_MAXLEN);
922
923 *result = serial;
924 return (0);
925 }
926
927 int
get_subname(char ** result)928 get_subname(char **result)
929 {
930 char *country = NULL;
931 char *state = NULL;
932 char *locality = NULL;
933 char *org = NULL;
934 char *unit = NULL;
935 char *name = NULL;
936 char *email = NULL;
937 char *subname = NULL;
938
939 (void) printf("Entering following fields for subject (a DN) ...\n");
940 country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
941 COUNTRYNAME_MIN, COUNTRYNAME_MAX);
942 if (country == NULL)
943 return (-1);
944
945 state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
946 RDN_MIN, RDN_MAX);
947
948 locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
949 org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
950 unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
951 name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
952 email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
953
954 /* Now create a subject name from the input strings */
955 if ((subname = malloc(SUBNAMESIZ)) == NULL)
956 goto out;
957
958 (void) memset(subname, 0, SUBNAMESIZ);
959 (void) strlcpy(subname, "C=", SUBNAMESIZ);
960 (void) strlcat(subname, country, SUBNAMESIZ);
961 if (state != NULL) {
962 (void) strlcat(subname, ", ST=", SUBNAMESIZ);
963 (void) strlcat(subname, state, SUBNAMESIZ);
964 }
965
966 if (locality != NULL) {
967 (void) strlcat(subname, ", L=", SUBNAMESIZ);
968 (void) strlcat(subname, locality, SUBNAMESIZ);
969 }
970
971 if (org != NULL) {
972 (void) strlcat(subname, ", O=", SUBNAMESIZ);
973 (void) strlcat(subname, org, SUBNAMESIZ);
974 }
975
976 if (unit != NULL) {
977 (void) strlcat(subname, ", OU=", SUBNAMESIZ);
978 (void) strlcat(subname, unit, SUBNAMESIZ);
979 }
980
981 if (name != NULL) {
982 (void) strlcat(subname, ", CN=", SUBNAMESIZ);
983 (void) strlcat(subname, name, SUBNAMESIZ);
984 }
985
986 if (email != NULL) {
987 (void) strlcat(subname, ", E=", SUBNAMESIZ);
988 (void) strlcat(subname, email, SUBNAMESIZ);
989 }
990
991 out:
992 if (country)
993 free(country);
994 if (state)
995 free(state);
996 if (locality)
997 free(locality);
998 if (org)
999 free(org);
1000 if (unit)
1001 free(unit);
1002 if (name)
1003 free(name);
1004 if (email)
1005 free(email);
1006
1007 if (subname == NULL)
1008 return (-1);
1009 else {
1010 *result = subname;
1011 return (0);
1012 }
1013 }
1014
1015 /*
1016 * Parse a string of KeyUsage values and convert
1017 * them to the correct KU Bits.
1018 * The field may be marked "critical" by prepending
1019 * "critical:" to the list.
1020 * EX: critical:digitialSignature,keyEncipherment
1021 */
1022 KMF_RETURN
verify_keyusage(char * kustr,uint16_t * kubits,int * critical)1023 verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
1024 {
1025 KMF_RETURN ret = KMF_OK;
1026 uint16_t kuval;
1027 char *k;
1028
1029 *kubits = 0;
1030 if (kustr == NULL || strlen(kustr) == 0)
1031 return (KMF_ERR_BAD_PARAMETER);
1032
1033 /* Check to see if this is critical */
1034 if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
1035 *critical = TRUE;
1036 kustr += strlen("critical:");
1037 } else {
1038 *critical = FALSE;
1039 }
1040
1041 k = strtok(kustr, ",");
1042 while (k != NULL) {
1043 kuval = kmf_string_to_ku(k);
1044 if (kuval == 0) {
1045 *kubits = 0;
1046 return (KMF_ERR_BAD_PARAMETER);
1047 }
1048 *kubits |= kuval;
1049 k = strtok(NULL, ",");
1050 }
1051
1052 return (ret);
1053 }
1054
1055 /*
1056 * Verify the alternate subject label is real or invalid.
1057 *
1058 * The field may be marked "critical" by prepending
1059 * "critical:" to the list.
1060 * EX: "critical:IP=1.2.3.4"
1061 */
1062 KMF_RETURN
verify_altname(char * arg,KMF_GENERALNAMECHOICES * type,int * critical)1063 verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
1064 {
1065 char *p;
1066 KMF_RETURN rv = KMF_OK;
1067
1068 /* Check to see if this is critical */
1069 if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
1070 *critical = TRUE;
1071 arg += strlen("critical:");
1072 } else {
1073 *critical = FALSE;
1074 }
1075
1076 /* Make sure there is an "=" sign */
1077 p = strchr(arg, '=');
1078 if (p == NULL)
1079 return (KMF_ERR_BAD_PARAMETER);
1080
1081 p[0] = '\0';
1082
1083 if (strcmp(arg, "IP") == 0)
1084 *type = GENNAME_IPADDRESS;
1085 else if (strcmp(arg, "DNS") == 0)
1086 *type = GENNAME_DNSNAME;
1087 else if (strcmp(arg, "EMAIL") == 0)
1088 *type = GENNAME_RFC822NAME;
1089 else if (strcmp(arg, "URI") == 0)
1090 *type = GENNAME_URI;
1091 else if (strcmp(arg, "DN") == 0)
1092 *type = GENNAME_DIRECTORYNAME;
1093 else if (strcmp(arg, "RID") == 0)
1094 *type = GENNAME_REGISTEREDID;
1095 else if (strcmp(arg, "KRB") == 0)
1096 *type = GENNAME_KRB5PRINC;
1097 else if (strcmp(arg, "UPN") == 0)
1098 *type = GENNAME_SCLOGON_UPN;
1099 else
1100 rv = KMF_ERR_BAD_PARAMETER;
1101
1102 p[0] = '=';
1103
1104 return (rv);
1105 }
1106
1107 int
get_token_password(KMF_KEYSTORE_TYPE kstype,char * token_spec,KMF_CREDENTIAL * cred)1108 get_token_password(KMF_KEYSTORE_TYPE kstype,
1109 char *token_spec, KMF_CREDENTIAL *cred)
1110 {
1111 char prompt[1024];
1112 char temptoken[32];
1113 char *p = NULL;
1114 char *t = NULL;
1115 int len;
1116
1117 (void) memset(temptoken, 0, sizeof (temptoken));
1118 if (kstype == KMF_KEYSTORE_PK11TOKEN) {
1119 p = strchr(token_spec, ':');
1120 if (p != NULL)
1121 *p = 0;
1122 }
1123 len = strlen(token_spec);
1124 if (len > sizeof (temptoken))
1125 len = sizeof (temptoken);
1126
1127 (void) strncpy(temptoken, token_spec, len);
1128
1129 /*
1130 * Strip trailing whitespace
1131 */
1132 t = temptoken + (len - 1);
1133 while (isspace(*t) && t >= temptoken) {
1134 *t = 0x00;
1135 t--;
1136 }
1137
1138 /*
1139 * Login to the token first.
1140 */
1141 (void) snprintf(prompt, sizeof (prompt),
1142 gettext(DEFAULT_TOKEN_PROMPT), temptoken);
1143
1144 if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
1145 (ulong_t *)&cred->credlen) != CKR_OK) {
1146 cred->cred = NULL;
1147 cred->credlen = 0;
1148 }
1149
1150 if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
1151 *p = ':';
1152 return (KMF_OK);
1153 }
1154
1155 KMF_RETURN
verify_file(char * filename)1156 verify_file(char *filename)
1157 {
1158 KMF_RETURN ret = KMF_OK;
1159 int fd;
1160
1161 /*
1162 * Attempt to open with the EXCL flag so that if
1163 * it already exists, the open will fail. It will
1164 * also fail if the file cannot be created due to
1165 * permissions on the parent directory, or if the
1166 * parent directory itself does not exist.
1167 */
1168 fd = open(filename, O_CREAT | O_EXCL, 0600);
1169 if (fd == -1) {
1170 if (errno == EEXIST)
1171 return (KMF_ERR_OPEN_FILE);
1172 else
1173 return (KMF_ERR_WRITE_FILE);
1174 }
1175
1176 /* If we were able to create it, delete it. */
1177 (void) close(fd);
1178 (void) unlink(filename);
1179
1180 return (ret);
1181 }
1182
1183 void
display_error(void * handle,KMF_RETURN errcode,char * prefix)1184 display_error(void *handle, KMF_RETURN errcode, char *prefix)
1185 {
1186 KMF_RETURN rv1, rv2;
1187 char *plugin_errmsg = NULL;
1188 char *kmf_errmsg = NULL;
1189
1190 rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
1191 rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
1192
1193 cryptoerror(LOG_STDERR, "%s:", prefix);
1194 if (rv1 == KMF_OK && plugin_errmsg) {
1195 cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
1196 plugin_errmsg);
1197 kmf_free_str(plugin_errmsg);
1198 }
1199
1200 if (rv2 == KMF_OK && kmf_errmsg) {
1201 cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
1202 kmf_errmsg);
1203 kmf_free_str(kmf_errmsg);
1204 }
1205
1206 if (rv1 != KMF_OK && rv2 != KMF_OK)
1207 cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
1208
1209 }
1210
1211 static KMF_RETURN
addToEKUList(EKU_LIST * ekus,int critical,KMF_OID * newoid)1212 addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
1213 {
1214 if (newoid != NULL && ekus != NULL) {
1215 ekus->eku_count++;
1216
1217 ekus->critlist = realloc(ekus->critlist,
1218 ekus->eku_count * sizeof (int));
1219 if (ekus->critlist != NULL)
1220 ekus->critlist[ekus->eku_count-1] = critical;
1221 else
1222 return (KMF_ERR_MEMORY);
1223
1224 ekus->ekulist = realloc(
1225 ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
1226 if (ekus->ekulist != NULL)
1227 ekus->ekulist[ekus->eku_count-1] = *newoid;
1228 else
1229 return (KMF_ERR_MEMORY);
1230 }
1231 return (KMF_OK);
1232 }
1233
1234 void
free_eku_list(EKU_LIST * ekus)1235 free_eku_list(EKU_LIST *ekus)
1236 {
1237 if (ekus != NULL && ekus->eku_count > 0) {
1238 int i;
1239 for (i = 0; i < ekus->eku_count; i++) {
1240 kmf_free_data(&ekus->ekulist[i]);
1241 }
1242 free(ekus->ekulist);
1243 free(ekus->critlist);
1244 free(ekus);
1245 }
1246 }
1247
1248 static KMF_RETURN
parse_ekus(char * ekustr,EKU_LIST * ekus)1249 parse_ekus(char *ekustr, EKU_LIST *ekus)
1250 {
1251 KMF_RETURN rv = KMF_OK;
1252 KMF_OID *newoid;
1253 int critical;
1254
1255 if (strncasecmp(ekustr, "critical:",
1256 strlen("critical:")) == 0) {
1257 critical = TRUE;
1258 ekustr += strlen("critical:");
1259 } else {
1260 critical = FALSE;
1261 }
1262 newoid = kmf_ekuname_to_oid(ekustr);
1263 if (newoid != NULL) {
1264 rv = addToEKUList(ekus, critical, newoid);
1265 free(newoid);
1266 } else {
1267 rv = PK_ERR_USAGE;
1268 }
1269
1270 return (rv);
1271 }
1272
1273 KMF_RETURN
verify_ekunames(char * ekuliststr,EKU_LIST ** ekulist)1274 verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
1275 {
1276 KMF_RETURN rv = KMF_OK;
1277 char *p;
1278 EKU_LIST *ekus = NULL;
1279
1280 if (ekuliststr == NULL || strlen(ekuliststr) == 0)
1281 return (0);
1282
1283 ekus = calloc(sizeof (EKU_LIST), 1);
1284 if (ekus == NULL)
1285 return (KMF_ERR_MEMORY);
1286
1287 /*
1288 * The list should be comma separated list of EKU Names.
1289 */
1290 p = strtok(ekuliststr, ",");
1291
1292 /* If no tokens found, then maybe it's just a single EKU value */
1293 if (p == NULL) {
1294 rv = parse_ekus(ekuliststr, ekus);
1295 }
1296
1297 while (p != NULL) {
1298 rv = parse_ekus(p, ekus);
1299
1300 if (rv != KMF_OK)
1301 break;
1302 p = strtok(NULL, ",");
1303 }
1304
1305 if (rv != KMF_OK)
1306 free_eku_list(ekus);
1307 else
1308 *ekulist = ekus;
1309
1310 return (rv);
1311 }
1312
1313 KMF_RETURN
token_auth_needed(KMF_HANDLE_T handle,char * tokenlabel,int * auth)1314 token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
1315 {
1316 CK_TOKEN_INFO info;
1317 CK_SLOT_ID slot;
1318 CK_RV ckrv;
1319 KMF_RETURN rv;
1320
1321 *auth = 0;
1322 rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
1323 if (rv != KMF_OK)
1324 return (rv);
1325
1326 ckrv = C_GetTokenInfo(slot, &info);
1327 if (ckrv != KMF_OK)
1328 return (KMF_ERR_INTERNAL);
1329
1330 *auth = (info.flags & CKF_LOGIN_REQUIRED);
1331
1332 return (KMF_OK);
1333 }
1334
1335 void
show_ecc_curves()1336 show_ecc_curves()
1337 {
1338 int i;
1339
1340 (void) printf(gettext("Supported ECC curve names:\n"));
1341 for (i = 0; i < number_of_curves; i++) {
1342 (void) printf("%s", oid_table[i].name);
1343 if (i > 0 && ((i+1) % 5) == 0)
1344 (void) printf("\n");
1345 else if (i+1 < number_of_curves)
1346 (void) printf(", ");
1347 }
1348 (void) printf("\n");
1349 }
1350
1351 KMF_OID *
ecc_name_to_oid(char * name)1352 ecc_name_to_oid(char *name)
1353 {
1354 int i;
1355 for (i = 0; i < number_of_oids; i++) {
1356 if (strcasecmp(name, oid_table[i].name) == 0)
1357 return ((KMF_OID *)oid_table[i].oid);
1358 }
1359 return (NULL);
1360 }
1361