Exemple #1
0
static int
key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource,
    int crypt, zfs_cmd_t *zc, zfs_crypto_zckey_t cmd)
{
    //	CK_SESSION_HANDLE session;
	int ret = 0;
	key_format_t format;
	key_locator_t locator;
	char *uri;
	//pkcs11_uri_t p11uri;
	size_t keylen = zio_crypt_table[crypt].ci_keylen;
	char *keydata = NULL;
	size_t keydatalen = 0;
	char *tmpkeydata = NULL;
	size_t tmpkeydatalen = 0;
	uint64_t salt;
	//struct cb_arg_curl cb_curl = { 0 };

    fprintf(stderr, "in key_hdl_to_zc\r\n");

	zc->zc_crypto.zic_clone_newkey = hdl->libzfs_crypt.zc_clone_newkey;

	if (!keysource_prop_parser(keysource, &format, &locator, &uri)) {
		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
		    "invalid keysource property."));
		return (-1);
	}

	/*
	 * First check if there was anything in the handle already
	 * if so we use that and we are done with locating the data.
	 * Note that we may be looking at other fields
	 * and zic_clone_newkey even if zc_key_data_len is empty.
	 *
	 * We allow this regardless of the locator so that things
	 * like a PAM module can provide the passphrase but the user
	 * can still have "passphrase,prompt" to use zfs(1M) interactively.
	 */
	if (hdl->libzfs_crypt.zc_key_data_len != 0) {
		keydata = zfs_alloc(hdl, hdl->libzfs_crypt.zc_key_data_len);
		bcopy(hdl->libzfs_crypt.zc_key_data, keydata,
		    hdl->libzfs_crypt.zc_key_data_len);
		keydatalen = hdl->libzfs_crypt.zc_key_data_len;
		goto format_key;
	}

	/*
	 * Get the key from the URI or prompt for it.
	 * If the format is raw then prompting is a simple read(2)
	 * otherwise we put up a prompt saying what we are asking for.
	 * We can't do this with the 'zfs mount -a' that is in
	 * sys:/system/filesystem/local:default but we shouldn't
	 * cause errors or warnings there either.
	 */
	switch (locator) {
	case KEY_LOCATOR_PROMPT:
		if (format == KEY_FORMAT_RAW) {
			keydata = zfs_alloc(hdl, keylen);
			errno = 0;
			keydatalen = read(STDIN_FILENO, keydata, keylen);
			if (keydatalen != keylen) {
				free(keydata);
				return (-1);
			}

		} else {
			int tries = 0;
			do {
				/* get_passphrase allocates keydata */
				ret = get_passphrase(hdl, &keydata,
				    &keydatalen, format, zc, cmd);
			} while (ret != 0 && ++tries < 3);
			if (ret)
				return (-1);
		}
		break;
	case KEY_LOCATOR_FILE_URI:
		/*
		 * Need to tell pkcs11_read_data() how big of a key
		 * we want in case the locator URI is a device (eg, /dev/random)
		 * to be read from and not a file.
		 *
		 * Note that pkcs11_read_data allocates memory with malloc
		 * that we need to free.
		 */
#if 0 // FIXME
		keydatalen = keylen;
		ret = pkcs11_read_data(&(uri[7]),
		    (void **)&keydata, &keydatalen);
		if (ret != 0) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "failed to read key file: %s"), strerror(ret));
			errno = ret;
			return (-1);
		}
#endif
		break;

	case KEY_LOCATOR_PKCS11_URI:
#if 0 // FIXME
		keydatalen = keylen;
		/*
		 * Parse out the PKCS#11 URI and
		 * get the value of the wrapping key.
		 */
		if (pkcs11_parse_uri(uri, &p11uri) != PK11_URI_OK) {
			errno = EINVAL;
			return (-1);
		}
		ret = get_pkcs11_key_value(hdl, zc, cmd, &p11uri,
		    &keydata, &keydatalen);
		pkcs11_free_uri(&p11uri);
		if (ret != 0) {
			return (-1);
		}
#endif
		break;
	case KEY_LOCATOR_HTTPS_URI: {
#if 0
		CURL *curl_hdl = curl_easy_init();
		CURLcode cerr;

		cerr = curl_easy_setopt(curl_hdl, CURLOPT_URL, uri);
		if (cerr != CURLE_OK)
			goto curl_fail;
		cerr = curl_easy_setopt(curl_hdl, CURLOPT_FAILONERROR, 1L);
		if (cerr != CURLE_OK)
			goto curl_fail;
		cerr = curl_easy_setopt(curl_hdl, CURLOPT_WRITEFUNCTION,
		    get_keydata_curl);
		if (cerr != CURLE_OK)
			goto curl_fail;
		cb_curl.cb_hdl = hdl;
		cerr = curl_easy_setopt(curl_hdl, CURLOPT_WRITEDATA,
		    &cb_curl);
		if (cerr != CURLE_OK)
			goto curl_fail;
		cerr = curl_easy_perform(curl_hdl);
curl_fail:
		/*
		 * Just deal with libcurl errors here, reading the wrong key
		 * size is dealt with generically in the format_key section.
		 */
		if (cerr != 0) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "failed to retreive key from '%s': '%s'"),
			    uri, curl_easy_strerror(cerr));
			return (-1);
		}

		keydata = cb_curl.cb_keydata;
		keydatalen = cb_curl.cb_keydatalen;

		curl_easy_cleanup(curl_hdl);
