1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #ifndef _KERNEL 29 #include <strings.h> 30 #include <limits.h> 31 #include <assert.h> 32 #include <security/cryptoki.h> 33 #endif 34 35 #include <sys/types.h> 36 #include <modes/modes.h> 37 #include <sys/crypto/common.h> 38 #include <sys/crypto/impl.h> 39 40 /* 41 * Algorithm independent ECB functions. 42 */ 43 int 44 ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length, 45 crypto_data_t *out, size_t block_size, 46 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct)) 47 { 48 size_t remainder = length; 49 size_t need; 50 uint8_t *datap = (uint8_t *)data; 51 uint8_t *blockp; 52 uint8_t *lastp; 53 void *iov_or_mp; 54 offset_t offset; 55 uint8_t *out_data_1; 56 uint8_t *out_data_2; 57 size_t out_data_1_len; 58 59 if (length + ctx->cc_remainder_len < block_size) { 60 /* accumulate bytes here and return */ 61 bcopy(datap, 62 (uint8_t *)ctx->cc_remainder + ctx->cc_remainder_len, 63 length); 64 ctx->cc_remainder_len += length; 65 ctx->cc_copy_to = datap; 66 return (CRYPTO_SUCCESS); 67 } 68 69 lastp = (uint8_t *)ctx->cc_iv; 70 if (out != NULL) 71 crypto_init_ptrs(out, &iov_or_mp, &offset); 72 73 do { 74 /* Unprocessed data from last call. */ 75 if (ctx->cc_remainder_len > 0) { 76 need = block_size - ctx->cc_remainder_len; 77 78 if (need > remainder) 79 return (CRYPTO_DATA_LEN_RANGE); 80 81 bcopy(datap, &((uint8_t *)ctx->cc_remainder) 82 [ctx->cc_remainder_len], need); 83 84 blockp = (uint8_t *)ctx->cc_remainder; 85 } else { 86 blockp = datap; 87 } 88 89 if (out == NULL) { 90 cipher(ctx->cc_keysched, blockp, blockp); 91 92 ctx->cc_lastp = blockp; 93 lastp = blockp; 94 95 if (ctx->cc_remainder_len > 0) { 96 bcopy(blockp, ctx->cc_copy_to, 97 ctx->cc_remainder_len); 98 bcopy(blockp + ctx->cc_remainder_len, datap, 99 need); 100 } 101 } else { 102 cipher(ctx->cc_keysched, blockp, lastp); 103 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 104 &out_data_1_len, &out_data_2, block_size); 105 106 /* copy block to where it belongs */ 107 bcopy(lastp, out_data_1, out_data_1_len); 108 if (out_data_2 != NULL) { 109 bcopy(lastp + out_data_1_len, out_data_2, 110 block_size - out_data_1_len); 111 } 112 /* update offset */ 113 out->cd_offset += block_size; 114 } 115 116 /* Update pointer to next block of data to be processed. */ 117 if (ctx->cc_remainder_len != 0) { 118 datap += need; 119 ctx->cc_remainder_len = 0; 120 } else { 121 datap += block_size; 122 } 123 124 remainder = (size_t)&data[length] - (size_t)datap; 125 126 /* Incomplete last block. */ 127 if (remainder > 0 && remainder < block_size) { 128 bcopy(datap, ctx->cc_remainder, remainder); 129 ctx->cc_remainder_len = remainder; 130 ctx->cc_copy_to = datap; 131 goto out; 132 } 133 ctx->cc_copy_to = NULL; 134 135 } while (remainder > 0); 136 137 out: 138 return (CRYPTO_SUCCESS); 139 } 140 141 /* ARGSUSED */ 142 void * 143 ecb_alloc_ctx(int kmflag) 144 { 145 ecb_ctx_t *ecb_ctx; 146 147 #ifdef _KERNEL 148 if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL) 149 #else 150 if ((ecb_ctx = calloc(1, sizeof (ecb_ctx_t))) == NULL) 151 #endif 152 return (NULL); 153 154 ecb_ctx->cc_flags = ECB_MODE; 155 return (ecb_ctx); 156 } 157