Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474


   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  * Encrypt and decrypt multiple blocks of data in counter mode.
  42  */
  43 int
  44 ctr_mode_contiguous_blocks(ctr_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     void (*xor_block)(uint8_t *, uint8_t *))
  48 {
  49         size_t remainder = length;
  50         size_t need;
  51         uint8_t *datap = (uint8_t *)data;
  52         uint8_t *blockp;
  53         uint8_t *lastp;
  54         void *iov_or_mp;
  55         offset_t offset;
  56         uint8_t *out_data_1;
  57         uint8_t *out_data_2;
  58         size_t out_data_1_len;
  59         uint64_t counter;


  84                                 return (CRYPTO_DATA_LEN_RANGE);
  85 
  86                         bcopy(datap, &((uint8_t *)ctx->ctr_remainder)
  87                             [ctx->ctr_remainder_len], need);
  88 
  89                         blockp = (uint8_t *)ctx->ctr_remainder;
  90                 } else {
  91                         blockp = datap;
  92                 }
  93 
  94                 /* ctr_cb is the counter block */
  95                 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
  96                     (uint8_t *)ctx->ctr_tmp);
  97 
  98                 lastp = (uint8_t *)ctx->ctr_tmp;
  99 
 100                 /*
 101                  * Increment counter. Counter bits are confined
 102                  * to the bottom 64 bits of the counter block.
 103                  */
 104                 counter = ctx->ctr_cb[1] & ctx->ctr_counter_mask;
 105 #ifdef _LITTLE_ENDIAN
 106                 p = (uint8_t *)&counter;
 107                 counter = (((uint64_t)p[0] << 56) |
 108                     ((uint64_t)p[1] << 48) |
 109                     ((uint64_t)p[2] << 40) |
 110                     ((uint64_t)p[3] << 32) |
 111                     ((uint64_t)p[4] << 24) |
 112                     ((uint64_t)p[5] << 16) |
 113                     ((uint64_t)p[6] << 8) |
 114                     (uint64_t)p[7]);
 115 #endif
 116                 counter++;
 117 #ifdef _LITTLE_ENDIAN
 118                 counter = (((uint64_t)p[0] << 56) |
 119                     ((uint64_t)p[1] << 48) |
 120                     ((uint64_t)p[2] << 40) |
 121                     ((uint64_t)p[3] << 32) |
 122                     ((uint64_t)p[4] << 24) |
 123                     ((uint64_t)p[5] << 16) |
 124                     ((uint64_t)p[6] << 8) |
 125                     (uint64_t)p[7]);
 126 #endif
 127                 counter &= ctx->ctr_counter_mask;
 128                 ctx->ctr_cb[1] =
 129                     (ctx->ctr_cb[1] & ~(ctx->ctr_counter_mask)) | counter;
 130 
 131                 /*
 132                  * XOR the previous cipher block or IV with the
 133                  * current clear block.
 134                  */
 135                 xor_block(blockp, lastp);
 136 
 137                 if (out == NULL) {
 138                         if (ctx->ctr_remainder_len > 0) {
 139                                 bcopy(lastp, ctx->ctr_copy_to,
 140                                     ctx->ctr_remainder_len);
 141                                 bcopy(lastp + ctx->ctr_remainder_len, datap,
 142                                     need);
 143                         }
 144                 } else {
 145                         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
 146                             &out_data_1_len, &out_data_2, block_size);


 207 
 208         crypto_init_ptrs(out, &iov_or_mp, &offset);
 209         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
 210             &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
 211 
 212         bcopy(p, out_data_1, out_data_1_len);
 213         if (out_data_2 != NULL) {
 214                 bcopy((uint8_t *)p + out_data_1_len,
 215                     out_data_2, ctx->ctr_remainder_len - out_data_1_len);
 216         }
 217         out->cd_offset += ctx->ctr_remainder_len;
 218         ctx->ctr_remainder_len = 0;
 219         return (CRYPTO_SUCCESS);
 220 }
 221 
 222 int
 223 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
 224 void (*copy_block)(uint8_t *, uint8_t *))
 225 {
 226         uint64_t mask = 0;
 227 #ifdef _LITTLE_ENDIAN
 228         uint8_t *p8;
 229 #endif
 230 
 231         if (count == 0 || count > 64) {
 232                 return (CRYPTO_MECHANISM_PARAM_INVALID);
 233         }
 234         while (count-- > 0)
 235                 mask |= (1ULL << count);

 236 #ifdef _LITTLE_ENDIAN
 237         p8 = (uint8_t *)&mask;
 238         mask = (((uint64_t)p8[0] << 56) |
 239             ((uint64_t)p8[1] << 48) |
 240             ((uint64_t)p8[2] << 40) |
 241             ((uint64_t)p8[3] << 32) |
 242             ((uint64_t)p8[4] << 24) |
 243             ((uint64_t)p8[5] << 16) |
 244             ((uint64_t)p8[6] << 8) |
 245             (uint64_t)p8[7]);
 246 #endif
 247         ctr_ctx->ctr_counter_mask = mask;
 248         copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
 249         ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
 250         ctr_ctx->ctr_flags |= CTR_MODE;
 251         return (CRYPTO_SUCCESS);
 252 }
 253 
 254 /* ARGSUSED */
 255 void *
 256 ctr_alloc_ctx(int kmflag)
 257 {
 258         ctr_ctx_t *ctr_ctx;
 259 
 260 #ifdef _KERNEL
 261         if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
 262 #else
 263         if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
 264 #endif
 265                 return (NULL);


   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 #ifdef _LITTLE_ENDIAN
  39 #include <sys/byteorder.h>
  40 #endif
  41 
  42 /*
  43  * Encrypt and decrypt multiple blocks of data in counter mode.
  44  */
  45 int
  46 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
  47     crypto_data_t *out, size_t block_size,
  48     int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
  49     void (*xor_block)(uint8_t *, uint8_t *))
  50 {
  51         size_t remainder = length;
  52         size_t need;
  53         uint8_t *datap = (uint8_t *)data;
  54         uint8_t *blockp;
  55         uint8_t *lastp;
  56         void *iov_or_mp;
  57         offset_t offset;
  58         uint8_t *out_data_1;
  59         uint8_t *out_data_2;
  60         size_t out_data_1_len;
  61         uint64_t counter;


  86                                 return (CRYPTO_DATA_LEN_RANGE);
  87 
  88                         bcopy(datap, &((uint8_t *)ctx->ctr_remainder)
  89                             [ctx->ctr_remainder_len], need);
  90 
  91                         blockp = (uint8_t *)ctx->ctr_remainder;
  92                 } else {
  93                         blockp = datap;
  94                 }
  95 
  96                 /* ctr_cb is the counter block */
  97                 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
  98                     (uint8_t *)ctx->ctr_tmp);
  99 
 100                 lastp = (uint8_t *)ctx->ctr_tmp;
 101 
 102                 /*
 103                  * Increment counter. Counter bits are confined
 104                  * to the bottom 64 bits of the counter block.
 105                  */

 106 #ifdef _LITTLE_ENDIAN
 107                 counter = ntohll(ctx->ctr_cb[1] & ctx->ctr_counter_mask);
 108                 counter = htonll(counter + 1);
 109 #else
 110                 counter = ctx->ctr_cb[1] & ctx->ctr_counter_mask;






 111                 counter++;
 112 #endif  /* _LITTLE_ENDIAN */









 113                 counter &= ctx->ctr_counter_mask;
 114                 ctx->ctr_cb[1] =
 115                     (ctx->ctr_cb[1] & ~(ctx->ctr_counter_mask)) | counter;
 116 
 117                 /*
 118                  * XOR the previous cipher block or IV with the
 119                  * current clear block.
 120                  */
 121                 xor_block(blockp, lastp);
 122 
 123                 if (out == NULL) {
 124                         if (ctx->ctr_remainder_len > 0) {
 125                                 bcopy(lastp, ctx->ctr_copy_to,
 126                                     ctx->ctr_remainder_len);
 127                                 bcopy(lastp + ctx->ctr_remainder_len, datap,
 128                                     need);
 129                         }
 130                 } else {
 131                         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
 132                             &out_data_1_len, &out_data_2, block_size);


 193 
 194         crypto_init_ptrs(out, &iov_or_mp, &offset);
 195         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
 196             &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
 197 
 198         bcopy(p, out_data_1, out_data_1_len);
 199         if (out_data_2 != NULL) {
 200                 bcopy((uint8_t *)p + out_data_1_len,
 201                     out_data_2, ctx->ctr_remainder_len - out_data_1_len);
 202         }
 203         out->cd_offset += ctx->ctr_remainder_len;
 204         ctx->ctr_remainder_len = 0;
 205         return (CRYPTO_SUCCESS);
 206 }
 207 
 208 int
 209 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
 210 void (*copy_block)(uint8_t *, uint8_t *))
 211 {
 212         uint64_t mask = 0;



 213 
 214         if (count == 0 || count > 64) {
 215                 return (CRYPTO_MECHANISM_PARAM_INVALID);
 216         }
 217         while (count-- > 0)
 218                 mask |= (1ULL << count);
 219 
 220 #ifdef _LITTLE_ENDIAN
 221         mask = htonll(mask);








 222 #endif
 223         ctr_ctx->ctr_counter_mask = mask;
 224         copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
 225         ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
 226         ctr_ctx->ctr_flags |= CTR_MODE;
 227         return (CRYPTO_SUCCESS);
 228 }
 229 
 230 /* ARGSUSED */
 231 void *
 232 ctr_alloc_ctx(int kmflag)
 233 {
 234         ctr_ctx_t *ctr_ctx;
 235 
 236 #ifdef _KERNEL
 237         if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
 238 #else
 239         if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
 240 #endif
 241                 return (NULL);