static int ddt_zap_update(objset_t *os, uint64_t object, ddt_entry_t *dde, dmu_tx_t *tx) { uchar_t cbuf[sizeof (dde->dde_phys) + 1]; uint64_t csize; csize = ddt_compress(dde->dde_phys, cbuf, sizeof (dde->dde_phys), sizeof (cbuf)); return (zap_update_uint64(os, object, (uint64_t *)&dde->dde_key, DDT_KEY_WORDS, 1, csize, cbuf, tx)); }
static void dsl_keychain_set_key(dsl_dir_t *dd, dmu_tx_t *tx, caddr_t wkeybuf, size_t wkeylen, uint64_t rekey_date) { objset_t *mos = dd->dd_pool->dp_meta_objset; uint64_t keychain_zapobj = dsl_dir_phys(dd)->dd_keychain_obj; uint64_t props_zapobj = dsl_dir_phys(dd)->dd_props_zapobj; ASSERT(keychain_zapobj != 0); VERIFY(zap_update_uint64(mos, keychain_zapobj, (uint64_t *)&tx->tx_txg, 1, 1, wkeylen, wkeybuf, tx) == 0); VERIFY(zap_update(mos, props_zapobj, zfs_prop_to_name(ZFS_PROP_REKEYDATE), 8, 1, (void *)&rekey_date, tx) == 0); }
static void dsl_keychain_clone_phys(dsl_dataset_t *src, dsl_dir_t *dd, dmu_tx_t *tx, zcrypt_key_t *dwkey) { objset_t *mos = dd->dd_pool->dp_meta_objset; uint64_t keychain = dsl_dir_phys(dd)->dd_keychain_obj; caddr_t wrappedkey = NULL; size_t wkeylen = 0; zcrypt_keystore_node_t *kn; zcrypt_keychain_node_t *n; uint64_t newest_txg = dsl_dataset_phys(src)->ds_creation_txg; kn = zcrypt_keystore_find_node(dsl_dataset_get_spa(src), src->ds_object, B_FALSE); if (kn == NULL) { kn = zcrypt_keystore_find_node(dsl_dataset_get_spa(src), dsl_dir_phys(src->ds_dir)->dd_head_dataset_obj, B_FALSE); } ASSERT(kn != NULL); ASSERT(dwkey != NULL); /* * Walk the in memory AVL tree representation of the keychain * creating new keychain entries using our wrappingkey, stopping * when we reach keychain entries created after the snapshot we * are cloning from. */ mutex_enter(&kn->skn_lock); for (n = avl_first(&kn->skn_keychain); n != NULL && n->dkn_txg <= newest_txg; n = AVL_NEXT(&kn->skn_keychain, n)) { VERIFY(zcrypt_wrap_key(dwkey, n->dkn_key, &wrappedkey, &wkeylen, zio_crypt_select_wrap(dwkey->zk_crypt)) == 0); VERIFY(zap_update_uint64(mos, keychain, &n->dkn_txg, 1, 1, wkeylen, wrappedkey, tx) == 0); kmem_free(wrappedkey, wkeylen); } mutex_exit(&kn->skn_lock); }
/* * dsl_crypto_key_change * * The old key must already be present in memory since the user interface * doesn't provide away to prompt or retrieve the old key. */ static void dsl_crypto_key_change_sync(void *arg1, dmu_tx_t *tx) { struct wkey_change_arg *ca = arg1; dsl_dataset_t *ds = ca->ca_ds; size_t wkeylen; char *wkeybuf = NULL; zcrypt_key_t *txgkey; zap_cursor_t zc; zap_attribute_t za; objset_t *mos; uint64_t keychain_zapobj; spa_t *spa; zcrypt_keystore_node_t *zkn; ASSERT(RRW_WRITE_HELD(&ds->ds_dir->dd_pool->dp_config_rwlock)); mos = ds->ds_dir->dd_pool->dp_meta_objset; keychain_zapobj = dsl_dir_phys(ds->ds_dir)->dd_keychain_obj; /* * To allow for the case were the keychains of child datasets * are not loaded (ie an explicit 'zfs key -u tank/fs/sub' had * been done some time before doing 'zfs key -c tank/fs') we itterate * over the zap objects on disk rather than copying from the * in memory keystore node. */ for (zap_cursor_init(&zc, mos, keychain_zapobj); zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) { wkeylen = za.za_num_integers; wkeybuf = kmem_alloc(wkeylen, KM_SLEEP); VERIFY(zap_lookup_uint64(mos, keychain_zapobj, (uint64_t *)za.za_name, 1, 1, wkeylen, wkeybuf) == 0); VERIFY(zcrypt_unwrap_key(ca->ca_old_key, ds->ds_objset->os_crypt, wkeybuf, wkeylen, &txgkey) == 0); kmem_free(wkeybuf, wkeylen); VERIFY(zcrypt_wrap_key(ca->ca_new_key, txgkey, &wkeybuf, &wkeylen, zio_crypt_select_wrap(ds->ds_objset->os_crypt)) == 0); zcrypt_key_free(txgkey); VERIFY(zap_update_uint64(mos, keychain_zapobj, (uint64_t *)za.za_name, 1, 1, wkeylen, wkeybuf, tx) == 0); kmem_free(wkeybuf, wkeylen); } zap_cursor_fini(&zc); spa = dsl_dataset_get_spa(ds); /* * If the wrapping key is loaded switch the in memory copy now. */ zkn = zcrypt_keystore_find_node(spa, ds->ds_object, B_FALSE); if (zkn != NULL) { zcrypt_key_free(zkn->skn_wrapkey); zkn->skn_wrapkey = zcrypt_key_copy(ca->ca_new_key); } spa_history_log_internal(spa, "key change", tx, "succeeded dataset = %llu", ds->ds_object); }