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 /* 22*95014fbbSDan OpenSolaris Anderson * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2323c57df7Smcpowers * Use is subject to license terms. 2423c57df7Smcpowers */ 2523c57df7Smcpowers 2623c57df7Smcpowers #include <sys/strsun.h> 2723c57df7Smcpowers #include <sys/systm.h> 2823c57df7Smcpowers #include <sys/sysmacros.h> 2923c57df7Smcpowers #include <sys/kmem.h> 3023c57df7Smcpowers #include <sys/md5.h> 3123c57df7Smcpowers #include <sys/sha1.h> 3223c57df7Smcpowers #include <sys/sha2.h> 3323c57df7Smcpowers #include <modes/modes.h> 3423c57df7Smcpowers #include <sys/crypto/common.h> 3523c57df7Smcpowers #include <sys/crypto/impl.h> 3623c57df7Smcpowers 3723c57df7Smcpowers /* 3823c57df7Smcpowers * Utility routine to apply the command, 'cmd', to the 3923c57df7Smcpowers * data in the uio structure. 4023c57df7Smcpowers */ 4123c57df7Smcpowers int 4223c57df7Smcpowers crypto_uio_data(crypto_data_t *data, uchar_t *buf, int len, cmd_type_t cmd, 4323c57df7Smcpowers void *digest_ctx, void (*update)()) 4423c57df7Smcpowers { 4523c57df7Smcpowers uio_t *uiop = data->cd_uio; 4623c57df7Smcpowers off_t offset = data->cd_offset; 4723c57df7Smcpowers size_t length = len; 4823c57df7Smcpowers uint_t vec_idx; 4923c57df7Smcpowers size_t cur_len; 5023c57df7Smcpowers uchar_t *datap; 5123c57df7Smcpowers 5223c57df7Smcpowers ASSERT(data->cd_format == CRYPTO_DATA_UIO); 5323c57df7Smcpowers if (uiop->uio_segflg != UIO_SYSSPACE) { 5423c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 5523c57df7Smcpowers } 5623c57df7Smcpowers 5723c57df7Smcpowers /* 5823c57df7Smcpowers * Jump to the first iovec containing data to be 5923c57df7Smcpowers * processed. 6023c57df7Smcpowers */ 6123c57df7Smcpowers for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 6223c57df7Smcpowers offset >= uiop->uio_iov[vec_idx].iov_len; 6323c57df7Smcpowers offset -= uiop->uio_iov[vec_idx++].iov_len) 6423c57df7Smcpowers ; 6523c57df7Smcpowers 6623c57df7Smcpowers if (vec_idx == uiop->uio_iovcnt) { 6723c57df7Smcpowers /* 6823c57df7Smcpowers * The caller specified an offset that is larger than 6923c57df7Smcpowers * the total size of the buffers it provided. 7023c57df7Smcpowers */ 7123c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 7223c57df7Smcpowers } 7323c57df7Smcpowers 7423c57df7Smcpowers while (vec_idx < uiop->uio_iovcnt && length > 0) { 7523c57df7Smcpowers cur_len = MIN(uiop->uio_iov[vec_idx].iov_len - 7623c57df7Smcpowers offset, length); 7723c57df7Smcpowers 7823c57df7Smcpowers datap = (uchar_t *)(uiop->uio_iov[vec_idx].iov_base + 7923c57df7Smcpowers offset); 8023c57df7Smcpowers switch (cmd) { 8123c57df7Smcpowers case COPY_FROM_DATA: 8223c57df7Smcpowers bcopy(datap, buf, cur_len); 8323c57df7Smcpowers buf += cur_len; 8423c57df7Smcpowers break; 8523c57df7Smcpowers case COPY_TO_DATA: 8623c57df7Smcpowers bcopy(buf, datap, cur_len); 8723c57df7Smcpowers buf += cur_len; 8823c57df7Smcpowers break; 8923c57df7Smcpowers case COMPARE_TO_DATA: 9023c57df7Smcpowers if (bcmp(datap, buf, cur_len)) 9123c57df7Smcpowers return (CRYPTO_SIGNATURE_INVALID); 9223c57df7Smcpowers buf += cur_len; 9323c57df7Smcpowers break; 9423c57df7Smcpowers case MD5_DIGEST_DATA: 9523c57df7Smcpowers case SHA1_DIGEST_DATA: 9623c57df7Smcpowers case SHA2_DIGEST_DATA: 97e8c016efSMark Powers case GHASH_DATA: 9823c57df7Smcpowers update(digest_ctx, datap, cur_len); 9923c57df7Smcpowers break; 10023c57df7Smcpowers } 10123c57df7Smcpowers 10223c57df7Smcpowers length -= cur_len; 10323c57df7Smcpowers vec_idx++; 10423c57df7Smcpowers offset = 0; 10523c57df7Smcpowers } 10623c57df7Smcpowers 10723c57df7Smcpowers if (vec_idx == uiop->uio_iovcnt && length > 0) { 10823c57df7Smcpowers /* 10923c57df7Smcpowers * The end of the specified iovec's was reached but 11023c57df7Smcpowers * the length requested could not be processed. 11123c57df7Smcpowers */ 11223c57df7Smcpowers switch (cmd) { 11323c57df7Smcpowers case COPY_TO_DATA: 11423c57df7Smcpowers data->cd_length = len; 11523c57df7Smcpowers return (CRYPTO_BUFFER_TOO_SMALL); 11623c57df7Smcpowers default: 11723c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 11823c57df7Smcpowers } 11923c57df7Smcpowers } 12023c57df7Smcpowers 12123c57df7Smcpowers return (CRYPTO_SUCCESS); 12223c57df7Smcpowers } 12323c57df7Smcpowers 12423c57df7Smcpowers /* 12523c57df7Smcpowers * Utility routine to apply the command, 'cmd', to the 12623c57df7Smcpowers * data in the mblk structure. 12723c57df7Smcpowers */ 12823c57df7Smcpowers int 12923c57df7Smcpowers crypto_mblk_data(crypto_data_t *data, uchar_t *buf, int len, cmd_type_t cmd, 13023c57df7Smcpowers void *digest_ctx, void (*update)()) 13123c57df7Smcpowers { 13223c57df7Smcpowers off_t offset = data->cd_offset; 13323c57df7Smcpowers size_t length = len; 13423c57df7Smcpowers mblk_t *mp; 13523c57df7Smcpowers size_t cur_len; 13623c57df7Smcpowers uchar_t *datap; 13723c57df7Smcpowers 13823c57df7Smcpowers ASSERT(data->cd_format == CRYPTO_DATA_MBLK); 13923c57df7Smcpowers /* 14023c57df7Smcpowers * Jump to the first mblk_t containing data to be processed. 14123c57df7Smcpowers */ 14223c57df7Smcpowers for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 14323c57df7Smcpowers offset -= MBLKL(mp), mp = mp->b_cont) 14423c57df7Smcpowers ; 14523c57df7Smcpowers if (mp == NULL) { 14623c57df7Smcpowers /* 14723c57df7Smcpowers * The caller specified an offset that is larger 14823c57df7Smcpowers * than the total size of the buffers it provided. 14923c57df7Smcpowers */ 15023c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 15123c57df7Smcpowers } 15223c57df7Smcpowers 15323c57df7Smcpowers /* 15423c57df7Smcpowers * Now do the processing on the mblk chain. 15523c57df7Smcpowers */ 15623c57df7Smcpowers while (mp != NULL && length > 0) { 15723c57df7Smcpowers cur_len = MIN(MBLKL(mp) - offset, length); 15823c57df7Smcpowers 15923c57df7Smcpowers datap = (uchar_t *)(mp->b_rptr + offset); 16023c57df7Smcpowers switch (cmd) { 16123c57df7Smcpowers case COPY_FROM_DATA: 16223c57df7Smcpowers bcopy(datap, buf, cur_len); 16323c57df7Smcpowers buf += cur_len; 16423c57df7Smcpowers break; 16523c57df7Smcpowers case COPY_TO_DATA: 16623c57df7Smcpowers bcopy(buf, datap, cur_len); 16723c57df7Smcpowers buf += cur_len; 16823c57df7Smcpowers break; 16923c57df7Smcpowers case COMPARE_TO_DATA: 17023c57df7Smcpowers if (bcmp(datap, buf, cur_len)) 17123c57df7Smcpowers return (CRYPTO_SIGNATURE_INVALID); 17223c57df7Smcpowers buf += cur_len; 17323c57df7Smcpowers break; 17423c57df7Smcpowers case MD5_DIGEST_DATA: 17523c57df7Smcpowers case SHA1_DIGEST_DATA: 17623c57df7Smcpowers case SHA2_DIGEST_DATA: 177e8c016efSMark Powers case GHASH_DATA: 17823c57df7Smcpowers update(digest_ctx, datap, cur_len); 17923c57df7Smcpowers break; 18023c57df7Smcpowers } 18123c57df7Smcpowers 18223c57df7Smcpowers length -= cur_len; 18323c57df7Smcpowers offset = 0; 18423c57df7Smcpowers mp = mp->b_cont; 18523c57df7Smcpowers } 18623c57df7Smcpowers 18723c57df7Smcpowers if (mp == NULL && length > 0) { 18823c57df7Smcpowers /* 18923c57df7Smcpowers * The end of the mblk was reached but the length 19023c57df7Smcpowers * requested could not be processed. 19123c57df7Smcpowers */ 19223c57df7Smcpowers switch (cmd) { 19323c57df7Smcpowers case COPY_TO_DATA: 19423c57df7Smcpowers data->cd_length = len; 19523c57df7Smcpowers return (CRYPTO_BUFFER_TOO_SMALL); 19623c57df7Smcpowers default: 19723c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 19823c57df7Smcpowers } 19923c57df7Smcpowers } 20023c57df7Smcpowers 20123c57df7Smcpowers return (CRYPTO_SUCCESS); 20223c57df7Smcpowers } 20323c57df7Smcpowers 20423c57df7Smcpowers /* 20523c57df7Smcpowers * Utility routine to copy a buffer to a crypto_data structure. 20623c57df7Smcpowers */ 20723c57df7Smcpowers int 20823c57df7Smcpowers crypto_put_output_data(uchar_t *buf, crypto_data_t *output, int len) 20923c57df7Smcpowers { 21023c57df7Smcpowers switch (output->cd_format) { 21123c57df7Smcpowers case CRYPTO_DATA_RAW: 21223c57df7Smcpowers if (output->cd_raw.iov_len < len) { 21323c57df7Smcpowers output->cd_length = len; 21423c57df7Smcpowers return (CRYPTO_BUFFER_TOO_SMALL); 21523c57df7Smcpowers } 21623c57df7Smcpowers bcopy(buf, (uchar_t *)(output->cd_raw.iov_base + 21723c57df7Smcpowers output->cd_offset), len); 21823c57df7Smcpowers break; 21923c57df7Smcpowers 22023c57df7Smcpowers case CRYPTO_DATA_UIO: 22123c57df7Smcpowers return (crypto_uio_data(output, buf, len, 22223c57df7Smcpowers COPY_TO_DATA, NULL, NULL)); 22323c57df7Smcpowers 22423c57df7Smcpowers case CRYPTO_DATA_MBLK: 22523c57df7Smcpowers return (crypto_mblk_data(output, buf, len, 22623c57df7Smcpowers COPY_TO_DATA, NULL, NULL)); 22723c57df7Smcpowers 22823c57df7Smcpowers default: 22923c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 23023c57df7Smcpowers } 23123c57df7Smcpowers 23223c57df7Smcpowers return (CRYPTO_SUCCESS); 23323c57df7Smcpowers } 23423c57df7Smcpowers 23523c57df7Smcpowers /* 23623c57df7Smcpowers * Utility routine to get data from a crypto_data structure. 23723c57df7Smcpowers * 23823c57df7Smcpowers * '*dptr' contains a pointer to a buffer on return. 'buf' 23923c57df7Smcpowers * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case. 24023c57df7Smcpowers */ 24123c57df7Smcpowers int 24223c57df7Smcpowers crypto_get_input_data(crypto_data_t *input, uchar_t **dptr, uchar_t *buf) 24323c57df7Smcpowers { 24423c57df7Smcpowers int rv; 24523c57df7Smcpowers 24623c57df7Smcpowers switch (input->cd_format) { 24723c57df7Smcpowers case CRYPTO_DATA_RAW: 24823c57df7Smcpowers if (input->cd_raw.iov_len < input->cd_length) 24923c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 25023c57df7Smcpowers *dptr = (uchar_t *)(input->cd_raw.iov_base + 25123c57df7Smcpowers input->cd_offset); 25223c57df7Smcpowers break; 25323c57df7Smcpowers 25423c57df7Smcpowers case CRYPTO_DATA_UIO: 25523c57df7Smcpowers if ((rv = crypto_uio_data(input, buf, input->cd_length, 25623c57df7Smcpowers COPY_FROM_DATA, NULL, NULL)) != CRYPTO_SUCCESS) 25723c57df7Smcpowers return (rv); 25823c57df7Smcpowers *dptr = buf; 25923c57df7Smcpowers break; 26023c57df7Smcpowers 26123c57df7Smcpowers case CRYPTO_DATA_MBLK: 26223c57df7Smcpowers if ((rv = crypto_mblk_data(input, buf, input->cd_length, 26323c57df7Smcpowers COPY_FROM_DATA, NULL, NULL)) != CRYPTO_SUCCESS) 26423c57df7Smcpowers return (rv); 26523c57df7Smcpowers *dptr = buf; 26623c57df7Smcpowers break; 26723c57df7Smcpowers 26823c57df7Smcpowers default: 26923c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 27023c57df7Smcpowers } 27123c57df7Smcpowers 27223c57df7Smcpowers return (CRYPTO_SUCCESS); 27323c57df7Smcpowers } 27423c57df7Smcpowers 27523c57df7Smcpowers int 27623c57df7Smcpowers crypto_copy_key_to_ctx(crypto_key_t *in_key, crypto_key_t **out_key, 27723c57df7Smcpowers size_t *out_size, int kmflag) 27823c57df7Smcpowers { 27923c57df7Smcpowers int i, count; 28023c57df7Smcpowers size_t len; 28123c57df7Smcpowers caddr_t attr_val; 28223c57df7Smcpowers crypto_object_attribute_t *k_attrs = NULL; 28323c57df7Smcpowers crypto_key_t *key; 28423c57df7Smcpowers 28523c57df7Smcpowers ASSERT(in_key->ck_format == CRYPTO_KEY_ATTR_LIST); 28623c57df7Smcpowers 28723c57df7Smcpowers count = in_key->ck_count; 28823c57df7Smcpowers /* figure out how much memory to allocate for everything */ 28923c57df7Smcpowers len = sizeof (crypto_key_t) + 29023c57df7Smcpowers count * sizeof (crypto_object_attribute_t); 29123c57df7Smcpowers for (i = 0; i < count; i++) { 29223c57df7Smcpowers len += roundup(in_key->ck_attrs[i].oa_value_len, 29323c57df7Smcpowers sizeof (caddr_t)); 29423c57df7Smcpowers } 29523c57df7Smcpowers 29623c57df7Smcpowers /* one big allocation for everything */ 29723c57df7Smcpowers key = kmem_alloc(len, kmflag); 29823c57df7Smcpowers if (key == NULL) 29923c57df7Smcpowers return (CRYPTO_HOST_MEMORY); 300*95014fbbSDan OpenSolaris Anderson k_attrs = (crypto_object_attribute_t *)(void *)((caddr_t)key + 30123c57df7Smcpowers sizeof (crypto_key_t)); 30223c57df7Smcpowers 30323c57df7Smcpowers attr_val = (caddr_t)k_attrs + 30423c57df7Smcpowers count * sizeof (crypto_object_attribute_t); 30523c57df7Smcpowers for (i = 0; i < count; i++) { 30623c57df7Smcpowers k_attrs[i].oa_type = in_key->ck_attrs[i].oa_type; 30723c57df7Smcpowers bcopy(in_key->ck_attrs[i].oa_value, attr_val, 30823c57df7Smcpowers in_key->ck_attrs[i].oa_value_len); 30923c57df7Smcpowers k_attrs[i].oa_value = attr_val; 31023c57df7Smcpowers k_attrs[i].oa_value_len = in_key->ck_attrs[i].oa_value_len; 31123c57df7Smcpowers attr_val += roundup(k_attrs[i].oa_value_len, sizeof (caddr_t)); 31223c57df7Smcpowers } 31323c57df7Smcpowers 31423c57df7Smcpowers key->ck_format = CRYPTO_KEY_ATTR_LIST; 31523c57df7Smcpowers key->ck_count = count; 31623c57df7Smcpowers key->ck_attrs = k_attrs; 31723c57df7Smcpowers *out_key = key; 31823c57df7Smcpowers *out_size = len; /* save the size to be freed */ 31923c57df7Smcpowers 32023c57df7Smcpowers return (CRYPTO_SUCCESS); 32123c57df7Smcpowers } 32223c57df7Smcpowers 32323c57df7Smcpowers int 32423c57df7Smcpowers crypto_digest_data(crypto_data_t *data, void *dctx, uchar_t *digest, 32523c57df7Smcpowers void (*update)(), void (*final)(), uchar_t flag) 32623c57df7Smcpowers { 32723c57df7Smcpowers int rv, dlen; 32823c57df7Smcpowers uchar_t *dptr; 32923c57df7Smcpowers 33023c57df7Smcpowers ASSERT(flag & CRYPTO_DO_MD5 || flag & CRYPTO_DO_SHA1 || 33123c57df7Smcpowers flag & CRYPTO_DO_SHA2); 33223c57df7Smcpowers if (data == NULL) { 33323c57df7Smcpowers ASSERT((flag & CRYPTO_DO_UPDATE) == 0); 33423c57df7Smcpowers goto dofinal; 33523c57df7Smcpowers } 33623c57df7Smcpowers 33723c57df7Smcpowers dlen = data->cd_length; 33823c57df7Smcpowers 33923c57df7Smcpowers if (flag & CRYPTO_DO_UPDATE) { 34023c57df7Smcpowers 34123c57df7Smcpowers switch (data->cd_format) { 34223c57df7Smcpowers case CRYPTO_DATA_RAW: 34323c57df7Smcpowers dptr = (uchar_t *)(data->cd_raw.iov_base + 34423c57df7Smcpowers data->cd_offset); 34523c57df7Smcpowers 34623c57df7Smcpowers update(dctx, dptr, dlen); 34723c57df7Smcpowers 34823c57df7Smcpowers break; 34923c57df7Smcpowers 35023c57df7Smcpowers case CRYPTO_DATA_UIO: 35123c57df7Smcpowers if (flag & CRYPTO_DO_MD5) 35223c57df7Smcpowers rv = crypto_uio_data(data, NULL, dlen, 35323c57df7Smcpowers MD5_DIGEST_DATA, dctx, update); 35423c57df7Smcpowers 35523c57df7Smcpowers else if (flag & CRYPTO_DO_SHA1) 35623c57df7Smcpowers rv = crypto_uio_data(data, NULL, dlen, 35723c57df7Smcpowers SHA1_DIGEST_DATA, dctx, update); 35823c57df7Smcpowers 35923c57df7Smcpowers else 36023c57df7Smcpowers rv = crypto_uio_data(data, NULL, dlen, 36123c57df7Smcpowers SHA2_DIGEST_DATA, dctx, update); 36223c57df7Smcpowers 36323c57df7Smcpowers if (rv != CRYPTO_SUCCESS) 36423c57df7Smcpowers return (rv); 36523c57df7Smcpowers 36623c57df7Smcpowers break; 36723c57df7Smcpowers 36823c57df7Smcpowers case CRYPTO_DATA_MBLK: 36923c57df7Smcpowers if (flag & CRYPTO_DO_MD5) 37023c57df7Smcpowers rv = crypto_mblk_data(data, NULL, dlen, 37123c57df7Smcpowers MD5_DIGEST_DATA, dctx, update); 37223c57df7Smcpowers 37323c57df7Smcpowers else if (flag & CRYPTO_DO_SHA1) 37423c57df7Smcpowers rv = crypto_mblk_data(data, NULL, dlen, 37523c57df7Smcpowers SHA1_DIGEST_DATA, dctx, update); 37623c57df7Smcpowers 37723c57df7Smcpowers else 37823c57df7Smcpowers rv = crypto_mblk_data(data, NULL, dlen, 37923c57df7Smcpowers SHA2_DIGEST_DATA, dctx, update); 38023c57df7Smcpowers 38123c57df7Smcpowers if (rv != CRYPTO_SUCCESS) 38223c57df7Smcpowers return (rv); 38323c57df7Smcpowers 38423c57df7Smcpowers break; 38523c57df7Smcpowers } 38623c57df7Smcpowers } 38723c57df7Smcpowers 38823c57df7Smcpowers dofinal: 38923c57df7Smcpowers if (flag & CRYPTO_DO_FINAL) { 39023c57df7Smcpowers final(digest, dctx); 39123c57df7Smcpowers } 39223c57df7Smcpowers 39323c57df7Smcpowers return (CRYPTO_SUCCESS); 39423c57df7Smcpowers } 39523c57df7Smcpowers 39623c57df7Smcpowers int 39723c57df7Smcpowers crypto_update_iov(void *ctx, crypto_data_t *input, crypto_data_t *output, 39823c57df7Smcpowers int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), 39923c57df7Smcpowers void (*copy_block)(uint8_t *, uint64_t *)) 40023c57df7Smcpowers { 40123c57df7Smcpowers common_ctx_t *common_ctx = ctx; 40223c57df7Smcpowers int rv; 40323c57df7Smcpowers 40423c57df7Smcpowers if (input->cd_miscdata != NULL) { 40523c57df7Smcpowers copy_block((uint8_t *)input->cd_miscdata, 40623c57df7Smcpowers &common_ctx->cc_iv[0]); 40723c57df7Smcpowers } 40823c57df7Smcpowers 40923c57df7Smcpowers if (input->cd_raw.iov_len < input->cd_length) 41023c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 41123c57df7Smcpowers 41223c57df7Smcpowers rv = (cipher)(ctx, input->cd_raw.iov_base + input->cd_offset, 41323c57df7Smcpowers input->cd_length, (input == output) ? NULL : output); 41423c57df7Smcpowers 41523c57df7Smcpowers return (rv); 41623c57df7Smcpowers } 41723c57df7Smcpowers 41823c57df7Smcpowers int 41923c57df7Smcpowers crypto_update_uio(void *ctx, crypto_data_t *input, crypto_data_t *output, 42023c57df7Smcpowers int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), 42123c57df7Smcpowers void (*copy_block)(uint8_t *, uint64_t *)) 42223c57df7Smcpowers { 42323c57df7Smcpowers common_ctx_t *common_ctx = ctx; 42423c57df7Smcpowers uio_t *uiop = input->cd_uio; 42523c57df7Smcpowers off_t offset = input->cd_offset; 42623c57df7Smcpowers size_t length = input->cd_length; 42723c57df7Smcpowers uint_t vec_idx; 42823c57df7Smcpowers size_t cur_len; 42923c57df7Smcpowers 43023c57df7Smcpowers if (input->cd_miscdata != NULL) { 43123c57df7Smcpowers copy_block((uint8_t *)input->cd_miscdata, 43223c57df7Smcpowers &common_ctx->cc_iv[0]); 43323c57df7Smcpowers } 43423c57df7Smcpowers 43523c57df7Smcpowers if (input->cd_uio->uio_segflg != UIO_SYSSPACE) { 43623c57df7Smcpowers return (CRYPTO_ARGUMENTS_BAD); 43723c57df7Smcpowers } 43823c57df7Smcpowers 43923c57df7Smcpowers /* 44023c57df7Smcpowers * Jump to the first iovec containing data to be 44123c57df7Smcpowers * processed. 44223c57df7Smcpowers */ 44323c57df7Smcpowers for (vec_idx = 0; vec_idx < uiop->uio_iovcnt && 44423c57df7Smcpowers offset >= uiop->uio_iov[vec_idx].iov_len; 44523c57df7Smcpowers offset -= uiop->uio_iov[vec_idx++].iov_len) 44623c57df7Smcpowers ; 44723c57df7Smcpowers if (vec_idx == uiop->uio_iovcnt) { 44823c57df7Smcpowers /* 44923c57df7Smcpowers * The caller specified an offset that is larger than the 45023c57df7Smcpowers * total size of the buffers it provided. 45123c57df7Smcpowers */ 45223c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 45323c57df7Smcpowers } 45423c57df7Smcpowers 45523c57df7Smcpowers /* 45623c57df7Smcpowers * Now process the iovecs. 45723c57df7Smcpowers */ 45823c57df7Smcpowers while (vec_idx < uiop->uio_iovcnt && length > 0) { 45923c57df7Smcpowers cur_len = MIN(uiop->uio_iov[vec_idx].iov_len - 46023c57df7Smcpowers offset, length); 46123c57df7Smcpowers 46223c57df7Smcpowers (cipher)(ctx, uiop->uio_iov[vec_idx].iov_base + offset, 46323c57df7Smcpowers cur_len, (input == output) ? NULL : output); 46423c57df7Smcpowers 46523c57df7Smcpowers length -= cur_len; 46623c57df7Smcpowers vec_idx++; 46723c57df7Smcpowers offset = 0; 46823c57df7Smcpowers } 46923c57df7Smcpowers 47023c57df7Smcpowers if (vec_idx == uiop->uio_iovcnt && length > 0) { 47123c57df7Smcpowers /* 47223c57df7Smcpowers * The end of the specified iovec's was reached but 47323c57df7Smcpowers * the length requested could not be processed, i.e. 47423c57df7Smcpowers * The caller requested to digest more data than it provided. 47523c57df7Smcpowers */ 47623c57df7Smcpowers 47723c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 47823c57df7Smcpowers } 47923c57df7Smcpowers 48023c57df7Smcpowers return (CRYPTO_SUCCESS); 48123c57df7Smcpowers } 48223c57df7Smcpowers 48323c57df7Smcpowers int 48423c57df7Smcpowers crypto_update_mp(void *ctx, crypto_data_t *input, crypto_data_t *output, 48523c57df7Smcpowers int (*cipher)(void *, caddr_t, size_t, crypto_data_t *), 48623c57df7Smcpowers void (*copy_block)(uint8_t *, uint64_t *)) 48723c57df7Smcpowers { 48823c57df7Smcpowers common_ctx_t *common_ctx = ctx; 48923c57df7Smcpowers off_t offset = input->cd_offset; 49023c57df7Smcpowers size_t length = input->cd_length; 49123c57df7Smcpowers mblk_t *mp; 49223c57df7Smcpowers size_t cur_len; 49323c57df7Smcpowers 49423c57df7Smcpowers if (input->cd_miscdata != NULL) { 49523c57df7Smcpowers copy_block((uint8_t *)input->cd_miscdata, 49623c57df7Smcpowers &common_ctx->cc_iv[0]); 49723c57df7Smcpowers } 49823c57df7Smcpowers 49923c57df7Smcpowers /* 50023c57df7Smcpowers * Jump to the first mblk_t containing data to be processed. 50123c57df7Smcpowers */ 50223c57df7Smcpowers for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp); 50323c57df7Smcpowers offset -= MBLKL(mp), mp = mp->b_cont) 50423c57df7Smcpowers ; 50523c57df7Smcpowers if (mp == NULL) { 50623c57df7Smcpowers /* 50723c57df7Smcpowers * The caller specified an offset that is larger than the 50823c57df7Smcpowers * total size of the buffers it provided. 50923c57df7Smcpowers */ 51023c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 51123c57df7Smcpowers } 51223c57df7Smcpowers 51323c57df7Smcpowers /* 51423c57df7Smcpowers * Now do the processing on the mblk chain. 51523c57df7Smcpowers */ 51623c57df7Smcpowers while (mp != NULL && length > 0) { 51723c57df7Smcpowers cur_len = MIN(MBLKL(mp) - offset, length); 51823c57df7Smcpowers (cipher)(ctx, (char *)(mp->b_rptr + offset), cur_len, 51923c57df7Smcpowers (input == output) ? NULL : output); 52023c57df7Smcpowers 52123c57df7Smcpowers length -= cur_len; 52223c57df7Smcpowers offset = 0; 52323c57df7Smcpowers mp = mp->b_cont; 52423c57df7Smcpowers } 52523c57df7Smcpowers 52623c57df7Smcpowers if (mp == NULL && length > 0) { 52723c57df7Smcpowers /* 52823c57df7Smcpowers * The end of the mblk was reached but the length requested 52923c57df7Smcpowers * could not be processed, i.e. The caller requested 53023c57df7Smcpowers * to digest more data than it provided. 53123c57df7Smcpowers */ 53223c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 53323c57df7Smcpowers } 53423c57df7Smcpowers 53523c57df7Smcpowers return (CRYPTO_SUCCESS); 53623c57df7Smcpowers } 53723c57df7Smcpowers 53823c57df7Smcpowers /* 53923c57df7Smcpowers * Utility routine to look up a attribute of type, 'type', 54023c57df7Smcpowers * in the key. 54123c57df7Smcpowers */ 54223c57df7Smcpowers int 54323c57df7Smcpowers crypto_get_key_attr(crypto_key_t *key, crypto_attr_type_t type, 54423c57df7Smcpowers uchar_t **value, ssize_t *value_len) 54523c57df7Smcpowers { 54623c57df7Smcpowers int i; 54723c57df7Smcpowers 54823c57df7Smcpowers ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST); 54923c57df7Smcpowers for (i = 0; i < key->ck_count; i++) { 55023c57df7Smcpowers if (key->ck_attrs[i].oa_type == type) { 55123c57df7Smcpowers *value = (uchar_t *)key->ck_attrs[i].oa_value; 55223c57df7Smcpowers *value_len = key->ck_attrs[i].oa_value_len; 55323c57df7Smcpowers return (CRYPTO_SUCCESS); 55423c57df7Smcpowers } 55523c57df7Smcpowers } 55623c57df7Smcpowers 55723c57df7Smcpowers return (CRYPTO_FAILED); 55823c57df7Smcpowers } 559