The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/icp/algs/modes/ctr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 https://opensource.org/licenses/CDDL-1.0.
   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 #include <sys/zfs_context.h>
   27 #include <modes/modes.h>
   28 #include <sys/crypto/common.h>
   29 #include <sys/crypto/impl.h>
   30 #include <sys/byteorder.h>
   31 
   32 /*
   33  * Encrypt and decrypt multiple blocks of data in counter mode.
   34  */
   35 int
   36 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
   37     crypto_data_t *out, size_t block_size,
   38     int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
   39     void (*xor_block)(uint8_t *, uint8_t *))
   40 {
   41         size_t remainder = length;
   42         size_t need = 0;
   43         uint8_t *datap = (uint8_t *)data;
   44         uint8_t *blockp;
   45         uint8_t *lastp;
   46         void *iov_or_mp;
   47         offset_t offset;
   48         uint8_t *out_data_1;
   49         uint8_t *out_data_2;
   50         size_t out_data_1_len;
   51         uint64_t lower_counter, upper_counter;
   52 
   53         if (length + ctx->ctr_remainder_len < block_size) {
   54                 /* accumulate bytes here and return */
   55                 memcpy((uint8_t *)ctx->ctr_remainder + ctx->ctr_remainder_len,
   56                     datap,
   57                     length);
   58                 ctx->ctr_remainder_len += length;
   59                 ctx->ctr_copy_to = datap;
   60                 return (CRYPTO_SUCCESS);
   61         }
   62 
   63         crypto_init_ptrs(out, &iov_or_mp, &offset);
   64 
   65         do {
   66                 /* Unprocessed data from last call. */
   67                 if (ctx->ctr_remainder_len > 0) {
   68                         need = block_size - ctx->ctr_remainder_len;
   69 
   70                         if (need > remainder)
   71                                 return (CRYPTO_DATA_LEN_RANGE);
   72 
   73                         memcpy(&((uint8_t *)ctx->ctr_remainder)
   74                             [ctx->ctr_remainder_len], datap, need);
   75 
   76                         blockp = (uint8_t *)ctx->ctr_remainder;
   77                 } else {
   78                         blockp = datap;
   79                 }
   80 
   81                 /* ctr_cb is the counter block */
   82                 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
   83                     (uint8_t *)ctx->ctr_tmp);
   84 
   85                 lastp = (uint8_t *)ctx->ctr_tmp;
   86 
   87                 /*
   88                  * Increment Counter.
   89                  */
   90                 lower_counter = ntohll(ctx->ctr_cb[1] & ctx->ctr_lower_mask);
   91                 lower_counter = htonll(lower_counter + 1);
   92                 lower_counter &= ctx->ctr_lower_mask;
   93                 ctx->ctr_cb[1] = (ctx->ctr_cb[1] & ~(ctx->ctr_lower_mask)) |
   94                     lower_counter;
   95 
   96                 /* wrap around */
   97                 if (lower_counter == 0) {
   98                         upper_counter =
   99                             ntohll(ctx->ctr_cb[0] & ctx->ctr_upper_mask);
  100                         upper_counter = htonll(upper_counter + 1);
  101                         upper_counter &= ctx->ctr_upper_mask;
  102                         ctx->ctr_cb[0] =
  103                             (ctx->ctr_cb[0] & ~(ctx->ctr_upper_mask)) |
  104                             upper_counter;
  105                 }
  106 
  107                 /*
  108                  * XOR encrypted counter block with the current clear block.
  109                  */
  110                 xor_block(blockp, lastp);
  111 
  112                 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
  113                     &out_data_1_len, &out_data_2, block_size);
  114 
  115                 /* copy block to where it belongs */
  116                 memcpy(out_data_1, lastp, out_data_1_len);
  117                 if (out_data_2 != NULL) {
  118                         memcpy(out_data_2, lastp + out_data_1_len,
  119                             block_size - out_data_1_len);
  120                 }
  121                 /* update offset */
  122                 out->cd_offset += block_size;
  123 
  124                 /* Update pointer to next block of data to be processed. */
  125                 if (ctx->ctr_remainder_len != 0) {
  126                         datap += need;
  127                         ctx->ctr_remainder_len = 0;
  128                 } else {
  129                         datap += block_size;
  130                 }
  131 
  132                 remainder = (size_t)&data[length] - (size_t)datap;
  133 
  134                 /* Incomplete last block. */
  135                 if (remainder > 0 && remainder < block_size) {
  136                         memcpy(ctx->ctr_remainder, datap, remainder);
  137                         ctx->ctr_remainder_len = remainder;
  138                         ctx->ctr_copy_to = datap;
  139                         goto out;
  140                 }
  141                 ctx->ctr_copy_to = NULL;
  142 
  143         } while (remainder > 0);
  144 
  145 out:
  146         return (CRYPTO_SUCCESS);
  147 }
  148 
  149 int
  150 ctr_mode_final(ctr_ctx_t *ctx, crypto_data_t *out,
  151     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
  152 {
  153         uint8_t *lastp;
  154         void *iov_or_mp;
  155         offset_t offset;
  156         uint8_t *out_data_1;
  157         uint8_t *out_data_2;
  158         size_t out_data_1_len;
  159         uint8_t *p;
  160         int i;
  161 
  162         if (out->cd_length < ctx->ctr_remainder_len)
  163                 return (CRYPTO_DATA_LEN_RANGE);
  164 
  165         encrypt_block(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
  166             (uint8_t *)ctx->ctr_tmp);
  167 
  168         lastp = (uint8_t *)ctx->ctr_tmp;
  169         p = (uint8_t *)ctx->ctr_remainder;
  170         for (i = 0; i < ctx->ctr_remainder_len; i++) {
  171                 p[i] ^= lastp[i];
  172         }
  173 
  174         crypto_init_ptrs(out, &iov_or_mp, &offset);
  175         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
  176             &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
  177 
  178         memcpy(out_data_1, p, out_data_1_len);
  179         if (out_data_2 != NULL) {
  180                 memcpy(out_data_2,
  181                     (uint8_t *)p + out_data_1_len,
  182                     ctx->ctr_remainder_len - out_data_1_len);
  183         }
  184         out->cd_offset += ctx->ctr_remainder_len;
  185         ctx->ctr_remainder_len = 0;
  186         return (CRYPTO_SUCCESS);
  187 }
  188 
  189 int
  190 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
  191     void (*copy_block)(uint8_t *, uint8_t *))
  192 {
  193         uint64_t upper_mask = 0;
  194         uint64_t lower_mask = 0;
  195 
  196         if (count == 0 || count > 128) {
  197                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  198         }
  199         /* upper 64 bits of the mask */
  200         if (count >= 64) {
  201                 count -= 64;
  202                 upper_mask = (count == 64) ? UINT64_MAX : (1ULL << count) - 1;
  203                 lower_mask = UINT64_MAX;
  204         } else {
  205                 /* now the lower 63 bits */
  206                 lower_mask = (1ULL << count) - 1;
  207         }
  208         ctr_ctx->ctr_lower_mask = htonll(lower_mask);
  209         ctr_ctx->ctr_upper_mask = htonll(upper_mask);
  210 
  211         copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
  212         ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
  213         ctr_ctx->ctr_flags |= CTR_MODE;
  214         return (CRYPTO_SUCCESS);
  215 }
  216 
  217 void *
  218 ctr_alloc_ctx(int kmflag)
  219 {
  220         ctr_ctx_t *ctr_ctx;
  221 
  222         if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
  223                 return (NULL);
  224 
  225         ctr_ctx->ctr_flags = CTR_MODE;
  226         return (ctr_ctx);
  227 }

Cache object: 3065847332a5f3a9b2e6512e4b6fc19d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.