"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/utils_benchmark.c" between
cryptsetup-2.0.6.tar.xz and cryptsetup-2.1.0.tar.xz

About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.

utils_benchmark.c  (cryptsetup-2.0.6.tar.xz):utils_benchmark.c  (cryptsetup-2.1.0.tar.xz)
/* /*
* libcryptsetup - cryptsetup library, cipher benchmark * libcryptsetup - cryptsetup library, cipher benchmark
* *
* Copyright (C) 2012-2018, Red Hat, Inc. All rights reserved. * Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2018, Milan Broz * Copyright (C) 2012-2019 Milan Broz
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 66 skipping to change at line 66
{ {
double start_ms, end_ms; double start_ms, end_ms;
start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000); start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000); end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
*ms = end_ms - start_ms; *ms = end_ms - start_ms;
return 0; return 0;
} }
static int cipher_perf_one(struct cipher_perf *cp, char *buf, static int cipher_perf_one(struct crypt_device *cd,
struct cipher_perf *cp, char *buf,
size_t buf_size, int enc) size_t buf_size, int enc)
{ {
struct crypt_cipher *cipher = NULL; struct crypt_cipher *cipher = NULL;
size_t done = 0, block = CIPHER_BLOCK_BYTES; size_t done = 0, block = CIPHER_BLOCK_BYTES;
int r; int r;
if (buf_size < block) if (buf_size < block)
block = buf_size; block = buf_size;
r = crypt_cipher_init(&cipher, cp->name, cp->mode, cp->key, cp->key_lengt h); r = crypt_cipher_init(&cipher, cp->name, cp->mode, cp->key, cp->key_lengt h);
if (r < 0) { if (r < 0) {
log_dbg("Cannot initialise cipher %s, mode %s.", cp->name, cp->mo de); log_dbg(cd, "Cannot initialise cipher %s, mode %s.", cp->name, cp ->mode);
return r; return r;
} }
while (done < buf_size) { while (done < buf_size) {
if ((done + block) > buf_size) if ((done + block) > buf_size)
block = buf_size - done; block = buf_size - done;
if (enc) if (enc)
r = crypt_cipher_encrypt(cipher, &buf[done], &buf[done], r = crypt_cipher_encrypt(cipher, &buf[done], &buf[done],
block, cp->iv, cp->iv_length); block, cp->iv, cp->iv_length);
skipping to change at line 102 skipping to change at line 103
if (r < 0) if (r < 0)
break; break;
done += block; done += block;
} }
crypt_cipher_destroy(cipher); crypt_cipher_destroy(cipher);
return r; return r;
} }
static int cipher_measure(struct cipher_perf *cp, char *buf, static int cipher_measure(struct crypt_device *cd,
struct cipher_perf *cp, char *buf,
size_t buf_size, int encrypt, double *ms) size_t buf_size, int encrypt, double *ms)
{ {
struct timespec start, end; struct timespec start, end;
int r; int r;
/* /*
* Using getrusage would be better here but the precision * Using getrusage would be better here but the precision
* is not adequate, so better stick with CLOCK_MONOTONIC * is not adequate, so better stick with CLOCK_MONOTONIC
*/ */
if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
return -EINVAL; return -EINVAL;
r = cipher_perf_one(cp, buf, buf_size, encrypt); r = cipher_perf_one(cd, cp, buf, buf_size, encrypt);
if (r < 0) if (r < 0)
return r; return r;
if (clock_gettime(CLOCK_MONOTONIC, &end) < 0) if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
return -EINVAL; return -EINVAL;
r = time_ms(&start, &end, ms); r = time_ms(&start, &end, ms);
if (r < 0) if (r < 0)
return r; return r;
if (*ms < CIPHER_TIME_MIN_MS) { if (*ms < CIPHER_TIME_MIN_MS) {
log_dbg("Measured cipher runtime (%1.6f) is too low.", *ms); log_dbg(cd, "Measured cipher runtime (%1.6f) is too low.", *ms);
return -ERANGE; return -ERANGE;
} }
return 0; return 0;
} }
static double speed_mbs(unsigned long bytes, double ms) static double speed_mbs(unsigned long bytes, double ms)
{ {
double speed = bytes, s = ms / 1000.; double speed = bytes, s = ms / 1000.;
return speed / (1024 * 1024) / s; return speed / (1024 * 1024) / s;
} }
static int cipher_perf(struct cipher_perf *cp, static int cipher_perf(struct crypt_device *cd, struct cipher_perf *cp,
double *encryption_mbs, double *decryption_mbs) double *encryption_mbs, double *decryption_mbs)
{ {
double ms_enc, ms_dec, ms; double ms_enc, ms_dec, ms;
int r, repeat_enc, repeat_dec; int r, repeat_enc, repeat_dec;
void *buf = NULL; void *buf = NULL;
if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size)) if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size))
return -ENOMEM; return -ENOMEM;
ms_enc = 0.0; ms_enc = 0.0;
repeat_enc = 1; repeat_enc = 1;
while (ms_enc < 1000.0) { while (ms_enc < 1000.0) {
r = cipher_measure(cp, buf, cp->buffer_size, 1, &ms); r = cipher_measure(cd, cp, buf, cp->buffer_size, 1, &ms);
if (r < 0) { if (r < 0) {
free(buf); free(buf);
return r; return r;
} }
ms_enc += ms; ms_enc += ms;
repeat_enc++; repeat_enc++;
} }
ms_dec = 0.0; ms_dec = 0.0;
repeat_dec = 1; repeat_dec = 1;
while (ms_dec < 1000.0) { while (ms_dec < 1000.0) {
r = cipher_measure(cp, buf, cp->buffer_size, 0, &ms); r = cipher_measure(cd, cp, buf, cp->buffer_size, 0, &ms);
if (r < 0) { if (r < 0) {
free(buf); free(buf);
return r; return r;
} }
ms_dec += ms; ms_dec += ms;
repeat_dec++; repeat_dec++;
} }
free(buf); free(buf);
skipping to change at line 227 skipping to change at line 229
goto out; goto out;
crypt_random_get(cd, cp.key, volume_key_size, CRYPT_RND_NORMAL); crypt_random_get(cd, cp.key, volume_key_size, CRYPT_RND_NORMAL);
strncpy(cp.name, cipher, sizeof(cp.name)-1); strncpy(cp.name, cipher, sizeof(cp.name)-1);
strncpy(cp.mode, cipher_mode, sizeof(cp.mode)-1); strncpy(cp.mode, cipher_mode, sizeof(cp.mode)-1);
/* Ignore IV generator */ /* Ignore IV generator */
if ((c = strchr(cp.mode, '-'))) if ((c = strchr(cp.mode, '-')))
*c = '\0'; *c = '\0';
r = cipher_perf(&cp, encryption_mbs, decryption_mbs); r = cipher_perf(cd, &cp, encryption_mbs, decryption_mbs);
out: out:
free(cp.key); free(cp.key);
free(cp.iv); free(cp.iv);
return r; return r;
} }
int crypt_benchmark_pbkdf(struct crypt_device *cd, int crypt_benchmark_pbkdf(struct crypt_device *cd,
struct crypt_pbkdf_type *pbkdf, struct crypt_pbkdf_type *pbkdf,
const char *password, const char *password,
size_t password_size, size_t password_size,
skipping to change at line 256 skipping to change at line 258
if (!pbkdf || (!password && password_size)) if (!pbkdf || (!password && password_size))
return -EINVAL; return -EINVAL;
r = init_crypto(cd); r = init_crypto(cd);
if (r < 0) if (r < 0)
return r; return r;
kdf_opt = !strcmp(pbkdf->type, CRYPT_KDF_PBKDF2) ? pbkdf->hash : ""; kdf_opt = !strcmp(pbkdf->type, CRYPT_KDF_PBKDF2) ? pbkdf->hash : "";
log_dbg("Running %s(%s) benchmark.", pbkdf->type, kdf_opt); log_dbg(cd, "Running %s(%s) benchmark.", pbkdf->type, kdf_opt);
r = crypt_pbkdf_perf(pbkdf->type, pbkdf->hash, password, password_size, r = crypt_pbkdf_perf(pbkdf->type, pbkdf->hash, password, password_size,
salt, salt_size, volume_key_size, pbkdf->time_ms, salt, salt_size, volume_key_size, pbkdf->time_ms,
pbkdf->max_memory_kb, pbkdf->parallel_threads, pbkdf->max_memory_kb, pbkdf->parallel_threads,
&pbkdf->iterations, &pbkdf->max_memory_kb, progress, usrptr); &pbkdf->iterations, &pbkdf->max_memory_kb, progress, usrptr);
if (!r) if (!r)
log_dbg("Benchmark returns %s(%s) %u iterations, %u memory, %u th reads (for %zu-bits key).", log_dbg(cd, "Benchmark returns %s(%s) %u iterations, %u memory, % u threads (for %zu-bits key).",
pbkdf->type, kdf_opt, pbkdf->iterations, pbkdf->max_memor y_kb, pbkdf->type, kdf_opt, pbkdf->iterations, pbkdf->max_memor y_kb,
pbkdf->parallel_threads, volume_key_size * 8); pbkdf->parallel_threads, volume_key_size * 8);
return r; return r;
} }
struct benchmark_usrptr {
struct crypt_device *cd;
struct crypt_pbkdf_type *pbkdf;
};
static int benchmark_callback(uint32_t time_ms, void *usrptr) static int benchmark_callback(uint32_t time_ms, void *usrptr)
{ {
struct crypt_pbkdf_type *pbkdf = usrptr; struct benchmark_usrptr *u = usrptr;
log_dbg("PBKDF benchmark: memory cost = %u, iterations = %u, " log_dbg(u->cd, "PBKDF benchmark: memory cost = %u, iterations = %u, "
"threads = %u (took %u ms)", pbkdf->max_memory_kb, "threads = %u (took %u ms)", u->pbkdf->max_memory_kb,
pbkdf->iterations, pbkdf->parallel_threads, time_ms); u->pbkdf->iterations, u->pbkdf->parallel_threads, time_ms);
return 0; return 0;
} }
/* /*
* Used in internal places to benchmark crypt_device context PBKDF. * Used in internal places to benchmark crypt_device context PBKDF.
* Once requested parameters are benchmarked, iterations attribute is set, * Once requested parameters are benchmarked, iterations attribute is set,
* and the benchmarked values can be reused. * and the benchmarked values can be reused.
* Note that memory cost can be changed after benchmark (if used). * Note that memory cost can be changed after benchmark (if used).
* NOTE: You need to check that you are benchmarking for the same key size. * NOTE: You need to check that you are benchmarking for the same key size.
*/ */
int crypt_benchmark_pbkdf_internal(struct crypt_device *cd, int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
struct crypt_pbkdf_type *pbkdf, struct crypt_pbkdf_type *pbkdf,
size_t volume_key_size) size_t volume_key_size)
{ {
struct crypt_pbkdf_limits pbkdf_limits; struct crypt_pbkdf_limits pbkdf_limits;
double PBKDF2_tmp; double PBKDF2_tmp;
uint32_t ms_tmp; uint32_t ms_tmp;
int r = -EINVAL; int r = -EINVAL;
struct benchmark_usrptr u = {
.cd = cd,
.pbkdf = pbkdf
};
r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits); r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
if (r) if (r)
return r; return r;
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) { if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) {
if (pbkdf->iterations) { if (pbkdf->iterations) {
log_dbg("Reusing PBKDF values (no benchmark flag is set). "); log_dbg(cd, "Reusing PBKDF values (no benchmark flag is s et).");
return 0; return 0;
} }
log_err(cd, _("PBKDF benchmark disabled but iterations not set.") ); log_err(cd, _("PBKDF benchmark disabled but iterations not set.") );
return -EINVAL; return -EINVAL;
} }
/* For PBKDF2 run benchmark always. Also note it depends on volume_key_si ze! */ /* For PBKDF2 run benchmark always. Also note it depends on volume_key_si ze! */
if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) { if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
/* /*
* For PBKDF2 it is enough to run benchmark for only 1 second * For PBKDF2 it is enough to run benchmark for only 1 second
* and interpolate final iterations value from it. * and interpolate final iterations value from it.
*/ */
ms_tmp = pbkdf->time_ms; ms_tmp = pbkdf->time_ms;
pbkdf->time_ms = 1000; pbkdf->time_ms = 1000;
pbkdf->parallel_threads = 0; /* N/A in PBKDF2 */ pbkdf->parallel_threads = 0; /* N/A in PBKDF2 */
pbkdf->max_memory_kb = 0; /* N/A in PBKDF2 */ pbkdf->max_memory_kb = 0; /* N/A in PBKDF2 */
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, "bar", 3, r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, "bar", 3,
volume_key_size, &benchmark_callback, pbk df); volume_key_size, &benchmark_callback, &u) ;
pbkdf->time_ms = ms_tmp; pbkdf->time_ms = ms_tmp;
if (r < 0) { if (r < 0) {
log_err(cd, _("Not compatible PBKDF2 options (using hash algorithm %s)."), log_err(cd, _("Not compatible PBKDF2 options (using hash algorithm %s)."),
pbkdf->hash); pbkdf->hash);
return r; return r;
} }
PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.) ; PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.) ;
if (PBKDF2_tmp > (double)UINT32_MAX) if (PBKDF2_tmp > (double)UINT32_MAX)
return -EINVAL; return -EINVAL;
pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, pbkdf_limits.m in_iterations); pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, pbkdf_limits.m in_iterations);
} else { } else {
/* Already benchmarked */ /* Already benchmarked */
if (pbkdf->iterations) { if (pbkdf->iterations) {
log_dbg("Reusing PBKDF values."); log_dbg(cd, "Reusing PBKDF values.");
return 0; return 0;
} }
r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3, r = crypt_benchmark_pbkdf(cd, pbkdf, "foo", 3,
"0123456789abcdef0123456789abcdef", 32, "0123456789abcdef0123456789abcdef", 32,
volume_key_size, &benchmark_callback, pbkdf); volume_key_size, &benchmark_callback, &u);
if (r < 0) if (r < 0)
log_err(cd, _("Not compatible PBKDF options.")); log_err(cd, _("Not compatible PBKDF options."));
} }
return r; return r;
} }
 End of changes. 20 change blocks. 
21 lines changed or deleted 32 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)