diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 7a17cf10..4ff7140d 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -1,3155 +1,3155 @@ /* bench-slope.c - for libgcrypt * Copyright (C) 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #ifdef _WIN32 #include #endif #ifdef _GCRYPT_IN_LIBGCRYPT # include "../src/gcrypt-int.h" # include "../compat/libcompat.h" #else # include #endif #ifndef STR #define STR(v) #v #define STR2(v) STR(v) #endif #define PGM "bench-slope" #include "t-common.h" static int verbose; static int csv_mode; static int unaligned_mode; static int num_measurement_repetitions; /* CPU Ghz value provided by user, allows constructing cycles/byte and other results. */ static double cpu_ghz = -1; /* Attempt to autodetect CPU Ghz. */ static int auto_ghz; /* Whether we are running as part of the regression test suite. */ static int in_regression_test; /* The name of the currently printed section. */ static char *current_section_name; /* The name of the currently printed algorithm. */ static char *current_algo_name; /* The name of the currently printed mode. */ static char *current_mode_name; /* Currently used CPU Ghz (either user input or auto-detected. */ static double bench_ghz; /* Current accuracy of auto-detected CPU Ghz. */ static double bench_ghz_diff; -static int in_fips_mode = 0; +static int in_fips_mode; /*************************************** Default parameters for measurements. */ /* Start at small buffer size, to get reasonable timer calibration for fast * implementations (AES-NI etc). Sixteen selected to support the largest block * size of current set cipher blocks. */ #define BUF_START_SIZE 16 /* From ~0 to ~4kbytes give comparable results with results from academia * (SUPERCOP). */ #define BUF_END_SIZE (BUF_START_SIZE + 4096) /* With 128 byte steps, we get (4096)/64 = 64 data points. */ #define BUF_STEP_SIZE 64 /* Number of repeated measurements at each data point. The median of these * measurements is selected as data point further analysis. */ #define NUM_MEASUREMENT_REPETITIONS 64 /* Target accuracy for auto-detected CPU Ghz. */ #define AUTO_GHZ_TARGET_DIFF (5e-5) /**************************************************** High-resolution timers. */ /* This benchmarking module needs needs high resolution timer. */ #undef NO_GET_NSEC_TIME #if defined(_WIN32) struct nsec_time { LARGE_INTEGER perf_count; }; static void get_nsec_time (struct nsec_time *t) { BOOL ok; ok = QueryPerformanceCounter (&t->perf_count); assert (ok); } static double get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end) { static double nsecs_per_count = 0.0; double nsecs; if (nsecs_per_count == 0.0) { LARGE_INTEGER perf_freq; BOOL ok; /* Get counts per second. */ ok = QueryPerformanceFrequency (&perf_freq); assert (ok); nsecs_per_count = 1.0 / perf_freq.QuadPart; nsecs_per_count *= 1000000.0 * 1000.0; /* sec => nsec */ assert (nsecs_per_count > 0.0); } nsecs = end->perf_count.QuadPart - start->perf_count.QuadPart; /* counts */ nsecs *= nsecs_per_count; /* counts * (nsecs / count) => nsecs */ return nsecs; } #elif defined(HAVE_CLOCK_GETTIME) struct nsec_time { struct timespec ts; }; static void get_nsec_time (struct nsec_time *t) { int err; err = clock_gettime (CLOCK_REALTIME, &t->ts); assert (err == 0); } static double get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end) { double nsecs; nsecs = end->ts.tv_sec - start->ts.tv_sec; nsecs *= 1000000.0 * 1000.0; /* sec => nsec */ /* This way we don't have to care if tv_nsec unsigned or signed. */ if (end->ts.tv_nsec >= start->ts.tv_nsec) nsecs += end->ts.tv_nsec - start->ts.tv_nsec; else nsecs -= start->ts.tv_nsec - end->ts.tv_nsec; return nsecs; } #elif defined(HAVE_GETTIMEOFDAY) struct nsec_time { struct timeval tv; }; static void get_nsec_time (struct nsec_time *t) { int err; err = gettimeofday (&t->tv, NULL); assert (err == 0); } static double get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end) { double nsecs; nsecs = end->tv.tv_sec - start->tv.tv_sec; nsecs *= 1000000; /* sec => µsec */ /* This way we don't have to care if tv_usec unsigned or signed. */ if (end->tv.tv_usec >= start->tv.tv_usec) nsecs += end->tv.tv_usec - start->tv.tv_usec; else nsecs -= start->tv.tv_usec - end->tv.tv_usec; nsecs *= 1000; /* µsec => nsec */ return nsecs; } #else #define NO_GET_NSEC_TIME 1 #endif /* If no high resolution timer found, provide dummy bench-slope. */ #ifdef NO_GET_NSEC_TIME int main (void) { /* No nsec timer => SKIP test. */ return 77; } #else /* !NO_GET_NSEC_TIME */ /********************************************** Slope benchmarking framework. */ struct bench_obj { const struct bench_ops *ops; unsigned int num_measure_repetitions; unsigned int min_bufsize; unsigned int max_bufsize; unsigned int step_size; void *priv; void *hd; }; typedef int (*const bench_initialize_t) (struct bench_obj * obj); typedef void (*const bench_finalize_t) (struct bench_obj * obj); typedef void (*const bench_do_run_t) (struct bench_obj * obj, void *buffer, size_t buflen); struct bench_ops { bench_initialize_t initialize; bench_finalize_t finalize; bench_do_run_t do_run; }; static double safe_div (double x, double y) { union { double d; char buf[sizeof(double)]; } u_neg_zero, u_y; if (y != 0) return x / y; u_neg_zero.d = -0.0; u_y.d = y; if (memcmp(u_neg_zero.buf, u_y.buf, sizeof(double)) == 0) return -DBL_MAX; return DBL_MAX; } static double get_slope (double (*const get_x) (unsigned int idx, void *priv), void *get_x_priv, double y_points[], unsigned int npoints, double *overhead) { double sumx, sumy, sumx2, sumy2, sumxy; unsigned int i; double b, a; sumx = sumy = sumx2 = sumy2 = sumxy = 0; if (npoints <= 1) { /* No slope with zero or one point. */ return 0; } for (i = 0; i < npoints; i++) { double x, y; x = get_x (i, get_x_priv); /* bytes */ y = y_points[i]; /* nsecs */ sumx += x; sumy += y; sumx2 += x * x; /*sumy2 += y * y;*/ sumxy += x * y; } b = safe_div(npoints * sumxy - sumx * sumy, npoints * sumx2 - sumx * sumx); if (overhead) { a = safe_div(sumy - b * sumx, npoints); *overhead = a; /* nsecs */ } return b; /* nsecs per byte */ } double get_bench_obj_point_x (unsigned int idx, void *priv) { struct bench_obj *obj = priv; return (double) (obj->min_bufsize + (idx * obj->step_size)); } unsigned int get_num_measurements (struct bench_obj *obj) { unsigned int buf_range = obj->max_bufsize - obj->min_bufsize; unsigned int num = buf_range / obj->step_size + 1; while (obj->min_bufsize + (num * obj->step_size) > obj->max_bufsize) num--; return num + 1; } static int double_cmp (const void *_a, const void *_b) { const double *a, *b; a = _a; b = _b; if (*a > *b) return 1; if (*a < *b) return -1; return 0; } double do_bench_obj_measurement (struct bench_obj *obj, void *buffer, size_t buflen, double *measurement_raw, unsigned int loop_iterations) { const unsigned int num_repetitions = obj->num_measure_repetitions; const bench_do_run_t do_run = obj->ops->do_run; struct nsec_time start, end; unsigned int rep, loop; double res; if (num_repetitions < 1 || loop_iterations < 1) return 0.0; for (rep = 0; rep < num_repetitions; rep++) { get_nsec_time (&start); for (loop = 0; loop < loop_iterations; loop++) do_run (obj, buffer, buflen); get_nsec_time (&end); measurement_raw[rep] = get_time_nsec_diff (&start, &end); } /* Return median of repeated measurements. */ qsort (measurement_raw, num_repetitions, sizeof (measurement_raw[0]), double_cmp); if (num_repetitions % 2 == 1) return measurement_raw[num_repetitions / 2]; res = measurement_raw[num_repetitions / 2] + measurement_raw[num_repetitions / 2 - 1]; return res / 2; } unsigned int adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer, double *measurement_raw) { const double increase_thres = 3.0; double tmp, nsecs; unsigned int loop_iterations; unsigned int test_bufsize; test_bufsize = obj->min_bufsize; if (test_bufsize == 0) test_bufsize += obj->step_size; loop_iterations = 0; do { /* Increase loop iterations until we get other results than zero. */ nsecs = do_bench_obj_measurement (obj, buffer, test_bufsize, measurement_raw, ++loop_iterations); } while (nsecs < 1.0 - 0.1); do { /* Increase loop iterations until we get reasonable increase for elapsed time. */ tmp = do_bench_obj_measurement (obj, buffer, test_bufsize, measurement_raw, ++loop_iterations); } while (tmp < nsecs * (increase_thres - 0.1)); return loop_iterations; } /* Benchmark and return linear regression slope in nanoseconds per byte. */ double slope_benchmark (struct bench_obj *obj) { unsigned int num_measurements; double *measurements = NULL; double *measurement_raw = NULL; double slope, overhead; unsigned int loop_iterations, midx, i; unsigned char *real_buffer = NULL; unsigned char *buffer; size_t cur_bufsize; int err; err = obj->ops->initialize (obj); if (err < 0) return -1; num_measurements = get_num_measurements (obj); measurements = calloc (num_measurements, sizeof (*measurements)); if (!measurements) goto err_free; measurement_raw = calloc (obj->num_measure_repetitions, sizeof (*measurement_raw)); if (!measurement_raw) goto err_free; if (num_measurements < 1 || obj->num_measure_repetitions < 1 || obj->max_bufsize < 1 || obj->min_bufsize > obj->max_bufsize) goto err_free; real_buffer = malloc (obj->max_bufsize + 128 + unaligned_mode); if (!real_buffer) goto err_free; /* Get aligned buffer */ buffer = real_buffer; buffer += 128 - ((real_buffer - (unsigned char *) 0) & (128 - 1)); if (unaligned_mode) buffer += unaligned_mode; /* Make buffer unaligned */ for (i = 0; i < obj->max_bufsize; i++) buffer[i] = 0x55 ^ (-i); /* Adjust number of loop iterations up to timer accuracy. */ loop_iterations = adjust_loop_iterations_to_timer_accuracy (obj, buffer, measurement_raw); /* Perform measurements */ for (midx = 0, cur_bufsize = obj->min_bufsize; cur_bufsize <= obj->max_bufsize; cur_bufsize += obj->step_size, midx++) { measurements[midx] = do_bench_obj_measurement (obj, buffer, cur_bufsize, measurement_raw, loop_iterations); measurements[midx] /= loop_iterations; } assert (midx == num_measurements); slope = get_slope (&get_bench_obj_point_x, obj, measurements, num_measurements, &overhead); free (measurement_raw); free (measurements); free (real_buffer); obj->ops->finalize (obj); return slope; err_free: if (measurement_raw) free (measurement_raw); if (measurements) free (measurements); if (real_buffer) free (real_buffer); obj->ops->finalize (obj); return -1; } /********************************************* CPU frequency auto-detection. */ static int auto_ghz_init (struct bench_obj *obj) { obj->min_bufsize = 16; obj->max_bufsize = 64 + obj->min_bufsize; obj->step_size = 8; obj->num_measure_repetitions = 16; return 0; } static void auto_ghz_free (struct bench_obj *obj) { (void)obj; } static void auto_ghz_bench (struct bench_obj *obj, void *buf, size_t buflen) { (void)obj; (void)buf; buflen *= 1024; /* Turbo frequency detection benchmark. Without CPU turbo-boost, this * function will give cycles/iteration result 1024.0 on high-end CPUs. * With turbo, result will be less and can be used detect turbo-clock. */ #ifdef HAVE_GCC_ASM_VOLATILE_MEMORY /* Auto-ghz operation takes two CPU cycles to perform. Memory barriers * are used to prevent compiler from optimizing this loop away. */ #define AUTO_GHZ_OPERATION \ asm volatile ("":"+r"(buflen)::"memory"); \ buflen ^= 1; \ asm volatile ("":"+r"(buflen)::"memory"); \ buflen -= 2 #else /* TODO: Needs alternative way of preventing compiler optimizations. * Mix of XOR and subtraction appears to do the trick for now. */ #define AUTO_GHZ_OPERATION \ buflen ^= 1; \ buflen -= 2 #endif #define AUTO_GHZ_OPERATION_2 \ AUTO_GHZ_OPERATION; \ AUTO_GHZ_OPERATION #define AUTO_GHZ_OPERATION_4 \ AUTO_GHZ_OPERATION_2; \ AUTO_GHZ_OPERATION_2 #define AUTO_GHZ_OPERATION_8 \ AUTO_GHZ_OPERATION_4; \ AUTO_GHZ_OPERATION_4 #define AUTO_GHZ_OPERATION_16 \ AUTO_GHZ_OPERATION_8; \ AUTO_GHZ_OPERATION_8 #define AUTO_GHZ_OPERATION_32 \ AUTO_GHZ_OPERATION_16; \ AUTO_GHZ_OPERATION_16 #define AUTO_GHZ_OPERATION_64 \ AUTO_GHZ_OPERATION_32; \ AUTO_GHZ_OPERATION_32 #define AUTO_GHZ_OPERATION_128 \ AUTO_GHZ_OPERATION_64; \ AUTO_GHZ_OPERATION_64 do { /* 1024 auto-ghz operations per loop, total 2048 instructions. */ AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128; } while (buflen); } static struct bench_ops auto_ghz_detect_ops = { &auto_ghz_init, &auto_ghz_free, &auto_ghz_bench }; double get_auto_ghz (void) { struct bench_obj obj = { 0 }; double nsecs_per_iteration; double cycles_per_iteration; obj.ops = &auto_ghz_detect_ops; nsecs_per_iteration = slope_benchmark (&obj); cycles_per_iteration = nsecs_per_iteration * cpu_ghz; /* Adjust CPU Ghz so that cycles per iteration would give '1024.0'. */ return safe_div(cpu_ghz * 1024, cycles_per_iteration); } double do_slope_benchmark (struct bench_obj *obj) { unsigned int try_count = 0; double ret; if (!auto_ghz) { /* Perform measurement without autodetection of CPU frequency. */ do { ret = slope_benchmark (obj); } while (ret <= 0 && try_count++ <= 4); bench_ghz = cpu_ghz; bench_ghz_diff = 0; } else { double target_diff = AUTO_GHZ_TARGET_DIFF; double cpu_auto_ghz_before; double cpu_auto_ghz_after; double nsecs_per_iteration; double diff; /* Perform measurement with CPU frequency autodetection. */ do { /* Repeat measurement until CPU turbo frequency has stabilized. */ if ((++try_count % 4) == 0) { /* Too much frequency instability on the system, relax target * accuracy. */ target_diff *= 2; } cpu_auto_ghz_before = get_auto_ghz (); nsecs_per_iteration = slope_benchmark (obj); cpu_auto_ghz_after = get_auto_ghz (); diff = 1.0 - safe_div(cpu_auto_ghz_before, cpu_auto_ghz_after); diff = diff < 0 ? -diff : diff; } while ((nsecs_per_iteration <= 0 || diff > target_diff) && try_count < 1000); ret = nsecs_per_iteration; bench_ghz = (cpu_auto_ghz_before + cpu_auto_ghz_after) / 2; bench_ghz_diff = diff; } return ret; } /********************************************************** Printing results. */ static void double_to_str (char *out, size_t outlen, double value) { const char *fmt; if (value < 1.0) fmt = "%.3f"; else if (value < 100.0) fmt = "%.2f"; else if (value < 1000.0) fmt = "%.1f"; else fmt = "%.0f"; snprintf (out, outlen, fmt, value); } static void bench_print_result_csv (double nsecs_per_byte) { double cycles_per_byte, mbytes_per_sec; char nsecpbyte_buf[16]; char mbpsec_buf[16]; char cpbyte_buf[16]; char mhz_buf[16]; char mhz_diff_buf[32]; strcpy (mhz_diff_buf, ""); *cpbyte_buf = 0; *mhz_buf = 0; double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte); /* If user didn't provide CPU speed, we cannot show cycles/byte results. */ if (bench_ghz > 0.0) { cycles_per_byte = nsecs_per_byte * bench_ghz; double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte); double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); if (auto_ghz && bench_ghz_diff * 1000 >= 1) { snprintf(mhz_diff_buf, sizeof(mhz_diff_buf), ",%.0f,Mhz-diff", bench_ghz_diff * 1000); } } mbytes_per_sec = safe_div(1000.0 * 1000.0 * 1000.0, nsecs_per_byte * 1024 * 1024); double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec); /* We print two empty fields to allow for future enhancements. */ if (auto_ghz) { printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B,%s,Mhz%s\n", current_section_name, current_algo_name? current_algo_name : "", current_mode_name? current_mode_name : "", nsecpbyte_buf, mbpsec_buf, cpbyte_buf, mhz_buf, mhz_diff_buf); } else { printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B\n", current_section_name, current_algo_name? current_algo_name : "", current_mode_name? current_mode_name : "", nsecpbyte_buf, mbpsec_buf, cpbyte_buf); } } static void bench_print_result_std (double nsecs_per_byte) { double cycles_per_byte, mbytes_per_sec; char nsecpbyte_buf[16]; char mbpsec_buf[16]; char cpbyte_buf[16]; char mhz_buf[16]; char mhz_diff_buf[32]; strcpy (mhz_diff_buf, ""); double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte); /* If user didn't provide CPU speed, we cannot show cycles/byte results. */ if (bench_ghz > 0.0) { cycles_per_byte = nsecs_per_byte * bench_ghz; double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte); double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); if (auto_ghz && bench_ghz_diff * 1000 >= 0.5) { snprintf(mhz_diff_buf, sizeof(mhz_diff_buf), "±%.0f", bench_ghz_diff * 1000); } } else { strcpy (cpbyte_buf, "-"); strcpy (mhz_buf, "-"); } mbytes_per_sec = safe_div(1000.0 * 1000.0 * 1000.0, nsecs_per_byte * 1024 * 1024); double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec); if (auto_ghz) { printf ("%9s ns/B %9s MiB/s %9s c/B %9s%s\n", nsecpbyte_buf, mbpsec_buf, cpbyte_buf, mhz_buf, mhz_diff_buf); } else { printf ("%9s ns/B %9s MiB/s %9s c/B\n", nsecpbyte_buf, mbpsec_buf, cpbyte_buf); } } static void bench_print_result (double nsecs_per_byte) { if (csv_mode) bench_print_result_csv (nsecs_per_byte); else bench_print_result_std (nsecs_per_byte); } static void bench_print_result_nsec_per_iteration (double nsecs_per_iteration) { double cycles_per_iteration; char nsecpiter_buf[16]; char cpiter_buf[16]; char mhz_buf[16]; strcpy(cpiter_buf, csv_mode ? "" : "-"); strcpy(mhz_buf, csv_mode ? "" : "-"); double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration); /* If user didn't provide CPU speed, we cannot show cycles/iter results. */ if (bench_ghz > 0.0) { cycles_per_iteration = nsecs_per_iteration * bench_ghz; double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration); double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); } if (csv_mode) { if (auto_ghz) printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n", current_section_name, current_algo_name ? current_algo_name : "", current_mode_name ? current_mode_name : "", nsecpiter_buf, cpiter_buf, mhz_buf); else printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n", current_section_name, current_algo_name ? current_algo_name : "", current_mode_name ? current_mode_name : "", nsecpiter_buf, cpiter_buf); } else { if (auto_ghz) printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf); else printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf); } } static void bench_print_section (const char *section_name, const char *print_name) { if (csv_mode) { gcry_free (current_section_name); current_section_name = gcry_xstrdup (section_name); } else printf ("%s:\n", print_name); } static void bench_print_header (int algo_width, const char *algo_name) { if (csv_mode) { gcry_free (current_algo_name); current_algo_name = gcry_xstrdup (algo_name); } else { if (algo_width < 0) printf (" %-*s | ", -algo_width, algo_name); else printf (" %-*s | ", algo_width, algo_name); if (auto_ghz) printf ("%14s %15s %13s %9s\n", "nanosecs/byte", "mebibytes/sec", "cycles/byte", "auto Mhz"); else printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec", "cycles/byte"); } } static void bench_print_header_nsec_per_iteration (int algo_width, const char *algo_name) { if (csv_mode) { gcry_free (current_algo_name); current_algo_name = gcry_xstrdup (algo_name); } else { if (algo_width < 0) printf (" %-*s | ", -algo_width, algo_name); else printf (" %-*s | ", algo_width, algo_name); if (auto_ghz) printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz"); else printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter"); } } static void bench_print_algo (int algo_width, const char *algo_name) { if (csv_mode) { gcry_free (current_algo_name); current_algo_name = gcry_xstrdup (algo_name); } else { if (algo_width < 0) printf (" %-*s | ", -algo_width, algo_name); else printf (" %-*s | ", algo_width, algo_name); } } static void bench_print_mode (int width, const char *mode_name) { if (csv_mode) { gcry_free (current_mode_name); current_mode_name = gcry_xstrdup (mode_name); } else { if (width < 0) printf (" %-*s | ", -width, mode_name); else printf (" %*s | ", width, mode_name); fflush (stdout); } } static void bench_print_footer (int algo_width) { if (!csv_mode) printf (" %-*s =\n", algo_width, ""); } /********************************************************* Cipher benchmarks. */ struct bench_cipher_mode { int mode; const char *name; struct bench_ops *ops; int algo; }; static int bench_encrypt_init (struct bench_obj *obj) { struct bench_cipher_mode *mode = obj->priv; gcry_cipher_hd_t hd; int err, keylen; obj->min_bufsize = BUF_START_SIZE; obj->max_bufsize = BUF_END_SIZE; obj->step_size = BUF_STEP_SIZE; obj->num_measure_repetitions = num_measurement_repetitions; err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", gcry_cipher_algo_name (mode->algo)); exit (1); } keylen = gcry_cipher_get_algo_keylen (mode->algo); if (mode->mode == GCRY_CIPHER_MODE_SIV) { keylen *= 2; } if (keylen) { char key[keylen]; int i; for (i = 0; i < keylen; i++) key[i] = 0x33 ^ (11 - i); err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } else { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", gcry_cipher_algo_name (mode->algo)); gcry_cipher_close (hd); exit (1); } obj->hd = hd; return 0; } static void bench_encrypt_free (struct bench_obj *obj) { gcry_cipher_hd_t hd = obj->hd; gcry_cipher_close (hd); } static void bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_cipher_hd_t hd = obj->hd; int err; err = gcry_cipher_reset (hd); if (!err) err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_cipher_hd_t hd = obj->hd; int err; err = gcry_cipher_reset (hd); if (!err) err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static struct bench_ops encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_encrypt_do_bench }; static struct bench_ops decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_decrypt_do_bench }; static int bench_xts_encrypt_init (struct bench_obj *obj) { struct bench_cipher_mode *mode = obj->priv; gcry_cipher_hd_t hd; int err, keylen; obj->min_bufsize = BUF_START_SIZE; obj->max_bufsize = BUF_END_SIZE; obj->step_size = BUF_STEP_SIZE; obj->num_measure_repetitions = num_measurement_repetitions; err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", gcry_cipher_algo_name (mode->algo)); exit (1); } /* Double key-length for XTS. */ keylen = gcry_cipher_get_algo_keylen (mode->algo) * 2; if (keylen) { char key[keylen]; int i; for (i = 0; i < keylen; i++) key[i] = 0x33 ^ (11 - i); err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } else { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", gcry_cipher_algo_name (mode->algo)); gcry_cipher_close (hd); exit (1); } obj->hd = hd; return 0; } static struct bench_ops xts_encrypt_ops = { &bench_xts_encrypt_init, &bench_encrypt_free, &bench_encrypt_do_bench }; static struct bench_ops xts_decrypt_ops = { &bench_xts_encrypt_init, &bench_encrypt_free, &bench_decrypt_do_bench }; static void bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[8]; char nonce[11] = { 0x80, 0x01, }; u64 params[3]; gcry_cipher_setiv (hd, nonce, sizeof (nonce)); /* Set CCM lengths */ params[0] = buflen; params[1] = 0; /*aadlen */ params[2] = sizeof (tag); err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params)); if (err) { fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_gettag (hd, tag, sizeof (tag)); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_ccm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[8] = { 0, }; char nonce[11] = { 0x80, 0x01, }; u64 params[3]; gcry_cipher_setiv (hd, nonce, sizeof (nonce)); /* Set CCM lengths */ params[0] = buflen; params[1] = 0; /*aadlen */ params[2] = sizeof (tag); err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params)); if (err) { fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_checktag (hd, tag, sizeof (tag)); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) err = gpg_error (GPG_ERR_NO_ERROR); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_ccm_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[8] = { 0, }; char nonce[11] = { 0x80, 0x01, }; u64 params[3]; char data = 0xff; gcry_cipher_setiv (hd, nonce, sizeof (nonce)); /* Set CCM lengths */ params[0] = sizeof (data); /*datalen */ params[1] = buflen; /*aadlen */ params[2] = sizeof (tag); err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params)); if (err) { fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_authenticate (hd, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data)); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_gettag (hd, tag, sizeof (tag)); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static struct bench_ops ccm_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ccm_encrypt_do_bench }; static struct bench_ops ccm_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ccm_decrypt_do_bench }; static struct bench_ops ccm_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ccm_authenticate_do_bench }; static void bench_aead_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen, const char *nonce, size_t noncelen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[16]; gcry_cipher_reset (hd); gcry_cipher_setiv (hd, nonce, noncelen); gcry_cipher_final (hd); err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_gettag (hd, tag, sizeof (tag)); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_aead_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen, const char *nonce, size_t noncelen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[16] = { 0, }; gcry_cipher_reset (hd); gcry_cipher_set_decryption_tag (hd, tag, 16); gcry_cipher_setiv (hd, nonce, noncelen); gcry_cipher_final (hd); err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) err = gpg_error (GPG_ERR_NO_ERROR); if (err) { fprintf (stderr, PGM ": gcry_cipher_decrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_checktag (hd, tag, sizeof (tag)); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) err = gpg_error (GPG_ERR_NO_ERROR); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_aead_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen, const char *nonce, size_t noncelen) { gcry_cipher_hd_t hd = obj->hd; int err; char tag[16] = { 0, }; char data = 0xff; gcry_cipher_reset (hd); if (noncelen > 0) { err = gcry_cipher_setiv (hd, nonce, noncelen); if (err) { fprintf (stderr, PGM ": gcry_cipher_setiv failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } err = gcry_cipher_authenticate (hd, buf, buflen); if (err) { fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } gcry_cipher_final (hd); err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data)); if (err) { fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } err = gcry_cipher_gettag (hd, tag, sizeof (tag)); if (err) { fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static void bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static struct bench_ops gcm_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_encrypt_do_bench }; static struct bench_ops gcm_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_decrypt_do_bench }; static struct bench_ops gcm_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_authenticate_do_bench }; static void bench_ocb_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01 }; bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_ocb_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01 }; bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_ocb_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01 }; bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static struct bench_ops ocb_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ocb_encrypt_do_bench }; static struct bench_ops ocb_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ocb_decrypt_do_bench }; static struct bench_ops ocb_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_ocb_authenticate_do_bench }; static void bench_siv_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { bench_aead_encrypt_do_bench (obj, buf, buflen, NULL, 0); } static void bench_siv_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { bench_aead_decrypt_do_bench (obj, buf, buflen, NULL, 0); } static void bench_siv_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { bench_aead_authenticate_do_bench (obj, buf, buflen, NULL, 0); } static struct bench_ops siv_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_siv_encrypt_do_bench }; static struct bench_ops siv_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_siv_decrypt_do_bench }; static struct bench_ops siv_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_siv_authenticate_do_bench }; static void bench_gcm_siv_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_gcm_siv_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_gcm_siv_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static struct bench_ops gcm_siv_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_siv_encrypt_do_bench }; static struct bench_ops gcm_siv_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_siv_decrypt_do_bench }; static struct bench_ops gcm_siv_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_gcm_siv_authenticate_do_bench }; static void bench_eax_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01, 0x00 }; bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_eax_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01, 0x00 }; bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_eax_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x01, 0x00 }; bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static struct bench_ops eax_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_eax_encrypt_do_bench }; static struct bench_ops eax_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_eax_decrypt_do_bench }; static struct bench_ops eax_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_eax_authenticate_do_bench }; static void bench_poly1305_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_poly1305_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static void bench_poly1305_authenticate_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); } static struct bench_ops poly1305_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_poly1305_encrypt_do_bench }; static struct bench_ops poly1305_decrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_poly1305_decrypt_do_bench }; static struct bench_ops poly1305_authenticate_ops = { &bench_encrypt_init, &bench_encrypt_free, &bench_poly1305_authenticate_do_bench }; static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops}, {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops}, {GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops}, {GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops}, {GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops}, {GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops}, {GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops}, {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops}, {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops}, {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops}, {GCRY_CIPHER_MODE_XTS, "XTS enc", &xts_encrypt_ops}, {GCRY_CIPHER_MODE_XTS, "XTS dec", &xts_decrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops}, {GCRY_CIPHER_MODE_EAX, "EAX enc", &eax_encrypt_ops}, {GCRY_CIPHER_MODE_EAX, "EAX dec", &eax_decrypt_ops}, {GCRY_CIPHER_MODE_EAX, "EAX auth", &eax_authenticate_ops}, {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops}, {GCRY_CIPHER_MODE_OCB, "OCB enc", &ocb_encrypt_ops}, {GCRY_CIPHER_MODE_OCB, "OCB dec", &ocb_decrypt_ops}, {GCRY_CIPHER_MODE_OCB, "OCB auth", &ocb_authenticate_ops}, {GCRY_CIPHER_MODE_SIV, "SIV enc", &siv_encrypt_ops}, {GCRY_CIPHER_MODE_SIV, "SIV dec", &siv_decrypt_ops}, {GCRY_CIPHER_MODE_SIV, "SIV auth", &siv_authenticate_ops}, {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV enc", &gcm_siv_encrypt_ops}, {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV dec", &gcm_siv_decrypt_ops}, {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV auth", &gcm_siv_authenticate_ops}, {GCRY_CIPHER_MODE_POLY1305, "POLY1305 enc", &poly1305_encrypt_ops}, {GCRY_CIPHER_MODE_POLY1305, "POLY1305 dec", &poly1305_decrypt_ops}, {GCRY_CIPHER_MODE_POLY1305, "POLY1305 auth", &poly1305_authenticate_ops}, {0}, }; static void cipher_bench_one (int algo, struct bench_cipher_mode *pmode) { struct bench_cipher_mode mode = *pmode; struct bench_obj obj = { 0 }; double result; unsigned int blklen; unsigned int keylen; mode.algo = algo; /* Check if this mode is ok */ blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) return; keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) return; /* Stream cipher? Only test with "ECB" and POLY1305. */ if (blklen == 1 && (mode.mode != GCRY_CIPHER_MODE_ECB && mode.mode != GCRY_CIPHER_MODE_POLY1305)) return; if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB) { mode.mode = GCRY_CIPHER_MODE_STREAM; mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec"; } /* Poly1305 has restriction for cipher algorithm */ if (mode.mode == GCRY_CIPHER_MODE_POLY1305 && algo != GCRY_CIPHER_CHACHA20) return; /* CCM has restrictions for block-size */ if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN) return; /* GCM has restrictions for block-size; not allowed in FIPS mode */ if (mode.mode == GCRY_CIPHER_MODE_GCM && (in_fips_mode || blklen != GCRY_GCM_BLOCK_LEN)) return; /* XTS has restrictions for block-size */ if (mode.mode == GCRY_CIPHER_MODE_XTS && blklen != GCRY_XTS_BLOCK_LEN) return; /* SIV has restrictions for block-size */ if (mode.mode == GCRY_CIPHER_MODE_SIV && blklen != GCRY_SIV_BLOCK_LEN) return; /* GCM-SIV has restrictions for block-size */ if (mode.mode == GCRY_CIPHER_MODE_GCM_SIV && blklen != GCRY_SIV_BLOCK_LEN) return; /* GCM-SIV has restrictions for key length */ if (mode.mode == GCRY_CIPHER_MODE_GCM_SIV && !(keylen == 16 || keylen == 32)) return; /* Our OCB implementation has restrictions for block-size. */ if (mode.mode == GCRY_CIPHER_MODE_OCB && blklen != GCRY_OCB_BLOCK_LEN) return; bench_print_mode (14, mode.name); obj.ops = mode.ops; obj.priv = &mode; result = do_slope_benchmark (&obj); bench_print_result (result); } static void _cipher_bench (int algo) { const char *algoname; int i; algoname = gcry_cipher_algo_name (algo); bench_print_header (14, algoname); for (i = 0; cipher_modes[i].mode; i++) cipher_bench_one (algo, &cipher_modes[i]); bench_print_footer (14); } void cipher_bench (char **argv, int argc) { int i, algo; bench_print_section ("cipher", "Cipher"); if (argv && argc) { for (i = 0; i < argc; i++) { algo = gcry_cipher_map_name (argv[i]); if (algo) _cipher_bench (algo); } } else { for (i = 1; i < 400; i++) if (!gcry_cipher_test_algo (i)) _cipher_bench (i); } } /*********************************************************** Hash benchmarks. */ struct bench_hash_mode { const char *name; struct bench_ops *ops; int algo; }; static int bench_hash_init (struct bench_obj *obj) { struct bench_hash_mode *mode = obj->priv; gcry_md_hd_t hd; int err; obj->min_bufsize = BUF_START_SIZE; obj->max_bufsize = BUF_END_SIZE; obj->step_size = BUF_STEP_SIZE; obj->num_measure_repetitions = num_measurement_repetitions; err = gcry_md_open (&hd, mode->algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash `%s'\n", gcry_md_algo_name (mode->algo)); exit (1); } obj->hd = hd; return 0; } static void bench_hash_free (struct bench_obj *obj) { gcry_md_hd_t hd = obj->hd; gcry_md_close (hd); } static void bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_md_hd_t hd = obj->hd; gcry_md_reset (hd); gcry_md_write (hd, buf, buflen); gcry_md_final (hd); } static struct bench_ops hash_ops = { &bench_hash_init, &bench_hash_free, &bench_hash_do_bench }; static struct bench_hash_mode hash_modes[] = { {"", &hash_ops}, {0}, }; static void hash_bench_one (int algo, struct bench_hash_mode *pmode) { struct bench_hash_mode mode = *pmode; struct bench_obj obj = { 0 }; double result; mode.algo = algo; if (mode.name[0] == '\0') bench_print_algo (-14, gcry_md_algo_name (algo)); else bench_print_algo (14, mode.name); obj.ops = mode.ops; obj.priv = &mode; result = do_slope_benchmark (&obj); bench_print_result (result); } static void _hash_bench (int algo) { int i; for (i = 0; hash_modes[i].name; i++) hash_bench_one (algo, &hash_modes[i]); } void hash_bench (char **argv, int argc) { int i, algo; bench_print_section ("hash", "Hash"); bench_print_header (14, ""); if (argv && argc) { for (i = 0; i < argc; i++) { algo = gcry_md_map_name (argv[i]); if (algo) _hash_bench (algo); } } else { for (i = 1; i < 400; i++) if (!gcry_md_test_algo (i)) _hash_bench (i); } bench_print_footer (14); } /************************************************************ MAC benchmarks. */ struct bench_mac_mode { const char *name; struct bench_ops *ops; int algo; }; static int bench_mac_init (struct bench_obj *obj) { struct bench_mac_mode *mode = obj->priv; gcry_mac_hd_t hd; int err; unsigned int keylen; void *key; obj->min_bufsize = BUF_START_SIZE; obj->max_bufsize = BUF_END_SIZE; obj->step_size = BUF_STEP_SIZE; obj->num_measure_repetitions = num_measurement_repetitions; keylen = gcry_mac_get_algo_keylen (mode->algo); if (keylen == 0) keylen = 32; key = malloc (keylen); if (!key) { fprintf (stderr, PGM ": couldn't allocate %d bytes\n", keylen); exit (1); } memset(key, 42, keylen); err = gcry_mac_open (&hd, mode->algo, 0, NULL); if (err) { fprintf (stderr, PGM ": error opening mac `%s'\n", gcry_mac_algo_name (mode->algo)); free (key); exit (1); } err = gcry_mac_setkey (hd, key, keylen); if (err) { fprintf (stderr, PGM ": error setting key for mac `%s'\n", gcry_mac_algo_name (mode->algo)); free (key); exit (1); } switch (mode->algo) { default: break; case GCRY_MAC_POLY1305_AES: case GCRY_MAC_POLY1305_CAMELLIA: case GCRY_MAC_POLY1305_TWOFISH: case GCRY_MAC_POLY1305_SERPENT: case GCRY_MAC_POLY1305_SEED: gcry_mac_setiv (hd, key, 16); break; } obj->hd = hd; free (key); return 0; } static void bench_mac_free (struct bench_obj *obj) { gcry_mac_hd_t hd = obj->hd; gcry_mac_close (hd); } static void bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_mac_hd_t hd = obj->hd; size_t bs; char b; gcry_mac_reset (hd); gcry_mac_write (hd, buf, buflen); bs = sizeof(b); gcry_mac_read (hd, &b, &bs); } static struct bench_ops mac_ops = { &bench_mac_init, &bench_mac_free, &bench_mac_do_bench }; static struct bench_mac_mode mac_modes[] = { {"", &mac_ops}, {0}, }; static void mac_bench_one (int algo, struct bench_mac_mode *pmode) { struct bench_mac_mode mode = *pmode; struct bench_obj obj = { 0 }; double result; mode.algo = algo; if (mode.name[0] == '\0') bench_print_algo (-18, gcry_mac_algo_name (algo)); else bench_print_algo (18, mode.name); obj.ops = mode.ops; obj.priv = &mode; result = do_slope_benchmark (&obj); bench_print_result (result); } static void _mac_bench (int algo) { int i; for (i = 0; mac_modes[i].name; i++) mac_bench_one (algo, &mac_modes[i]); } void mac_bench (char **argv, int argc) { int i, algo; bench_print_section ("mac", "MAC"); bench_print_header (18, ""); if (argv && argc) { for (i = 0; i < argc; i++) { algo = gcry_mac_map_name (argv[i]); if (algo) _mac_bench (algo); } } else { for (i = 1; i < 600; i++) if (!gcry_mac_test_algo (i)) _mac_bench (i); } bench_print_footer (18); } /************************************************************ KDF benchmarks. */ struct bench_kdf_mode { struct bench_ops *ops; int algo; int subalgo; }; static int bench_kdf_init (struct bench_obj *obj) { struct bench_kdf_mode *mode = obj->priv; if (mode->algo == GCRY_KDF_PBKDF2) { obj->min_bufsize = 2; obj->max_bufsize = 2 * 32; obj->step_size = 2; } obj->num_measure_repetitions = num_measurement_repetitions; return 0; } static void bench_kdf_free (struct bench_obj *obj) { (void)obj; } static void bench_kdf_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { struct bench_kdf_mode *mode = obj->priv; char keybuf[16]; (void)buf; if (mode->algo == GCRY_KDF_PBKDF2) { gcry_kdf_derive("qwerty", 6, mode->algo, mode->subalgo, "01234567", 8, buflen, sizeof(keybuf), keybuf); } } static struct bench_ops kdf_ops = { &bench_kdf_init, &bench_kdf_free, &bench_kdf_do_bench }; static void kdf_bench_one (int algo, int subalgo) { struct bench_kdf_mode mode = { &kdf_ops }; struct bench_obj obj = { 0 }; double nsecs_per_iteration; char algo_name[32]; mode.algo = algo; mode.subalgo = subalgo; switch (subalgo) { case GCRY_MD_CRC32: case GCRY_MD_CRC32_RFC1510: case GCRY_MD_CRC24_RFC2440: case GCRY_MD_MD4: /* Skip CRC32s. */ return; } if (gcry_md_get_algo_dlen (subalgo) == 0) { /* Skip XOFs */ return; } *algo_name = 0; if (algo == GCRY_KDF_PBKDF2) { snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s", gcry_md_algo_name (subalgo)); } bench_print_algo (-24, algo_name); obj.ops = mode.ops; obj.priv = &mode; nsecs_per_iteration = do_slope_benchmark (&obj); bench_print_result_nsec_per_iteration (nsecs_per_iteration); } void kdf_bench (char **argv, int argc) { char algo_name[32]; int i, j; bench_print_section ("kdf", "KDF"); bench_print_header_nsec_per_iteration (24, ""); if (argv && argc) { for (i = 0; i < argc; i++) { for (j = 1; j < 400; j++) { if (gcry_md_test_algo (j)) continue; snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s", gcry_md_algo_name (j)); if (!strcmp(argv[i], algo_name)) kdf_bench_one (GCRY_KDF_PBKDF2, j); } } } else { for (i = 1; i < 400; i++) if (!gcry_md_test_algo (i)) kdf_bench_one (GCRY_KDF_PBKDF2, i); } bench_print_footer (24); } /************************************************************ ECC benchmarks. */ #if USE_ECC enum bench_ecc_algo { ECC_ALGO_ED25519 = 0, ECC_ALGO_ED448, ECC_ALGO_X25519, ECC_ALGO_X448, ECC_ALGO_NIST_P192, ECC_ALGO_NIST_P224, ECC_ALGO_NIST_P256, ECC_ALGO_NIST_P384, ECC_ALGO_NIST_P521, ECC_ALGO_SECP256K1, __MAX_ECC_ALGO }; enum bench_ecc_operation { ECC_OPER_MULT = 0, ECC_OPER_KEYGEN, ECC_OPER_SIGN, ECC_OPER_VERIFY, __MAX_ECC_OPER }; struct bench_ecc_oper { enum bench_ecc_operation oper; const char *name; struct bench_ops *ops; enum bench_ecc_algo algo; }; struct bench_ecc_mult_hd { gcry_ctx_t ec; gcry_mpi_t k, x, y; gcry_mpi_point_t G, Q; }; struct bench_ecc_hd { gcry_sexp_t key_spec; gcry_sexp_t data; gcry_sexp_t pub_key; gcry_sexp_t sec_key; gcry_sexp_t sig; }; static int ecc_algo_fips_allowed (int algo) { switch (algo) { case ECC_ALGO_NIST_P224: case ECC_ALGO_NIST_P256: case ECC_ALGO_NIST_P384: case ECC_ALGO_NIST_P521: return 1; case ECC_ALGO_SECP256K1: case ECC_ALGO_ED25519: case ECC_ALGO_ED448: case ECC_ALGO_X25519: case ECC_ALGO_X448: case ECC_ALGO_NIST_P192: default: return 0; } } static const char * ecc_algo_name (int algo) { switch (algo) { case ECC_ALGO_ED25519: return "Ed25519"; case ECC_ALGO_ED448: return "Ed448"; case ECC_ALGO_X25519: return "X25519"; case ECC_ALGO_X448: return "X448"; case ECC_ALGO_NIST_P192: return "NIST-P192"; case ECC_ALGO_NIST_P224: return "NIST-P224"; case ECC_ALGO_NIST_P256: return "NIST-P256"; case ECC_ALGO_NIST_P384: return "NIST-P384"; case ECC_ALGO_NIST_P521: return "NIST-P521"; case ECC_ALGO_SECP256K1: return "secp256k1"; default: return NULL; } } static const char * ecc_algo_curve (int algo) { switch (algo) { case ECC_ALGO_ED25519: return "Ed25519"; case ECC_ALGO_ED448: return "Ed448"; case ECC_ALGO_X25519: return "Curve25519"; case ECC_ALGO_X448: return "X448"; case ECC_ALGO_NIST_P192: return "NIST P-192"; case ECC_ALGO_NIST_P224: return "NIST P-224"; case ECC_ALGO_NIST_P256: return "NIST P-256"; case ECC_ALGO_NIST_P384: return "NIST P-384"; case ECC_ALGO_NIST_P521: return "NIST P-521"; case ECC_ALGO_SECP256K1: return "secp256k1"; default: return NULL; } } static int ecc_nbits (int algo) { switch (algo) { case ECC_ALGO_ED25519: return 255; case ECC_ALGO_ED448: return 448; case ECC_ALGO_X25519: return 255; case ECC_ALGO_X448: return 448; case ECC_ALGO_NIST_P192: return 192; case ECC_ALGO_NIST_P224: return 224; case ECC_ALGO_NIST_P256: return 256; case ECC_ALGO_NIST_P384: return 384; case ECC_ALGO_NIST_P521: return 521; case ECC_ALGO_SECP256K1: return 256; default: return 0; } } static int ecc_map_name (const char *name) { int i; for (i = 0; i < __MAX_ECC_ALGO; i++) { if (strcmp(ecc_algo_name(i), name) == 0) { return i; } } return -1; } static int bench_ecc_mult_init (struct bench_obj *obj) { struct bench_ecc_oper *oper = obj->priv; struct bench_ecc_mult_hd *hd; int p_size = ecc_nbits (oper->algo); gpg_error_t err; gcry_mpi_t p; obj->min_bufsize = 1; obj->max_bufsize = 4; obj->step_size = 1; obj->num_measure_repetitions = num_measurement_repetitions / obj->max_bufsize; while (obj->num_measure_repetitions == 0) { if (obj->max_bufsize == 2) { obj->num_measure_repetitions = 2; } else { obj->max_bufsize--; obj->num_measure_repetitions = num_measurement_repetitions / obj->max_bufsize; } } hd = calloc (1, sizeof(*hd)); if (!hd) return -1; err = gcry_mpi_ec_new (&hd->ec, NULL, ecc_algo_curve(oper->algo)); if (err) { fprintf (stderr, PGM ": gcry_mpi_ec_new failed: %s\n", gpg_strerror (err)); exit (1); } hd->G = gcry_mpi_ec_get_point ("g", hd->ec, 1); hd->Q = gcry_mpi_point_new (0); hd->x = gcry_mpi_new (0); hd->y = gcry_mpi_new (0); hd->k = gcry_mpi_new (p_size); gcry_mpi_randomize (hd->k, p_size, GCRY_WEAK_RANDOM); p = gcry_mpi_ec_get_mpi ("p", hd->ec, 1); gcry_mpi_mod (hd->k, hd->k, p); gcry_mpi_release (p); obj->hd = hd; return 0; } static void bench_ecc_mult_free (struct bench_obj *obj) { struct bench_ecc_mult_hd *hd = obj->hd; gcry_mpi_release (hd->k); gcry_mpi_release (hd->y); gcry_mpi_release (hd->x); gcry_mpi_point_release (hd->Q); gcry_mpi_point_release (hd->G); gcry_ctx_release (hd->ec); free (hd); obj->hd = NULL; } static void bench_ecc_mult_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) { struct bench_ecc_oper *oper = obj->priv; struct bench_ecc_mult_hd *hd = obj->hd; gcry_mpi_t y; size_t i; (void)buf; if (oper->algo == ECC_ALGO_X25519 || oper->algo == ECC_ALGO_X448) { y = NULL; } else { y = hd->y; } for (i = 0; i < num_iter; i++) { gcry_mpi_ec_mul (hd->Q, hd->k, hd->G, hd->ec); if (gcry_mpi_ec_get_affine (hd->x, y, hd->Q, hd->ec)) { fprintf (stderr, PGM ": gcry_mpi_ec_get_affine failed\n"); exit (1); } } } static int bench_ecc_init (struct bench_obj *obj) { struct bench_ecc_oper *oper = obj->priv; struct bench_ecc_hd *hd; int p_size = ecc_nbits (oper->algo); gpg_error_t err; gcry_mpi_t x; obj->min_bufsize = 1; obj->max_bufsize = 4; obj->step_size = 1; obj->num_measure_repetitions = num_measurement_repetitions / obj->max_bufsize; while (obj->num_measure_repetitions == 0) { if (obj->max_bufsize == 2) { obj->num_measure_repetitions = 2; } else { obj->max_bufsize--; obj->num_measure_repetitions = num_measurement_repetitions / obj->max_bufsize; } } hd = calloc (1, sizeof(*hd)); if (!hd) return -1; x = gcry_mpi_new (p_size); gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM); switch (oper->algo) { default: return -1; case ECC_ALGO_ED25519: err = gcry_sexp_build (&hd->key_spec, NULL, "(genkey (ecdsa (curve \"Ed25519\")" "(flags eddsa)))"); if (err) break; err = gcry_sexp_build (&hd->data, NULL, "(data (flags eddsa)(hash-algo sha512)" " (value %m))", x); break; case ECC_ALGO_ED448: err = gcry_sexp_build (&hd->key_spec, NULL, "(genkey (ecdsa (curve \"Ed448\")" "(flags eddsa)))"); if (err) break; err = gcry_sexp_build (&hd->data, NULL, "(data (flags eddsa)(hash-algo shake256)" " (value %m))", x); break; case ECC_ALGO_NIST_P192: case ECC_ALGO_NIST_P224: case ECC_ALGO_NIST_P256: case ECC_ALGO_NIST_P384: case ECC_ALGO_NIST_P521: err = gcry_sexp_build (&hd->key_spec, NULL, "(genkey (ECDSA (nbits %d)))", p_size); if (err) break; err = gcry_sexp_build (&hd->data, NULL, "(data (flags raw) (value %m))", x); break; } gcry_mpi_release (x); if (err) { fprintf (stderr, PGM ": gcry_sexp_build failed: %s\n", gpg_strerror (err)); exit (1); } obj->hd = hd; return 0; } static void bench_ecc_free (struct bench_obj *obj) { struct bench_ecc_hd *hd = obj->hd; gcry_sexp_release (hd->sig); gcry_sexp_release (hd->pub_key); gcry_sexp_release (hd->sec_key); gcry_sexp_release (hd->data); gcry_sexp_release (hd->key_spec); free (hd); obj->hd = NULL; } static void bench_ecc_keygen (struct bench_ecc_hd *hd) { gcry_sexp_t key_pair; gpg_error_t err; err = gcry_pk_genkey (&key_pair, hd->key_spec); if (err) { fprintf (stderr, PGM ": gcry_pk_genkey failed: %s\n", gpg_strerror (err)); exit (1); } hd->pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (!hd->pub_key) { fprintf (stderr, PGM ": public part missing in key\n"); exit (1); } hd->sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (!hd->sec_key) { fprintf (stderr, PGM ": private part missing in key\n"); exit (1); } gcry_sexp_release (key_pair); } static void bench_ecc_keygen_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) { struct bench_ecc_hd *hd = obj->hd; size_t i; (void)buf; for (i = 0; i < num_iter; i++) { bench_ecc_keygen (hd); gcry_sexp_release (hd->pub_key); gcry_sexp_release (hd->sec_key); } hd->pub_key = NULL; hd->sec_key = NULL; } static void bench_ecc_sign_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) { struct bench_ecc_hd *hd = obj->hd; gpg_error_t err; size_t i; (void)buf; bench_ecc_keygen (hd); for (i = 0; i < num_iter; i++) { err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); if (err) { fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", gpg_strerror (err)); exit (1); } gcry_sexp_release (hd->sig); } gcry_sexp_release (hd->pub_key); gcry_sexp_release (hd->sec_key); hd->sig = NULL; hd->pub_key = NULL; hd->sec_key = NULL; } static void bench_ecc_verify_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) { struct bench_ecc_hd *hd = obj->hd; gpg_error_t err; int i; (void)buf; bench_ecc_keygen (hd); err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); if (err) { fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", gpg_strerror (err)); exit (1); } for (i = 0; i < num_iter; i++) { err = gcry_pk_verify (hd->sig, hd->data, hd->pub_key); if (err) { fprintf (stderr, PGM ": gcry_pk_verify failed: %s\n", gpg_strerror (err)); exit (1); } } gcry_sexp_release (hd->sig); gcry_sexp_release (hd->pub_key); gcry_sexp_release (hd->sec_key); hd->sig = NULL; hd->pub_key = NULL; hd->sec_key = NULL; } static struct bench_ops ecc_mult_ops = { &bench_ecc_mult_init, &bench_ecc_mult_free, &bench_ecc_mult_do_bench }; static struct bench_ops ecc_keygen_ops = { &bench_ecc_init, &bench_ecc_free, &bench_ecc_keygen_do_bench }; static struct bench_ops ecc_sign_ops = { &bench_ecc_init, &bench_ecc_free, &bench_ecc_sign_do_bench }; static struct bench_ops ecc_verify_ops = { &bench_ecc_init, &bench_ecc_free, &bench_ecc_verify_do_bench }; static struct bench_ecc_oper ecc_operations[] = { { ECC_OPER_MULT, "mult", &ecc_mult_ops }, { ECC_OPER_KEYGEN, "keygen", &ecc_keygen_ops }, { ECC_OPER_SIGN, "sign", &ecc_sign_ops }, { ECC_OPER_VERIFY, "verify", &ecc_verify_ops }, { 0, NULL, NULL } }; static void cipher_ecc_one (enum bench_ecc_algo algo, struct bench_ecc_oper *poper) { struct bench_ecc_oper oper = *poper; struct bench_obj obj = { 0 }; double result; if ((algo == ECC_ALGO_X25519 || algo == ECC_ALGO_X448 || algo == ECC_ALGO_SECP256K1) && oper.oper != ECC_OPER_MULT) return; oper.algo = algo; bench_print_mode (14, oper.name); obj.ops = oper.ops; obj.priv = &oper; result = do_slope_benchmark (&obj); bench_print_result_nsec_per_iteration (result); } static void _ecc_bench (int algo) { const char *algo_name; int i; /* Skip not allowed mechanisms */ if (in_fips_mode && !ecc_algo_fips_allowed (algo)) return; algo_name = ecc_algo_name (algo); bench_print_header_nsec_per_iteration (14, algo_name); for (i = 0; ecc_operations[i].name; i++) cipher_ecc_one (algo, &ecc_operations[i]); bench_print_footer (14); } #endif void ecc_bench (char **argv, int argc) { #if USE_ECC int i, algo; bench_print_section ("ecc", "ECC"); if (argv && argc) { for (i = 0; i < argc; i++) { algo = ecc_map_name (argv[i]); if (algo >= 0) _ecc_bench (algo); } } else { for (i = 0; i < __MAX_ECC_ALGO; i++) _ecc_bench (i); } #else (void)argv; (void)argc; #endif } /************************************************************** Main program. */ void print_help (void) { static const char *help_lines[] = { "usage: bench-slope [options] [hash|mac|cipher|kdf|ecc [algonames]]", "", " options:", " --cpu-mhz Set CPU speed for calculating cycles", " per bytes results. Set as \"auto\"", " for auto-detection of CPU speed.", " --disable-hwf Disable hardware acceleration feature(s)", " for benchmarking.", " --repetitions Use N repetitions (default " STR2(NUM_MEASUREMENT_REPETITIONS) ")", " --unaligned Use unaligned input buffers.", " --csv Use CSV output format", NULL }; const char **line; for (line = help_lines; *line; line++) fprintf (stdout, "%s\n", *line); } /* Warm up CPU. */ static void warm_up_cpu (void) { struct nsec_time start, end; get_nsec_time (&start); do { get_nsec_time (&end); } while (get_time_nsec_diff (&start, &end) < 1000.0 * 1000.0 * 1000.0); } int main (int argc, char **argv) { int last_argc = -1; if (argc) { argc--; argv++; } /* We skip this test if we are running under the test suite (no args and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */ if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS")) exit (77); if (getenv ("GCRYPT_IN_REGRESSION_TEST")) { in_regression_test = 1; num_measurement_repetitions = 2; } else num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS; while (argc && last_argc != argc) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { print_help (); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--csv")) { csv_mode = 1; argc--; argv++; } else if (!strcmp (*argv, "--unaligned")) { unaligned_mode = 1; argc--; argv++; } else if (!strcmp (*argv, "--disable-hwf")) { argc--; argv++; if (argc) { if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL)) fprintf (stderr, PGM ": unknown hardware feature `%s' - option ignored\n", *argv); argc--; argv++; } } else if (!strcmp (*argv, "--cpu-mhz")) { argc--; argv++; if (argc) { if (!strcmp (*argv, "auto")) { auto_ghz = 1; } else { cpu_ghz = atof (*argv); cpu_ghz /= 1000; /* Mhz => Ghz */ } argc--; argv++; } } else if (!strcmp (*argv, "--repetitions")) { argc--; argv++; if (argc) { num_measurement_repetitions = atof (*argv); if (num_measurement_repetitions < 2) { fprintf (stderr, PGM ": value for --repetitions too small - using %d\n", NUM_MEASUREMENT_REPETITIONS); num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS; } argc--; argv++; } } } xgcry_control ((GCRYCTL_SET_VERBOSITY, (int) verbose)); if (!gcry_check_version (GCRYPT_VERSION)) { fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n", GCRYPT_VERSION, gcry_check_version (NULL)); exit (1); } if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; if (in_regression_test) fputs ("Note: " PGM " running in quick regression test mode.\n", stdout); if (!argc) { warm_up_cpu (); hash_bench (NULL, 0); mac_bench (NULL, 0); cipher_bench (NULL, 0); kdf_bench (NULL, 0); ecc_bench (NULL, 0); } else if (!strcmp (*argv, "hash")) { argc--; argv++; warm_up_cpu (); hash_bench ((argc == 0) ? NULL : argv, argc); } else if (!strcmp (*argv, "mac")) { argc--; argv++; warm_up_cpu (); mac_bench ((argc == 0) ? NULL : argv, argc); } else if (!strcmp (*argv, "cipher")) { argc--; argv++; warm_up_cpu (); cipher_bench ((argc == 0) ? NULL : argv, argc); } else if (!strcmp (*argv, "kdf")) { argc--; argv++; warm_up_cpu (); kdf_bench ((argc == 0) ? NULL : argv, argc); } else if (!strcmp (*argv, "ecc")) { argc--; argv++; warm_up_cpu (); ecc_bench ((argc == 0) ? NULL : argv, argc); } else { fprintf (stderr, PGM ": unknown argument: %s\n", *argv); print_help (); } return 0; } #endif /* !NO_GET_NSEC_TIME */ diff --git a/tests/curves.c b/tests/curves.c index 2dd067a0..3c738171 100644 --- a/tests/curves.c +++ b/tests/curves.c @@ -1,353 +1,353 @@ /* curves.c - ECC curves regression tests * Copyright (C) 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "../src/gcrypt-int.h" #define PGM "curves" #include "t-common.h" /* Number of curves defined in ../cipher/ecc-curves.c */ #define N_CURVES 27 /* A real world sample public key. */ static char const sample_key_1[] = "(public-key\n" " (ecdsa\n" " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)\n" " (a #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC#)\n" " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)\n" " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)\n" " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)\n" " (h #000000000000000000000000000000000000000000000000000000000000000001#)\n" " (q #0442B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146EE" "86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E#)\n" " ))"; static char const sample_key_1_curve[] = "NIST P-256"; static unsigned int sample_key_1_nbits = 256; /* A made up sample public key. */ static char const sample_key_2[] = "(public-key\n" " (ecdh\n" " (p #00e95e4a5f737059dc60dfc7ad95b3d8139515620f#)\n" " (a #340e7be2a280eb74e2be61bada745d97e8f7c300#)\n" " (b #1e589a8595423412134faa2dbdec95c8d8675e58#)\n" " (g #04bed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3" "1667cb477a1a8ec338f94741669c976316da6321#)\n" " (n #00e95e4a5f737059dc60df5991d45029409e60fc09#)\n" " (h #000000000000000000000000000000000000000000000000000000000000000001#)\n" " (q #041111111111111111111111111111111111111111" "2222222222222222222222222222222222222222#)\n" " ))"; static char const sample_key_2_curve[] = "brainpoolP160r1"; static unsigned int sample_key_2_nbits = 160; -static int in_fips_mode = 0; +static int in_fips_mode; static void list_curves (void) { int idx; const char *name; unsigned int nbits; for (idx=0; (name = gcry_pk_get_curve (NULL, idx, &nbits)); idx++) { if (verbose) printf ("%s - %u bits\n", name, nbits); } if (idx != N_CURVES) fail ("expected %d curves but got %d\n", N_CURVES, idx); if (gcry_pk_get_curve (NULL, -1, NULL)) fail ("curve iteration failed\n"); } static void check_matching (void) { gpg_error_t err; gcry_sexp_t key; const char *name; unsigned int nbits; err = gcry_sexp_new (&key, sample_key_1, 0, 1); if (err) die ("parsing s-expression string failed: %s\n", gpg_strerror (err)); name = gcry_pk_get_curve (key, 0, &nbits); if (!name) fail ("curve name not found for sample_key_1\n"); else if (strcmp (name, sample_key_1_curve)) fail ("expected curve name %s but got %s for sample_key_1\n", sample_key_1_curve, name); else if (nbits != sample_key_1_nbits) fail ("expected curve size %u but got %u for sample_key_1\n", sample_key_1_nbits, nbits); gcry_sexp_release (key); if (!in_fips_mode) { err = gcry_sexp_new (&key, sample_key_2, 0, 1); if (err) die ("parsing s-expression string failed: %s\n", gpg_strerror (err)); name = gcry_pk_get_curve (key, 0, &nbits); if (!name) fail ("curve name not found for sample_key_2\n"); else if (strcmp (name, sample_key_2_curve)) fail ("expected curve name %s but got %s for sample_key_2\n", sample_key_2_curve, name); else if (nbits != sample_key_2_nbits) fail ("expected curve size %u but got %u for sample_key_2\n", sample_key_2_nbits, nbits); gcry_sexp_release (key); } } #define TEST_ERROR_EXPECTED (1 << 0) #define TEST_NOFIPS (1 << 1) static void check_get_params (void) { static struct { int algo; const char *name; int flags; } tv[] = { { GCRY_PK_ECC, "Ed25519", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.6.1.4.1.11591.15.1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.101.112", TEST_NOFIPS }, { GCRY_PK_ECC, "Curve25519", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.6.1.4.1.3029.1.5.1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.101.110", TEST_NOFIPS }, { GCRY_PK_ECC, "X25519", TEST_NOFIPS }, { GCRY_PK_ECC, "Ed448", TEST_NOFIPS }, { GCRY_PK_ECC, "X448", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.101.113", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.101.111", TEST_NOFIPS }, { GCRY_PK_ECC, "NIST P-192", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.840.10045.3.1.1", TEST_NOFIPS }, { GCRY_PK_ECC, "prime192v1", TEST_NOFIPS }, { GCRY_PK_ECC, "secp192r1", TEST_NOFIPS }, { GCRY_PK_ECC, "nistp192", TEST_NOFIPS }, { GCRY_PK_ECC, "NIST P-224" }, { GCRY_PK_ECC, "secp224r1" }, { GCRY_PK_ECC, "1.3.132.0.33" }, { GCRY_PK_ECC, "nistp224" }, { GCRY_PK_ECC, "NIST P-256" }, { GCRY_PK_ECC, "1.2.840.10045.3.1.7" }, { GCRY_PK_ECC, "prime256v1" }, { GCRY_PK_ECC, "secp256r1" }, { GCRY_PK_ECC, "nistp256" }, { GCRY_PK_ECC, "NIST P-384" }, { GCRY_PK_ECC, "secp384r1" }, { GCRY_PK_ECC, "1.3.132.0.34" }, { GCRY_PK_ECC, "nistp384" }, { GCRY_PK_ECC, "NIST P-521" }, { GCRY_PK_ECC, "secp521r1" }, { GCRY_PK_ECC, "1.3.132.0.35" }, { GCRY_PK_ECC, "nistp521" }, { GCRY_PK_ECC, "brainpoolP160r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.1", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP192r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.3", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP224r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.5", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP256r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.7", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP320r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.9", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP384r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.11", TEST_NOFIPS }, { GCRY_PK_ECC, "brainpoolP512r1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.13", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-test", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.35.0", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.35.1", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.35.2", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.35.3", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-XchA", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-XchB", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.36.0", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.2.2.36.1", TEST_NOFIPS }, /* Noet that GOST2012-256-tc26-A" is only in the curve alias * list but has no parameter entry. */ { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.2", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-256-tc26-B", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.3", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-256-tc26-C", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.4", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-256-tc26-D", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-test", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-test", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-test", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.0", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-tc26-A", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-tc26-A", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-tc26-B", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-tc26-B", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-tc26-A", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.1", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-tc26-B", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.2", TEST_NOFIPS }, { GCRY_PK_ECC, "GOST2012-512-tc26-C", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.3", TEST_NOFIPS }, { GCRY_PK_ECC, "secp256k1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.3.132.0.10", TEST_NOFIPS }, { GCRY_PK_ECC, "sm2p256v1", TEST_NOFIPS }, { GCRY_PK_ECC, "1.2.156.10197.1.301", TEST_NOFIPS }, /* Check also the ECC algo mapping. */ { GCRY_PK_ECDSA, "Ed25519", TEST_NOFIPS }, { GCRY_PK_EDDSA, "Ed25519", TEST_NOFIPS }, { GCRY_PK_ECDH, "Ed25519", TEST_NOFIPS }, { GCRY_PK_ECDSA, "Curve25519", TEST_NOFIPS }, { GCRY_PK_EDDSA, "Curve25519", TEST_NOFIPS }, { GCRY_PK_ECDH, "Curve25519", TEST_NOFIPS }, { GCRY_PK_ECC, "NoSuchCurve", TEST_ERROR_EXPECTED }, { GCRY_PK_RSA, "rsa", TEST_ERROR_EXPECTED }, { GCRY_PK_ELG, "elg", TEST_ERROR_EXPECTED }, { GCRY_PK_DSA, "dsa", TEST_ERROR_EXPECTED } }; int idx; gcry_sexp_t param; const char *name; param = gcry_pk_get_param (GCRY_PK_ECDSA, sample_key_1_curve); if (!param) fail ("error gerring parameters for `%s'\n", sample_key_1_curve); name = gcry_pk_get_curve (param, 0, NULL); if (!name) fail ("get_param: curve name not found for sample_key_1\n"); else if (strcmp (name, sample_key_1_curve)) fail ("get_param: expected curve name %s but got %s for sample_key_1\n", sample_key_1_curve, name); gcry_sexp_release (param); if (!in_fips_mode) { param = gcry_pk_get_param (GCRY_PK_ECDSA, sample_key_2_curve); if (!param) fail ("error gerring parameters for `%s'\n", sample_key_2_curve); name = gcry_pk_get_curve (param, 0, NULL); if (!name) fail ("get_param: curve name not found for sample_key_2\n"); else if (strcmp (name, sample_key_2_curve)) fail ("get_param: expected curve name %s but got %s for sample_key_2\n", sample_key_2_curve, name); gcry_sexp_release (param); } /* Some simple tests */ for (idx=0; idx < DIM (tv); idx++) { param = gcry_pk_get_param (tv[idx].algo, tv[idx].name); if (in_fips_mode && tv[idx].flags & TEST_NOFIPS) { if (param) fail ("get_param: test %d (%s) should have failed in fips mode\n", idx, tv[idx].name); } else { if (!param) { if (!(tv[idx].flags & TEST_ERROR_EXPECTED)) fail ("get_param: test %d (%s) failed\n", idx, tv[idx].name); } else { if (tv[idx].flags & TEST_ERROR_EXPECTED) fail ("get_param: test %d (%s) failed (error expected)\n", idx, tv[idx].name); } } gcry_sexp_release (param); } } int main (int argc, char **argv) { if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) verbose = debug = 1; if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; list_curves (); check_matching (); check_get_params (); return error_count ? 1 : 0; } diff --git a/tests/dsa-rfc6979.c b/tests/dsa-rfc6979.c index b647efa2..cd68cd25 100644 --- a/tests/dsa-rfc6979.c +++ b/tests/dsa-rfc6979.c @@ -1,993 +1,993 @@ /* dsa-rfc6979.c - Test for Deterministic DSA * Copyright (C) 2008 Free Software Foundation, Inc. * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifndef _GCRYPT_IN_LIBGCRYPT # include #endif #define PGM "dsa-rfc6979" #include "t-common.h" -static int in_fips_mode = 0; +static int in_fips_mode; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) { fail ("parameter \"%s\" does not match expected value\n", name); if (verbose) { info ("expected: %s\n", expected); show_sexp ("sexp: ", sexp); } } gcry_free (b); gcry_sexp_release (l1); } /* These test vectors are from RFC 6979. */ static void check_dsa_rfc6979 (void) { static struct { const char *name; const char *key; int fips; } keys[] = { { "DSA, 1024 bits", "(private-key" " (DSA" " (p #86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" " E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" " 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" " 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779#)" " (q #996F967F6C8E388D9E28D01E205FBA957A5698B1#)" " (g #07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" " 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" " 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" " 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD#)" " (x #411602CB19A6CCC34494D79D98EF1E7ED5AF25F7#)" " (y #5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653" " 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D" " 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6" " 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B#)" " ))", 0 }, { "DSA, 2048 bits", "(private-key" " (DSA" " (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" " C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" " FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" " B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" " 35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" " F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" " 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" " 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)" " (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)" " (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" " D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" " 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" " 085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" " AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" " 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" " BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" " DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)" " (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)" " (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94" " 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61" " 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE" " CB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB" " 5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254" " 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1" " 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA" " 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)" " ))", 0 }, { "ECDSA, 192 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-192\")" " (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56" " 3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)" " (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)" " ))", 0 }, { "ECDSA, 224 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-224\")" " (q #04" " 00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C" " EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A#)" " (d #F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1#)" " ))", 1 }, { "ECDSA, 256 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-256\")" " (q #04" " 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6" " 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)" " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)" " ))", 1 }, { "ECDSA, 384 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-384\")" " (q #04" " EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64" " DEF8F0EA9055866064A254515480BC13" " 8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1" " 288B231C3AE0D4FE7344FD2533264720#)" " (d #6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" " 96D5724E4C70A825F872C9EA60D2EDF5#)" " ))", 1 }, { "ECDSA, 521 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-521\")" " (q #04" " 01894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD" " 371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F50" " 23A4" " 00493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A" " 28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFD" " FCF5#)" " (d #FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75" " CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B8" " 3538#)" " ))", 1 }, { NULL } }; static struct { const char *keyname; const char *name; const char *hashname; const char *message; const char *k, *r, *s; } tests[] = { { "DSA, 1024 bits", "With SHA-1, message = \"sample\"", "sha1", "sample", "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", "2E1A0C2562B2912CAAF89186FB0F42001585DA55", "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5" }, { "DSA, 1024 bits", "With SHA-224, message = \"sample\"", "sha224", "sample", "562097C06782D60C3037BA7BE104774344687649", "4BC3B686AEA70145856814A6F1BB53346F02101E", "410697B92295D994D21EDD2F4ADA85566F6F94C1" }, { "DSA, 1024 bits", "With SHA-256, message = \"sample\"", "sha256", "sample", "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", "81F2F5850BE5BC123C43F71A3033E9384611C545", "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89" }, { "DSA, 1024 bits", "With SHA-384, message = \"sample\"", "sha384", "sample", "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", "54DF70456C86FAC10FAB47C1949AB83F2C6F7595" }, { "DSA, 1024 bits", "With SHA-512, message = \"sample\"", "sha512", "sample", "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C" }, { "DSA, 1024 bits", "With SHA-1, message = \"test\"", "sha1", "test", "5C842DF4F9E344EE09F056838B42C7A17F4A6433", "42AB2052FD43E123F0607F115052A67DCD9C5C77", "183916B0230D45B9931491D4C6B0BD2FB4AAF088" }, { "DSA, 1024 bits", "With SHA-224, message = \"test\"", "sha224", "test", "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", "6868E9964E36C1689F6037F91F28D5F2C30610F2", "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F" }, { "DSA, 1024 bits", "With SHA-256, message = \"test\"", "sha256", "test", "5A67592E8128E03A417B0484410FB72C0B630E1A", "22518C127299B0F6FDC9872B282B9E70D0790812", "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160" }, { "DSA, 1024 bits", "With SHA-384, message = \"test\"", "sha384", "test", "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", "91D0E0F53E22F898D158380676A871A157CDA622" }, { "DSA, 1024 bits", "With SHA-512, message = \"test\"", "sha512", "test", "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", "7C670C7AD72B6C050C109E1790008097125433E8" }, { "DSA, 2048 bits", "With SHA-1, message = \"sample\"", "sha1", "sample", "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF" }, { "DSA, 2048 bits", "With SHA-224, message = \"sample\"", "sha224", "sample", "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC" }, { "DSA, 2048 bits", "With SHA-256, message = \"sample\"", "sha256", "sample", "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53" }, { "DSA, 2048 bits", "With SHA-384, message = \"sample\"", "sha384", "sample", "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B" }, { "DSA, 2048 bits", "With SHA-512, message = \"sample\"", "sha512", "sample", "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351" }, { "DSA, 2048 bits", "With SHA-1, message = \"test\"", "sha1", "test", "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA" }, { "DSA, 2048 bits", "With SHA-224, message = \"test\"", "sha224", "test", "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806" }, { "DSA, 2048 bits", "With SHA-256, message = \"test\"", "sha256", "test", "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E" }, { "DSA, 2048 bits", "With SHA-384, message = \"test\"", "sha384", "test", "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961" }, { "DSA, 2048 bits", "With SHA-512, message = \"test\"", "sha512", "test", "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1" }, { "ECDSA, 192 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64" }, { "ECDSA, 192 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A" }, { "ECDSA, 192 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85" }, { "ECDSA, 192 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E" }, { "ECDSA, 192 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67" }, { "ECDSA, 192 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7" }, { "ECDSA, 192 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293" }, { "ECDSA, 192 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F" }, { "ECDSA, 192 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A" }, { "ECDSA, 192 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290" }, { "ECDSA, 224 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69" }, { "ECDSA, 224 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC" }, { "ECDSA, 224 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101" }, { "ECDSA, 224 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D" }, { "ECDSA, 224 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084" }, { "ECDSA, 224 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2" }, { "ECDSA, 224 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4" }, { "ECDSA, 224 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD" }, { "ECDSA, 224 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB" }, { "ECDSA, 224 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF" }, { "ECDSA, 256 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB" }, { "ECDSA, 256 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C" }, { "ECDSA, 256 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8" }, { "ECDSA, 256 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954" }, { "ECDSA, 256 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE" }, { "ECDSA, 256 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1" }, { "ECDSA, 256 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D" }, { "ECDSA, 256 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083" }, { "ECDSA, 256 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C" }, { "ECDSA, 256 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55" }, { "ECDSA, 384 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB09663" "0F29E5938D25106C3C340045A2DB01A7", "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3" "7B9BA002899F6FDA3A4A9386790D4EB2", "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF" "26F49CA031D4857570CCB5CA4424A443" }, { "ECDSA, 384 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB" "8083EE4E3C45B06A5899EA56C51B5879", "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366" "450F76EE3DE43F5A125333A6BE060122", "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483" "4C082C03D83028EFBF93A3C23940CA8D" }, { "ECDSA, 384 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E" "375572342863C899F9F2EDF9747A9B60", "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33" "BDE1E888E63355D92FA2B3C36D8FB2CD", "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB" "EFDC63ECCD1AC42EC0CB8668A4FA0AB0" }, { "ECDSA, 384 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA" "2907E3E83BA95368623B8C4686915CF9", "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C" "81A648152E44ACF96E36DD1E80FABE46", "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F" "A329C145786E679E7B82C71A38628AC8" }, { "ECDSA, 384 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331" "A4E966532593A52980D0E3AAA5E10EC3", "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C" "FE30F35CC900056D7C99CD7882433709", "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112" "DC7CC3EF3446DEFCEB01A45C2667FDD5" }, { "ECDSA, 384 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47" "EC3727F3A3C186C15054492E30698497", "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678" "ACD9D29876DAF46638645F7F404B11C7", "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916" "95BA1C84541327E966FA7B50F7382282" }, { "ECDSA, 384 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E" "3D33BE4DC5EB8886A8ECD093F2935726", "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624" "64A9A817C47FF78B8C11066B24080E72", "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614" "1C53EA5ABEF0D8231077A04540A96B66" }, { "ECDSA, 384 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FA" "A48DD070BA79921A3457ABFF2D630AD7", "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559" "F918EEDAF2293BE5B475CC8F0188636B", "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D" "51AB373F9845C0514EEFB14024787265" }, { "ECDSA, 384 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092AD" "A71F4A459BC0DA98ADB95837DB8312EA", "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB" "0542A7F0812998DA8F1DD3CA3CF023DB", "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0" "6A739F040649A667BF3B828246BAA5A5" }, { "ECDSA, 384 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE" "0E2CC8A136036DC4B9C00E6888F66B6C", "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0" "6FB6495CD21B4B6E340FC236584FB277", "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463" "4A2092CD3792E0159AD9CEE37659C736" }, { "ECDSA, 521 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB" "42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D" "0F9", "343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910" "FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D" "75D", "E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D" "5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5" "D16" }, { "ECDSA, 521 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0" "493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B9211" "3F3", "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3" "0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E" "D2E", "50CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B" "A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B" "41F" }, { "ECDSA, 521 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C3257576" "1793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E" "1A0", "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659" "D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E" "1A7", "4A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916" "E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E" "CFC" }, { "ECDSA, 521 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "1546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FF" "AD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4" "211", "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4" "B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67" "451", "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5" "FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65" "D61" }, { "ECDSA, 521 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F1019" "8B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBF" "FD3", "C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1" "74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37" "7FA", "617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2" "82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A" "67A" }, { "ECDSA, 521 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "0BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DD" "BA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B" "222", "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0" "693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0" "367", "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90" "F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679" "7FF" }, { "ECDSA, 521 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A011369" "87E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F" "706", "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086" "BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1" "7FB", "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5" "BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51" "9A4" }, { "ECDSA, 521 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "01DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E84384" "1AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909" "258", "0E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104" "2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656" "AA8", "CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9" "FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694" "E86" }, { "ECDSA, 521 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "1F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5D" "CEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0" "C88", "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C" "89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755" "78C", "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E" "D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B" "979" }, { "ECDSA, 521 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1" "B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC" "56D", "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10" "CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E" "E6D", "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78" "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D" "CE3" }, { NULL } }; gpg_error_t err; int tno, i, hashalgo; gcry_sexp_t seckey, data, sig; unsigned char digest[64]; int digestlen; for (tno = 0; tests[tno].keyname; tno++) { if (verbose) info ("Test %d: %s. %s.\n", tno, tests[tno].keyname, tests[tno].name); { for (i=0; keys[i].name; i++) if (!strcmp (tests[tno].keyname, keys[i].name)) break; if (!keys[i].name) die ("Key '%s' used by test '%s' not found\n", tests[tno].keyname, tests[tno].name); err = gcry_sexp_new (&seckey, keys[i].key, 0, 1); if (err) die ("reading key failed: %s\n", gpg_strerror (err)); } hashalgo = gcry_md_map_name (tests[tno].hashname); if (!hashalgo) die ("hash with name '%s' is not supported\n", tests[tno].hashname); digestlen = gcry_md_get_algo_dlen (hashalgo); if (digestlen > sizeof digest) die ("internal error: digest does not fit into our buffer\n"); gcry_md_hash_buffer (hashalgo, digest, tests[tno].message, strlen (tests[tno].message)); err = gcry_sexp_build (&data, NULL, "(data " " (flags rfc6979)" " (hash %s %b))", tests[tno].hashname, digestlen, digest); if (err) die ("building data sexp failed: %s\n", gpg_strerror (err)); err = gcry_pk_sign (&sig, data, seckey); if (in_fips_mode && !keys[i].fips) { if (!err) fail ("signing should not work in FIPS mode: %s\n", gpg_strerror (err)); continue; } if (err) fail ("signing failed: %s\n", gpg_strerror (err)); extract_cmp_data (sig, "r", tests[tno].r); extract_cmp_data (sig, "s", tests[tno].s); err = gcry_pk_verify (sig, data, seckey); if (err) fail ("verification failed: %s\n", gpg_strerror (err)); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (seckey); } } int main (int argc, char **argv) { if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); /* Check that we test exactly our version - including the patchlevel. */ if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL))) die ("version mismatch; pgm=%s, library=%s\n", GCRYPT_VERSION,gcry_check_version (NULL)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); check_dsa_rfc6979 (); return error_count ? 1 : 0; } diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c index 22a88892..3f7c0d1b 100644 --- a/tests/fips186-dsa.c +++ b/tests/fips186-dsa.c @@ -1,588 +1,588 @@ /* fips186-dsa.c - FIPS 186 DSA tests * Copyright (C) 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef _GCRYPT_IN_LIBGCRYPT # include "../src/gcrypt-int.h" #else # include #endif #define PGM "fips186-dsa" #include "t-common.h" -static int in_fips_mode = 0; +static int in_fips_mode; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } static gcry_mpi_t mpi_from_string (const char *string) { gpg_error_t err; gcry_mpi_t a; err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, string, 0, NULL); if (err) die ("error converting string to mpi: %s\n", gpg_strerror (err)); return a; } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; gcry_mpi_t a, b; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); b = mpi_from_string (expected); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( gcry_mpi_cmp (a, b) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_mpi_release (b); gcry_mpi_release (a); gcry_sexp_release (l1); } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (b); gcry_sexp_release (l1); } static void extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected) { gcry_sexp_t l1; char *a; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_string (l1, 1); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( strtoul (a, NULL, 10) != expected ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (a); gcry_sexp_release (l1); } static void check_dsa_gen_186_2 (void) { static struct { int nbits; const char *p, *q, *g; const char *seed; int counter; const char *h; } tbl[] = { /* These tests are from FIPS 186-2, DSAVS B.3.1 PQGGen.rsp. CAVS 2.2. */ { 1024, "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69", "9c916d121de9a03f71fb21bc2e1c0d116f065a4f", "8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44", "0cb1990c1fd3626055d7a0096f8fa99807399871", 98, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002" }, { 1024, "f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f" "8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb" "0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be" "3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9", "f8751166cf4f6f3b07c081fd2a9071f23ca1988d", "1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62" "4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a" "665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c" "4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33", "34b3520d45d240a8861b82c8b61ffa16e67b5cce", 622, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7" "b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4" "55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc" "1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad", "d32b29f065c1394a30490b6fcbf812a32a8634ab", "06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1" "ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714" "c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231" "80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2", "b6ec750da2f824cb42c5f7e28c81350d97f75125", 185, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b" "ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f" "d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b" "c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5", "de822c03445b77cec4ad3a6fb0ca39ff97059ddf", "65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371" "681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b" "848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69" "1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748", "cd2221dd73815a75224e9fde7faf52829b81ac7a", 62, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803" "ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891" "354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9" "8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227", "c6d786643d2acfc6b8d576863fda8cfbfbd5e03f", "2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d" "af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d" "5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb" "e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb", "73483e697599871af983a281e3afa22e0ed86b68", 272, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, /* These tests are generated by the OpenSSL FIPS version. */ { 1024, "A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C" "A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255" "EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033" "11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9", "C643946CEA8748E12D430C48DB038F9165814389", "59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16" "892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC" "B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7" "44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225", "02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd", 50, "02" }, { 1024, "9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987" "6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3" "D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450" "04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5", "AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7", "74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701" "95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E" "039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A" "C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498", "6481a12a50384888ee84b61024f7c9c685d6ac96", 289, "02" }, { 1024, "B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828" "1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63" "5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503" "B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF", "EA649C04911FAB5A41440287A517EF752A40354B", "88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162" "01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194" "93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C" "858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696", "5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a", 626, "02" }, { 1024, "F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C" "F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D" "5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977" "CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD", "A40D9EE456AED4C8A653FDB47B6629C0B843FE8F", "DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE" "700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614" "F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7" "2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67", "8a9a57706f69f4f566252cdf6d5cbfdf2020150b", 397, "02" }, { 1024, "D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068" "29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934" "96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A" "093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B", "D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5", "468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC" "58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5" "7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159" "928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839", "30b3599944a914a330a3f49d11ec88f555422aef", 678, "02" } }; gpg_error_t err; int tno; gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; gcry_sexp_t l1; for (tno = 0; tno < DIM (tbl); tno++) { if (verbose) info ("generating FIPS 186-2 test key %d\n", tno); { void *data; size_t datalen; data = data_from_hex (tbl[tno].seed, &datalen); err = gcry_sexp_build (&key_spec, NULL, "(genkey (dsa (nbits %d)(use-fips186-2)" "(derive-parms(seed %b))))", tbl[tno].nbits, (int)datalen, data); gcry_free (data); } if (err) die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { if (in_fips_mode) { if (verbose > 1) fprintf (stderr, "DSA keys are not available in FIPS mode"); } else fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); continue; } if (verbose > 1) show_sexp ("generated key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) fail ("public part missing in key %d\n", tno); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) fail ("private part missing in key %d\n", tno); l1 = gcry_sexp_find_token (key, "misc-key-info", 0); if (!l1) fail ("misc_key_info part missing in key %d\n", tno); seed_values = gcry_sexp_find_token (l1, "seed-values", 0); if (!seed_values) fail ("seed-values part missing in key %d\n", tno); gcry_sexp_release (l1); extract_cmp_mpi (sec_key, "p", tbl[tno].p); extract_cmp_mpi (sec_key, "q", tbl[tno].q); extract_cmp_mpi (sec_key, "g", tbl[tno].g); extract_cmp_data (seed_values, "seed", tbl[tno].seed); extract_cmp_int (seed_values, "counter", tbl[tno].counter); extract_cmp_mpi (seed_values, "h", tbl[tno].h); gcry_sexp_release (seed_values); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); gcry_sexp_release (key); } } static void check_dsa_gen_186_3 (void) { static struct { int nbits, qbits; const char *p, *q; const char *seed; int counter; } tbl[] = { /* These tests are from FIPS 186-3 Test Vectors, PQGGen.rsp. CAVS 11.1. */ { 2048, 256, "8e2266d5cb5b1e9ad34ac6380e3d166fd4d60dadc6dfa1be8492a5642c91fdf7" "e81b9634a4eeff59e7e93b1b0e8f49ded45a72788866dff71b1329feeb4b6cdb" "f2c7166c7cbca20b04300ae127c9940233e891712ac905ed6b43495717a2998e" "a8c4eef4ec6c32dc9e774e8e66476f17d9c39abac59e8b583b1107b679e0bed0" "78476e933a90cfcf80c89b831c0e054f86eac7ca848e059662d938a4e12947e2" "e73b1ffedd7125dd54ba463217abc9c5f3399132aec77b946c806429f6f812c1" "0716d57dde7b5d45cb2e5eb6e4dbb81d5a465054fa17e613cbe01afb49ea593f" "33f1a696a774941ca1ff6f208577fe529f5e7592f39698c63bf6ae9d56cd2d93", "b19c6d094e1210c92910f49aa083957fbe68c0ca4602896f50123fd776786275", "f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b", 105 }, { 2048, 256, "b636e5970383cecab68840cca8a909a29325c3924e2c187dd034222f9e1a4334" "1061ca620f82787bd349fb8f380fc3f0adb84be116c695529114aecee8a0a1b0" "9e7ebb6888e6da71f48eefb3e9990e2d7bd36c1aa24fb10e011a193d6b5a1b22" "6cf97fab302e237ecb1dc824264dba2e2285930005717c4e9a12cc1a1ac336c2" "0619c4d06ec4e1e02e0d1d2d285661a7472d30c4282646506487cbe6a5c988ee" "8402d474713a7d8213eeb19a0719996bbfd3835eb8832eead5a3a340e61c52f0" "0dde1c98655a13839ad215d8f43c8e482317af8b086c3d555fc8dbb2f595f256" "3520a0c6387661774e1e6ca5fe2626b26a2c4f99b7aff043a091434dfd3275b7", "fe9f06fa1901182ab00bf063bff8fd4f736922ce830fd50fee47ebbd21e291e9", "3a66a430f23374ce3d2e758881c411c23dad4a8cd6ad697056d24b8cfcc8c353", 720 }, { 2048, 256, "8d636640981c2ce1935bd16ad3aa3ce2a6efa26f23f07ceda92766f80e82fa03" "5c6cf44dc41e08fea242c5cd5846d839bdf0c11d3a29ebaca00aad844cd33a80" "448f1f96cebe66b9963f7e3b5c976e29dc430bc5ddf5d2c198eb736339adc14d" "5c8a3d22533d7c6a861b6a8b31c55e46804e4c2f95e2e9cc2bbb23bbc833995a" "7afe619127d28fa53b0712b17da4786f9116cc39e2c6254845e85513c220e368" "fe9c92bc71eabfa831062f01e66e8a970f043112ca0af175f64d13fcff2f087f" "ff9198a9fe9732001ab49b2a48d0e39f99d036698703aa853ac02c65f3d55993" "5a72c8bbc6ab2fa59ff9a2fcd837a4675229abed23d42badc12a60b34a3bf0f5", "b5f3c535e7f48d3251d353b73b3a05c4bdb4591a8c2f2ba4a6a945a889f5aeff", "77eb88f087bfbbc312bca7572bafd36f2a7aca2e4d7378dd923b0b277f3d730f", 137 }, { 2048, 256, "8fa95228b848a9533375e4789c88bb7df505c4478ed3c79545c5d2b04f0e0efb" "ac8d3f603603a48b203e1cc67ded22b840ac21bc41b7ab78c73a9cd0773148ca" "7c87a5a51564164f683e8f8a77b97cf7d91f989aa3668819bca8f54e0ec8f10c" "78ecd26982048cf0ab0446a6de154bbed8891be916627d470061811caf51bef1" "b5be8ef2b560cf981c2a097b3769bed61d6ee9b66221e956fe2c49f1809a2d5f" "6996be7b39f41afea5184a73c049f3abbd28fddbf37bcae6c4aa4a7255464c2e" "ee915c44b8d90d76e5d9e3d8e6cf4ac7c5d9436d19ccc27c5bc1b65dbb56723b" "5e77624489652313f9da2ce38554401fdbd61c78f2a4fa69bcc2f5aaffbfed2d", "ed3f52bce81572d126b27fb1e9c02346ae523532af82b79943565593d6f46d45", "e0ed96bf5e7d78754b5095ed766a1bbc4338eaa8f3d00e9906ef51a8798bc1c2", 40 }, { 2048, 256, "a80f2481a814d07eb47a7c67e24bc3f8f1ccebc6cf684a0bc9fbb0054cc24cef" "24872315b566630d5147184980b4bce3f0849660c84b22dfacb785446c0f6314" "b7a53a92cf821bcceb325e03dc9e404832146d34ff8a9b112ed0e69efe69c619" "5de03373e590eba88fc5b9d337d6566dc7e82e326a28343f644779f6784159eb" "3d33f2ddf1157a02f2f91d0897a4e8ad53f614186a5fe043187510316904bd95" "6966e10735d6ef01c195b7dd7fd245a83c18af7908fef0bced2f454e1954f2a3" "2c35658f4e0f5811a3d06c81cca715537debabbbc65ba4dd0e7fb0c08397622f" "039a51df69f5b10dda61f57bbb84c55f25eacd0f3d8b40ae016ed0ba856837e7", "9e3b5a7939082c95069902d3833df8421871ca2dab8a34f7be6cd39151291d07", "c7bb440d973189ca07464b037fd309f68ec38baba390988a2e986ecee281e2f5", 722 } }; gpg_error_t err; int tno; gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; gcry_sexp_t l1; for (tno = 0; tno < DIM (tbl); tno++) { if (verbose) info ("generating FIPS 186-3 test key %d\n", tno); { void *data; size_t datalen; data = data_from_hex (tbl[tno].seed, &datalen); err = gcry_sexp_build (&key_spec, NULL, "(genkey (dsa (nbits %d)(qbits %d)(use-fips186)" "(derive-parms(seed %b))))", tbl[tno].nbits, tbl[tno].qbits, (int)datalen, data); gcry_free (data); } if (err) die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { if (in_fips_mode) { if (verbose > 1) fprintf (stderr, "DSA keys are not available in FIPS mode"); } else fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); continue; } if (verbose > 1) show_sexp ("generated key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) fail ("public part missing in key %d\n", tno); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) fail ("private part missing in key %d\n", tno); l1 = gcry_sexp_find_token (key, "misc-key-info", 0); if (!l1) fail ("misc_key_info part missing in key %d\n", tno); seed_values = gcry_sexp_find_token (l1, "seed-values", 0); if (!seed_values) fail ("seed-values part missing in key %d\n", tno); gcry_sexp_release (l1); extract_cmp_mpi (sec_key, "p", tbl[tno].p); extract_cmp_mpi (sec_key, "q", tbl[tno].q); extract_cmp_data (seed_values, "seed", tbl[tno].seed); extract_cmp_int (seed_values, "counter", tbl[tno].counter); gcry_sexp_release (seed_values); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); gcry_sexp_release (key); } } int main (int argc, char **argv) { if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; check_dsa_gen_186_2 (); check_dsa_gen_186_3 (); return error_count ? 1 : 0; } diff --git a/tests/pubkey.c b/tests/pubkey.c index 751f508c..c5510d05 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -1,1323 +1,1336 @@ /* pubkey.c - Public key encryption/decryption tests * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #define PGM "pubkey" #include "t-common.h" static int in_fips_mode; /* Sample RSA keys, taken from basic.c. */ static const char sample_private_key_1[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" " 83#)\n" " (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" " 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" " 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" " 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9" " 19#)\n" " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" " #)\n" " )\n" ")\n"; /* The same key as above but without p, q and u to test the non CRT case. */ static const char sample_private_key_1_1[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " )\n" ")\n"; /* The same key as above but just without q to test the non CRT case. This should fail. */ static const char sample_private_key_1_2[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" " 83#)\n" " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" " #)\n" " )\n" ")\n"; static const char sample_public_key_1[] = "(public-key\n" " (rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " )\n" ")\n"; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* from ../cipher/pubkey-util.c */ static gpg_err_code_t _gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits) { char buf[50]; const char *s; size_t n; *r_nbits = 0; list = gcry_sexp_find_token (list, "nbits", 0); if (!list) return 0; /* No NBITS found. */ s = gcry_sexp_nth_data (list, 1, &n); if (!s || n >= DIM (buf) - 1 ) { /* NBITS given without a cdr. */ gcry_sexp_release (list); return GPG_ERR_INV_OBJ; } memcpy (buf, s, n); buf[n] = 0; *r_nbits = (unsigned int)strtoul (buf, NULL, 0); gcry_sexp_release (list); return 0; } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) { fail ("parameter \"%s\" does not match expected value\n", name); if (verbose) { info ("expected: %s\n", expected); show_sexp ("sexp: ", sexp); } } gcry_free (b); gcry_sexp_release (l1); } static void check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey, gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain1, cipher, l; gcry_mpi_t x0, x1; int rc; int have_flags; /* Extract data from plaintext. */ l = gcry_sexp_find_token (plain0, "value", 0); x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); /* Encrypt data. */ rc = gcry_pk_encrypt (&cipher, plain0, pkey); if (rc) die ("encryption failed: %s\n", gcry_strerror (rc)); l = gcry_sexp_find_token (cipher, "flags", 0); have_flags = !!l; gcry_sexp_release (l); /* Decrypt data. */ rc = gcry_pk_decrypt (&plain1, cipher, skey); gcry_sexp_release (cipher); if (rc) { if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code) { gcry_mpi_release (x0); return; /* This is the expected failure code. */ } die ("decryption failed: %s\n", gcry_strerror (rc)); } /* Extract decrypted data. Note that for compatibility reasons, the output of gcry_pk_decrypt depends on whether a flags lists (even if empty) occurs in its input data. Because we passed the output of encrypt directly to decrypt, such a flag value won't be there as of today. We check it anyway. */ l = gcry_sexp_find_token (plain1, "value", 0); if (l) { if (!have_flags) die ("compatibility mode of pk_decrypt broken\n"); gcry_sexp_release (plain1); x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); } else { if (have_flags) die ("compatibility mode of pk_decrypt broken\n"); x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG); gcry_sexp_release (plain1); } /* Compare. */ if (gcry_mpi_cmp (x0, x1)) die ("data corrupted\n"); gcry_mpi_release (x0); gcry_mpi_release (x1); } static void check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain; gcry_mpi_t x; int rc; /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); gcry_mpi_release (x); /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %m))", x); gcry_mpi_release (x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); } static void get_keys_sample (gcry_sexp_t *pkey, gcry_sexp_t *skey, int secret_variant) { gcry_sexp_t pub_key, sec_key; int rc; static const char *secret; switch (secret_variant) { case 0: secret = sample_private_key_1; break; case 1: secret = sample_private_key_1_1; break; case 2: secret = sample_private_key_1_2; break; default: die ("BUG\n"); } rc = gcry_sexp_sscan (&pub_key, NULL, sample_public_key_1, strlen (sample_public_key_1)); if (!rc) rc = gcry_sexp_sscan (&sec_key, NULL, secret, strlen (secret)); if (rc) die ("converting sample keys failed: %s\n", gcry_strerror (rc)); *pkey = pub_key; *skey = sec_key; } static void get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (rsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating RSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated RSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (rsa (nbits 4:2048)(use-x931)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating RSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated RSA (X9.31) key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, (fixed_x ? "(genkey (elg (nbits 4:1024)(xvalue my.not-so-secret.key)))" : "(genkey (elg (nbits 3:512)))"), 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) { if (in_fips_mode) { if (verbose) fprintf (stderr, "The Elgamal keys are not available in FIPS modee.\n"); return; } die ("error generating Elgamal key: %s\n", gcry_strerror (rc)); } if (verbose > 1) show_sexp ("generated ELG key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, transient_key ? "(genkey (dsa (nbits 4:2048)(transient-key)))" : "(genkey (dsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) { if (in_fips_mode) { if (verbose) fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); return; } die ("error generating DSA key: %s\n", gcry_strerror (rc)); } if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (nbits 4:2048)(use-fips186)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) { if (in_fips_mode) { if (verbose) fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); return; } die ("error generating DSA key: %s\n", gcry_strerror (rc)); } if (verbose > 1) show_sexp ("generated DSA key (fips 186):\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (transient-key)(domain" "(p #a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe13a059705e" "663230a377bf7323a8fa117100200bfd5adf857393b0bbd67906c081e585410e" "38480ead51684dac3a38f7b64c9eb109f19739a4517cd7d5d6291e8af20a3fbf" "17336c7bf80ee718ee087e322ee41047dabefbcc34d10b66b644ddb3160a28c0" "639563d71993a26543eadb7718f317bf5d9577a6156561b082a10029cd44012b" "18de6844509fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d" "125dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31b9f96d5f" "34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff007e8be2f0be06cc15f#)" "(q #e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e68604d6b9dfb#)" "(g #5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa104abfb5d" "84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff8071d63b9bb956e547" "af3a8df99e5d3061979652ff96b765cb3ee493643544c75dbe5bb39834531952" "a0fb4b0378b3fcbb4c8b5800a5330392a2a04e700bb6ed7e0b85795ea38b1b96" "2741b3f33b9dde2f4ec1354f09e2eb78e95f037a5804b6171659f88715ce1a9b" "0cc90c27f35ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de" "8347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d2183f1ba" "3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb64fd9a6c5b75c4561#)" ")))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) { if (in_fips_mode) { if (verbose) fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); return; } die ("error generating DSA key: %s\n", gcry_strerror (rc)); } if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } #if 0 static void get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (transient-key)(use-fips186)(domain" "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)" "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)" "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)" ")))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating DSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } #endif /*0*/ static void get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey" " (dsa" " (nbits 4:2048)" " (qbits 3:256)" " (use-fips186)" " (transient-key)" " (derive-parms" " (seed #f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b#))))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) { if (in_fips_mode) { if (verbose) fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); return; } die ("error generating DSA key: %s\n", gcry_strerror (rc)); } if (verbose > 1) show_sexp ("generated DSA key (fips 186 with seed):\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void check_run (void) { gpg_error_t err; gcry_sexp_t pkey, skey; int variant; + pkey = skey = NULL; for (variant=0; variant < 3; variant++) { if (verbose) fprintf (stderr, "Checking sample key (%d).\n", variant); get_keys_sample (&pkey, &skey, variant); /* Check gcry_pk_testkey which requires all elements. */ err = gcry_pk_testkey (skey); if ((variant == 0 && err) || (variant > 0 && gpg_err_code (err) != GPG_ERR_NO_OBJ)) die ("gcry_pk_testkey failed: %s\n", gpg_strerror (err)); /* Run the usual check but expect an error from variant 2. */ check_keys (pkey, skey, 800, variant == 2? GPG_ERR_NO_OBJ : 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); + pkey = skey = NULL; } if (verbose) fprintf (stderr, "Checking generated RSA key.\n"); get_keys_new (&pkey, &skey); check_keys (pkey, skey, 800, 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Checking generated RSA key (X9.31).\n"); get_keys_x931_new (&pkey, &skey); check_keys (pkey, skey, 800, 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Checking generated Elgamal key.\n"); get_elg_key_new (&pkey, &skey, 0); if (!in_fips_mode) - { - check_keys (pkey, skey, 400, 0); - gcry_sexp_release (pkey); - gcry_sexp_release (skey); - } + check_keys (pkey, skey, 400, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Checking passphrase generated Elgamal key.\n"); get_elg_key_new (&pkey, &skey, 1); if (!in_fips_mode) - { - check_keys (pkey, skey, 800, 0); - gcry_sexp_release (pkey); - gcry_sexp_release (skey); - } + check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Generating DSA key.\n"); get_dsa_key_new (&pkey, &skey, 0); if (!in_fips_mode) { /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + ; } + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; + if (verbose) fprintf (stderr, "Generating transient DSA key.\n"); get_dsa_key_new (&pkey, &skey, 1); if (!in_fips_mode) { /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + ; } + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Generating DSA key (FIPS 186).\n"); get_dsa_key_fips186_new (&pkey, &skey); if (!in_fips_mode) { /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + ; } + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; if (verbose) fprintf (stderr, "Generating DSA key with given domain.\n"); get_dsa_key_with_domain_new (&pkey, &skey); if (!in_fips_mode) { /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + ; } + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; /* We need new test vectors for get_dsa_key_fips186_with_domain_new. */ if (verbose) fprintf (stderr, "Generating DSA key with given domain (FIPS 186)" " - skipped.\n"); /* get_dsa_key_fips186_with_domain_new (&pkey, &skey); */ /* /\* Fixme: Add a check function for DSA keys. *\/ */ /* gcry_sexp_release (pkey); */ /* gcry_sexp_release (skey); */ if (verbose) fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n"); get_dsa_key_fips186_with_seed_new (&pkey, &skey); if (!in_fips_mode) { /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + ; } + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; } static gcry_mpi_t key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name) { gcry_sexp_t l1, l2; gcry_mpi_t result; l1 = gcry_sexp_find_token (sexp, topname, 0); if (!l1) return NULL; l2 = gcry_sexp_find_token (l1, name, 0); if (!l2) { gcry_sexp_release (l1); return NULL; } result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l2); gcry_sexp_release (l1); return result; } static void check_x931_derived_key (int what) { static struct { const char *param; const char *expected_d; } testtable[] = { { /* First example from X9.31 (D.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1024)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1A1916DDB29B4EB7EB6732E128#)\n" " (Xp2 #192E8AAC41C576C822D93EA433#)\n" " (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D\n" " 769D6D76646C7A792E16EBD89FE6FC5B605A6493\n" " 39DFC925A86A4C6D150B71B9EEA02D68885F5009\n" " B98BD984#)\n" " (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)\n" " (Xq2 #134E4CAA16D2350A21D775C404#)\n" " (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D\n" " 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325\n" " 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34\n" " 321DE34A#))))\n", "1CCDA20BCFFB8D517EE9666866621B11822C7950D55F4BB5BEE37989A7D173" "12E326718BE0D79546EAAE87A56623B919B1715FFBD7F16028FC4007741961" "C88C5D7B4DAAAC8D36A98C9EFBB26C8A4A0E6BC15B358E528A1AC9D0F042BE" "B93BCA16B541B33F80C933A3B769285C462ED5677BFE89DF07BED5C127FD13" "241D3C4B" }, { /* Second example from X9.31 (D.2.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1536)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #18272558B61316348297EACA74#)\n" " (Xp2 #1E970E8C6C97CEF91F05B0FA80#)\n" " (Xp #F7E943C7EF2169E930DCF23FE389EF7507EE8265\n" " 0D42F4A0D3A3CEFABE367999BB30EE680B2FE064\n" " 60F707F46005F8AA7CBFCDDC4814BBE7F0F8BC09\n" " 318C8E51A48D134296E40D0BBDD282DCCBDDEE1D\n" " EC86F0B1C96EAFF5CDA70F9AEB6EE31E#)\n" " (Xq1 #11FDDA6E8128DC1629F75192BA#)\n" " (Xq2 #18AB178ECA907D72472F65E480#)\n" " (Xq #C47560011412D6E13E3E7D007B5C05DBF5FF0D0F\n" " CFF1FA2070D16C7ABA93EDFB35D8700567E5913D\n" " B734E3FBD15862EBC59FA0425DFA131E549136E8\n" " E52397A8ABE4705EC4877D4F82C4AAC651B33DA6\n" " EA14B9D5F2A263DC65626E4D6CEAC767#))))\n", "1FB56069985F18C4519694FB71055721A01F14422DC901C35B03A64D4A5BD1" "259D573305F5B056AC931B82EDB084E39A0FD1D1A86CC5B147A264F7EF4EB2" "0ED1E7FAAE5CAE4C30D5328B7F74C3CAA72C88B70DED8EDE207B8629DA2383" "B78C3CE1CA3F9F218D78C938B35763AF2A8714664CC57F5CECE2413841F5E9" "EDEC43B728E25A41BF3E1EF8D9EEE163286C9F8BF0F219D3B322C3E4B0389C" "2E8BB28DC04C47DA2BF38823731266D2CF6CC3FC181738157624EF051874D0" "BBCCB9F65C83" /* Note that this example in X9.31 gives this value for D: "7ED581A6617C6311465A53EDC4155C86807C5108B724070D6C0E9935296F44" "96755CCC17D6C15AB24C6E0BB6C2138E683F4746A1B316C51E8993DFBD3AC8" "3B479FEAB972B930C354CA2DFDD30F2A9CB222DC37B63B7881EE18A7688E0E" "DE30F38728FE7C8635E324E2CD5D8EBCAA1C51993315FD73B38904E107D7A7" "B7B10EDCA3896906FCF87BE367BB858CA1B27E2FC3C8674ECC8B0F92C0E270" "BA2ECA3701311F68AFCE208DCC499B4B3DB30FF0605CE055D893BC1461D342" "EF32E7D9720B" This is a bug in X9.31, obviously introduced by using d = e^{-1} mod (p-1)(q-1) instead of using the universal exponent as required by 4.1.3: d = e^{-1} mod lcm(p-1,q-1) The examples in X9.31 seem to be pretty buggy, see cipher/primegen.c for another bug. Not only that I had to spend 100 USD for the 66 pages of the document, it also took me several hours to figure out that the bugs are in the document and not in my code. */ }, { /* First example from NIST RSAVS (B.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1024)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1ed3d6368e101dab9124c92ac8#)\n" " (Xp2 #16e5457b8844967ce83cab8c11#)\n" " (Xp #b79f2c2493b4b76f329903d7555b7f5f06aaa5ea\n" " ab262da1dcda8194720672a4e02229a0c71f60ae\n" " c4f0d2ed8d49ef583ca7d5eeea907c10801c302a\n" " cab44595#)\n" " (Xq1 #1a5d9e3fa34fb479bedea412f6#)\n" " (Xq2 #1f9cca85f185341516d92e82fd#)\n" " (Xq #c8387fd38fa33ddcea6a9de1b2d55410663502db\n" " c225655a9310cceac9f4cf1bce653ec916d45788\n" " f8113c46bc0fa42bf5e8d0c41120c1612e2ea8bb\n" " 2f389eda#))))\n", "17ef7ad4fd96011b62d76dfb2261b4b3270ca8e07bc501be954f8719ef586b" "f237e8f693dd16c23e7adecc40279dc6877c62ab541df5849883a5254fccfd" "4072a657b7f4663953930346febd6bbd82f9a499038402cbf97fd5f068083a" "c81ad0335c4aab0da19cfebe060a1bac7482738efafea078e21df785e56ea0" "dc7e8feb" }, { /* Second example from NIST RSAVS (B.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1536)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1e64c1af460dff8842c22b64d0#)\n" " (Xp2 #1e948edcedba84039c81f2ac0c#)\n" " (Xp #c8c67df894c882045ede26a9008ab09ea0672077\n" " d7bc71d412511cd93981ddde8f91b967da404056\n" " c39f105f7f239abdaff92923859920f6299e82b9\n" " 5bd5b8c959948f4a034d81613d6235a3953b49ce\n" " 26974eb7bb1f14843841281b363b9cdb#)\n" " (Xq1 #1f3df0f017ddd05611a97b6adb#)\n" " (Xq2 #143edd7b22d828913abf24ca4d#)\n" " (Xq #f15147d0e7c04a1e3f37adde802cdc610999bf7a\n" " b0088434aaeda0c0ab3910b14d2ce56cb66bffd9\n" " 7552195fae8b061077e03920814d8b9cfb5a3958\n" " b3a82c2a7fc97e55db543948d3396289245336ec\n" " 9e3cb308cc655aebd766340da8921383#))))\n", "1f8b19f3f5f2ac9fc599f110cad403dcd9bdf5f7f00fb2790e78e820398184" "1f3fb3dd230fb223d898f45719d9b2d3525587ff2b8bcc7425e40550a5b536" "1c8e9c1d26e83fbd9c33c64029c0e878b829d55def12912b73d94fd758c461" "0f473e230c41b5e4c86e27c5a5029d82c811c88525d0269b95bd2ff272994a" "dbd80f2c2ecf69065feb8abd8b445b9c6d306b1585d7d3d7576d49842bc7e2" "8b4a2f88f4a47e71c3edd35fdf83f547ea5c2b532975c551ed5268f748b2c4" "2ccf8a84835b" } }; gpg_error_t err; gcry_sexp_t key_spec = NULL, key = NULL, pub_key = NULL, sec_key = NULL; gcry_mpi_t d_expected = NULL, d_have = NULL; if (what < 0 && what >= sizeof testtable) die ("invalid WHAT value\n"); err = gcry_sexp_new (&key_spec, testtable[what].param, 0, 1); if (err) die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err)); { unsigned nbits; err = _gcry_pk_util_get_nbits(key_spec, &nbits); if (err) die ("nbits not found\n"); if (in_fips_mode && nbits < 2048) { info("RSA key test with %d bits skipped in fips mode\n", nbits); goto leave; } } err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { fail ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err)); goto leave; } pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key [%d]\n", what); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key [%d]\n", what); err = gcry_mpi_scan (&d_expected, GCRYMPI_FMT_HEX, testtable[what].expected_d, 0, NULL); if (err) die ("error converting string [%d]\n", what); if (verbose > 1) show_sexp ("generated key:\n", key); d_have = key_param_from_sexp (sec_key, "rsa", "d"); if (!d_have) die ("parameter d not found in RSA secret key [%d]\n", what); if (gcry_mpi_cmp (d_expected, d_have)) { show_sexp (NULL, sec_key); die ("parameter d does match expected value [%d]\n", what); } leave: gcry_mpi_release (d_expected); gcry_mpi_release (d_have); gcry_sexp_release (key); gcry_sexp_release (pub_key); gcry_sexp_release (sec_key); } static void check_ecc_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)" "))"; static const char hash_string[] = "(data (flags raw)\n" " (value #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; static const char hash2_string[] = "(data (flags raw)\n" " (hash sha1 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "00112233445566778899AABBCCDDEEFF#))"; /* hash2, but longer than curve length, so it will be truncated */ static const char hash3_string[] = "(data (flags raw)\n" " (hash sha1 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, hash2, hash3, sig, sig2; if (verbose) fprintf (stderr, "Checking sample ECC key.\n"); if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&hash2, hash2_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&hash3, hash3_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Verify hash truncation */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig2, hash2, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash3, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash2, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); if ((err = gcry_pk_verify (sig2, hash3, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Now try signing without the Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); gcry_sexp_release (sig2); gcry_sexp_release (key); gcry_sexp_release (hash); gcry_sexp_release (hash2); gcry_sexp_release (hash3); } static void check_ed25519ecdsa_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" "))"; static const char ecc_public_key_comp[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #047b57c2c1d3ded93332b52d588dd45863478b658387413a718779c0dd1a6d95#)" "))"; static const char hash_string[] = "(data (flags rfc6979)\n" " (hash sha256 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, sig; if (verbose) fprintf (stderr, "Checking sample Ed25519/ECDSA key.\n"); /* Sign. */ if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed (comp): %s", gpg_strerror (err)); /* Sign without a Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign w/o Q failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed (comp): %s", gpg_strerror (err)); extract_cmp_data (sig, "r", ("a63123a783ef29b8276e08987daca4" "655d0179e22199bf63691fd88eb64e15")); extract_cmp_data (sig, "s", ("0d9b45c696ab90b96b08812b485df185" "623ddaf5d02fa65ca5056cb6bd0f16f1")); gcry_sexp_release (sig); gcry_sexp_release (key); gcry_sexp_release (hash); } int main (int argc, char **argv) { int i; if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; for (i=0; i < 2; i++) check_run (); for (i=0; i < 4; i++) check_x931_derived_key (i); check_ecc_sample_key (); if (!in_fips_mode) check_ed25519ecdsa_sample_key (); return !!error_count; } diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c index b4126f4c..ec1472a9 100644 --- a/tests/t-cv25519.c +++ b/tests/t-cv25519.c @@ -1,683 +1,683 @@ /* t-cv25519.c - Check the cv25519 crypto * Copyright (C) 2016 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-cv25519" #include "t-common.h" #define N_TESTS 18 -static int in_fips_mode = 0; +static int in_fips_mode; static void print_mpi (const char *text, gcry_mpi_t a) { gcry_error_t err; char *buf; void *bufaddr = &buf; err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); if (err) fprintf (stderr, "%s: [error printing number: %s]\n", text, gpg_strerror (err)); else { fprintf (stderr, "%s: %s\n", text, buf); gcry_free (buf); } } static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void reverse_buffer (unsigned char *buffer, unsigned int length) { unsigned int tmp, i; for (i=0; i < length/2; i++) { tmp = buffer[i]; buffer[i] = buffer[length-1-i]; buffer[length-1-i] = tmp; } } /* * Test X25519 functionality through higher layer crypto routines. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X25519 (K, U). * * It calls gcry_pk_encrypt with Curve25519 private key and let * it compute X25519. */ static void test_cv_hl (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_sexp_t s_pk = NULL; gcry_mpi_t mpi_k = NULL; gcry_sexp_t s_data = NULL; gcry_sexp_t s_result = NULL; gcry_sexp_t s_tmp = NULL; unsigned char *res = NULL; size_t res_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) { fail ("error building s-exp for test %d, %s: %s", testno, "data", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } /* * The procedure of decodeUCoordinate will be done internally * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian * binary to build S-exp. * * We could add the prefix 0x40, but libgcrypt also supports * format with no prefix. So, it is OK not to put the prefix. */ if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Curve25519\")" " (flags djb-tweak)" " (q%b)))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; err = gcry_pk_encrypt (&s_result, s_data, s_pk); if (in_fips_mode) { if (!err) fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_pk_encrypt failed for test %d: %s", testno, gpg_strerror (err)); s_tmp = gcry_sexp_find_token (s_result, "s", 0); if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); else { char *r, *r0; int i; /* To skip the prefix 0x40, for-loop start with i=1 */ r0 = r = xmalloc (2*(res_len)+1); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=1; i < res_len; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("gcry_pk_encrypt failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: xfree (res); gcry_mpi_release (mpi_k); gcry_sexp_release (s_tmp); gcry_sexp_release (s_result); gcry_sexp_release (s_data); gcry_sexp_release (s_pk); xfree (buffer); } /* * Test X25519 functionality through the API for X25519. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X25519 (K, U). * */ static void test_cv_x25519 (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *scalar = NULL; void *point = NULL; size_t buflen; unsigned char result[32]; char result_hex[65]; int i; int algo = GCRY_ECC_CURVE25519; unsigned int keylen; if (verbose > 1) info ("Running test %d\n", testno); if (!(keylen = gcry_ecc_get_algo_keylen (algo))) { fail ("error getting keylen for test %d", testno); goto leave; } if (keylen != 32) { fail ("error invalid keylen for test %d", testno); goto leave; } if (!(scalar = hex2buffer (k_str, &buflen)) || buflen != keylen) { fail ("error of input for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } if (!(point = hex2buffer (u_str, &buflen)) || buflen != keylen) { fail ("error of input for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } err = gcry_ecc_mul_point (algo, result, scalar, point); if (in_fips_mode) { if (!err) fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_ecc_mul_point failed for test %d: %s", testno, gpg_strerror (err)); for (i=0; i < keylen; i++) snprintf (&result_hex[i*2], 3, "%02x", result[i]); if (strcmp (result_str, result_hex)) { fail ("gcry_ecc_mul_point failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", result_hex); } leave: xfree (scalar); xfree (point); } static void test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { test_cv_hl (testno, k_str, u_str, result_str); test_cv_x25519 (testno, k_str, u_str, result_str); } /* * Test iterative X25519 computation through lower layer MPI routines. * * Input: K (as hex string), ITER, R (as hex string) * * where R is expected result of iterating X25519 by ITER times. * */ static void test_it (int testno, const char *k_str, int iter, const char *result_str) { gcry_ctx_t ctx; gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_mpi_t mpi_k = NULL; gcry_mpi_t mpi_x = NULL; gcry_mpi_point_t P = NULL; gcry_mpi_point_t Q; int i; gcry_mpi_t mpi_kk = NULL; if (verbose > 1) info ("Running test %d: iteration=%d\n", testno, iter); gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); if (in_fips_mode) { if (ctx) fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); return; } Q = gcry_mpi_point_new (0); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error scanning MPI for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error scanning MPI for test %d, %s: %s", testno, "x", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE); mpi_k = gcry_mpi_copy (mpi_x); if (debug) print_mpi ("k", mpi_k); for (i = 0; i < iter; i++) { /* * Another variant of decodeScalar25519 thing. */ mpi_kk = gcry_mpi_set (mpi_kk, mpi_k); gcry_mpi_set_bit (mpi_kk, 254); gcry_mpi_clear_bit (mpi_kk, 255); gcry_mpi_clear_bit (mpi_kk, 0); gcry_mpi_clear_bit (mpi_kk, 1); gcry_mpi_clear_bit (mpi_kk, 2); gcry_mpi_ec_mul (Q, mpi_kk, P, ctx); P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE); gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx); if (debug) print_mpi ("k", mpi_k); } { unsigned char res[32]; char *r, *r0; gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k); reverse_buffer (res, 32); r0 = r = xmalloc (65); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=0; i < 32; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("curv25519 failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: gcry_mpi_release (mpi_kk); gcry_mpi_release (mpi_k); gcry_mpi_point_release (P); gcry_mpi_release (mpi_x); xfree (buffer); gcry_mpi_point_release (Q); gcry_ctx_release (ctx); } /* * X-coordinate of generator of the Curve25519. */ #define G_X "0900000000000000000000000000000000000000000000000000000000000000" /* * Test Diffie-Hellman in RFC-7748. * * Note that it's not like the ECDH of OpenPGP, where we use * ephemeral public key. */ static void test_dh (int testno, const char *a_priv_str, const char *a_pub_str, const char *b_priv_str, const char *b_pub_str, const char *result_str) { /* Test A for private key corresponds to public key. */ test_cv (testno, a_priv_str, G_X, a_pub_str); /* Test B for private key corresponds to public key. */ test_cv (testno, b_priv_str, G_X, b_pub_str); /* Test DH with A's private key and B's public key. */ test_cv (testno, a_priv_str, b_pub_str, result_str); /* Test DH with B's private key and A's public key. */ test_cv (testno, b_priv_str, a_pub_str, result_str); } static void check_cv25519 (void) { int ntests; info ("Checking Curve25519.\n"); ntests = 0; /* * Values are cited from RFC-7748: 5.2. Test Vectors. * Following two tests are for the first type test. */ test_cv (1, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"); ntests++; test_cv (2, "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"); ntests++; /* * Additional test. Value is from second type test. */ test_cv (3, G_X, G_X, "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"); ntests++; /* * Following two tests are for the second type test, * with one iteration and 1,000 iterations. (1,000,000 iterations * takes too long.) */ test_it (4, G_X, 1, "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"); ntests++; test_it (5, G_X, 1000, "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51"); ntests++; /* * Last test is from: 6. Diffie-Hellman, 6.1. Curve25519 */ test_dh (6, /* Alice's private key, a */ "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", /* Alice's public key, X25519(a, 9) */ "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", /* Bob's private key, b */ "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", /* Bob's public key, X25519(b, 9) */ "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", /* Their shared secret, K */ "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); ntests++; /* Seven tests which results 0. */ test_cv (7, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (8, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "0100000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (9, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (10, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (11, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (12, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (13, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "0000000000000000000000000000000000000000000000000000000000000000"); ntests++; /* Five tests which resulted 0 if decodeUCoordinate didn't change MSB. */ test_cv (14, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880", "7ce548bc4919008436244d2da7a9906528fe3a6d278047654bd32d8acde9707b"); ntests++; test_cv (15, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7", "e17902e989a034acdf7248260e2c94cdaf2fe1e72aaac7024a128058b6189939"); ntests++; test_cv (16, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ea6e6ddf0685c31e152d5818441ac9ac8db1a01f3d6cb5041b07443a901e7145"); ntests++; test_cv (17, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "845ddce7b3a9b3ee01a2f1fd4282ad293310f7a232cbc5459fb35d94bccc9d05"); ntests++; test_cv (18, "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "6989e2cb1cea159acf121b0af6bf77493189c9bd32c2dac71669b540f9488247"); ntests++; if (ntests != N_TESTS) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); } int main (int argc, char **argv) { int last_argc = -1; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_cv25519 (); stop_timer (); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-dsa.c b/tests/t-dsa.c index e82db62d..965b7cf2 100644 --- a/tests/t-dsa.c +++ b/tests/t-dsa.c @@ -1,627 +1,627 @@ /* t-dsa.c - Check the DSA crypto * Copyright (C) 2021 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-dsa" #include "t-common.h" #define N_TESTS 300 static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* * The input line is like: * * [mod = L=2048, N=256, SHA-384] * */ static void parse_annotation (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '-'); if (!s) { fail ("syntax error at input line %d", lineno); return; } *buffer = xstrdup (s-3); (*buffer)[strlen (*buffer) - 1] = 0; /* Remove ']'. */ } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void one_test_sexp (const char *sha_alg, const char *p, const char *q, const char *g, const char *x, const char *y, const char *msg, const char *k, const char *r, const char *s) { gpg_error_t err; int i; char *p0; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; void *buffer4 = NULL; void *buffer5 = NULL; size_t buflen, buflen2, buflen3, buflen4, buflen5; gcry_ctx_t ctx = NULL; int md_algo; const char *data_tmpl; gcry_md_hd_t hd = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_sig= NULL; gcry_sexp_t s_tmp, s_tmp2; unsigned char *out_r = NULL; unsigned char *out_s = NULL; size_t out_r_len, out_s_len; char *sig_r_string = NULL; char *sig_s_string = NULL; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (sha_alg, "SHA-1")) md_algo = GCRY_MD_SHA1; else if (!strcmp (sha_alg, "SHA-224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA-256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA-384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA-512")) md_algo = GCRY_MD_SHA512; else { fail ("error for test, %s: %s: %s", "SHA algo", "invalid", sha_alg); goto leave; } err = gcry_md_open (&hd, md_algo, 0); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err)); return; } if (!(buffer = hex2buffer (p, &buflen))) { fail ("error parsing for test, %s: %s", "p", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (q, &buflen2))) { fail ("error parsing for test, %s: %s", "q", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (g, &buflen3))) { fail ("error parsing for test, %s: %s", "g", "invalid hex string"); goto leave; } if (!(buffer4 = hex2buffer (y, &buflen4))) { fail ("error parsing for test, %s: %s", "y", "invalid hex string"); goto leave; } if (!(buffer5 = hex2buffer (x, &buflen5))) { fail ("error parsing for test, %s: %s", "x", "invalid hex string"); goto leave; } err = gcry_sexp_build (&s_sk, NULL, "(private-key (dsa (p %b)(q %b)(g %b)(y %b)(x %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3, (int)buflen4, buffer4, (int)buflen5, buffer5); if (err) { fail ("error building SEXP for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } err = gcry_sexp_build (&s_pk, NULL, "(public-key (dsa (p %b)(q %b)(g %b)(y %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3, (int)buflen4, buffer4); if (err) { fail ("error building SEXP for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (buffer4); xfree (buffer5); buffer = buffer2 = buffer3 = buffer4 = buffer5 = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } gcry_md_write (hd, buffer, buflen); xfree (buffer); buffer = NULL; if (!(buffer2 = hex2buffer (k, &buflen2))) { fail ("error parsing for test, %s: %s", "salt_val", "invalid hex string"); goto leave; } err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; } xfree (buffer2); buffer2 = NULL; data_tmpl = "(data(flags raw)(hash %s %b)(label %b))"; err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx); if (err) { if (in_fips_mode) { if (verbose) show_note ("DSA is not allowed in FIPS mode\n"); } else fail ("gcry_pkey_hash_sign failed: %s", gpg_strerror (err)); goto leave; } out_r_len = out_s_len = 0; out_s = out_r = NULL; s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "dsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { const char *p1; size_t n; out_r_len = buflen2; out_r = xmalloc (out_r_len); if (!out_r) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p1 = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_r_len) memcpy (out_r, p1, out_r_len); else { memset (out_r, 0, out_r_len - n); memcpy (out_r + out_r_len - n, p1, n); } gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { const char *p1; size_t n; out_s_len = out_r_len; out_s = xmalloc (out_s_len); if (!out_s) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p1 = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_s_len) memcpy (out_s, p1, out_s_len); else { memset (out_s, 0, out_s_len - n); memcpy (out_s + out_s_len - n, p1, n); } gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); sig_r_string = xmalloc (2*out_r_len+1); p0 = sig_r_string; *p0 = 0; for (i=0; i < out_r_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_r[i]); sig_s_string = xmalloc (2*out_s_len+1); p0 = sig_s_string; *p0 = 0; for (i=0; i < out_s_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_s[i]); if (strcmp (sig_r_string, r) || strcmp (sig_s_string, s)) { fail ("gcry_pk_hash_sign failed: %s", "wrong value returned"); info (" expected: '%s'", r); info (" got: '%s'", sig_r_string); info (" expected: '%s'", s); info (" got: '%s'", sig_s_string); } if (!no_verify) { err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx); if (err) fail ("gcry_pk_hash_verify failed for test: %s", gpg_strerror (err)); } leave: gcry_ctx_release (ctx); gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); if (hd) gcry_md_close (hd); xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (buffer4); xfree (buffer5); xfree (out_r); xfree (out_s); xfree (sig_r_string); xfree (sig_s_string); } static void check_dsa (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *sha_alg; char *p, *q, *g; char *msg, *x, *y, *k, *r, *s; info ("Checking DSA.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); sha_alg = NULL; p = q = g = NULL; msg = x = y = k = r = s = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[mod", 4)) parse_annotation (&sha_alg, line, lineno); else if (!strncmp (line, "P =", 3)) copy_data (&p, line, lineno); else if (!strncmp (line, "Q =", 3)) copy_data (&q, line, lineno); else if (!strncmp (line, "G =", 3)) copy_data (&g, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "X =", 3)) copy_data (&x, line, lineno); else if (!strncmp (line, "Y =", 3)) copy_data (&y, line, lineno); else if (!strncmp (line, "K =", 3)) copy_data (&k, line, lineno); else if (!strncmp (line, "R =", 3)) copy_data (&r, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (sha_alg && p && q && g && msg && x && y && k && r && s) { one_test_sexp (sha_alg, p, q, g, x, y, msg, k, r, s); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (msg); msg = NULL; xfree (x); x = NULL; xfree (y); y = NULL; xfree (k); k = NULL; xfree (r); r = NULL; xfree (s); s = NULL; } } xfree (p); xfree (q); xfree (g); xfree (sha_alg); xfree (msg); xfree (x); xfree (y); xfree (k); xfree (r); xfree (s); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-dsa.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_dsa (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-ecdsa.c b/tests/t-ecdsa.c index ddc49df0..9a0773b7 100644 --- a/tests/t-ecdsa.c +++ b/tests/t-ecdsa.c @@ -1,652 +1,652 @@ /* t-ecdsa.c - Check the ECDSA crypto * Copyright (C) 2021 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-ecdsa" #include "t-common.h" #define N_TESTS 320 static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* * The input line is like: * * [P-224,SHA-224] * */ static void parse_annotation (char **buffer, char **buffer2, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; xfree (*buffer2); *buffer2 = NULL; s = strchr (line, '-'); if (!s) { fail ("syntax error at input line %d", lineno); return; } *buffer = xstrdup (s-1); (*buffer)[5] = 0; /* Remove ','. */ s = strchr (s+1, ','); if (!s) { fail ("syntax error at input line %d", lineno); return; } *buffer2 = xstrdup (s+1); (*buffer2)[strlen (*buffer2) - 1] = 0; /* Remove ']'. */ } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; int odd; odd = ((strlen (string) & 1)); buffer = xmalloc (strlen (string)/2 + odd + 1); if (odd) { length = 1; s = string; buffer[0] = xtoi_1 (s); s++; } else { length = 0; s = string; } for (; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ buffer[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void one_test_sexp (const char *curvename, const char *sha_alg, const char *x, const char *y, const char *d, const char *msg, const char *k, const char *r, const char *s) { gpg_error_t err; int i; char *p0; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; size_t buflen, buflen2, buflen3; unsigned char *pkbuffer = NULL; size_t pkbuflen; char curvename_gcrypt[11]; gcry_ctx_t ctx = NULL; int md_algo; const char *data_tmpl; gcry_md_hd_t hd = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_sig= NULL; gcry_sexp_t s_tmp, s_tmp2; unsigned char *out_r = NULL; unsigned char *out_s = NULL; size_t out_r_len, out_s_len; char *sig_r_string = NULL; char *sig_s_string = NULL; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (curvename, "P-224") || !strcmp (curvename, "P-256") || !strcmp (curvename, "P-384") || !strcmp (curvename, "P-521")) { memcpy (curvename_gcrypt, "NIST ", 5); strcpy (curvename_gcrypt+5, curvename); } else { fail ("error for test, %s: %s: %s", "ECC curve", "invalid", curvename); goto leave; } if (!strcmp (sha_alg, "SHA-224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA-256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA-384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA-512")) md_algo = GCRY_MD_SHA512; else if (!strcmp (sha_alg, "SHA-512224")) md_algo = GCRY_MD_SHA512_224; else if (!strcmp (sha_alg, "SHA-512256")) md_algo = GCRY_MD_SHA512_256; else { fail ("error for test, %s: %s: %s", "SHA algo", "invalid", sha_alg); goto leave; } err = gcry_md_open (&hd, md_algo, 0); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err)); return; } if (!(buffer = hex2buffer (x, &buflen))) { fail ("error parsing for test, %s: %s", "Qx", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (y, &buflen2))) { fail ("error parsing for test, %s: %s", "Qy", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (d, &buflen3))) { fail ("error parsing for test, %s: %s", "d", "invalid hex string"); goto leave; } pkbuflen = buflen + buflen2 + 1; pkbuffer = xmalloc (pkbuflen); pkbuffer[0] = 0x04; memcpy (pkbuffer+1, buffer, buflen); memcpy (pkbuffer+1+buflen, buffer2, buflen2); err = gcry_sexp_build (&s_sk, NULL, "(private-key (ecc (curve %s)(q %b)(d %b)))", curvename_gcrypt, (int)pkbuflen, pkbuffer, (int)buflen3, buffer3); if (err) { fail ("error building SEXP for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } err = gcry_sexp_build (&s_pk, NULL, "(public-key (ecc (curve %s)(q %b)))", curvename_gcrypt, (int)pkbuflen, pkbuffer); if (err) { fail ("error building SEXP for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); buffer = buffer2 = buffer3 = NULL; xfree (pkbuffer); pkbuffer = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } gcry_md_write (hd, buffer, buflen); xfree (buffer); buffer = NULL; if (!(buffer2 = hex2buffer (k, &buflen2))) { fail ("error parsing for test, %s: %s", "salt_val", "invalid hex string"); goto leave; } err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; } xfree (buffer2); buffer2 = NULL; data_tmpl = "(data(flags raw)(hash %s %b)(label %b))"; err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx); if (err) { fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err)); goto leave; } out_r_len = out_s_len = 0; out_s = out_r = NULL; s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "ecdsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { const char *p; size_t n; out_r_len = buflen3; out_r = xmalloc (out_r_len); if (!out_r) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_r_len) memcpy (out_r, p, out_r_len); else { memset (out_r, 0, out_r_len - n); memcpy (out_r + out_r_len - n, p, n); } gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { const char *p; size_t n; out_s_len = out_r_len; out_s = xmalloc (out_s_len); if (!out_s) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_s_len) memcpy (out_s, p, out_s_len); else { memset (out_s, 0, out_s_len - n); memcpy (out_s + out_s_len - n, p, n); } gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); sig_r_string = xmalloc (2*out_r_len+1); p0 = sig_r_string; *p0 = 0; for (i=0; i < out_r_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_r[i]); sig_s_string = xmalloc (2*out_s_len+1); p0 = sig_s_string; *p0 = 0; for (i=0; i < out_s_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_s[i]); if (strcmp (sig_r_string + (strcmp (curvename, "P-521") == 0), r) || strcmp (sig_s_string + (strcmp (curvename, "P-521") == 0), s)) { fail ("gcry_pkey_op failed: %s", "wrong value returned"); info (" expected: '%s'", r); info (" got: '%s'", sig_r_string); info (" expected: '%s'", s); info (" got: '%s'", sig_s_string); } if (!no_verify) { err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx); if (err) fail ("gcry_pk_hash_verify failed for test: %s", gpg_strerror (err)); } leave: gcry_ctx_release (ctx); gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); if (hd) gcry_md_close (hd); xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (out_r); xfree (out_s); xfree (sig_r_string); xfree (sig_s_string); } static void check_ecdsa (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *curve, *sha_alg; char *x, *y; char *d; char *msg, *k, *r, *s; info ("Checking ECDSA.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); curve = NULL; sha_alg = NULL; x = y = d = NULL; msg = k = r = s = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[", 1)) parse_annotation (&curve, &sha_alg, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "d =", 3)) copy_data (&d, line, lineno); else if (!strncmp (line, "Qx =", 4)) copy_data (&x, line, lineno); else if (!strncmp (line, "Qy =", 4)) copy_data (&y, line, lineno); else if (!strncmp (line, "k =", 3)) copy_data (&k, line, lineno); else if (!strncmp (line, "R =", 3)) copy_data (&r, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (curve && sha_alg && x && y && d && msg && k && r && s) { one_test_sexp (curve, sha_alg, x, y, d, msg, k, r, s); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (msg); msg = NULL; xfree (x); x = NULL; xfree (y); y = NULL; xfree (d); d = NULL; xfree (k); k = NULL; xfree (r); r = NULL; xfree (s); s = NULL; } } xfree (curve); xfree (sha_alg); xfree (x); xfree (y); xfree (d); xfree (msg); xfree (k); xfree (r); xfree (s); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-ecdsa.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_ecdsa (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c index 567bc797..160bf980 100644 --- a/tests/t-ed25519.c +++ b/tests/t-ed25519.c @@ -1,507 +1,507 @@ /* t-ed25519.c - Check the Ed25519 crypto * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-ed25519" #include "t-common.h" #define N_TESTS 1026 static int sign_with_pk; static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; fprintf (stderr, "%s: ", PGM); if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, ':'); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void hexdowncase (char *string) { char *p; for (p=string; *p; p++) if (my_isascii (*p)) *p = tolower (*p); } static void one_test (int testno, const char *sk, const char *pk, const char *msg, const char *sig) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; size_t buflen, buflen2; gcry_sexp_t s_tmp, s_tmp2; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; unsigned char *sig_r = NULL; unsigned char *sig_s = NULL; char *sig_rs_string = NULL; size_t sig_r_len, sig_s_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (sk, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (pk, &buflen2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", "invalid hex string"); goto leave; } if (sign_with_pk) err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)" " (d %b)))", (int)buflen2, buffer2, (int)buflen, buffer); else err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (d %b)))", (int)buflen, buffer); if (err) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)))", (int)buflen2, buffer2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", "invalid hex string"); goto leave; } if ((err = gcry_sexp_build (&s_msg, NULL, "(data" " (flags eddsa)" " (hash-algo sha512)" " (value %b))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", gpg_strerror (err)); goto leave; } err = gcry_pk_sign (&s_sig, s_msg, s_sk); if (in_fips_mode) { if (!err) fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); if (debug) show_sexp ("sig=", s_sig); s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len); gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); s_tmp2 = NULL; if (!sig_r || !sig_s) fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing"); else { sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1); p = sig_rs_string; *p = 0; for (i=0; i < sig_r_len; i++, p += 2) snprintf (p, 3, "%02x", sig_r[i]); for (i=0; i < sig_s_len; i++, p += 2) snprintf (p, 3, "%02x", sig_s[i]); if (strcmp (sig_rs_string, sig)) { fail ("gcry_pk_sign failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", sig); info (" got: '%s'", sig_rs_string); } } if (!no_verify) if ((err = gcry_pk_verify (s_sig, s_msg, s_pk))) fail ("gcry_pk_verify failed for test %d: %s", testno, gpg_strerror (err)); leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); gcry_sexp_release (s_msg); xfree (buffer); xfree (buffer2); xfree (sig_r); xfree (sig_s); xfree (sig_rs_string); } static void check_ed25519 (const char *fname) { FILE *fp; int lineno, ntests; char *line; int testno; char *sk, *pk, *msg, *sig; info ("Checking Ed25519.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); testno = 0; sk = pk = msg = sig = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "TST:", 4)) testno = atoi (line+4); else if (!strncmp (line, "SK:", 3)) copy_data (&sk, line, lineno); else if (!strncmp (line, "PK:", 3)) copy_data (&pk, line, lineno); else if (!strncmp (line, "MSG:", 4)) copy_data (&msg, line, lineno); else if (!strncmp (line, "SIG:", 4)) copy_data (&sig, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (testno && sk && pk && msg && sig) { hexdowncase (sig); one_test (testno, sk, pk, msg, sig); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (pk); pk = NULL; xfree (sk); sk = NULL; xfree (msg); msg = NULL; xfree (sig); sig = NULL; } } xfree (pk); xfree (sk); xfree (msg); xfree (sig); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --sign-with-pk also use the public key for signing\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--sign-with-pk")) { sign_with_pk = 1; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-ed25519.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_ed25519 (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-ed448.c b/tests/t-ed448.c index f38cd10c..3e3dd34a 100644 --- a/tests/t-ed448.c +++ b/tests/t-ed448.c @@ -1,547 +1,547 @@ /* t-ed448.c - Check the Ed448 crypto * Copyright (C) 2020 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-ed448" #include "t-common.h" #define N_TESTS 11 static int sign_with_pk; static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; fprintf (stderr, "%s: ", PGM); if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, ':'); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void hexdowncase (char *string) { char *p; for (p=string; *p; p++) if (my_isascii (*p)) *p = tolower (*p); } static void one_test (int testno, int ph, const char *sk, const char *pk, const char *msg, const char *ctx, const char *sig) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; size_t buflen, buflen2; gcry_sexp_t s_tmp, s_tmp2; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; unsigned char *sig_r = NULL; unsigned char *sig_s = NULL; char *sig_rs_string = NULL; size_t sig_r_len, sig_s_len; if (verbose > 1) info ("Running test %d %d\n", testno, ph); if (!(buffer = hex2buffer (sk, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (pk, &buflen2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", "invalid hex string"); goto leave; } if (sign_with_pk) err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed448\")" " (q %b)" " (d %b)))", (int)buflen2, buffer2, (int)buflen, buffer); else err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed448\")" " (d %b)))", (int)buflen, buffer); if (err) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Ed448\")" " (q %b)))", (int)buflen2, buffer2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", "invalid hex string"); goto leave; } if (ctx) { xfree (buffer2); if (!(buffer2 = hex2buffer (ctx, &buflen2))) { fail ("error building s-exp for test %d, %s: %s", testno, "ctx", "invalid hex string"); goto leave; } if ((err = gcry_sexp_build (&s_msg, NULL, ph ? "(data" " (flags prehash)" " (label %b)" " (value %b))" : "(data" " (label %b)" " (value %b))", (int)buflen2, buffer2, (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", gpg_strerror (err)); goto leave; } } else { if ((err = gcry_sexp_build (&s_msg, NULL, ph ? "(data" " (flags prehash)" " (value %b))" : "(data" " (value %b))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", gpg_strerror (err)); goto leave; } } err = gcry_pk_sign (&s_sig, s_msg, s_sk); if (in_fips_mode) { if (!err) fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); if (debug) show_sexp ("sig=", s_sig); s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len); gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); s_tmp2 = NULL; if (!sig_r || !sig_s) fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing"); else { sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1); p = sig_rs_string; *p = 0; for (i=0; i < sig_r_len; i++, p += 2) snprintf (p, 3, "%02x", sig_r[i]); for (i=0; i < sig_s_len; i++, p += 2) snprintf (p, 3, "%02x", sig_s[i]); if (strcmp (sig_rs_string, sig)) { fail ("gcry_pk_sign failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", sig); info (" got: '%s'", sig_rs_string); } } if (!no_verify) if ((err = gcry_pk_verify (s_sig, s_msg, s_pk))) fail ("gcry_pk_verify failed for test %d: %s", testno, gpg_strerror (err)); leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); gcry_sexp_release (s_msg); xfree (buffer); xfree (buffer2); xfree (sig_r); xfree (sig_s); xfree (sig_rs_string); } static void check_ed448 (const char *fname) { FILE *fp; int lineno, ntests; char *line; int testno; int ph; char *sk, *pk, *msg, *ctx, *sig; info ("Checking Ed448.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); testno = 0; ph = 0; sk = pk = msg = ctx = sig = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "TST:", 4)) testno = atoi (line+4); else if (!strncmp (line, "PH:", 3)) ph = atoi (line+3); else if (!strncmp (line, "SK:", 3)) copy_data (&sk, line, lineno); else if (!strncmp (line, "PK:", 3)) copy_data (&pk, line, lineno); else if (!strncmp (line, "MSG:", 4)) copy_data (&msg, line, lineno); else if (!strncmp (line, "CTX:", 4)) copy_data (&ctx, line, lineno); else if (!strncmp (line, "SIG:", 4)) copy_data (&sig, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (testno && sk && pk && msg && sig) { hexdowncase (sig); one_test (testno, ph, sk, pk, msg, ctx, sig); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); ph = 0; xfree (pk); pk = NULL; xfree (sk); sk = NULL; xfree (msg); msg = NULL; xfree (ctx); ctx = NULL; xfree (sig); sig = NULL; } } xfree (pk); xfree (sk); xfree (msg); xfree (ctx); xfree (sig); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --sign-with-pk also use the public key for signing\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--sign-with-pk")) { sign_with_pk = 1; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-ed448.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_ed448 (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-rsa-15.c b/tests/t-rsa-15.c index 99315509..63495e9e 100644 --- a/tests/t-rsa-15.c +++ b/tests/t-rsa-15.c @@ -1,478 +1,478 @@ /* t-rsa-15.c - Check the RSA PKCS#1 Ver1.5 crypto * Copyright (C) 2021 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-rsa-15" #include "t-common.h" #define N_TESTS 120 static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void one_test_sexp (const char *n, const char *e, const char *d, const char *sha_alg, const char *msg, const char *s) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; size_t buflen, buflen2, buflen3; int md_algo; const char *data_tmpl; gcry_md_hd_t hd = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_sig= NULL; gcry_sexp_t s_tmp, s_tmp2; unsigned char *out = NULL; size_t out_len; char *sig_string = NULL; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (sha_alg, "SHA224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA512")) md_algo = GCRY_MD_SHA512; else if (!strcmp (sha_alg, "SHA512224")) md_algo = GCRY_MD_SHA512_224; else if (!strcmp (sha_alg, "SHA512256")) md_algo = GCRY_MD_SHA512_256; else { fail ("error for test, %s: %s", "d", "invalid hex string"); goto leave; } err = gcry_md_open (&hd, md_algo, 0); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err)); return; } if (!(buffer = hex2buffer (n, &buflen))) { fail ("error parsing for test, %s: %s", "n", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (e, &buflen2))) { fail ("error parsing for test, %s: %s", "e", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (d, &buflen3))) { fail ("error parsing for test, %s: %s", "d", "invalid hex string"); goto leave; } err = gcry_sexp_build (&s_sk, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3); if (err) { fail ("error building SEXP for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } err = gcry_sexp_build (&s_pk, NULL, "(public-key (rsa (n %b)(e %b)))", (int)buflen, buffer, (int)buflen2, buffer2); if (err) { fail ("error building SEXP for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); buffer = buffer2 = buffer3 = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } gcry_md_write (hd, buffer, buflen); xfree (buffer); buffer = NULL; data_tmpl = "(data(flags pkcs1)(hash %s %b))"; err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, NULL); if (err) { fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err)); goto leave; } s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "rsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { out = gcry_sexp_nth_buffer (s_tmp, 1, &out_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); sig_string = gcry_xmalloc (2*out_len+1); p = sig_string; *p = 0; for (i=0; i < out_len; i++, p += 2) snprintf (p, 3, "%02x", out[i]); if (strcmp (sig_string, s)) { fail ("gcry_pk_hash_sign failed: %s", "wrong value returned"); info (" expected: '%s'", s); info (" got: '%s'", sig_string); } if (!no_verify) { err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, NULL); if (err) fail ("gcry_pk_hash_verify failed for test: %s", gpg_strerror (err)); } leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); if (hd) gcry_md_close (hd); xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (out); xfree (sig_string); } static void check_rsa_15 (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *n, *e, *d; char *sha_alg, *msg, *s; info ("Checking RSA PKCS#1 Ver1.5.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); n = e = d = NULL; sha_alg = msg = s = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[mod", 4)) /* Skip the annotation for modulus. */ ; else if (!strncmp (line, "n =", 3)) copy_data (&n, line, lineno); else if (!strncmp (line, "e =", 3)) copy_data (&e, line, lineno); else if (!strncmp (line, "d =", 3)) copy_data (&d, line, lineno); else if (!strncmp (line, "SHAAlg =", 8)) copy_data (&sha_alg, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (n && e && d && sha_alg && msg && s) { one_test_sexp (n, e, d, sha_alg, msg, s); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (sha_alg); sha_alg = NULL; xfree (msg); msg = NULL; xfree (s); s = NULL; } } xfree (n); xfree (e); xfree (d); xfree (sha_alg); xfree (msg); xfree (s); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-rsa-15.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_rsa_15 (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-rsa-pss.c b/tests/t-rsa-pss.c index f167a79d..521d5734 100644 --- a/tests/t-rsa-pss.c +++ b/tests/t-rsa-pss.c @@ -1,527 +1,527 @@ /* t-rsa-pss.c - Check the RSA-PSS crypto * Copyright (C) 2021 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-rsa-pss" #include "t-common.h" #define N_TESTS 120 static int no_verify; static int custom_data_file; -static int in_fips_mode = 0; +static int in_fips_mode; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } #define DATA_TMPL_NO_SALT "(data(flags pss)(hash %s %b)(salt-length 1:0))" #define DATA_TMPL_WITH_SALT "(data(flags pss)(hash %%s %%b)(salt-length %zd:%zd)(random-override %%b))" static void one_test_sexp (const char *n, const char *e, const char *d, const char *sha_alg, const char *msg, const char *s, const char *salt_val) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; size_t buflen, buflen2, buflen3; gcry_ctx_t ctx; int md_algo; char *data_tmpl = NULL; size_t len_data_tmpl; gcry_md_hd_t hd = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_sig= NULL; gcry_sexp_t s_tmp, s_tmp2; unsigned char *out = NULL; size_t out_len; char *sig_string = NULL; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (sha_alg, "SHA224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA512")) md_algo = GCRY_MD_SHA512; else if (!strcmp (sha_alg, "SHA512224")) md_algo = GCRY_MD_SHA512_224; else if (!strcmp (sha_alg, "SHA512256")) md_algo = GCRY_MD_SHA512_256; else { fail ("error for test, %s: %s", "d", "invalid hex string"); return; } err = gcry_md_open (&hd, md_algo, 0); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err)); return; } if (!(buffer = hex2buffer (n, &buflen))) { fail ("error parsing for test, %s: %s", "n", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (e, &buflen2))) { fail ("error parsing for test, %s: %s", "e", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (d, &buflen3))) { fail ("error parsing for test, %s: %s", "d", "invalid hex string"); goto leave; } err = gcry_sexp_build (&s_sk, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3); if (err) { fail ("error building SEXP for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } err = gcry_sexp_build (&s_pk, NULL, "(public-key (rsa (n %b)(e %b)))", (int)buflen, buffer, (int)buflen2, buffer2); if (err) { fail ("error building SEXP for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); buffer = buffer2 = buffer3 = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } gcry_md_write (hd, buffer, buflen); xfree (buffer); buffer = NULL; if (!(buffer2 = hex2buffer (salt_val, &buflen2))) { fail ("error parsing for test, %s: %s", "salt_val", "invalid hex string"); goto leave; } /* SaltVal = 00 means no salt. */ if (buflen2 == 1 && ((char *)buffer2)[0] == 0) ctx = NULL; else { err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; } } len_data_tmpl = strlen (DATA_TMPL_WITH_SALT) + 21; data_tmpl = gcry_xmalloc (len_data_tmpl); if (ctx) { size_t len_digits; char number[21]; len_digits = snprintf (number, sizeof (number), "%zd", buflen2); snprintf (data_tmpl, len_data_tmpl, DATA_TMPL_WITH_SALT, len_digits, buflen2); } else strcpy (data_tmpl, DATA_TMPL_NO_SALT); xfree (buffer2); buffer2 = NULL; err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx); if (err) { fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err)); goto leave; } s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "rsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { out = gcry_sexp_nth_buffer (s_tmp, 1, &out_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); sig_string = gcry_xmalloc (2*out_len+1); p = sig_string; *p = 0; for (i=0; i < out_len; i++, p += 2) snprintf (p, 3, "%02x", out[i]); if (strcmp (sig_string, s)) { fail ("gcry_pkhash_sign failed: %s", "wrong value returned"); info (" expected: '%s'", s); info (" got: '%s'", sig_string); } if (!no_verify) { err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx); if (err) fail ("gcry_pk_hash_verify failed for test: %s", gpg_strerror (err)); } leave: gcry_ctx_release (ctx); gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); if (hd) gcry_md_close (hd); xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (out); xfree (sig_string); xfree (data_tmpl); } static void check_rsa_pss (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *n, *e, *d; char *sha_alg, *msg, *s, *salt_val; info ("Checking RSASSA-PSS.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); n = e = d = NULL; sha_alg = msg = s = salt_val = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[mod", 4)) /* Skip the annotation for modulus. */ ; else if (!strncmp (line, "n =", 3)) copy_data (&n, line, lineno); else if (!strncmp (line, "e =", 3)) copy_data (&e, line, lineno); else if (!strncmp (line, "d =", 3)) copy_data (&d, line, lineno); else if (!strncmp (line, "SHAAlg =", 8)) copy_data (&sha_alg, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else if (!strncmp (line, "SaltVal =", 9)) copy_data (&salt_val, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (n && e && d && sha_alg && msg && s && salt_val) { one_test_sexp (n, e, d, sha_alg, msg, s, salt_val); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (sha_alg); sha_alg = NULL; xfree (msg); msg = NULL; xfree (s); s = NULL; xfree (salt_val); salt_val = NULL; } } xfree (n); xfree (e); xfree (d); xfree (sha_alg); xfree (msg); xfree (s); xfree (salt_val); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-rsa-pss.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_rsa_pss (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; } diff --git a/tests/t-secmem.c b/tests/t-secmem.c index e735628f..a6557dce 100644 --- a/tests/t-secmem.c +++ b/tests/t-secmem.c @@ -1,218 +1,218 @@ /* t-secmem.c - Test the secmem memory allocator * Copyright (C) 2016 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #define PGM "t-secmem" #include "t-common.h" #include "../src/gcrypt-testapi.h" #define DEFAULT_PAGE_SIZE 4096 #define MINIMUM_POOL_SIZE 16384 static size_t pool_size; static size_t chunk_size; -static int in_fips_mode = 0; +static int in_fips_mode; static void test_secmem (void) { void *a[28]; void *b; int i; int i_max; memset (a, 0, sizeof a); /* Allocating 28*512=14k should work in the default 16k pool even * with extra alignment requirements. */ i_max = DIM(a); for (i=0; i < i_max; i++) a[i] = gcry_xmalloc_secure (chunk_size); /* Allocating another 2k should fail for the default 16k pool. */ b = gcry_malloc_secure (chunk_size*4); if (b) fail ("allocation did not fail as expected\n"); for (i=0; i < DIM(a); i++) xfree (a[i]); xfree (b); } static void test_secmem_overflow (void) { void *a[150]; int i; memset (a, 0, sizeof a); /* Allocating 150*512=75k should require more than one overflow buffer. */ for (i=0; i < DIM(a); i++) { a[i] = gcry_xmalloc_secure (chunk_size); if (verbose && !(i %40)) xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0)); } if (debug) xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0)); if (verbose) xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0)); for (i=0; i < DIM(a); i++) xfree (a[i]); } /* This function is called when we ran out of core and there is no way * to return that error to the caller (xmalloc or mpi allocation). */ static int outofcore_handler (void *opaque, size_t req_n, unsigned int flags) { static int been_here; /* Used to protect against recursive calls. */ (void)opaque; /* Protect against a second call. */ if (been_here) return 0; /* Let libgcrypt call its own fatal error handler. */ been_here = 1; info ("outofcore handler invoked"); xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0)); fail ("out of core%s while allocating %lu bytes", (flags & 1)?" in secure memory":"", (unsigned long)req_n); die ("stopped"); /*NOTREACHED*/ return 0; } int main (int argc, char **argv) { int last_argc = -1; long int pgsize_val = -1; size_t pgsize; if (getenv ("GCRYPT_IN_ASAN_TEST")) { /* 'mlock' is not available when build with address sanitizer, * so skip test. */ fputs ("Note: " PGM " skipped because running with ASAN.\n", stdout); return 0; } #if HAVE_MMAP # if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) pgsize_val = sysconf (_SC_PAGESIZE); # elif defined(HAVE_GETPAGESIZE) pgsize_val = getpagesize (); # endif #endif pgsize = (pgsize_val > 0)? pgsize_val : DEFAULT_PAGE_SIZE; pool_size = (MINIMUM_POOL_SIZE + pgsize - 1) & ~(pgsize - 1); chunk_size = pool_size / 32; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" , stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch; pgm=%s, library=%s\n", GCRYPT_VERSION, gcry_check_version (NULL)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INIT_SECMEM, pool_size, 0)); /* This is ignored in FIPS Mode */ gcry_set_outofcore_handler (outofcore_handler, NULL); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; /* Libgcrypt prints a warning when the first overflow is allocated; * we do not want to see that. */ if (!verbose) xgcry_control ((GCRYCTL_DISABLE_SECMEM_WARN, 0)); test_secmem (); if (!in_fips_mode) test_secmem_overflow (); /* FIXME: We need to improve the tests, for example by registering * our own log handler and comparing the output of * PRIV_CTL_DUMP_SECMEM_STATS to expected pattern. */ if (verbose) { xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0)); xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0)); } info ("All tests completed. Errors: %d\n", error_count); xgcry_control ((GCRYCTL_TERM_SECMEM, 0 , 0)); return !!error_count; } diff --git a/tests/t-x448.c b/tests/t-x448.c index cc4b10fc..f5f49e5e 100644 --- a/tests/t-x448.c +++ b/tests/t-x448.c @@ -1,626 +1,626 @@ /* t-x448.c - Check the X488 computation * Copyright (C) 2019 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-x448" #include "t-common.h" #define N_TESTS 9 -static int in_fips_mode = 0; +static int in_fips_mode; static void print_mpi (const char *text, gcry_mpi_t a) { gcry_error_t err; char *buf; void *bufaddr = &buf; err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); if (err) fprintf (stderr, "%s: [error printing number: %s]\n", text, gpg_strerror (err)); else { fprintf (stderr, "%s: %s\n", text, buf); gcry_free (buf); } } static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void reverse_buffer (unsigned char *buffer, unsigned int length) { unsigned int tmp, i; for (i=0; i < length/2; i++) { tmp = buffer[i]; buffer[i] = buffer[length-1-i]; buffer[length-1-i] = tmp; } } /* * Test X448 functionality through higher layer crypto routines. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X448 (K, U). * */ static void test_cv_hl (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_sexp_t s_pk = NULL; gcry_mpi_t mpi_k = NULL; gcry_sexp_t s_data = NULL; gcry_sexp_t s_result = NULL; gcry_sexp_t s_tmp = NULL; unsigned char *res = NULL; size_t res_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } mpi_k = gcry_mpi_set_opaque (NULL, buffer, buflen*8); if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) { fail ("error building s-exp for test %d, %s: %s", testno, "data", gpg_strerror (err)); goto leave; } if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 56) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } /* * The procedure of decodeUCoordinate will be done internally * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian * binary to build S-exp. * * We could add the prefix 0x40, but libgcrypt also supports * format with no prefix. So, it is OK not to put the prefix. */ if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"X448\")" " (q%b)))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; err = gcry_pk_encrypt (&s_result, s_data, s_pk); if (in_fips_mode) { if (!err) fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_pk_encrypt goto leavefailed for test %d: %s", testno, gpg_strerror (err)); s_tmp = gcry_sexp_find_token (s_result, "s", 0); if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); else { char *r, *r0; int i; r0 = r = xmalloc (2*(res_len)+1); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=0; i < res_len; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("gcry_pk_encrypt failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: xfree (res); gcry_mpi_release (mpi_k); gcry_sexp_release (s_tmp); gcry_sexp_release (s_result); gcry_sexp_release (s_data); gcry_sexp_release (s_pk); xfree (buffer); } /* * Test X448 functionality through the API for X448. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X448 (K, U). * */ static void test_cv_x448 (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *scalar; void *point = NULL; size_t buflen; unsigned char result[56]; char result_hex[113]; int i; if (verbose > 1) info ("Running test %d\n", testno); if (!(scalar = hex2buffer (k_str, &buflen)) || buflen != 56) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } if (!(point = hex2buffer (u_str, &buflen)) || buflen != 56) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point); if (in_fips_mode) { if (err != GPG_ERR_NOT_SUPPORTED) fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d: %s", testno, gpg_strerror (err)); if (verbose > 1) info ("not executed in FIPS mode\n"); goto leave; } if (err) fail ("gcry_ecc_mul_point failed for test %d: %s", testno, gpg_strerror (err)); for (i=0; i < 56; i++) snprintf (&result_hex[i*2], 3, "%02x", result[i]); if (strcmp (result_str, result_hex)) { fail ("gcry_ecc_mul_point failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", result_hex); } leave: xfree (scalar); xfree (point); } static void test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { test_cv_hl (testno, k_str, u_str, result_str); test_cv_x448 (testno, k_str, u_str, result_str); } /* * Test iterative X448 computation through lower layer MPI routines. * * Input: K (as hex string), ITER, R (as hex string) * * where R is expected result of iterating X448 by ITER times. * */ static void test_it (int testno, const char *k_str, int iter, const char *result_str) { gcry_ctx_t ctx = NULL; gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_mpi_t mpi_k = NULL; gcry_mpi_t mpi_x = NULL; gcry_mpi_point_t P = NULL; gcry_mpi_point_t Q; int i; gcry_mpi_t mpi_kk = NULL; if (verbose > 1) info ("Running test %d: iteration=%d\n", testno, iter); gcry_mpi_ec_new (&ctx, NULL, "X448"); if (in_fips_mode) { if (ctx) fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); return; } Q = gcry_mpi_point_new (0); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56) { fail ("error scanning MPI for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error scanning MPI for test %d, %s: %s", testno, "x", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE); mpi_k = gcry_mpi_copy (mpi_x); if (debug) print_mpi ("k", mpi_k); for (i = 0; i < iter; i++) { /* * Another variant of decodeScalar448 thing. */ mpi_kk = gcry_mpi_set (mpi_kk, mpi_k); gcry_mpi_set_bit (mpi_kk, 447); gcry_mpi_clear_bit (mpi_kk, 0); gcry_mpi_clear_bit (mpi_kk, 1); gcry_mpi_ec_mul (Q, mpi_kk, P, ctx); P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE); gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx); if (debug) print_mpi ("k", mpi_k); } { unsigned char res[56]; char *r, *r0; gcry_mpi_print (GCRYMPI_FMT_USG, res, 56, NULL, mpi_k); reverse_buffer (res, 56); r0 = r = xmalloc (113); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=0; i < 56; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("X448 failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: gcry_mpi_release (mpi_kk); gcry_mpi_release (mpi_k); gcry_mpi_point_release (P); gcry_mpi_release (mpi_x); xfree (buffer); gcry_mpi_point_release (Q); gcry_ctx_release (ctx); } /* * X-coordinate of generator of the X448. */ #define G_X ("0500000000000000000000000000000000000000000000000000000000000000" \ "000000000000000000000000000000000000000000000000") /* * Test Diffie-Hellman in RFC-7748. * * Note that it's not like the ECDH of OpenPGP, where we use * ephemeral public key. */ static void test_dh (int testno, const char *a_priv_str, const char *a_pub_str, const char *b_priv_str, const char *b_pub_str, const char *result_str) { /* Test A for private key corresponds to public key. */ test_cv (testno, a_priv_str, G_X, a_pub_str); /* Test B for private key corresponds to public key. */ test_cv (testno, b_priv_str, G_X, b_pub_str); /* Test DH with A's private key and B's public key. */ test_cv (testno, a_priv_str, b_pub_str, result_str); /* Test DH with B's private key and A's public key. */ test_cv (testno, b_priv_str, a_pub_str, result_str); } static void check_x448 (void) { int ntests; info ("Checking X448.\n"); ntests = 0; /* * Values are cited from RFC-7748: 5.2. Test Vectors. * Following two tests are for the first type test. */ test_cv (1, "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121" "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9" "814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239f" "e14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"); ntests++; test_cv (2, "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c5" "38345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b" "165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7" "ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d"); ntests++; /* * Additional test. Value is from second type test. */ test_cv (3, G_X, G_X, "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a" "4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113"); ntests++; /* * Following two tests are for the second type test, * with one iteration and 1,000 iterations. (1,000,000 iterations * takes too long.) */ test_it (4, G_X, 1, "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a" "4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113"); ntests++; test_it (5, G_X, 1000, "aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4" "af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38"); ntests++; /* * Last test is from: 6. Diffie-Hellman, 6.2. Curve448 */ test_dh (6, /* Alice's private key, a */ "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28d" "d9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b", /* Alice's public key, X448(a, 5) */ "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c" "22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0", /* Bob's private key, b */ "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d" "6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d", /* Bob's public key, X448(b, 5) */ "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430" "27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609", /* Their shared secret, K */ "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282b" "b60c0b56fd2464c335543936521c24403085d59a449a5037514a879d"); ntests++; /* three tests which results 0. */ test_cv (7, "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121" "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (8, "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121" "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", "01000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000"); ntests++; test_cv (9, "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121" "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", "feffffffffffffffffffffffffffffffffffffffffffffffffffffff" "feffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000"); ntests++; if (ntests != N_TESTS) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); } int main (int argc, char **argv) { int last_argc = -1; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_x448 (); stop_timer (); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; }