17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*b5a2d845SHai-May Chao * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <errno.h> 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include "cryptoutil.h" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **); 357c478bd9Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *); 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 387c478bd9Sstevel@tonic-gate * Retrieve the user-level provider info from the pkcs11.conf file. 397c478bd9Sstevel@tonic-gate * If successful, the result is returned from the ppliblist argument. 407c478bd9Sstevel@tonic-gate * This function returns SUCCESS if successfully done; otherwise it returns 417c478bd9Sstevel@tonic-gate * FAILURE. 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate int 447c478bd9Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist) 457c478bd9Sstevel@tonic-gate { 467c478bd9Sstevel@tonic-gate FILE *pfile; 477c478bd9Sstevel@tonic-gate char buffer[BUFSIZ]; 487c478bd9Sstevel@tonic-gate size_t len; 497c478bd9Sstevel@tonic-gate uentry_t *pent; 507c478bd9Sstevel@tonic-gate uentrylist_t *pentlist; 517c478bd9Sstevel@tonic-gate uentrylist_t *pcur; 527c478bd9Sstevel@tonic-gate int rc = SUCCESS; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate *ppliblist = NULL; 55004388ebScasper if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) { 567c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF); 577c478bd9Sstevel@tonic-gate return (FAILURE); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 617c478bd9Sstevel@tonic-gate if (buffer[0] == '#' || buffer[0] == ' ' || 627c478bd9Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t') { 637c478bd9Sstevel@tonic-gate continue; /* ignore comment lines */ 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate len = strlen(buffer); 677c478bd9Sstevel@tonic-gate if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */ 687c478bd9Sstevel@tonic-gate len--; 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate buffer[len] = '\0'; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate if ((rc = uef_interpret(buffer, &pent)) != SUCCESS) { 737c478bd9Sstevel@tonic-gate break; 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* append pent into ppliblist */ 777c478bd9Sstevel@tonic-gate pentlist = malloc(sizeof (uentrylist_t)); 787c478bd9Sstevel@tonic-gate if (pentlist == NULL) { 797c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 807c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 817c478bd9Sstevel@tonic-gate free_uentry(pent); 827c478bd9Sstevel@tonic-gate rc = FAILURE; 837c478bd9Sstevel@tonic-gate break; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate pentlist->puent = pent; 867c478bd9Sstevel@tonic-gate pentlist->next = NULL; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (*ppliblist == NULL) { 897c478bd9Sstevel@tonic-gate *ppliblist = pcur = pentlist; 907c478bd9Sstevel@tonic-gate } else { 917c478bd9Sstevel@tonic-gate pcur->next = pentlist; 927c478bd9Sstevel@tonic-gate pcur = pcur->next; 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate (void) fclose(pfile); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (rc != SUCCESS) { 997c478bd9Sstevel@tonic-gate free_uentrylist(*ppliblist); 1007c478bd9Sstevel@tonic-gate *ppliblist = NULL; 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate return (rc); 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * This routine converts a char string into a uentry_t structure 1097c478bd9Sstevel@tonic-gate * The input string "buf" should be one of the following: 1107c478bd9Sstevel@tonic-gate * library_name 1117c478bd9Sstevel@tonic-gate * library_name:NO_RANDOM 1127c478bd9Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk 1137c478bd9Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk;NO_RANDOM 1147c478bd9Sstevel@tonic-gate * library_name:enabledlist= 1157c478bd9Sstevel@tonic-gate * library_name:enabledlist=;NO_RANDOM 1167c478bd9Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk 1177c478bd9Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk;NO_RANDOM 1187c478bd9Sstevel@tonic-gate * metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\ 1197c478bd9Sstevel@tonic-gate * token=<token-label> 1207c478bd9Sstevel@tonic-gate * 1217c478bd9Sstevel@tonic-gate * Note: 1227c478bd9Sstevel@tonic-gate * The mechanisms m1,..mk are in hex form. For example, "0x00000210" 1237c478bd9Sstevel@tonic-gate * for CKM_MD5. 1247c478bd9Sstevel@tonic-gate * 1257c478bd9Sstevel@tonic-gate * For the metaslot entry, "enabledlist", "slot", "auto_key_migrate" 1267c478bd9Sstevel@tonic-gate * or "token" is optional 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static int 1297c478bd9Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent) 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate uentry_t *pent; 1327c478bd9Sstevel@tonic-gate char *token1; 1337c478bd9Sstevel@tonic-gate char *token2; 1347c478bd9Sstevel@tonic-gate char *lasts; 1357c478bd9Sstevel@tonic-gate int rc; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate *ppent = NULL; 1387c478bd9Sstevel@tonic-gate if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) { 1397c478bd9Sstevel@tonic-gate /* buf is NULL */ 1407c478bd9Sstevel@tonic-gate return (FAILURE); 1417c478bd9Sstevel@tonic-gate }; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate pent = calloc(sizeof (uentry_t), 1); 1447c478bd9Sstevel@tonic-gate if (pent == NULL) { 1457c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 1467c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 1477c478bd9Sstevel@tonic-gate return (FAILURE); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate (void) strlcpy(pent->name, token1, sizeof (pent->name)); 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * in case metaslot_auto_key_migrate is not specified, it should 1527c478bd9Sstevel@tonic-gate * be default to true 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) { 1577c478bd9Sstevel@tonic-gate if ((rc = parse_policylist(token2, pent)) != SUCCESS) { 1587c478bd9Sstevel@tonic-gate free_uentry(pent); 1597c478bd9Sstevel@tonic-gate return (rc); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate *ppent = pent; 1647c478bd9Sstevel@tonic-gate return (SUCCESS); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * This routine parses the policy list and stored the result in the argument 1707c478bd9Sstevel@tonic-gate * pent. 1717c478bd9Sstevel@tonic-gate * 1727c478bd9Sstevel@tonic-gate * Arg buf: input only, its format should be one of the following: 1737c478bd9Sstevel@tonic-gate * enabledlist= 1747c478bd9Sstevel@tonic-gate * enabledlist=m1,m2,...,mk 1757c478bd9Sstevel@tonic-gate * disabledlist=m1,m2,...,mk 1767c478bd9Sstevel@tonic-gate * NO_RANDOM 1777c478bd9Sstevel@tonic-gate * metaslot_status=enabled|disabled 1787c478bd9Sstevel@tonic-gate * metaslot_token=<token-label> 1797c478bd9Sstevel@tonic-gate * metaslot_slot=<slot-description. 1807c478bd9Sstevel@tonic-gate * 1817c478bd9Sstevel@tonic-gate * Arg pent: input/output 1827c478bd9Sstevel@tonic-gate * 1837c478bd9Sstevel@tonic-gate * return: SUCCESS or FAILURE 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate static int 1867c478bd9Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate umechlist_t *phead = NULL; 1897c478bd9Sstevel@tonic-gate umechlist_t *pcur = NULL; 1907c478bd9Sstevel@tonic-gate umechlist_t *pmech; 1917c478bd9Sstevel@tonic-gate char *next_token; 1927c478bd9Sstevel@tonic-gate char *value; 1937c478bd9Sstevel@tonic-gate char *lasts; 1947c478bd9Sstevel@tonic-gate int count = 0; 1957c478bd9Sstevel@tonic-gate int rc = SUCCESS; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (pent == NULL) { 1987c478bd9Sstevel@tonic-gate return (FAILURE); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) { 2027c478bd9Sstevel@tonic-gate pent->flag_enabledlist = B_FALSE; 2037c478bd9Sstevel@tonic-gate } else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) { 2047c478bd9Sstevel@tonic-gate pent->flag_enabledlist = B_TRUE; 2057c478bd9Sstevel@tonic-gate } else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) { 2067c478bd9Sstevel@tonic-gate pent->flag_norandom = B_TRUE; 2077c478bd9Sstevel@tonic-gate return (rc); 2087c478bd9Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_TOKEN, 2097c478bd9Sstevel@tonic-gate sizeof (METASLOT_TOKEN) - 1) == 0) { 2107c478bd9Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2117c478bd9Sstevel@tonic-gate value++; /* get rid of = */ 2127c478bd9Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_token, value, 21399ebb4caSwyllys sizeof (pent->metaslot_ks_token)); 2147c478bd9Sstevel@tonic-gate return (SUCCESS); 2157c478bd9Sstevel@tonic-gate } else { 2167c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2177c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2187c478bd9Sstevel@tonic-gate return (FAILURE); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_SLOT, 2217c478bd9Sstevel@tonic-gate sizeof (METASLOT_SLOT) - 1) == 0) { 2227c478bd9Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2237c478bd9Sstevel@tonic-gate value++; /* get rid of = */ 2247c478bd9Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_slot, value, 22599ebb4caSwyllys sizeof (pent->metaslot_ks_slot)); 2267c478bd9Sstevel@tonic-gate return (SUCCESS); 2277c478bd9Sstevel@tonic-gate } else { 2287c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2297c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2307c478bd9Sstevel@tonic-gate return (FAILURE); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_STATUS, 2337c478bd9Sstevel@tonic-gate sizeof (METASLOT_STATUS) - 1) == 0) { 2347c478bd9Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2357c478bd9Sstevel@tonic-gate value++; /* get rid of = */ 236*b5a2d845SHai-May Chao if (strcmp(value, DISABLED_KEYWORD) == 0) { 2377c478bd9Sstevel@tonic-gate pent->flag_metaslot_enabled = B_FALSE; 238*b5a2d845SHai-May Chao } else if (strcmp(value, ENABLED_KEYWORD) == 0) { 2397c478bd9Sstevel@tonic-gate pent->flag_metaslot_enabled = B_TRUE; 2407c478bd9Sstevel@tonic-gate } else { 2417c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2427c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2437c478bd9Sstevel@tonic-gate return (FAILURE); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate return (SUCCESS); 2467c478bd9Sstevel@tonic-gate } else { 2477c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2487c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2497c478bd9Sstevel@tonic-gate return (FAILURE); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE, 2527c478bd9Sstevel@tonic-gate sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) { 2537c478bd9Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2547c478bd9Sstevel@tonic-gate value++; /* get rid of = */ 255*b5a2d845SHai-May Chao if (strcmp(value, DISABLED_KEYWORD) == 0) { 2567c478bd9Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_FALSE; 257*b5a2d845SHai-May Chao } else if (strcmp(value, ENABLED_KEYWORD) == 0) { 2587c478bd9Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE; 2597c478bd9Sstevel@tonic-gate } else { 2607c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2617c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2627c478bd9Sstevel@tonic-gate return (FAILURE); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate return (SUCCESS); 2657c478bd9Sstevel@tonic-gate } else { 2667c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2677c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2687c478bd9Sstevel@tonic-gate return (FAILURE); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate } else { 2717c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2727c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2737c478bd9Sstevel@tonic-gate return (FAILURE); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2777c478bd9Sstevel@tonic-gate value++; /* get rid of = */ 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) { 2817c478bd9Sstevel@tonic-gate if (pent->flag_enabledlist) { 2827c478bd9Sstevel@tonic-gate return (SUCCESS); 2837c478bd9Sstevel@tonic-gate } else { 2847c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 2857c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2867c478bd9Sstevel@tonic-gate return (FAILURE); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate while (next_token) { 2917c478bd9Sstevel@tonic-gate if ((pmech = create_umech(next_token)) == NULL) { 2927c478bd9Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 2937c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF); 2947c478bd9Sstevel@tonic-gate rc = FAILURE; 2957c478bd9Sstevel@tonic-gate break; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (phead == NULL) { 2997c478bd9Sstevel@tonic-gate phead = pcur = pmech; 3007c478bd9Sstevel@tonic-gate } else { 3017c478bd9Sstevel@tonic-gate pcur->next = pmech; 3027c478bd9Sstevel@tonic-gate pcur = pcur->next; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate count++; 3057c478bd9Sstevel@tonic-gate next_token = strtok_r(NULL, SEP_COMMA, &lasts); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (rc == SUCCESS) { 3097c478bd9Sstevel@tonic-gate pent->policylist = phead; 3107c478bd9Sstevel@tonic-gate pent->count = count; 3117c478bd9Sstevel@tonic-gate } else { 3127c478bd9Sstevel@tonic-gate free_umechlist(phead); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate return (rc); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * Create one item of type umechlist_t with the mechanism name. A NULL is 3217c478bd9Sstevel@tonic-gate * returned when the input name is NULL or the heap memory is insufficient. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate umechlist_t * 3247c478bd9Sstevel@tonic-gate create_umech(char *name) 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate umechlist_t *pmech = NULL; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (name == NULL) { 3297c478bd9Sstevel@tonic-gate return (NULL); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate if ((pmech = malloc(sizeof (umechlist_t))) != NULL) { 3337c478bd9Sstevel@tonic-gate (void) strlcpy(pmech->name, name, sizeof (pmech->name)); 3347c478bd9Sstevel@tonic-gate pmech->next = NULL; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate return (pmech); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate void 3427c478bd9Sstevel@tonic-gate free_umechlist(umechlist_t *plist) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate umechlist_t *pnext; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate while (plist != NULL) { 3477c478bd9Sstevel@tonic-gate pnext = plist->next; 3487c478bd9Sstevel@tonic-gate free(plist); 3497c478bd9Sstevel@tonic-gate plist = pnext; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate void 3557c478bd9Sstevel@tonic-gate free_uentry(uentry_t *pent) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate if (pent == NULL) { 3587c478bd9Sstevel@tonic-gate return; 3597c478bd9Sstevel@tonic-gate } else { 3607c478bd9Sstevel@tonic-gate free_umechlist(pent->policylist); 3617c478bd9Sstevel@tonic-gate free(pent); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate void 3677c478bd9Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist) 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate uentrylist_t *pnext; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate while (entrylist != NULL) { 3727c478bd9Sstevel@tonic-gate pnext = entrylist->next; 3737c478bd9Sstevel@tonic-gate free_uentry(entrylist->puent); 3747c478bd9Sstevel@tonic-gate free(entrylist); 3757c478bd9Sstevel@tonic-gate entrylist = pnext; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate } 37899ebb4caSwyllys 37999ebb4caSwyllys 38099ebb4caSwyllys 38199ebb4caSwyllys /* 38299ebb4caSwyllys * Duplicate an UEF mechanism list. A NULL pointer is returned if out of 38399ebb4caSwyllys * memory or the input argument is NULL. 38499ebb4caSwyllys */ 38599ebb4caSwyllys static umechlist_t * 38699ebb4caSwyllys dup_umechlist(umechlist_t *plist) 38799ebb4caSwyllys { 38899ebb4caSwyllys umechlist_t *pres = NULL; 38999ebb4caSwyllys umechlist_t *pcur; 39099ebb4caSwyllys umechlist_t *ptmp; 39199ebb4caSwyllys int rc = SUCCESS; 39299ebb4caSwyllys 39399ebb4caSwyllys while (plist != NULL) { 39499ebb4caSwyllys if (!(ptmp = create_umech(plist->name))) { 39599ebb4caSwyllys rc = FAILURE; 39699ebb4caSwyllys break; 39799ebb4caSwyllys } 39899ebb4caSwyllys 39999ebb4caSwyllys if (pres == NULL) { 40099ebb4caSwyllys pres = pcur = ptmp; 40199ebb4caSwyllys } else { 40299ebb4caSwyllys pcur->next = ptmp; 40399ebb4caSwyllys pcur = pcur->next; 40499ebb4caSwyllys } 40599ebb4caSwyllys plist = plist->next; 40699ebb4caSwyllys } 40799ebb4caSwyllys 40899ebb4caSwyllys if (rc != SUCCESS) { 40999ebb4caSwyllys free_umechlist(pres); 41099ebb4caSwyllys return (NULL); 41199ebb4caSwyllys } 41299ebb4caSwyllys 41399ebb4caSwyllys return (pres); 41499ebb4caSwyllys } 41599ebb4caSwyllys 41699ebb4caSwyllys 41799ebb4caSwyllys /* 41899ebb4caSwyllys * Duplicate an uentry. A NULL pointer is returned if out of memory 41999ebb4caSwyllys * or the input argument is NULL. 42099ebb4caSwyllys */ 42199ebb4caSwyllys static uentry_t * 42299ebb4caSwyllys dup_uentry(uentry_t *puent1) 42399ebb4caSwyllys { 42499ebb4caSwyllys uentry_t *puent2 = NULL; 42599ebb4caSwyllys 42699ebb4caSwyllys if (puent1 == NULL) { 42799ebb4caSwyllys return (NULL); 42899ebb4caSwyllys } 42999ebb4caSwyllys 43099ebb4caSwyllys if ((puent2 = malloc(sizeof (uentry_t))) == NULL) { 43199ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("out of memory.")); 43299ebb4caSwyllys return (NULL); 43399ebb4caSwyllys } else { 43499ebb4caSwyllys (void) strlcpy(puent2->name, puent1->name, 43599ebb4caSwyllys sizeof (puent2->name)); 43699ebb4caSwyllys puent2->flag_norandom = puent1->flag_norandom; 43799ebb4caSwyllys puent2->flag_enabledlist = puent1->flag_enabledlist; 43899ebb4caSwyllys puent2->policylist = dup_umechlist(puent1->policylist); 43999ebb4caSwyllys puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled; 44099ebb4caSwyllys puent2->flag_metaslot_auto_key_migrate 44199ebb4caSwyllys = puent1->flag_metaslot_auto_key_migrate; 44299ebb4caSwyllys (void) memcpy(puent2->metaslot_ks_slot, 44399ebb4caSwyllys puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE); 44499ebb4caSwyllys (void) memcpy(puent2->metaslot_ks_token, 44599ebb4caSwyllys puent1->metaslot_ks_token, TOKEN_LABEL_SIZE); 44699ebb4caSwyllys puent2->count = puent1->count; 44799ebb4caSwyllys return (puent2); 44899ebb4caSwyllys } 44999ebb4caSwyllys } 45099ebb4caSwyllys 45199ebb4caSwyllys /* 45299ebb4caSwyllys * Find the entry in the "pkcs11.conf" file with "libname" as the provider 45399ebb4caSwyllys * name. Return the entry if found, otherwise return NULL. 45499ebb4caSwyllys */ 45599ebb4caSwyllys uentry_t * 45699ebb4caSwyllys getent_uef(char *libname) 45799ebb4caSwyllys { 45899ebb4caSwyllys uentrylist_t *pliblist = NULL; 45999ebb4caSwyllys uentrylist_t *plib = NULL; 46099ebb4caSwyllys uentry_t *puent = NULL; 46199ebb4caSwyllys boolean_t found = B_FALSE; 46299ebb4caSwyllys 46399ebb4caSwyllys if (libname == NULL) { 46499ebb4caSwyllys return (NULL); 46599ebb4caSwyllys } 46699ebb4caSwyllys 46799ebb4caSwyllys if ((get_pkcs11conf_info(&pliblist)) == FAILURE) { 46899ebb4caSwyllys return (NULL); 46999ebb4caSwyllys } 47099ebb4caSwyllys 47199ebb4caSwyllys plib = pliblist; 47299ebb4caSwyllys while (plib) { 47399ebb4caSwyllys if (strcmp(plib->puent->name, libname) == 0) { 47499ebb4caSwyllys found = B_TRUE; 47599ebb4caSwyllys break; 47699ebb4caSwyllys } else { 47799ebb4caSwyllys plib = plib->next; 47899ebb4caSwyllys } 47999ebb4caSwyllys } 48099ebb4caSwyllys 48199ebb4caSwyllys if (found) { 48299ebb4caSwyllys puent = dup_uentry(plib->puent); 48399ebb4caSwyllys } 48499ebb4caSwyllys 48599ebb4caSwyllys free_uentrylist(pliblist); 48699ebb4caSwyllys return (puent); 48799ebb4caSwyllys } 48899ebb4caSwyllys 48999ebb4caSwyllys 49099ebb4caSwyllys 49199ebb4caSwyllys /* 49299ebb4caSwyllys * Retrieve the metaslot information from the pkcs11.conf file. 49399ebb4caSwyllys * This function returns SUCCESS if successfully done; otherwise it returns 49499ebb4caSwyllys * FAILURE. If successful, the caller is responsible to free the space 49599ebb4caSwyllys * allocated for objectstore_slot_info and objectstore_token_info. 49699ebb4caSwyllys */ 49799ebb4caSwyllys int 49899ebb4caSwyllys get_metaslot_info(boolean_t *status_enabled, boolean_t *migrate_enabled, 49999ebb4caSwyllys char **objectstore_slot_info, char **objectstore_token_info) 50099ebb4caSwyllys { 50199ebb4caSwyllys 50299ebb4caSwyllys int rc = SUCCESS; 50399ebb4caSwyllys uentry_t *puent; 50499ebb4caSwyllys char *buf1 = NULL; 50599ebb4caSwyllys char *buf2 = NULL; 50699ebb4caSwyllys 50799ebb4caSwyllys if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) { 50899ebb4caSwyllys /* metaslot entry doesn't exist */ 50999ebb4caSwyllys return (FAILURE); 51099ebb4caSwyllys } 51199ebb4caSwyllys 51299ebb4caSwyllys *status_enabled = puent->flag_metaslot_enabled; 51399ebb4caSwyllys *migrate_enabled = puent->flag_metaslot_auto_key_migrate; 51499ebb4caSwyllys 51599ebb4caSwyllys buf1 = malloc(SLOT_DESCRIPTION_SIZE); 51699ebb4caSwyllys if (buf1 == NULL) { 51799ebb4caSwyllys cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n"); 51899ebb4caSwyllys rc = FAILURE; 51999ebb4caSwyllys goto out; 52099ebb4caSwyllys } 52199ebb4caSwyllys (void) strcpy(buf1, (const char *) puent->metaslot_ks_slot); 52299ebb4caSwyllys *objectstore_slot_info = buf1; 52399ebb4caSwyllys 52499ebb4caSwyllys buf2 = malloc(TOKEN_LABEL_SIZE); 52599ebb4caSwyllys if (objectstore_slot_info == NULL) { 52699ebb4caSwyllys cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n"); 52799ebb4caSwyllys rc = FAILURE; 52899ebb4caSwyllys goto out; 52999ebb4caSwyllys } 53099ebb4caSwyllys (void) strcpy(buf2, (const char *) puent->metaslot_ks_token); 53199ebb4caSwyllys *objectstore_token_info = buf2; 53299ebb4caSwyllys 53399ebb4caSwyllys out: 53499ebb4caSwyllys if (puent != NULL) { 53599ebb4caSwyllys free_uentry(puent); 53699ebb4caSwyllys } 53799ebb4caSwyllys 53899ebb4caSwyllys if (rc == FAILURE) { 53999ebb4caSwyllys if (buf1 != NULL) { 54099ebb4caSwyllys free(buf1); 54199ebb4caSwyllys } 54299ebb4caSwyllys if (buf2 != NULL) { 54399ebb4caSwyllys free(buf2); 54499ebb4caSwyllys } 54599ebb4caSwyllys } 54699ebb4caSwyllys 54799ebb4caSwyllys return (rc); 54899ebb4caSwyllys } 549*b5a2d845SHai-May Chao 550*b5a2d845SHai-May Chao static CK_RV 551*b5a2d845SHai-May Chao parse_fips_mode(char *buf, int *mode) 552*b5a2d845SHai-May Chao { 553*b5a2d845SHai-May Chao 554*b5a2d845SHai-May Chao char *value; 555*b5a2d845SHai-May Chao 556*b5a2d845SHai-May Chao if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) { 557*b5a2d845SHai-May Chao if (value = strpbrk(buf, SEP_EQUAL)) { 558*b5a2d845SHai-May Chao value++; /* get rid of = */ 559*b5a2d845SHai-May Chao if (strcmp(value, DISABLED_KEYWORD) == 0) { 560*b5a2d845SHai-May Chao *mode = CRYPTO_FIPS_MODE_DISABLED; 561*b5a2d845SHai-May Chao } else if (strcmp(value, ENABLED_KEYWORD) == 0) { 562*b5a2d845SHai-May Chao *mode = CRYPTO_FIPS_MODE_ENABLED; 563*b5a2d845SHai-May Chao } else { 564*b5a2d845SHai-May Chao cryptoerror(LOG_ERR, 565*b5a2d845SHai-May Chao "failed to parse kcf.conf file.\n"); 566*b5a2d845SHai-May Chao return (CKR_FUNCTION_FAILED); 567*b5a2d845SHai-May Chao } 568*b5a2d845SHai-May Chao return (CKR_OK); 569*b5a2d845SHai-May Chao } else { 570*b5a2d845SHai-May Chao return (CKR_FUNCTION_FAILED); 571*b5a2d845SHai-May Chao } 572*b5a2d845SHai-May Chao } else { 573*b5a2d845SHai-May Chao /* should not come here */ 574*b5a2d845SHai-May Chao return (CKR_FUNCTION_FAILED); 575*b5a2d845SHai-May Chao } 576*b5a2d845SHai-May Chao 577*b5a2d845SHai-May Chao } 578*b5a2d845SHai-May Chao 579*b5a2d845SHai-May Chao static boolean_t 580*b5a2d845SHai-May Chao is_fips(char *name) 581*b5a2d845SHai-May Chao { 582*b5a2d845SHai-May Chao if (strcmp(name, FIPS_KEYWORD) == 0) { 583*b5a2d845SHai-May Chao return (B_TRUE); 584*b5a2d845SHai-May Chao } else { 585*b5a2d845SHai-May Chao return (B_FALSE); 586*b5a2d845SHai-May Chao } 587*b5a2d845SHai-May Chao } 588*b5a2d845SHai-May Chao 589*b5a2d845SHai-May Chao CK_RV 590*b5a2d845SHai-May Chao get_fips_mode(int *mode) 591*b5a2d845SHai-May Chao { 592*b5a2d845SHai-May Chao FILE *pfile = NULL; 593*b5a2d845SHai-May Chao char buffer[BUFSIZ]; 594*b5a2d845SHai-May Chao int len; 595*b5a2d845SHai-May Chao CK_RV rc = CKR_OK; 596*b5a2d845SHai-May Chao int found = 0; 597*b5a2d845SHai-May Chao char *token1; 598*b5a2d845SHai-May Chao 599*b5a2d845SHai-May Chao if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) { 600*b5a2d845SHai-May Chao cryptoerror(LOG_ERR, 601*b5a2d845SHai-May Chao "failed to open the kcf.conf file for read only."); 602*b5a2d845SHai-May Chao return (CKR_FUNCTION_FAILED); 603*b5a2d845SHai-May Chao } 604*b5a2d845SHai-May Chao 605*b5a2d845SHai-May Chao while (fgets(buffer, BUFSIZ, pfile) != NULL) { 606*b5a2d845SHai-May Chao if (buffer[0] == '#' || buffer[0] == ' ' || 607*b5a2d845SHai-May Chao buffer[0] == '\n'|| buffer[0] == '\t') { 608*b5a2d845SHai-May Chao continue; /* ignore comment lines */ 609*b5a2d845SHai-May Chao } 610*b5a2d845SHai-May Chao 611*b5a2d845SHai-May Chao len = strlen(buffer); 612*b5a2d845SHai-May Chao if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */ 613*b5a2d845SHai-May Chao len--; 614*b5a2d845SHai-May Chao } 615*b5a2d845SHai-May Chao buffer[len] = '\0'; 616*b5a2d845SHai-May Chao 617*b5a2d845SHai-May Chao /* Get provider name */ 618*b5a2d845SHai-May Chao if ((token1 = strtok(buffer, SEP_COLON)) == 619*b5a2d845SHai-May Chao NULL) { /* buf is NULL */ 620*b5a2d845SHai-May Chao return (CKR_FUNCTION_FAILED); 621*b5a2d845SHai-May Chao }; 622*b5a2d845SHai-May Chao 623*b5a2d845SHai-May Chao if (is_fips(token1)) { 624*b5a2d845SHai-May Chao if ((rc = parse_fips_mode(buffer + strlen(token1) + 1, 625*b5a2d845SHai-May Chao mode)) != CKR_OK) { 626*b5a2d845SHai-May Chao goto out; 627*b5a2d845SHai-May Chao } else { 628*b5a2d845SHai-May Chao found++; 629*b5a2d845SHai-May Chao break; 630*b5a2d845SHai-May Chao } 631*b5a2d845SHai-May Chao } else { 632*b5a2d845SHai-May Chao continue; 633*b5a2d845SHai-May Chao } 634*b5a2d845SHai-May Chao } 635*b5a2d845SHai-May Chao 636*b5a2d845SHai-May Chao if (!found) { 637*b5a2d845SHai-May Chao *mode = CRYPTO_FIPS_MODE_DISABLED; 638*b5a2d845SHai-May Chao } 639*b5a2d845SHai-May Chao 640*b5a2d845SHai-May Chao out: 641*b5a2d845SHai-May Chao (void) fclose(pfile); 642*b5a2d845SHai-May Chao return (rc); 643*b5a2d845SHai-May Chao } 644