11f1e2261SMartin Matuska /* 21f1e2261SMartin Matuska * CDDL HEADER START 31f1e2261SMartin Matuska * 41f1e2261SMartin Matuska * The contents of this file are subject to the terms of the 51f1e2261SMartin Matuska * Common Development and Distribution License (the "License"). 61f1e2261SMartin Matuska * You may not use this file except in compliance with the License. 71f1e2261SMartin Matuska * 81f1e2261SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91f1e2261SMartin Matuska * or http://opensource.org/licenses/CDDL-1.0. 101f1e2261SMartin Matuska * See the License for the specific language governing permissions 111f1e2261SMartin Matuska * and limitations under the License. 121f1e2261SMartin Matuska * 131f1e2261SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 141f1e2261SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151f1e2261SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 161f1e2261SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 171f1e2261SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 181f1e2261SMartin Matuska * 191f1e2261SMartin Matuska * CDDL HEADER END 201f1e2261SMartin Matuska */ 211f1e2261SMartin Matuska 221f1e2261SMartin Matuska /* 231f1e2261SMartin Matuska * Copyright 2022 Tino Reichardt <milky-zfs@mcmilk.de> 241f1e2261SMartin Matuska */ 251f1e2261SMartin Matuska 261f1e2261SMartin Matuska #include <sys/zfs_context.h> 271f1e2261SMartin Matuska #include <sys/zio_checksum.h> 281f1e2261SMartin Matuska #include <sys/blake3.h> 291f1e2261SMartin Matuska #include <sys/abd.h> 301f1e2261SMartin Matuska 311f1e2261SMartin Matuska static int 321f1e2261SMartin Matuska blake3_incremental(void *buf, size_t size, void *arg) 331f1e2261SMartin Matuska { 341f1e2261SMartin Matuska BLAKE3_CTX *ctx = arg; 351f1e2261SMartin Matuska 361f1e2261SMartin Matuska Blake3_Update(ctx, buf, size); 371f1e2261SMartin Matuska 381f1e2261SMartin Matuska return (0); 391f1e2261SMartin Matuska } 401f1e2261SMartin Matuska 411f1e2261SMartin Matuska /* 421f1e2261SMartin Matuska * Computes a native 256-bit BLAKE3 MAC checksum. Please note that this 431f1e2261SMartin Matuska * function requires the presence of a ctx_template that should be allocated 441f1e2261SMartin Matuska * using abd_checksum_blake3_tmpl_init. 451f1e2261SMartin Matuska */ 461f1e2261SMartin Matuska void 471f1e2261SMartin Matuska abd_checksum_blake3_native(abd_t *abd, uint64_t size, const void *ctx_template, 481f1e2261SMartin Matuska zio_cksum_t *zcp) 491f1e2261SMartin Matuska { 50*15f0b8c3SMartin Matuska ASSERT(ctx_template != NULL); 511f1e2261SMartin Matuska 521f1e2261SMartin Matuska #if defined(_KERNEL) 531f1e2261SMartin Matuska BLAKE3_CTX *ctx = blake3_per_cpu_ctx[CPU_SEQID_UNSTABLE]; 541f1e2261SMartin Matuska #else 551f1e2261SMartin Matuska BLAKE3_CTX *ctx = kmem_alloc(sizeof (*ctx), KM_SLEEP); 561f1e2261SMartin Matuska #endif 571f1e2261SMartin Matuska 581f1e2261SMartin Matuska memcpy(ctx, ctx_template, sizeof (*ctx)); 591f1e2261SMartin Matuska (void) abd_iterate_func(abd, 0, size, blake3_incremental, ctx); 601f1e2261SMartin Matuska Blake3_Final(ctx, (uint8_t *)zcp); 611f1e2261SMartin Matuska 621f1e2261SMartin Matuska #if !defined(_KERNEL) 631f1e2261SMartin Matuska memset(ctx, 0, sizeof (*ctx)); 641f1e2261SMartin Matuska kmem_free(ctx, sizeof (*ctx)); 651f1e2261SMartin Matuska #endif 661f1e2261SMartin Matuska } 671f1e2261SMartin Matuska 681f1e2261SMartin Matuska /* 691f1e2261SMartin Matuska * Byteswapped version of abd_checksum_blake3_native. This just invokes 701f1e2261SMartin Matuska * the native checksum function and byteswaps the resulting checksum (since 711f1e2261SMartin Matuska * BLAKE3 is internally endian-insensitive). 721f1e2261SMartin Matuska */ 731f1e2261SMartin Matuska void 741f1e2261SMartin Matuska abd_checksum_blake3_byteswap(abd_t *abd, uint64_t size, 751f1e2261SMartin Matuska const void *ctx_template, zio_cksum_t *zcp) 761f1e2261SMartin Matuska { 771f1e2261SMartin Matuska zio_cksum_t tmp; 781f1e2261SMartin Matuska 79*15f0b8c3SMartin Matuska ASSERT(ctx_template != NULL); 801f1e2261SMartin Matuska 811f1e2261SMartin Matuska abd_checksum_blake3_native(abd, size, ctx_template, &tmp); 821f1e2261SMartin Matuska zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]); 831f1e2261SMartin Matuska zcp->zc_word[1] = BSWAP_64(tmp.zc_word[1]); 841f1e2261SMartin Matuska zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]); 851f1e2261SMartin Matuska zcp->zc_word[3] = BSWAP_64(tmp.zc_word[3]); 861f1e2261SMartin Matuska } 871f1e2261SMartin Matuska 881f1e2261SMartin Matuska /* 891f1e2261SMartin Matuska * Allocates a BLAKE3 MAC template suitable for using in BLAKE3 MAC checksum 901f1e2261SMartin Matuska * computations and returns a pointer to it. 911f1e2261SMartin Matuska */ 921f1e2261SMartin Matuska void * 931f1e2261SMartin Matuska abd_checksum_blake3_tmpl_init(const zio_cksum_salt_t *salt) 941f1e2261SMartin Matuska { 951f1e2261SMartin Matuska BLAKE3_CTX *ctx; 961f1e2261SMartin Matuska 971f1e2261SMartin Matuska ASSERT(sizeof (salt->zcs_bytes) == 32); 981f1e2261SMartin Matuska 991f1e2261SMartin Matuska /* init reference object */ 1001f1e2261SMartin Matuska ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); 1011f1e2261SMartin Matuska Blake3_InitKeyed(ctx, salt->zcs_bytes); 1021f1e2261SMartin Matuska 1031f1e2261SMartin Matuska return (ctx); 1041f1e2261SMartin Matuska } 1051f1e2261SMartin Matuska 1061f1e2261SMartin Matuska /* 1071f1e2261SMartin Matuska * Frees a BLAKE3 context template previously allocated using 1081f1e2261SMartin Matuska * zio_checksum_blake3_tmpl_init. 1091f1e2261SMartin Matuska */ 1101f1e2261SMartin Matuska void 1111f1e2261SMartin Matuska abd_checksum_blake3_tmpl_free(void *ctx_template) 1121f1e2261SMartin Matuska { 1131f1e2261SMartin Matuska BLAKE3_CTX *ctx = ctx_template; 1141f1e2261SMartin Matuska 1151f1e2261SMartin Matuska memset(ctx, 0, sizeof (*ctx)); 1161f1e2261SMartin Matuska kmem_free(ctx, sizeof (*ctx)); 1171f1e2261SMartin Matuska } 118