#endif
		break;

        case KEY_LOCATOR_NONE: // Avoid Warning
            break;
		}
	}

format_key:
	if (keydata == NULL || keydatalen == 0) {
		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
		    "key can not be of zero size"));
		errno = ret;
		return (-1);
	}

	/*
	 * Now that we have the key do any transform that is necessary
	 * such as turning the hex format into raw or in the case of
	 * a passphrase running it through PKCS#5 to get the raw key.
	 *
	 * Note that zic_keydata is not malloc'd memory so that we
	 * don't have to worry about our caller freeing it.
	 */
	switch (format) {
	case KEY_FORMAT_RAW:
		bcopy(keydata, zc->zc_crypto.zic_keydata, keydatalen);
		zc->zc_crypto.zic_keydatalen = keydatalen;
		zc->zc_crypto.zic_salt = 0;
		break;
	case KEY_FORMAT_HEX:
		/*
		 * If the keylen is not on the byte boundary, in terms of hex
		 * format, and that extra char is a linefeed, we can trim it
		 */
		if (keydatalen == (keylen * 2) + 1 &&
		    keydata[keydatalen] == '\n') {
			keydatalen--;
		}

		/*
		 * hexstr_to_bytes allocates memory with malloc
		 * but we want the data in zic_keydata which isn't malloc'd
		 * so to avoid a memory leak we use a tmpkeydata buffer
		 * and bcopy it.
		 */
#if 0        // FIXME
		ret = hexstr_to_bytes(keydata, keydatalen,
		    (uchar_t **)&tmpkeydata, &tmpkeydatalen);
#endif

		if (ret) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "invalid hex format key."));
			errno = EACCES;
			ret = -1;
			goto out;
		}

		bcopy(tmpkeydata, zc->zc_crypto.zic_keydata, tmpkeydatalen);
		bzero(tmpkeydata, tmpkeydatalen);
		free(tmpkeydata);
		zc->zc_crypto.zic_keydatalen = tmpkeydatalen;
		zc->zc_crypto.zic_salt = 0;
		break;
	case KEY_FORMAT_PASSPHRASE:
		/* Remove any extra linefeed that may be on the end */
		if (keydata[keydatalen - 1] == '\n')
			keydatalen--;

		if (cmd == ZFS_CRYPTO_KEY_LOAD) {
			salt = zfs_prop_get_int(zhp, ZFS_PROP_SALT);
		} else {
#if 0 // FIXME
			ret = pkcs11_get_random(&salt, sizeof (uint64_t));
			if (ret) {
				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
				    "failed to obtain salt: %s."),
				    pkcs11_strerror(ret));
				errno = EINVAL;
				ret = -1;
				goto out;
			}
#endif
		}

        fprintf(stderr, "Key is '%s' and is len %u\r\n",
                keydata, keydatalen);

        // FIXME
        tmpkeydata = strdup(keydata);
        tmpkeydatalen = keydatalen;
        salt = 0x1234;

#if 0 // FIXME
		ret = SUNW_C_GetMechSession(CKM_PKCS5_PBKD2, &session);
		if (ret) {
			zfs_error_aux(hdl,
			    dgettext(TEXT_DOMAIN,
			    "failed to access CKM_PKCS5_PBKD2: %s."),
			    pkcs11_strerror(ret));
			errno = EINVAL;
			ret = -1;
			goto out;
		}

		/*
		 * pkcs11_PasswdToKey allocates memory with malloc
		 * but we want the data in zic_keydata which isn't malloc'd
		 * so to avoid a memory leak we use a tmpkeydata buffer
		 * and bcopy it.
		 */
		ret = pkcs11_PasswdToKey(session, keydata, keydatalen,
		    (void *)&salt, sizeof (uint64_t), CKK_AES,
		    keylen, (void **)&tmpkeydata, &tmpkeydatalen);

		(void) C_CloseSession(session);

		if (ret) {
			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
			    "failed to generate key: %s."),
			    pkcs11_strerror(ret));
			errno = EINVAL;
			ret = -1;
			goto out;
		}
