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/ccm.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 #ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
   32 #include <sys/byteorder.h>
   33 #define UNALIGNED_POINTERS_PERMITTED
   34 #endif
   35 
   36 /*
   37  * Encrypt multiple blocks of data in CCM mode.  Decrypt for CCM mode
   38  * is done in another function.
   39  */
   40 int
   41 ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
   42     crypto_data_t *out, size_t block_size,
   43     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
   44     void (*copy_block)(uint8_t *, uint8_t *),
   45     void (*xor_block)(uint8_t *, uint8_t *))
   46 {
   47         size_t remainder = length;
   48         size_t need = 0;
   49         uint8_t *datap = (uint8_t *)data;
   50         uint8_t *blockp;
   51         uint8_t *lastp;
   52         void *iov_or_mp;
   53         offset_t offset;
   54         uint8_t *out_data_1;
   55         uint8_t *out_data_2;
   56         size_t out_data_1_len;
   57         uint64_t counter;
   58         uint8_t *mac_buf;
   59 
   60         if (length + ctx->ccm_remainder_len < block_size) {
   61                 /* accumulate bytes here and return */
   62                 memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
   63                     datap,
   64                     length);
   65                 ctx->ccm_remainder_len += length;
   66                 ctx->ccm_copy_to = datap;
   67                 return (CRYPTO_SUCCESS);
   68         }
   69 
   70         crypto_init_ptrs(out, &iov_or_mp, &offset);
   71 
   72         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
   73 
   74         do {
   75                 /* Unprocessed data from last call. */
   76                 if (ctx->ccm_remainder_len > 0) {
   77                         need = block_size - ctx->ccm_remainder_len;
   78 
   79                         if (need > remainder)
   80                                 return (CRYPTO_DATA_LEN_RANGE);
   81 
   82                         memcpy(&((uint8_t *)ctx->ccm_remainder)
   83                             [ctx->ccm_remainder_len], datap, need);
   84 
   85                         blockp = (uint8_t *)ctx->ccm_remainder;
   86                 } else {
   87                         blockp = datap;
   88                 }
   89 
   90                 /*
   91                  * do CBC MAC
   92                  *
   93                  * XOR the previous cipher block current clear block.
   94                  * mac_buf always contain previous cipher block.
   95                  */
   96                 xor_block(blockp, mac_buf);
   97                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
   98 
   99                 /* ccm_cb is the counter block */
  100                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb,
  101                     (uint8_t *)ctx->ccm_tmp);
  102 
  103                 lastp = (uint8_t *)ctx->ccm_tmp;
  104 
  105                 /*
  106                  * Increment counter. Counter bits are confined
  107                  * to the bottom 64 bits of the counter block.
  108                  */
  109 #ifdef _ZFS_LITTLE_ENDIAN
  110                 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
  111                 counter = htonll(counter + 1);
  112 #else
  113                 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
  114                 counter++;
  115 #endif  /* _ZFS_LITTLE_ENDIAN */
  116                 counter &= ctx->ccm_counter_mask;
  117                 ctx->ccm_cb[1] =
  118                     (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
  119 
  120                 /*
  121                  * XOR encrypted counter block with the current clear block.
  122                  */
  123                 xor_block(blockp, lastp);
  124 
  125                 ctx->ccm_processed_data_len += block_size;
  126 
  127                 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
  128                     &out_data_1_len, &out_data_2, block_size);
  129 
  130                 /* copy block to where it belongs */
  131                 if (out_data_1_len == block_size) {
  132                         copy_block(lastp, out_data_1);
  133                 } else {
  134                         memcpy(out_data_1, lastp, out_data_1_len);
  135                         if (out_data_2 != NULL) {
  136                                 memcpy(out_data_2,
  137                                     lastp + out_data_1_len,
  138                                     block_size - out_data_1_len);
  139                         }
  140                 }
  141                 /* update offset */
  142                 out->cd_offset += block_size;
  143 
  144                 /* Update pointer to next block of data to be processed. */
  145                 if (ctx->ccm_remainder_len != 0) {
  146                         datap += need;
  147                         ctx->ccm_remainder_len = 0;
  148                 } else {
  149                         datap += block_size;
  150                 }
  151 
  152                 remainder = (size_t)&data[length] - (size_t)datap;
  153 
  154                 /* Incomplete last block. */
  155                 if (remainder > 0 && remainder < block_size) {
  156                         memcpy(ctx->ccm_remainder, datap, remainder);
  157                         ctx->ccm_remainder_len = remainder;
  158                         ctx->ccm_copy_to = datap;
  159                         goto out;
  160                 }
  161                 ctx->ccm_copy_to = NULL;
  162 
  163         } while (remainder > 0);
  164 
  165 out:
  166         return (CRYPTO_SUCCESS);
  167 }
  168 
  169 void
  170 calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac,
  171     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
  172 {
  173         uint64_t counter;
  174         uint8_t *counterp, *mac_buf;
  175         int i;
  176 
  177         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
  178 
  179         /* first counter block start with index 0 */
  180         counter = 0;
  181         ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
  182 
  183         counterp = (uint8_t *)ctx->ccm_tmp;
  184         encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
  185 
  186         /* calculate XOR of MAC with first counter block */
  187         for (i = 0; i < ctx->ccm_mac_len; i++) {
  188                 ccm_mac[i] = mac_buf[i] ^ counterp[i];
  189         }
  190 }
  191 
  192 int
  193 ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
  194     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
  195     void (*xor_block)(uint8_t *, uint8_t *))
  196 {
  197         uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp = NULL;
  198         void *iov_or_mp;
  199         offset_t offset;
  200         uint8_t *out_data_1;
  201         uint8_t *out_data_2;
  202         size_t out_data_1_len;
  203         int i;
  204 
  205         if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) {
  206                 return (CRYPTO_DATA_LEN_RANGE);
  207         }
  208 
  209         /*
  210          * When we get here, the number of bytes of payload processed
  211          * plus whatever data remains, if any,
  212          * should be the same as the number of bytes that's being
  213          * passed in the argument during init time.
  214          */
  215         if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len)
  216             != (ctx->ccm_data_len)) {
  217                 return (CRYPTO_DATA_LEN_RANGE);
  218         }
  219 
  220         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
  221 
  222         if (ctx->ccm_remainder_len > 0) {
  223 
  224                 /* ccm_mac_input_buf is not used for encryption */
  225                 macp = (uint8_t *)ctx->ccm_mac_input_buf;
  226                 memset(macp, 0, block_size);
  227 
  228                 /* copy remainder to temporary buffer */
  229                 memcpy(macp, ctx->ccm_remainder, ctx->ccm_remainder_len);
  230 
  231                 /* calculate the CBC MAC */
  232                 xor_block(macp, mac_buf);
  233                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
  234 
  235                 /* calculate the counter mode */
  236                 lastp = (uint8_t *)ctx->ccm_tmp;
  237                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp);
  238 
  239                 /* XOR with counter block */
  240                 for (i = 0; i < ctx->ccm_remainder_len; i++) {
  241                         macp[i] ^= lastp[i];
  242                 }
  243                 ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
  244         }
  245 
  246         /* Calculate the CCM MAC */
  247         ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
  248         calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block);
  249 
  250         crypto_init_ptrs(out, &iov_or_mp, &offset);
  251         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
  252             &out_data_1_len, &out_data_2,
  253             ctx->ccm_remainder_len + ctx->ccm_mac_len);
  254 
  255         if (ctx->ccm_remainder_len > 0) {
  256                 /* copy temporary block to where it belongs */
  257                 if (out_data_2 == NULL) {
  258                         /* everything will fit in out_data_1 */
  259                         memcpy(out_data_1, macp, ctx->ccm_remainder_len);
  260                         memcpy(out_data_1 + ctx->ccm_remainder_len, ccm_mac_p,
  261                             ctx->ccm_mac_len);
  262                 } else {
  263                         if (out_data_1_len < ctx->ccm_remainder_len) {
  264                                 size_t data_2_len_used;
  265 
  266                                 memcpy(out_data_1, macp, out_data_1_len);
  267 
  268                                 data_2_len_used = ctx->ccm_remainder_len
  269                                     - out_data_1_len;
  270 
  271                                 memcpy(out_data_2,
  272                                     (uint8_t *)macp + out_data_1_len,
  273                                     data_2_len_used);
  274                                 memcpy(out_data_2 + data_2_len_used,
  275                                     ccm_mac_p,
  276                                     ctx->ccm_mac_len);
  277                         } else {
  278                                 memcpy(out_data_1, macp, out_data_1_len);
  279                                 if (out_data_1_len == ctx->ccm_remainder_len) {
  280                                         /* mac will be in out_data_2 */
  281                                         memcpy(out_data_2, ccm_mac_p,
  282                                             ctx->ccm_mac_len);
  283                                 } else {
  284                                         size_t len_not_used = out_data_1_len -
  285                                             ctx->ccm_remainder_len;
  286                                         /*
  287                                          * part of mac in will be in
  288                                          * out_data_1, part of the mac will be
  289                                          * in out_data_2
  290                                          */
  291                                         memcpy(out_data_1 +
  292                                             ctx->ccm_remainder_len,
  293                                             ccm_mac_p, len_not_used);
  294                                         memcpy(out_data_2,
  295                                             ccm_mac_p + len_not_used,
  296                                             ctx->ccm_mac_len - len_not_used);
  297 
  298                                 }
  299                         }
  300                 }
  301         } else {
  302                 /* copy block to where it belongs */
  303                 memcpy(out_data_1, ccm_mac_p, out_data_1_len);
  304                 if (out_data_2 != NULL) {
  305                         memcpy(out_data_2, ccm_mac_p + out_data_1_len,
  306                             block_size - out_data_1_len);
  307                 }
  308         }
  309         out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len;
  310         ctx->ccm_remainder_len = 0;
  311         return (CRYPTO_SUCCESS);
  312 }
  313 
  314 /*
  315  * This will only deal with decrypting the last block of the input that
  316  * might not be a multiple of block length.
  317  */
  318 static void
  319 ccm_decrypt_incomplete_block(ccm_ctx_t *ctx,
  320     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
  321 {
  322         uint8_t *datap, *outp, *counterp;
  323         int i;
  324 
  325         datap = (uint8_t *)ctx->ccm_remainder;
  326         outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]);
  327 
  328         counterp = (uint8_t *)ctx->ccm_tmp;
  329         encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
  330 
  331         /* XOR with counter block */
  332         for (i = 0; i < ctx->ccm_remainder_len; i++) {
  333                 outp[i] = datap[i] ^ counterp[i];
  334         }
  335 }
  336 
  337 /*
  338  * This will decrypt the cipher text.  However, the plaintext won't be
  339  * returned to the caller.  It will be returned when decrypt_final() is
  340  * called if the MAC matches
  341  */
  342 int
  343 ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
  344     crypto_data_t *out, size_t block_size,
  345     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
  346     void (*copy_block)(uint8_t *, uint8_t *),
  347     void (*xor_block)(uint8_t *, uint8_t *))
  348 {
  349         (void) out;
  350         size_t remainder = length;
  351         size_t need = 0;
  352         uint8_t *datap = (uint8_t *)data;
  353         uint8_t *blockp;
  354         uint8_t *cbp;
  355         uint64_t counter;
  356         size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len;
  357         uint8_t *resultp;
  358 
  359 
  360         pm_len = ctx->ccm_processed_mac_len;
  361 
  362         if (pm_len > 0) {
  363                 uint8_t *tmp;
  364                 /*
  365                  * all ciphertext has been processed, just waiting for
  366                  * part of the value of the mac
  367                  */
  368                 if ((pm_len + length) > ctx->ccm_mac_len) {
  369                         return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
  370                 }
  371                 tmp = (uint8_t *)ctx->ccm_mac_input_buf;
  372 
  373                 memcpy(tmp + pm_len, datap, length);
  374 
  375                 ctx->ccm_processed_mac_len += length;
  376                 return (CRYPTO_SUCCESS);
  377         }
  378 
  379         /*
  380          * If we decrypt the given data, what total amount of data would
  381          * have been decrypted?
  382          */
  383         pd_len = ctx->ccm_processed_data_len;
  384         total_decrypted_len = pd_len + length + ctx->ccm_remainder_len;
  385 
  386         if (total_decrypted_len >
  387             (ctx->ccm_data_len + ctx->ccm_mac_len)) {
  388                 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
  389         }
  390 
  391         pt_len = ctx->ccm_data_len;
  392 
  393         if (total_decrypted_len > pt_len) {
  394                 /*
  395                  * part of the input will be the MAC, need to isolate that
  396                  * to be dealt with later.  The left-over data in
  397                  * ccm_remainder_len from last time will not be part of the
  398                  * MAC.  Otherwise, it would have already been taken out
  399                  * when this call is made last time.
  400                  */
  401                 size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len;
  402 
  403                 mac_len = length - pt_part;
  404 
  405                 ctx->ccm_processed_mac_len = mac_len;
  406                 memcpy(ctx->ccm_mac_input_buf, data + pt_part, mac_len);
  407 
  408                 if (pt_part + ctx->ccm_remainder_len < block_size) {
  409                         /*
  410                          * since this is last of the ciphertext, will
  411                          * just decrypt with it here
  412                          */
  413                         memcpy(&((uint8_t *)ctx->ccm_remainder)
  414                             [ctx->ccm_remainder_len], datap, pt_part);
  415                         ctx->ccm_remainder_len += pt_part;
  416                         ccm_decrypt_incomplete_block(ctx, encrypt_block);
  417                         ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
  418                         ctx->ccm_remainder_len = 0;
  419                         return (CRYPTO_SUCCESS);
  420                 } else {
  421                         /* let rest of the code handle this */
  422                         length = pt_part;
  423                 }
  424         } else if (length + ctx->ccm_remainder_len < block_size) {
  425                 /* accumulate bytes here and return */
  426                 memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
  427                     datap,
  428                     length);
  429                 ctx->ccm_remainder_len += length;
  430                 ctx->ccm_copy_to = datap;
  431                 return (CRYPTO_SUCCESS);
  432         }
  433 
  434         do {
  435                 /* Unprocessed data from last call. */
  436                 if (ctx->ccm_remainder_len > 0) {
  437                         need = block_size - ctx->ccm_remainder_len;
  438 
  439                         if (need > remainder)
  440                                 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
  441 
  442                         memcpy(&((uint8_t *)ctx->ccm_remainder)
  443                             [ctx->ccm_remainder_len], datap, need);
  444 
  445                         blockp = (uint8_t *)ctx->ccm_remainder;
  446                 } else {
  447                         blockp = datap;
  448                 }
  449 
  450                 /* Calculate the counter mode, ccm_cb is the counter block */
  451                 cbp = (uint8_t *)ctx->ccm_tmp;
  452                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp);
  453 
  454                 /*
  455                  * Increment counter.
  456                  * Counter bits are confined to the bottom 64 bits
  457                  */
  458 #ifdef _ZFS_LITTLE_ENDIAN
  459                 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
  460                 counter = htonll(counter + 1);
  461 #else
  462                 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
  463                 counter++;
  464 #endif  /* _ZFS_LITTLE_ENDIAN */
  465                 counter &= ctx->ccm_counter_mask;
  466                 ctx->ccm_cb[1] =
  467                     (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
  468 
  469                 /* XOR with the ciphertext */
  470                 xor_block(blockp, cbp);
  471 
  472                 /* Copy the plaintext to the "holding buffer" */
  473                 resultp = (uint8_t *)ctx->ccm_pt_buf +
  474                     ctx->ccm_processed_data_len;
  475                 copy_block(cbp, resultp);
  476 
  477                 ctx->ccm_processed_data_len += block_size;
  478 
  479                 ctx->ccm_lastp = blockp;
  480 
  481                 /* Update pointer to next block of data to be processed. */
  482                 if (ctx->ccm_remainder_len != 0) {
  483                         datap += need;
  484                         ctx->ccm_remainder_len = 0;
  485                 } else {
  486                         datap += block_size;
  487                 }
  488 
  489                 remainder = (size_t)&data[length] - (size_t)datap;
  490 
  491                 /* Incomplete last block */
  492                 if (remainder > 0 && remainder < block_size) {
  493                         memcpy(ctx->ccm_remainder, datap, remainder);
  494                         ctx->ccm_remainder_len = remainder;
  495                         ctx->ccm_copy_to = datap;
  496                         if (ctx->ccm_processed_mac_len > 0) {
  497                                 /*
  498                                  * not expecting anymore ciphertext, just
  499                                  * compute plaintext for the remaining input
  500                                  */
  501                                 ccm_decrypt_incomplete_block(ctx,
  502                                     encrypt_block);
  503                                 ctx->ccm_processed_data_len += remainder;
  504                                 ctx->ccm_remainder_len = 0;
  505                         }
  506                         goto out;
  507                 }
  508                 ctx->ccm_copy_to = NULL;
  509 
  510         } while (remainder > 0);
  511 
  512 out:
  513         return (CRYPTO_SUCCESS);
  514 }
  515 
  516 int
  517 ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
  518     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
  519     void (*copy_block)(uint8_t *, uint8_t *),
  520     void (*xor_block)(uint8_t *, uint8_t *))
  521 {
  522         size_t mac_remain, pt_len;
  523         uint8_t *pt, *mac_buf, *macp, *ccm_mac_p;
  524         int rv;
  525 
  526         pt_len = ctx->ccm_data_len;
  527 
  528         /* Make sure output buffer can fit all of the plaintext */
  529         if (out->cd_length < pt_len) {
  530                 return (CRYPTO_DATA_LEN_RANGE);
  531         }
  532 
  533         pt = ctx->ccm_pt_buf;
  534         mac_remain = ctx->ccm_processed_data_len;
  535         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
  536 
  537         macp = (uint8_t *)ctx->ccm_tmp;
  538 
  539         while (mac_remain > 0) {
  540                 if (mac_remain < block_size) {
  541                         memset(macp, 0, block_size);
  542                         memcpy(macp, pt, mac_remain);
  543                         mac_remain = 0;
  544                 } else {
  545                         copy_block(pt, macp);
  546                         mac_remain -= block_size;
  547                         pt += block_size;
  548                 }
  549 
  550                 /* calculate the CBC MAC */
  551                 xor_block(macp, mac_buf);
  552                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
  553         }
  554 
  555         /* Calculate the CCM MAC */
  556         ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
  557         calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block);
  558 
  559         /* compare the input CCM MAC value with what we calculated */
  560         if (memcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) {
  561                 /* They don't match */
  562                 return (CRYPTO_INVALID_MAC);
  563         } else {
  564                 rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len);
  565                 if (rv != CRYPTO_SUCCESS)
  566                         return (rv);
  567                 out->cd_offset += pt_len;
  568         }
  569         return (CRYPTO_SUCCESS);
  570 }
  571 
  572 static int
  573 ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init)
  574 {
  575         size_t macSize, nonceSize;
  576         uint8_t q;
  577         uint64_t maxValue;
  578 
  579         /*
  580          * Check the length of the MAC.  The only valid
  581          * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
  582          */
  583         macSize = ccm_param->ulMACSize;
  584         if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) {
  585                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  586         }
  587 
  588         /* Check the nonce length.  Valid values are 7, 8, 9, 10, 11, 12, 13 */
  589         nonceSize = ccm_param->ulNonceSize;
  590         if ((nonceSize < 7) || (nonceSize > 13)) {
  591                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  592         }
  593 
  594         /* q is the length of the field storing the length, in bytes */
  595         q = (uint8_t)((15 - nonceSize) & 0xFF);
  596 
  597 
  598         /*
  599          * If it is decrypt, need to make sure size of ciphertext is at least
  600          * bigger than MAC len
  601          */
  602         if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) {
  603                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  604         }
  605 
  606         /*
  607          * Check to make sure the length of the payload is within the
  608          * range of values allowed by q
  609          */
  610         if (q < 8) {
  611                 maxValue = (1ULL << (q * 8)) - 1;
  612         } else {
  613                 maxValue = ULONG_MAX;
  614         }
  615 
  616         if (ccm_param->ulDataSize > maxValue) {
  617                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  618         }
  619         return (CRYPTO_SUCCESS);
  620 }
  621 
  622 /*
  623  * Format the first block used in CBC-MAC (B0) and the initial counter
  624  * block based on formatting functions and counter generation functions
  625  * specified in RFC 3610 and NIST publication 800-38C, appendix A
  626  *
  627  * b0 is the first block used in CBC-MAC
  628  * cb0 is the first counter block
  629  *
  630  * It's assumed that the arguments b0 and cb0 are preallocated AES blocks
  631  *
  632  */
  633 static void
  634 ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
  635     ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx)
  636 {
  637         uint64_t payloadSize;
  638         uint8_t t, q, have_adata = 0;
  639         size_t limit;
  640         int i, j, k;
  641         uint64_t mask = 0;
  642         uint8_t *cb;
  643 
  644         q = (uint8_t)((15 - nonceSize) & 0xFF);
  645         t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF);
  646 
  647         /* Construct the first octet of b0 */
  648         if (authDataSize > 0) {
  649                 have_adata = 1;
  650         }
  651         b0[0] = (have_adata << 6) | (((t - 2)  / 2) << 3) | (q - 1);
  652 
  653         /* copy the nonce value into b0 */
  654         memcpy(&(b0[1]), nonce, nonceSize);
  655 
  656         /* store the length of the payload into b0 */
  657         memset(&(b0[1+nonceSize]), 0, q);
  658 
  659         payloadSize = aes_ctx->ccm_data_len;
  660         limit = MIN(8, q);
  661 
  662         for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) {
  663                 b0[k] = (uint8_t)((payloadSize >> j) & 0xFF);
  664         }
  665 
  666         /* format the counter block */
  667 
  668         cb = (uint8_t *)aes_ctx->ccm_cb;
  669 
  670         cb[0] = 0x07 & (q-1); /* first byte */
  671 
  672         /* copy the nonce value into the counter block */
  673         memcpy(&(cb[1]), nonce, nonceSize);
  674 
  675         memset(&(cb[1+nonceSize]), 0, q);
  676 
  677         /* Create the mask for the counter field based on the size of nonce */
  678         q <<= 3;
  679         while (q-- > 0) {
  680                 mask |= (1ULL << q);
  681         }
  682 
  683 #ifdef _ZFS_LITTLE_ENDIAN
  684         mask = htonll(mask);
  685 #endif
  686         aes_ctx->ccm_counter_mask = mask;
  687 
  688         /*
  689          * During calculation, we start using counter block 1, we will
  690          * set it up right here.
  691          * We can just set the last byte to have the value 1, because
  692          * even with the biggest nonce of 13, the last byte of the
  693          * counter block will be used for the counter value.
  694          */
  695         cb[15] = 0x01;
  696 }
  697 
  698 /*
  699  * Encode the length of the associated data as
  700  * specified in RFC 3610 and NIST publication 800-38C, appendix A
  701  */
  702 static void
  703 encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len)
  704 {
  705 #ifdef UNALIGNED_POINTERS_PERMITTED
  706         uint32_t        *lencoded_ptr;
  707 #ifdef _LP64
  708         uint64_t        *llencoded_ptr;
  709 #endif
  710 #endif  /* UNALIGNED_POINTERS_PERMITTED */
  711 
  712         if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) {
  713                 /* 0 < a < (2^16-2^8) */
  714                 *encoded_len = 2;
  715                 encoded[0] = (auth_data_len & 0xff00) >> 8;
  716                 encoded[1] = auth_data_len & 0xff;
  717 
  718         } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) &&
  719             (auth_data_len < (1ULL << 31))) {
  720                 /* (2^16-2^8) <= a < 2^32 */
  721                 *encoded_len = 6;
  722                 encoded[0] = 0xff;
  723                 encoded[1] = 0xfe;
  724 #ifdef UNALIGNED_POINTERS_PERMITTED
  725                 lencoded_ptr = (uint32_t *)&encoded[2];
  726                 *lencoded_ptr = htonl(auth_data_len);
  727 #else
  728                 encoded[2] = (auth_data_len & 0xff000000) >> 24;
  729                 encoded[3] = (auth_data_len & 0xff0000) >> 16;
  730                 encoded[4] = (auth_data_len & 0xff00) >> 8;
  731                 encoded[5] = auth_data_len & 0xff;
  732 #endif  /* UNALIGNED_POINTERS_PERMITTED */
  733 
  734 #ifdef _LP64
  735         } else {
  736                 /* 2^32 <= a < 2^64 */
  737                 *encoded_len = 10;
  738                 encoded[0] = 0xff;
  739                 encoded[1] = 0xff;
  740 #ifdef UNALIGNED_POINTERS_PERMITTED
  741                 llencoded_ptr = (uint64_t *)&encoded[2];
  742                 *llencoded_ptr = htonl(auth_data_len);
  743 #else
  744                 encoded[2] = (auth_data_len & 0xff00000000000000) >> 56;
  745                 encoded[3] = (auth_data_len & 0xff000000000000) >> 48;
  746                 encoded[4] = (auth_data_len & 0xff0000000000) >> 40;
  747                 encoded[5] = (auth_data_len & 0xff00000000) >> 32;
  748                 encoded[6] = (auth_data_len & 0xff000000) >> 24;
  749                 encoded[7] = (auth_data_len & 0xff0000) >> 16;
  750                 encoded[8] = (auth_data_len & 0xff00) >> 8;
  751                 encoded[9] = auth_data_len & 0xff;
  752 #endif  /* UNALIGNED_POINTERS_PERMITTED */
  753 #endif  /* _LP64 */
  754         }
  755 }
  756 
  757 static int
  758 ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len,
  759     unsigned char *auth_data, size_t auth_data_len, size_t block_size,
  760     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
  761     void (*xor_block)(uint8_t *, uint8_t *))
  762 {
  763         uint8_t *mac_buf, *datap, *ivp, *authp;
  764         size_t remainder, processed;
  765         uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */
  766         size_t encoded_a_len = 0;
  767 
  768         mac_buf = (uint8_t *)&(ctx->ccm_mac_buf);
  769 
  770         /*
  771          * Format the 1st block for CBC-MAC and construct the
  772          * 1st counter block.
  773          *
  774          * aes_ctx->ccm_iv is used for storing the counter block
  775          * mac_buf will store b0 at this time.
  776          */
  777         ccm_format_initial_blocks(nonce, nonce_len,
  778             auth_data_len, mac_buf, ctx);
  779 
  780         /* The IV for CBC MAC for AES CCM mode is always zero */
  781         ivp = (uint8_t *)ctx->ccm_tmp;
  782         memset(ivp, 0, block_size);
  783 
  784         xor_block(ivp, mac_buf);
  785 
  786         /* encrypt the nonce */
  787         encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
  788 
  789         /* take care of the associated data, if any */
  790         if (auth_data_len == 0) {
  791                 return (CRYPTO_SUCCESS);
  792         }
  793 
  794         encode_adata_len(auth_data_len, encoded_a, &encoded_a_len);
  795 
  796         remainder = auth_data_len;
  797 
  798         /* 1st block: it contains encoded associated data, and some data */
  799         authp = (uint8_t *)ctx->ccm_tmp;
  800         memset(authp, 0, block_size);
  801         memcpy(authp, encoded_a, encoded_a_len);
  802         processed = block_size - encoded_a_len;
  803         if (processed > auth_data_len) {
  804                 /* in case auth_data is very small */
  805                 processed = auth_data_len;
  806         }
  807         memcpy(authp+encoded_a_len, auth_data, processed);
  808         /* xor with previous buffer */
  809         xor_block(authp, mac_buf);
  810         encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
  811         remainder -= processed;
  812         if (remainder == 0) {
  813                 /* a small amount of associated data, it's all done now */
  814                 return (CRYPTO_SUCCESS);
  815         }
  816 
  817         do {
  818                 if (remainder < block_size) {
  819                         /*
  820                          * There's not a block full of data, pad rest of
  821                          * buffer with zero
  822                          */
  823                         memset(authp, 0, block_size);
  824                         memcpy(authp, &(auth_data[processed]), remainder);
  825                         datap = (uint8_t *)authp;
  826                         remainder = 0;
  827                 } else {
  828                         datap = (uint8_t *)(&(auth_data[processed]));
  829                         processed += block_size;
  830                         remainder -= block_size;
  831                 }
  832 
  833                 xor_block(datap, mac_buf);
  834                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
  835 
  836         } while (remainder > 0);
  837 
  838         return (CRYPTO_SUCCESS);
  839 }
  840 
  841 /*
  842  * The following function should be call at encrypt or decrypt init time
  843  * for AES CCM mode.
  844  */
  845 int
  846 ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag,
  847     boolean_t is_encrypt_init, size_t block_size,
  848     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
  849     void (*xor_block)(uint8_t *, uint8_t *))
  850 {
  851         int rv;
  852         CK_AES_CCM_PARAMS *ccm_param;
  853 
  854         if (param != NULL) {
  855                 ccm_param = (CK_AES_CCM_PARAMS *)param;
  856 
  857                 if ((rv = ccm_validate_args(ccm_param,
  858                     is_encrypt_init)) != 0) {
  859                         return (rv);
  860                 }
  861 
  862                 ccm_ctx->ccm_mac_len = ccm_param->ulMACSize;
  863                 if (is_encrypt_init) {
  864                         ccm_ctx->ccm_data_len = ccm_param->ulDataSize;
  865                 } else {
  866                         ccm_ctx->ccm_data_len =
  867                             ccm_param->ulDataSize - ccm_ctx->ccm_mac_len;
  868                         ccm_ctx->ccm_processed_mac_len = 0;
  869                 }
  870                 ccm_ctx->ccm_processed_data_len = 0;
  871 
  872                 ccm_ctx->ccm_flags |= CCM_MODE;
  873         } else {
  874                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  875         }
  876 
  877         if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize,
  878             ccm_param->authData, ccm_param->ulAuthDataSize, block_size,
  879             encrypt_block, xor_block) != 0) {
  880                 return (CRYPTO_MECHANISM_PARAM_INVALID);
  881         }
  882         if (!is_encrypt_init) {
  883                 /* allocate buffer for storing decrypted plaintext */
  884                 ccm_ctx->ccm_pt_buf = vmem_alloc(ccm_ctx->ccm_data_len,
  885                     kmflag);
  886                 if (ccm_ctx->ccm_pt_buf == NULL) {
  887                         rv = CRYPTO_HOST_MEMORY;
  888                 }
  889         }
  890         return (rv);
  891 }
  892 
  893 void *
  894 ccm_alloc_ctx(int kmflag)
  895 {
  896         ccm_ctx_t *ccm_ctx;
  897 
  898         if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL)
  899                 return (NULL);
  900 
  901         ccm_ctx->ccm_flags = CCM_MODE;
  902         return (ccm_ctx);
  903 }

Cache object: bf3a5eec51948c218f9df4f67c909e80


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