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 * Copyright 2015 by Saso Kiselkov. All rights reserved. 27 */ 28 29 #ifndef _KERNEL 30 #include <strings.h> 31 #include <limits.h> 32 #include <assert.h> 33 #include <security/cryptoki.h> 34 #endif 35 36 #include <sys/types.h> 37 #define INLINE_CRYPTO_GET_PTRS 38 #include <modes/modes.h> 39 #include <sys/crypto/common.h> 40 #include <sys/crypto/impl.h> 41 #include <sys/byteorder.h> 42 #include <sys/cmn_err.h> 43 44 boolean_t ctr_fastpath_enabled = B_TRUE; 45 46 /* 47 * Encrypt and decrypt multiple blocks of data in counter mode. 48 */ 49 int 50 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length, 51 crypto_data_t *out, size_t block_size, 52 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct), 53 void (*xor_block)(const uint8_t *, uint8_t *), 54 int (*cipher_ctr)(const void *ks, const uint8_t *pt, uint8_t *ct, 55 uint64_t len, uint64_t counter[2])) 56 { 57 size_t remainder = length; 58 size_t need; 59 uint8_t *datap = (uint8_t *)data; 60 uint8_t *blockp; 61 uint8_t *lastp; 62 void *iov_or_mp; 63 offset_t offset; 64 uint8_t *out_data_1; 65 uint8_t *out_data_2; 66 size_t out_data_1_len; 67 uint64_t lower_counter, upper_counter; 68 69 /* 70 * CTR encryption/decryption fastpath requirements: 71 * - fastpath is enabled 72 * - algorithm-specific acceleration function is available 73 * - input is block-aligned 74 * - the counter value won't overflow the lower counter mask 75 * - output is a single contiguous region and doesn't alias input 76 */ 77 if (ctr_fastpath_enabled && cipher_ctr != NULL && 78 ctx->ctr_remainder_len == 0 && (length & (block_size - 1)) == 0 && 79 ntohll(ctx->ctr_cb[1]) <= ctx->ctr_lower_mask - 80 length / block_size && CRYPTO_DATA_IS_SINGLE_BLOCK(out)) { 81 cipher_ctr(ctx->ctr_keysched, (uint8_t *)data, 82 CRYPTO_DATA_FIRST_BLOCK(out), length, ctx->ctr_cb); 83 out->cd_offset += length; 84 return (CRYPTO_SUCCESS); 85 } 86 87 if (length + ctx->ctr_remainder_len < block_size) { 88 /* accumulate bytes here and return */ 89 bcopy(datap, 90 (uint8_t *)ctx->ctr_remainder + ctx->ctr_remainder_len, 91 length); 92 ctx->ctr_remainder_len += length; 93 ctx->ctr_copy_to = datap; 94 return (CRYPTO_SUCCESS); 95 } 96 97 lastp = (uint8_t *)ctx->ctr_cb; 98 if (out != NULL) 99 crypto_init_ptrs(out, &iov_or_mp, &offset); 100 101 do { 102 /* Unprocessed data from last call. */ 103 if (ctx->ctr_remainder_len > 0) { 104 need = block_size - ctx->ctr_remainder_len; 105 106 if (need > remainder) 107 return (CRYPTO_DATA_LEN_RANGE); 108 109 bcopy(datap, &((uint8_t *)ctx->ctr_remainder) 110 [ctx->ctr_remainder_len], need); 111 112 blockp = (uint8_t *)ctx->ctr_remainder; 113 } else { 114 blockp = datap; 115 } 116 117 /* ctr_cb is the counter block */ 118 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb, 119 (uint8_t *)ctx->ctr_tmp); 120 121 lastp = (uint8_t *)ctx->ctr_tmp; 122 123 /* 124 * Increment Counter. 125 */ 126 lower_counter = ntohll(ctx->ctr_cb[1] & ctx->ctr_lower_mask); 127 lower_counter = htonll(lower_counter + 1); 128 lower_counter &= ctx->ctr_lower_mask; 129 ctx->ctr_cb[1] = (ctx->ctr_cb[1] & ~(ctx->ctr_lower_mask)) | 130 lower_counter; 131 132 /* wrap around */ 133 if (lower_counter == 0) { 134 upper_counter = 135 ntohll(ctx->ctr_cb[0] & ctx->ctr_upper_mask); 136 upper_counter = htonll(upper_counter + 1); 137 upper_counter &= ctx->ctr_upper_mask; 138 ctx->ctr_cb[0] = 139 (ctx->ctr_cb[0] & ~(ctx->ctr_upper_mask)) | 140 upper_counter; 141 } 142 143 /* 144 * XOR encrypted counter block with the current clear block. 145 */ 146 xor_block(blockp, lastp); 147 148 if (out == NULL) { 149 if (ctx->ctr_remainder_len > 0) { 150 bcopy(lastp, ctx->ctr_copy_to, 151 ctx->ctr_remainder_len); 152 bcopy(lastp + ctx->ctr_remainder_len, datap, 153 need); 154 } 155 } else { 156 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 157 &out_data_1_len, &out_data_2, block_size); 158 159 /* copy block to where it belongs */ 160 bcopy(lastp, out_data_1, out_data_1_len); 161 if (out_data_2 != NULL) { 162 bcopy(lastp + out_data_1_len, out_data_2, 163 block_size - out_data_1_len); 164 } 165 /* update offset */ 166 out->cd_offset += block_size; 167 } 168 169 /* Update pointer to next block of data to be processed. */ 170 if (ctx->ctr_remainder_len != 0) { 171 datap += need; 172 ctx->ctr_remainder_len = 0; 173 } else { 174 datap += block_size; 175 } 176 177 remainder = (size_t)&data[length] - (size_t)datap; 178 179 /* Incomplete last block. */ 180 if (remainder > 0 && remainder < block_size) { 181 bcopy(datap, ctx->ctr_remainder, remainder); 182 ctx->ctr_remainder_len = remainder; 183 ctx->ctr_copy_to = datap; 184 goto out; 185 } 186 ctx->ctr_copy_to = NULL; 187 188 } while (remainder > 0); 189 190 out: 191 return (CRYPTO_SUCCESS); 192 } 193 194 int 195 ctr_mode_final(ctr_ctx_t *ctx, crypto_data_t *out, 196 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 197 { 198 uint8_t *lastp; 199 void *iov_or_mp; 200 offset_t offset; 201 uint8_t *out_data_1; 202 uint8_t *out_data_2; 203 size_t out_data_1_len; 204 uint8_t *p; 205 int i; 206 207 if (out->cd_length < ctx->ctr_remainder_len) 208 return (CRYPTO_DATA_LEN_RANGE); 209 210 encrypt_block(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb, 211 (uint8_t *)ctx->ctr_tmp); 212 213 lastp = (uint8_t *)ctx->ctr_tmp; 214 p = (uint8_t *)ctx->ctr_remainder; 215 for (i = 0; i < ctx->ctr_remainder_len; i++) { 216 p[i] ^= lastp[i]; 217 } 218 219 crypto_init_ptrs(out, &iov_or_mp, &offset); 220 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 221 &out_data_1_len, &out_data_2, ctx->ctr_remainder_len); 222 223 bcopy(p, out_data_1, out_data_1_len); 224 if (out_data_2 != NULL) { 225 bcopy((uint8_t *)p + out_data_1_len, 226 out_data_2, ctx->ctr_remainder_len - out_data_1_len); 227 } 228 out->cd_offset += ctx->ctr_remainder_len; 229 ctx->ctr_remainder_len = 0; 230 return (CRYPTO_SUCCESS); 231 } 232 233 int 234 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb, 235 void (*copy_block)(const uint8_t *, uint8_t *)) 236 { 237 uint64_t upper_mask = 0; 238 uint64_t lower_mask = 0; 239 240 if (count == 0 || count > 128) { 241 return (CRYPTO_MECHANISM_PARAM_INVALID); 242 } 243 /* upper 64 bits of the mask */ 244 if (count >= 64) { 245 count -= 64; 246 upper_mask = (count == 64) ? UINT64_MAX : (1ULL << count) - 1; 247 lower_mask = UINT64_MAX; 248 } else { 249 /* now the lower 63 bits */ 250 lower_mask = (1ULL << count) - 1; 251 } 252 ctr_ctx->ctr_lower_mask = htonll(lower_mask); 253 ctr_ctx->ctr_upper_mask = htonll(upper_mask); 254 255 copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb); 256 ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0]; 257 ctr_ctx->ctr_flags |= CTR_MODE; 258 return (CRYPTO_SUCCESS); 259 } 260 261 /* ARGSUSED */ 262 void * 263 ctr_alloc_ctx(int kmflag) 264 { 265 ctr_ctx_t *ctr_ctx; 266 267 #ifdef _KERNEL 268 if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL) 269 #else 270 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL) 271 #endif 272 return (NULL); 273 274 ctr_ctx->ctr_flags = CTR_MODE; 275 return (ctr_ctx); 276 }