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 /* 227188Smcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237188Smcpowers * Use is subject to license terms. 247188Smcpowers */ 257188Smcpowers 267188Smcpowers #ifndef _KERNEL 277188Smcpowers #include <strings.h> 287188Smcpowers #include <limits.h> 297188Smcpowers #include <assert.h> 307188Smcpowers #include <security/cryptoki.h> 317188Smcpowers #endif 327188Smcpowers 337188Smcpowers #include <sys/types.h> 347188Smcpowers #include <modes/modes.h> 357188Smcpowers #include <sys/crypto/common.h> 367188Smcpowers #include <sys/crypto/impl.h> 377188Smcpowers 387188Smcpowers /* 397188Smcpowers * Algorithm independent ECB functions. 407188Smcpowers */ 417188Smcpowers int 427188Smcpowers ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length, 437188Smcpowers crypto_data_t *out, size_t block_size, 447188Smcpowers int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct)) 457188Smcpowers { 467188Smcpowers size_t remainder = length; 477188Smcpowers size_t need; 487188Smcpowers uint8_t *datap = (uint8_t *)data; 497188Smcpowers uint8_t *blockp; 507188Smcpowers uint8_t *lastp; 517188Smcpowers void *iov_or_mp; 527188Smcpowers offset_t offset; 537188Smcpowers uint8_t *out_data_1; 547188Smcpowers uint8_t *out_data_2; 557188Smcpowers size_t out_data_1_len; 567188Smcpowers 57*7581SMark.Powers@Sun.COM if (length + ctx->ecb_remainder_len < block_size) { 587188Smcpowers /* accumulate bytes here and return */ 597188Smcpowers bcopy(datap, 60*7581SMark.Powers@Sun.COM (uint8_t *)ctx->ecb_remainder + ctx->ecb_remainder_len, 617188Smcpowers length); 62*7581SMark.Powers@Sun.COM ctx->ecb_remainder_len += length; 63*7581SMark.Powers@Sun.COM ctx->ecb_copy_to = datap; 647188Smcpowers return (CRYPTO_SUCCESS); 657188Smcpowers } 667188Smcpowers 67*7581SMark.Powers@Sun.COM lastp = (uint8_t *)ctx->ecb_iv; 687188Smcpowers if (out != NULL) 697188Smcpowers crypto_init_ptrs(out, &iov_or_mp, &offset); 707188Smcpowers 717188Smcpowers do { 727188Smcpowers /* Unprocessed data from last call. */ 73*7581SMark.Powers@Sun.COM if (ctx->ecb_remainder_len > 0) { 74*7581SMark.Powers@Sun.COM need = block_size - ctx->ecb_remainder_len; 757188Smcpowers 767188Smcpowers if (need > remainder) 777188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 787188Smcpowers 79*7581SMark.Powers@Sun.COM bcopy(datap, &((uint8_t *)ctx->ecb_remainder) 80*7581SMark.Powers@Sun.COM [ctx->ecb_remainder_len], need); 817188Smcpowers 82*7581SMark.Powers@Sun.COM blockp = (uint8_t *)ctx->ecb_remainder; 837188Smcpowers } else { 847188Smcpowers blockp = datap; 857188Smcpowers } 867188Smcpowers 877188Smcpowers if (out == NULL) { 88*7581SMark.Powers@Sun.COM cipher(ctx->ecb_keysched, blockp, blockp); 897188Smcpowers 90*7581SMark.Powers@Sun.COM ctx->ecb_lastp = blockp; 917188Smcpowers lastp = blockp; 927188Smcpowers 93*7581SMark.Powers@Sun.COM if (ctx->ecb_remainder_len > 0) { 94*7581SMark.Powers@Sun.COM bcopy(blockp, ctx->ecb_copy_to, 95*7581SMark.Powers@Sun.COM ctx->ecb_remainder_len); 96*7581SMark.Powers@Sun.COM bcopy(blockp + ctx->ecb_remainder_len, datap, 977188Smcpowers need); 987188Smcpowers } 997188Smcpowers } else { 100*7581SMark.Powers@Sun.COM cipher(ctx->ecb_keysched, blockp, lastp); 1017188Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1027188Smcpowers &out_data_1_len, &out_data_2, block_size); 1037188Smcpowers 1047188Smcpowers /* copy block to where it belongs */ 1057188Smcpowers bcopy(lastp, out_data_1, out_data_1_len); 1067188Smcpowers if (out_data_2 != NULL) { 1077188Smcpowers bcopy(lastp + out_data_1_len, out_data_2, 1087188Smcpowers block_size - out_data_1_len); 1097188Smcpowers } 1107188Smcpowers /* update offset */ 1117188Smcpowers out->cd_offset += block_size; 1127188Smcpowers } 1137188Smcpowers 1147188Smcpowers /* Update pointer to next block of data to be processed. */ 115*7581SMark.Powers@Sun.COM if (ctx->ecb_remainder_len != 0) { 1167188Smcpowers datap += need; 117*7581SMark.Powers@Sun.COM ctx->ecb_remainder_len = 0; 1187188Smcpowers } else { 1197188Smcpowers datap += block_size; 1207188Smcpowers } 1217188Smcpowers 1227188Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 1237188Smcpowers 1247188Smcpowers /* Incomplete last block. */ 1257188Smcpowers if (remainder > 0 && remainder < block_size) { 126*7581SMark.Powers@Sun.COM bcopy(datap, ctx->ecb_remainder, remainder); 127*7581SMark.Powers@Sun.COM ctx->ecb_remainder_len = remainder; 128*7581SMark.Powers@Sun.COM ctx->ecb_copy_to = datap; 1297188Smcpowers goto out; 1307188Smcpowers } 131*7581SMark.Powers@Sun.COM ctx->ecb_copy_to = NULL; 1327188Smcpowers 1337188Smcpowers } while (remainder > 0); 1347188Smcpowers 1357188Smcpowers out: 1367188Smcpowers return (CRYPTO_SUCCESS); 1377188Smcpowers } 1387188Smcpowers 1397188Smcpowers /* ARGSUSED */ 1407188Smcpowers void * 1417188Smcpowers ecb_alloc_ctx(int kmflag) 1427188Smcpowers { 1437188Smcpowers ecb_ctx_t *ecb_ctx; 1447188Smcpowers 1457188Smcpowers #ifdef _KERNEL 1467188Smcpowers if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL) 1477188Smcpowers #else 1487188Smcpowers if ((ecb_ctx = calloc(1, sizeof (ecb_ctx_t))) == NULL) 1497188Smcpowers #endif 1507188Smcpowers return (NULL); 1517188Smcpowers 152*7581SMark.Powers@Sun.COM ecb_ctx->ecb_flags = ECB_MODE; 1537188Smcpowers return (ecb_ctx); 1547188Smcpowers } 155