Path: blob/main/sys/contrib/openzfs/module/icp/algs/modes/modes.c
48774 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright 2009 Sun Microsystems, Inc. All rights reserved.23* Use is subject to license terms.24*/2526#include <sys/zfs_context.h>27#include <modes/modes.h>28#include <sys/crypto/common.h>29#include <sys/crypto/impl.h>3031/*32* Initialize by setting iov_or_mp to point to the current iovec or mp,33* and by setting current_offset to an offset within the current iovec or mp.34*/35void36crypto_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset)37{38offset_t offset;3940switch (out->cd_format) {41case CRYPTO_DATA_RAW:42*current_offset = out->cd_offset;43break;4445case CRYPTO_DATA_UIO: {46zfs_uio_t *uiop = out->cd_uio;47uint_t vec_idx;4849offset = out->cd_offset;50offset = zfs_uio_index_at_offset(uiop, offset, &vec_idx);5152*current_offset = offset;53*iov_or_mp = (void *)(uintptr_t)vec_idx;54break;55}56} /* end switch */57}5859/*60* Get pointers for where in the output to copy a block of encrypted or61* decrypted data. The iov_or_mp argument stores a pointer to the current62* iovec or mp, and offset stores an offset into the current iovec or mp.63*/64void65crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset,66uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2,67size_t amt)68{69offset_t offset;7071switch (out->cd_format) {72case CRYPTO_DATA_RAW: {73iovec_t *iov;7475offset = *current_offset;76iov = &out->cd_raw;77if ((offset + amt) <= iov->iov_len) {78/* one block fits */79*out_data_1 = (uint8_t *)iov->iov_base + offset;80*out_data_1_len = amt;81*out_data_2 = NULL;82*current_offset = offset + amt;83}84break;85}8687case CRYPTO_DATA_UIO: {88zfs_uio_t *uio = out->cd_uio;89offset_t offset;90uint_t vec_idx;91uint8_t *p;92uint64_t iov_len;93void *iov_base;9495offset = *current_offset;96vec_idx = (uintptr_t)(*iov_or_mp);97zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len);98p = (uint8_t *)iov_base + offset;99*out_data_1 = p;100101if (offset + amt <= iov_len) {102/* can fit one block into this iov */103*out_data_1_len = amt;104*out_data_2 = NULL;105*current_offset = offset + amt;106} else {107/* one block spans two iovecs */108*out_data_1_len = iov_len - offset;109if (vec_idx == zfs_uio_iovcnt(uio)) {110*out_data_2 = NULL;111return;112}113vec_idx++;114zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len);115*out_data_2 = (uint8_t *)iov_base;116*current_offset = amt - *out_data_1_len;117}118*iov_or_mp = (void *)(uintptr_t)vec_idx;119break;120}121} /* end switch */122}123124void125crypto_free_mode_ctx(void *ctx)126{127common_ctx_t *common_ctx = (common_ctx_t *)ctx;128129switch (common_ctx->cc_flags & (CCM_MODE|GCM_MODE)) {130case CCM_MODE:131if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL)132vmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf,133((ccm_ctx_t *)ctx)->ccm_data_len);134135kmem_free(ctx, sizeof (ccm_ctx_t));136break;137138case GCM_MODE:139gcm_clear_ctx((gcm_ctx_t *)ctx);140kmem_free(ctx, sizeof (gcm_ctx_t));141break;142143default:144__builtin_unreachable();145}146}147148static void *149explicit_memset(void *s, int c, size_t n)150{151memset(s, c, n);152__asm__ __volatile__("" :: "r"(s) : "memory");153return (s);154}155156/*157* Clear sensitive data in the context and free allocated memory.158*159* ctx->gcm_remainder may contain a plaintext remainder. ctx->gcm_H and160* ctx->gcm_Htable contain the hash sub key which protects authentication.161* ctx->gcm_pt_buf contains the plaintext result of decryption.162*163* Although extremely unlikely, ctx->gcm_J0 and ctx->gcm_tmp could be used for164* a known plaintext attack, they consist of the IV and the first and last165* counter respectively. If they should be cleared is debatable.166*/167void168gcm_clear_ctx(gcm_ctx_t *ctx)169{170explicit_memset(ctx->gcm_remainder, 0, sizeof (ctx->gcm_remainder));171explicit_memset(ctx->gcm_H, 0, sizeof (ctx->gcm_H));172#if defined(CAN_USE_GCM_ASM)173if (ctx->impl != GCM_IMPL_GENERIC) {174ASSERT3P(ctx->gcm_Htable, !=, NULL);175explicit_memset(ctx->gcm_Htable, 0, ctx->gcm_htab_len);176kmem_free(ctx->gcm_Htable, ctx->gcm_htab_len);177}178#endif179if (ctx->gcm_pt_buf != NULL) {180explicit_memset(ctx->gcm_pt_buf, 0, ctx->gcm_pt_buf_len);181vmem_free(ctx->gcm_pt_buf, ctx->gcm_pt_buf_len);182}183/* Optional */184explicit_memset(ctx->gcm_J0, 0, sizeof (ctx->gcm_J0));185explicit_memset(ctx->gcm_tmp, 0, sizeof (ctx->gcm_tmp));186}187188189