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 <strings.h> 2823c57df7Smcpowers #include <limits.h> 2923c57df7Smcpowers #include <assert.h> 3023c57df7Smcpowers #include <security/cryptoki.h> 3123c57df7Smcpowers #endif 3223c57df7Smcpowers 3323c57df7Smcpowers #include <sys/types.h> 3423c57df7Smcpowers #include <modes/modes.h> 3523c57df7Smcpowers #include <sys/crypto/common.h> 3623c57df7Smcpowers #include <sys/crypto/impl.h> 3723c57df7Smcpowers 3823c57df7Smcpowers /* 3923c57df7Smcpowers * Algorithm independent ECB functions. 4023c57df7Smcpowers */ 4123c57df7Smcpowers int 4223c57df7Smcpowers ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length, 4323c57df7Smcpowers crypto_data_t *out, size_t block_size, 4423c57df7Smcpowers int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct)) 4523c57df7Smcpowers { 4623c57df7Smcpowers size_t remainder = length; 4723c57df7Smcpowers size_t need; 4823c57df7Smcpowers uint8_t *datap = (uint8_t *)data; 4923c57df7Smcpowers uint8_t *blockp; 5023c57df7Smcpowers uint8_t *lastp; 5123c57df7Smcpowers void *iov_or_mp; 5223c57df7Smcpowers offset_t offset; 5323c57df7Smcpowers uint8_t *out_data_1; 5423c57df7Smcpowers uint8_t *out_data_2; 5523c57df7Smcpowers size_t out_data_1_len; 5623c57df7Smcpowers 57*16239bc8SMark Powers if (length + ctx->ecb_remainder_len < block_size) { 5823c57df7Smcpowers /* accumulate bytes here and return */ 5923c57df7Smcpowers bcopy(datap, 60*16239bc8SMark Powers (uint8_t *)ctx->ecb_remainder + ctx->ecb_remainder_len, 6123c57df7Smcpowers length); 62*16239bc8SMark Powers ctx->ecb_remainder_len += length; 63*16239bc8SMark Powers ctx->ecb_copy_to = datap; 6423c57df7Smcpowers return (CRYPTO_SUCCESS); 6523c57df7Smcpowers } 6623c57df7Smcpowers 67*16239bc8SMark Powers lastp = (uint8_t *)ctx->ecb_iv; 6823c57df7Smcpowers if (out != NULL) 6923c57df7Smcpowers crypto_init_ptrs(out, &iov_or_mp, &offset); 7023c57df7Smcpowers 7123c57df7Smcpowers do { 7223c57df7Smcpowers /* Unprocessed data from last call. */ 73*16239bc8SMark Powers if (ctx->ecb_remainder_len > 0) { 74*16239bc8SMark Powers need = block_size - ctx->ecb_remainder_len; 7523c57df7Smcpowers 7623c57df7Smcpowers if (need > remainder) 7723c57df7Smcpowers return (CRYPTO_DATA_LEN_RANGE); 7823c57df7Smcpowers 79*16239bc8SMark Powers bcopy(datap, &((uint8_t *)ctx->ecb_remainder) 80*16239bc8SMark Powers [ctx->ecb_remainder_len], need); 8123c57df7Smcpowers 82*16239bc8SMark Powers blockp = (uint8_t *)ctx->ecb_remainder; 8323c57df7Smcpowers } else { 8423c57df7Smcpowers blockp = datap; 8523c57df7Smcpowers } 8623c57df7Smcpowers 8723c57df7Smcpowers if (out == NULL) { 88*16239bc8SMark Powers cipher(ctx->ecb_keysched, blockp, blockp); 8923c57df7Smcpowers 90*16239bc8SMark Powers ctx->ecb_lastp = blockp; 9123c57df7Smcpowers lastp = blockp; 9223c57df7Smcpowers 93*16239bc8SMark Powers if (ctx->ecb_remainder_len > 0) { 94*16239bc8SMark Powers bcopy(blockp, ctx->ecb_copy_to, 95*16239bc8SMark Powers ctx->ecb_remainder_len); 96*16239bc8SMark Powers bcopy(blockp + ctx->ecb_remainder_len, datap, 9723c57df7Smcpowers need); 9823c57df7Smcpowers } 9923c57df7Smcpowers } else { 100*16239bc8SMark Powers cipher(ctx->ecb_keysched, blockp, lastp); 10123c57df7Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 10223c57df7Smcpowers &out_data_1_len, &out_data_2, block_size); 10323c57df7Smcpowers 10423c57df7Smcpowers /* copy block to where it belongs */ 10523c57df7Smcpowers bcopy(lastp, out_data_1, out_data_1_len); 10623c57df7Smcpowers if (out_data_2 != NULL) { 10723c57df7Smcpowers bcopy(lastp + out_data_1_len, out_data_2, 10823c57df7Smcpowers block_size - out_data_1_len); 10923c57df7Smcpowers } 11023c57df7Smcpowers /* update offset */ 11123c57df7Smcpowers out->cd_offset += block_size; 11223c57df7Smcpowers } 11323c57df7Smcpowers 11423c57df7Smcpowers /* Update pointer to next block of data to be processed. */ 115*16239bc8SMark Powers if (ctx->ecb_remainder_len != 0) { 11623c57df7Smcpowers datap += need; 117*16239bc8SMark Powers ctx->ecb_remainder_len = 0; 11823c57df7Smcpowers } else { 11923c57df7Smcpowers datap += block_size; 12023c57df7Smcpowers } 12123c57df7Smcpowers 12223c57df7Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 12323c57df7Smcpowers 12423c57df7Smcpowers /* Incomplete last block. */ 12523c57df7Smcpowers if (remainder > 0 && remainder < block_size) { 126*16239bc8SMark Powers bcopy(datap, ctx->ecb_remainder, remainder); 127*16239bc8SMark Powers ctx->ecb_remainder_len = remainder; 128*16239bc8SMark Powers ctx->ecb_copy_to = datap; 12923c57df7Smcpowers goto out; 13023c57df7Smcpowers } 131*16239bc8SMark Powers ctx->ecb_copy_to = NULL; 13223c57df7Smcpowers 13323c57df7Smcpowers } while (remainder > 0); 13423c57df7Smcpowers 13523c57df7Smcpowers out: 13623c57df7Smcpowers return (CRYPTO_SUCCESS); 13723c57df7Smcpowers } 13823c57df7Smcpowers 13923c57df7Smcpowers /* ARGSUSED */ 14023c57df7Smcpowers void * 14123c57df7Smcpowers ecb_alloc_ctx(int kmflag) 14223c57df7Smcpowers { 14323c57df7Smcpowers ecb_ctx_t *ecb_ctx; 14423c57df7Smcpowers 14523c57df7Smcpowers #ifdef _KERNEL 14623c57df7Smcpowers if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL) 14723c57df7Smcpowers #else 14823c57df7Smcpowers if ((ecb_ctx = calloc(1, sizeof (ecb_ctx_t))) == NULL) 14923c57df7Smcpowers #endif 15023c57df7Smcpowers return (NULL); 15123c57df7Smcpowers 152*16239bc8SMark Powers ecb_ctx->ecb_flags = ECB_MODE; 15323c57df7Smcpowers return (ecb_ctx); 15423c57df7Smcpowers } 155