Skip to content

Commit 3001309

Browse files
committed
x509storeissuer: add ability to add certificates to the store during the run
Signed-off-by: Eugene Syromiatnikov <[email protected]>
1 parent b076124 commit 3001309

File tree

1 file changed

+96
-10
lines changed

1 file changed

+96
-10
lines changed

source/x509storeissuer.c

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define NUM_LOAD_CERTS 128
3535
#define NUM_KEYS 16
3636
#define KEY_ALGO "rsa:2048"
37+
#define W_PROBABILITY 50
38+
#define MAX_WRITERS 0
3739
#define RUN_TIME 5
3840
#define QUANTILES 5
3941
#define NONCE_CFG "file:servercert.pem"
@@ -45,6 +47,8 @@ static size_t num_gen_keys = NUM_KEYS;
4547
static const char *gen_key_algo = KEY_ALGO;
4648
static size_t timeout_us = RUN_TIME * 1000000;
4749
static size_t quantiles = QUANTILES;
50+
static size_t max_writers = MAX_WRITERS;
51+
static size_t w_probability = W_PROBABILITY * 65536 / 100;
4852

4953
enum verbosity {
5054
VERBOSITY_TERSE,
@@ -56,6 +60,11 @@ enum verbosity {
5660
VERBOSITY_MAX__
5761
};
5862

63+
static enum mode {
64+
MODE_R,
65+
MODE_RW, /* "MODE_W" is just MODE_RW with 100% write probability */
66+
} mode = MODE_R;
67+
5968
enum nonce_type {
6069
NONCE_GENERATED,
6170
NONCE_PATH,
@@ -65,6 +74,7 @@ struct call_times {
6574
uint64_t duration;
6675
uint64_t total_count;
6776
uint64_t total_found;
77+
uint64_t total_added;
6878
uint64_t min_count;
6979
uint64_t max_count;
7080
double avg;
@@ -88,6 +98,7 @@ struct thread_data {
8898
struct {
8999
uint64_t count;
90100
uint64_t found;
101+
uint64_t added_certs;
91102
OSSL_TIME end_time;
92103
} *q_data;
93104
X509_STORE_CTX *ctx;
@@ -489,24 +500,45 @@ do_x509storeissuer(size_t num)
489500
OSSL_TIME q_end;
490501
size_t q = 0;
491502
size_t count = 0;
503+
size_t add = 0;
492504
size_t found = 0;
493505

494506
td->start_time = ossl_time_now();
495507
duration.t = max_time.t - td->start_time.t;
496508
q_end.t = duration.t / quantiles + td->start_time.t;
497509

498510
do {
499-
if (X509_STORE_CTX_get1_issuer(&issuer, td->ctx, x509_nonce) != 0) {
500-
found++;
501-
X509_free(issuer);
511+
if (mode == MODE_RW
512+
&& (!max_writers || (num < max_writers))
513+
&& (rand() % 65536 < w_probability)) {
514+
size_t cert_id = num_gen_load_certs
515+
+ ((num_gen_certs - num_gen_load_certs)
516+
* num / threadcount)
517+
+ rand() % OSSL_MAX((num_gen_certs
518+
- num_gen_load_certs)
519+
/ threadcount, 1);
520+
521+
if (!X509_STORE_add_cert(store, gen_certs[cert_id])) {
522+
warnx("Failed to add generated certificate %zu to the store",
523+
cert_id);
524+
} else {
525+
add++;
526+
}
527+
} else {
528+
if (X509_STORE_CTX_get1_issuer(&issuer, td->ctx, x509_nonce) != 0) {
529+
found++;
530+
X509_free(issuer);
531+
}
532+
issuer = NULL;
502533
}
503-
issuer = NULL;
534+
504535
count++;
505536
if ((count & 0x3f) == 0) {
506537
time = ossl_time_now();
507538
if (time.t >= q_end.t) {
508539
td->q_data[q].count = count;
509540
td->q_data[q].found = found;
541+
td->q_data[q].added_certs = add;
510542
td->q_data[q].end_time = time;
511543
q_end.t = (duration.t * (++q + 1)) / quantiles + td->start_time.t;
512544
}
@@ -515,6 +547,7 @@ do_x509storeissuer(size_t num)
515547

516548
td->q_data[quantiles - 1].count = count;
517549
td->q_data[quantiles - 1].found = found;
550+
td->q_data[quantiles - 1].added_certs = add;
518551
td->q_data[quantiles - 1].end_time = time;
519552
}
520553

@@ -561,17 +594,21 @@ get_calltimes(struct call_times *times, int verbosity)
561594
(q ? thread_data[i].q_data[q - 1].count : 0);
562595
uint64_t found = thread_data[i].q_data[q].found -
563596
(q ? thread_data[i].q_data[q - 1].found : 0);
597+
uint64_t add = thread_data[i].q_data[q].added_certs -
598+
(q ? thread_data[i].q_data[q - 1].added_certs : 0);
564599

565600
times[q].duration += thread_data[i].q_data[q].end_time.t - start_t;
566601
times[q].total_count += count;
567602
times[q].total_found += found;
603+
times[q].total_added += add;
568604
}
569605
}
570606

571607
for (size_t q = 0; q < quantiles; q++) {
572608
times[quantiles].duration += times[q].duration;
573609
times[quantiles].total_count += times[q].total_count;
574610
times[quantiles].total_found += times[q].total_found;
611+
times[quantiles].total_added += times[q].total_added;
575612
}
576613

577614
for (size_t q = (quantiles == 1); q <= quantiles; q++)
@@ -656,14 +693,18 @@ report_result(int verbosity)
656693
printf(": avg: %9.3lf us, median: %9.3lf us"
657694
", min: %9.3lf us @thread %3zu, max: %9.3lf us @thread %3zu"
658695
", stddev: %9.3lf us (%8.4lf%%)"
659-
", hits %9zu of %9zu (%8.4lf%%)\n",
696+
", hits %9zu of %9zu (%8.4lf%%)"
697+
", added certs: %zu\n",
660698
times[i].avg, times[i].median,
661699
times[i].min, times[i].min_idx,
662700
times[i].max, times[i].max_idx,
663701
times[i].stddev,
664702
100.0 * times[i].stddev / times[i].avg,
665-
times[i].total_found, times[i].total_count,
666-
100.0 * times[i].total_found / (times[i].total_count));
703+
times[i].total_found,
704+
(times[i].total_count - times[i].total_added),
705+
100.0 * times[i].total_found
706+
/ (times[i].total_count - times[i].total_added),
707+
times[i].total_added);
667708
}
668709
break;
669710
}
@@ -675,8 +716,8 @@ usage(char * const argv[])
675716
fprintf(stderr,
676717
"Usage: %s [-t] [-v] [-q N] [-T time] [-G num] [-g num] "
677718
"[-k num_keys] [-K keyalg[:bits][:param=value...]] "
678-
"[-n nonce_type:type_args] "
679-
"[-C threads] certsdir [certsdir...] threadcount\n"
719+
"[-n nonce_type:type_args] [-m mode] [-w writer_threads] "
720+
"[-W percentage] [-C threads] certsdir [certsdir...] threadcount\n"
680721
"\t-t\tTerse output\n"
681722
"\t-v\tVerbose output. Multiple usage increases verbosity.\n"
682723
"\t-q\tGather information about temporal N-quantiles.\n"
@@ -699,6 +740,13 @@ usage(char * const argv[])
699740
"\t\t\tfile:PATH - load nonce certificate from PATH;\n"
700741
"\t\t\tif PATH is relative, the provided certsdir's are searched.\n"
701742
"\t\tDefault: " NONCE_CFG "\n"
743+
"\t-m\tTest mode, can be one of r, rw. Default: r\n"
744+
"\t-w\tMaximum number of threads that attempt addition\n"
745+
"\t\tof the new certificates to the store in rw mode,\n"
746+
"\t\t0 is unlimited. Default: " OPENSSL_MSTR(MAX_WRITERS) "\n"
747+
"\t-W\tProbability of a certificate being written\n"
748+
"\t\tto the store, instead of being queried,\n"
749+
"\t\tin percents. Default: " OPENSSL_MSTR(W_PROBABILITY) "\n"
702750
"\t-C\tNumber of threads that share the same X.509\n"
703751
"\t\tstore context object. Default: "
704752
OPENSSL_MSTR(CTX_SHARE_THREADS) "\n"
@@ -722,8 +770,23 @@ parse_timeout(const char * const optarg)
722770
return timeout_s * 1e6;
723771
}
724772

773+
static double
774+
parse_probability(const char * const optarg)
775+
{
776+
char *endptr = NULL;
777+
double prob;
778+
779+
prob = strtod(optarg, &endptr);
780+
781+
if (endptr == NULL || *endptr != '\0' || prob < 0 || prob > 100)
782+
errx(EXIT_FAILURE, "incorrect probability value: \"%s\"", optarg);
783+
784+
return prob;
785+
}
786+
725787
/**
726788
* Parse nonce configuration string. Currently supported formats:
789+
* * "gen" - generate a nonce certificate
727790
* * "file:PATH" - where PATH is either a relative path (that will be then
728791
* checked against the list of directories provided),
729792
* or an absolute one.
@@ -778,7 +841,7 @@ main(int argc, char *argv[])
778841

779842
parse_nonce_cfg(NONCE_CFG, &nonce_cfg);
780843

781-
while ((opt = getopt(argc, argv, "tvq:T:G:g:k:K:n:C:")) != -1) {
844+
while ((opt = getopt(argc, argv, "tvq:T:G:g:k:K:m:n:w:W:C:")) != -1) {
782845
switch (opt) {
783846
case 't': /* terse */
784847
verbosity = VERBOSITY_TERSE;
@@ -815,9 +878,24 @@ main(int argc, char *argv[])
815878
case 'K': /* key type */
816879
gen_key_algo = optarg;
817880
break;
881+
case 'm': /* mode */
882+
if (strcasecmp(optarg, "r") == 0) {
883+
mode = MODE_R;
884+
} else if (strcasecmp(optarg, "rw") == 0) {
885+
mode = MODE_RW;
886+
} else {
887+
errx(EXIT_FAILURE, "Unknown mode: \"%s\"", optarg);
888+
}
889+
break;
818890
case 'n': /* nonce */
819891
parse_nonce_cfg(optarg, &nonce_cfg);
820892
break;
893+
case 'w': /* maximum writers */
894+
max_writers = parse_int(optarg, 0, INT_MAX,
895+
"maximum number of writers");
896+
case 'W': /* percent of writes */
897+
w_probability = (size_t) (parse_probability(optarg) * 65536 / 100);
898+
break;
821899
case 'C': /* how many threads share X509_STORE_CTX */
822900
ctx_share_cnt = parse_int(optarg, 1, INT_MAX,
823901
"X509_STORE_CTX share degree");
@@ -838,6 +916,11 @@ main(int argc, char *argv[])
838916
if (num_gen_certs < num_gen_load_certs)
839917
errx(EXIT_FAILURE, "Cannot load more certificates than generate");
840918

919+
if (num_gen_certs == num_gen_load_certs && mode == MODE_RW)
920+
errx(EXIT_FAILURE, "No generated certificates to use after"
921+
" the initially loaded ones, please increase"
922+
" -G to be more than -g");
923+
841924
if (argv[optind] == NULL)
842925
errx(EXIT_FAILURE, "certsdir is missing");
843926

@@ -1054,6 +1137,9 @@ main(int argc, char *argv[])
10541137
if (error)
10551138
errx(EXIT_FAILURE, "Error during test");
10561139

1140+
if (mode == MODE_RW)
1141+
report_store_size(store, "after the test run", verbosity);
1142+
10571143
report_result(verbosity);
10581144

10591145
ret = EXIT_SUCCESS;

0 commit comments

Comments
 (0)