Ejemplo n.º 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);
}
Ejemplo n.º 2
0
// At the moment, test values are arbitrary and are not real hashes of previous txs or blocks
int main(void)
{
    //TRANSACTION GENERATION TESTING ////////////////////////////////////////////////////////////
    unshort version = __VERSION;
    size_t in_count = 1;
    size_t out_count = 1;
    unint time = 1435969063;
    
    // the following few things could be done in a loop in implementation for all the ins and outs
    unchar *ins[1];
    unchar *outs[1];
    
    
    ins[0] = malloc(TX_INPUT_BYTESIZE);
    outs[0] = malloc(TX_OUTPUT_BYTESIZE);
    
    ///// INPUT GENERATING /////
    unchar *ref_tx = malloc(SHA256_SIZE);
    hexstr_to_bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", SHA256_SIZE, ref_tx);
    
    unchar *sig = malloc(RSA1024_SIZE);
    hexstr_to_bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", RSA1024_SIZE, sig);
    
    
    generate_tx_input(ref_tx, sig, ins[0]);
    

    
    ///// OUTPUT GENERATING /////
    unchar *out_address = malloc(RSA1024_SIZE);
    hexstr_to_bytes("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", RSA1024_SIZE, out_address);
    unint amount = 0x00000001;
    generate_tx_output(out_address, amount, outs[0]);
    
    unchar *tx0 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    generate_transaction(version, in_count, out_count, time, ins, outs, tx0);

    
    // MERKLE ROOT TESTING ///////////////////////////////////////////////////////////////////////
    size_t size = (TX_HEADER_SIZE + TX_INPUT_BYTESIZE + TX_OUTPUT_BYTESIZE); // This is only computable like this because we know there's only 1 in and 1 out.
    unchar* hash = malloc(SHA256_SIZE);
    
    unchar *tx1 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    unchar *tx2 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    unchar *tx3 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    unchar *tx4 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    unchar *tx5 = malloc(TX_HEADER_SIZE + 1*TX_INPUT_BYTESIZE + 1*TX_OUTPUT_BYTESIZE);
    
    tx1=memcpy(tx1, tx0, size);
    tx2=memcpy(tx2, tx1, size);
    tx3=memcpy(tx3, tx2, size);
    tx4=memcpy(tx4, tx3, size);
    tx5=memcpy(tx5, tx4, size);

    unchar *txs[6] = {tx0,tx1,tx2,tx3,tx4,tx5};
    
    generate_merkle_root(txs, 6, hash);
    
    printf("Transaction:            ");
    int i;
    for(i=0;i<size;i++)
        printf("%02x",tx0[i]);
    printf("\n");
    
    printf("Merkle root: ");
    //int i;
    for(i=0; i<SHA256_SIZE; i++)
        printf("%02x", hash[i]);
    return 0;
};