1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23eda14cbcSMatt Macy * Use is subject to license terms. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <sys/zfs_context.h> 27eda14cbcSMatt Macy #include <modes/modes.h> 28eda14cbcSMatt Macy #include <sys/crypto/common.h> 29eda14cbcSMatt Macy #include <sys/crypto/impl.h> 30eda14cbcSMatt Macy 31eda14cbcSMatt Macy /* 32eda14cbcSMatt Macy * Initialize by setting iov_or_mp to point to the current iovec or mp, 33eda14cbcSMatt Macy * and by setting current_offset to an offset within the current iovec or mp. 34eda14cbcSMatt Macy */ 35eda14cbcSMatt Macy void 36eda14cbcSMatt Macy crypto_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset) 37eda14cbcSMatt Macy { 38eda14cbcSMatt Macy offset_t offset; 39eda14cbcSMatt Macy 40eda14cbcSMatt Macy switch (out->cd_format) { 41eda14cbcSMatt Macy case CRYPTO_DATA_RAW: 42eda14cbcSMatt Macy *current_offset = out->cd_offset; 43eda14cbcSMatt Macy break; 44eda14cbcSMatt Macy 45eda14cbcSMatt Macy case CRYPTO_DATA_UIO: { 46184c1b94SMartin Matuska zfs_uio_t *uiop = out->cd_uio; 47eda14cbcSMatt Macy uint_t vec_idx; 48eda14cbcSMatt Macy 49eda14cbcSMatt Macy offset = out->cd_offset; 50184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(uiop, offset, &vec_idx); 51eda14cbcSMatt Macy 52eda14cbcSMatt Macy *current_offset = offset; 53eda14cbcSMatt Macy *iov_or_mp = (void *)(uintptr_t)vec_idx; 54eda14cbcSMatt Macy break; 55eda14cbcSMatt Macy } 56eda14cbcSMatt Macy } /* end switch */ 57eda14cbcSMatt Macy } 58eda14cbcSMatt Macy 59eda14cbcSMatt Macy /* 60eda14cbcSMatt Macy * Get pointers for where in the output to copy a block of encrypted or 61eda14cbcSMatt Macy * decrypted data. The iov_or_mp argument stores a pointer to the current 62eda14cbcSMatt Macy * iovec or mp, and offset stores an offset into the current iovec or mp. 63eda14cbcSMatt Macy */ 64eda14cbcSMatt Macy void 65eda14cbcSMatt Macy crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset, 66eda14cbcSMatt Macy uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2, 67eda14cbcSMatt Macy size_t amt) 68eda14cbcSMatt Macy { 69eda14cbcSMatt Macy offset_t offset; 70eda14cbcSMatt Macy 71eda14cbcSMatt Macy switch (out->cd_format) { 72eda14cbcSMatt Macy case CRYPTO_DATA_RAW: { 73eda14cbcSMatt Macy iovec_t *iov; 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy offset = *current_offset; 76eda14cbcSMatt Macy iov = &out->cd_raw; 77eda14cbcSMatt Macy if ((offset + amt) <= iov->iov_len) { 78eda14cbcSMatt Macy /* one block fits */ 79eda14cbcSMatt Macy *out_data_1 = (uint8_t *)iov->iov_base + offset; 80eda14cbcSMatt Macy *out_data_1_len = amt; 81eda14cbcSMatt Macy *out_data_2 = NULL; 82eda14cbcSMatt Macy *current_offset = offset + amt; 83eda14cbcSMatt Macy } 84eda14cbcSMatt Macy break; 85eda14cbcSMatt Macy } 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy case CRYPTO_DATA_UIO: { 88184c1b94SMartin Matuska zfs_uio_t *uio = out->cd_uio; 89eda14cbcSMatt Macy offset_t offset; 90eda14cbcSMatt Macy uint_t vec_idx; 91eda14cbcSMatt Macy uint8_t *p; 92eda14cbcSMatt Macy uint64_t iov_len; 93eda14cbcSMatt Macy void *iov_base; 94eda14cbcSMatt Macy 95eda14cbcSMatt Macy offset = *current_offset; 96eda14cbcSMatt Macy vec_idx = (uintptr_t)(*iov_or_mp); 97184c1b94SMartin Matuska zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); 98eda14cbcSMatt Macy p = (uint8_t *)iov_base + offset; 99eda14cbcSMatt Macy *out_data_1 = p; 100eda14cbcSMatt Macy 101eda14cbcSMatt Macy if (offset + amt <= iov_len) { 102eda14cbcSMatt Macy /* can fit one block into this iov */ 103eda14cbcSMatt Macy *out_data_1_len = amt; 104eda14cbcSMatt Macy *out_data_2 = NULL; 105eda14cbcSMatt Macy *current_offset = offset + amt; 106eda14cbcSMatt Macy } else { 107eda14cbcSMatt Macy /* one block spans two iovecs */ 108eda14cbcSMatt Macy *out_data_1_len = iov_len - offset; 109dbd5678dSMartin Matuska if (vec_idx == zfs_uio_iovcnt(uio)) { 110dbd5678dSMartin Matuska *out_data_2 = NULL; 111eda14cbcSMatt Macy return; 112dbd5678dSMartin Matuska } 113eda14cbcSMatt Macy vec_idx++; 114184c1b94SMartin Matuska zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); 115eda14cbcSMatt Macy *out_data_2 = (uint8_t *)iov_base; 116eda14cbcSMatt Macy *current_offset = amt - *out_data_1_len; 117eda14cbcSMatt Macy } 118eda14cbcSMatt Macy *iov_or_mp = (void *)(uintptr_t)vec_idx; 119eda14cbcSMatt Macy break; 120eda14cbcSMatt Macy } 121eda14cbcSMatt Macy } /* end switch */ 122eda14cbcSMatt Macy } 123eda14cbcSMatt Macy 124eda14cbcSMatt Macy void 125eda14cbcSMatt Macy crypto_free_mode_ctx(void *ctx) 126eda14cbcSMatt Macy { 127eda14cbcSMatt Macy common_ctx_t *common_ctx = (common_ctx_t *)ctx; 128eda14cbcSMatt Macy 129*75e1fea6SMartin Matuska switch (common_ctx->cc_flags & (CCM_MODE|GCM_MODE)) { 130eda14cbcSMatt Macy case CCM_MODE: 131eda14cbcSMatt Macy if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 132eda14cbcSMatt Macy vmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf, 133eda14cbcSMatt Macy ((ccm_ctx_t *)ctx)->ccm_data_len); 134eda14cbcSMatt Macy 135eda14cbcSMatt Macy kmem_free(ctx, sizeof (ccm_ctx_t)); 136eda14cbcSMatt Macy break; 137eda14cbcSMatt Macy 138eda14cbcSMatt Macy case GCM_MODE: 1392a58b312SMartin Matuska gcm_clear_ctx((gcm_ctx_t *)ctx); 140eda14cbcSMatt Macy kmem_free(ctx, sizeof (gcm_ctx_t)); 141*75e1fea6SMartin Matuska break; 142*75e1fea6SMartin Matuska 143*75e1fea6SMartin Matuska default: 144*75e1fea6SMartin Matuska __builtin_unreachable(); 145eda14cbcSMatt Macy } 146eda14cbcSMatt Macy } 1472a58b312SMartin Matuska 1482a58b312SMartin Matuska static void * 1492a58b312SMartin Matuska explicit_memset(void *s, int c, size_t n) 1502a58b312SMartin Matuska { 1512a58b312SMartin Matuska memset(s, c, n); 1522a58b312SMartin Matuska __asm__ __volatile__("" :: "r"(s) : "memory"); 1532a58b312SMartin Matuska return (s); 1542a58b312SMartin Matuska } 1552a58b312SMartin Matuska 1562a58b312SMartin Matuska /* 1572a58b312SMartin Matuska * Clear sensitive data in the context and free allocated memory. 1582a58b312SMartin Matuska * 1592a58b312SMartin Matuska * ctx->gcm_remainder may contain a plaintext remainder. ctx->gcm_H and 1602a58b312SMartin Matuska * ctx->gcm_Htable contain the hash sub key which protects authentication. 1612a58b312SMartin Matuska * ctx->gcm_pt_buf contains the plaintext result of decryption. 1622a58b312SMartin Matuska * 1632a58b312SMartin Matuska * Although extremely unlikely, ctx->gcm_J0 and ctx->gcm_tmp could be used for 1642a58b312SMartin Matuska * a known plaintext attack, they consist of the IV and the first and last 1652a58b312SMartin Matuska * counter respectively. If they should be cleared is debatable. 1662a58b312SMartin Matuska */ 1672a58b312SMartin Matuska void 1682a58b312SMartin Matuska gcm_clear_ctx(gcm_ctx_t *ctx) 1692a58b312SMartin Matuska { 1702a58b312SMartin Matuska explicit_memset(ctx->gcm_remainder, 0, sizeof (ctx->gcm_remainder)); 1712a58b312SMartin Matuska explicit_memset(ctx->gcm_H, 0, sizeof (ctx->gcm_H)); 1722a58b312SMartin Matuska #if defined(CAN_USE_GCM_ASM) 1732a58b312SMartin Matuska if (ctx->gcm_use_avx == B_TRUE) { 1742a58b312SMartin Matuska ASSERT3P(ctx->gcm_Htable, !=, NULL); 1752a58b312SMartin Matuska memset(ctx->gcm_Htable, 0, ctx->gcm_htab_len); 1762a58b312SMartin Matuska kmem_free(ctx->gcm_Htable, ctx->gcm_htab_len); 1772a58b312SMartin Matuska } 1782a58b312SMartin Matuska #endif 1792a58b312SMartin Matuska if (ctx->gcm_pt_buf != NULL) { 1802a58b312SMartin Matuska memset(ctx->gcm_pt_buf, 0, ctx->gcm_pt_buf_len); 1812a58b312SMartin Matuska vmem_free(ctx->gcm_pt_buf, ctx->gcm_pt_buf_len); 1822a58b312SMartin Matuska } 1832a58b312SMartin Matuska /* Optional */ 1842a58b312SMartin Matuska explicit_memset(ctx->gcm_J0, 0, sizeof (ctx->gcm_J0)); 1852a58b312SMartin Matuska explicit_memset(ctx->gcm_tmp, 0, sizeof (ctx->gcm_tmp)); 1862a58b312SMartin Matuska } 187