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 #ifndef _KERNEL 27 #include <strings.h> 28 #include <limits.h> 29 #include <assert.h> 30 #include <security/cryptoki.h> 31 #endif 32 33 #include <sys/types.h> 34 #include <modes/modes.h> 35 #include <sys/crypto/common.h> 36 #include <sys/crypto/impl.h> 37 38 /* 39 * Algorithm independent ECB functions. 40 */ 41 int 42 ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length, 43 crypto_data_t *out, size_t block_size, 44 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct)) 45 { 46 size_t remainder = length; 47 size_t need; 48 uint8_t *datap = (uint8_t *)data; 49 uint8_t *blockp; 50 uint8_t *lastp; 51 void *iov_or_mp; 52 offset_t offset; 53 uint8_t *out_data_1; 54 uint8_t *out_data_2; 55 size_t out_data_1_len; 56 57 if (length + ctx->ecb_remainder_len < block_size) { 58 /* accumulate bytes here and return */ 59 bcopy(datap, 60 (uint8_t *)ctx->ecb_remainder + ctx->ecb_remainder_len, 61 length); 62 ctx->ecb_remainder_len += length; 63 ctx->ecb_copy_to = datap; 64 return (CRYPTO_SUCCESS); 65 } 66 67 lastp = (uint8_t *)ctx->ecb_iv; 68 if (out != NULL) 69 crypto_init_ptrs(out, &iov_or_mp, &offset); 70 71 do { 72 /* Unprocessed data from last call. */ 73 if (ctx->ecb_remainder_len > 0) { 74 need = block_size - ctx->ecb_remainder_len; 75 76 if (need > remainder) 77 return (CRYPTO_DATA_LEN_RANGE); 78 79 bcopy(datap, &((uint8_t *)ctx->ecb_remainder) 80 [ctx->ecb_remainder_len], need); 81 82 blockp = (uint8_t *)ctx->ecb_remainder; 83 } else { 84 blockp = datap; 85 } 86 87 if (out == NULL) { 88 cipher(ctx->ecb_keysched, blockp, blockp); 89 90 ctx->ecb_lastp = blockp; 91 lastp = blockp; 92 93 if (ctx->ecb_remainder_len > 0) { 94 bcopy(blockp, ctx->ecb_copy_to, 95 ctx->ecb_remainder_len); 96 bcopy(blockp + ctx->ecb_remainder_len, datap, 97 need); 98 } 99 } else { 100 cipher(ctx->ecb_keysched, blockp, lastp); 101 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 102 &out_data_1_len, &out_data_2, block_size); 103 104 /* copy block to where it belongs */ 105 bcopy(lastp, out_data_1, out_data_1_len); 106 if (out_data_2 != NULL) { 107 bcopy(lastp + out_data_1_len, out_data_2, 108 block_size - out_data_1_len); 109 } 110 /* update offset */ 111 out->cd_offset += block_size; 112 } 113 114 /* Update pointer to next block of data to be processed. */ 115 if (ctx->ecb_remainder_len != 0) { 116 datap += need; 117 ctx->ecb_remainder_len = 0; 118 } else { 119 datap += block_size; 120 } 121 122 remainder = (size_t)&data[length] - (size_t)datap; 123 124 /* Incomplete last block. */ 125 if (remainder > 0 && remainder < block_size) { 126 bcopy(datap, ctx->ecb_remainder, remainder); 127 ctx->ecb_remainder_len = remainder; 128 ctx->ecb_copy_to = datap; 129 goto out; 130 } 131 ctx->ecb_copy_to = NULL; 132 133 } while (remainder > 0); 134 135 out: 136 return (CRYPTO_SUCCESS); 137 } 138 139 /* ARGSUSED */ 140 void * 141 ecb_alloc_ctx(int kmflag) 142 { 143 ecb_ctx_t *ecb_ctx; 144 145 #ifdef _KERNEL 146 if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL) 147 #else 148 if ((ecb_ctx = calloc(1, sizeof (ecb_ctx_t))) == NULL) 149 #endif 150 return (NULL); 151 152 ecb_ctx->ecb_flags = ECB_MODE; 153 return (ecb_ctx); 154 }