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/cbc.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 
   31 /*
   32  * Algorithm independent CBC functions.
   33  */
   34 int
   35 cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
   36     crypto_data_t *out, size_t block_size,
   37     int (*encrypt)(const void *, const uint8_t *, uint8_t *),
   38     void (*copy_block)(uint8_t *, uint8_t *),
   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 
   52         if (length + ctx->cbc_remainder_len < block_size) {
   53                 /* accumulate bytes here and return */
   54                 memcpy((uint8_t *)ctx->cbc_remainder + ctx->cbc_remainder_len,
   55                     datap,
   56                     length);
   57                 ctx->cbc_remainder_len += length;
   58                 ctx->cbc_copy_to = datap;
   59                 return (CRYPTO_SUCCESS);
   60         }
   61 
   62         lastp = (uint8_t *)ctx->cbc_iv;
   63         crypto_init_ptrs(out, &iov_or_mp, &offset);
   64 
   65         do {
   66                 /* Unprocessed data from last call. */
   67                 if (ctx->cbc_remainder_len > 0) {
   68                         need = block_size - ctx->cbc_remainder_len;
   69 
   70                         if (need > remainder)
   71                                 return (CRYPTO_DATA_LEN_RANGE);
   72 
   73                         memcpy(&((uint8_t *)ctx->cbc_remainder)
   74                             [ctx->cbc_remainder_len], datap, need);
   75 
   76                         blockp = (uint8_t *)ctx->cbc_remainder;
   77                 } else {
   78                         blockp = datap;
   79                 }
   80 
   81                 /*
   82                  * XOR the previous cipher block or IV with the
   83                  * current clear block.
   84                  */
   85                 xor_block(blockp, lastp);
   86                 encrypt(ctx->cbc_keysched, lastp, lastp);
   87                 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
   88                     &out_data_1_len, &out_data_2, block_size);
   89 
   90                 /* copy block to where it belongs */
   91                 if (out_data_1_len == block_size) {
   92                         copy_block(lastp, out_data_1);
   93                 } else {
   94                         memcpy(out_data_1, lastp, out_data_1_len);
   95                         if (out_data_2 != NULL) {
   96                                 memcpy(out_data_2,
   97                                     lastp + out_data_1_len,
   98                                     block_size - out_data_1_len);
   99                         }
  100                 }
  101                 /* update offset */
  102                 out->cd_offset += block_size;
  103 
  104                 /* Update pointer to next block of data to be processed. */
  105                 if (ctx->cbc_remainder_len != 0) {
  106                         datap += need;
  107                         ctx->cbc_remainder_len = 0;
  108                 } else {
  109                         datap += block_size;
  110                 }
  111 
  112                 remainder = (size_t)&data[length] - (size_t)datap;
  113 
  114                 /* Incomplete last block. */
  115                 if (remainder > 0 && remainder < block_size) {
  116                         memcpy(ctx->cbc_remainder, datap, remainder);
  117                         ctx->cbc_remainder_len = remainder;
  118                         ctx->cbc_copy_to = datap;
  119                         goto out;
  120                 }
  121                 ctx->cbc_copy_to = NULL;
  122 
  123         } while (remainder > 0);
  124 
  125 out:
  126         /*
  127          * Save the last encrypted block in the context.
  128          */
  129         if (ctx->cbc_lastp != NULL) {
  130                 copy_block((uint8_t *)ctx->cbc_lastp, (uint8_t *)ctx->cbc_iv);
  131                 ctx->cbc_lastp = (uint8_t *)ctx->cbc_iv;
  132         }
  133 
  134         return (CRYPTO_SUCCESS);
  135 }
  136 
  137 #define OTHER(a, ctx) \
  138         (((a) == (ctx)->cbc_lastblock) ? (ctx)->cbc_iv : (ctx)->cbc_lastblock)
  139 
  140 int
  141 cbc_decrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
  142     crypto_data_t *out, size_t block_size,
  143     int (*decrypt)(const void *, const uint8_t *, uint8_t *),
  144     void (*copy_block)(uint8_t *, uint8_t *),
  145     void (*xor_block)(uint8_t *, uint8_t *))
  146 {
  147         size_t remainder = length;
  148         size_t need = 0;
  149         uint8_t *datap = (uint8_t *)data;
  150         uint8_t *blockp;
  151         uint8_t *lastp;
  152         void *iov_or_mp;
  153         offset_t offset;
  154         uint8_t *out_data_1;
  155         uint8_t *out_data_2;
  156         size_t out_data_1_len;
  157 
  158         if (length + ctx->cbc_remainder_len < block_size) {
  159                 /* accumulate bytes here and return */
  160                 memcpy((uint8_t *)ctx->cbc_remainder + ctx->cbc_remainder_len,
  161                     datap,
  162                     length);
  163                 ctx->cbc_remainder_len += length;
  164                 ctx->cbc_copy_to = datap;
  165                 return (CRYPTO_SUCCESS);
  166         }
  167 
  168         lastp = ctx->cbc_lastp;
  169         crypto_init_ptrs(out, &iov_or_mp, &offset);
  170 
  171         do {
  172                 /* Unprocessed data from last call. */
  173                 if (ctx->cbc_remainder_len > 0) {
  174                         need = block_size - ctx->cbc_remainder_len;
  175 
  176                         if (need > remainder)
  177                                 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
  178 
  179                         memcpy(&((uint8_t *)ctx->cbc_remainder)
  180                             [ctx->cbc_remainder_len], datap, need);
  181 
  182                         blockp = (uint8_t *)ctx->cbc_remainder;
  183                 } else {
  184                         blockp = datap;
  185                 }
  186 
  187                 /* LINTED: pointer alignment */
  188                 copy_block(blockp, (uint8_t *)OTHER((uint64_t *)lastp, ctx));
  189 
  190                 decrypt(ctx->cbc_keysched, blockp,
  191                     (uint8_t *)ctx->cbc_remainder);
  192                 blockp = (uint8_t *)ctx->cbc_remainder;
  193 
  194                 /*
  195                  * XOR the previous cipher block or IV with the
  196                  * currently decrypted block.
  197                  */
  198                 xor_block(lastp, blockp);
  199 
  200                 /* LINTED: pointer alignment */
  201                 lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
  202 
  203                 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
  204                     &out_data_1_len, &out_data_2, block_size);
  205 
  206                 memcpy(out_data_1, blockp, out_data_1_len);
  207                 if (out_data_2 != NULL) {
  208                         memcpy(out_data_2, blockp + out_data_1_len,
  209                             block_size - out_data_1_len);
  210                 }
  211 
  212                 /* update offset */
  213                 out->cd_offset += block_size;
  214 
  215                 /* Update pointer to next block of data to be processed. */
  216                 if (ctx->cbc_remainder_len != 0) {
  217                         datap += need;
  218                         ctx->cbc_remainder_len = 0;
  219                 } else {
  220                         datap += block_size;
  221                 }
  222 
  223                 remainder = (size_t)&data[length] - (size_t)datap;
  224 
  225                 /* Incomplete last block. */
  226                 if (remainder > 0 && remainder < block_size) {
  227                         memcpy(ctx->cbc_remainder, datap, remainder);
  228                         ctx->cbc_remainder_len = remainder;
  229                         ctx->cbc_lastp = lastp;
  230                         ctx->cbc_copy_to = datap;
  231                         return (CRYPTO_SUCCESS);
  232                 }
  233                 ctx->cbc_copy_to = NULL;
  234 
  235         } while (remainder > 0);
  236 
  237         ctx->cbc_lastp = lastp;
  238         return (CRYPTO_SUCCESS);
  239 }
  240 
  241 int
  242 cbc_init_ctx(cbc_ctx_t *cbc_ctx, char *param, size_t param_len,
  243     size_t block_size, void (*copy_block)(uint8_t *, uint64_t *))
  244 {
  245         /* Copy IV into context. */
  246         ASSERT3P(param, !=, NULL);
  247         ASSERT3U(param_len, ==, block_size);
  248 
  249         copy_block((uchar_t *)param, cbc_ctx->cbc_iv);
  250 
  251         return (CRYPTO_SUCCESS);
  252 }
  253 
  254 void *
  255 cbc_alloc_ctx(int kmflag)
  256 {
  257         cbc_ctx_t *cbc_ctx;
  258 
  259         if ((cbc_ctx = kmem_zalloc(sizeof (cbc_ctx_t), kmflag)) == NULL)
  260                 return (NULL);
  261 
  262         cbc_ctx->cbc_flags = CBC_MODE;
  263         return (cbc_ctx);
  264 }

Cache object: ec63a4a2ec98c2386343d7f0bfeaaf6b


[ 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.