123c57df7Smcpowers /* 223c57df7Smcpowers * CDDL HEADER START 323c57df7Smcpowers * 423c57df7Smcpowers * The contents of this file are subject to the terms of the 523c57df7Smcpowers * Common Development and Distribution License (the "License"). 623c57df7Smcpowers * You may not use this file except in compliance with the License. 723c57df7Smcpowers * 823c57df7Smcpowers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 923c57df7Smcpowers * or http://www.opensolaris.org/os/licensing. 1023c57df7Smcpowers * See the License for the specific language governing permissions 1123c57df7Smcpowers * and limitations under the License. 1223c57df7Smcpowers * 1323c57df7Smcpowers * When distributing Covered Code, include this CDDL HEADER in each 1423c57df7Smcpowers * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1523c57df7Smcpowers * If applicable, add the following below this CDDL HEADER, with the 1623c57df7Smcpowers * fields enclosed by brackets "[]" replaced with your own identifying 1723c57df7Smcpowers * information: Portions Copyright [yyyy] [name of copyright owner] 1823c57df7Smcpowers * 1923c57df7Smcpowers * CDDL HEADER END 2023c57df7Smcpowers */ 2123c57df7Smcpowers /* 2223c57df7Smcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2323c57df7Smcpowers * Use is subject to license terms. 2423c57df7Smcpowers */ 2523c57df7Smcpowers 2623c57df7Smcpowers #ifndef _KERNEL 2723c57df7Smcpowers #include <stdlib.h> 2823c57df7Smcpowers #endif 2923c57df7Smcpowers 3023c57df7Smcpowers #include <sys/strsun.h> 3123c57df7Smcpowers #include <sys/types.h> 3223c57df7Smcpowers #include <modes/modes.h> 3323c57df7Smcpowers #include <sys/crypto/common.h> 3423c57df7Smcpowers #include <sys/crypto/impl.h> 3523c57df7Smcpowers 3623c57df7Smcpowers /* 3723c57df7Smcpowers * Initialize by setting iov_or_mp to point to the current iovec or mp, 3823c57df7Smcpowers * and by setting current_offset to an offset within the current iovec or mp. 3923c57df7Smcpowers */ 4023c57df7Smcpowers void 4123c57df7Smcpowers crypto_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset) 4223c57df7Smcpowers { 4323c57df7Smcpowers offset_t offset; 4423c57df7Smcpowers 4523c57df7Smcpowers switch (out->cd_format) { 4623c57df7Smcpowers case CRYPTO_DATA_RAW: 4723c57df7Smcpowers *current_offset = out->cd_offset; 4823c57df7Smcpowers break; 4923c57df7Smcpowers 5023c57df7Smcpowers case CRYPTO_DATA_UIO: { 5123c57df7Smcpowers uio_t *uiop = out->cd_uio; 5223c57df7Smcpowers uintptr_t vec_idx; 5323c57df7Smcpowers 5423c57df7Smcpowers offset = out->cd_offset; 5523c57df7Smcpowers for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 5623c57df7Smcpowers offset >= uiop->uio_iov[vec_idx].iov_len; 5723c57df7Smcpowers offset -= uiop->uio_iov[vec_idx++].iov_len) 5823c57df7Smcpowers ; 5923c57df7Smcpowers 6023c57df7Smcpowers *current_offset = offset; 6123c57df7Smcpowers *iov_or_mp = (void *)vec_idx; 6223c57df7Smcpowers break; 6323c57df7Smcpowers } 6423c57df7Smcpowers 6523c57df7Smcpowers case CRYPTO_DATA_MBLK: { 6623c57df7Smcpowers mblk_t *mp; 6723c57df7Smcpowers 6823c57df7Smcpowers offset = out->cd_offset; 6923c57df7Smcpowers for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); 7023c57df7Smcpowers offset -= MBLKL(mp), mp = mp->b_cont) 7123c57df7Smcpowers ; 7223c57df7Smcpowers 7323c57df7Smcpowers *current_offset = offset; 7423c57df7Smcpowers *iov_or_mp = mp; 7523c57df7Smcpowers break; 7623c57df7Smcpowers 7723c57df7Smcpowers } 7823c57df7Smcpowers } /* end switch */ 7923c57df7Smcpowers } 8023c57df7Smcpowers 8123c57df7Smcpowers /* 8223c57df7Smcpowers * Get pointers for where in the output to copy a block of encrypted or 8323c57df7Smcpowers * decrypted data. The iov_or_mp argument stores a pointer to the current 8423c57df7Smcpowers * iovec or mp, and offset stores an offset into the current iovec or mp. 8523c57df7Smcpowers */ 8623c57df7Smcpowers void 8723c57df7Smcpowers crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset, 8823c57df7Smcpowers uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2, 8923c57df7Smcpowers size_t amt) 9023c57df7Smcpowers { 9123c57df7Smcpowers offset_t offset; 9223c57df7Smcpowers 9323c57df7Smcpowers switch (out->cd_format) { 9423c57df7Smcpowers case CRYPTO_DATA_RAW: { 9523c57df7Smcpowers iovec_t *iov; 9623c57df7Smcpowers 9723c57df7Smcpowers offset = *current_offset; 9823c57df7Smcpowers iov = &out->cd_raw; 9923c57df7Smcpowers if ((offset + amt) <= iov->iov_len) { 10023c57df7Smcpowers /* one block fits */ 10123c57df7Smcpowers *out_data_1 = (uint8_t *)iov->iov_base + offset; 10223c57df7Smcpowers *out_data_1_len = amt; 10323c57df7Smcpowers *out_data_2 = NULL; 10423c57df7Smcpowers *current_offset = offset + amt; 10523c57df7Smcpowers } 10623c57df7Smcpowers break; 10723c57df7Smcpowers } 10823c57df7Smcpowers 10923c57df7Smcpowers case CRYPTO_DATA_UIO: { 11023c57df7Smcpowers uio_t *uio = out->cd_uio; 11123c57df7Smcpowers iovec_t *iov; 11223c57df7Smcpowers offset_t offset; 11323c57df7Smcpowers uintptr_t vec_idx; 11423c57df7Smcpowers uint8_t *p; 11523c57df7Smcpowers 11623c57df7Smcpowers offset = *current_offset; 11723c57df7Smcpowers vec_idx = (uintptr_t)(*iov_or_mp); 11823c57df7Smcpowers iov = &uio->uio_iov[vec_idx]; 11923c57df7Smcpowers p = (uint8_t *)iov->iov_base + offset; 12023c57df7Smcpowers *out_data_1 = p; 12123c57df7Smcpowers 12223c57df7Smcpowers if (offset + amt <= iov->iov_len) { 12323c57df7Smcpowers /* can fit one block into this iov */ 12423c57df7Smcpowers *out_data_1_len = amt; 12523c57df7Smcpowers *out_data_2 = NULL; 12623c57df7Smcpowers *current_offset = offset + amt; 12723c57df7Smcpowers } else { 12823c57df7Smcpowers /* one block spans two iovecs */ 12923c57df7Smcpowers *out_data_1_len = iov->iov_len - offset; 13023c57df7Smcpowers if (vec_idx == uio->uio_iovcnt) 13123c57df7Smcpowers return; 13223c57df7Smcpowers vec_idx++; 13323c57df7Smcpowers iov = &uio->uio_iov[vec_idx]; 13423c57df7Smcpowers *out_data_2 = (uint8_t *)iov->iov_base; 13523c57df7Smcpowers *current_offset = amt - *out_data_1_len; 13623c57df7Smcpowers } 13723c57df7Smcpowers *iov_or_mp = (void *)vec_idx; 13823c57df7Smcpowers break; 13923c57df7Smcpowers } 14023c57df7Smcpowers 14123c57df7Smcpowers case CRYPTO_DATA_MBLK: { 14223c57df7Smcpowers mblk_t *mp; 14323c57df7Smcpowers uint8_t *p; 14423c57df7Smcpowers 14523c57df7Smcpowers offset = *current_offset; 14623c57df7Smcpowers mp = (mblk_t *)*iov_or_mp; 14723c57df7Smcpowers p = mp->b_rptr + offset; 14823c57df7Smcpowers *out_data_1 = p; 14923c57df7Smcpowers if ((p + amt) <= mp->b_wptr) { 15023c57df7Smcpowers /* can fit one block into this mblk */ 15123c57df7Smcpowers *out_data_1_len = amt; 15223c57df7Smcpowers *out_data_2 = NULL; 15323c57df7Smcpowers *current_offset = offset + amt; 15423c57df7Smcpowers } else { 15523c57df7Smcpowers /* one block spans two mblks */ 15623c57df7Smcpowers *out_data_1_len = mp->b_wptr - p; 15723c57df7Smcpowers if ((mp = mp->b_cont) == NULL) 15823c57df7Smcpowers return; 15923c57df7Smcpowers *out_data_2 = mp->b_rptr; 16023c57df7Smcpowers *current_offset = (amt - *out_data_1_len); 16123c57df7Smcpowers } 16223c57df7Smcpowers *iov_or_mp = mp; 16323c57df7Smcpowers break; 16423c57df7Smcpowers } 16523c57df7Smcpowers } /* end switch */ 16623c57df7Smcpowers } 16723c57df7Smcpowers 16823c57df7Smcpowers void 16923c57df7Smcpowers crypto_free_mode_ctx(void *ctx) 17023c57df7Smcpowers { 17123c57df7Smcpowers common_ctx_t *common_ctx = (common_ctx_t *)ctx; 17223c57df7Smcpowers 173*4d703b5cSMark Powers switch (common_ctx->cc_flags & 174*4d703b5cSMark Powers (ECB_MODE|CBC_MODE|CTR_MODE|CCM_MODE|GCM_MODE)) { 175*4d703b5cSMark Powers case ECB_MODE: 17623c57df7Smcpowers #ifdef _KERNEL 17723c57df7Smcpowers kmem_free(common_ctx, sizeof (ecb_ctx_t)); 17823c57df7Smcpowers #else 17923c57df7Smcpowers free(common_ctx); 18023c57df7Smcpowers #endif 181*4d703b5cSMark Powers break; 182*4d703b5cSMark Powers 183*4d703b5cSMark Powers case CBC_MODE: 18423c57df7Smcpowers #ifdef _KERNEL 18523c57df7Smcpowers kmem_free(common_ctx, sizeof (cbc_ctx_t)); 18623c57df7Smcpowers #else 18723c57df7Smcpowers free(common_ctx); 18823c57df7Smcpowers #endif 189*4d703b5cSMark Powers break; 190*4d703b5cSMark Powers 191*4d703b5cSMark Powers case CTR_MODE: 19223c57df7Smcpowers #ifdef _KERNEL 19323c57df7Smcpowers kmem_free(common_ctx, sizeof (ctr_ctx_t)); 19423c57df7Smcpowers #else 19523c57df7Smcpowers free(common_ctx); 19623c57df7Smcpowers #endif 197*4d703b5cSMark Powers break; 198*4d703b5cSMark Powers 199*4d703b5cSMark Powers case CCM_MODE: 20023c57df7Smcpowers #ifdef _KERNEL 20123c57df7Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 20223c57df7Smcpowers kmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf, 20323c57df7Smcpowers ((ccm_ctx_t *)ctx)->ccm_data_len); 20423c57df7Smcpowers 20523c57df7Smcpowers kmem_free(ctx, sizeof (ccm_ctx_t)); 20623c57df7Smcpowers #else 20723c57df7Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 20823c57df7Smcpowers free(((ccm_ctx_t *)ctx)->ccm_pt_buf); 20923c57df7Smcpowers free(ctx); 21023c57df7Smcpowers #endif 211*4d703b5cSMark Powers break; 212*4d703b5cSMark Powers 213*4d703b5cSMark Powers case GCM_MODE: 214*4d703b5cSMark Powers #ifdef _KERNEL 215*4d703b5cSMark Powers if (((gcm_ctx_t *)ctx)->gcm_pt_buf != NULL) 216*4d703b5cSMark Powers kmem_free(((gcm_ctx_t *)ctx)->gcm_pt_buf, 217*4d703b5cSMark Powers ((gcm_ctx_t *)ctx)->gcm_pt_buf_len); 218*4d703b5cSMark Powers 219*4d703b5cSMark Powers kmem_free(ctx, sizeof (gcm_ctx_t)); 220*4d703b5cSMark Powers #else 221*4d703b5cSMark Powers if (((gcm_ctx_t *)ctx)->gcm_pt_buf != NULL) 222*4d703b5cSMark Powers free(((gcm_ctx_t *)ctx)->gcm_pt_buf); 223*4d703b5cSMark Powers free(ctx); 224*4d703b5cSMark Powers #endif 22523c57df7Smcpowers } 22623c57df7Smcpowers } 227