"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/crypto_backend/cipher_check.c" (13 Jan 2022, 4368 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cipher_check.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Cipher performance check
    3  *
    4  * Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
    5  * Copyright (C) 2018-2021 Milan Broz
    6  *
    7  * This file is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * This file is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this file; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20  */
   21 
   22 #include <errno.h>
   23 #include <time.h>
   24 #include "crypto_backend_internal.h"
   25 
   26 #ifndef CLOCK_MONOTONIC_RAW
   27 #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
   28 #endif
   29 
   30 /*
   31  * This is not simulating storage, so using disk block causes extreme overhead.
   32  * Let's use some fixed block size where results are more reliable...
   33  */
   34 #define CIPHER_BLOCK_BYTES 65536
   35 
   36 /*
   37  * If the measured value is lower, encrypted buffer is probably too small
   38  * and calculated values are not reliable.
   39  */
   40 #define CIPHER_TIME_MIN_MS 0.001
   41 
   42 /*
   43  * The whole test depends on Linux kernel usermode crypto API for now.
   44  * (The same implementations are used in dm-crypt though.)
   45  */
   46 
   47 static int time_ms(struct timespec *start, struct timespec *end, double *ms)
   48 {
   49     double start_ms, end_ms;
   50 
   51     start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
   52     end_ms   = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
   53 
   54     *ms = end_ms - start_ms;
   55     return 0;
   56 }
   57 
   58 static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size,
   59               const char *key, size_t key_size, const char *iv, size_t iv_size, int enc)
   60 {
   61     struct crypt_cipher_kernel cipher;
   62     size_t done = 0, block = CIPHER_BLOCK_BYTES;
   63     int r;
   64 
   65     if (buffer_size < block)
   66         block = buffer_size;
   67 
   68     r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size);
   69     if (r < 0)
   70         return r;
   71 
   72     while (done < buffer_size) {
   73         if ((done + block) > buffer_size)
   74             block = buffer_size - done;
   75 
   76         if (enc)
   77             r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done],
   78                          block, iv, iv_size);
   79         else
   80             r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done],
   81                          block, iv, iv_size);
   82         if (r < 0)
   83             break;
   84 
   85         done += block;
   86     }
   87 
   88     crypt_cipher_destroy_kernel(&cipher);
   89 
   90     return r;
   91 }
   92 static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size,
   93               const char *key, size_t key_size, const char *iv, size_t iv_size,
   94               int encrypt, double *ms)
   95 {
   96     struct timespec start, end;
   97     int r;
   98 
   99     /*
  100      * Using getrusage would be better here but the precision
  101      * is not adequate, so better stick with CLOCK_MONOTONIC
  102      */
  103     if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0)
  104         return -EINVAL;
  105 
  106     r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt);
  107     if (r < 0)
  108         return r;
  109 
  110     if (clock_gettime(CLOCK_MONOTONIC_RAW, &end) < 0)
  111         return -EINVAL;
  112 
  113     r = time_ms(&start, &end, ms);
  114     if (r < 0)
  115         return r;
  116 
  117     if (*ms < CIPHER_TIME_MIN_MS)
  118         return -ERANGE;
  119 
  120     return 0;
  121 }
  122 
  123 static double speed_mbs(unsigned long bytes, double ms)
  124 {
  125     double speed = bytes, s = ms / 1000.;
  126 
  127     return speed / (1024 * 1024) / s;
  128 }
  129 
  130 int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
  131                  const char *key, size_t key_size, const char *iv, size_t iv_size,
  132                  double *encryption_mbs, double *decryption_mbs)
  133 {
  134     double ms_enc, ms_dec, ms;
  135     int r, repeat_enc, repeat_dec;
  136 
  137     ms_enc = 0.0;
  138     repeat_enc = 1;
  139     while (ms_enc < 1000.0) {
  140         r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms);
  141         if (r < 0)
  142             return r;
  143         ms_enc += ms;
  144         repeat_enc++;
  145     }
  146 
  147     ms_dec = 0.0;
  148     repeat_dec = 1;
  149     while (ms_dec < 1000.0) {
  150         r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms);
  151         if (r < 0)
  152             return r;
  153         ms_dec += ms;
  154         repeat_dec++;
  155     }
  156 
  157     *encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc);
  158     *decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec);
  159 
  160     return  0;
  161 }