17188Smcpowers /* 27188Smcpowers * CDDL HEADER START 37188Smcpowers * 47188Smcpowers * The contents of this file are subject to the terms of the 57188Smcpowers * Common Development and Distribution License (the "License"). 67188Smcpowers * You may not use this file except in compliance with the License. 77188Smcpowers * 87188Smcpowers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97188Smcpowers * or http://www.opensolaris.org/os/licensing. 107188Smcpowers * See the License for the specific language governing permissions 117188Smcpowers * and limitations under the License. 127188Smcpowers * 137188Smcpowers * When distributing Covered Code, include this CDDL HEADER in each 147188Smcpowers * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157188Smcpowers * If applicable, add the following below this CDDL HEADER, with the 167188Smcpowers * fields enclosed by brackets "[]" replaced with your own identifying 177188Smcpowers * information: Portions Copyright [yyyy] [name of copyright owner] 187188Smcpowers * 197188Smcpowers * CDDL HEADER END 207188Smcpowers */ 217188Smcpowers /* 229339SMark.Powers@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237188Smcpowers * Use is subject to license terms. 247188Smcpowers */ 257188Smcpowers 267188Smcpowers #ifndef _KERNEL 277188Smcpowers #include <stdlib.h> 287188Smcpowers #endif 297188Smcpowers 307188Smcpowers #include <sys/strsun.h> 317188Smcpowers #include <sys/types.h> 327188Smcpowers #include <modes/modes.h> 337188Smcpowers #include <sys/crypto/common.h> 347188Smcpowers #include <sys/crypto/impl.h> 357188Smcpowers 367188Smcpowers /* 377188Smcpowers * Initialize by setting iov_or_mp to point to the current iovec or mp, 387188Smcpowers * and by setting current_offset to an offset within the current iovec or mp. 397188Smcpowers */ 407188Smcpowers void 417188Smcpowers crypto_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset) 427188Smcpowers { 437188Smcpowers offset_t offset; 447188Smcpowers 457188Smcpowers switch (out->cd_format) { 467188Smcpowers case CRYPTO_DATA_RAW: 477188Smcpowers *current_offset = out->cd_offset; 487188Smcpowers break; 497188Smcpowers 507188Smcpowers case CRYPTO_DATA_UIO: { 517188Smcpowers uio_t *uiop = out->cd_uio; 527188Smcpowers uintptr_t vec_idx; 537188Smcpowers 547188Smcpowers offset = out->cd_offset; 557188Smcpowers for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 567188Smcpowers offset >= uiop->uio_iov[vec_idx].iov_len; 577188Smcpowers offset -= uiop->uio_iov[vec_idx++].iov_len) 587188Smcpowers ; 597188Smcpowers 607188Smcpowers *current_offset = offset; 617188Smcpowers *iov_or_mp = (void *)vec_idx; 627188Smcpowers break; 637188Smcpowers } 647188Smcpowers 657188Smcpowers case CRYPTO_DATA_MBLK: { 667188Smcpowers mblk_t *mp; 677188Smcpowers 687188Smcpowers offset = out->cd_offset; 697188Smcpowers for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp); 707188Smcpowers offset -= MBLKL(mp), mp = mp->b_cont) 717188Smcpowers ; 727188Smcpowers 737188Smcpowers *current_offset = offset; 747188Smcpowers *iov_or_mp = mp; 757188Smcpowers break; 767188Smcpowers 777188Smcpowers } 787188Smcpowers } /* end switch */ 797188Smcpowers } 807188Smcpowers 817188Smcpowers /* 827188Smcpowers * Get pointers for where in the output to copy a block of encrypted or 837188Smcpowers * decrypted data. The iov_or_mp argument stores a pointer to the current 847188Smcpowers * iovec or mp, and offset stores an offset into the current iovec or mp. 857188Smcpowers */ 867188Smcpowers void 877188Smcpowers crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset, 887188Smcpowers uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2, 897188Smcpowers size_t amt) 907188Smcpowers { 917188Smcpowers offset_t offset; 927188Smcpowers 937188Smcpowers switch (out->cd_format) { 947188Smcpowers case CRYPTO_DATA_RAW: { 957188Smcpowers iovec_t *iov; 967188Smcpowers 977188Smcpowers offset = *current_offset; 987188Smcpowers iov = &out->cd_raw; 997188Smcpowers if ((offset + amt) <= iov->iov_len) { 1007188Smcpowers /* one block fits */ 1017188Smcpowers *out_data_1 = (uint8_t *)iov->iov_base + offset; 1027188Smcpowers *out_data_1_len = amt; 1037188Smcpowers *out_data_2 = NULL; 1047188Smcpowers *current_offset = offset + amt; 1057188Smcpowers } 1067188Smcpowers break; 1077188Smcpowers } 1087188Smcpowers 1097188Smcpowers case CRYPTO_DATA_UIO: { 1107188Smcpowers uio_t *uio = out->cd_uio; 1117188Smcpowers iovec_t *iov; 1127188Smcpowers offset_t offset; 1137188Smcpowers uintptr_t vec_idx; 1147188Smcpowers uint8_t *p; 1157188Smcpowers 1167188Smcpowers offset = *current_offset; 1177188Smcpowers vec_idx = (uintptr_t)(*iov_or_mp); 1187188Smcpowers iov = &uio->uio_iov[vec_idx]; 1197188Smcpowers p = (uint8_t *)iov->iov_base + offset; 1207188Smcpowers *out_data_1 = p; 1217188Smcpowers 1227188Smcpowers if (offset + amt <= iov->iov_len) { 1237188Smcpowers /* can fit one block into this iov */ 1247188Smcpowers *out_data_1_len = amt; 1257188Smcpowers *out_data_2 = NULL; 1267188Smcpowers *current_offset = offset + amt; 1277188Smcpowers } else { 1287188Smcpowers /* one block spans two iovecs */ 1297188Smcpowers *out_data_1_len = iov->iov_len - offset; 1307188Smcpowers if (vec_idx == uio->uio_iovcnt) 1317188Smcpowers return; 1327188Smcpowers vec_idx++; 1337188Smcpowers iov = &uio->uio_iov[vec_idx]; 1347188Smcpowers *out_data_2 = (uint8_t *)iov->iov_base; 1357188Smcpowers *current_offset = amt - *out_data_1_len; 1367188Smcpowers } 1377188Smcpowers *iov_or_mp = (void *)vec_idx; 1387188Smcpowers break; 1397188Smcpowers } 1407188Smcpowers 1417188Smcpowers case CRYPTO_DATA_MBLK: { 1427188Smcpowers mblk_t *mp; 1437188Smcpowers uint8_t *p; 1447188Smcpowers 1457188Smcpowers offset = *current_offset; 1467188Smcpowers mp = (mblk_t *)*iov_or_mp; 1477188Smcpowers p = mp->b_rptr + offset; 1487188Smcpowers *out_data_1 = p; 1497188Smcpowers if ((p + amt) <= mp->b_wptr) { 1507188Smcpowers /* can fit one block into this mblk */ 1517188Smcpowers *out_data_1_len = amt; 1527188Smcpowers *out_data_2 = NULL; 1537188Smcpowers *current_offset = offset + amt; 1547188Smcpowers } else { 1557188Smcpowers /* one block spans two mblks */ 156*10627Sopensolaris@drydog.com *out_data_1_len = _PTRDIFF(mp->b_wptr, p); 1577188Smcpowers if ((mp = mp->b_cont) == NULL) 1587188Smcpowers return; 1597188Smcpowers *out_data_2 = mp->b_rptr; 1607188Smcpowers *current_offset = (amt - *out_data_1_len); 1617188Smcpowers } 1627188Smcpowers *iov_or_mp = mp; 1637188Smcpowers break; 1647188Smcpowers } 1657188Smcpowers } /* end switch */ 1667188Smcpowers } 1677188Smcpowers 1687188Smcpowers void 1697188Smcpowers crypto_free_mode_ctx(void *ctx) 1707188Smcpowers { 1717188Smcpowers common_ctx_t *common_ctx = (common_ctx_t *)ctx; 1727188Smcpowers 1738005SMark.Powers@Sun.COM switch (common_ctx->cc_flags & 1749339SMark.Powers@Sun.COM (ECB_MODE|CBC_MODE|CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) { 1758005SMark.Powers@Sun.COM case ECB_MODE: 1767188Smcpowers #ifdef _KERNEL 1777188Smcpowers kmem_free(common_ctx, sizeof (ecb_ctx_t)); 1787188Smcpowers #else 1797188Smcpowers free(common_ctx); 1807188Smcpowers #endif 1818005SMark.Powers@Sun.COM break; 1828005SMark.Powers@Sun.COM 1838005SMark.Powers@Sun.COM case CBC_MODE: 1847188Smcpowers #ifdef _KERNEL 1857188Smcpowers kmem_free(common_ctx, sizeof (cbc_ctx_t)); 1867188Smcpowers #else 1877188Smcpowers free(common_ctx); 1887188Smcpowers #endif 1898005SMark.Powers@Sun.COM break; 1908005SMark.Powers@Sun.COM 1918005SMark.Powers@Sun.COM case CTR_MODE: 1927188Smcpowers #ifdef _KERNEL 1937188Smcpowers kmem_free(common_ctx, sizeof (ctr_ctx_t)); 1947188Smcpowers #else 1957188Smcpowers free(common_ctx); 1967188Smcpowers #endif 1978005SMark.Powers@Sun.COM break; 1988005SMark.Powers@Sun.COM 1998005SMark.Powers@Sun.COM case CCM_MODE: 2007188Smcpowers #ifdef _KERNEL 2017188Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 2027188Smcpowers kmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf, 2037188Smcpowers ((ccm_ctx_t *)ctx)->ccm_data_len); 2047188Smcpowers 2057188Smcpowers kmem_free(ctx, sizeof (ccm_ctx_t)); 2067188Smcpowers #else 2077188Smcpowers if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL) 2087188Smcpowers free(((ccm_ctx_t *)ctx)->ccm_pt_buf); 2097188Smcpowers free(ctx); 2107188Smcpowers #endif 2118005SMark.Powers@Sun.COM break; 2128005SMark.Powers@Sun.COM 2138005SMark.Powers@Sun.COM case GCM_MODE: 2149339SMark.Powers@Sun.COM case GMAC_MODE: 2158005SMark.Powers@Sun.COM #ifdef _KERNEL 2168005SMark.Powers@Sun.COM if (((gcm_ctx_t *)ctx)->gcm_pt_buf != NULL) 2178005SMark.Powers@Sun.COM kmem_free(((gcm_ctx_t *)ctx)->gcm_pt_buf, 2188005SMark.Powers@Sun.COM ((gcm_ctx_t *)ctx)->gcm_pt_buf_len); 2198005SMark.Powers@Sun.COM 2208005SMark.Powers@Sun.COM kmem_free(ctx, sizeof (gcm_ctx_t)); 2218005SMark.Powers@Sun.COM #else 2228005SMark.Powers@Sun.COM if (((gcm_ctx_t *)ctx)->gcm_pt_buf != NULL) 2238005SMark.Powers@Sun.COM free(((gcm_ctx_t *)ctx)->gcm_pt_buf); 2248005SMark.Powers@Sun.COM free(ctx); 2258005SMark.Powers@Sun.COM #endif 2267188Smcpowers } 2277188Smcpowers } 228