static void
crypt_changed_cb(void *arg, uint64_t newval)
{
    objset_t *os = arg;

    /*
     * Inheritance and range checking should have been done by now.
     */
    ASSERT(newval != ZIO_CRYPT_INHERIT);

    os->os_crypt = zio_crypt_select(newval, ZIO_CRYPT_ON_VALUE);
}
Exemple #2
0
/*
 * dsl_crypto_key_gen - Generate dataset key
 *
 * Generate a new key for this dataset based on its encryption property type.
 * Store the key as a usable zcrypt_key_t in the in memory keystore and
 * put the wrapped version of it in the on disk keychain.
 *
 * returns 0 on success
 */
int
dsl_crypto_key_create(dsl_dir_t *dd, dsl_dataset_phys_t *dsphys,
                      uint64_t dsobj, dsl_crypto_ctx_t *ctx, dmu_tx_t *tx)
{
    int error = -1;
#ifdef DEBUG
    zcrypt_key_t *debugkey;
#endif /* DEBUG */
    zcrypt_key_t *wrappingkey, *dslkey;
    caddr_t wkeybuf = NULL;
    size_t wkeylen = 0;
    uint64_t crypt;
    spa_t *spa = dd->dd_pool->dp_spa;
    zcrypt_keystore_node_t *skn;

    if (ctx == NULL) {
        return (0);
    }

    crypt = ctx->dcc_crypt;
    if (crypt == ZIO_CRYPT_OFF || crypt == ZIO_CRYPT_INHERIT) {
        return (0);
    }

    crypt = zio_crypt_select(crypt, ZIO_CRYPT_ON_VALUE);
    wrappingkey = ctx->dcc_wrap_key;
    skn = zcrypt_keystore_insert(spa, dsobj, wrappingkey);
    if (skn == NULL) {
        error = ENOKEY;
        goto out;
    }

    dslkey = zcrypt_key_gen(crypt);
    zcrypt_key_hold(wrappingkey, FTAG);
    error = zcrypt_wrap_key(wrappingkey, dslkey,
                            &wkeybuf, &wkeylen, zio_crypt_select_wrap(crypt));
    if (error != 0) {
        zcrypt_key_free(dslkey);
        spa_history_log_internal(spa, "key create", tx,
                                 "failed dataset = %llu unable to wrap key", dsobj, error);
        goto out;
    }
    dsl_keychain_create_obj(dd, tx);
    dsl_keychain_set_key(dd, tx, wkeybuf, wkeylen,
                         dsphys->ds_creation_time);
    zcrypt_keychain_insert(&skn->skn_keychain,
                           dsphys->ds_creation_txg, dslkey);
    if (ctx->dcc_salt != 0) {
        objset_t *mos = dd->dd_pool->dp_meta_objset;
        uint64_t props_zapobj = dsl_dir_phys(dd)->dd_props_zapobj;

        error = zap_update(mos, props_zapobj,
                           zfs_prop_to_name(ZFS_PROP_SALT), 8, 1,
                           (void *)&ctx->dcc_salt, tx);
    }
    if (error == 0)
        spa_history_log_internal(spa, "key create", tx,
                                 "succeeded dataset = %llu", dsobj);
#ifdef DEBUG
    ASSERT3U(zcrypt_unwrap_key(wrappingkey, crypt,
                               wkeybuf, wkeylen, &debugkey), ==, 0);
    zcrypt_key_compare(dslkey, debugkey);
    zcrypt_key_free(debugkey);
#endif /* DEBUG */
out:
    zcrypt_key_release(wrappingkey, FTAG);
    if (wkeylen > 0) {
        kmem_free(wkeybuf, wkeylen);
    }

    return (error);
}
/* called from dsl for meta-objset */
objset_t *
dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
                       dmu_objset_type_t type, dsl_crypto_ctx_t *dcc, dmu_tx_t *tx)
{
	objset_t *os;
	dnode_t *mdn;

	ASSERT(dmu_tx_is_syncing(tx));
	if (ds != NULL)
		VERIFY(0 == dmu_objset_from_ds(ds, &os));
	else
		VERIFY(0 == dmu_objset_open_impl(spa, NULL, bp, &os));

	mdn = DMU_META_DNODE(os);

	dnode_allocate(mdn, DMU_OT_DNODE, 1 << DNODE_BLOCK_SHIFT,
	    DN_MAX_INDBLKSHIFT, DMU_OT_NONE, 0, tx);

	/*
	 * We don't want to have to increase the meta-dnode's nlevels
	 * later, because then we could do it in quescing context while
	 * we are also accessing it in open context.
	 *
	 * This precaution is not necessary for the MOS (ds == NULL),
	 * because the MOS is only updated in syncing context.
	 * This is most fortunate: the MOS is the only objset that
	 * needs to be synced multiple times as spa_sync() iterates
	 * to convergence, so minimizing its dn_nlevels matters.
	 */
	if (ds != NULL) {
		int levels = 1;

		/*
		 * Determine the number of levels necessary for the meta-dnode
		 * to contain DN_MAX_OBJECT dnodes.
		 */
		while ((uint64_t)mdn->dn_nblkptr << (mdn->dn_datablkshift +
		    (levels - 1) * (mdn->dn_indblkshift - SPA_BLKPTRSHIFT)) <
		    DN_MAX_OBJECT * sizeof (dnode_phys_t))
			levels++;

		mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] =
		    mdn->dn_nlevels = levels;
	}

	ASSERT(type != DMU_OST_NONE);
	ASSERT(type != DMU_OST_ANY);
	ASSERT(type < DMU_OST_NUMTYPES);
    /*
     * Note: although we should not be dirtying the objset outside of
     * sync context, the os_type is used directly from the os_phys
     * in dsl_scan so it may not be save to put os_type in the in-core
     * objset_t and set it in the phys in sync context (as with os_flags)
     */
    dmu_objset_dirty(os);
	os->os_phys->os_type = type;
	if (dmu_objset_userused_enabled(os)) {
		os->os_phys->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE;
        // FIXME - removed in newer.
		// os->os_flags = os->os_phys->os_flags;
	}

    if (dcc != NULL && dcc->dcc_crypt != ZIO_CRYPT_INHERIT) {
        os->os_crypt = zio_crypt_select(dcc->dcc_crypt,
                                        ZIO_CRYPT_ON_VALUE);
    }

	dsl_dataset_dirty(ds, tx);

	return (os);
}