#endif

		bcopy(tmpkeydata, zc->zc_crypto.zic_keydata, tmpkeydatalen);
		bzero(tmpkeydata, tmpkeydatalen);
		free(tmpkeydata);
		zc->zc_crypto.zic_keydatalen = tmpkeydatalen;
		zc->zc_crypto.zic_salt = salt;
		break;

	default:
		ASSERT(format);
	}

	if (zc->zc_crypto.zic_keydatalen != keylen) {
		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
		    "key length invalid. expected %lu bytes have %lu"),
		    keylen, zc->zc_crypto.zic_keydatalen);
		errno = EIO;
		ret = -1;
	}

    if (tmpkeydatalen) // Only decrease if NOT zero.
        tmpkeydatalen--;
	while (zc->zc_crypto.zic_keydata[tmpkeydatalen] == 0 &&
	    tmpkeydatalen > 0)
		tmpkeydatalen--;

	if (tmpkeydatalen == 0) {
		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                    "invalid all zeros key %lu"), tmpkeydatalen);
		errno = EIO;
		ret = -1;
	}
out:
	if (keydata) {
		bzero(keydata, keydatalen);
		free(keydata);
	}

	return (ret);
}
Exemple #2
0
static void cmd_parser(int argc, char **argv)
{
	int ret, debug = 0;
	common_info_st cinfo;
	unsigned int pkcs11_type = -1, key_type = GNUTLS_PK_UNKNOWN;
	const char *url = NULL;
	unsigned int detailed_url = 0, optct;
	unsigned int bits = 0;
	const char *label = NULL, *sec_param = NULL;
	unsigned flags;

	optct = optionProcess(&p11toolOptions, argc, argv);
	argc += optct;
	argv += optct;

	if (url == NULL && argc > 0)
		url = argv[0];
	else
		url = "pkcs11:";

	if (HAVE_OPT(DEBUG))
		debug = OPT_VALUE_DEBUG;

	gnutls_global_set_log_function(tls_log_func);
	gnutls_global_set_log_level(debug);
	if (debug > 1)
		printf("Setting log level to %d\n", debug);

	if ((ret = gnutls_global_init()) < 0) {
		fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	if (HAVE_OPT(PROVIDER)) {
		ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
		if (ret < 0)
			fprintf(stderr, "pkcs11_init: %s\n",
				gnutls_strerror(ret));
		else {
			ret =
			    gnutls_pkcs11_add_provider(OPT_ARG(PROVIDER),
						       NULL);
			if (ret < 0) {
				fprintf(stderr, "pkcs11_add_provider: %s\n",
					gnutls_strerror(ret));
				exit(1);
			}
		}
	} else {
		ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL);
		if (ret < 0)
			fprintf(stderr, "pkcs11_init: %s\n",
				gnutls_strerror(ret));
	}

	if (HAVE_OPT(OUTFILE)) {
		outfile = safe_open_rw(OPT_ARG(OUTFILE), 0);
		if (outfile == NULL) {
			fprintf(stderr, "cannot open %s\n", OPT_ARG(OUTFILE));
			exit(1);
		}
	} else
		outfile = stdout;

	memset(&cinfo, 0, sizeof(cinfo));

	flags = opt_to_flags();

	if (HAVE_OPT(SECRET_KEY))
		cinfo.secret_key = OPT_ARG(SECRET_KEY);

	if (HAVE_OPT(LOAD_PRIVKEY))
		cinfo.privkey = OPT_ARG(LOAD_PRIVKEY);

	if (HAVE_OPT(PKCS8))
		cinfo.pkcs8 = 1;

	if (HAVE_OPT(BATCH)) {
		batch = cinfo.batch = 1;
	}

	if (ENABLED_OPT(INDER) || ENABLED_OPT(INRAW))
		cinfo.incert_format = GNUTLS_X509_FMT_DER;
	else
		cinfo.incert_format = GNUTLS_X509_FMT_PEM;

	if (HAVE_OPT(OUTDER) || HAVE_OPT(OUTRAW))
		cinfo.outcert_format = GNUTLS_X509_FMT_DER;
	else
		cinfo.outcert_format = GNUTLS_X509_FMT_PEM;

	if (HAVE_OPT(SET_PIN))
		cinfo.pin = OPT_ARG(SET_PIN);

	if (HAVE_OPT(SET_SO_PIN))
		cinfo.so_pin = OPT_ARG(SET_SO_PIN);

	if (HAVE_OPT(LOAD_CERTIFICATE))
		cinfo.cert = OPT_ARG(LOAD_CERTIFICATE);

	if (HAVE_OPT(LOAD_PUBKEY))
		cinfo.pubkey = OPT_ARG(LOAD_PUBKEY);

	if (ENABLED_OPT(DETAILED_URL))
		detailed_url = 1;

	if (HAVE_OPT(LABEL)) {
		label = OPT_ARG(LABEL);
	}

	if (HAVE_OPT(BITS)) {
		bits = OPT_VALUE_BITS;
	}

	if (HAVE_OPT(CURVE)) {
		bits = GNUTLS_CURVE_TO_BITS(str_to_curve(OPT_ARG(CURVE)));
	}

	if (HAVE_OPT(SEC_PARAM)) {
		sec_param = OPT_ARG(SEC_PARAM);
	}

	if (debug > 4) {
		if (HAVE_OPT(MARK_PRIVATE))
			fprintf(stderr, "Private: %s\n",
				ENABLED_OPT(MARK_PRIVATE) ? "yes" : "no");
		fprintf(stderr, "Trusted: %s\n",
			ENABLED_OPT(MARK_TRUSTED) ? "yes" : "no");
		fprintf(stderr, "Wrap: %s\n",
			ENABLED_OPT(MARK_WRAP) ? "yes" : "no");
		fprintf(stderr, "CA: %s\n",
			ENABLED_OPT(MARK_CA) ? "yes" : "no");
		fprintf(stderr, "Login: %s\n",
			ENABLED_OPT(LOGIN) ? "yes" : "no");
		fprintf(stderr, "SO Login: %s\n",
			ENABLED_OPT(SO_LOGIN) ? "yes" : "no");
		fprintf(stderr, "Detailed URLs: %s\n",
			ENABLED_OPT(DETAILED_URL) ? "yes" : "no");
		fprintf(stderr, "\n");
	}

	/* handle actions 
	 */
	if (HAVE_OPT(LIST_TOKENS)) {
		pkcs11_token_list(outfile, detailed_url, &cinfo, 0);
	} else if (HAVE_OPT(LIST_MECHANISMS)) {
		pkcs11_mechanism_list(outfile, url, flags, &cinfo);
	} else if (HAVE_OPT(GENERATE_RANDOM)) {
		pkcs11_get_random(outfile, url, OPT_VALUE_GENERATE_RANDOM,
				  &cinfo);
	} else if (HAVE_OPT(INFO)) {
		pkcs11_type = PKCS11_TYPE_INFO;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(LIST_ALL)) {
		pkcs11_type = PKCS11_TYPE_ALL;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(LIST_ALL_CERTS)) {
		pkcs11_type = PKCS11_TYPE_CRT_ALL;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(LIST_CERTS)) {
		pkcs11_type = PKCS11_TYPE_PK;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(LIST_ALL_PRIVKEYS)) {
		pkcs11_type = PKCS11_TYPE_PRIVKEY;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(LIST_ALL_TRUSTED)) {
		pkcs11_type = PKCS11_TYPE_TRUSTED;
		pkcs11_list(outfile, url, pkcs11_type,
			    flags, detailed_url, &cinfo);
	} else if (HAVE_OPT(EXPORT)) {
		pkcs11_export(outfile, url, flags, &cinfo);
	} else if (HAVE_OPT(EXPORT_CHAIN)) {
		pkcs11_export_chain(outfile, url, flags, &cinfo);
	} else if (HAVE_OPT(WRITE)) {
		pkcs11_write(outfile, url, label,
			     flags, &cinfo);
	} else if (HAVE_OPT(INITIALIZE))
		pkcs11_init(outfile, url, label, &cinfo);
	else if (HAVE_OPT(DELETE))
		pkcs11_delete(outfile, url, flags, &cinfo);
	else if (HAVE_OPT(GENERATE_ECC)) {
		key_type = GNUTLS_PK_EC;
		pkcs11_generate(outfile, url, key_type,
				get_bits(key_type, bits, sec_param, 0),
				label, detailed_url,
				flags, &cinfo);
	} else if (HAVE_OPT(GENERATE_RSA)) {
		key_type = GNUTLS_PK_RSA;
		pkcs11_generate(outfile, url, key_type,
				get_bits(key_type, bits, sec_param, 0),
				label, detailed_url,
				flags, &cinfo);
	} else if (HAVE_OPT(GENERATE_DSA)) {
		key_type = GNUTLS_PK_DSA;
		pkcs11_generate(outfile, url, key_type,
				get_bits(key_type, bits, sec_param, 0),
				label, detailed_url,
				flags, &cinfo);
	} else if (HAVE_OPT(EXPORT_PUBKEY)) {
		pkcs11_export_pubkey(outfile, url, detailed_url, flags, &cinfo);
	} else {
		USAGE(1);
	}

	fclose(outfile);

#ifdef ENABLE_PKCS11
	gnutls_pkcs11_deinit();
#endif
	gnutls_global_deinit();
}