PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/usr/src/cmd/cmd-crypto/pktool/common.c

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