Print this page
    
4896 Performance improvements for KCF AES modes
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/crypto/io/blowfish.c
          +++ new/usr/src/uts/common/crypto/io/blowfish.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  
    | ↓ open down ↓ | 14 lines elided | ↑ open up ↑ | 
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
       25 +/*
       26 + * Copyright 2015 by Saso Kiselkov. All rights reserved.
       27 + */
  25   28  
  26   29  /*
  27   30   * Blowfish provider for the Kernel Cryptographic Framework (KCF)
  28   31   */
  29   32  
  30   33  #include <sys/types.h>
  31   34  #include <sys/systm.h>
  32   35  #include <sys/modctl.h>
  33   36  #include <sys/cmn_err.h>
  34   37  #include <sys/ddi.h>
  35   38  #include <sys/crypto/common.h>
  36   39  #include <sys/crypto/spi.h>
  37   40  #include <sys/sysmacros.h>
  38   41  #include <sys/strsun.h>
  39   42  #include <sys/note.h>
  40   43  #include <modes/modes.h>
  41   44  #include <blowfish/blowfish_impl.h>
  42   45  
  43   46  extern struct mod_ops mod_cryptoops;
  44   47  
  45   48  /*
  46   49   * Module linkage information for the kernel.
  47   50   */
  48   51  static struct modlcrypto modlcrypto = {
  49   52          &mod_cryptoops,
  50   53          "Blowfish Kernel SW Provider"
  51   54  };
  52   55  
  53   56  static struct modlinkage modlinkage = {
  54   57          MODREV_1,
  55   58          (void *)&modlcrypto,
  56   59          NULL
  57   60  };
  58   61  
  59   62  /*
  60   63   * CSPI information (entry points, provider info, etc.)
  61   64   */
  62   65  typedef enum blowfish_mech_type {
  63   66          BLOWFISH_ECB_MECH_INFO_TYPE,            /* SUN_CKM_BLOWFISH_ECB */
  64   67          BLOWFISH_CBC_MECH_INFO_TYPE             /* SUN_CKM_BLOWFISH_CBC */
  65   68  } blowfish_mech_type_t;
  66   69  
  67   70  
  68   71  #define BLOWFISH_COPY_BLOCK(src, dst) \
  69   72          (dst)[0] = (src)[0]; \
  70   73          (dst)[1] = (src)[1]; \
  71   74          (dst)[2] = (src)[2]; \
  72   75          (dst)[3] = (src)[3]; \
  73   76          (dst)[4] = (src)[4]; \
  74   77          (dst)[5] = (src)[5]; \
  75   78          (dst)[6] = (src)[6]; \
  76   79          (dst)[7] = (src)[7]
  77   80  
  78   81  #define BLOWFISH_XOR_BLOCK(src, dst) \
  79   82          (dst)[0] ^= (src)[0]; \
  80   83          (dst)[1] ^= (src)[1]; \
  81   84          (dst)[2] ^= (src)[2]; \
  82   85          (dst)[3] ^= (src)[3]; \
  83   86          (dst)[4] ^= (src)[4]; \
  84   87          (dst)[5] ^= (src)[5]; \
  85   88          (dst)[6] ^= (src)[6]; \
  86   89          (dst)[7] ^= (src)[7]
  87   90  
  88   91  /*
  89   92   * Mechanism info structure passed to KCF during registration.
  90   93   */
  91   94  
  92   95  static crypto_mech_info_t blowfish_mech_info_tab[] = {
  93   96          /* BLOWFISH_ECB */
  94   97          {SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE,
  95   98              CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
  96   99              CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
  97  100              BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS},
  98  101          /* BLOWFISH_CBC */
  99  102          {SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE,
 100  103              CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 101  104              CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
 102  105              BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}
 103  106  };
 104  107  
 105  108  #define BLOWFISH_VALID_MECH(mech)                               \
 106  109          (((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE ||             \
 107  110          (mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0)
 108  111  
 109  112  /* operations are in-place if the output buffer is NULL */
 110  113  #define BLOWFISH_ARG_INPLACE(input, output)                     \
 111  114          if ((output) == NULL)                                   \
 112  115                  (output) = (input);
 113  116  
 114  117  static void blowfish_provider_status(crypto_provider_handle_t, uint_t *);
 115  118  
 116  119  static crypto_control_ops_t blowfish_control_ops = {
 117  120          blowfish_provider_status
 118  121  };
 119  122  
 120  123  static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *,
 121  124      crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 122  125  static int blowfish_common_init_ctx(blowfish_ctx_t *,
 123  126      crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int);
 124  127  static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *,
 125  128      crypto_req_handle_t);
 126  129  static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *,
 127  130      crypto_req_handle_t);
 128  131  
 129  132  static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 130  133      crypto_req_handle_t);
 131  134  static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *,
 132  135      crypto_data_t *, crypto_req_handle_t);
 133  136  static int blowfish_encrypt_atomic(crypto_provider_handle_t,
 134  137      crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 135  138      crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 136  139  
 137  140  static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 138  141      crypto_req_handle_t);
 139  142  static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *,
 140  143      crypto_data_t *, crypto_req_handle_t);
 141  144  static int blowfish_decrypt_atomic(crypto_provider_handle_t,
 142  145      crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 143  146      crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 144  147  
 145  148  static crypto_cipher_ops_t blowfish_cipher_ops = {
 146  149          blowfish_common_init,
 147  150          blowfish_encrypt,
 148  151          blowfish_encrypt_update,
 149  152          blowfish_encrypt_final,
 150  153          blowfish_encrypt_atomic,
 151  154          blowfish_common_init,
 152  155          blowfish_decrypt,
 153  156          blowfish_decrypt_update,
 154  157          blowfish_decrypt_final,
 155  158          blowfish_decrypt_atomic
 156  159  };
 157  160  
 158  161  static int blowfish_create_ctx_template(crypto_provider_handle_t,
 159  162      crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
 160  163      size_t *, crypto_req_handle_t);
 161  164  static int blowfish_free_context(crypto_ctx_t *);
 162  165  
 163  166  static crypto_ctx_ops_t blowfish_ctx_ops = {
 164  167          blowfish_create_ctx_template,
 165  168          blowfish_free_context
 166  169  };
 167  170  
 168  171  static crypto_ops_t blowfish_crypto_ops = {
 169  172          &blowfish_control_ops,
 170  173          NULL,
 171  174          &blowfish_cipher_ops,
 172  175          NULL,
 173  176          NULL,
 174  177          NULL,
 175  178          NULL,
 176  179          NULL,
 177  180          NULL,
 178  181          NULL,
 179  182          NULL,
 180  183          NULL,
 181  184          NULL,
 182  185          &blowfish_ctx_ops
 183  186  };
 184  187  
 185  188  static crypto_provider_info_t blowfish_prov_info = {
 186  189          CRYPTO_SPI_VERSION_1,
 187  190          "Blowfish Software Provider",
 188  191          CRYPTO_SW_PROVIDER,
 189  192          {&modlinkage},
 190  193          NULL,
 191  194          &blowfish_crypto_ops,
 192  195          sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t),
 193  196          blowfish_mech_info_tab
 194  197  };
 195  198  
 196  199  
 197  200  static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL;
 198  201  
 199  202  int
 200  203  _init(void)
 201  204  {
 202  205          int ret;
 203  206  
 204  207          if ((ret = mod_install(&modlinkage)) != 0)
 205  208                  return (ret);
 206  209  
 207  210          /* Register with KCF.  If the registration fails, remove the module. */
 208  211          if (crypto_register_provider(&blowfish_prov_info,
 209  212              &blowfish_prov_handle)) {
 210  213                  (void) mod_remove(&modlinkage);
 211  214                  return (EACCES);
 212  215          }
 213  216  
 214  217          return (0);
 215  218  }
 216  219  
 217  220  int
 218  221  _fini(void)
 219  222  {
 220  223          /* Unregister from KCF if module is registered */
 221  224          if (blowfish_prov_handle != NULL) {
 222  225                  if (crypto_unregister_provider(blowfish_prov_handle))
 223  226                          return (EBUSY);
 224  227  
 225  228                  blowfish_prov_handle = NULL;
 226  229          }
 227  230  
 228  231          return (mod_remove(&modlinkage));
 229  232  }
 230  233  
 231  234  int
 232  235  _info(struct modinfo *modinfop)
 233  236  {
 234  237          return (mod_info(&modlinkage, modinfop));
 235  238  }
 236  239  
 237  240  /*
 238  241   * Initialize key schedules for blowfish
 239  242   */
 240  243  static int
 241  244  init_keysched(crypto_key_t *key, void *keysched)
 242  245  {
 243  246          /*
 244  247           * Only keys by value are supported by this module.
 245  248           */
 246  249          switch (key->ck_format) {
 247  250          case CRYPTO_KEY_RAW:
 248  251                  if (key->ck_length < BLOWFISH_MINBITS ||
 249  252                      key->ck_length > BLOWFISH_MAXBITS) {
 250  253                          return (CRYPTO_KEY_SIZE_RANGE);
 251  254                  }
 252  255                  break;
 253  256          default:
 254  257                  return (CRYPTO_KEY_TYPE_INCONSISTENT);
 255  258          }
 256  259  
 257  260          blowfish_init_keysched(key->ck_data, key->ck_length, keysched);
 258  261          return (CRYPTO_SUCCESS);
 259  262  }
 260  263  
 261  264  /*
 262  265   * KCF software provider control entry points.
 263  266   */
 264  267  /* ARGSUSED */
 265  268  static void
 266  269  blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status)
 267  270  {
 268  271          *status = CRYPTO_PROVIDER_READY;
 269  272  }
 270  273  
 271  274  /*
 272  275   * KCF software provider encrypt entry points.
 273  276   */
 274  277  static int
 275  278  blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 276  279      crypto_key_t *key, crypto_spi_ctx_template_t template,
 277  280      crypto_req_handle_t req)
 278  281  {
 279  282          blowfish_ctx_t *blowfish_ctx;
 280  283          int rv;
 281  284          int kmflag;
 282  285  
 283  286          /*
 284  287           * Only keys by value are supported by this module.
 285  288           */
 286  289          if (key->ck_format != CRYPTO_KEY_RAW) {
 287  290                  return (CRYPTO_KEY_TYPE_INCONSISTENT);
 288  291          }
 289  292  
 290  293          if (!BLOWFISH_VALID_MECH(mechanism))
 291  294                  return (CRYPTO_MECHANISM_INVALID);
 292  295  
 293  296          if (mechanism->cm_param != NULL &&
 294  297              mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
 295  298                  return (CRYPTO_MECHANISM_PARAM_INVALID);
 296  299  
 297  300          kmflag = crypto_kmflag(req);
 298  301          switch (mechanism->cm_type) {
 299  302          case BLOWFISH_ECB_MECH_INFO_TYPE:
 300  303                  blowfish_ctx = ecb_alloc_ctx(kmflag);
 301  304                  break;
 302  305          case BLOWFISH_CBC_MECH_INFO_TYPE:
 303  306                  blowfish_ctx = cbc_alloc_ctx(kmflag);
 304  307                  break;
 305  308          }
 306  309          if (blowfish_ctx == NULL)
 307  310                  return (CRYPTO_HOST_MEMORY);
 308  311  
 309  312          rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
 310  313              key, kmflag);
 311  314          if (rv != CRYPTO_SUCCESS) {
  
    | ↓ open down ↓ | 277 lines elided | ↑ open up ↑ | 
 312  315                  crypto_free_mode_ctx(blowfish_ctx);
 313  316                  return (rv);
 314  317          }
 315  318  
 316  319          ctx->cc_provider_private = blowfish_ctx;
 317  320  
 318  321          return (CRYPTO_SUCCESS);
 319  322  }
 320  323  
 321  324  static void
 322      -blowfish_copy_block64(uint8_t *in, uint64_t *out)
      325 +blowfish_copy_block64(const uint8_t *in, uint64_t *out)
 323  326  {
 324  327          if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
 325  328                  /* LINTED: pointer alignment */
 326  329                  out[0] = *(uint64_t *)&in[0];
 327  330          } else {
 328  331                  uint8_t *iv8 = (uint8_t *)&out[0];
 329  332  
 330  333                  BLOWFISH_COPY_BLOCK(in, iv8);
 331  334          }
 332  335  }
 333  336  
 334  337  /* ARGSUSED */
 335  338  static int
 336  339  blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
 337  340      crypto_data_t *ciphertext, crypto_req_handle_t req)
 338  341  {
 339  342          int ret;
 340  343  
 341  344          blowfish_ctx_t *blowfish_ctx;
 342  345  
 343  346          /*
 344  347           * Plaintext must be a multiple of blowfish block size.
 345  348           * This test only works for non-padded mechanisms
 346  349           * when blocksize is 2^N.
 347  350           */
 348  351          if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
 349  352                  return (CRYPTO_DATA_LEN_RANGE);
 350  353  
 351  354          ASSERT(ctx->cc_provider_private != NULL);
 352  355          blowfish_ctx = ctx->cc_provider_private;
 353  356  
 354  357          BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
 355  358  
 356  359          /*
 357  360           * We need to just return the length needed to store the output.
 358  361           * We should not destroy the context for the following case.
 359  362           */
 360  363          if (ciphertext->cd_length < plaintext->cd_length) {
 361  364                  ciphertext->cd_length = plaintext->cd_length;
 362  365                  return (CRYPTO_BUFFER_TOO_SMALL);
 363  366          }
 364  367  
 365  368          /*
 366  369           * Do an update on the specified input data.
 367  370           */
 368  371          ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
 369  372          ASSERT(blowfish_ctx->bc_remainder_len  == 0);
 370  373          (void) blowfish_free_context(ctx);
 371  374  
 372  375          /* LINTED */
 373  376          return (ret);
 374  377  }
 375  378  
 376  379  /* ARGSUSED */
 377  380  static int
 378  381  blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
 379  382      crypto_data_t *plaintext, crypto_req_handle_t req)
 380  383  {
 381  384          int ret;
 382  385  
 383  386          blowfish_ctx_t *blowfish_ctx;
 384  387  
 385  388          /*
 386  389           * Ciphertext must be a multiple of blowfish block size.
 387  390           * This test only works for non-padded mechanisms
 388  391           * when blocksize is 2^N.
 389  392           */
 390  393          if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
 391  394                  return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
 392  395  
 393  396          ASSERT(ctx->cc_provider_private != NULL);
 394  397          blowfish_ctx = ctx->cc_provider_private;
 395  398  
 396  399          BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
 397  400  
 398  401          /*
 399  402           * We need to just return the length needed to store the output.
 400  403           * We should not destroy the context for the following case.
 401  404           */
 402  405          if (plaintext->cd_length < ciphertext->cd_length) {
 403  406                  plaintext->cd_length = ciphertext->cd_length;
 404  407                  return (CRYPTO_BUFFER_TOO_SMALL);
 405  408          }
 406  409  
 407  410          /*
 408  411           * Do an update on the specified input data.
 409  412           */
 410  413          ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req);
 411  414          ASSERT(blowfish_ctx->bc_remainder_len == 0);
 412  415          (void) blowfish_free_context(ctx);
 413  416  
 414  417          /* LINTED */
 415  418          return (ret);
 416  419  }
 417  420  
 418  421  /* ARGSUSED */
 419  422  static int
 420  423  blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
 421  424      crypto_data_t *ciphertext, crypto_req_handle_t req)
 422  425  {
 423  426          off_t saved_offset;
 424  427          size_t saved_length, out_len;
 425  428          int ret = CRYPTO_SUCCESS;
 426  429  
 427  430          ASSERT(ctx->cc_provider_private != NULL);
 428  431  
 429  432          BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
 430  433  
 431  434          /* compute number of bytes that will hold the ciphertext */
 432  435          out_len =
 433  436              ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
 434  437          out_len += plaintext->cd_length;
 435  438          out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
 436  439  
 437  440          /* return length needed to store the output */
 438  441          if (ciphertext->cd_length < out_len) {
 439  442                  ciphertext->cd_length = out_len;
 440  443                  return (CRYPTO_BUFFER_TOO_SMALL);
 441  444          }
 442  445  
 443  446          saved_offset = ciphertext->cd_offset;
 444  447          saved_length = ciphertext->cd_length;
 445  448  
 446  449          /*
 447  450           * Do the blowfish update on the specified input data.
 448  451           */
 449  452          switch (plaintext->cd_format) {
 450  453          case CRYPTO_DATA_RAW:
 451  454                  ret = crypto_update_iov(ctx->cc_provider_private,
 452  455                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 453  456                      blowfish_copy_block64);
 454  457                  break;
 455  458          case CRYPTO_DATA_UIO:
 456  459                  ret = crypto_update_uio(ctx->cc_provider_private,
 457  460                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 458  461                      blowfish_copy_block64);
 459  462                  break;
 460  463          case CRYPTO_DATA_MBLK:
 461  464                  ret = crypto_update_mp(ctx->cc_provider_private,
 462  465                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 463  466                      blowfish_copy_block64);
 464  467                  break;
 465  468          default:
 466  469                  ret = CRYPTO_ARGUMENTS_BAD;
 467  470          }
 468  471  
 469  472          if (ret == CRYPTO_SUCCESS) {
 470  473                  if (plaintext != ciphertext)
 471  474                          ciphertext->cd_length =
 472  475                              ciphertext->cd_offset - saved_offset;
 473  476          } else {
 474  477                  ciphertext->cd_length = saved_length;
 475  478          }
 476  479          ciphertext->cd_offset = saved_offset;
 477  480  
 478  481          return (ret);
 479  482  }
 480  483  
 481  484  /* ARGSUSED */
 482  485  static int
 483  486  blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
 484  487      crypto_data_t *plaintext, crypto_req_handle_t req)
 485  488  {
 486  489          off_t saved_offset;
 487  490          size_t saved_length, out_len;
 488  491          int ret = CRYPTO_SUCCESS;
 489  492  
 490  493          ASSERT(ctx->cc_provider_private != NULL);
 491  494  
 492  495          BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
 493  496  
 494  497          /* compute number of bytes that will hold the plaintext */
 495  498          out_len =
 496  499              ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
 497  500          out_len += ciphertext->cd_length;
 498  501          out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
 499  502  
 500  503          /* return length needed to store the output */
 501  504          if (plaintext->cd_length < out_len) {
 502  505                  plaintext->cd_length = out_len;
 503  506                  return (CRYPTO_BUFFER_TOO_SMALL);
 504  507          }
 505  508  
 506  509          saved_offset = plaintext->cd_offset;
 507  510          saved_length = plaintext->cd_length;
 508  511  
 509  512          /*
 510  513           * Do the blowfish update on the specified input data.
 511  514           */
 512  515          switch (ciphertext->cd_format) {
 513  516          case CRYPTO_DATA_RAW:
 514  517                  ret = crypto_update_iov(ctx->cc_provider_private,
 515  518                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 516  519                      blowfish_copy_block64);
 517  520                  break;
 518  521          case CRYPTO_DATA_UIO:
 519  522                  ret = crypto_update_uio(ctx->cc_provider_private,
 520  523                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 521  524                      blowfish_copy_block64);
 522  525                  break;
 523  526          case CRYPTO_DATA_MBLK:
 524  527                  ret = crypto_update_mp(ctx->cc_provider_private,
 525  528                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 526  529                      blowfish_copy_block64);
 527  530                  break;
 528  531          default:
 529  532                  ret = CRYPTO_ARGUMENTS_BAD;
 530  533          }
 531  534  
 532  535          if (ret == CRYPTO_SUCCESS) {
 533  536                  if (ciphertext != plaintext)
 534  537                          plaintext->cd_length =
 535  538                              plaintext->cd_offset - saved_offset;
 536  539          } else {
 537  540                  plaintext->cd_length = saved_length;
 538  541          }
 539  542          plaintext->cd_offset = saved_offset;
 540  543  
 541  544          return (ret);
 542  545  }
 543  546  
 544  547  /* ARGSUSED */
 545  548  static int
 546  549  blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
 547  550      crypto_req_handle_t req)
 548  551  {
 549  552          blowfish_ctx_t *blowfish_ctx;
 550  553  
 551  554          ASSERT(ctx->cc_provider_private != NULL);
 552  555          blowfish_ctx = ctx->cc_provider_private;
 553  556  
 554  557          /*
 555  558           * There must be no unprocessed data.
 556  559           * This happens if the length of the last data is
 557  560           * not a multiple of the BLOWFISH block length.
 558  561           */
 559  562          if (blowfish_ctx->bc_remainder_len > 0)
 560  563                  return (CRYPTO_DATA_LEN_RANGE);
 561  564  
 562  565          (void) blowfish_free_context(ctx);
 563  566          data->cd_length = 0;
 564  567  
 565  568          return (CRYPTO_SUCCESS);
 566  569  }
 567  570  
 568  571  /* ARGSUSED */
 569  572  static int
 570  573  blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
 571  574      crypto_req_handle_t req)
 572  575  {
 573  576          blowfish_ctx_t *blowfish_ctx;
 574  577  
 575  578          ASSERT(ctx->cc_provider_private != NULL);
 576  579          blowfish_ctx = ctx->cc_provider_private;
 577  580  
 578  581          /*
 579  582           * There must be no unprocessed ciphertext.
 580  583           * This happens if the length of the last ciphertext is
 581  584           * not a multiple of the BLOWFISH block length.
 582  585           */
 583  586          if (blowfish_ctx->bc_remainder_len > 0)
 584  587                  return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
 585  588  
 586  589          (void) blowfish_free_context(ctx);
 587  590          data->cd_length = 0;
 588  591  
 589  592          return (CRYPTO_SUCCESS);
 590  593  }
 591  594  
 592  595  /* ARGSUSED */
 593  596  static int
 594  597  blowfish_encrypt_atomic(crypto_provider_handle_t provider,
 595  598      crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 596  599      crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
 597  600      crypto_spi_ctx_template_t template, crypto_req_handle_t req)
 598  601  {
 599  602          blowfish_ctx_t blowfish_ctx;    /* on the stack */
 600  603          off_t saved_offset;
 601  604          size_t saved_length;
 602  605          int ret;
 603  606  
 604  607          BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
 605  608  
 606  609          /*
 607  610           * Plaintext must be a multiple of blowfish block size.
 608  611           * This test only works for non-padded mechanisms
 609  612           * when blocksize is 2^N.
 610  613           */
 611  614          if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
 612  615                  return (CRYPTO_DATA_LEN_RANGE);
 613  616  
 614  617          /* return length needed to store the output */
 615  618          if (ciphertext->cd_length < plaintext->cd_length) {
 616  619                  ciphertext->cd_length = plaintext->cd_length;
 617  620                  return (CRYPTO_BUFFER_TOO_SMALL);
 618  621          }
 619  622  
 620  623          if (!BLOWFISH_VALID_MECH(mechanism))
 621  624                  return (CRYPTO_MECHANISM_INVALID);
 622  625  
 623  626          if (mechanism->cm_param_len != 0 &&
 624  627              mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
 625  628                  return (CRYPTO_MECHANISM_PARAM_INVALID);
 626  629  
 627  630          bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
 628  631  
 629  632          ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
 630  633              key, crypto_kmflag(req));
 631  634          if (ret != CRYPTO_SUCCESS)
 632  635                  return (ret);
 633  636  
 634  637          saved_offset = ciphertext->cd_offset;
 635  638          saved_length = ciphertext->cd_length;
 636  639  
 637  640          /*
 638  641           * Do an update on the specified input data.
 639  642           */
 640  643          switch (plaintext->cd_format) {
 641  644          case CRYPTO_DATA_RAW:
 642  645                  ret = crypto_update_iov(&blowfish_ctx,
 643  646                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 644  647                      blowfish_copy_block64);
 645  648                  break;
 646  649          case CRYPTO_DATA_UIO:
 647  650                  ret = crypto_update_uio(&blowfish_ctx,
 648  651                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 649  652                      blowfish_copy_block64);
 650  653                  break;
 651  654          case CRYPTO_DATA_MBLK:
 652  655                  ret = crypto_update_mp((void *)&blowfish_ctx,
 653  656                      plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
 654  657                      blowfish_copy_block64);
 655  658                  break;
 656  659          default:
 657  660                  ret = CRYPTO_ARGUMENTS_BAD;
 658  661          }
 659  662  
 660  663          if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
 661  664                  bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
 662  665                  kmem_free(blowfish_ctx.bc_keysched,
 663  666                      blowfish_ctx.bc_keysched_len);
 664  667          }
 665  668  
 666  669          if (ret == CRYPTO_SUCCESS) {
 667  670                  ASSERT(blowfish_ctx.bc_remainder_len == 0);
 668  671                  if (plaintext != ciphertext)
 669  672                          ciphertext->cd_length =
 670  673                              ciphertext->cd_offset - saved_offset;
 671  674          } else {
 672  675                  ciphertext->cd_length = saved_length;
 673  676          }
 674  677          ciphertext->cd_offset = saved_offset;
 675  678  
 676  679          return (ret);
 677  680  }
 678  681  
 679  682  /* ARGSUSED */
 680  683  static int
 681  684  blowfish_decrypt_atomic(crypto_provider_handle_t provider,
 682  685      crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 683  686      crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
 684  687      crypto_spi_ctx_template_t template, crypto_req_handle_t req)
 685  688  {
 686  689          blowfish_ctx_t blowfish_ctx;    /* on the stack */
 687  690          off_t saved_offset;
 688  691          size_t saved_length;
 689  692          int ret;
 690  693  
 691  694          BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
 692  695  
 693  696          /*
 694  697           * Ciphertext must be a multiple of blowfish block size.
 695  698           * This test only works for non-padded mechanisms
 696  699           * when blocksize is 2^N.
 697  700           */
 698  701          if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
 699  702                  return (CRYPTO_DATA_LEN_RANGE);
 700  703  
 701  704          /* return length needed to store the output */
 702  705          if (plaintext->cd_length < ciphertext->cd_length) {
 703  706                  plaintext->cd_length = ciphertext->cd_length;
 704  707                  return (CRYPTO_BUFFER_TOO_SMALL);
 705  708          }
 706  709  
 707  710          if (!BLOWFISH_VALID_MECH(mechanism))
 708  711                  return (CRYPTO_MECHANISM_INVALID);
 709  712  
 710  713          if (mechanism->cm_param_len != 0 &&
 711  714              mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
 712  715                  return (CRYPTO_MECHANISM_PARAM_INVALID);
 713  716  
 714  717          bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
 715  718  
 716  719          ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
 717  720              key, crypto_kmflag(req));
 718  721          if (ret != CRYPTO_SUCCESS)
 719  722                  return (ret);
 720  723  
 721  724          saved_offset = plaintext->cd_offset;
 722  725          saved_length = plaintext->cd_length;
 723  726  
 724  727          /*
 725  728           * Do an update on the specified input data.
 726  729           */
 727  730          switch (ciphertext->cd_format) {
 728  731          case CRYPTO_DATA_RAW:
 729  732                  ret = crypto_update_iov(&blowfish_ctx,
 730  733                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 731  734                      blowfish_copy_block64);
 732  735                  break;
 733  736          case CRYPTO_DATA_UIO:
 734  737                  ret = crypto_update_uio(&blowfish_ctx,
 735  738                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 736  739                      blowfish_copy_block64);
 737  740                  break;
 738  741          case CRYPTO_DATA_MBLK:
 739  742                  ret = crypto_update_mp(&blowfish_ctx,
 740  743                      ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
 741  744                      blowfish_copy_block64);
 742  745                  break;
 743  746          default:
 744  747                  ret = CRYPTO_ARGUMENTS_BAD;
 745  748          }
 746  749  
 747  750          if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
 748  751                  bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
 749  752                  kmem_free(blowfish_ctx.bc_keysched,
 750  753                      blowfish_ctx.bc_keysched_len);
 751  754          }
 752  755  
 753  756          if (ret == CRYPTO_SUCCESS) {
 754  757                  ASSERT(blowfish_ctx.bc_remainder_len == 0);
 755  758                  if (ciphertext != plaintext)
 756  759                          plaintext->cd_length =
 757  760                              plaintext->cd_offset - saved_offset;
 758  761          } else {
 759  762                  plaintext->cd_length = saved_length;
 760  763          }
 761  764          plaintext->cd_offset = saved_offset;
 762  765  
 763  766          return (ret);
 764  767  }
 765  768  
 766  769  /*
 767  770   * KCF software provider context template entry points.
 768  771   */
 769  772  /* ARGSUSED */
 770  773  static int
 771  774  blowfish_create_ctx_template(crypto_provider_handle_t provider,
 772  775      crypto_mechanism_t *mechanism, crypto_key_t *key,
 773  776      crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
 774  777  {
 775  778          void *keysched;
 776  779          size_t size;
 777  780          int rv;
 778  781  
 779  782          if (!BLOWFISH_VALID_MECH(mechanism))
 780  783                  return (CRYPTO_MECHANISM_INVALID);
 781  784  
 782  785          if ((keysched = blowfish_alloc_keysched(&size,
 783  786              crypto_kmflag(req))) == NULL) {
 784  787                  return (CRYPTO_HOST_MEMORY);
 785  788          }
 786  789  
 787  790          /*
 788  791           * Initialize key schedule.  Key length information is stored
 789  792           * in the key.
 790  793           */
 791  794          if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
 792  795                  bzero(keysched, size);
 793  796                  kmem_free(keysched, size);
 794  797                  return (rv);
 795  798          }
 796  799  
 797  800          *tmpl = keysched;
 798  801          *tmpl_size = size;
 799  802  
 800  803          return (CRYPTO_SUCCESS);
 801  804  }
 802  805  
 803  806  /* ARGSUSED */
 804  807  static int
 805  808  blowfish_free_context(crypto_ctx_t *ctx)
 806  809  {
 807  810          blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
 808  811  
 809  812          if (blowfish_ctx != NULL) {
 810  813                  if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
 811  814                          ASSERT(blowfish_ctx->bc_keysched_len != 0);
 812  815                          bzero(blowfish_ctx->bc_keysched,
 813  816                              blowfish_ctx->bc_keysched_len);
 814  817                          kmem_free(blowfish_ctx->bc_keysched,
 815  818                              blowfish_ctx->bc_keysched_len);
 816  819                  }
 817  820                  crypto_free_mode_ctx(blowfish_ctx);
 818  821                  ctx->cc_provider_private = NULL;
 819  822          }
 820  823  
 821  824          return (CRYPTO_SUCCESS);
 822  825  }
 823  826  
 824  827  /* ARGSUSED */
 825  828  static int
 826  829  blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
 827  830      crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
 828  831      crypto_key_t *key, int kmflag)
 829  832  {
 830  833          int rv = CRYPTO_SUCCESS;
 831  834  
 832  835          void *keysched;
 833  836          size_t size;
 834  837  
 835  838          if (template == NULL) {
 836  839                  if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
 837  840                          return (CRYPTO_HOST_MEMORY);
 838  841                  /*
 839  842                   * Initialize key schedule.
 840  843                   * Key length is stored in the key.
 841  844                   */
 842  845                  if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
 843  846                          kmem_free(keysched, size);
 844  847  
 845  848                  blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
 846  849                  blowfish_ctx->bc_keysched_len = size;
 847  850          } else {
 848  851                  keysched = template;
 849  852          }
 850  853          blowfish_ctx->bc_keysched = keysched;
 851  854  
 852  855          switch (mechanism->cm_type) {
 853  856          case BLOWFISH_CBC_MECH_INFO_TYPE:
 854  857                  rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx,
 855  858                      mechanism->cm_param, mechanism->cm_param_len,
 856  859                      BLOWFISH_BLOCK_LEN, blowfish_copy_block64);
 857  860                  break;
 858  861          case BLOWFISH_ECB_MECH_INFO_TYPE:
 859  862                  blowfish_ctx->bc_flags |= ECB_MODE;
 860  863          }
 861  864  
 862  865          if (rv != CRYPTO_SUCCESS) {
 863  866                  if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
 864  867                          bzero(keysched, size);
 865  868                          kmem_free(keysched, size);
 866  869                  }
 867  870          }
 868  871  
 869  872          return (rv);
 870  873  }
  
    | ↓ open down ↓ | 538 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX