/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. */ /* * This file implements the setpin operation for this tool. * The basic flow of the process is to load the PKCS#11 module, * finds the soft token, prompt the user for the old PIN (if * any) and the new PIN, change the token's PIN, and clean up. */ #include #include #include #include #include #include #include "common.h" static int setpin_nss(KMF_HANDLE_T handle, char *token_spec, char *dir, char *prefix) { int rv = 0; KMF_CREDENTIAL oldcred = { NULL, 0 }; KMF_CREDENTIAL newpincred = { NULL, 0 }; CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; CK_ULONG old_pinlen = 0, new_pinlen = 0; KMF_ATTRIBUTE setpinattrs[6]; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; int numattrs = 0; rv = configure_nss(handle, dir, prefix); if (rv != KMF_OK) return (rv); kmf_set_attr_at_index(setpinattrs, numattrs, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattrs++; if (token_spec != NULL) { kmf_set_attr_at_index(setpinattrs, numattrs, KMF_TOKEN_LABEL_ATTR, token_spec, strlen(token_spec)); numattrs++; } if ((rv = get_pin(gettext("Enter current token passphrase " "( if not set):"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to get token passphrase.")); return (PK_ERR_NSS); } /* Get the user's new PIN. */ if ((rv = get_pin(gettext("Create new passphrase:"), gettext( "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { if (rv == CKR_PIN_INCORRECT) cryptoerror(LOG_STDERR, gettext( "Passphrases do not match.")); else cryptoerror(LOG_STDERR, gettext( "Unable to get and confirm new passphrase.")); if (old_pin != NULL) free(old_pin); return (PK_ERR_NSS); } oldcred.cred = (char *)old_pin; oldcred.credlen = old_pinlen; kmf_set_attr_at_index(setpinattrs, numattrs, KMF_CREDENTIAL_ATTR, &oldcred, sizeof (oldcred)); numattrs++; newpincred.cred = (char *)new_pin; newpincred.credlen = new_pinlen; kmf_set_attr_at_index(setpinattrs, numattrs, KMF_NEWPIN_ATTR, &newpincred, sizeof (newpincred)); numattrs++; rv = kmf_set_token_pin(handle, numattrs, setpinattrs); if (new_pin) free(new_pin); if (old_pin) free(old_pin); return (rv); } static int setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec, boolean_t souser) { CK_SLOT_ID slot_id; CK_FLAGS pin_state; CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL; CK_ULONG old_pinlen = 0, new_pinlen = 0; CK_RV rv = CKR_OK; char *token_name = NULL; CK_TOKEN_INFO token_info; KMF_CREDENTIAL newpincred = { NULL, 0 }; KMF_CREDENTIAL oldcred = { NULL, 0 }; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; KMF_ATTRIBUTE attrlist[6]; CK_USER_TYPE user = CKU_USER; int numattr = 0; /* If nothing is specified, default is to use softtoken. */ if (token_spec == NULL) { token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID; token_name = SOFT_TOKEN_LABEL; } rv = kmf_pk11_token_lookup(NULL, token_spec, &slot_id); if (rv == KMF_OK) { /* find the pin state for the selected token */ if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK) return (PK_ERR_PK11); pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED; if (token_name == NULL) token_name = (char *)token_info.label; } /* * If the token is the softtoken, check if the token flags show the * PIN has not been set yet. If not then set the old PIN to the * default "changeme". Otherwise, let user type in the correct old * PIN to unlock token. */ if (pin_state == CKF_USER_PIN_TO_BE_CHANGED && strcmp(token_name, SOFT_TOKEN_LABEL) == 0) { if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); final_pk11(0); return (PK_ERR_PK11); } old_pinlen = strlen(SOFT_DEFAULT_PIN); } else { if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &old_pin, &old_pinlen)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to get token passphrase (%s)."), pkcs11_strerror(rv)); final_pk11(0); return (PK_ERR_PK11); } } /* Get the user's new PIN. */ if ((rv = get_pin(gettext("Create new passphrase:"), gettext( "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) { if (rv == CKR_PIN_INCORRECT) cryptoerror(LOG_STDERR, gettext( "Passphrases do not match.")); else cryptoerror(LOG_STDERR, gettext( "Unable to get and confirm new passphrase (%s)."), pkcs11_strerror(rv)); free(old_pin); final_pk11(0); return (PK_ERR_PK11); } kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; if (token_name != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, token_name, strlen(token_name)); numattr++; } oldcred.cred = (char *)old_pin; oldcred.credlen = old_pinlen; kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, &oldcred, sizeof (oldcred)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_SLOT_ID_ATTR, &slot_id, sizeof (slot_id)); numattr++; newpincred.cred = (char *)new_pin; newpincred.credlen = new_pinlen; kmf_set_attr_at_index(attrlist, numattr, KMF_NEWPIN_ATTR, &newpincred, sizeof (newpincred)); numattr++; if (souser) { user = CKU_SO; kmf_set_attr_at_index(attrlist, numattr, KMF_PK11_USER_TYPE_ATTR, &user, sizeof (user)); numattr++; } rv = kmf_set_token_pin(handle, numattr, attrlist); /* Clean up. */ if (old_pin != NULL) free(old_pin); if (new_pin != NULL) free(new_pin); return (rv); } /* * Changes the token's PIN. */ int pk_setpin(int argc, char *argv[]) /* ARGSUSED */ { int opt; int rv; extern int optind_av; extern char *optarg_av; char *token_spec = NULL; char *dir = NULL; char *prefix = NULL; char *utype = NULL; KMF_HANDLE_T handle; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; boolean_t souser = 0; /* Parse command line options. Do NOT i18n/l10n. */ while ((opt = getopt_av(argc, argv, "T:(token)k:(keystore)d:(dir)" "p:(prefix)u:(usertype)")) != EOF) { switch (opt) { case 'k': kstype = KS2Int(optarg_av); if (kstype == 0) return (PK_ERR_USAGE); break; case 'T': /* token specifier */ if (token_spec) return (PK_ERR_USAGE); token_spec = optarg_av; break; case 'd': if (dir) return (PK_ERR_USAGE); dir = optarg_av; break; case 'p': if (prefix) return (PK_ERR_USAGE); prefix = optarg_av; break; case 'u': utype = optarg_av; break; default: return (PK_ERR_USAGE); } } /* No additional args allowed. */ argc -= optind_av; argv += optind_av; if (argc != 0) return (PK_ERR_USAGE); /* Done parsing command line options. */ if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) { token_spec = PK_DEFAULT_PK11TOKEN; } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) { token_spec = DEFAULT_NSS_TOKEN; } if ((rv = kmf_initialize(&handle, NULL, NULL)) != KMF_OK) return (rv); if (utype != NULL) { if (strcmp(utype, "so") == 0) souser = 1; else if (strcmp(utype, "user") == 0) souser = 0; else /* Wrong option string */ return (PK_ERR_USAGE); } switch (kstype) { case KMF_KEYSTORE_PK11TOKEN: rv = setpin_pkcs11(handle, token_spec, souser); break; case KMF_KEYSTORE_NSS: rv = setpin_nss(handle, token_spec, dir, prefix); break; default: cryptoerror(LOG_STDERR, gettext("incorrect keystore.")); return (PK_ERR_USAGE); } (void) kmf_finalize(handle); if (rv == KMF_ERR_AUTH_FAILED) { cryptoerror(LOG_STDERR, gettext("Incorrect passphrase.")); return (PK_ERR_SYSTEM); } else if (rv != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to change passphrase.")); return (PK_ERR_SYSTEM); } else { (void) fprintf(stdout, gettext("Passphrase changed.\n")); } return (0); }