1*23c57df7Smcpowers /* 2*23c57df7Smcpowers * CDDL HEADER START 3*23c57df7Smcpowers * 4*23c57df7Smcpowers * The contents of this file are subject to the terms of the 5*23c57df7Smcpowers * Common Development and Distribution License (the "License"). 6*23c57df7Smcpowers * You may not use this file except in compliance with the License. 7*23c57df7Smcpowers * 8*23c57df7Smcpowers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*23c57df7Smcpowers * or http://www.opensolaris.org/os/licensing. 10*23c57df7Smcpowers * See the License for the specific language governing permissions 11*23c57df7Smcpowers * and limitations under the License. 12*23c57df7Smcpowers * 13*23c57df7Smcpowers * When distributing Covered Code, include this CDDL HEADER in each 14*23c57df7Smcpowers * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*23c57df7Smcpowers * If applicable, add the following below this CDDL HEADER, with the 16*23c57df7Smcpowers * fields enclosed by brackets "[]" replaced with your own identifying 17*23c57df7Smcpowers * information: Portions Copyright [yyyy] [name of copyright owner] 18*23c57df7Smcpowers * 19*23c57df7Smcpowers * CDDL HEADER END 20*23c57df7Smcpowers */ 21*23c57df7Smcpowers /* 22*23c57df7Smcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*23c57df7Smcpowers * Use is subject to license terms. 24*23c57df7Smcpowers */ 25*23c57df7Smcpowers 26*23c57df7Smcpowers #pragma ident "%Z%%M% %I% %E% SMI" 27*23c57df7Smcpowers 28*23c57df7Smcpowers #ifndef _KERNEL 29*23c57df7Smcpowers #include <stdlib.h> 30*23c57df7Smcpowers #endif 31*23c57df7Smcpowers 32*23c57df7Smcpowers #include <sys/strsun.h> 33*23c57df7Smcpowers #include <sys/types.h> 34*23c57df7Smcpowers #include <modes/modes.h> 35*23c57df7Smcpowers #include <sys/crypto/common.h> 36*23c57df7Smcpowers #include <sys/crypto/impl.h> 37*23c57df7Smcpowers 38*23c57df7Smcpowers /* 39*23c57df7Smcpowers * Initialize by setting iov_or_mp to point to the current iovec or mp, 40*23c57df7Smcpowers * and by setting current_offset to an offset within the current iovec or mp. 41*23c57df7Smcpowers */ 42*23c57df7Smcpowers void 43*23c57df7Smcpowers crypto_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset) 44*23c57df7Smcpowers { 45*23c57df7Smcpowers offset_t offset; 46*23c57df7Smcpowers 47*23c57df7Smcpowers switch (out->cd_format) { 48*23c57df7Smcpowers case CRYPTO_DATA_RAW: 49*23c57df7Smcpowers *current_offset = out->cd_offset; 50*23c57df7Smcpowers break; 51*23c57df7Smcpowers 52*23c57df7Smcpowers case CRYPTO_DATA_UIO: { 53*23c57df7Smcpowers uio_t *uiop = out->cd_uio; 54*23c57df7Smcpowers uintptr_t vec_idx; 55*23c57df7Smcpowers 56*23c57df7Smcpowers offset = out->cd_offset; 57*23c57df7Smcpowers for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 58*23c57df7Smcpowers offset >= uiop->uio_iov[vec_idx].iov_len; 59*23c57df7Smcpowers offset -= uiop->uio_iov[vec_idx++].iov_len) 60*23c57df7Smcpowers ; 61*23c57df7Smcpowers 62*23c57df7Smcpowers *current_offset = offset; 63*23c57df7Smcpowers *iov_or_mp = (void *)vec_idx; 64*23c57df7Smcpowers break; 65*23c57df7Smcpowers } 66*23c57df7Smcpowers 67*23c57df7Smcpowers case CRYPTO_DATA_MBLK: { 68*23c57df7Smcpowers mblk_t *mp; 69*23c57df7Smcpowers 70*23c57df7Smcpowers offset = out->cd_offset; 71*23c57df7Smcpowers for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); 72*23c57df7Smcpowers offset -= MBLKL(mp), mp = mp->b_cont) 73*23c57df7Smcpowers ; 74*23c57df7Smcpowers 75*23c57df7Smcpowers *current_offset = offset; 76*23c57df7Smcpowers *iov_or_mp = mp; 77*23c57df7Smcpowers break; 78*23c57df7Smcpowers 79*23c57df7Smcpowers } 80*23c57df7Smcpowers } /* end switch */ 81*23c57df7Smcpowers } 82*23c57df7Smcpowers 83*23c57df7Smcpowers /* 84*23c57df7Smcpowers * Get pointers for where in the output to copy a block of encrypted or 85*23c57df7Smcpowers * decrypted data. The iov_or_mp argument stores a pointer to the current 86*23c57df7Smcpowers * iovec or mp, and offset stores an offset into the current iovec or mp. 87*23c57df7Smcpowers */ 88*23c57df7Smcpowers void 89*23c57df7Smcpowers crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset, 90*23c57df7Smcpowers uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2, 91*23c57df7Smcpowers size_t amt) 92*23c57df7Smcpowers { 93*23c57df7Smcpowers offset_t offset; 94*23c57df7Smcpowers 95*23c57df7Smcpowers switch (out->cd_format) { 96*23c57df7Smcpowers case CRYPTO_DATA_RAW: { 97*23c57df7Smcpowers iovec_t *iov; 98*23c57df7Smcpowers 99*23c57df7Smcpowers offset = *current_offset; 100*23c57df7Smcpowers iov = &out->cd_raw; 101*23c57df7Smcpowers if ((offset + amt) <= iov->iov_len) { 102*23c57df7Smcpowers /* one block fits */ 103*23c57df7Smcpowers *out_data_1 = (uint8_t *)iov->iov_base + offset; 104*23c57df7Smcpowers *out_data_1_len = amt; 105*23c57df7Smcpowers *out_data_2 = NULL; 106*23c57df7Smcpowers *current_offset = offset + amt; 107*23c57df7Smcpowers } 108*23c57df7Smcpowers break; 109*23c57df7Smcpowers } 110*23c57df7Smcpowers 111*23c57df7Smcpowers case CRYPTO_DATA_UIO: { 112*23c57df7Smcpowers uio_t *uio = out->cd_uio; 113*23c57df7Smcpowers iovec_t *iov; 114*23c57df7Smcpowers offset_t offset; 115*23c57df7Smcpowers uintptr_t vec_idx; 116*23c57df7Smcpowers uint8_t *p; 117*23c57df7Smcpowers 118*23c57df7Smcpowers offset = *current_offset; 119*23c57df7Smcpowers vec_idx = (uintptr_t)(*iov_or_mp); 120*23c57df7Smcpowers iov = &uio->uio_iov[vec_idx]; 121*23c57df7Smcpowers p = (uint8_t *)iov->iov_base + offset; 122*23c57df7Smcpowers *out_data_1 = p; 123*23c57df7Smcpowers 124*23c57df7Smcpowers if (offset + amt <= iov->iov_len) { 125*23c57df7Smcpowers /* can fit one block into this iov */ 126*23c57df7Smcpowers *out_data_1_len = amt; 127*23c57df7Smcpowers *out_data_2 = NULL; 128*23c57df7Smcpowers *current_offset = offset + amt; 129*23c57df7Smcpowers } else { 130*23c57df7Smcpowers /* one block spans two iovecs */ 131*23c57df7Smcpowers *out_data_1_len = iov->iov_len - offset; 132*23c57df7Smcpowers if (vec_idx == uio->uio_iovcnt) 133*23c57df7Smcpowers return; 134*23c57df7Smcpowers vec_idx++; 135*23c57df7Smcpowers iov = &uio->uio_iov[vec_idx]; 136*23c57df7Smcpowers *out_data_2 = (uint8_t *)iov->iov_base; 137*23c57df7Smcpowers *current_offset = amt - *out_data_1_len; 138*23c57df7Smcpowers } 139*23c57df7Smcpowers *iov_or_mp = (void *)vec_idx; 140*23c57df7Smcpowers break; 141*23c57df7Smcpowers } 142*23c57df7Smcpowers 143*23c57df7Smcpowers case CRYPTO_DATA_MBLK: { 144*23c57df7Smcpowers mblk_t *mp; 145*23c57df7Smcpowers uint8_t *p; 146*23c57df7Smcpowers 147*23c57df7Smcpowers offset = *current_offset; 148*23c57df7Smcpowers mp = (mblk_t *)*iov_or_mp; 149*23c57df7Smcpowers p = mp->b_rptr + offset; 150*23c57df7Smcpowers *out_data_1 = p; 151*23c57df7Smcpowers if ((p + amt) <= mp->b_wptr) { 152*23c57df7Smcpowers /* can fit one block into this mblk */ 153*23c57df7Smcpowers *out_data_1_len = amt; 154*23c57df7Smcpowers *out_data_2 = NULL; 155*23c57df7Smcpowers *current_offset = offset + amt; 156*23c57df7Smcpowers } else { 157*23c57df7Smcpowers /* one block spans two mblks */ 158*23c57df7Smcpowers *out_data_1_len = mp->b_wptr - p; 159*23c57df7Smcpowers if ((mp = mp->b_cont) == NULL) 160*23c57df7Smcpowers return; 161*23c57df7Smcpowers *out_data_2 = mp->b_rptr; 162*23c57df7Smcpowers *current_offset = (amt - *out_data_1_len); 163*23c57df7Smcpowers } 164*23c57df7Smcpowers *iov_or_mp = mp; 165*23c57df7Smcpowers break; 166*23c57df7Smcpowers } 167*23c57df7Smcpowers } /* end switch */ 168*23c57df7Smcpowers } 169*23c57df7Smcpowers 170*23c57df7Smcpowers void 171*23c57df7Smcpowers crypto_free_mode_ctx(void *ctx) 172*23c57df7Smcpowers { 173*23c57df7Smcpowers common_ctx_t *common_ctx = (common_ctx_t *)ctx; 174*23c57df7Smcpowers 175*23c57df7Smcpowers if (common_ctx->cc_flags & ECB_MODE) 176*23c57df7Smcpowers #ifdef _KERNEL 177*23c57df7Smcpowers kmem_free(common_ctx, sizeof (ecb_ctx_t)); 178*23c57df7Smcpowers #else 179*23c57df7Smcpowers free(common_ctx); 180*23c57df7Smcpowers #endif 181*23c57df7Smcpowers else if (common_ctx->cc_flags & CBC_MODE) 182*23c57df7Smcpowers #ifdef _KERNEL 183*23c57df7Smcpowers kmem_free(common_ctx, sizeof (cbc_ctx_t)); 184*23c57df7Smcpowers #else 185*23c57df7Smcpowers free(common_ctx); 186*23c57df7Smcpowers #endif 187*23c57df7Smcpowers else if (common_ctx->cc_flags & CTR_MODE) 188*23c57df7Smcpowers #ifdef _KERNEL 189*23c57df7Smcpowers kmem_free(common_ctx, sizeof (ctr_ctx_t)); 190*23c57df7Smcpowers #else 191*23c57df7Smcpowers free(common_ctx); 192*23c57df7Smcpowers #endif 193*23c57df7Smcpowers else if (common_ctx->cc_flags & CCM_MODE) { 194*23c57df7Smcpowers #ifdef _KERNEL 195*23c57df7Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 196*23c57df7Smcpowers kmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf, 197*23c57df7Smcpowers ((ccm_ctx_t *)ctx)->ccm_data_len); 198*23c57df7Smcpowers 199*23c57df7Smcpowers kmem_free(ctx, sizeof (ccm_ctx_t)); 200*23c57df7Smcpowers #else 201*23c57df7Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 202*23c57df7Smcpowers free(((ccm_ctx_t *)ctx)->ccm_pt_buf); 203*23c57df7Smcpowers free(ctx); 204*23c57df7Smcpowers #endif 205*23c57df7Smcpowers } 206*23c57df7Smcpowers } 207