summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mauderer <christian.mauderer@embedded-brains.de>2019-03-26 10:19:22 +0100
committerChristian Mauderer <christian.mauderer@embedded-brains.de>2019-03-26 10:19:22 +0100
commit0fecf49362778d77da97e19cf9cbb639c64e1735 (patch)
tree2523337b4a42fd7125e1d785f1061a97618eef60
parentREADME.md: Add Qemu and networking section (diff)
downloadrtems-libbsd-0fecf49362778d77da97e19cf9cbb639c64e1735.tar.bz2
bin/openssl: Import from FreeBSD.
-rw-r--r--freebsd/crypto/openssl/apps/app_rand.c95
-rw-r--r--freebsd/crypto/openssl/apps/apps.c2754
-rw-r--r--freebsd/crypto/openssl/apps/apps.h634
-rw-r--r--freebsd/crypto/openssl/apps/asn1pars.c359
-rw-r--r--freebsd/crypto/openssl/apps/bf_prefix.c179
-rw-r--r--freebsd/crypto/openssl/apps/ca.c2608
-rw-r--r--freebsd/crypto/openssl/apps/ciphers.c268
-rw-r--r--freebsd/crypto/openssl/apps/cms.c1291
-rw-r--r--freebsd/crypto/openssl/apps/crl.c344
-rw-r--r--freebsd/crypto/openssl/apps/crl2p7.c219
-rw-r--r--freebsd/crypto/openssl/apps/dgst.c494
-rw-r--r--freebsd/crypto/openssl/apps/dhparam.c381
-rw-r--r--freebsd/crypto/openssl/apps/dsa.c267
-rw-r--r--freebsd/crypto/openssl/apps/dsaparam.c260
-rw-r--r--freebsd/crypto/openssl/apps/ec.c285
-rw-r--r--freebsd/crypto/openssl/apps/ecparam.c452
-rw-r--r--freebsd/crypto/openssl/apps/enc.c677
-rw-r--r--freebsd/crypto/openssl/apps/engine.c491
-rw-r--r--freebsd/crypto/openssl/apps/errstr.c69
-rw-r--r--freebsd/crypto/openssl/apps/gendsa.c148
-rw-r--r--freebsd/crypto/openssl/apps/genpkey.c324
-rw-r--r--freebsd/crypto/openssl/apps/genrsa.c203
-rw-r--r--freebsd/crypto/openssl/apps/nseq.c116
-rw-r--r--freebsd/crypto/openssl/apps/ocsp.c1595
-rw-r--r--freebsd/crypto/openssl/apps/openssl.c828
-rw-r--r--freebsd/crypto/openssl/apps/opt.c900
-rw-r--r--freebsd/crypto/openssl/apps/passwd.c855
-rw-r--r--freebsd/crypto/openssl/apps/pkcs12.c963
-rw-r--r--freebsd/crypto/openssl/apps/pkcs7.c200
-rw-r--r--freebsd/crypto/openssl/apps/pkcs8.c361
-rw-r--r--freebsd/crypto/openssl/apps/pkey.c245
-rw-r--r--freebsd/crypto/openssl/apps/pkeyparam.c144
-rw-r--r--freebsd/crypto/openssl/apps/pkeyutl.c527
-rw-r--r--freebsd/crypto/openssl/apps/prime.c135
-rw-r--r--freebsd/crypto/openssl/apps/progs.h508
-rw-r--r--freebsd/crypto/openssl/apps/rand.c135
-rw-r--r--freebsd/crypto/openssl/apps/rehash.c514
-rw-r--r--freebsd/crypto/openssl/apps/req.c1666
-rw-r--r--freebsd/crypto/openssl/apps/rsa.c318
-rw-r--r--freebsd/crypto/openssl/apps/rsautl.c284
-rw-r--r--freebsd/crypto/openssl/apps/s_apps.h89
-rw-r--r--freebsd/crypto/openssl/apps/s_cb.c1483
-rw-r--r--freebsd/crypto/openssl/apps/s_client.c3464
-rw-r--r--freebsd/crypto/openssl/apps/s_server.c3617
-rw-r--r--freebsd/crypto/openssl/apps/s_socket.c397
-rw-r--r--freebsd/crypto/openssl/apps/s_time.c407
-rw-r--r--freebsd/crypto/openssl/apps/sess_id.c193
-rw-r--r--freebsd/crypto/openssl/apps/smime.c649
-rw-r--r--freebsd/crypto/openssl/apps/speed.c3693
-rw-r--r--freebsd/crypto/openssl/apps/spkac.c204
-rw-r--r--freebsd/crypto/openssl/apps/srp.c615
-rw-r--r--freebsd/crypto/openssl/apps/storeutl.c475
-rw-r--r--freebsd/crypto/openssl/apps/testdsa.h260
-rw-r--r--freebsd/crypto/openssl/apps/testrsa.h1960
-rw-r--r--freebsd/crypto/openssl/apps/timeouts.h17
-rw-r--r--freebsd/crypto/openssl/apps/ts.c988
-rw-r--r--freebsd/crypto/openssl/apps/verify.c321
-rw-r--r--freebsd/crypto/openssl/apps/version.c196
-rw-r--r--freebsd/crypto/openssl/apps/x509.c1198
59 files changed, 43322 insertions, 0 deletions
diff --git a/freebsd/crypto/openssl/apps/app_rand.c b/freebsd/crypto/openssl/apps/app_rand.c
new file mode 100644
index 00000000..072dfa40
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/app_rand.c
@@ -0,0 +1,95 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/conf.h>
+
+static char *save_rand_file;
+
+void app_RAND_load_conf(CONF *c, const char *section)
+{
+ const char *randfile = NCONF_get_string(c, section, "RANDFILE");
+
+ if (randfile == NULL) {
+ ERR_clear_error();
+ return;
+ }
+ if (RAND_load_file(randfile, -1) < 0) {
+ BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
+ ERR_print_errors(bio_err);
+ }
+ if (save_rand_file == NULL)
+ save_rand_file = OPENSSL_strdup(randfile);
+}
+
+static int loadfiles(char *name)
+{
+ char *p;
+ int last, ret = 1;
+
+ for ( ; ; ) {
+ last = 0;
+ for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++)
+ continue;
+ if (*p == '\0')
+ last = 1;
+ *p = '\0';
+ if (RAND_load_file(name, -1) < 0) {
+ BIO_printf(bio_err, "Can't load %s into RNG\n", name);
+ ERR_print_errors(bio_err);
+ ret = 0;
+ }
+ if (last)
+ break;
+ name = p + 1;
+ if (*name == '\0')
+ break;
+ }
+ return ret;
+}
+
+void app_RAND_write(void)
+{
+ if (save_rand_file == NULL)
+ return;
+ if (RAND_write_file(save_rand_file) == -1) {
+ BIO_printf(bio_err, "Cannot write random bytes:\n");
+ ERR_print_errors(bio_err);
+ }
+ OPENSSL_free(save_rand_file);
+ save_rand_file = NULL;
+}
+
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum r_range { OPT_R_ENUM };
+
+int opt_rand(int opt)
+{
+ switch ((enum r_range)opt) {
+ case OPT_R__FIRST:
+ case OPT_R__LAST:
+ break;
+ case OPT_R_RAND:
+ return loadfiles(opt_arg());
+ break;
+ case OPT_R_WRITERAND:
+ OPENSSL_free(save_rand_file);
+ save_rand_file = OPENSSL_strdup(opt_arg());
+ break;
+ }
+ return 1;
+}
diff --git a/freebsd/crypto/openssl/apps/apps.c b/freebsd/crypto/openssl/apps/apps.c
new file mode 100644
index 00000000..9a7dce83
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/apps.c
@@ -0,0 +1,2754 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
+/*
+ * On VMS, you need to define this to get the declaration of fileno(). The
+ * value 2 is to make sure no function defined in POSIX-2 is left undefined.
+ */
+# define _POSIX_C_SOURCE 2
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# include <fcntl.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ui.h>
+#include <openssl/safestack.h>
+#ifndef OPENSSL_NO_ENGINE
+# include <openssl/engine.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+#endif
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+#include "s_apps.h"
+#include "apps.h"
+
+#ifdef _WIN32
+static int WIN32_rename(const char *from, const char *to);
+# define rename(from,to) WIN32_rename((from),(to))
+#endif
+
+typedef struct {
+ const char *name;
+ unsigned long flag;
+ unsigned long mask;
+} NAME_EX_TBL;
+
+static UI_METHOD *ui_method = NULL;
+static const UI_METHOD *ui_fallback_method = NULL;
+
+static int set_table_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl);
+static int set_multi_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl);
+
+int app_init(long mesgwin);
+
+int chopup_args(ARGS *arg, char *buf)
+{
+ int quoted;
+ char c = '\0', *p = NULL;
+
+ arg->argc = 0;
+ if (arg->size == 0) {
+ arg->size = 20;
+ arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space");
+ }
+
+ for (p = buf;;) {
+ /* Skip whitespace. */
+ while (*p && isspace(_UC(*p)))
+ p++;
+ if (!*p)
+ break;
+
+ /* The start of something good :-) */
+ if (arg->argc >= arg->size) {
+ char **tmp;
+ arg->size += 20;
+ tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size);
+ if (tmp == NULL)
+ return 0;
+ arg->argv = tmp;
+ }
+ quoted = *p == '\'' || *p == '"';
+ if (quoted)
+ c = *p++;
+ arg->argv[arg->argc++] = p;
+
+ /* now look for the end of this */
+ if (quoted) {
+ while (*p && *p != c)
+ p++;
+ *p++ = '\0';
+ } else {
+ while (*p && !isspace(_UC(*p)))
+ p++;
+ if (*p)
+ *p++ = '\0';
+ }
+ }
+ arg->argv[arg->argc] = NULL;
+ return 1;
+}
+
+#ifndef APP_INIT
+int app_init(long mesgwin)
+{
+ return 1;
+}
+#endif
+
+int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath, int noCAfile, int noCApath)
+{
+ if (CAfile == NULL && CApath == NULL) {
+ if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0)
+ return 0;
+ if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0)
+ return 0;
+
+ return 1;
+ }
+ return SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
+}
+
+#ifndef OPENSSL_NO_CT
+
+int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
+{
+ if (path == NULL)
+ return SSL_CTX_set_default_ctlog_list_file(ctx);
+
+ return SSL_CTX_set_ctlog_list_file(ctx, path);
+}
+
+#endif
+
+static unsigned long nmflag = 0;
+static char nmflag_set = 0;
+
+int set_nameopt(const char *arg)
+{
+ int ret = set_name_ex(&nmflag, arg);
+
+ if (ret)
+ nmflag_set = 1;
+
+ return ret;
+}
+
+unsigned long get_nameopt(void)
+{
+ return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
+}
+
+int dump_cert_text(BIO *out, X509 *x)
+{
+ print_name(out, "subject=", X509_get_subject_name(x), get_nameopt());
+ BIO_puts(out, "\n");
+ print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
+ BIO_puts(out, "\n");
+
+ return 0;
+}
+
+static int ui_open(UI *ui)
+{
+ int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method);
+
+ if (opener)
+ return opener(ui);
+ return 1;
+}
+
+static int ui_read(UI *ui, UI_STRING *uis)
+{
+ int (*reader)(UI *ui, UI_STRING *uis) = NULL;
+
+ if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
+ && UI_get0_user_data(ui)) {
+ switch (UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+ if (password && password[0] != '\0') {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ reader = UI_method_get_reader(ui_fallback_method);
+ if (reader)
+ return reader(ui, uis);
+ return 1;
+}
+
+static int ui_write(UI *ui, UI_STRING *uis)
+{
+ int (*writer)(UI *ui, UI_STRING *uis) = NULL;
+
+ if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
+ && UI_get0_user_data(ui)) {
+ switch (UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ {
+ const char *password =
+ ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
+ if (password && password[0] != '\0')
+ return 1;
+ }
+ break;
+ case UIT_NONE:
+ case UIT_BOOLEAN:
+ case UIT_INFO:
+ case UIT_ERROR:
+ break;
+ }
+ }
+
+ writer = UI_method_get_writer(ui_fallback_method);
+ if (writer)
+ return writer(ui, uis);
+ return 1;
+}
+
+static int ui_close(UI *ui)
+{
+ int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method);
+
+ if (closer)
+ return closer(ui);
+ return 1;
+}
+
+int setup_ui_method(void)
+{
+ ui_fallback_method = UI_null();
+#ifndef OPENSSL_NO_UI_CONSOLE
+ ui_fallback_method = UI_OpenSSL();
+#endif
+ ui_method = UI_create_method("OpenSSL application user interface");
+ UI_method_set_opener(ui_method, ui_open);
+ UI_method_set_reader(ui_method, ui_read);
+ UI_method_set_writer(ui_method, ui_write);
+ UI_method_set_closer(ui_method, ui_close);
+ return 0;
+}
+
+void destroy_ui_method(void)
+{
+ if (ui_method) {
+ UI_destroy_method(ui_method);
+ ui_method = NULL;
+ }
+}
+
+const UI_METHOD *get_ui_method(void)
+{
+ return ui_method;
+}
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp)
+{
+ int res = 0;
+ UI *ui = NULL;
+ PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
+
+ ui = UI_new_method(ui_method);
+ if (ui) {
+ int ok = 0;
+ char *buff = NULL;
+ int ui_flags = 0;
+ const char *prompt_info = NULL;
+ char *prompt;
+
+ if (cb_data != NULL && cb_data->prompt_info != NULL)
+ prompt_info = cb_data->prompt_info;
+ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
+ if (!prompt) {
+ BIO_printf(bio_err, "Out of memory\n");
+ UI_free(ui);
+ return 0;
+ }
+
+ ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
+ UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+
+ /* We know that there is no previous user data to return to us */
+ (void)UI_add_user_data(ui, cb_data);
+
+ ok = UI_add_input_string(ui, prompt, ui_flags, buf,
+ PW_MIN_LENGTH, bufsiz - 1);
+
+ if (ok >= 0 && verify) {
+ buff = app_malloc(bufsiz, "password buffer");
+ ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
+ PW_MIN_LENGTH, bufsiz - 1, buf);
+ }
+ if (ok >= 0)
+ do {
+ ok = UI_process(ui);
+ } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
+
+ OPENSSL_clear_free(buff, (unsigned int)bufsiz);
+
+ if (ok >= 0)
+ res = strlen(buf);
+ if (ok == -1) {
+ BIO_printf(bio_err, "User interface error\n");
+ ERR_print_errors(bio_err);
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ if (ok == -2) {
+ BIO_printf(bio_err, "aborted!\n");
+ OPENSSL_cleanse(buf, (unsigned int)bufsiz);
+ res = 0;
+ }
+ UI_free(ui);
+ OPENSSL_free(prompt);
+ }
+ return res;
+}
+
+static char *app_get_pass(const char *arg, int keepbio);
+
+int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
+{
+ int same;
+ if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2))
+ same = 0;
+ else
+ same = 1;
+ if (arg1 != NULL) {
+ *pass1 = app_get_pass(arg1, same);
+ if (*pass1 == NULL)
+ return 0;
+ } else if (pass1 != NULL) {
+ *pass1 = NULL;
+ }
+ if (arg2 != NULL) {
+ *pass2 = app_get_pass(arg2, same ? 2 : 0);
+ if (*pass2 == NULL)
+ return 0;
+ } else if (pass2 != NULL) {
+ *pass2 = NULL;
+ }
+ return 1;
+}
+
+static char *app_get_pass(const char *arg, int keepbio)
+{
+ char *tmp, tpass[APP_PASS_LEN];
+ static BIO *pwdbio = NULL;
+ int i;
+
+ if (strncmp(arg, "pass:", 5) == 0)
+ return OPENSSL_strdup(arg + 5);
+ if (strncmp(arg, "env:", 4) == 0) {
+ tmp = getenv(arg + 4);
+ if (tmp == NULL) {
+ BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4);
+ return NULL;
+ }
+ return OPENSSL_strdup(tmp);
+ }
+ if (!keepbio || pwdbio == NULL) {
+ if (strncmp(arg, "file:", 5) == 0) {
+ pwdbio = BIO_new_file(arg + 5, "r");
+ if (pwdbio == NULL) {
+ BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
+ return NULL;
+ }
+#if !defined(_WIN32)
+ /*
+ * Under _WIN32, which covers even Win64 and CE, file
+ * descriptors referenced by BIO_s_fd are not inherited
+ * by child process and therefore below is not an option.
+ * It could have been an option if bss_fd.c was operating
+ * on real Windows descriptors, such as those obtained
+ * with CreateFile.
+ */
+ } else if (strncmp(arg, "fd:", 3) == 0) {
+ BIO *btmp;
+ i = atoi(arg + 3);
+ if (i >= 0)
+ pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
+ if ((i < 0) || !pwdbio) {
+ BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
+ return NULL;
+ }
+ /*
+ * Can't do BIO_gets on an fd BIO so add a buffering BIO
+ */
+ btmp = BIO_new(BIO_f_buffer());
+ pwdbio = BIO_push(btmp, pwdbio);
+#endif
+ } else if (strcmp(arg, "stdin") == 0) {
+ pwdbio = dup_bio_in(FORMAT_TEXT);
+ if (!pwdbio) {
+ BIO_printf(bio_err, "Can't open BIO for stdin\n");
+ return NULL;
+ }
+ } else {
+ BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg);
+ return NULL;
+ }
+ }
+ i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
+ if (keepbio != 1) {
+ BIO_free_all(pwdbio);
+ pwdbio = NULL;
+ }
+ if (i <= 0) {
+ BIO_printf(bio_err, "Error reading password from BIO\n");
+ return NULL;
+ }
+ tmp = strchr(tpass, '\n');
+ if (tmp != NULL)
+ *tmp = 0;
+ return OPENSSL_strdup(tpass);
+}
+
+CONF *app_load_config_bio(BIO *in, const char *filename)
+{
+ long errorline = -1;
+ CONF *conf;
+ int i;
+
+ conf = NCONF_new(NULL);
+ i = NCONF_load_bio(conf, in, &errorline);
+ if (i > 0)
+ return conf;
+
+ if (errorline <= 0) {
+ BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
+ } else {
+ BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
+ errorline);
+ }
+ if (filename != NULL)
+ BIO_printf(bio_err, "config file \"%s\"\n", filename);
+ else
+ BIO_printf(bio_err, "config input");
+
+ NCONF_free(conf);
+ return NULL;
+}
+
+CONF *app_load_config(const char *filename)
+{
+ BIO *in;
+ CONF *conf;
+
+ in = bio_open_default(filename, 'r', FORMAT_TEXT);
+ if (in == NULL)
+ return NULL;
+
+ conf = app_load_config_bio(in, filename);
+ BIO_free(in);
+ return conf;
+}
+
+CONF *app_load_config_quiet(const char *filename)
+{
+ BIO *in;
+ CONF *conf;
+
+ in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT);
+ if (in == NULL)
+ return NULL;
+
+ conf = app_load_config_bio(in, filename);
+ BIO_free(in);
+ return conf;
+}
+
+int app_load_modules(const CONF *config)
+{
+ CONF *to_free = NULL;
+
+ if (config == NULL)
+ config = to_free = app_load_config_quiet(default_config_file);
+ if (config == NULL)
+ return 1;
+
+ if (CONF_modules_load(config, NULL, 0) <= 0) {
+ BIO_printf(bio_err, "Error configuring OpenSSL modules\n");
+ ERR_print_errors(bio_err);
+ NCONF_free(to_free);
+ return 0;
+ }
+ NCONF_free(to_free);
+ return 1;
+}
+
+int add_oid_section(CONF *conf)
+{
+ char *p;
+ STACK_OF(CONF_VALUE) *sktmp;
+ CONF_VALUE *cnf;
+ int i;
+
+ if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
+ ERR_clear_error();
+ return 1;
+ }
+ if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
+ BIO_printf(bio_err, "problem loading oid section %s\n", p);
+ return 0;
+ }
+ for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
+ cnf = sk_CONF_VALUE_value(sktmp, i);
+ if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+ BIO_printf(bio_err, "problem creating object %s=%s\n",
+ cnf->name, cnf->value);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int load_pkcs12(BIO *in, const char *desc,
+ pem_password_cb *pem_cb, void *cb_data,
+ EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
+{
+ const char *pass;
+ char tpass[PEM_BUFSIZE];
+ int len, ret = 0;
+ PKCS12 *p12;
+ p12 = d2i_PKCS12_bio(in, NULL);
+ if (p12 == NULL) {
+ BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc);
+ goto die;
+ }
+ /* See if an empty password will do */
+ if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
+ pass = "";
+ } else {
+ if (!pem_cb)
+ pem_cb = (pem_password_cb *)password_callback;
+ len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
+ if (len < 0) {
+ BIO_printf(bio_err, "Passphrase callback error for %s\n", desc);
+ goto die;
+ }
+ if (len < PEM_BUFSIZE)
+ tpass[len] = 0;
+ if (!PKCS12_verify_mac(p12, tpass, len)) {
+ BIO_printf(bio_err,
+ "Mac verify error (wrong password?) in PKCS12 file for %s\n",
+ desc);
+ goto die;
+ }
+ pass = tpass;
+ }
+ ret = PKCS12_parse(p12, pass, pkey, cert, ca);
+ die:
+ PKCS12_free(p12);
+ return ret;
+}
+
+#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
+static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl)
+{
+ char *host = NULL, *port = NULL, *path = NULL;
+ BIO *bio = NULL;
+ OCSP_REQ_CTX *rctx = NULL;
+ int use_ssl, rv = 0;
+ if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
+ goto err;
+ if (use_ssl) {
+ BIO_puts(bio_err, "https not supported\n");
+ goto err;
+ }
+ bio = BIO_new_connect(host);
+ if (!bio || !BIO_set_conn_port(bio, port))
+ goto err;
+ rctx = OCSP_REQ_CTX_new(bio, 1024);
+ if (rctx == NULL)
+ goto err;
+ if (!OCSP_REQ_CTX_http(rctx, "GET", path))
+ goto err;
+ if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
+ goto err;
+ if (pcert) {
+ do {
+ rv = X509_http_nbio(rctx, pcert);
+ } while (rv == -1);
+ } else {
+ do {
+ rv = X509_CRL_http_nbio(rctx, pcrl);
+ } while (rv == -1);
+ }
+
+ err:
+ OPENSSL_free(host);
+ OPENSSL_free(path);
+ OPENSSL_free(port);
+ BIO_free_all(bio);
+ OCSP_REQ_CTX_free(rctx);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error loading %s from %s\n",
+ pcert ? "certificate" : "CRL", url);
+ ERR_print_errors(bio_err);
+ }
+ return rv;
+}
+#endif
+
+X509 *load_cert(const char *file, int format, const char *cert_descrip)
+{
+ X509 *x = NULL;
+ BIO *cert;
+
+ if (format == FORMAT_HTTP) {
+#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
+ load_cert_crl_http(file, &x, NULL);
+#endif
+ return x;
+ }
+
+ if (file == NULL) {
+ unbuffer(stdin);
+ cert = dup_bio_in(format);
+ } else {
+ cert = bio_open_default(file, 'r', format);
+ }
+ if (cert == NULL)
+ goto end;
+
+ if (format == FORMAT_ASN1) {
+ x = d2i_X509_bio(cert, NULL);
+ } else if (format == FORMAT_PEM) {
+ x = PEM_read_bio_X509_AUX(cert, NULL,
+ (pem_password_cb *)password_callback, NULL);
+ } else if (format == FORMAT_PKCS12) {
+ if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL))
+ goto end;
+ } else {
+ BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip);
+ goto end;
+ }
+ end:
+ if (x == NULL) {
+ BIO_printf(bio_err, "unable to load certificate\n");
+ ERR_print_errors(bio_err);
+ }
+ BIO_free(cert);
+ return x;
+}
+
+X509_CRL *load_crl(const char *infile, int format)
+{
+ X509_CRL *x = NULL;
+ BIO *in = NULL;
+
+ if (format == FORMAT_HTTP) {
+#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
+ load_cert_crl_http(infile, NULL, &x);
+#endif
+ return x;
+ }
+
+ in = bio_open_default(infile, 'r', format);
+ if (in == NULL)
+ goto end;
+ if (format == FORMAT_ASN1) {
+ x = d2i_X509_CRL_bio(in, NULL);
+ } else if (format == FORMAT_PEM) {
+ x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+ } else {
+ BIO_printf(bio_err, "bad input format specified for input crl\n");
+ goto end;
+ }
+ if (x == NULL) {
+ BIO_printf(bio_err, "unable to load CRL\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ end:
+ BIO_free(in);
+ return x;
+}
+
+EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *key_descrip)
+{
+ BIO *key = NULL;
+ EVP_PKEY *pkey = NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
+
+ if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
+ BIO_printf(bio_err, "no keyfile specified\n");
+ goto end;
+ }
+ if (format == FORMAT_ENGINE) {
+ if (e == NULL) {
+ BIO_printf(bio_err, "no engine specified\n");
+ } else {
+#ifndef OPENSSL_NO_ENGINE
+ if (ENGINE_init(e)) {
+ pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data);
+ ENGINE_finish(e);
+ }
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
+ ERR_print_errors(bio_err);
+ }
+#else
+ BIO_printf(bio_err, "engines not supported\n");
+#endif
+ }
+ goto end;
+ }
+ if (file == NULL && maybe_stdin) {
+ unbuffer(stdin);
+ key = dup_bio_in(format);
+ } else {
+ key = bio_open_default(file, 'r', format);
+ }
+ if (key == NULL)
+ goto end;
+ if (format == FORMAT_ASN1) {
+ pkey = d2i_PrivateKey_bio(key, NULL);
+ } else if (format == FORMAT_PEM) {
+ pkey = PEM_read_bio_PrivateKey(key, NULL,
+ (pem_password_cb *)password_callback,
+ &cb_data);
+ } else if (format == FORMAT_PKCS12) {
+ if (!load_pkcs12(key, key_descrip,
+ (pem_password_cb *)password_callback, &cb_data,
+ &pkey, NULL, NULL))
+ goto end;
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
+ } else if (format == FORMAT_MSBLOB) {
+ pkey = b2i_PrivateKey_bio(key);
+ } else if (format == FORMAT_PVK) {
+ pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
+ &cb_data);
+#endif
+ } else {
+ BIO_printf(bio_err, "bad input format specified for key file\n");
+ goto end;
+ }
+ end:
+ BIO_free(key);
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "unable to load %s\n", key_descrip);
+ ERR_print_errors(bio_err);
+ }
+ return pkey;
+}
+
+EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *key_descrip)
+{
+ BIO *key = NULL;
+ EVP_PKEY *pkey = NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
+
+ if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
+ BIO_printf(bio_err, "no keyfile specified\n");
+ goto end;
+ }
+ if (format == FORMAT_ENGINE) {
+ if (e == NULL) {
+ BIO_printf(bio_err, "no engine specified\n");
+ } else {
+#ifndef OPENSSL_NO_ENGINE
+ pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data);
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip);
+ ERR_print_errors(bio_err);
+ }
+#else
+ BIO_printf(bio_err, "engines not supported\n");
+#endif
+ }
+ goto end;
+ }
+ if (file == NULL && maybe_stdin) {
+ unbuffer(stdin);
+ key = dup_bio_in(format);
+ } else {
+ key = bio_open_default(file, 'r', format);
+ }
+ if (key == NULL)
+ goto end;
+ if (format == FORMAT_ASN1) {
+ pkey = d2i_PUBKEY_bio(key, NULL);
+ } else if (format == FORMAT_ASN1RSA) {
+#ifndef OPENSSL_NO_RSA
+ RSA *rsa;
+ rsa = d2i_RSAPublicKey_bio(key, NULL);
+ if (rsa) {
+ pkey = EVP_PKEY_new();
+ if (pkey != NULL)
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ RSA_free(rsa);
+ } else
+#else
+ BIO_printf(bio_err, "RSA keys not supported\n");
+#endif
+ pkey = NULL;
+ } else if (format == FORMAT_PEMRSA) {
+#ifndef OPENSSL_NO_RSA
+ RSA *rsa;
+ rsa = PEM_read_bio_RSAPublicKey(key, NULL,
+ (pem_password_cb *)password_callback,
+ &cb_data);
+ if (rsa != NULL) {
+ pkey = EVP_PKEY_new();
+ if (pkey != NULL)
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ RSA_free(rsa);
+ } else
+#else
+ BIO_printf(bio_err, "RSA keys not supported\n");
+#endif
+ pkey = NULL;
+ } else if (format == FORMAT_PEM) {
+ pkey = PEM_read_bio_PUBKEY(key, NULL,
+ (pem_password_cb *)password_callback,
+ &cb_data);
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
+ } else if (format == FORMAT_MSBLOB) {
+ pkey = b2i_PublicKey_bio(key);
+#endif
+ }
+ end:
+ BIO_free(key);
+ if (pkey == NULL)
+ BIO_printf(bio_err, "unable to load %s\n", key_descrip);
+ return pkey;
+}
+
+static int load_certs_crls(const char *file, int format,
+ const char *pass, const char *desc,
+ STACK_OF(X509) **pcerts,
+ STACK_OF(X509_CRL) **pcrls)
+{
+ int i;
+ BIO *bio;
+ STACK_OF(X509_INFO) *xis = NULL;
+ X509_INFO *xi;
+ PW_CB_DATA cb_data;
+ int rv = 0;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
+
+ if (format != FORMAT_PEM) {
+ BIO_printf(bio_err, "bad input format specified for %s\n", desc);
+ return 0;
+ }
+
+ bio = bio_open_default(file, 'r', FORMAT_PEM);
+ if (bio == NULL)
+ return 0;
+
+ xis = PEM_X509_INFO_read_bio(bio, NULL,
+ (pem_password_cb *)password_callback,
+ &cb_data);
+
+ BIO_free(bio);
+
+ if (pcerts != NULL && *pcerts == NULL) {
+ *pcerts = sk_X509_new_null();
+ if (*pcerts == NULL)
+ goto end;
+ }
+
+ if (pcrls != NULL && *pcrls == NULL) {
+ *pcrls = sk_X509_CRL_new_null();
+ if (*pcrls == NULL)
+ goto end;
+ }
+
+ for (i = 0; i < sk_X509_INFO_num(xis); i++) {
+ xi = sk_X509_INFO_value(xis, i);
+ if (xi->x509 != NULL && pcerts != NULL) {
+ if (!sk_X509_push(*pcerts, xi->x509))
+ goto end;
+ xi->x509 = NULL;
+ }
+ if (xi->crl != NULL && pcrls != NULL) {
+ if (!sk_X509_CRL_push(*pcrls, xi->crl))
+ goto end;
+ xi->crl = NULL;
+ }
+ }
+
+ if (pcerts != NULL && sk_X509_num(*pcerts) > 0)
+ rv = 1;
+
+ if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0)
+ rv = 1;
+
+ end:
+
+ sk_X509_INFO_pop_free(xis, X509_INFO_free);
+
+ if (rv == 0) {
+ if (pcerts != NULL) {
+ sk_X509_pop_free(*pcerts, X509_free);
+ *pcerts = NULL;
+ }
+ if (pcrls != NULL) {
+ sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
+ *pcrls = NULL;
+ }
+ BIO_printf(bio_err, "unable to load %s\n",
+ pcerts ? "certificates" : "CRLs");
+ ERR_print_errors(bio_err);
+ }
+ return rv;
+}
+
+void* app_malloc(int sz, const char *what)
+{
+ void *vp = OPENSSL_malloc(sz);
+
+ if (vp == NULL) {
+ BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n",
+ opt_getprog(), sz, what);
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ return vp;
+}
+
+/*
+ * Initialize or extend, if *certs != NULL, a certificate stack.
+ */
+int load_certs(const char *file, STACK_OF(X509) **certs, int format,
+ const char *pass, const char *desc)
+{
+ return load_certs_crls(file, format, pass, desc, certs, NULL);
+}
+
+/*
+ * Initialize or extend, if *crls != NULL, a certificate stack.
+ */
+int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
+ const char *pass, const char *desc)
+{
+ return load_certs_crls(file, format, pass, desc, NULL, crls);
+}
+
+#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
+/* Return error for unknown extensions */
+#define X509V3_EXT_DEFAULT 0
+/* Print error for unknown extensions */
+#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
+/* ASN1 parse unknown extensions */
+#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
+/* BIO_dump unknown extensions */
+#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+
+#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
+ X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
+
+int set_cert_ex(unsigned long *flags, const char *arg)
+{
+ static const NAME_EX_TBL cert_tbl[] = {
+ {"compatible", X509_FLAG_COMPAT, 0xffffffffl},
+ {"ca_default", X509_FLAG_CA, 0xffffffffl},
+ {"no_header", X509_FLAG_NO_HEADER, 0},
+ {"no_version", X509_FLAG_NO_VERSION, 0},
+ {"no_serial", X509_FLAG_NO_SERIAL, 0},
+ {"no_signame", X509_FLAG_NO_SIGNAME, 0},
+ {"no_validity", X509_FLAG_NO_VALIDITY, 0},
+ {"no_subject", X509_FLAG_NO_SUBJECT, 0},
+ {"no_issuer", X509_FLAG_NO_ISSUER, 0},
+ {"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
+ {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
+ {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
+ {"no_aux", X509_FLAG_NO_AUX, 0},
+ {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
+ {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
+ {NULL, 0, 0}
+ };
+ return set_multi_opts(flags, arg, cert_tbl);
+}
+
+int set_name_ex(unsigned long *flags, const char *arg)
+{
+ static const NAME_EX_TBL ex_tbl[] = {
+ {"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
+ {"esc_2254", ASN1_STRFLGS_ESC_2254, 0},
+ {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
+ {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
+ {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
+ {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
+ {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
+ {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
+ {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
+ {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
+ {"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
+ {"compat", XN_FLAG_COMPAT, 0xffffffffL},
+ {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
+ {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
+ {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
+ {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
+ {"dn_rev", XN_FLAG_DN_REV, 0},
+ {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
+ {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
+ {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
+ {"align", XN_FLAG_FN_ALIGN, 0},
+ {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
+ {"space_eq", XN_FLAG_SPC_EQ, 0},
+ {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
+ {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
+ {"oneline", XN_FLAG_ONELINE, 0xffffffffL},
+ {"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
+ {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
+ {NULL, 0, 0}
+ };
+ if (set_multi_opts(flags, arg, ex_tbl) == 0)
+ return 0;
+ if (*flags != XN_FLAG_COMPAT
+ && (*flags & XN_FLAG_SEP_MASK) == 0)
+ *flags |= XN_FLAG_SEP_CPLUS_SPC;
+ return 1;
+}
+
+int set_ext_copy(int *copy_type, const char *arg)
+{
+ if (strcasecmp(arg, "none") == 0)
+ *copy_type = EXT_COPY_NONE;
+ else if (strcasecmp(arg, "copy") == 0)
+ *copy_type = EXT_COPY_ADD;
+ else if (strcasecmp(arg, "copyall") == 0)
+ *copy_type = EXT_COPY_ALL;
+ else
+ return 0;
+ return 1;
+}
+
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
+{
+ STACK_OF(X509_EXTENSION) *exts = NULL;
+ X509_EXTENSION *ext, *tmpext;
+ ASN1_OBJECT *obj;
+ int i, idx, ret = 0;
+ if (!x || !req || (copy_type == EXT_COPY_NONE))
+ return 1;
+ exts = X509_REQ_get_extensions(req);
+
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ ext = sk_X509_EXTENSION_value(exts, i);
+ obj = X509_EXTENSION_get_object(ext);
+ idx = X509_get_ext_by_OBJ(x, obj, -1);
+ /* Does extension exist? */
+ if (idx != -1) {
+ /* If normal copy don't override existing extension */
+ if (copy_type == EXT_COPY_ADD)
+ continue;
+ /* Delete all extensions of same type */
+ do {
+ tmpext = X509_get_ext(x, idx);
+ X509_delete_ext(x, idx);
+ X509_EXTENSION_free(tmpext);
+ idx = X509_get_ext_by_OBJ(x, obj, -1);
+ } while (idx != -1);
+ }
+ if (!X509_add_ext(x, ext, -1))
+ goto end;
+ }
+
+ ret = 1;
+
+ end:
+
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+
+ return ret;
+}
+
+static int set_multi_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl)
+{
+ STACK_OF(CONF_VALUE) *vals;
+ CONF_VALUE *val;
+ int i, ret = 1;
+ if (!arg)
+ return 0;
+ vals = X509V3_parse_list(arg);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ val = sk_CONF_VALUE_value(vals, i);
+ if (!set_table_opts(flags, val->name, in_tbl))
+ ret = 0;
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return ret;
+}
+
+static int set_table_opts(unsigned long *flags, const char *arg,
+ const NAME_EX_TBL * in_tbl)
+{
+ char c;
+ const NAME_EX_TBL *ptbl;
+ c = arg[0];
+
+ if (c == '-') {
+ c = 0;
+ arg++;
+ } else if (c == '+') {
+ c = 1;
+ arg++;
+ } else {
+ c = 1;
+ }
+
+ for (ptbl = in_tbl; ptbl->name; ptbl++) {
+ if (strcasecmp(arg, ptbl->name) == 0) {
+ *flags &= ~ptbl->mask;
+ if (c)
+ *flags |= ptbl->flag;
+ else
+ *flags &= ~ptbl->flag;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void print_name(BIO *out, const char *title, X509_NAME *nm,
+ unsigned long lflags)
+{
+ char *buf;
+ char mline = 0;
+ int indent = 0;
+
+ if (title)
+ BIO_puts(out, title);
+ if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+ mline = 1;
+ indent = 4;
+ }
+ if (lflags == XN_FLAG_COMPAT) {
+ buf = X509_NAME_oneline(nm, 0, 0);
+ BIO_puts(out, buf);
+ BIO_puts(out, "\n");
+ OPENSSL_free(buf);
+ } else {
+ if (mline)
+ BIO_puts(out, "\n");
+ X509_NAME_print_ex(out, nm, indent, lflags);
+ BIO_puts(out, "\n");
+ }
+}
+
+void print_bignum_var(BIO *out, const BIGNUM *in, const char *var,
+ int len, unsigned char *buffer)
+{
+ BIO_printf(out, " static unsigned char %s_%d[] = {", var, len);
+ if (BN_is_zero(in)) {
+ BIO_printf(out, "\n 0x00");
+ } else {
+ int i, l;
+
+ l = BN_bn2bin(in, buffer);
+ for (i = 0; i < l; i++) {
+ BIO_printf(out, (i % 10) == 0 ? "\n " : " ");
+ if (i < l - 1)
+ BIO_printf(out, "0x%02X,", buffer[i]);
+ else
+ BIO_printf(out, "0x%02X", buffer[i]);
+ }
+ }
+ BIO_printf(out, "\n };\n");
+}
+
+void print_array(BIO *out, const char* title, int len, const unsigned char* d)
+{
+ int i;
+
+ BIO_printf(out, "unsigned char %s[%d] = {", title, len);
+ for (i = 0; i < len; i++) {
+ if ((i % 10) == 0)
+ BIO_printf(out, "\n ");
+ if (i < len - 1)
+ BIO_printf(out, "0x%02X, ", d[i]);
+ else
+ BIO_printf(out, "0x%02X", d[i]);
+ }
+ BIO_printf(out, "\n};\n");
+}
+
+X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath)
+{
+ X509_STORE *store = X509_STORE_new();
+ X509_LOOKUP *lookup;
+
+ if (store == NULL)
+ goto end;
+
+ if (CAfile != NULL || !noCAfile) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if (lookup == NULL)
+ goto end;
+ if (CAfile) {
+ if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
+ BIO_printf(bio_err, "Error loading file %s\n", CAfile);
+ goto end;
+ }
+ } else {
+ X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+ }
+ }
+
+ if (CApath != NULL || !noCApath) {
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ goto end;
+ if (CApath) {
+ if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) {
+ BIO_printf(bio_err, "Error loading directory %s\n", CApath);
+ goto end;
+ }
+ } else {
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+ }
+ }
+
+ ERR_clear_error();
+ return store;
+ end:
+ X509_STORE_free(store);
+ return NULL;
+}
+
+#ifndef OPENSSL_NO_ENGINE
+/* Try to load an engine in a shareable library */
+static ENGINE *try_load_engine(const char *engine)
+{
+ ENGINE *e = ENGINE_by_id("dynamic");
+ if (e) {
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
+ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+ ENGINE_free(e);
+ e = NULL;
+ }
+ }
+ return e;
+}
+#endif
+
+ENGINE *setup_engine(const char *engine, int debug)
+{
+ ENGINE *e = NULL;
+
+#ifndef OPENSSL_NO_ENGINE
+ if (engine != NULL) {
+ if (strcmp(engine, "auto") == 0) {
+ BIO_printf(bio_err, "enabling auto ENGINE support\n");
+ ENGINE_register_all_complete();
+ return NULL;
+ }
+ if ((e = ENGINE_by_id(engine)) == NULL
+ && (e = try_load_engine(engine)) == NULL) {
+ BIO_printf(bio_err, "invalid engine \"%s\"\n", engine);
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+ if (debug) {
+ ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
+ }
+ ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
+ if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+ BIO_printf(bio_err, "can't use that engine\n");
+ ERR_print_errors(bio_err);
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e));
+ }
+#endif
+ return e;
+}
+
+void release_engine(ENGINE *e)
+{
+#ifndef OPENSSL_NO_ENGINE
+ if (e != NULL)
+ /* Free our "structural" reference. */
+ ENGINE_free(e);
+#endif
+}
+
+static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
+{
+ const char *n;
+
+ n = a[DB_serial];
+ while (*n == '0')
+ n++;
+ return OPENSSL_LH_strhash(n);
+}
+
+static int index_serial_cmp(const OPENSSL_CSTRING *a,
+ const OPENSSL_CSTRING *b)
+{
+ const char *aa, *bb;
+
+ for (aa = a[DB_serial]; *aa == '0'; aa++) ;
+ for (bb = b[DB_serial]; *bb == '0'; bb++) ;
+ return strcmp(aa, bb);
+}
+
+static int index_name_qual(char **a)
+{
+ return (a[0][0] == 'V');
+}
+
+static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
+{
+ return OPENSSL_LH_strhash(a[DB_name]);
+}
+
+int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
+{
+ return strcmp(a[DB_name], b[DB_name]);
+}
+
+static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
+static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
+#undef BSIZE
+#define BSIZE 256
+BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai)
+{
+ BIO *in = NULL;
+ BIGNUM *ret = NULL;
+ char buf[1024];
+ ASN1_INTEGER *ai = NULL;
+
+ ai = ASN1_INTEGER_new();
+ if (ai == NULL)
+ goto err;
+
+ in = BIO_new_file(serialfile, "r");
+ if (in == NULL) {
+ if (!create) {
+ perror(serialfile);
+ goto err;
+ }
+ ERR_clear_error();
+ ret = BN_new();
+ if (ret == NULL || !rand_serial(ret, ai))
+ BIO_printf(bio_err, "Out of memory\n");
+ } else {
+ if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
+ BIO_printf(bio_err, "unable to load number from %s\n",
+ serialfile);
+ goto err;
+ }
+ ret = ASN1_INTEGER_to_BN(ai, NULL);
+ if (ret == NULL) {
+ BIO_printf(bio_err,
+ "error converting number from bin to BIGNUM\n");
+ goto err;
+ }
+ }
+
+ if (ret && retai) {
+ *retai = ai;
+ ai = NULL;
+ }
+ err:
+ BIO_free(in);
+ ASN1_INTEGER_free(ai);
+ return ret;
+}
+
+int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
+ ASN1_INTEGER **retai)
+{
+ char buf[1][BSIZE];
+ BIO *out = NULL;
+ int ret = 0;
+ ASN1_INTEGER *ai = NULL;
+ int j;
+
+ if (suffix == NULL)
+ j = strlen(serialfile);
+ else
+ j = strlen(serialfile) + strlen(suffix) + 1;
+ if (j >= BSIZE) {
+ BIO_printf(bio_err, "file name too long\n");
+ goto err;
+ }
+
+ if (suffix == NULL)
+ OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
+ else {
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
+#else
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
+#endif
+ }
+ out = BIO_new_file(buf[0], "w");
+ if (out == NULL) {
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
+ if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
+ BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
+ goto err;
+ }
+ i2a_ASN1_INTEGER(out, ai);
+ BIO_puts(out, "\n");
+ ret = 1;
+ if (retai) {
+ *retai = ai;
+ ai = NULL;
+ }
+ err:
+ BIO_free_all(out);
+ ASN1_INTEGER_free(ai);
+ return ret;
+}
+
+int rotate_serial(const char *serialfile, const char *new_suffix,
+ const char *old_suffix)
+{
+ char buf[2][BSIZE];
+ int i, j;
+
+ i = strlen(serialfile) + strlen(old_suffix);
+ j = strlen(serialfile) + strlen(new_suffix);
+ if (i > j)
+ j = i;
+ if (j + 1 >= BSIZE) {
+ BIO_printf(bio_err, "file name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
+#else
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
+#endif
+ if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err,
+ "unable to rename %s to %s\n", serialfile, buf[1]);
+ perror("reason");
+ goto err;
+ }
+ if (rename(buf[0], serialfile) < 0) {
+ BIO_printf(bio_err,
+ "unable to rename %s to %s\n", buf[0], serialfile);
+ perror("reason");
+ rename(buf[1], serialfile);
+ goto err;
+ }
+ return 1;
+ err:
+ return 0;
+}
+
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
+{
+ BIGNUM *btmp;
+ int ret = 0;
+
+ btmp = b == NULL ? BN_new() : b;
+ if (btmp == NULL)
+ return 0;
+
+ if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
+ goto error;
+ if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
+ goto error;
+
+ ret = 1;
+
+ error:
+
+ if (btmp != b)
+ BN_free(btmp);
+
+ return ret;
+}
+
+CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
+{
+ CA_DB *retdb = NULL;
+ TXT_DB *tmpdb = NULL;
+ BIO *in;
+ CONF *dbattr_conf = NULL;
+ char buf[BSIZE];
+#ifndef OPENSSL_NO_POSIX_IO
+ FILE *dbfp;
+ struct stat dbst;
+#endif
+
+ in = BIO_new_file(dbfile, "r");
+ if (in == NULL) {
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_POSIX_IO
+ BIO_get_fp(in, &dbfp);
+ if (fstat(fileno(dbfp), &dbst) == -1) {
+ SYSerr(SYS_F_FSTAT, errno);
+ ERR_add_error_data(3, "fstat('", dbfile, "')");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+#endif
+
+ if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
+ goto err;
+
+#ifndef OPENSSL_SYS_VMS
+ BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
+#else
+ BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
+#endif
+ dbattr_conf = app_load_config(buf);
+
+ retdb = app_malloc(sizeof(*retdb), "new DB");
+ retdb->db = tmpdb;
+ tmpdb = NULL;
+ if (db_attr)
+ retdb->attributes = *db_attr;
+ else {
+ retdb->attributes.unique_subject = 1;
+ }
+
+ if (dbattr_conf) {
+ char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
+ if (p) {
+ retdb->attributes.unique_subject = parse_yesno(p, 1);
+ }
+ }
+
+ retdb->dbfname = OPENSSL_strdup(dbfile);
+#ifndef OPENSSL_NO_POSIX_IO
+ retdb->dbst = dbst;
+#endif
+
+ err:
+ NCONF_free(dbattr_conf);
+ TXT_DB_free(tmpdb);
+ BIO_free_all(in);
+ return retdb;
+}
+
+/*
+ * Returns > 0 on success, <= 0 on error
+ */
+int index_index(CA_DB *db)
+{
+ if (!TXT_DB_create_index(db->db, DB_serial, NULL,
+ LHASH_HASH_FN(index_serial),
+ LHASH_COMP_FN(index_serial))) {
+ BIO_printf(bio_err,
+ "error creating serial number index:(%ld,%ld,%ld)\n",
+ db->db->error, db->db->arg1, db->db->arg2);
+ return 0;
+ }
+
+ if (db->attributes.unique_subject
+ && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
+ LHASH_HASH_FN(index_name),
+ LHASH_COMP_FN(index_name))) {
+ BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n",
+ db->db->error, db->db->arg1, db->db->arg2);
+ return 0;
+ }
+ return 1;
+}
+
+int save_index(const char *dbfile, const char *suffix, CA_DB *db)
+{
+ char buf[3][BSIZE];
+ BIO *out;
+ int j;
+
+ j = strlen(dbfile) + strlen(suffix);
+ if (j + 6 >= BSIZE) {
+ BIO_printf(bio_err, "file name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
+#else
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
+#endif
+ out = BIO_new_file(buf[0], "w");
+ if (out == NULL) {
+ perror(dbfile);
+ BIO_printf(bio_err, "unable to open '%s'\n", dbfile);
+ goto err;
+ }
+ j = TXT_DB_write(out, db->db);
+ BIO_free(out);
+ if (j <= 0)
+ goto err;
+
+ out = BIO_new_file(buf[1], "w");
+ if (out == NULL) {
+ perror(buf[2]);
+ BIO_printf(bio_err, "unable to open '%s'\n", buf[2]);
+ goto err;
+ }
+ BIO_printf(out, "unique_subject = %s\n",
+ db->attributes.unique_subject ? "yes" : "no");
+ BIO_free(out);
+
+ return 1;
+ err:
+ return 0;
+}
+
+int rotate_index(const char *dbfile, const char *new_suffix,
+ const char *old_suffix)
+{
+ char buf[5][BSIZE];
+ int i, j;
+
+ i = strlen(dbfile) + strlen(old_suffix);
+ j = strlen(dbfile) + strlen(new_suffix);
+ if (i > j)
+ j = i;
+ if (j + 6 >= BSIZE) {
+ BIO_printf(bio_err, "file name too long\n");
+ goto err;
+ }
+#ifndef OPENSSL_SYS_VMS
+ j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
+ j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
+#else
+ j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
+ j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
+ j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
+ j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
+#endif
+ if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]);
+ perror("reason");
+ goto err;
+ }
+ if (rename(buf[0], dbfile) < 0) {
+ BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile);
+ perror("reason");
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
+#ifdef ENOTDIR
+ && errno != ENOTDIR
+#endif
+ ) {
+ BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]);
+ perror("reason");
+ rename(dbfile, buf[0]);
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ if (rename(buf[2], buf[4]) < 0) {
+ BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]);
+ perror("reason");
+ rename(buf[3], buf[4]);
+ rename(dbfile, buf[0]);
+ rename(buf[1], dbfile);
+ goto err;
+ }
+ return 1;
+ err:
+ return 0;
+}
+
+void free_index(CA_DB *db)
+{
+ if (db) {
+ TXT_DB_free(db->db);
+ OPENSSL_free(db->dbfname);
+ OPENSSL_free(db);
+ }
+}
+
+int parse_yesno(const char *str, int def)
+{
+ if (str) {
+ switch (*str) {
+ case 'f': /* false */
+ case 'F': /* FALSE */
+ case 'n': /* no */
+ case 'N': /* NO */
+ case '0': /* 0 */
+ return 0;
+ case 't': /* true */
+ case 'T': /* TRUE */
+ case 'y': /* yes */
+ case 'Y': /* YES */
+ case '1': /* 1 */
+ return 1;
+ }
+ }
+ return def;
+}
+
+/*
+ * name is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
+X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
+{
+ int nextismulti = 0;
+ char *work;
+ X509_NAME *n;
+
+ if (*cp++ != '/') {
+ BIO_printf(bio_err,
+ "name is expected to be in the format "
+ "/type0=value0/type1=value1/type2=... where characters may "
+ "be escaped by \\. This name is not in that format: '%s'\n",
+ --cp);
+ return NULL;
+ }
+
+ n = X509_NAME_new();
+ if (n == NULL)
+ return NULL;
+ work = OPENSSL_strdup(cp);
+ if (work == NULL)
+ goto err;
+
+ while (*cp) {
+ char *bp = work;
+ char *typestr = bp;
+ unsigned char *valstr;
+ int nid;
+ int ismulti = nextismulti;
+ nextismulti = 0;
+
+ /* Collect the type */
+ while (*cp && *cp != '=')
+ *bp++ = *cp++;
+ if (*cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: Hit end of string before finding the equals.\n",
+ opt_getprog());
+ goto err;
+ }
+ *bp++ = '\0';
+ ++cp;
+
+ /* Collect the value. */
+ valstr = (unsigned char *)bp;
+ for (; *cp && *cp != '/'; *bp++ = *cp++) {
+ if (canmulti && *cp == '+') {
+ nextismulti = 1;
+ break;
+ }
+ if (*cp == '\\' && *++cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: escape character at end of string\n",
+ opt_getprog());
+ goto err;
+ }
+ }
+ *bp++ = '\0';
+
+ /* If not at EOS (must be + or /), move forward. */
+ if (*cp)
+ ++cp;
+
+ /* Parse */
+ nid = OBJ_txt2nid(typestr);
+ if (nid == NID_undef) {
+ BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n",
+ opt_getprog(), typestr);
+ continue;
+ }
+ if (*valstr == '\0') {
+ BIO_printf(bio_err,
+ "%s: No value provided for Subject Attribute %s, skipped\n",
+ opt_getprog(), typestr);
+ continue;
+ }
+ if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
+ valstr, strlen((char *)valstr),
+ -1, ismulti ? -1 : 0))
+ goto err;
+ }
+
+ OPENSSL_free(work);
+ return n;
+
+ err:
+ X509_NAME_free(n);
+ OPENSSL_free(work);
+ return NULL;
+}
+
+/*
+ * Read whole contents of a BIO into an allocated memory buffer and return
+ * it.
+ */
+
+int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
+{
+ BIO *mem;
+ int len, ret;
+ unsigned char tbuf[1024];
+
+ mem = BIO_new(BIO_s_mem());
+ if (mem == NULL)
+ return -1;
+ for (;;) {
+ if ((maxlen != -1) && maxlen < 1024)
+ len = maxlen;
+ else
+ len = 1024;
+ len = BIO_read(in, tbuf, len);
+ if (len < 0) {
+ BIO_free(mem);
+ return -1;
+ }
+ if (len == 0)
+ break;
+ if (BIO_write(mem, tbuf, len) != len) {
+ BIO_free(mem);
+ return -1;
+ }
+ maxlen -= len;
+
+ if (maxlen == 0)
+ break;
+ }
+ ret = BIO_get_mem_data(mem, (char **)out);
+ BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
+ BIO_free(mem);
+ return ret;
+}
+
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
+{
+ int rv;
+ char *stmp, *vtmp = NULL;
+ stmp = OPENSSL_strdup(value);
+ if (!stmp)
+ return -1;
+ vtmp = strchr(stmp, ':');
+ if (vtmp) {
+ *vtmp = 0;
+ vtmp++;
+ }
+ rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
+ OPENSSL_free(stmp);
+ return rv;
+}
+
+static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
+{
+ X509_POLICY_NODE *node;
+ int i;
+
+ BIO_printf(bio_err, "%s Policies:", name);
+ if (nodes) {
+ BIO_puts(bio_err, "\n");
+ for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ X509_POLICY_NODE_print(bio_err, node, 2);
+ }
+ } else {
+ BIO_puts(bio_err, " <empty>\n");
+ }
+}
+
+void policies_print(X509_STORE_CTX *ctx)
+{
+ X509_POLICY_TREE *tree;
+ int explicit_policy;
+ tree = X509_STORE_CTX_get0_policy_tree(ctx);
+ explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
+
+ BIO_printf(bio_err, "Require explicit Policy: %s\n",
+ explicit_policy ? "True" : "False");
+
+ nodes_print("Authority", X509_policy_tree_get0_policies(tree));
+ nodes_print("User", X509_policy_tree_get0_user_policies(tree));
+}
+
+/*-
+ * next_protos_parse parses a comma separated list of strings into a string
+ * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
+ * outlen: (output) set to the length of the resulting buffer on success.
+ * err: (maybe NULL) on failure, an error message line is written to this BIO.
+ * in: a NUL terminated string like "abc,def,ghi"
+ *
+ * returns: a malloc'd buffer or NULL on failure.
+ */
+unsigned char *next_protos_parse(size_t *outlen, const char *in)
+{
+ size_t len;
+ unsigned char *out;
+ size_t i, start = 0;
+
+ len = strlen(in);
+ if (len >= 65535)
+ return NULL;
+
+ out = app_malloc(strlen(in) + 1, "NPN buffer");
+ for (i = 0; i <= len; ++i) {
+ if (i == len || in[i] == ',') {
+ if (i - start > 255) {
+ OPENSSL_free(out);
+ return NULL;
+ }
+ out[start] = (unsigned char)(i - start);
+ start = i + 1;
+ } else {
+ out[i + 1] = in[i];
+ }
+ }
+
+ *outlen = len + 1;
+ return out;
+}
+
+void print_cert_checks(BIO *bio, X509 *x,
+ const char *checkhost,
+ const char *checkemail, const char *checkip)
+{
+ if (x == NULL)
+ return;
+ if (checkhost) {
+ BIO_printf(bio, "Hostname %s does%s match certificate\n",
+ checkhost,
+ X509_check_host(x, checkhost, 0, 0, NULL) == 1
+ ? "" : " NOT");
+ }
+
+ if (checkemail) {
+ BIO_printf(bio, "Email %s does%s match certificate\n",
+ checkemail, X509_check_email(x, checkemail, 0, 0)
+ ? "" : " NOT");
+ }
+
+ if (checkip) {
+ BIO_printf(bio, "IP %s does%s match certificate\n",
+ checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
+ }
+}
+
+/* Get first http URL from a DIST_POINT structure */
+
+static const char *get_dp_url(DIST_POINT *dp)
+{
+ GENERAL_NAMES *gens;
+ GENERAL_NAME *gen;
+ int i, gtype;
+ ASN1_STRING *uri;
+ if (!dp->distpoint || dp->distpoint->type != 0)
+ return NULL;
+ gens = dp->distpoint->name.fullname;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ uri = GENERAL_NAME_get0_value(gen, &gtype);
+ if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
+ const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
+ if (strncmp(uptr, "http://", 7) == 0)
+ return uptr;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Look through a CRLDP structure and attempt to find an http URL to
+ * downloads a CRL from.
+ */
+
+static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
+{
+ int i;
+ const char *urlptr = NULL;
+ for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
+ DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
+ urlptr = get_dp_url(dp);
+ if (urlptr)
+ return load_crl(urlptr, FORMAT_HTTP);
+ }
+ return NULL;
+}
+
+/*
+ * Example of downloading CRLs from CRLDP: not usable for real world as it
+ * always downloads, doesn't support non-blocking I/O and doesn't cache
+ * anything.
+ */
+
+static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+ X509 *x;
+ STACK_OF(X509_CRL) *crls = NULL;
+ X509_CRL *crl;
+ STACK_OF(DIST_POINT) *crldp;
+
+ crls = sk_X509_CRL_new_null();
+ if (!crls)
+ return NULL;
+ x = X509_STORE_CTX_get_current_cert(ctx);
+ crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+ crl = load_crl_crldp(crldp);
+ sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+ if (!crl) {
+ sk_X509_CRL_free(crls);
+ return NULL;
+ }
+ sk_X509_CRL_push(crls, crl);
+ /* Try to download delta CRL */
+ crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
+ crl = load_crl_crldp(crldp);
+ sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+ if (crl)
+ sk_X509_CRL_push(crls, crl);
+ return crls;
+}
+
+void store_setup_crl_download(X509_STORE *st)
+{
+ X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
+}
+
+/*
+ * Platform-specific sections
+ */
+#if defined(_WIN32)
+# ifdef fileno
+# undef fileno
+# define fileno(a) (int)_fileno(a)
+# endif
+
+# include <windows.h>
+# include <tchar.h>
+
+static int WIN32_rename(const char *from, const char *to)
+{
+ TCHAR *tfrom = NULL, *tto;
+ DWORD err;
+ int ret = 0;
+
+ if (sizeof(TCHAR) == 1) {
+ tfrom = (TCHAR *)from;
+ tto = (TCHAR *)to;
+ } else { /* UNICODE path */
+
+ size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
+ tfrom = malloc(sizeof(*tfrom) * (flen + tlen));
+ if (tfrom == NULL)
+ goto err;
+ tto = tfrom + flen;
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
+# endif
+ for (i = 0; i < flen; i++)
+ tfrom[i] = (TCHAR)from[i];
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
+# endif
+ for (i = 0; i < tlen; i++)
+ tto[i] = (TCHAR)to[i];
+ }
+
+ if (MoveFile(tfrom, tto))
+ goto ok;
+ err = GetLastError();
+ if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
+ if (DeleteFile(tto) && MoveFile(tfrom, tto))
+ goto ok;
+ err = GetLastError();
+ }
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+ else if (err == ERROR_ACCESS_DENIED)
+ errno = EACCES;
+ else
+ errno = EINVAL; /* we could map more codes... */
+ err:
+ ret = -1;
+ ok:
+ if (tfrom != NULL && tfrom != (TCHAR *)from)
+ free(tfrom);
+ return ret;
+}
+#endif
+
+/* app_tminterval section */
+#if defined(_WIN32)
+double app_tminterval(int stop, int usertime)
+{
+ FILETIME now;
+ double ret = 0;
+ static ULARGE_INTEGER tmstart;
+ static int warning = 1;
+# ifdef _WIN32_WINNT
+ static HANDLE proc = NULL;
+
+ if (proc == NULL) {
+ if (check_winnt())
+ proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
+ GetCurrentProcessId());
+ if (proc == NULL)
+ proc = (HANDLE) - 1;
+ }
+
+ if (usertime && proc != (HANDLE) - 1) {
+ FILETIME junk;
+ GetProcessTimes(proc, &junk, &junk, &junk, &now);
+ } else
+# endif
+ {
+ SYSTEMTIME systime;
+
+ if (usertime && warning) {
+ BIO_printf(bio_err, "To get meaningful results, run "
+ "this program on idle system.\n");
+ warning = 0;
+ }
+ GetSystemTime(&systime);
+ SystemTimeToFileTime(&systime, &now);
+ }
+
+ if (stop == TM_START) {
+ tmstart.u.LowPart = now.dwLowDateTime;
+ tmstart.u.HighPart = now.dwHighDateTime;
+ } else {
+ ULARGE_INTEGER tmstop;
+
+ tmstop.u.LowPart = now.dwLowDateTime;
+ tmstop.u.HighPart = now.dwHighDateTime;
+
+ ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
+ }
+
+ return ret;
+}
+#elif defined(OPENSSL_SYSTEM_VXWORKS)
+# include <time.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+# ifdef CLOCK_REALTIME
+ static struct timespec tmstart;
+ struct timespec now;
+# else
+ static unsigned long tmstart;
+ unsigned long now;
+# endif
+ static int warning = 1;
+
+ if (usertime && warning) {
+ BIO_printf(bio_err, "To get meaningful results, run "
+ "this program on idle system.\n");
+ warning = 0;
+ }
+# ifdef CLOCK_REALTIME
+ clock_gettime(CLOCK_REALTIME, &now);
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = ((now.tv_sec + now.tv_nsec * 1e-9)
+ - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
+# else
+ now = tickGet();
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = (now - tmstart) / (double)sysClkRateGet();
+# endif
+ return ret;
+}
+
+#elif defined(OPENSSL_SYSTEM_VMS)
+# include <time.h>
+# include <times.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ static clock_t tmstart;
+ double ret = 0;
+ clock_t now;
+# ifdef __TMS
+ struct tms rus;
+
+ now = times(&rus);
+ if (usertime)
+ now = rus.tms_utime;
+# else
+ if (usertime)
+ now = clock(); /* sum of user and kernel times */
+ else {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK +
+ (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK)
+ );
+ }
+# endif
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = (now - tmstart) / (double)(CLK_TCK);
+
+ return ret;
+}
+
+#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
+# include <sys/times.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+ struct tms rus;
+ clock_t now = times(&rus);
+ static clock_t tmstart;
+
+ if (usertime)
+ now = rus.tms_utime;
+
+ if (stop == TM_START) {
+ tmstart = now;
+ } else {
+ long int tck = sysconf(_SC_CLK_TCK);
+ ret = (now - tmstart) / (double)tck;
+ }
+
+ return ret;
+}
+
+#else
+# include <sys/time.h>
+# include <sys/resource.h>
+
+double app_tminterval(int stop, int usertime)
+{
+ double ret = 0;
+ struct rusage rus;
+ struct timeval now;
+ static struct timeval tmstart;
+
+ if (usertime)
+ getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
+ else
+ gettimeofday(&now, NULL);
+
+ if (stop == TM_START)
+ tmstart = now;
+ else
+ ret = ((now.tv_sec + now.tv_usec * 1e-6)
+ - (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
+
+ return ret;
+}
+#endif
+
+int app_access(const char* name, int flag)
+{
+#ifdef _WIN32
+ return _access(name, flag);
+#else
+ return access(name, flag);
+#endif
+}
+
+/* app_isdir section */
+#ifdef _WIN32
+int app_isdir(const char *name)
+{
+ DWORD attr;
+# if defined(UNICODE) || defined(_UNICODE)
+ size_t i, len_0 = strlen(name) + 1;
+ WCHAR tempname[MAX_PATH];
+
+ if (len_0 > MAX_PATH)
+ return -1;
+
+# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
+ if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
+# endif
+ for (i = 0; i < len_0; i++)
+ tempname[i] = (WCHAR)name[i];
+
+ attr = GetFileAttributes(tempname);
+# else
+ attr = GetFileAttributes(name);
+# endif
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return -1;
+ return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
+}
+#else
+# include <sys/stat.h>
+# ifndef S_ISDIR
+# if defined(_S_IFMT) && defined(_S_IFDIR)
+# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR)
+# else
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+# endif
+# endif
+
+int app_isdir(const char *name)
+{
+# if defined(S_ISDIR)
+ struct stat st;
+
+ if (stat(name, &st) == 0)
+ return S_ISDIR(st.st_mode);
+ else
+ return -1;
+# else
+ return -1;
+# endif
+}
+#endif
+
+/* raw_read|write section */
+#if defined(__VMS)
+# include "vms_term_sock.h"
+static int stdin_sock = -1;
+
+static void close_stdin_sock(void)
+{
+ TerminalSocket (TERM_SOCK_DELETE, &stdin_sock);
+}
+
+int fileno_stdin(void)
+{
+ if (stdin_sock == -1) {
+ TerminalSocket(TERM_SOCK_CREATE, &stdin_sock);
+ atexit(close_stdin_sock);
+ }
+
+ return stdin_sock;
+}
+#else
+int fileno_stdin(void)
+{
+ return fileno(stdin);
+}
+#endif
+
+int fileno_stdout(void)
+{
+ return fileno(stdout);
+}
+
+#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
+int raw_read_stdin(void *buf, int siz)
+{
+ DWORD n;
+ if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
+ return n;
+ else
+ return -1;
+}
+#elif defined(__VMS)
+# include <sys/socket.h>
+
+int raw_read_stdin(void *buf, int siz)
+{
+ return recv(fileno_stdin(), buf, siz, 0);
+}
+#else
+int raw_read_stdin(void *buf, int siz)
+{
+ return read(fileno_stdin(), buf, siz);
+}
+#endif
+
+#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
+int raw_write_stdout(const void *buf, int siz)
+{
+ DWORD n;
+ if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
+ return n;
+ else
+ return -1;
+}
+#else
+int raw_write_stdout(const void *buf, int siz)
+{
+ return write(fileno_stdout(), buf, siz);
+}
+#endif
+
+/*
+ * Centralized handling if input and output files with format specification
+ * The format is meant to show what the input and output is supposed to be,
+ * and is therefore a show of intent more than anything else. However, it
+ * does impact behavior on some platform, such as differentiating between
+ * text and binary input/output on non-Unix platforms
+ */
+static int istext(int format)
+{
+ return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
+}
+
+BIO *dup_bio_in(int format)
+{
+ return BIO_new_fp(stdin,
+ BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
+}
+
+static BIO_METHOD *prefix_method = NULL;
+
+BIO *dup_bio_out(int format)
+{
+ BIO *b = BIO_new_fp(stdout,
+ BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
+ void *prefix = NULL;
+
+#ifdef OPENSSL_SYS_VMS
+ if (istext(format))
+ b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
+#endif
+
+ if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
+ if (prefix_method == NULL)
+ prefix_method = apps_bf_prefix();
+ b = BIO_push(BIO_new(prefix_method), b);
+ BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix);
+ }
+
+ return b;
+}
+
+BIO *dup_bio_err(int format)
+{
+ BIO *b = BIO_new_fp(stderr,
+ BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
+#ifdef OPENSSL_SYS_VMS
+ if (istext(format))
+ b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
+#endif
+ return b;
+}
+
+void destroy_prefix_method(void)
+{
+ BIO_meth_free(prefix_method);
+ prefix_method = NULL;
+}
+
+void unbuffer(FILE *fp)
+{
+/*
+ * On VMS, setbuf() will only take 32-bit pointers, and a compilation
+ * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
+ * However, we trust that the C RTL will never give us a FILE pointer
+ * above the first 4 GB of memory, so we simply turn off the warning
+ * temporarily.
+ */
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma environment save
+# pragma message disable maylosedata2
+#endif
+ setbuf(fp, NULL);
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+# pragma environment restore
+#endif
+}
+
+static const char *modestr(char mode, int format)
+{
+ OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w');
+
+ switch (mode) {
+ case 'a':
+ return istext(format) ? "a" : "ab";
+ case 'r':
+ return istext(format) ? "r" : "rb";
+ case 'w':
+ return istext(format) ? "w" : "wb";
+ }
+ /* The assert above should make sure we never reach this point */
+ return NULL;
+}
+
+static const char *modeverb(char mode)
+{
+ switch (mode) {
+ case 'a':
+ return "appending";
+ case 'r':
+ return "reading";
+ case 'w':
+ return "writing";
+ }
+ return "(doing something)";
+}
+
+/*
+ * Open a file for writing, owner-read-only.
+ */
+BIO *bio_open_owner(const char *filename, int format, int private)
+{
+ FILE *fp = NULL;
+ BIO *b = NULL;
+ int fd = -1, bflags, mode, textmode;
+
+ if (!private || filename == NULL || strcmp(filename, "-") == 0)
+ return bio_open_default(filename, 'w', format);
+
+ mode = O_WRONLY;
+#ifdef O_CREAT
+ mode |= O_CREAT;
+#endif
+#ifdef O_TRUNC
+ mode |= O_TRUNC;
+#endif
+ textmode = istext(format);
+ if (!textmode) {
+#ifdef O_BINARY
+ mode |= O_BINARY;
+#elif defined(_O_BINARY)
+ mode |= _O_BINARY;
+#endif
+ }
+
+#ifdef OPENSSL_SYS_VMS
+ /* VMS doesn't have O_BINARY, it just doesn't make sense. But,
+ * it still needs to know that we're going binary, or fdopen()
+ * will fail with "invalid argument"... so we tell VMS what the
+ * context is.
+ */
+ if (!textmode)
+ fd = open(filename, mode, 0600, "ctx=bin");
+ else
+#endif
+ fd = open(filename, mode, 0600);
+ if (fd < 0)
+ goto err;
+ fp = fdopen(fd, modestr('w', format));
+ if (fp == NULL)
+ goto err;
+ bflags = BIO_CLOSE;
+ if (textmode)
+ bflags |= BIO_FP_TEXT;
+ b = BIO_new_fp(fp, bflags);
+ if (b)
+ return b;
+
+ err:
+ BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n",
+ opt_getprog(), filename, strerror(errno));
+ ERR_print_errors(bio_err);
+ /* If we have fp, then fdopen took over fd, so don't close both. */
+ if (fp)
+ fclose(fp);
+ else if (fd >= 0)
+ close(fd);
+ return NULL;
+}
+
+static BIO *bio_open_default_(const char *filename, char mode, int format,
+ int quiet)
+{
+ BIO *ret;
+
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format);
+ if (quiet) {
+ ERR_clear_error();
+ return ret;
+ }
+ if (ret != NULL)
+ return ret;
+ BIO_printf(bio_err,
+ "Can't open %s, %s\n",
+ mode == 'r' ? "stdin" : "stdout", strerror(errno));
+ } else {
+ ret = BIO_new_file(filename, modestr(mode, format));
+ if (quiet) {
+ ERR_clear_error();
+ return ret;
+ }
+ if (ret != NULL)
+ return ret;
+ BIO_printf(bio_err,
+ "Can't open %s for %s, %s\n",
+ filename, modeverb(mode), strerror(errno));
+ }
+ ERR_print_errors(bio_err);
+ return NULL;
+}
+
+BIO *bio_open_default(const char *filename, char mode, int format)
+{
+ return bio_open_default_(filename, mode, format, 0);
+}
+
+BIO *bio_open_default_quiet(const char *filename, char mode, int format)
+{
+ return bio_open_default_(filename, mode, format, 1);
+}
+
+void wait_for_async(SSL *s)
+{
+ /* On Windows select only works for sockets, so we simply don't wait */
+#ifndef OPENSSL_SYS_WINDOWS
+ int width = 0;
+ fd_set asyncfds;
+ OSSL_ASYNC_FD *fds;
+ size_t numfds;
+ size_t i;
+
+ if (!SSL_get_all_async_fds(s, NULL, &numfds))
+ return;
+ if (numfds == 0)
+ return;
+ fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds");
+ if (!SSL_get_all_async_fds(s, fds, &numfds)) {
+ OPENSSL_free(fds);
+ return;
+ }
+
+ FD_ZERO(&asyncfds);
+ for (i = 0; i < numfds; i++) {
+ if (width <= (int)fds[i])
+ width = (int)fds[i] + 1;
+ openssl_fdset((int)fds[i], &asyncfds);
+ }
+ select(width, (void *)&asyncfds, NULL, NULL, NULL);
+ OPENSSL_free(fds);
+#endif
+}
+
+/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
+#if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void)
+{
+# if defined(OPENSSL_SYS_WINDOWS)
+ HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD events = 0;
+ INPUT_RECORD inputrec;
+ DWORD insize = 1;
+ BOOL peeked;
+
+ if (inhand == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
+ if (!peeked) {
+ /* Probably redirected input? _kbhit() does not work in this case */
+ if (!feof(stdin)) {
+ return 1;
+ }
+ return 0;
+ }
+# endif
+ return _kbhit();
+}
+#endif
+
+/* Corrupt a signature by modifying final byte */
+void corrupt_signature(const ASN1_STRING *signature)
+{
+ unsigned char *s = signature->data;
+ s[signature->length - 1] ^= 0x1;
+}
+
+int set_cert_times(X509 *x, const char *startdate, const char *enddate,
+ int days)
+{
+ if (startdate == NULL || strcmp(startdate, "today") == 0) {
+ if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
+ return 0;
+ } else {
+ if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
+ return 0;
+ }
+ if (enddate == NULL) {
+ if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
+ == NULL)
+ return 0;
+ } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
+ return 0;
+ }
+ return 1;
+}
+
+void make_uppercase(char *string)
+{
+ int i;
+
+ for (i = 0; string[i] != '\0'; i++)
+ string[i] = toupper((unsigned char)string[i]);
+}
diff --git a/freebsd/crypto/openssl/apps/apps.h b/freebsd/crypto/openssl/apps/apps.h
new file mode 100644
index 00000000..d9eb650e
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/apps.h
@@ -0,0 +1,634 @@
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_APPS_H
+# define HEADER_APPS_H
+
+# include "e_os.h" /* struct timeval for DTLS */
+# include "internal/nelem.h"
+# include <assert.h>
+
+# include <sys/types.h>
+# ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# include <fcntl.h>
+# endif
+
+# include <openssl/e_os2.h>
+# include <openssl/ossl_typ.h>
+# include <openssl/bio.h>
+# include <openssl/x509.h>
+# include <openssl/conf.h>
+# include <openssl/txt_db.h>
+# include <openssl/engine.h>
+# include <openssl/ocsp.h>
+# include <signal.h>
+
+# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE)
+# define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
+# else
+# define openssl_fdset(a,b) FD_SET(a, b)
+# endif
+
+/*
+ * quick macro when you need to pass an unsigned char instead of a char.
+ * this is true for some implementations of the is*() functions, for
+ * example.
+ */
+#define _UC(c) ((unsigned char)(c))
+
+void app_RAND_load_conf(CONF *c, const char *section);
+void app_RAND_write(void);
+
+extern char *default_config_file;
+extern BIO *bio_in;
+extern BIO *bio_out;
+extern BIO *bio_err;
+extern const unsigned char tls13_aes128gcmsha256_id[];
+extern const unsigned char tls13_aes256gcmsha384_id[];
+extern BIO_ADDR *ourpeer;
+
+BIO_METHOD *apps_bf_prefix(void);
+/*
+ * The control used to set the prefix with BIO_ctrl()
+ * We make it high enough so the chance of ever clashing with the BIO library
+ * remains unlikely for the foreseeable future and beyond.
+ */
+#define PREFIX_CTRL_SET_PREFIX (1 << 15)
+/*
+ * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we
+ * need to destroy at some point. When created internally, it's stored
+ * in an internal pointer which can be freed with the following function
+ */
+void destroy_prefix_method(void);
+
+BIO *dup_bio_in(int format);
+BIO *dup_bio_out(int format);
+BIO *dup_bio_err(int format);
+BIO *bio_open_owner(const char *filename, int format, int private);
+BIO *bio_open_default(const char *filename, char mode, int format);
+BIO *bio_open_default_quiet(const char *filename, char mode, int format);
+CONF *app_load_config_bio(BIO *in, const char *filename);
+CONF *app_load_config(const char *filename);
+CONF *app_load_config_quiet(const char *filename);
+int app_load_modules(const CONF *config);
+void unbuffer(FILE *fp);
+void wait_for_async(SSL *s);
+# if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void);
+# endif
+
+void corrupt_signature(const ASN1_STRING *signature);
+int set_cert_times(X509 *x, const char *startdate, const char *enddate,
+ int days);
+
+/*
+ * Common verification options.
+ */
+# define OPT_V_ENUM \
+ OPT_V__FIRST=2000, \
+ OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \
+ OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \
+ OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \
+ OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \
+ OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \
+ OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \
+ OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \
+ OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \
+ OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \
+ OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \
+ OPT_V__LAST
+
+# define OPT_V_OPTIONS \
+ { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \
+ { "purpose", OPT_V_PURPOSE, 's', \
+ "certificate chain purpose"}, \
+ { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \
+ { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \
+ "chain depth limit" }, \
+ { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \
+ "chain authentication security level" }, \
+ { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \
+ { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \
+ "expected peer hostname" }, \
+ { "verify_email", OPT_V_VERIFY_EMAIL, 's', \
+ "expected peer email" }, \
+ { "verify_ip", OPT_V_VERIFY_IP, 's', \
+ "expected peer IP address" }, \
+ { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \
+ "permit unhandled critical extensions"}, \
+ { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \
+ { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \
+ { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \
+ { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \
+ { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \
+ "set policy variable require-explicit-policy"}, \
+ { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \
+ "set policy variable inhibit-any-policy"}, \
+ { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \
+ "set policy variable inhibit-policy-mapping"}, \
+ { "x509_strict", OPT_V_X509_STRICT, '-', \
+ "disable certificate compatibility work-arounds"}, \
+ { "extended_crl", OPT_V_EXTENDED_CRL, '-', \
+ "enable extended CRL features"}, \
+ { "use_deltas", OPT_V_USE_DELTAS, '-', \
+ "use delta CRLs"}, \
+ { "policy_print", OPT_V_POLICY_PRINT, '-', \
+ "print policy processing diagnostics"}, \
+ { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \
+ "check root CA self-signatures"}, \
+ { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \
+ "search trust store first (default)" }, \
+ { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \
+ { "suiteB_128", OPT_V_SUITEB_128, '-', \
+ "Suite B 128-bit mode allowing 192-bit algorithms"}, \
+ { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \
+ { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \
+ "accept chains anchored by intermediate trust-store CAs"}, \
+ { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \
+ { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \
+ { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" }
+
+# define OPT_V_CASES \
+ OPT_V__FIRST: case OPT_V__LAST: break; \
+ case OPT_V_POLICY: \
+ case OPT_V_PURPOSE: \
+ case OPT_V_VERIFY_NAME: \
+ case OPT_V_VERIFY_DEPTH: \
+ case OPT_V_VERIFY_AUTH_LEVEL: \
+ case OPT_V_ATTIME: \
+ case OPT_V_VERIFY_HOSTNAME: \
+ case OPT_V_VERIFY_EMAIL: \
+ case OPT_V_VERIFY_IP: \
+ case OPT_V_IGNORE_CRITICAL: \
+ case OPT_V_ISSUER_CHECKS: \
+ case OPT_V_CRL_CHECK: \
+ case OPT_V_CRL_CHECK_ALL: \
+ case OPT_V_POLICY_CHECK: \
+ case OPT_V_EXPLICIT_POLICY: \
+ case OPT_V_INHIBIT_ANY: \
+ case OPT_V_INHIBIT_MAP: \
+ case OPT_V_X509_STRICT: \
+ case OPT_V_EXTENDED_CRL: \
+ case OPT_V_USE_DELTAS: \
+ case OPT_V_POLICY_PRINT: \
+ case OPT_V_CHECK_SS_SIG: \
+ case OPT_V_TRUSTED_FIRST: \
+ case OPT_V_SUITEB_128_ONLY: \
+ case OPT_V_SUITEB_128: \
+ case OPT_V_SUITEB_192: \
+ case OPT_V_PARTIAL_CHAIN: \
+ case OPT_V_NO_ALT_CHAINS: \
+ case OPT_V_NO_CHECK_TIME: \
+ case OPT_V_ALLOW_PROXY_CERTS
+
+/*
+ * Common "extended validation" options.
+ */
+# define OPT_X_ENUM \
+ OPT_X__FIRST=1000, \
+ OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \
+ OPT_X_CERTFORM, OPT_X_KEYFORM, \
+ OPT_X__LAST
+
+# define OPT_X_OPTIONS \
+ { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \
+ { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \
+ { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \
+ { "xchain_build", OPT_X_CHAIN_BUILD, '-', \
+ "build certificate chain for the extended certificates"}, \
+ { "xcertform", OPT_X_CERTFORM, 'F', \
+ "format of Extended certificate (PEM or DER) PEM default " }, \
+ { "xkeyform", OPT_X_KEYFORM, 'F', \
+ "format of Extended certificate's key (PEM or DER) PEM default"}
+
+# define OPT_X_CASES \
+ OPT_X__FIRST: case OPT_X__LAST: break; \
+ case OPT_X_KEY: \
+ case OPT_X_CERT: \
+ case OPT_X_CHAIN: \
+ case OPT_X_CHAIN_BUILD: \
+ case OPT_X_CERTFORM: \
+ case OPT_X_KEYFORM
+
+/*
+ * Common SSL options.
+ * Any changes here must be coordinated with ../ssl/ssl_conf.c
+ */
+# define OPT_S_ENUM \
+ OPT_S__FIRST=3000, \
+ OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \
+ OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \
+ OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \
+ OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \
+ OPT_S_PRIORITIZE_CHACHA, \
+ OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \
+ OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \
+ OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \
+ OPT_S_MINPROTO, OPT_S_MAXPROTO, \
+ OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST
+
+# define OPT_S_OPTIONS \
+ {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \
+ {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \
+ {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \
+ {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \
+ {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \
+ {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \
+ {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \
+ {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \
+ {"no_ticket", OPT_S_NOTICKET, '-', \
+ "Disable use of TLS session tickets"}, \
+ {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
+ {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
+ "Enable use of legacy renegotiation (dangerous)"}, \
+ {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
+ "Disable all renegotiation."}, \
+ {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
+ "Allow initial connection to servers that don't support RI"}, \
+ {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \
+ "Disallow session resumption on renegotiation"}, \
+ {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \
+ "Disallow initial connection to servers that don't support RI"}, \
+ {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \
+ "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \
+ {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \
+ "Prioritize ChaCha ciphers when preferred by clients"}, \
+ {"strict", OPT_S_STRICT, '-', \
+ "Enforce strict certificate checks as per TLS standard"}, \
+ {"sigalgs", OPT_S_SIGALGS, 's', \
+ "Signature algorithms to support (colon-separated list)" }, \
+ {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \
+ "Signature algorithms to support for client certificate" \
+ " authentication (colon-separated list)" }, \
+ {"groups", OPT_S_GROUPS, 's', \
+ "Groups to advertise (colon-separated list)" }, \
+ {"curves", OPT_S_CURVES, 's', \
+ "Groups to advertise (colon-separated list)" }, \
+ {"named_curve", OPT_S_NAMEDCURVE, 's', \
+ "Elliptic curve used for ECDHE (server-side only)" }, \
+ {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \
+ {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \
+ {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \
+ {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \
+ {"record_padding", OPT_S_RECORD_PADDING, 's', \
+ "Block size to pad TLS 1.3 records to."}, \
+ {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \
+ "Perform all sorts of protocol violations for testing purposes"}, \
+ {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \
+ "Disable TLSv1.3 middlebox compat mode" }
+
+# define OPT_S_CASES \
+ OPT_S__FIRST: case OPT_S__LAST: break; \
+ case OPT_S_NOSSL3: \
+ case OPT_S_NOTLS1: \
+ case OPT_S_NOTLS1_1: \
+ case OPT_S_NOTLS1_2: \
+ case OPT_S_NOTLS1_3: \
+ case OPT_S_BUGS: \
+ case OPT_S_NO_COMP: \
+ case OPT_S_COMP: \
+ case OPT_S_NOTICKET: \
+ case OPT_S_SERVERPREF: \
+ case OPT_S_LEGACYRENEG: \
+ case OPT_S_LEGACYCONN: \
+ case OPT_S_ONRESUMP: \
+ case OPT_S_NOLEGACYCONN: \
+ case OPT_S_ALLOW_NO_DHE_KEX: \
+ case OPT_S_PRIORITIZE_CHACHA: \
+ case OPT_S_STRICT: \
+ case OPT_S_SIGALGS: \
+ case OPT_S_CLIENTSIGALGS: \
+ case OPT_S_GROUPS: \
+ case OPT_S_CURVES: \
+ case OPT_S_NAMEDCURVE: \
+ case OPT_S_CIPHER: \
+ case OPT_S_CIPHERSUITES: \
+ case OPT_S_RECORD_PADDING: \
+ case OPT_S_NO_RENEGOTIATION: \
+ case OPT_S_MINPROTO: \
+ case OPT_S_MAXPROTO: \
+ case OPT_S_DEBUGBROKE: \
+ case OPT_S_NO_MIDDLEBOX
+
+#define IS_NO_PROT_FLAG(o) \
+ (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
+ || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3)
+
+/*
+ * Random state options.
+ */
+# define OPT_R_ENUM \
+ OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
+
+# define OPT_R_OPTIONS \
+ {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \
+ {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
+
+# define OPT_R_CASES \
+ OPT_R__FIRST: case OPT_R__LAST: break; \
+ case OPT_R_RAND: case OPT_R_WRITERAND
+
+/*
+ * Option parsing.
+ */
+extern const char OPT_HELP_STR[];
+extern const char OPT_MORE_STR[];
+typedef struct options_st {
+ const char *name;
+ int retval;
+ /*
+ * value type: - no value (also the value zero), n number, p positive
+ * number, u unsigned, l long, s string, < input file, > output file,
+ * f any format, F der/pem format, E der/pem/engine format identifier.
+ * l, n and u include zero; p does not.
+ */
+ int valtype;
+ const char *helpstr;
+} OPTIONS;
+
+/*
+ * A string/int pairing; widely use for option value lookup, hence the
+ * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use
+ * the "generic" name STRINT_PAIR.
+ */
+typedef struct string_int_pair_st {
+ const char *name;
+ int retval;
+} OPT_PAIR, STRINT_PAIR;
+
+/* Flags to pass into opt_format; see FORMAT_xxx, below. */
+# define OPT_FMT_PEMDER (1L << 1)
+# define OPT_FMT_PKCS12 (1L << 2)
+# define OPT_FMT_SMIME (1L << 3)
+# define OPT_FMT_ENGINE (1L << 4)
+# define OPT_FMT_MSBLOB (1L << 5)
+/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */
+# define OPT_FMT_NSS (1L << 7)
+# define OPT_FMT_TEXT (1L << 8)
+# define OPT_FMT_HTTP (1L << 9)
+# define OPT_FMT_PVK (1L << 10)
+# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE)
+# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME)
+# define OPT_FMT_ANY ( \
+ OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \
+ OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \
+ OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK)
+
+char *opt_progname(const char *argv0);
+char *opt_getprog(void);
+char *opt_init(int ac, char **av, const OPTIONS * o);
+int opt_next(void);
+int opt_format(const char *s, unsigned long flags, int *result);
+int opt_int(const char *arg, int *result);
+int opt_ulong(const char *arg, unsigned long *result);
+int opt_long(const char *arg, long *result);
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
+ defined(INTMAX_MAX) && defined(UINTMAX_MAX)
+int opt_imax(const char *arg, intmax_t *result);
+int opt_umax(const char *arg, uintmax_t *result);
+#else
+# define opt_imax opt_long
+# define opt_umax opt_ulong
+# define intmax_t long
+# define uintmax_t unsigned long
+#endif
+int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result);
+int opt_cipher(const char *name, const EVP_CIPHER **cipherp);
+int opt_md(const char *name, const EVP_MD **mdp);
+char *opt_arg(void);
+char *opt_flag(void);
+char *opt_unknown(void);
+char **opt_rest(void);
+int opt_num_rest(void);
+int opt_verify(int i, X509_VERIFY_PARAM *vpm);
+int opt_rand(int i);
+void opt_help(const OPTIONS * list);
+int opt_format_error(const char *s, unsigned long flags);
+
+typedef struct args_st {
+ int size;
+ int argc;
+ char **argv;
+} ARGS;
+
+/*
+ * VMS C only for now, implemented in vms_decc_init.c
+ * If other C compilers forget to terminate argv with NULL, this function
+ * can be re-used.
+ */
+char **copy_argv(int *argc, char *argv[]);
+/*
+ * Win32-specific argv initialization that splits OS-supplied UNICODE
+ * command line string to array of UTF8-encoded strings.
+ */
+void win32_utf8argv(int *argc, char **argv[]);
+
+
+# define PW_MIN_LENGTH 4
+typedef struct pw_cb_data {
+ const void *password;
+ const char *prompt_info;
+} PW_CB_DATA;
+
+int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data);
+
+int setup_ui_method(void);
+void destroy_ui_method(void);
+const UI_METHOD *get_ui_method(void);
+
+int chopup_args(ARGS *arg, char *buf);
+# ifdef HEADER_X509_H
+int dump_cert_text(BIO *out, X509 *x);
+void print_name(BIO *out, const char *title, X509_NAME *nm,
+ unsigned long lflags);
+# endif
+void print_bignum_var(BIO *, const BIGNUM *, const char*,
+ int, unsigned char *);
+void print_array(BIO *, const char *, int, const unsigned char *);
+int set_nameopt(const char *arg);
+unsigned long get_nameopt(void);
+int set_cert_ex(unsigned long *flags, const char *arg);
+int set_name_ex(unsigned long *flags, const char *arg);
+int set_ext_copy(int *copy_type, const char *arg);
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
+int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
+int add_oid_section(CONF *conf);
+X509 *load_cert(const char *file, int format, const char *cert_descrip);
+X509_CRL *load_crl(const char *infile, int format);
+EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *key_descrip);
+EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin,
+ const char *pass, ENGINE *e, const char *key_descrip);
+int load_certs(const char *file, STACK_OF(X509) **certs, int format,
+ const char *pass, const char *cert_descrip);
+int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
+ const char *pass, const char *cert_descrip);
+X509_STORE *setup_verify(const char *CAfile, const char *CApath,
+ int noCAfile, int noCApath);
+__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath, int noCAfile,
+ int noCApath);
+
+#ifndef OPENSSL_NO_CT
+
+/*
+ * Sets the file to load the Certificate Transparency log list from.
+ * If path is NULL, loads from the default file path.
+ * Returns 1 on success, 0 otherwise.
+ */
+__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
+
+#endif
+
+ENGINE *setup_engine(const char *engine, int debug);
+void release_engine(ENGINE *e);
+
+# ifndef OPENSSL_NO_OCSP
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
+ const char *host, const char *path,
+ const char *port, int use_ssl,
+ STACK_OF(CONF_VALUE) *headers,
+ int req_timeout);
+# endif
+
+/* Functions defined in ca.c and also used in ocsp.c */
+int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
+ ASN1_GENERALIZEDTIME **pinvtm, const char *str);
+
+# define DB_type 0
+# define DB_exp_date 1
+# define DB_rev_date 2
+# define DB_serial 3 /* index - unique */
+# define DB_file 4
+# define DB_name 5 /* index - unique when active and not
+ * disabled */
+# define DB_NUMBER 6
+
+# define DB_TYPE_REV 'R' /* Revoked */
+# define DB_TYPE_EXP 'E' /* Expired */
+# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */
+# define DB_TYPE_SUSP 'S' /* Suspended */
+
+typedef struct db_attr_st {
+ int unique_subject;
+} DB_ATTR;
+typedef struct ca_db_st {
+ DB_ATTR attributes;
+ TXT_DB *db;
+ char *dbfname;
+# ifndef OPENSSL_NO_POSIX_IO
+ struct stat dbst;
+# endif
+} CA_DB;
+
+void* app_malloc(int sz, const char *what);
+BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai);
+int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
+ ASN1_INTEGER **retai);
+int rotate_serial(const char *serialfile, const char *new_suffix,
+ const char *old_suffix);
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai);
+CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr);
+int index_index(CA_DB *db);
+int save_index(const char *dbfile, const char *suffix, CA_DB *db);
+int rotate_index(const char *dbfile, const char *new_suffix,
+ const char *old_suffix);
+void free_index(CA_DB *db);
+# define index_name_cmp_noconst(a, b) \
+ index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
+ (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
+int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
+int parse_yesno(const char *str, int def);
+
+X509_NAME *parse_name(const char *str, long chtype, int multirdn);
+void policies_print(X509_STORE_CTX *ctx);
+int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
+int init_gen_str(EVP_PKEY_CTX **pctx,
+ const char *algname, ENGINE *e, int do_param);
+int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts);
+
+extern char *psk_key;
+
+
+unsigned char *next_protos_parse(size_t *outlen, const char *in);
+
+void print_cert_checks(BIO *bio, X509 *x,
+ const char *checkhost,
+ const char *checkemail, const char *checkip);
+
+void store_setup_crl_download(X509_STORE *st);
+
+/* See OPT_FMT_xxx, above. */
+/* On some platforms, it's important to distinguish between text and binary
+ * files. On some, there might even be specific file formats for different
+ * contents. The FORMAT_xxx macros are meant to express an intent with the
+ * file being read or created.
+ */
+# define B_FORMAT_TEXT 0x8000
+# define FORMAT_UNDEF 0
+# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
+# define FORMAT_BINARY 2 /* Generic binary */
+# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */
+# define FORMAT_ASN1 4 /* ASN.1/DER */
+# define FORMAT_PEM (5 | B_FORMAT_TEXT)
+# define FORMAT_PKCS12 6
+# define FORMAT_SMIME (7 | B_FORMAT_TEXT)
+# define FORMAT_ENGINE 8 /* Not really a file format */
+# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */
+# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */
+# define FORMAT_MSBLOB 11 /* MS Key blob format */
+# define FORMAT_PVK 12 /* MS PVK file format */
+# define FORMAT_HTTP 13 /* Download using HTTP */
+# define FORMAT_NSS 14 /* NSS keylog format */
+
+# define EXT_COPY_NONE 0
+# define EXT_COPY_ADD 1
+# define EXT_COPY_ALL 2
+
+# define NETSCAPE_CERT_HDR "certificate"
+
+# define APP_PASS_LEN 1024
+
+/*
+ * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
+ * so that the first bit will never be one, so that the DER encoding
+ * rules won't force a leading octet.
+ */
+# define SERIAL_RAND_BITS 159
+
+int app_isdir(const char *);
+int app_access(const char *, int flag);
+int fileno_stdin(void);
+int fileno_stdout(void);
+int raw_read_stdin(void *, int);
+int raw_write_stdout(const void *, int);
+
+# define TM_START 0
+# define TM_STOP 1
+double app_tminterval(int stop, int usertime);
+
+void make_uppercase(char *string);
+
+typedef struct verify_options_st {
+ int depth;
+ int quiet;
+ int error;
+ int return_error;
+} VERIFY_CB_ARGS;
+
+extern VERIFY_CB_ARGS verify_args;
+
+#endif
diff --git a/freebsd/crypto/openssl/apps/asn1pars.c b/freebsd/crypto/openssl/apps/asn1pars.c
new file mode 100644
index 00000000..7861fe4d
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/asn1pars.c
@@ -0,0 +1,359 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/asn1t.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT,
+ OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT,
+ OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM,
+ OPT_ITEM
+} OPTION_CHOICE;
+
+const OPTIONS asn1parse_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"},
+ {"in", OPT_IN, '<', "input file"},
+ {"out", OPT_OUT, '>', "output file (output format is always DER)"},
+ {"i", OPT_INDENT, 0, "indents the output"},
+ {"noout", OPT_NOOUT, 0, "do not produce any output"},
+ {"offset", OPT_OFFSET, 'p', "offset into file"},
+ {"length", OPT_LENGTH, 'p', "length of section in file"},
+ {"oid", OPT_OID, '<', "file of extra oid definitions"},
+ {"dump", OPT_DUMP, 0, "unknown data in hex form"},
+ {"dlimit", OPT_DLIMIT, 'p',
+ "dump the first arg bytes of unknown data in hex form"},
+ {"strparse", OPT_STRPARSE, 'p',
+ "offset; a series of these can be used to 'dig'"},
+ {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
+ {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"},
+ {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"},
+ {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
+ {"strictpem", OPT_STRICTPEM, 0,
+ "do not attempt base64 decode outside PEM markers"},
+ {"item", OPT_ITEM, 's', "item to parse and print"},
+ {NULL}
+};
+
+static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf);
+
+int asn1parse_main(int argc, char **argv)
+{
+ ASN1_TYPE *at = NULL;
+ BIO *in = NULL, *b64 = NULL, *derout = NULL;
+ BUF_MEM *buf = NULL;
+ STACK_OF(OPENSSL_STRING) *osk = NULL;
+ char *genstr = NULL, *genconf = NULL;
+ char *infile = NULL, *oidfile = NULL, *derfile = NULL;
+ unsigned char *str = NULL;
+ char *name = NULL, *header = NULL, *prog;
+ const unsigned char *ctmpbuf;
+ int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;
+ int offset = 0, ret = 1, i, j;
+ long num, tmplen;
+ unsigned char *tmpbuf;
+ unsigned int length = 0;
+ OPTION_CHOICE o;
+ const ASN1_ITEM *it = NULL;
+
+ prog = opt_init(argc, argv, asn1parse_options);
+
+ if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
+ BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
+ goto end;
+ }
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(asn1parse_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ derfile = opt_arg();
+ break;
+ case OPT_INDENT:
+ indent = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_OID:
+ oidfile = opt_arg();
+ break;
+ case OPT_OFFSET:
+ offset = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_LENGTH:
+ length = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_DUMP:
+ dump = -1;
+ break;
+ case OPT_DLIMIT:
+ dump = strtol(opt_arg(), NULL, 0);
+ break;
+ case OPT_STRPARSE:
+ sk_OPENSSL_STRING_push(osk, opt_arg());
+ break;
+ case OPT_GENSTR:
+ genstr = opt_arg();
+ break;
+ case OPT_GENCONF:
+ genconf = opt_arg();
+ break;
+ case OPT_STRICTPEM:
+ strictpem = 1;
+ informat = FORMAT_PEM;
+ break;
+ case OPT_ITEM:
+ it = ASN1_ITEM_lookup(opt_arg());
+ if (it == NULL) {
+ size_t tmp;
+
+ BIO_printf(bio_err, "Unknown item name %s\n", opt_arg());
+ BIO_puts(bio_err, "Supported types:\n");
+ for (tmp = 0;; tmp++) {
+ it = ASN1_ITEM_get(tmp);
+ if (it == NULL)
+ break;
+ BIO_printf(bio_err, " %s\n", it->sname);
+ }
+ goto end;
+ }
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (oidfile != NULL) {
+ in = bio_open_default(oidfile, 'r', FORMAT_TEXT);
+ if (in == NULL)
+ goto end;
+ OBJ_create_objects(in);
+ BIO_free(in);
+ }
+
+ if ((in = bio_open_default(infile, 'r', informat)) == NULL)
+ goto end;
+
+ if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
+ goto end;
+
+ if (strictpem) {
+ if (PEM_read_bio(in, &name, &header, &str, &num) !=
+ 1) {
+ BIO_printf(bio_err, "Error reading PEM file\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+
+ if ((buf = BUF_MEM_new()) == NULL)
+ goto end;
+ if (!BUF_MEM_grow(buf, BUFSIZ * 8))
+ goto end; /* Pre-allocate :-) */
+
+ if (genstr || genconf) {
+ num = do_generate(genstr, genconf, buf);
+ if (num < 0) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+
+ if (informat == FORMAT_PEM) {
+ BIO *tmp;
+
+ if ((b64 = BIO_new(BIO_f_base64())) == NULL)
+ goto end;
+ BIO_push(b64, in);
+ tmp = in;
+ in = b64;
+ b64 = tmp;
+ }
+
+ num = 0;
+ for (;;) {
+ if (!BUF_MEM_grow(buf, num + BUFSIZ))
+ goto end;
+ i = BIO_read(in, &(buf->data[num]), BUFSIZ);
+ if (i <= 0)
+ break;
+ num += i;
+ }
+ }
+ str = (unsigned char *)buf->data;
+
+ }
+
+ /* If any structs to parse go through in sequence */
+
+ if (sk_OPENSSL_STRING_num(osk)) {
+ tmpbuf = str;
+ tmplen = num;
+ for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
+ ASN1_TYPE *atmp;
+ int typ;
+ j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);
+ if (j <= 0 || j >= tmplen) {
+ BIO_printf(bio_err, "'%s' is out of range\n",
+ sk_OPENSSL_STRING_value(osk, i));
+ continue;
+ }
+ tmpbuf += j;
+ tmplen -= j;
+ atmp = at;
+ ctmpbuf = tmpbuf;
+ at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
+ ASN1_TYPE_free(atmp);
+ if (!at) {
+ BIO_printf(bio_err, "Error parsing structure\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ typ = ASN1_TYPE_get(at);
+ if ((typ == V_ASN1_OBJECT)
+ || (typ == V_ASN1_BOOLEAN)
+ || (typ == V_ASN1_NULL)) {
+ BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ /* hmm... this is a little evil but it works */
+ tmpbuf = at->value.asn1_string->data;
+ tmplen = at->value.asn1_string->length;
+ }
+ str = tmpbuf;
+ num = tmplen;
+ }
+
+ if (offset < 0 || offset >= num) {
+ BIO_printf(bio_err, "Error: offset out of range\n");
+ goto end;
+ }
+
+ num -= offset;
+
+ if (length == 0 || length > (unsigned int)num)
+ length = (unsigned int)num;
+ if (derout != NULL) {
+ if (BIO_write(derout, str + offset, length) != (int)length) {
+ BIO_printf(bio_err, "Error writing output\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (!noout) {
+ const unsigned char *p = str + offset;
+
+ if (it != NULL) {
+ ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);
+ if (value == NULL) {
+ BIO_printf(bio_err, "Error parsing item %s\n", it->sname);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ASN1_item_print(bio_out, value, 0, it, NULL);
+ ASN1_item_free(value, it);
+ } else {
+ if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+ ret = 0;
+ end:
+ BIO_free(derout);
+ BIO_free(in);
+ BIO_free(b64);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ BUF_MEM_free(buf);
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ if (strictpem)
+ OPENSSL_free(str);
+ ASN1_TYPE_free(at);
+ sk_OPENSSL_STRING_free(osk);
+ return ret;
+}
+
+static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf)
+{
+ CONF *cnf = NULL;
+ int len;
+ unsigned char *p;
+ ASN1_TYPE *atyp = NULL;
+
+ if (genconf != NULL) {
+ if ((cnf = app_load_config(genconf)) == NULL)
+ goto err;
+ if (genstr == NULL)
+ genstr = NCONF_get_string(cnf, "default", "asn1");
+ if (genstr == NULL) {
+ BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf);
+ goto err;
+ }
+ }
+
+ atyp = ASN1_generate_nconf(genstr, cnf);
+ NCONF_free(cnf);
+ cnf = NULL;
+
+ if (atyp == NULL)
+ return -1;
+
+ len = i2d_ASN1_TYPE(atyp, NULL);
+
+ if (len <= 0)
+ goto err;
+
+ if (!BUF_MEM_grow(buf, len))
+ goto err;
+
+ p = (unsigned char *)buf->data;
+
+ i2d_ASN1_TYPE(atyp, &p);
+
+ ASN1_TYPE_free(atyp);
+ return len;
+
+ err:
+ NCONF_free(cnf);
+ ASN1_TYPE_free(atyp);
+ return -1;
+}
diff --git a/freebsd/crypto/openssl/apps/bf_prefix.c b/freebsd/crypto/openssl/apps/bf_prefix.c
new file mode 100644
index 00000000..eb7dd052
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/bf_prefix.c
@@ -0,0 +1,179 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/bio.h>
+#include "apps.h"
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten);
+static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread);
+static int prefix_puts(BIO *b, const char *str);
+static int prefix_gets(BIO *b, char *str, int size);
+static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2);
+static int prefix_create(BIO *b);
+static int prefix_destroy(BIO *b);
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
+
+static BIO_METHOD *prefix_meth = NULL;
+
+BIO_METHOD *apps_bf_prefix(void)
+{
+ if (prefix_meth == NULL) {
+ if ((prefix_meth =
+ BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL
+ || !BIO_meth_set_create(prefix_meth, prefix_create)
+ || !BIO_meth_set_destroy(prefix_meth, prefix_destroy)
+ || !BIO_meth_set_write_ex(prefix_meth, prefix_write)
+ || !BIO_meth_set_read_ex(prefix_meth, prefix_read)
+ || !BIO_meth_set_puts(prefix_meth, prefix_puts)
+ || !BIO_meth_set_gets(prefix_meth, prefix_gets)
+ || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl)
+ || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) {
+ BIO_meth_free(prefix_meth);
+ prefix_meth = NULL;
+ }
+ }
+ return prefix_meth;
+}
+
+typedef struct prefix_ctx_st {
+ char *prefix;
+ int linestart; /* flag to indicate we're at the line start */
+} PREFIX_CTX;
+
+static int prefix_create(BIO *b)
+{
+ PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ return 0;
+
+ ctx->prefix = NULL;
+ ctx->linestart = 1;
+ BIO_set_data(b, ctx);
+ BIO_set_init(b, 1);
+ return 1;
+}
+
+static int prefix_destroy(BIO *b)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ OPENSSL_free(ctx->prefix);
+ OPENSSL_free(ctx);
+ return 1;
+}
+
+static int prefix_read(BIO *b, char *in, size_t size, size_t *numread)
+{
+ return BIO_read_ex(BIO_next(b), in, size, numread);
+}
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ if (ctx == NULL)
+ return 0;
+
+ /* If no prefix is set or if it's empty, we've got nothing to do here */
+ if (ctx->prefix == NULL || *ctx->prefix == '\0') {
+ /* We do note if what comes next will be a new line, though */
+ if (outl > 0)
+ ctx->linestart = (out[outl-1] == '\n');
+ return BIO_write_ex(BIO_next(b), out, outl, numwritten);
+ }
+
+ *numwritten = 0;
+
+ while (outl > 0) {
+ size_t i;
+ char c;
+
+ /* If we know that we're at the start of the line, output the prefix */
+ if (ctx->linestart) {
+ size_t dontcare;
+
+ if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
+ &dontcare))
+ return 0;
+ ctx->linestart = 0;
+ }
+
+ /* Now, go look for the next LF, or the end of the string */
+ for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++)
+ continue;
+ if (c == '\n')
+ i++;
+
+ /* Output what we found so far */
+ while (i > 0) {
+ size_t num = 0;
+
+ if (!BIO_write_ex(BIO_next(b), out, i, &num))
+ return 0;
+ out += num;
+ outl -= num;
+ *numwritten += num;
+ i -= num;
+ }
+
+ /* If we found a LF, what follows is a new line, so take note */
+ if (c == '\n')
+ ctx->linestart = 1;
+ }
+
+ return 1;
+}
+
+static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case PREFIX_CTRL_SET_PREFIX:
+ {
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ if (ctx == NULL)
+ break;
+
+ OPENSSL_free(ctx->prefix);
+ ctx->prefix = OPENSSL_strdup((const char *)ptr);
+ ret = ctx->prefix != NULL;
+ }
+ break;
+ default:
+ if (BIO_next(b) != NULL)
+ ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+ return BIO_callback_ctrl(BIO_next(b), cmd, fp);
+}
+
+static int prefix_gets(BIO *b, char *buf, int size)
+{
+ return BIO_gets(BIO_next(b), buf, size);
+}
+
+static int prefix_puts(BIO *b, const char *str)
+{
+ return BIO_write(b, str, strlen(str));
+}
diff --git a/freebsd/crypto/openssl/apps/ca.c b/freebsd/crypto/openssl/apps/ca.c
new file mode 100644
index 00000000..c36e2fd5
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ca.c
@@ -0,0 +1,2608 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <openssl/conf.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/txt_db.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/objects.h>
+#include <openssl/ocsp.h>
+#include <openssl/pem.h>
+
+#ifndef W_OK
+# ifdef OPENSSL_SYS_VMS
+# include <unistd.h>
+# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
+# include <sys/file.h>
+# endif
+#endif
+
+#include "apps.h"
+#include "progs.h"
+
+#ifndef W_OK
+# define F_OK 0
+# define W_OK 2
+# define R_OK 4
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+#define BASE_SECTION "ca"
+
+#define ENV_DEFAULT_CA "default_ca"
+
+#define STRING_MASK "string_mask"
+#define UTF8_IN "utf8"
+
+#define ENV_NEW_CERTS_DIR "new_certs_dir"
+#define ENV_CERTIFICATE "certificate"
+#define ENV_SERIAL "serial"
+#define ENV_RAND_SERIAL "rand_serial"
+#define ENV_CRLNUMBER "crlnumber"
+#define ENV_PRIVATE_KEY "private_key"
+#define ENV_DEFAULT_DAYS "default_days"
+#define ENV_DEFAULT_STARTDATE "default_startdate"
+#define ENV_DEFAULT_ENDDATE "default_enddate"
+#define ENV_DEFAULT_CRL_DAYS "default_crl_days"
+#define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
+#define ENV_DEFAULT_MD "default_md"
+#define ENV_DEFAULT_EMAIL_DN "email_in_dn"
+#define ENV_PRESERVE "preserve"
+#define ENV_POLICY "policy"
+#define ENV_EXTENSIONS "x509_extensions"
+#define ENV_CRLEXT "crl_extensions"
+#define ENV_MSIE_HACK "msie_hack"
+#define ENV_NAMEOPT "name_opt"
+#define ENV_CERTOPT "cert_opt"
+#define ENV_EXTCOPY "copy_extensions"
+#define ENV_UNIQUE_SUBJECT "unique_subject"
+
+#define ENV_DATABASE "database"
+
+/* Additional revocation information types */
+typedef enum {
+ REV_VALID = -1, /* Valid (not-revoked) status */
+ REV_NONE = 0, /* No additional information */
+ REV_CRL_REASON = 1, /* Value is CRL reason code */
+ REV_HOLD = 2, /* Value is hold instruction */
+ REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */
+ REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */
+} REVINFO_TYPE;
+
+static char *lookup_conf(const CONF *conf, const char *group, const char *tag);
+
+static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate,
+ long days, int batch, const char *ext_sect, CONF *conf,
+ int verbose, unsigned long certopt, unsigned long nameopt,
+ int default_op, int ext_copy, int selfsign);
+static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate, long days, int batch, const char *ext_sect,
+ CONF *conf, int verbose, unsigned long certopt,
+ unsigned long nameopt, int default_op, int ext_copy);
+static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
+ X509 *x509, const EVP_MD *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate, long days, const char *ext_sect, CONF *conf,
+ int verbose, unsigned long certopt,
+ unsigned long nameopt, int default_op, int ext_copy);
+static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
+ const char *subj, unsigned long chtype, int multirdn,
+ int email_dn, const char *startdate, const char *enddate, long days,
+ int batch, int verbose, X509_REQ *req, const char *ext_sect,
+ CONF *conf, unsigned long certopt, unsigned long nameopt,
+ int default_op, int ext_copy, int selfsign);
+static int get_certificate_status(const char *ser_status, CA_DB *db);
+static int do_updatedb(CA_DB *db);
+static int check_time_format(const char *str);
+static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
+ const char *extval);
+static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg);
+static int make_revoked(X509_REVOKED *rev, const char *str);
+static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str);
+static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
+
+static CONF *extconf = NULL;
+static int preserve = 0;
+static int msie_hack = 0;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8,
+ OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE,
+ OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN,
+ OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR,
+ OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN,
+ OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
+ OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
+ OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
+ OPT_RAND_SERIAL,
+ OPT_R_ENUM,
+ /* Do not change the order here; see related case statements below */
+ OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
+} OPTION_CHOICE;
+
+const OPTIONS ca_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"},
+ {"config", OPT_CONFIG, 's', "A config file"},
+ {"name", OPT_NAME, 's', "The particular CA definition to use"},
+ {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"},
+ {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
+ {"create_serial", OPT_CREATE_SERIAL, '-',
+ "If reading serial fails, create a new random serial"},
+ {"rand_serial", OPT_RAND_SERIAL, '-',
+ "Always create a random serial; do not store it"},
+ {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
+ "Enable support for multivalued RDNs"},
+ {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
+ {"enddate", OPT_ENDDATE, 's',
+ "YYMMDDHHMMSSZ cert notAfter (overrides -days)"},
+ {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"},
+ {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
+ {"policy", OPT_POLICY, 's', "The CA 'policy' to support"},
+ {"keyfile", OPT_KEYFILE, 's', "Private key"},
+ {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"},
+ {"cert", OPT_CERT, '<', "The CA cert"},
+ {"selfsign", OPT_SELFSIGN, '-',
+ "Sign a cert with the key associated with it"},
+ {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"},
+ {"out", OPT_OUT, '>', "Where to put the output file(s)"},
+ {"outdir", OPT_OUTDIR, '/', "Where to put output cert"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"},
+ {"batch", OPT_BATCH, '-', "Don't ask questions"},
+ {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"},
+ {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"},
+ {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"},
+ {"msie_hack", OPT_MSIE_HACK, '-',
+ "msie modifications to handle all those universal strings"},
+ {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"},
+ {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"},
+ {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"},
+ {"infiles", OPT_INFILES, '-', "The last argument, requests to process"},
+ {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"},
+ {"spkac", OPT_SPKAC, '<',
+ "File contains DN and signed public key and challenge"},
+ {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
+ {"valid", OPT_VALID, 's',
+ "Add a Valid(not-revoked) DB entry about a cert (given in file)"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Extension section (override value in config file)"},
+ {"extfile", OPT_EXTFILE, '<',
+ "Configuration file with X509v3 extensions to add"},
+ {"status", OPT_STATUS, 's', "Shows cert status given the serial number"},
+ {"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"},
+ {"crlexts", OPT_CRLEXTS, 's',
+ "CRL extension section (override value in config file)"},
+ {"crl_reason", OPT_CRL_REASON, 's', "revocation reason"},
+ {"crl_hold", OPT_CRL_HOLD, 's',
+ "the hold instruction, an OID. Sets revocation reason to certificateHold"},
+ {"crl_compromise", OPT_CRL_COMPROMISE, 's',
+ "sets compromise time to val and the revocation reason to keyCompromise"},
+ {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's',
+ "sets compromise time to val and the revocation reason to CACompromise"},
+ OPT_R_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int ca_main(int argc, char **argv)
+{
+ CONF *conf = NULL;
+ ENGINE *e = NULL;
+ BIGNUM *crlnumber = NULL, *serial = NULL;
+ EVP_PKEY *pkey = NULL;
+ BIO *in = NULL, *out = NULL, *Sout = NULL;
+ ASN1_INTEGER *tmpser;
+ ASN1_TIME *tmptm;
+ CA_DB *db = NULL;
+ DB_ATTR db_attr;
+ STACK_OF(CONF_VALUE) *attribs = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+ STACK_OF(X509) *cert_sk = NULL;
+ X509_CRL *crl = NULL;
+ const EVP_MD *dgst = NULL;
+ char *configfile = default_config_file, *section = NULL;
+ char *md = NULL, *policy = NULL, *keyfile = NULL;
+ char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL;
+ const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL;
+ const char *extensions = NULL, *extfile = NULL, *passinarg = NULL;
+ char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
+ const char *serialfile = NULL, *subj = NULL;
+ char *prog, *startdate = NULL, *enddate = NULL;
+ char *dbfile = NULL, *f;
+ char new_cert[PATH_MAX];
+ char tmp[10 + 1] = "\0";
+ char *const *pp;
+ const char *p;
+ size_t outdirlen = 0;
+ int create_ser = 0, free_key = 0, total = 0, total_done = 0;
+ int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
+ int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
+ int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
+ int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret;
+ long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
+ unsigned long chtype = MBSTRING_ASC, certopt = 0;
+ X509 *x509 = NULL, *x509p = NULL, *x = NULL;
+ REVINFO_TYPE rev_type = REV_NONE;
+ X509_REVOKED *r = NULL;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, ca_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(ca_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ req = 1;
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_CONFIG:
+ configfile = opt_arg();
+ break;
+ case OPT_NAME:
+ section = opt_arg();
+ break;
+ case OPT_SUBJ:
+ subj = opt_arg();
+ /* preserve=1; */
+ break;
+ case OPT_UTF8:
+ chtype = MBSTRING_UTF8;
+ break;
+ case OPT_RAND_SERIAL:
+ rand_ser = 1;
+ break;
+ case OPT_CREATE_SERIAL:
+ create_ser = 1;
+ break;
+ case OPT_MULTIVALUE_RDN:
+ multirdn = 1;
+ break;
+ case OPT_STARTDATE:
+ startdate = opt_arg();
+ break;
+ case OPT_ENDDATE:
+ enddate = opt_arg();
+ break;
+ case OPT_DAYS:
+ days = atoi(opt_arg());
+ break;
+ case OPT_MD:
+ md = opt_arg();
+ break;
+ case OPT_POLICY:
+ policy = opt_arg();
+ break;
+ case OPT_KEYFILE:
+ keyfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
+ goto opthelp;
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_KEY:
+ key = opt_arg();
+ break;
+ case OPT_CERT:
+ certfile = opt_arg();
+ break;
+ case OPT_SELFSIGN:
+ selfsign = 1;
+ break;
+ case OPT_OUTDIR:
+ outdir = opt_arg();
+ break;
+ case OPT_SIGOPT:
+ if (sigopts == NULL)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
+ goto end;
+ break;
+ case OPT_NOTEXT:
+ notext = 1;
+ break;
+ case OPT_BATCH:
+ batch = 1;
+ break;
+ case OPT_PRESERVEDN:
+ preserve = 1;
+ break;
+ case OPT_NOEMAILDN:
+ email_dn = 0;
+ break;
+ case OPT_GENCRL:
+ gencrl = 1;
+ break;
+ case OPT_MSIE_HACK:
+ msie_hack = 1;
+ break;
+ case OPT_CRLDAYS:
+ crldays = atol(opt_arg());
+ break;
+ case OPT_CRLHOURS:
+ crlhours = atol(opt_arg());
+ break;
+ case OPT_CRLSEC:
+ crlsec = atol(opt_arg());
+ break;
+ case OPT_INFILES:
+ req = 1;
+ goto end_of_options;
+ case OPT_SS_CERT:
+ ss_cert_file = opt_arg();
+ req = 1;
+ break;
+ case OPT_SPKAC:
+ spkac_file = opt_arg();
+ req = 1;
+ break;
+ case OPT_REVOKE:
+ infile = opt_arg();
+ dorevoke = 1;
+ break;
+ case OPT_VALID:
+ infile = opt_arg();
+ dorevoke = 2;
+ break;
+ case OPT_EXTENSIONS:
+ extensions = opt_arg();
+ break;
+ case OPT_EXTFILE:
+ extfile = opt_arg();
+ break;
+ case OPT_STATUS:
+ ser_status = opt_arg();
+ break;
+ case OPT_UPDATEDB:
+ doupdatedb = 1;
+ break;
+ case OPT_CRLEXTS:
+ crl_ext = opt_arg();
+ break;
+ case OPT_CRL_REASON: /* := REV_CRL_REASON */
+ case OPT_CRL_HOLD:
+ case OPT_CRL_COMPROMISE:
+ case OPT_CRL_CA_COMPROMISE:
+ rev_arg = opt_arg();
+ rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+end_of_options:
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ BIO_printf(bio_err, "Using configuration from %s\n", configfile);
+
+ if ((conf = app_load_config(configfile)) == NULL)
+ goto end;
+ if (configfile != default_config_file && !app_load_modules(conf))
+ goto end;
+
+ /* Lets get the config section we are using */
+ if (section == NULL
+ && (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL)
+ goto end;
+
+ p = NCONF_get_string(conf, NULL, "oid_file");
+ if (p == NULL)
+ ERR_clear_error();
+ if (p != NULL) {
+ BIO *oid_bio = BIO_new_file(p, "r");
+
+ if (oid_bio == NULL) {
+ ERR_clear_error();
+ } else {
+ OBJ_create_objects(oid_bio);
+ BIO_free(oid_bio);
+ }
+ }
+ if (!add_oid_section(conf)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ app_RAND_load_conf(conf, BASE_SECTION);
+
+ f = NCONF_get_string(conf, section, STRING_MASK);
+ if (f == NULL)
+ ERR_clear_error();
+
+ if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) {
+ BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
+ goto end;
+ }
+
+ if (chtype != MBSTRING_UTF8) {
+ f = NCONF_get_string(conf, section, UTF8_IN);
+ if (f == NULL)
+ ERR_clear_error();
+ else if (strcmp(f, "yes") == 0)
+ chtype = MBSTRING_UTF8;
+ }
+
+ db_attr.unique_subject = 1;
+ p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
+ if (p != NULL)
+ db_attr.unique_subject = parse_yesno(p, 1);
+ else
+ ERR_clear_error();
+
+ /*****************************************************************/
+ /* report status of cert with serial number given on command line */
+ if (ser_status) {
+ dbfile = lookup_conf(conf, section, ENV_DATABASE);
+ if (dbfile == NULL)
+ goto end;
+
+ db = load_index(dbfile, &db_attr);
+ if (db == NULL)
+ goto end;
+
+ if (index_index(db) <= 0)
+ goto end;
+
+ if (get_certificate_status(ser_status, db) != 1)
+ BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status);
+ goto end;
+ }
+
+ /*****************************************************************/
+ /* we definitely need a private key, so let's get it */
+
+ if (keyfile == NULL
+ && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
+ goto end;
+
+ if (key == NULL) {
+ free_key = 1;
+ if (!app_passwd(passinarg, NULL, &key, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+ }
+ pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
+ if (key != NULL)
+ OPENSSL_cleanse(key, strlen(key));
+ if (pkey == NULL)
+ /* load_key() has already printed an appropriate message */
+ goto end;
+
+ /*****************************************************************/
+ /* we need a certificate */
+ if (!selfsign || spkac_file || ss_cert_file || gencrl) {
+ if (certfile == NULL
+ && (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL)
+ goto end;
+
+ x509 = load_cert(certfile, FORMAT_PEM, "CA certificate");
+ if (x509 == NULL)
+ goto end;
+
+ if (!X509_check_private_key(x509, pkey)) {
+ BIO_printf(bio_err,
+ "CA certificate and CA private key do not match\n");
+ goto end;
+ }
+ }
+ if (!selfsign)
+ x509p = x509;
+
+ f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE);
+ if (f == NULL)
+ ERR_clear_error();
+ if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
+ preserve = 1;
+ f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK);
+ if (f == NULL)
+ ERR_clear_error();
+ if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
+ msie_hack = 1;
+
+ f = NCONF_get_string(conf, section, ENV_NAMEOPT);
+
+ if (f != NULL) {
+ if (!set_nameopt(f)) {
+ BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
+ goto end;
+ }
+ default_op = 0;
+ }
+
+ f = NCONF_get_string(conf, section, ENV_CERTOPT);
+
+ if (f != NULL) {
+ if (!set_cert_ex(&certopt, f)) {
+ BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
+ goto end;
+ }
+ default_op = 0;
+ } else {
+ ERR_clear_error();
+ }
+
+ f = NCONF_get_string(conf, section, ENV_EXTCOPY);
+
+ if (f != NULL) {
+ if (!set_ext_copy(&ext_copy, f)) {
+ BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
+ goto end;
+ }
+ } else {
+ ERR_clear_error();
+ }
+
+ /*****************************************************************/
+ /* lookup where to write new certificates */
+ if ((outdir == NULL) && (req)) {
+
+ outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR);
+ if (outdir == NULL) {
+ BIO_printf(bio_err,
+ "there needs to be defined a directory for new certificate to be placed in\n");
+ goto end;
+ }
+#ifndef OPENSSL_SYS_VMS
+ /*
+ * outdir is a directory spec, but access() for VMS demands a
+ * filename. We could use the DEC C routine to convert the
+ * directory syntax to Unix, and give that to app_isdir,
+ * but for now the fopen will catch the error if it's not a
+ * directory
+ */
+ if (app_isdir(outdir) <= 0) {
+ BIO_printf(bio_err, "%s: %s is not a directory\n", prog, outdir);
+ perror(outdir);
+ goto end;
+ }
+#endif
+ }
+
+ /*****************************************************************/
+ /* we need to load the database file */
+ dbfile = lookup_conf(conf, section, ENV_DATABASE);
+ if (dbfile == NULL)
+ goto end;
+
+ db = load_index(dbfile, &db_attr);
+ if (db == NULL)
+ goto end;
+
+ /* Lets check some fields */
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+ if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) {
+ BIO_printf(bio_err,
+ "entry %d: not revoked yet, but has a revocation date\n",
+ i + 1);
+ goto end;
+ }
+ if ((pp[DB_type][0] == DB_TYPE_REV) &&
+ !make_revoked(NULL, pp[DB_rev_date])) {
+ BIO_printf(bio_err, " in entry %d\n", i + 1);
+ goto end;
+ }
+ if (!check_time_format((char *)pp[DB_exp_date])) {
+ BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1);
+ goto end;
+ }
+ p = pp[DB_serial];
+ j = strlen(p);
+ if (*p == '-') {
+ p++;
+ j--;
+ }
+ if ((j & 1) || (j < 2)) {
+ BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n",
+ i + 1, j);
+ goto end;
+ }
+ for ( ; *p; p++) {
+ if (!isxdigit(_UC(*p))) {
+ BIO_printf(bio_err,
+ "entry %d: bad char 0%o '%c' in serial number\n",
+ i + 1, *p, *p);
+ goto end;
+ }
+ }
+ }
+ if (verbose) {
+ TXT_DB_write(bio_out, db->db);
+ BIO_printf(bio_err, "%d entries loaded from the database\n",
+ sk_OPENSSL_PSTRING_num(db->db->data));
+ BIO_printf(bio_err, "generating index\n");
+ }
+
+ if (index_index(db) <= 0)
+ goto end;
+
+ /*****************************************************************/
+ /* Update the db file for expired certificates */
+ if (doupdatedb) {
+ if (verbose)
+ BIO_printf(bio_err, "Updating %s ...\n", dbfile);
+
+ i = do_updatedb(db);
+ if (i == -1) {
+ BIO_printf(bio_err, "Malloc failure\n");
+ goto end;
+ } else if (i == 0) {
+ if (verbose)
+ BIO_printf(bio_err, "No entries found to mark expired\n");
+ } else {
+ if (!save_index(dbfile, "new", db))
+ goto end;
+
+ if (!rotate_index(dbfile, "new", "old"))
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "Done. %d entries marked as expired\n", i);
+ }
+ }
+
+ /*****************************************************************/
+ /* Read extensions config file */
+ if (extfile) {
+ if ((extconf = app_load_config(extfile)) == NULL) {
+ ret = 1;
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Successfully loaded extensions file %s\n",
+ extfile);
+
+ /* We can have sections in the ext file */
+ if (extensions == NULL) {
+ extensions = NCONF_get_string(extconf, "default", "extensions");
+ if (extensions == NULL)
+ extensions = "default";
+ }
+ }
+
+ /*****************************************************************/
+ if (req || gencrl) {
+ if (spkac_file != NULL) {
+ output_der = 1;
+ batch = 1;
+ }
+ }
+
+ def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid);
+ /*
+ * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is
+ * mandatory for this algorithm.
+ */
+ if (def_ret == 2 && def_nid == NID_undef) {
+ /* The signing algorithm requires there to be no digest */
+ dgst = EVP_md_null();
+ } else if (md == NULL
+ && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) {
+ goto end;
+ } else {
+ if (strcmp(md, "default") == 0) {
+ if (def_ret <= 0) {
+ BIO_puts(bio_err, "no default digest\n");
+ goto end;
+ }
+ md = (char *)OBJ_nid2sn(def_nid);
+ }
+
+ if (!opt_md(md, &dgst))
+ goto end;
+ }
+
+ if (req) {
+ if (email_dn == 1) {
+ char *tmp_email_dn = NULL;
+
+ tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN);
+ if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0)
+ email_dn = 0;
+ }
+ if (verbose)
+ BIO_printf(bio_err, "message digest is %s\n",
+ OBJ_nid2ln(EVP_MD_type(dgst)));
+ if (policy == NULL
+ && (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL)
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "policy is %s\n", policy);
+
+ if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) {
+ rand_ser = 1;
+ } else {
+ serialfile = lookup_conf(conf, section, ENV_SERIAL);
+ if (serialfile == NULL)
+ goto end;
+ }
+
+ if (extconf == NULL) {
+ /*
+ * no '-extfile' option, so we look for extensions in the main
+ * configuration file
+ */
+ if (extensions == NULL) {
+ extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
+ if (extensions == NULL)
+ ERR_clear_error();
+ }
+ if (extensions != NULL) {
+ /* Check syntax of file */
+ X509V3_CTX ctx;
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, conf);
+ if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
+ BIO_printf(bio_err,
+ "Error Loading extension section %s\n",
+ extensions);
+ ret = 1;
+ goto end;
+ }
+ }
+ }
+
+ if (startdate == NULL) {
+ startdate = NCONF_get_string(conf, section, ENV_DEFAULT_STARTDATE);
+ if (startdate == NULL)
+ ERR_clear_error();
+ }
+ if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) {
+ BIO_printf(bio_err,
+ "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
+ goto end;
+ }
+ if (startdate == NULL)
+ startdate = "today";
+
+ if (enddate == NULL) {
+ enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE);
+ if (enddate == NULL)
+ ERR_clear_error();
+ }
+ if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) {
+ BIO_printf(bio_err,
+ "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
+ goto end;
+ }
+
+ if (days == 0) {
+ if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
+ days = 0;
+ }
+ if (enddate == NULL && days == 0) {
+ BIO_printf(bio_err, "cannot lookup how many days to certify for\n");
+ goto end;
+ }
+
+ if (rand_ser) {
+ if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) {
+ BIO_printf(bio_err, "error generating serial number\n");
+ goto end;
+ }
+ } else {
+ if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
+ BIO_printf(bio_err, "error while loading serial number\n");
+ goto end;
+ }
+ if (verbose) {
+ if (BN_is_zero(serial)) {
+ BIO_printf(bio_err, "next serial number is 00\n");
+ } else {
+ if ((f = BN_bn2hex(serial)) == NULL)
+ goto end;
+ BIO_printf(bio_err, "next serial number is %s\n", f);
+ OPENSSL_free(f);
+ }
+ }
+ }
+
+ if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
+ BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
+ goto end;
+ }
+
+ if ((cert_sk = sk_X509_new_null()) == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ if (spkac_file != NULL) {
+ total++;
+ j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts,
+ attribs, db, serial, subj, chtype, multirdn,
+ email_dn, startdate, enddate, days, extensions,
+ conf, verbose, certopt, get_nameopt(), default_op,
+ ext_copy);
+ if (j < 0)
+ goto end;
+ if (j > 0) {
+ total_done++;
+ BIO_printf(bio_err, "\n");
+ if (!BN_add_word(serial, 1))
+ goto end;
+ if (!sk_X509_push(cert_sk, x)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ }
+ }
+ if (ss_cert_file != NULL) {
+ total++;
+ j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
+ attribs,
+ db, serial, subj, chtype, multirdn, email_dn,
+ startdate, enddate, days, batch, extensions,
+ conf, verbose, certopt, get_nameopt(), default_op,
+ ext_copy);
+ if (j < 0)
+ goto end;
+ if (j > 0) {
+ total_done++;
+ BIO_printf(bio_err, "\n");
+ if (!BN_add_word(serial, 1))
+ goto end;
+ if (!sk_X509_push(cert_sk, x)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ }
+ }
+ if (infile != NULL) {
+ total++;
+ j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
+ serial, subj, chtype, multirdn, email_dn, startdate,
+ enddate, days, batch, extensions, conf, verbose,
+ certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ if (j < 0)
+ goto end;
+ if (j > 0) {
+ total_done++;
+ BIO_printf(bio_err, "\n");
+ if (!BN_add_word(serial, 1))
+ goto end;
+ if (!sk_X509_push(cert_sk, x)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ }
+ }
+ for (i = 0; i < argc; i++) {
+ total++;
+ j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
+ serial, subj, chtype, multirdn, email_dn, startdate,
+ enddate, days, batch, extensions, conf, verbose,
+ certopt, get_nameopt(), default_op, ext_copy, selfsign);
+ if (j < 0)
+ goto end;
+ if (j > 0) {
+ total_done++;
+ BIO_printf(bio_err, "\n");
+ if (!BN_add_word(serial, 1)) {
+ X509_free(x);
+ goto end;
+ }
+ if (!sk_X509_push(cert_sk, x)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ X509_free(x);
+ goto end;
+ }
+ }
+ }
+ /*
+ * we have a stack of newly certified certificates and a data base
+ * and serial number that need updating
+ */
+
+ if (sk_X509_num(cert_sk) > 0) {
+ if (!batch) {
+ BIO_printf(bio_err,
+ "\n%d out of %d certificate requests certified, commit? [y/n]",
+ total_done, total);
+ (void)BIO_flush(bio_err);
+ tmp[0] = '\0';
+ if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
+ BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n");
+ ret = 0;
+ goto end;
+ }
+ if (tmp[0] != 'y' && tmp[0] != 'Y') {
+ BIO_printf(bio_err, "CERTIFICATION CANCELED\n");
+ ret = 0;
+ goto end;
+ }
+ }
+
+ BIO_printf(bio_err, "Write out database with %d new entries\n",
+ sk_X509_num(cert_sk));
+
+ if (serialfile != NULL
+ && !save_serial(serialfile, "new", serial, NULL))
+ goto end;
+
+ if (!save_index(dbfile, "new", db))
+ goto end;
+ }
+
+ outdirlen = OPENSSL_strlcpy(new_cert, outdir, sizeof(new_cert));
+#ifndef OPENSSL_SYS_VMS
+ outdirlen = OPENSSL_strlcat(new_cert, "/", sizeof(new_cert));
+#endif
+
+ if (verbose)
+ BIO_printf(bio_err, "writing new certificates\n");
+
+ for (i = 0; i < sk_X509_num(cert_sk); i++) {
+ BIO *Cout = NULL;
+ X509 *xi = sk_X509_value(cert_sk, i);
+ ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi);
+ const unsigned char *psn = ASN1_STRING_get0_data(serialNumber);
+ const int snl = ASN1_STRING_length(serialNumber);
+ const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem");
+ char *n = new_cert + outdirlen;
+
+ if (outdirlen + filen_len > PATH_MAX) {
+ BIO_printf(bio_err, "certificate file name too long\n");
+ goto end;
+ }
+
+ if (snl > 0) {
+ static const char HEX_DIGITS[] = "0123456789ABCDEF";
+
+ for (j = 0; j < snl; j++, psn++) {
+ *n++ = HEX_DIGITS[*psn >> 4];
+ *n++ = HEX_DIGITS[*psn & 0x0F];
+ }
+ } else {
+ *(n++) = '0';
+ *(n++) = '0';
+ }
+ *(n++) = '.';
+ *(n++) = 'p';
+ *(n++) = 'e';
+ *(n++) = 'm';
+ *n = '\0'; /* closing new_cert */
+ if (verbose)
+ BIO_printf(bio_err, "writing %s\n", new_cert);
+
+ Sout = bio_open_default(outfile, 'w',
+ output_der ? FORMAT_ASN1 : FORMAT_TEXT);
+ if (Sout == NULL)
+ goto end;
+
+ Cout = BIO_new_file(new_cert, "w");
+ if (Cout == NULL) {
+ perror(new_cert);
+ goto end;
+ }
+ write_new_certificate(Cout, xi, 0, notext);
+ write_new_certificate(Sout, xi, output_der, notext);
+ BIO_free_all(Cout);
+ BIO_free_all(Sout);
+ Sout = NULL;
+ }
+
+ if (sk_X509_num(cert_sk)) {
+ /* Rename the database and the serial file */
+ if (serialfile != NULL
+ && !rotate_serial(serialfile, "new", "old"))
+ goto end;
+
+ if (!rotate_index(dbfile, "new", "old"))
+ goto end;
+
+ BIO_printf(bio_err, "Data Base Updated\n");
+ }
+ }
+
+ /*****************************************************************/
+ if (gencrl) {
+ int crl_v2 = 0;
+ if (crl_ext == NULL) {
+ crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
+ if (crl_ext == NULL)
+ ERR_clear_error();
+ }
+ if (crl_ext != NULL) {
+ /* Check syntax of file */
+ X509V3_CTX ctx;
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, conf);
+ if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
+ BIO_printf(bio_err,
+ "Error Loading CRL extension section %s\n", crl_ext);
+ ret = 1;
+ goto end;
+ }
+ }
+
+ if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER))
+ != NULL)
+ if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) {
+ BIO_printf(bio_err, "error while loading CRL number\n");
+ goto end;
+ }
+
+ if (!crldays && !crlhours && !crlsec) {
+ if (!NCONF_get_number(conf, section,
+ ENV_DEFAULT_CRL_DAYS, &crldays))
+ crldays = 0;
+ if (!NCONF_get_number(conf, section,
+ ENV_DEFAULT_CRL_HOURS, &crlhours))
+ crlhours = 0;
+ ERR_clear_error();
+ }
+ if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
+ BIO_printf(bio_err,
+ "cannot lookup how long until the next CRL is issued\n");
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "making CRL\n");
+ if ((crl = X509_CRL_new()) == NULL)
+ goto end;
+ if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
+ goto end;
+
+ tmptm = ASN1_TIME_new();
+ if (tmptm == NULL
+ || X509_gmtime_adj(tmptm, 0) == NULL
+ || !X509_CRL_set1_lastUpdate(crl, tmptm)
+ || X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec,
+ NULL) == NULL) {
+ BIO_puts(bio_err, "error setting CRL nextUpdate\n");
+ ASN1_TIME_free(tmptm);
+ goto end;
+ }
+ X509_CRL_set1_nextUpdate(crl, tmptm);
+
+ ASN1_TIME_free(tmptm);
+
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+ if (pp[DB_type][0] == DB_TYPE_REV) {
+ if ((r = X509_REVOKED_new()) == NULL)
+ goto end;
+ j = make_revoked(r, pp[DB_rev_date]);
+ if (!j)
+ goto end;
+ if (j == 2)
+ crl_v2 = 1;
+ if (!BN_hex2bn(&serial, pp[DB_serial]))
+ goto end;
+ tmpser = BN_to_ASN1_INTEGER(serial, NULL);
+ BN_free(serial);
+ serial = NULL;
+ if (!tmpser)
+ goto end;
+ X509_REVOKED_set_serialNumber(r, tmpser);
+ ASN1_INTEGER_free(tmpser);
+ X509_CRL_add0_revoked(crl, r);
+ }
+ }
+
+ /*
+ * sort the data so it will be written in serial number order
+ */
+ X509_CRL_sort(crl);
+
+ /* we now have a CRL */
+ if (verbose)
+ BIO_printf(bio_err, "signing CRL\n");
+
+ /* Add any extensions asked for */
+
+ if (crl_ext != NULL || crlnumberfile != NULL) {
+ X509V3_CTX crlctx;
+ X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
+ X509V3_set_nconf(&crlctx, conf);
+
+ if (crl_ext != NULL)
+ if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
+ goto end;
+ if (crlnumberfile != NULL) {
+ tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
+ if (!tmpser)
+ goto end;
+ X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
+ ASN1_INTEGER_free(tmpser);
+ crl_v2 = 1;
+ if (!BN_add_word(crlnumber, 1))
+ goto end;
+ }
+ }
+ if (crl_ext != NULL || crl_v2) {
+ if (!X509_CRL_set_version(crl, 1))
+ goto end; /* version 2 CRL */
+ }
+
+ /* we have a CRL number that need updating */
+ if (crlnumberfile != NULL
+ && !save_serial(crlnumberfile, "new", crlnumber, NULL))
+ goto end;
+
+ BN_free(crlnumber);
+ crlnumber = NULL;
+
+ if (!do_X509_CRL_sign(crl, pkey, dgst, sigopts))
+ goto end;
+
+ Sout = bio_open_default(outfile, 'w',
+ output_der ? FORMAT_ASN1 : FORMAT_TEXT);
+ if (Sout == NULL)
+ goto end;
+
+ PEM_write_bio_X509_CRL(Sout, crl);
+
+ /* Rename the crlnumber file */
+ if (crlnumberfile != NULL
+ && !rotate_serial(crlnumberfile, "new", "old"))
+ goto end;
+
+ }
+ /*****************************************************************/
+ if (dorevoke) {
+ if (infile == NULL) {
+ BIO_printf(bio_err, "no input files\n");
+ goto end;
+ } else {
+ X509 *revcert;
+ revcert = load_cert(infile, FORMAT_PEM, infile);
+ if (revcert == NULL)
+ goto end;
+ if (dorevoke == 2)
+ rev_type = REV_VALID;
+ j = do_revoke(revcert, db, rev_type, rev_arg);
+ if (j <= 0)
+ goto end;
+ X509_free(revcert);
+
+ if (!save_index(dbfile, "new", db))
+ goto end;
+
+ if (!rotate_index(dbfile, "new", "old"))
+ goto end;
+
+ BIO_printf(bio_err, "Data Base Updated\n");
+ }
+ }
+ ret = 0;
+
+ end:
+ if (ret)
+ ERR_print_errors(bio_err);
+ BIO_free_all(Sout);
+ BIO_free_all(out);
+ BIO_free_all(in);
+ sk_X509_pop_free(cert_sk, X509_free);
+
+ if (free_key)
+ OPENSSL_free(key);
+ BN_free(serial);
+ BN_free(crlnumber);
+ free_index(db);
+ sk_OPENSSL_STRING_free(sigopts);
+ EVP_PKEY_free(pkey);
+ X509_free(x509);
+ X509_CRL_free(crl);
+ NCONF_free(conf);
+ NCONF_free(extconf);
+ release_engine(e);
+ return ret;
+}
+
+static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
+{
+ char *entry = NCONF_get_string(conf, section, tag);
+ if (entry == NULL)
+ BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag);
+ return entry;
+}
+
+static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate,
+ long days, int batch, const char *ext_sect, CONF *lconf,
+ int verbose, unsigned long certopt, unsigned long nameopt,
+ int default_op, int ext_copy, int selfsign)
+{
+ X509_REQ *req = NULL;
+ BIO *in = NULL;
+ EVP_PKEY *pktmp = NULL;
+ int ok = -1, i;
+
+ in = BIO_new_file(infile, "r");
+ if (in == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
+ BIO_printf(bio_err, "Error reading certificate request in %s\n",
+ infile);
+ goto end;
+ }
+ if (verbose)
+ X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT);
+
+ BIO_printf(bio_err, "Check that the request matches the signature\n");
+
+ if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
+ BIO_printf(bio_err,
+ "Certificate request and CA private key do not match\n");
+ ok = 0;
+ goto end;
+ }
+ if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) {
+ BIO_printf(bio_err, "error unpacking public key\n");
+ goto end;
+ }
+ i = X509_REQ_verify(req, pktmp);
+ pktmp = NULL;
+ if (i < 0) {
+ ok = 0;
+ BIO_printf(bio_err, "Signature verification problems....\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (i == 0) {
+ ok = 0;
+ BIO_printf(bio_err,
+ "Signature did not match the certificate request\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Signature ok\n");
+ }
+
+ ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
+ chtype, multirdn, email_dn, startdate, enddate, days, batch,
+ verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
+ ext_copy, selfsign);
+
+ end:
+ X509_REQ_free(req);
+ BIO_free(in);
+ return ok;
+}
+
+static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate, long days, int batch, const char *ext_sect,
+ CONF *lconf, int verbose, unsigned long certopt,
+ unsigned long nameopt, int default_op, int ext_copy)
+{
+ X509 *req = NULL;
+ X509_REQ *rreq = NULL;
+ EVP_PKEY *pktmp = NULL;
+ int ok = -1, i;
+
+ if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL)
+ goto end;
+ if (verbose)
+ X509_print(bio_err, req);
+
+ BIO_printf(bio_err, "Check that the request matches the signature\n");
+
+ if ((pktmp = X509_get0_pubkey(req)) == NULL) {
+ BIO_printf(bio_err, "error unpacking public key\n");
+ goto end;
+ }
+ i = X509_verify(req, pktmp);
+ if (i < 0) {
+ ok = 0;
+ BIO_printf(bio_err, "Signature verification problems....\n");
+ goto end;
+ }
+ if (i == 0) {
+ ok = 0;
+ BIO_printf(bio_err, "Signature did not match the certificate\n");
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Signature ok\n");
+ }
+
+ if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL)
+ goto end;
+
+ ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
+ chtype, multirdn, email_dn, startdate, enddate, days, batch,
+ verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op,
+ ext_copy, 0);
+
+ end:
+ X509_REQ_free(rreq);
+ X509_free(req);
+ return ok;
+}
+
+static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
+ const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
+ const char *subj, unsigned long chtype, int multirdn,
+ int email_dn, const char *startdate, const char *enddate, long days,
+ int batch, int verbose, X509_REQ *req, const char *ext_sect,
+ CONF *lconf, unsigned long certopt, unsigned long nameopt,
+ int default_op, int ext_copy, int selfsign)
+{
+ X509_NAME *name = NULL, *CAname = NULL, *subject = NULL;
+ const ASN1_TIME *tm;
+ ASN1_STRING *str, *str2;
+ ASN1_OBJECT *obj;
+ X509 *ret = NULL;
+ X509_NAME_ENTRY *ne, *tne;
+ EVP_PKEY *pktmp;
+ int ok = -1, i, j, last, nid;
+ const char *p;
+ CONF_VALUE *cv;
+ OPENSSL_STRING row[DB_NUMBER];
+ OPENSSL_STRING *irow = NULL;
+ OPENSSL_STRING *rrow = NULL;
+ char buf[25];
+
+ for (i = 0; i < DB_NUMBER; i++)
+ row[i] = NULL;
+
+ if (subj) {
+ X509_NAME *n = parse_name(subj, chtype, multirdn);
+
+ if (!n) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ X509_REQ_set_subject_name(req, n);
+ X509_NAME_free(n);
+ }
+
+ if (default_op)
+ BIO_printf(bio_err, "The Subject's Distinguished Name is as follows\n");
+
+ name = X509_REQ_get_subject_name(req);
+ for (i = 0; i < X509_NAME_entry_count(name); i++) {
+ ne = X509_NAME_get_entry(name, i);
+ str = X509_NAME_ENTRY_get_data(ne);
+ obj = X509_NAME_ENTRY_get_object(ne);
+ nid = OBJ_obj2nid(obj);
+
+ if (msie_hack) {
+ /* assume all type should be strings */
+
+ if (str->type == V_ASN1_UNIVERSALSTRING)
+ ASN1_UNIVERSALSTRING_to_string(str);
+
+ if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress)
+ str->type = V_ASN1_T61STRING;
+
+ if (nid == NID_pkcs9_emailAddress
+ && str->type == V_ASN1_PRINTABLESTRING)
+ str->type = V_ASN1_IA5STRING;
+ }
+
+ /* If no EMAIL is wanted in the subject */
+ if (nid == NID_pkcs9_emailAddress && !email_dn)
+ continue;
+
+ /* check some things */
+ if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) {
+ BIO_printf(bio_err,
+ "\nemailAddress type needs to be of type IA5STRING\n");
+ goto end;
+ }
+ if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) {
+ j = ASN1_PRINTABLE_type(str->data, str->length);
+ if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) ||
+ (j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING))
+ {
+ BIO_printf(bio_err,
+ "\nThe string contains characters that are illegal for the ASN.1 type\n");
+ goto end;
+ }
+ }
+
+ if (default_op)
+ old_entry_print(obj, str);
+ }
+
+ /* Ok, now we check the 'policy' stuff. */
+ if ((subject = X509_NAME_new()) == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+
+ /* take a copy of the issuer name before we mess with it. */
+ if (selfsign)
+ CAname = X509_NAME_dup(name);
+ else
+ CAname = X509_NAME_dup(X509_get_subject_name(x509));
+ if (CAname == NULL)
+ goto end;
+ str = str2 = NULL;
+
+ for (i = 0; i < sk_CONF_VALUE_num(policy); i++) {
+ cv = sk_CONF_VALUE_value(policy, i); /* get the object id */
+ if ((j = OBJ_txt2nid(cv->name)) == NID_undef) {
+ BIO_printf(bio_err,
+ "%s:unknown object type in 'policy' configuration\n",
+ cv->name);
+ goto end;
+ }
+ obj = OBJ_nid2obj(j);
+
+ last = -1;
+ for (;;) {
+ X509_NAME_ENTRY *push = NULL;
+
+ /* lookup the object in the supplied name list */
+ j = X509_NAME_get_index_by_OBJ(name, obj, last);
+ if (j < 0) {
+ if (last != -1)
+ break;
+ tne = NULL;
+ } else {
+ tne = X509_NAME_get_entry(name, j);
+ }
+ last = j;
+
+ /* depending on the 'policy', decide what to do. */
+ if (strcmp(cv->value, "optional") == 0) {
+ if (tne != NULL)
+ push = tne;
+ } else if (strcmp(cv->value, "supplied") == 0) {
+ if (tne == NULL) {
+ BIO_printf(bio_err,
+ "The %s field needed to be supplied and was missing\n",
+ cv->name);
+ goto end;
+ } else {
+ push = tne;
+ }
+ } else if (strcmp(cv->value, "match") == 0) {
+ int last2;
+
+ if (tne == NULL) {
+ BIO_printf(bio_err,
+ "The mandatory %s field was missing\n",
+ cv->name);
+ goto end;
+ }
+
+ last2 = -1;
+
+ again2:
+ j = X509_NAME_get_index_by_OBJ(CAname, obj, last2);
+ if ((j < 0) && (last2 == -1)) {
+ BIO_printf(bio_err,
+ "The %s field does not exist in the CA certificate,\n"
+ "the 'policy' is misconfigured\n", cv->name);
+ goto end;
+ }
+ if (j >= 0) {
+ push = X509_NAME_get_entry(CAname, j);
+ str = X509_NAME_ENTRY_get_data(tne);
+ str2 = X509_NAME_ENTRY_get_data(push);
+ last2 = j;
+ if (ASN1_STRING_cmp(str, str2) != 0)
+ goto again2;
+ }
+ if (j < 0) {
+ BIO_printf(bio_err,
+ "The %s field is different between\n"
+ "CA certificate (%s) and the request (%s)\n",
+ cv->name,
+ ((str2 == NULL) ? "NULL" : (char *)str2->data),
+ ((str == NULL) ? "NULL" : (char *)str->data));
+ goto end;
+ }
+ } else {
+ BIO_printf(bio_err,
+ "%s:invalid type in 'policy' configuration\n",
+ cv->value);
+ goto end;
+ }
+
+ if (push != NULL) {
+ if (!X509_NAME_add_entry(subject, push, -1, 0)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ }
+ if (j < 0)
+ break;
+ }
+ }
+
+ if (preserve) {
+ X509_NAME_free(subject);
+ /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
+ subject = X509_NAME_dup(name);
+ if (subject == NULL)
+ goto end;
+ }
+
+ /* We are now totally happy, lets make and sign the certificate */
+ if (verbose)
+ BIO_printf(bio_err,
+ "Everything appears to be ok, creating and signing the certificate\n");
+
+ if ((ret = X509_new()) == NULL)
+ goto end;
+
+#ifdef X509_V3
+ /* Make it an X509 v3 certificate. */
+ if (!X509_set_version(ret, 2))
+ goto end;
+#endif
+
+ if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL)
+ goto end;
+ if (selfsign) {
+ if (!X509_set_issuer_name(ret, subject))
+ goto end;
+ } else {
+ if (!X509_set_issuer_name(ret, X509_get_subject_name(x509)))
+ goto end;
+ }
+
+ if (!set_cert_times(ret, startdate, enddate, days))
+ goto end;
+
+ if (enddate != NULL) {
+ int tdays;
+
+ if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret)))
+ goto end;
+ days = tdays;
+ }
+
+ if (!X509_set_subject_name(ret, subject))
+ goto end;
+
+ pktmp = X509_REQ_get0_pubkey(req);
+ i = X509_set_pubkey(ret, pktmp);
+ if (!i)
+ goto end;
+
+ /* Lets add the extensions, if there are any */
+ if (ext_sect) {
+ X509V3_CTX ctx;
+
+ /* Initialize the context structure */
+ if (selfsign)
+ X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
+ else
+ X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
+
+ if (extconf != NULL) {
+ if (verbose)
+ BIO_printf(bio_err, "Extra configuration file found\n");
+
+ /* Use the extconf configuration db LHASH */
+ X509V3_set_nconf(&ctx, extconf);
+
+ /* Test the structure (needed?) */
+ /* X509V3_set_ctx_test(&ctx); */
+
+ /* Adds exts contained in the configuration file */
+ if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
+ BIO_printf(bio_err,
+ "ERROR: adding extensions in section %s\n",
+ ext_sect);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (verbose)
+ BIO_printf(bio_err,
+ "Successfully added extensions from file.\n");
+ } else if (ext_sect) {
+ /* We found extensions to be set from config file */
+ X509V3_set_nconf(&ctx, lconf);
+
+ if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
+ BIO_printf(bio_err,
+ "ERROR: adding extensions in section %s\n",
+ ext_sect);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err,
+ "Successfully added extensions from config\n");
+ }
+ }
+
+ /* Copy extensions from request (if any) */
+
+ if (!copy_extensions(ret, req, ext_copy)) {
+ BIO_printf(bio_err, "ERROR: adding extensions from request\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ {
+ const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret);
+
+ if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0)
+ /* Make it an X509 v3 certificate. */
+ if (!X509_set_version(ret, 2))
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err,
+ "The subject name appears to be ok, checking data base for clashes\n");
+
+ /* Build the correct Subject if no e-mail is wanted in the subject. */
+ if (!email_dn) {
+ X509_NAME_ENTRY *tmpne;
+ X509_NAME *dn_subject;
+
+ /*
+ * Its best to dup the subject DN and then delete any email addresses
+ * because this retains its structure.
+ */
+ if ((dn_subject = X509_NAME_dup(subject)) == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ i = -1;
+ while ((i = X509_NAME_get_index_by_NID(dn_subject,
+ NID_pkcs9_emailAddress,
+ i)) >= 0) {
+ tmpne = X509_NAME_delete_entry(dn_subject, i--);
+ X509_NAME_ENTRY_free(tmpne);
+ }
+
+ if (!X509_set_subject_name(ret, dn_subject)) {
+ X509_NAME_free(dn_subject);
+ goto end;
+ }
+ X509_NAME_free(dn_subject);
+ }
+
+ row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
+ if (row[DB_name] == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+
+ if (BN_is_zero(serial))
+ row[DB_serial] = OPENSSL_strdup("00");
+ else
+ row[DB_serial] = BN_bn2hex(serial);
+ if (row[DB_serial] == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+
+ if (row[DB_name][0] == '\0') {
+ /*
+ * An empty subject! We'll use the serial number instead. If
+ * unique_subject is in use then we don't want different entries with
+ * empty subjects matching each other.
+ */
+ OPENSSL_free(row[DB_name]);
+ row[DB_name] = OPENSSL_strdup(row[DB_serial]);
+ if (row[DB_name] == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ }
+
+ if (db->attributes.unique_subject) {
+ OPENSSL_STRING *crow = row;
+
+ rrow = TXT_DB_get_by_index(db->db, DB_name, crow);
+ if (rrow != NULL) {
+ BIO_printf(bio_err,
+ "ERROR:There is already a certificate for %s\n",
+ row[DB_name]);
+ }
+ }
+ if (rrow == NULL) {
+ rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
+ if (rrow != NULL) {
+ BIO_printf(bio_err,
+ "ERROR:Serial number %s has already been issued,\n",
+ row[DB_serial]);
+ BIO_printf(bio_err,
+ " check the database/serial_file for corruption\n");
+ }
+ }
+
+ if (rrow != NULL) {
+ BIO_printf(bio_err, "The matching entry has the following details\n");
+ if (rrow[DB_type][0] == DB_TYPE_EXP)
+ p = "Expired";
+ else if (rrow[DB_type][0] == DB_TYPE_REV)
+ p = "Revoked";
+ else if (rrow[DB_type][0] == DB_TYPE_VAL)
+ p = "Valid";
+ else
+ p = "\ninvalid type, Data base error\n";
+ BIO_printf(bio_err, "Type :%s\n", p);;
+ if (rrow[DB_type][0] == DB_TYPE_REV) {
+ p = rrow[DB_exp_date];
+ if (p == NULL)
+ p = "undef";
+ BIO_printf(bio_err, "Was revoked on:%s\n", p);
+ }
+ p = rrow[DB_exp_date];
+ if (p == NULL)
+ p = "undef";
+ BIO_printf(bio_err, "Expires on :%s\n", p);
+ p = rrow[DB_serial];
+ if (p == NULL)
+ p = "undef";
+ BIO_printf(bio_err, "Serial Number :%s\n", p);
+ p = rrow[DB_file];
+ if (p == NULL)
+ p = "undef";
+ BIO_printf(bio_err, "File name :%s\n", p);
+ p = rrow[DB_name];
+ if (p == NULL)
+ p = "undef";
+ BIO_printf(bio_err, "Subject Name :%s\n", p);
+ ok = -1; /* This is now a 'bad' error. */
+ goto end;
+ }
+
+ if (!default_op) {
+ BIO_printf(bio_err, "Certificate Details:\n");
+ /*
+ * Never print signature details because signature not present
+ */
+ certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
+ X509_print_ex(bio_err, ret, nameopt, certopt);
+ }
+
+ BIO_printf(bio_err, "Certificate is to be certified until ");
+ ASN1_TIME_print(bio_err, X509_get0_notAfter(ret));
+ if (days)
+ BIO_printf(bio_err, " (%ld days)", days);
+ BIO_printf(bio_err, "\n");
+
+ if (!batch) {
+
+ BIO_printf(bio_err, "Sign the certificate? [y/n]:");
+ (void)BIO_flush(bio_err);
+ buf[0] = '\0';
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ BIO_printf(bio_err,
+ "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
+ ok = 0;
+ goto end;
+ }
+ if (!(buf[0] == 'y' || buf[0] == 'Y')) {
+ BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n");
+ ok = 0;
+ goto end;
+ }
+ }
+
+ pktmp = X509_get0_pubkey(ret);
+ if (EVP_PKEY_missing_parameters(pktmp) &&
+ !EVP_PKEY_missing_parameters(pkey))
+ EVP_PKEY_copy_parameters(pktmp, pkey);
+
+ if (!do_X509_sign(ret, pkey, dgst, sigopts))
+ goto end;
+
+ /* We now just add it to the database as DB_TYPE_VAL('V') */
+ row[DB_type] = OPENSSL_strdup("V");
+ tm = X509_get0_notAfter(ret);
+ row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate");
+ memcpy(row[DB_exp_date], tm->data, tm->length);
+ row[DB_exp_date][tm->length] = '\0';
+ row[DB_rev_date] = NULL;
+ row[DB_file] = OPENSSL_strdup("unknown");
+ if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
+ (row[DB_file] == NULL) || (row[DB_name] == NULL)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+
+ irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space");
+ for (i = 0; i < DB_NUMBER; i++)
+ irow[i] = row[i];
+ irow[DB_NUMBER] = NULL;
+
+ if (!TXT_DB_insert(db->db, irow)) {
+ BIO_printf(bio_err, "failed to update database\n");
+ BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
+ goto end;
+ }
+ irow = NULL;
+ ok = 1;
+ end:
+ if (ok != 1) {
+ for (i = 0; i < DB_NUMBER; i++)
+ OPENSSL_free(row[i]);
+ }
+ OPENSSL_free(irow);
+
+ X509_NAME_free(CAname);
+ X509_NAME_free(subject);
+ if (ok <= 0)
+ X509_free(ret);
+ else
+ *xret = ret;
+ return ok;
+}
+
+static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
+{
+
+ if (output_der) {
+ (void)i2d_X509_bio(bp, x);
+ return;
+ }
+ if (!notext)
+ X509_print(bp, x);
+ PEM_write_bio_X509(bp, x);
+}
+
+static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey,
+ X509 *x509, const EVP_MD *dgst,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+ BIGNUM *serial, const char *subj, unsigned long chtype,
+ int multirdn, int email_dn, const char *startdate,
+ const char *enddate, long days, const char *ext_sect,
+ CONF *lconf, int verbose, unsigned long certopt,
+ unsigned long nameopt, int default_op, int ext_copy)
+{
+ STACK_OF(CONF_VALUE) *sk = NULL;
+ LHASH_OF(CONF_VALUE) *parms = NULL;
+ X509_REQ *req = NULL;
+ CONF_VALUE *cv = NULL;
+ NETSCAPE_SPKI *spki = NULL;
+ char *type, *buf;
+ EVP_PKEY *pktmp = NULL;
+ X509_NAME *n = NULL;
+ X509_NAME_ENTRY *ne = NULL;
+ int ok = -1, i, j;
+ long errline;
+ int nid;
+
+ /*
+ * Load input file into a hash table. (This is just an easy
+ * way to read and parse the file, then put it into a convenient
+ * STACK format).
+ */
+ parms = CONF_load(NULL, infile, &errline);
+ if (parms == NULL) {
+ BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ sk = CONF_get_section(parms, "default");
+ if (sk_CONF_VALUE_num(sk) == 0) {
+ BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
+ goto end;
+ }
+
+ /*
+ * Now create a dummy X509 request structure. We don't actually
+ * have an X509 request, but we have many of the components
+ * (a public key, various DN components). The idea is that we
+ * put these components into the right X509 request structure
+ * and we can use the same code as if you had a real X509 request.
+ */
+ req = X509_REQ_new();
+ if (req == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ /*
+ * Build up the subject name set.
+ */
+ n = X509_REQ_get_subject_name(req);
+
+ for (i = 0;; i++) {
+ if (sk_CONF_VALUE_num(sk) <= i)
+ break;
+
+ cv = sk_CONF_VALUE_value(sk, i);
+ type = cv->name;
+ /*
+ * Skip past any leading X. X: X, etc to allow for multiple instances
+ */
+ for (buf = cv->name; *buf; buf++)
+ if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
+ buf++;
+ if (*buf)
+ type = buf;
+ break;
+ }
+
+ buf = cv->value;
+ if ((nid = OBJ_txt2nid(type)) == NID_undef) {
+ if (strcmp(type, "SPKAC") == 0) {
+ spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
+ if (spki == NULL) {
+ BIO_printf(bio_err,
+ "unable to load Netscape SPKAC structure\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ continue;
+ }
+
+ if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
+ (unsigned char *)buf, -1, -1, 0))
+ goto end;
+ }
+ if (spki == NULL) {
+ BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n",
+ infile);
+ goto end;
+ }
+
+ /*
+ * Now extract the key from the SPKI structure.
+ */
+
+ BIO_printf(bio_err, "Check that the SPKAC request matches the signature\n");
+
+ if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) {
+ BIO_printf(bio_err, "error unpacking SPKAC public key\n");
+ goto end;
+ }
+
+ j = NETSCAPE_SPKI_verify(spki, pktmp);
+ if (j <= 0) {
+ EVP_PKEY_free(pktmp);
+ BIO_printf(bio_err,
+ "signature verification failed on SPKAC public key\n");
+ goto end;
+ }
+ BIO_printf(bio_err, "Signature ok\n");
+
+ X509_REQ_set_pubkey(req, pktmp);
+ EVP_PKEY_free(pktmp);
+ ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
+ chtype, multirdn, email_dn, startdate, enddate, days, 1,
+ verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
+ ext_copy, 0);
+ end:
+ X509_REQ_free(req);
+ CONF_free(parms);
+ NETSCAPE_SPKI_free(spki);
+ X509_NAME_ENTRY_free(ne);
+
+ return ok;
+}
+
+static int check_time_format(const char *str)
+{
+ return ASN1_TIME_set_string(NULL, str);
+}
+
+static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
+ const char *value)
+{
+ const ASN1_TIME *tm = NULL;
+ char *row[DB_NUMBER], **rrow, **irow;
+ char *rev_str = NULL;
+ BIGNUM *bn = NULL;
+ int ok = -1, i;
+
+ for (i = 0; i < DB_NUMBER; i++)
+ row[i] = NULL;
+ row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
+ bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
+ if (!bn)
+ goto end;
+ if (BN_is_zero(bn))
+ row[DB_serial] = OPENSSL_strdup("00");
+ else
+ row[DB_serial] = BN_bn2hex(bn);
+ BN_free(bn);
+ if (row[DB_name] != NULL && row[DB_name][0] == '\0') {
+ /* Entries with empty Subjects actually use the serial number instead */
+ OPENSSL_free(row[DB_name]);
+ row[DB_name] = OPENSSL_strdup(row[DB_serial]);
+ }
+ if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+ /*
+ * We have to lookup by serial number because name lookup skips revoked
+ * certs
+ */
+ rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
+ if (rrow == NULL) {
+ BIO_printf(bio_err,
+ "Adding Entry with serial number %s to DB for %s\n",
+ row[DB_serial], row[DB_name]);
+
+ /* We now just add it to the database as DB_TYPE_REV('V') */
+ row[DB_type] = OPENSSL_strdup("V");
+ tm = X509_get0_notAfter(x509);
+ row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data");
+ memcpy(row[DB_exp_date], tm->data, tm->length);
+ row[DB_exp_date][tm->length] = '\0';
+ row[DB_rev_date] = NULL;
+ row[DB_file] = OPENSSL_strdup("unknown");
+
+ if (row[DB_type] == NULL || row[DB_file] == NULL) {
+ BIO_printf(bio_err, "Memory allocation failure\n");
+ goto end;
+ }
+
+ irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr");
+ for (i = 0; i < DB_NUMBER; i++)
+ irow[i] = row[i];
+ irow[DB_NUMBER] = NULL;
+
+ if (!TXT_DB_insert(db->db, irow)) {
+ BIO_printf(bio_err, "failed to update database\n");
+ BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
+ OPENSSL_free(irow);
+ goto end;
+ }
+
+ for (i = 0; i < DB_NUMBER; i++)
+ row[i] = NULL;
+
+ /* Revoke Certificate */
+ if (rev_type == REV_VALID)
+ ok = 1;
+ else
+ /* Retry revocation after DB insertion */
+ ok = do_revoke(x509, db, rev_type, value);
+
+ goto end;
+
+ } else if (index_name_cmp_noconst(row, rrow)) {
+ BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
+ goto end;
+ } else if (rev_type == REV_VALID) {
+ BIO_printf(bio_err, "ERROR:Already present, serial number %s\n",
+ row[DB_serial]);
+ goto end;
+ } else if (rrow[DB_type][0] == DB_TYPE_REV) {
+ BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
+ row[DB_serial]);
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]);
+ rev_str = make_revocation_str(rev_type, value);
+ if (!rev_str) {
+ BIO_printf(bio_err, "Error in revocation arguments\n");
+ goto end;
+ }
+ rrow[DB_type][0] = DB_TYPE_REV;
+ rrow[DB_type][1] = '\0';
+ rrow[DB_rev_date] = rev_str;
+ }
+ ok = 1;
+ end:
+ for (i = 0; i < DB_NUMBER; i++)
+ OPENSSL_free(row[i]);
+ return ok;
+}
+
+static int get_certificate_status(const char *serial, CA_DB *db)
+{
+ char *row[DB_NUMBER], **rrow;
+ int ok = -1, i;
+ size_t serial_len = strlen(serial);
+
+ /* Free Resources */
+ for (i = 0; i < DB_NUMBER; i++)
+ row[i] = NULL;
+
+ /* Malloc needed char spaces */
+ row[DB_serial] = app_malloc(serial_len + 2, "row serial#");
+
+ if (serial_len % 2) {
+ /*
+ * Set the first char to 0
+ */
+ row[DB_serial][0] = '0';
+
+ /* Copy String from serial to row[DB_serial] */
+ memcpy(row[DB_serial] + 1, serial, serial_len);
+ row[DB_serial][serial_len + 1] = '\0';
+ } else {
+ /* Copy String from serial to row[DB_serial] */
+ memcpy(row[DB_serial], serial, serial_len);
+ row[DB_serial][serial_len] = '\0';
+ }
+
+ /* Make it Upper Case */
+ make_uppercase(row[DB_serial]);
+
+ ok = 1;
+
+ /* Search for the certificate */
+ rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
+ if (rrow == NULL) {
+ BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]);
+ ok = -1;
+ goto end;
+ } else if (rrow[DB_type][0] == DB_TYPE_VAL) {
+ BIO_printf(bio_err, "%s=Valid (%c)\n",
+ row[DB_serial], rrow[DB_type][0]);
+ goto end;
+ } else if (rrow[DB_type][0] == DB_TYPE_REV) {
+ BIO_printf(bio_err, "%s=Revoked (%c)\n",
+ row[DB_serial], rrow[DB_type][0]);
+ goto end;
+ } else if (rrow[DB_type][0] == DB_TYPE_EXP) {
+ BIO_printf(bio_err, "%s=Expired (%c)\n",
+ row[DB_serial], rrow[DB_type][0]);
+ goto end;
+ } else if (rrow[DB_type][0] == DB_TYPE_SUSP) {
+ BIO_printf(bio_err, "%s=Suspended (%c)\n",
+ row[DB_serial], rrow[DB_type][0]);
+ goto end;
+ } else {
+ BIO_printf(bio_err, "%s=Unknown (%c).\n",
+ row[DB_serial], rrow[DB_type][0]);
+ ok = -1;
+ }
+ end:
+ for (i = 0; i < DB_NUMBER; i++) {
+ OPENSSL_free(row[i]);
+ }
+ return ok;
+}
+
+static int do_updatedb(CA_DB *db)
+{
+ ASN1_UTCTIME *a_tm = NULL;
+ int i, cnt = 0;
+ int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
+ char **rrow, *a_tm_s;
+
+ a_tm = ASN1_UTCTIME_new();
+ if (a_tm == NULL)
+ return -1;
+
+ /* get actual time and make a string */
+ if (X509_gmtime_adj(a_tm, 0) == NULL) {
+ ASN1_UTCTIME_free(a_tm);
+ return -1;
+ }
+ a_tm_s = app_malloc(a_tm->length + 1, "time string");
+
+ memcpy(a_tm_s, a_tm->data, a_tm->length);
+ a_tm_s[a_tm->length] = '\0';
+
+ if (strncmp(a_tm_s, "49", 2) <= 0)
+ a_y2k = 1;
+ else
+ a_y2k = 0;
+
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (rrow[DB_type][0] == DB_TYPE_VAL) {
+ /* ignore entries that are not valid */
+ if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
+ db_y2k = 1;
+ else
+ db_y2k = 0;
+
+ if (db_y2k == a_y2k) {
+ /* all on the same y2k side */
+ if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) {
+ rrow[DB_type][0] = DB_TYPE_EXP;
+ rrow[DB_type][1] = '\0';
+ cnt++;
+
+ BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
+ }
+ } else if (db_y2k < a_y2k) {
+ rrow[DB_type][0] = DB_TYPE_EXP;
+ rrow[DB_type][1] = '\0';
+ cnt++;
+
+ BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
+ }
+
+ }
+ }
+
+ ASN1_UTCTIME_free(a_tm);
+ OPENSSL_free(a_tm_s);
+ return cnt;
+}
+
+static const char *crl_reasons[] = {
+ /* CRL reason strings */
+ "unspecified",
+ "keyCompromise",
+ "CACompromise",
+ "affiliationChanged",
+ "superseded",
+ "cessationOfOperation",
+ "certificateHold",
+ "removeFromCRL",
+ /* Additional pseudo reasons */
+ "holdInstruction",
+ "keyTime",
+ "CAkeyTime"
+};
+
+#define NUM_REASONS OSSL_NELEM(crl_reasons)
+
+/*
+ * Given revocation information convert to a DB string. The format of the
+ * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time
+ * (the current time). 'reason' is the optional CRL reason and 'extra' is any
+ * additional argument
+ */
+
+static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg)
+{
+ char *str;
+ const char *reason = NULL, *other = NULL;
+ ASN1_OBJECT *otmp;
+ ASN1_UTCTIME *revtm = NULL;
+ int i;
+
+ switch (rev_type) {
+ case REV_NONE:
+ case REV_VALID:
+ break;
+
+ case REV_CRL_REASON:
+ for (i = 0; i < 8; i++) {
+ if (strcasecmp(rev_arg, crl_reasons[i]) == 0) {
+ reason = crl_reasons[i];
+ break;
+ }
+ }
+ if (reason == NULL) {
+ BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
+ return NULL;
+ }
+ break;
+
+ case REV_HOLD:
+ /* Argument is an OID */
+ otmp = OBJ_txt2obj(rev_arg, 0);
+ ASN1_OBJECT_free(otmp);
+
+ if (otmp == NULL) {
+ BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
+ return NULL;
+ }
+
+ reason = "holdInstruction";
+ other = rev_arg;
+ break;
+
+ case REV_KEY_COMPROMISE:
+ case REV_CA_COMPROMISE:
+ /* Argument is the key compromise time */
+ if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) {
+ BIO_printf(bio_err,
+ "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n",
+ rev_arg);
+ return NULL;
+ }
+ other = rev_arg;
+ if (rev_type == REV_KEY_COMPROMISE)
+ reason = "keyTime";
+ else
+ reason = "CAkeyTime";
+
+ break;
+ }
+
+ revtm = X509_gmtime_adj(NULL, 0);
+
+ if (!revtm)
+ return NULL;
+
+ i = revtm->length + 1;
+
+ if (reason)
+ i += strlen(reason) + 1;
+ if (other)
+ i += strlen(other) + 1;
+
+ str = app_malloc(i, "revocation reason");
+ OPENSSL_strlcpy(str, (char *)revtm->data, i);
+ if (reason) {
+ OPENSSL_strlcat(str, ",", i);
+ OPENSSL_strlcat(str, reason, i);
+ }
+ if (other) {
+ OPENSSL_strlcat(str, ",", i);
+ OPENSSL_strlcat(str, other, i);
+ }
+ ASN1_UTCTIME_free(revtm);
+ return str;
+}
+
+/*-
+ * Convert revocation field to X509_REVOKED entry
+ * return code:
+ * 0 error
+ * 1 OK
+ * 2 OK and some extensions added (i.e. V2 CRL)
+ */
+
+static int make_revoked(X509_REVOKED *rev, const char *str)
+{
+ char *tmp = NULL;
+ int reason_code = -1;
+ int i, ret = 0;
+ ASN1_OBJECT *hold = NULL;
+ ASN1_GENERALIZEDTIME *comp_time = NULL;
+ ASN1_ENUMERATED *rtmp = NULL;
+
+ ASN1_TIME *revDate = NULL;
+
+ i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
+
+ if (i == 0)
+ goto end;
+
+ if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
+ goto end;
+
+ if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) {
+ rtmp = ASN1_ENUMERATED_new();
+ if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code))
+ goto end;
+ if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
+ goto end;
+ }
+
+ if (rev && comp_time) {
+ if (!X509_REVOKED_add1_ext_i2d
+ (rev, NID_invalidity_date, comp_time, 0, 0))
+ goto end;
+ }
+ if (rev && hold) {
+ if (!X509_REVOKED_add1_ext_i2d
+ (rev, NID_hold_instruction_code, hold, 0, 0))
+ goto end;
+ }
+
+ if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
+ ret = 2;
+ else
+ ret = 1;
+
+ end:
+
+ OPENSSL_free(tmp);
+ ASN1_OBJECT_free(hold);
+ ASN1_GENERALIZEDTIME_free(comp_time);
+ ASN1_ENUMERATED_free(rtmp);
+ ASN1_TIME_free(revDate);
+
+ return ret;
+}
+
+static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str)
+{
+ char buf[25], *pbuf;
+ const char *p;
+ int j;
+
+ j = i2a_ASN1_OBJECT(bio_err, obj);
+ pbuf = buf;
+ for (j = 22 - j; j > 0; j--)
+ *(pbuf++) = ' ';
+ *(pbuf++) = ':';
+ *(pbuf++) = '\0';
+ BIO_puts(bio_err, buf);
+
+ if (str->type == V_ASN1_PRINTABLESTRING)
+ BIO_printf(bio_err, "PRINTABLE:'");
+ else if (str->type == V_ASN1_T61STRING)
+ BIO_printf(bio_err, "T61STRING:'");
+ else if (str->type == V_ASN1_IA5STRING)
+ BIO_printf(bio_err, "IA5STRING:'");
+ else if (str->type == V_ASN1_UNIVERSALSTRING)
+ BIO_printf(bio_err, "UNIVERSALSTRING:'");
+ else
+ BIO_printf(bio_err, "ASN.1 %2d:'", str->type);
+
+ p = (const char *)str->data;
+ for (j = str->length; j > 0; j--) {
+ if ((*p >= ' ') && (*p <= '~'))
+ BIO_printf(bio_err, "%c", *p);
+ else if (*p & 0x80)
+ BIO_printf(bio_err, "\\0x%02X", *p);
+ else if ((unsigned char)*p == 0xf7)
+ BIO_printf(bio_err, "^?");
+ else
+ BIO_printf(bio_err, "^%c", *p + '@');
+ p++;
+ }
+ BIO_printf(bio_err, "'\n");
+ return 1;
+}
+
+int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
+ ASN1_GENERALIZEDTIME **pinvtm, const char *str)
+{
+ char *tmp;
+ char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
+ int reason_code = -1;
+ int ret = 0;
+ unsigned int i;
+ ASN1_OBJECT *hold = NULL;
+ ASN1_GENERALIZEDTIME *comp_time = NULL;
+
+ tmp = OPENSSL_strdup(str);
+ if (!tmp) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto end;
+ }
+
+ p = strchr(tmp, ',');
+
+ rtime_str = tmp;
+
+ if (p) {
+ *p = '\0';
+ p++;
+ reason_str = p;
+ p = strchr(p, ',');
+ if (p) {
+ *p = '\0';
+ arg_str = p + 1;
+ }
+ }
+
+ if (prevtm) {
+ *prevtm = ASN1_UTCTIME_new();
+ if (*prevtm == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto end;
+ }
+ if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) {
+ BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
+ goto end;
+ }
+ }
+ if (reason_str) {
+ for (i = 0; i < NUM_REASONS; i++) {
+ if (strcasecmp(reason_str, crl_reasons[i]) == 0) {
+ reason_code = i;
+ break;
+ }
+ }
+ if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) {
+ BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
+ goto end;
+ }
+
+ if (reason_code == 7) {
+ reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
+ } else if (reason_code == 8) { /* Hold instruction */
+ if (!arg_str) {
+ BIO_printf(bio_err, "missing hold instruction\n");
+ goto end;
+ }
+ reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
+ hold = OBJ_txt2obj(arg_str, 0);
+
+ if (!hold) {
+ BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
+ goto end;
+ }
+ if (phold)
+ *phold = hold;
+ else
+ ASN1_OBJECT_free(hold);
+ } else if ((reason_code == 9) || (reason_code == 10)) {
+ if (!arg_str) {
+ BIO_printf(bio_err, "missing compromised time\n");
+ goto end;
+ }
+ comp_time = ASN1_GENERALIZEDTIME_new();
+ if (comp_time == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto end;
+ }
+ if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) {
+ BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
+ goto end;
+ }
+ if (reason_code == 9)
+ reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
+ else
+ reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
+ }
+ }
+
+ if (preason)
+ *preason = reason_code;
+ if (pinvtm) {
+ *pinvtm = comp_time;
+ comp_time = NULL;
+ }
+
+ ret = 1;
+
+ end:
+
+ OPENSSL_free(tmp);
+ ASN1_GENERALIZEDTIME_free(comp_time);
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/ciphers.c b/freebsd/crypto/openssl/apps/ciphers.c
new file mode 100644
index 00000000..caaa088b
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ciphers.c
@@ -0,0 +1,268 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_STDNAME,
+ OPT_CONVERT,
+ OPT_SSL3,
+ OPT_TLS1,
+ OPT_TLS1_1,
+ OPT_TLS1_2,
+ OPT_TLS1_3,
+ OPT_PSK,
+ OPT_SRP,
+ OPT_CIPHERSUITES,
+ OPT_V, OPT_UPPER_V, OPT_S
+} OPTION_CHOICE;
+
+const OPTIONS ciphers_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"},
+ {"V", OPT_UPPER_V, '-', "Even more verbose"},
+ {"s", OPT_S, '-', "Only supported ciphers"},
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "SSL3 mode"},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {"tls1", OPT_TLS1, '-', "TLS1 mode"},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+ {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+ {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"},
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"},
+#endif
+ {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
+#ifndef OPENSSL_NO_PSK
+ {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"},
+#endif
+#ifndef OPENSSL_NO_SRP
+ {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"},
+#endif
+ {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"},
+ {"ciphersuites", OPT_CIPHERSUITES, 's',
+ "Configure the TLSv1.3 ciphersuites to use"},
+ {NULL}
+};
+
+#ifndef OPENSSL_NO_PSK
+static unsigned int dummy_psk(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len)
+{
+ return 0;
+}
+#endif
+#ifndef OPENSSL_NO_SRP
+static char *dummy_srp(SSL *ssl, void *arg)
+{
+ return "";
+}
+#endif
+
+int ciphers_main(int argc, char **argv)
+{
+ SSL_CTX *ctx = NULL;
+ SSL *ssl = NULL;
+ STACK_OF(SSL_CIPHER) *sk = NULL;
+ const SSL_METHOD *meth = TLS_server_method();
+ int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0;
+ int stdname = 0;
+#ifndef OPENSSL_NO_PSK
+ int psk = 0;
+#endif
+#ifndef OPENSSL_NO_SRP
+ int srp = 0;
+#endif
+ const char *p;
+ char *ciphers = NULL, *prog, *convert = NULL, *ciphersuites = NULL;
+ char buf[512];
+ OPTION_CHOICE o;
+ int min_version = 0, max_version = 0;
+
+ prog = opt_init(argc, argv, ciphers_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(ciphers_options);
+ ret = 0;
+ goto end;
+ case OPT_V:
+ verbose = 1;
+ break;
+ case OPT_UPPER_V:
+ verbose = Verbose = 1;
+ break;
+ case OPT_S:
+ use_supported = 1;
+ break;
+ case OPT_STDNAME:
+ stdname = verbose = 1;
+ break;
+ case OPT_CONVERT:
+ convert = opt_arg();
+ break;
+ case OPT_SSL3:
+ min_version = SSL3_VERSION;
+ max_version = SSL3_VERSION;
+ break;
+ case OPT_TLS1:
+ min_version = TLS1_VERSION;
+ max_version = TLS1_VERSION;
+ break;
+ case OPT_TLS1_1:
+ min_version = TLS1_1_VERSION;
+ max_version = TLS1_1_VERSION;
+ break;
+ case OPT_TLS1_2:
+ min_version = TLS1_2_VERSION;
+ max_version = TLS1_2_VERSION;
+ break;
+ case OPT_TLS1_3:
+ min_version = TLS1_3_VERSION;
+ max_version = TLS1_3_VERSION;
+ break;
+ case OPT_PSK:
+#ifndef OPENSSL_NO_PSK
+ psk = 1;
+#endif
+ break;
+ case OPT_SRP:
+#ifndef OPENSSL_NO_SRP
+ srp = 1;
+#endif
+ break;
+ case OPT_CIPHERSUITES:
+ ciphersuites = opt_arg();
+ break;
+ }
+ }
+ argv = opt_rest();
+ argc = opt_num_rest();
+
+ if (argc == 1)
+ ciphers = *argv;
+ else if (argc != 0)
+ goto opthelp;
+
+ if (convert != NULL) {
+ BIO_printf(bio_out, "OpenSSL cipher name: %s\n",
+ OPENSSL_cipher_name(convert));
+ goto end;
+ }
+
+ ctx = SSL_CTX_new(meth);
+ if (ctx == NULL)
+ goto err;
+ if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
+ goto err;
+ if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
+ goto err;
+
+#ifndef OPENSSL_NO_PSK
+ if (psk)
+ SSL_CTX_set_psk_client_callback(ctx, dummy_psk);
+#endif
+#ifndef OPENSSL_NO_SRP
+ if (srp)
+ SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
+#endif
+
+ if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) {
+ BIO_printf(bio_err, "Error setting TLSv1.3 ciphersuites\n");
+ goto err;
+ }
+
+ if (ciphers != NULL) {
+ if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
+ BIO_printf(bio_err, "Error in cipher list\n");
+ goto err;
+ }
+ }
+ ssl = SSL_new(ctx);
+ if (ssl == NULL)
+ goto err;
+
+ if (use_supported)
+ sk = SSL_get1_supported_ciphers(ssl);
+ else
+ sk = SSL_get_ciphers(ssl);
+
+ if (!verbose) {
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
+ p = SSL_CIPHER_get_name(c);
+ if (p == NULL)
+ break;
+ if (i != 0)
+ BIO_printf(bio_out, ":");
+ BIO_printf(bio_out, "%s", p);
+ }
+ BIO_printf(bio_out, "\n");
+ } else {
+
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ const SSL_CIPHER *c;
+
+ c = sk_SSL_CIPHER_value(sk, i);
+
+ if (Verbose) {
+ unsigned long id = SSL_CIPHER_get_id(c);
+ int id0 = (int)(id >> 24);
+ int id1 = (int)((id >> 16) & 0xffL);
+ int id2 = (int)((id >> 8) & 0xffL);
+ int id3 = (int)(id & 0xffL);
+
+ if ((id & 0xff000000L) == 0x03000000L)
+ BIO_printf(bio_out, " 0x%02X,0x%02X - ", id2, id3); /* SSL3
+ * cipher */
+ else
+ BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */
+ }
+ if (stdname) {
+ const char *nm = SSL_CIPHER_standard_name(c);
+ if (nm == NULL)
+ nm = "UNKNOWN";
+ BIO_printf(bio_out, "%s - ", nm);
+ }
+ BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf)));
+ }
+ }
+
+ ret = 0;
+ goto end;
+ err:
+ ERR_print_errors(bio_err);
+ end:
+ if (use_supported)
+ sk_SSL_CIPHER_free(sk);
+ SSL_CTX_free(ctx);
+ SSL_free(ssl);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/cms.c b/freebsd/crypto/openssl/apps/cms.c
new file mode 100644
index 00000000..de8818b6
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/cms.c
@@ -0,0 +1,1291 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMS utility function */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+
+#ifndef OPENSSL_NO_CMS
+
+# include <openssl/crypto.h>
+# include <openssl/pem.h>
+# include <openssl/err.h>
+# include <openssl/x509_vfy.h>
+# include <openssl/x509v3.h>
+# include <openssl/cms.h>
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers);
+static int cms_cb(int ok, X509_STORE_CTX *ctx);
+static void receipt_request_print(CMS_ContentInfo *cms);
+static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
+ *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
+ *rr_from);
+static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
+ STACK_OF(OPENSSL_STRING) *param);
+
+# define SMIME_OP 0x10
+# define SMIME_IP 0x20
+# define SMIME_SIGNERS 0x40
+# define SMIME_ENCRYPT (1 | SMIME_OP)
+# define SMIME_DECRYPT (2 | SMIME_IP)
+# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
+# define SMIME_VERIFY (4 | SMIME_IP)
+# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
+# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+# define SMIME_DATAOUT (7 | SMIME_IP)
+# define SMIME_DATA_CREATE (8 | SMIME_OP)
+# define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
+# define SMIME_DIGEST_CREATE (10 | SMIME_OP)
+# define SMIME_UNCOMPRESS (11 | SMIME_IP)
+# define SMIME_COMPRESS (12 | SMIME_OP)
+# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
+# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
+# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP)
+# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP)
+
+static int verify_err = 0;
+
+typedef struct cms_key_param_st cms_key_param;
+
+struct cms_key_param_st {
+ int idx;
+ STACK_OF(OPENSSL_STRING) *param;
+ cms_key_param *next;
+};
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
+ OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
+ OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
+ OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
+ OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
+ OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
+ OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
+ OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
+ OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
+ OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
+ OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
+ OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT,
+ OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
+ OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
+ OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
+ OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
+ OPT_3DES_WRAP, OPT_ENGINE,
+ OPT_R_ENUM,
+ OPT_V_ENUM,
+ OPT_CIPHER
+} OPTION_CHOICE;
+
+const OPTIONS cms_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
+ {OPT_HELP_STR, 1, '-',
+ " cert.pem... recipient certs for encryption\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output format SMIME (default), PEM or DER"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
+ {"sign", OPT_SIGN, '-', "Sign message"},
+ {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"verify", OPT_VERIFY, '-', "Verify signed message"},
+ {"verify_retcode", OPT_VERIFY_RETCODE, '-'},
+ {"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
+ {"cmsout", OPT_CMSOUT, '-', "Output CMS structure"},
+ {"data_out", OPT_DATA_OUT, '-'},
+ {"data_create", OPT_DATA_CREATE, '-'},
+ {"digest_verify", OPT_DIGEST_VERIFY, '-'},
+ {"digest_create", OPT_DIGEST_CREATE, '-'},
+ {"compress", OPT_COMPRESS, '-'},
+ {"uncompress", OPT_UNCOMPRESS, '-'},
+ {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'},
+ {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'},
+ {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'},
+ {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
+ {"asciicrlf", OPT_ASCIICRLF, '-'},
+ {"nointern", OPT_NOINTERN, '-',
+ "Don't search certificates in message for signer"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signers certificate when signing"},
+ {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
+ {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+ {"binary", OPT_BINARY, '-', "Don't translate message to text"},
+ {"keyid", OPT_KEYID, '-', "Use subject key identifier"},
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'},
+ {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'},
+ {"stream", OPT_INDEF, '-', "Enable CMS streaming"},
+ {"indef", OPT_INDEF, '-', "Same as -stream"},
+ {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+ {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" },
+ {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"},
+ {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
+ {"receipt_request_all", OPT_RR_ALL, '-'},
+ {"receipt_request_first", OPT_RR_FIRST, '-'},
+ {"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
+ {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"content", OPT_CONTENT, '<',
+ "Supply or override content for detached signature"},
+ {"print", OPT_PRINT, '-',
+ "For the -cmsout operation print out all fields of the CMS structure"},
+ {"secretkey", OPT_SECRETKEY, 's'},
+ {"secretkeyid", OPT_SECRETKEYID, 's'},
+ {"pwri_password", OPT_PWRI_PASSWORD, 's'},
+ {"econtent_type", OPT_ECONTENT_TYPE, 's'},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"to", OPT_TO, 's', "To address"},
+ {"from", OPT_FROM, 's', "From address"},
+ {"subject", OPT_SUBJECT, 's', "Subject"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate file"},
+ {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"},
+ {"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
+ {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
+ {"inkey", OPT_INKEY, 's',
+ "Input private key (if not signer or recipient)"},
+ {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
+ {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
+ {"receipt_request_from", OPT_RR_FROM, 's'},
+ {"receipt_request_to", OPT_RR_TO, 's'},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+ OPT_R_OPTIONS,
+ OPT_V_OPTIONS,
+ {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
+ {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
+ {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
+# ifndef OPENSSL_NO_DES
+ {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
+# endif
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int cms_main(int argc, char **argv)
+{
+ ASN1_OBJECT *econtent_type = NULL;
+ BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
+ CMS_ContentInfo *cms = NULL, *rcms = NULL;
+ CMS_ReceiptRequest *rr = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *key = NULL;
+ const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
+ const EVP_MD *sign_md = NULL;
+ STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
+ STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
+ STACK_OF(X509) *encerts = NULL, *other = NULL;
+ X509 *cert = NULL, *recip = NULL, *signer = NULL;
+ X509_STORE *store = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
+ const char *CAfile = NULL, *CApath = NULL;
+ char *certsoutfile = NULL;
+ int noCAfile = 0, noCApath = 0;
+ char *infile = NULL, *outfile = NULL, *rctfile = NULL;
+ char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
+ char *to = NULL, *from = NULL, *subject = NULL, *prog;
+ cms_key_param *key_first = NULL, *key_param = NULL;
+ int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
+ int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
+ int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
+ int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
+ size_t secret_keylen = 0, secret_keyidlen = 0;
+ unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
+ unsigned char *secret_key = NULL, *secret_keyid = NULL;
+ long ltmp;
+ const char *mime_eol = "\n";
+ OPTION_CHOICE o;
+
+ if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
+ return 1;
+
+ prog = opt_init(argc, argv, cms_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(cms_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENCRYPT:
+ operation = SMIME_ENCRYPT;
+ break;
+ case OPT_DECRYPT:
+ operation = SMIME_DECRYPT;
+ break;
+ case OPT_SIGN:
+ operation = SMIME_SIGN;
+ break;
+ case OPT_SIGN_RECEIPT:
+ operation = SMIME_SIGN_RECEIPT;
+ break;
+ case OPT_RESIGN:
+ operation = SMIME_RESIGN;
+ break;
+ case OPT_VERIFY:
+ operation = SMIME_VERIFY;
+ break;
+ case OPT_VERIFY_RETCODE:
+ verify_retcode = 1;
+ break;
+ case OPT_VERIFY_RECEIPT:
+ operation = SMIME_VERIFY_RECEIPT;
+ rctfile = opt_arg();
+ break;
+ case OPT_CMSOUT:
+ operation = SMIME_CMSOUT;
+ break;
+ case OPT_DATA_OUT:
+ operation = SMIME_DATAOUT;
+ break;
+ case OPT_DATA_CREATE:
+ operation = SMIME_DATA_CREATE;
+ break;
+ case OPT_DIGEST_VERIFY:
+ operation = SMIME_DIGEST_VERIFY;
+ break;
+ case OPT_DIGEST_CREATE:
+ operation = SMIME_DIGEST_CREATE;
+ break;
+ case OPT_COMPRESS:
+ operation = SMIME_COMPRESS;
+ break;
+ case OPT_UNCOMPRESS:
+ operation = SMIME_UNCOMPRESS;
+ break;
+ case OPT_ED_DECRYPT:
+ operation = SMIME_ENCRYPTED_DECRYPT;
+ break;
+ case OPT_ED_ENCRYPT:
+ operation = SMIME_ENCRYPTED_ENCRYPT;
+ break;
+ case OPT_DEBUG_DECRYPT:
+ flags |= CMS_DEBUG_DECRYPT;
+ break;
+ case OPT_TEXT:
+ flags |= CMS_TEXT;
+ break;
+ case OPT_ASCIICRLF:
+ flags |= CMS_ASCIICRLF;
+ break;
+ case OPT_NOINTERN:
+ flags |= CMS_NOINTERN;
+ break;
+ case OPT_NOVERIFY:
+ flags |= CMS_NO_SIGNER_CERT_VERIFY;
+ break;
+ case OPT_NOCERTS:
+ flags |= CMS_NOCERTS;
+ break;
+ case OPT_NOATTR:
+ flags |= CMS_NOATTR;
+ break;
+ case OPT_NODETACH:
+ flags &= ~CMS_DETACHED;
+ break;
+ case OPT_NOSMIMECAP:
+ flags |= CMS_NOSMIMECAP;
+ break;
+ case OPT_BINARY:
+ flags |= CMS_BINARY;
+ break;
+ case OPT_KEYID:
+ flags |= CMS_USE_KEYID;
+ break;
+ case OPT_NOSIGS:
+ flags |= CMS_NOSIGS;
+ break;
+ case OPT_NO_CONTENT_VERIFY:
+ flags |= CMS_NO_CONTENT_VERIFY;
+ break;
+ case OPT_NO_ATTR_VERIFY:
+ flags |= CMS_NO_ATTR_VERIFY;
+ break;
+ case OPT_INDEF:
+ flags |= CMS_STREAM;
+ break;
+ case OPT_NOINDEF:
+ flags &= ~CMS_STREAM;
+ break;
+ case OPT_CRLFEOL:
+ mime_eol = "\r\n";
+ flags |= CMS_CRLFEOL;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_RR_PRINT:
+ rr_print = 1;
+ break;
+ case OPT_RR_ALL:
+ rr_allorfirst = 0;
+ break;
+ case OPT_RR_FIRST:
+ rr_allorfirst = 1;
+ break;
+ case OPT_RCTFORM:
+ if (rctformat == FORMAT_SMIME)
+ rcms = SMIME_read_CMS(rctin, NULL);
+ else if (rctformat == FORMAT_PEM)
+ rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
+ else if (rctformat == FORMAT_ASN1)
+ if (!opt_format(opt_arg(),
+ OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
+ goto opthelp;
+ break;
+ case OPT_CERTFILE:
+ certfile = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_CONTENT:
+ contfile = opt_arg();
+ break;
+ case OPT_RR_FROM:
+ if (rr_from == NULL
+ && (rr_from = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(rr_from, opt_arg());
+ break;
+ case OPT_RR_TO:
+ if (rr_to == NULL
+ && (rr_to = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(rr_to, opt_arg());
+ break;
+ case OPT_PRINT:
+ noout = print = 1;
+ break;
+ case OPT_SECRETKEY:
+ if (secret_key != NULL) {
+ BIO_printf(bio_err, "Invalid key (supplied twice) %s\n",
+ opt_arg());
+ goto opthelp;
+ }
+ secret_key = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
+ if (secret_key == NULL) {
+ BIO_printf(bio_err, "Invalid key %s\n", opt_arg());
+ goto end;
+ }
+ secret_keylen = (size_t)ltmp;
+ break;
+ case OPT_SECRETKEYID:
+ if (secret_keyid != NULL) {
+ BIO_printf(bio_err, "Invalid id (supplied twice) %s\n",
+ opt_arg());
+ goto opthelp;
+ }
+ secret_keyid = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
+ if (secret_keyid == NULL) {
+ BIO_printf(bio_err, "Invalid id %s\n", opt_arg());
+ goto opthelp;
+ }
+ secret_keyidlen = (size_t)ltmp;
+ break;
+ case OPT_PWRI_PASSWORD:
+ pwri_pass = (unsigned char *)opt_arg();
+ break;
+ case OPT_ECONTENT_TYPE:
+ if (econtent_type != NULL) {
+ BIO_printf(bio_err, "Invalid OID (supplied twice) %s\n",
+ opt_arg());
+ goto opthelp;
+ }
+ econtent_type = OBJ_txt2obj(opt_arg(), 0);
+ if (econtent_type == NULL) {
+ BIO_printf(bio_err, "Invalid OID %s\n", opt_arg());
+ goto opthelp;
+ }
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_TO:
+ to = opt_arg();
+ break;
+ case OPT_FROM:
+ from = opt_arg();
+ break;
+ case OPT_SUBJECT:
+ subject = opt_arg();
+ break;
+ case OPT_CERTSOUT:
+ certsoutfile = opt_arg();
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_arg(), &sign_md))
+ goto end;
+ break;
+ case OPT_SIGNER:
+ /* If previous -signer argument add signer to list */
+ if (signerfile != NULL) {
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (keyfile == NULL)
+ keyfile = signerfile;
+ if (skkeys == NULL
+ && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ keyfile = NULL;
+ }
+ signerfile = opt_arg();
+ break;
+ case OPT_INKEY:
+ /* If previous -inkey argument add signer to list */
+ if (keyfile != NULL) {
+ if (signerfile == NULL) {
+ BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+ goto end;
+ }
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ signerfile = NULL;
+ if (skkeys == NULL
+ && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ }
+ keyfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
+ goto opthelp;
+ break;
+ case OPT_RECIP:
+ if (operation == SMIME_ENCRYPT) {
+ if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
+ goto end;
+ cert = load_cert(opt_arg(), FORMAT_PEM,
+ "recipient certificate file");
+ if (cert == NULL)
+ goto end;
+ sk_X509_push(encerts, cert);
+ cert = NULL;
+ } else {
+ recipfile = opt_arg();
+ }
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &cipher))
+ goto end;
+ break;
+ case OPT_KEYOPT:
+ keyidx = -1;
+ if (operation == SMIME_ENCRYPT) {
+ if (encerts != NULL)
+ keyidx += sk_X509_num(encerts);
+ } else {
+ if (keyfile != NULL || signerfile != NULL)
+ keyidx++;
+ if (skkeys != NULL)
+ keyidx += sk_OPENSSL_STRING_num(skkeys);
+ }
+ if (keyidx < 0) {
+ BIO_printf(bio_err, "No key specified\n");
+ goto opthelp;
+ }
+ if (key_param == NULL || key_param->idx != keyidx) {
+ cms_key_param *nparam;
+ nparam = app_malloc(sizeof(*nparam), "key param buffer");
+ nparam->idx = keyidx;
+ if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ nparam->next = NULL;
+ if (key_first == NULL)
+ key_first = nparam;
+ else
+ key_param->next = nparam;
+ key_param = nparam;
+ }
+ sk_OPENSSL_STRING_push(key_param->param, opt_arg());
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_3DES_WRAP:
+# ifndef OPENSSL_NO_DES
+ wrap_cipher = EVP_des_ede3_wrap();
+# endif
+ break;
+ case OPT_AES128_WRAP:
+ wrap_cipher = EVP_aes_128_wrap();
+ break;
+ case OPT_AES192_WRAP:
+ wrap_cipher = EVP_aes_192_wrap();
+ break;
+ case OPT_AES256_WRAP:
+ wrap_cipher = EVP_aes_256_wrap();
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) {
+ BIO_puts(bio_err, "No Signed Receipts Recipients\n");
+ goto opthelp;
+ }
+
+ if (!(operation & SMIME_SIGNERS) && (rr_to != NULL || rr_from != NULL)) {
+ BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
+ goto opthelp;
+ }
+ if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
+ BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
+ goto opthelp;
+ }
+
+ if (operation & SMIME_SIGNERS) {
+ if (keyfile != NULL && signerfile == NULL) {
+ BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+ goto opthelp;
+ }
+ /* Check to see if any final signer needs to be appended */
+ if (signerfile != NULL) {
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ if (keyfile == NULL)
+ keyfile = signerfile;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ }
+ if (sksigners == NULL) {
+ BIO_printf(bio_err, "No signer certificate specified\n");
+ goto opthelp;
+ }
+ signerfile = NULL;
+ keyfile = NULL;
+ } else if (operation == SMIME_DECRYPT) {
+ if (recipfile == NULL && keyfile == NULL
+ && secret_key == NULL && pwri_pass == NULL) {
+ BIO_printf(bio_err,
+ "No recipient certificate or key specified\n");
+ goto opthelp;
+ }
+ } else if (operation == SMIME_ENCRYPT) {
+ if (*argv == NULL && secret_key == NULL
+ && pwri_pass == NULL && encerts == NULL) {
+ BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
+ goto opthelp;
+ }
+ } else if (!operation) {
+ goto opthelp;
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ ret = 2;
+
+ if (!(operation & SMIME_SIGNERS))
+ flags &= ~CMS_DETACHED;
+
+ if (!(operation & SMIME_OP))
+ if (flags & CMS_BINARY)
+ outformat = FORMAT_BINARY;
+
+ if (!(operation & SMIME_IP))
+ if (flags & CMS_BINARY)
+ informat = FORMAT_BINARY;
+
+ if (operation == SMIME_ENCRYPT) {
+ if (!cipher) {
+# ifndef OPENSSL_NO_DES
+ cipher = EVP_des_ede3_cbc();
+# else
+ BIO_printf(bio_err, "No cipher selected\n");
+ goto end;
+# endif
+ }
+
+ if (secret_key && !secret_keyid) {
+ BIO_printf(bio_err, "No secret key id\n");
+ goto end;
+ }
+
+ if (*argv && encerts == NULL)
+ if ((encerts = sk_X509_new_null()) == NULL)
+ goto end;
+ while (*argv) {
+ if ((cert = load_cert(*argv, FORMAT_PEM,
+ "recipient certificate file")) == NULL)
+ goto end;
+ sk_X509_push(encerts, cert);
+ cert = NULL;
+ argv++;
+ }
+ }
+
+ if (certfile != NULL) {
+ if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
+ "certificate file")) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
+ if ((recip = load_cert(recipfile, FORMAT_PEM,
+ "recipient certificate file")) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (operation == SMIME_SIGN_RECEIPT) {
+ if ((signer = load_cert(signerfile, FORMAT_PEM,
+ "receipt signer certificate file")) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (operation == SMIME_DECRYPT) {
+ if (keyfile == NULL)
+ keyfile = recipfile;
+ } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
+ if (keyfile == NULL)
+ keyfile = signerfile;
+ } else {
+ keyfile = NULL;
+ }
+
+ if (keyfile != NULL) {
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ if (key == NULL)
+ goto end;
+ }
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (operation & SMIME_IP) {
+ if (informat == FORMAT_SMIME) {
+ cms = SMIME_read_CMS(in, &indata);
+ } else if (informat == FORMAT_PEM) {
+ cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
+ } else if (informat == FORMAT_ASN1) {
+ cms = d2i_CMS_bio(in, NULL);
+ } else {
+ BIO_printf(bio_err, "Bad input format for CMS file\n");
+ goto end;
+ }
+
+ if (cms == NULL) {
+ BIO_printf(bio_err, "Error reading S/MIME message\n");
+ goto end;
+ }
+ if (contfile != NULL) {
+ BIO_free(indata);
+ if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
+ BIO_printf(bio_err, "Can't read content file %s\n", contfile);
+ goto end;
+ }
+ }
+ if (certsoutfile != NULL) {
+ STACK_OF(X509) *allcerts;
+ allcerts = CMS_get1_certs(cms);
+ if (!save_certs(certsoutfile, allcerts)) {
+ BIO_printf(bio_err,
+ "Error writing certs to %s\n", certsoutfile);
+ ret = 5;
+ goto end;
+ }
+ sk_X509_pop_free(allcerts, X509_free);
+ }
+ }
+
+ if (rctfile != NULL) {
+ char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
+ if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
+ BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
+ goto end;
+ }
+
+ if (rctformat == FORMAT_SMIME) {
+ rcms = SMIME_read_CMS(rctin, NULL);
+ } else if (rctformat == FORMAT_PEM) {
+ rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
+ } else if (rctformat == FORMAT_ASN1) {
+ rcms = d2i_CMS_bio(rctin, NULL);
+ } else {
+ BIO_printf(bio_err, "Bad input format for receipt\n");
+ goto end;
+ }
+
+ if (rcms == NULL) {
+ BIO_printf(bio_err, "Error reading receipt\n");
+ goto end;
+ }
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
+ if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ goto end;
+ X509_STORE_set_verify_cb(store, cms_cb);
+ if (vpmtouched)
+ X509_STORE_set1_param(store, vpm);
+ }
+
+ ret = 3;
+
+ if (operation == SMIME_DATA_CREATE) {
+ cms = CMS_data_create(in, flags);
+ } else if (operation == SMIME_DIGEST_CREATE) {
+ cms = CMS_digest_create(in, sign_md, flags);
+ } else if (operation == SMIME_COMPRESS) {
+ cms = CMS_compress(in, -1, flags);
+ } else if (operation == SMIME_ENCRYPT) {
+ int i;
+ flags |= CMS_PARTIAL;
+ cms = CMS_encrypt(NULL, in, cipher, flags);
+ if (cms == NULL)
+ goto end;
+ for (i = 0; i < sk_X509_num(encerts); i++) {
+ CMS_RecipientInfo *ri;
+ cms_key_param *kparam;
+ int tflags = flags;
+ X509 *x = sk_X509_value(encerts, i);
+ for (kparam = key_first; kparam; kparam = kparam->next) {
+ if (kparam->idx == i) {
+ tflags |= CMS_KEY_PARAM;
+ break;
+ }
+ }
+ ri = CMS_add1_recipient_cert(cms, x, tflags);
+ if (ri == NULL)
+ goto end;
+ if (kparam != NULL) {
+ EVP_PKEY_CTX *pctx;
+ pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+ if (!cms_set_pkey_param(pctx, kparam->param))
+ goto end;
+ }
+ if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
+ && wrap_cipher) {
+ EVP_CIPHER_CTX *wctx;
+ wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+ EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
+ }
+ }
+
+ if (secret_key != NULL) {
+ if (!CMS_add0_recipient_key(cms, NID_undef,
+ secret_key, secret_keylen,
+ secret_keyid, secret_keyidlen,
+ NULL, NULL, NULL))
+ goto end;
+ /* NULL these because call absorbs them */
+ secret_key = NULL;
+ secret_keyid = NULL;
+ }
+ if (pwri_pass != NULL) {
+ pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass);
+ if (pwri_tmp == NULL)
+ goto end;
+ if (CMS_add0_recipient_password(cms,
+ -1, NID_undef, NID_undef,
+ pwri_tmp, -1, NULL) == NULL)
+ goto end;
+ pwri_tmp = NULL;
+ }
+ if (!(flags & CMS_STREAM)) {
+ if (!CMS_final(cms, in, NULL, flags))
+ goto end;
+ }
+ } else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
+ cms = CMS_EncryptedData_encrypt(in, cipher,
+ secret_key, secret_keylen, flags);
+
+ } else if (operation == SMIME_SIGN_RECEIPT) {
+ CMS_ContentInfo *srcms = NULL;
+ STACK_OF(CMS_SignerInfo) *sis;
+ CMS_SignerInfo *si;
+ sis = CMS_get0_SignerInfos(cms);
+ if (sis == NULL)
+ goto end;
+ si = sk_CMS_SignerInfo_value(sis, 0);
+ srcms = CMS_sign_receipt(si, signer, key, other, flags);
+ if (srcms == NULL)
+ goto end;
+ CMS_ContentInfo_free(cms);
+ cms = srcms;
+ } else if (operation & SMIME_SIGNERS) {
+ int i;
+ /*
+ * If detached data content we enable streaming if S/MIME output
+ * format.
+ */
+ if (operation == SMIME_SIGN) {
+
+ if (flags & CMS_DETACHED) {
+ if (outformat == FORMAT_SMIME)
+ flags |= CMS_STREAM;
+ }
+ flags |= CMS_PARTIAL;
+ cms = CMS_sign(NULL, NULL, other, in, flags);
+ if (cms == NULL)
+ goto end;
+ if (econtent_type != NULL)
+ CMS_set1_eContentType(cms, econtent_type);
+
+ if (rr_to != NULL) {
+ rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
+ if (rr == NULL) {
+ BIO_puts(bio_err,
+ "Signed Receipt Request Creation Error\n");
+ goto end;
+ }
+ }
+ } else {
+ flags |= CMS_REUSE_DIGEST;
+ }
+ for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
+ CMS_SignerInfo *si;
+ cms_key_param *kparam;
+ int tflags = flags;
+ signerfile = sk_OPENSSL_STRING_value(sksigners, i);
+ keyfile = sk_OPENSSL_STRING_value(skkeys, i);
+
+ signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
+ if (signer == NULL) {
+ ret = 2;
+ goto end;
+ }
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ if (key == NULL) {
+ ret = 2;
+ goto end;
+ }
+ for (kparam = key_first; kparam; kparam = kparam->next) {
+ if (kparam->idx == i) {
+ tflags |= CMS_KEY_PARAM;
+ break;
+ }
+ }
+ si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
+ if (si == NULL)
+ goto end;
+ if (kparam != NULL) {
+ EVP_PKEY_CTX *pctx;
+ pctx = CMS_SignerInfo_get0_pkey_ctx(si);
+ if (!cms_set_pkey_param(pctx, kparam->param))
+ goto end;
+ }
+ if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
+ goto end;
+ X509_free(signer);
+ signer = NULL;
+ EVP_PKEY_free(key);
+ key = NULL;
+ }
+ /* If not streaming or resigning finalize structure */
+ if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
+ if (!CMS_final(cms, in, NULL, flags))
+ goto end;
+ }
+ }
+
+ if (cms == NULL) {
+ BIO_printf(bio_err, "Error creating CMS structure\n");
+ goto end;
+ }
+
+ ret = 4;
+ if (operation == SMIME_DECRYPT) {
+ if (flags & CMS_DEBUG_DECRYPT)
+ CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);
+
+ if (secret_key != NULL) {
+ if (!CMS_decrypt_set1_key(cms,
+ secret_key, secret_keylen,
+ secret_keyid, secret_keyidlen)) {
+ BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
+ goto end;
+ }
+ }
+
+ if (key != NULL) {
+ if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
+ BIO_puts(bio_err, "Error decrypting CMS using private key\n");
+ goto end;
+ }
+ }
+
+ if (pwri_pass != NULL) {
+ if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
+ BIO_puts(bio_err, "Error decrypting CMS using password\n");
+ goto end;
+ }
+ }
+
+ if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
+ BIO_printf(bio_err, "Error decrypting CMS structure\n");
+ goto end;
+ }
+ } else if (operation == SMIME_DATAOUT) {
+ if (!CMS_data(cms, out, flags))
+ goto end;
+ } else if (operation == SMIME_UNCOMPRESS) {
+ if (!CMS_uncompress(cms, indata, out, flags))
+ goto end;
+ } else if (operation == SMIME_DIGEST_VERIFY) {
+ if (CMS_digest_verify(cms, indata, out, flags) > 0) {
+ BIO_printf(bio_err, "Verification successful\n");
+ } else {
+ BIO_printf(bio_err, "Verification failure\n");
+ goto end;
+ }
+ } else if (operation == SMIME_ENCRYPTED_DECRYPT) {
+ if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
+ indata, out, flags))
+ goto end;
+ } else if (operation == SMIME_VERIFY) {
+ if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
+ BIO_printf(bio_err, "Verification successful\n");
+ } else {
+ BIO_printf(bio_err, "Verification failure\n");
+ if (verify_retcode)
+ ret = verify_err + 32;
+ goto end;
+ }
+ if (signerfile != NULL) {
+ STACK_OF(X509) *signers;
+ signers = CMS_get0_signers(cms);
+ if (!save_certs(signerfile, signers)) {
+ BIO_printf(bio_err,
+ "Error writing signers to %s\n", signerfile);
+ ret = 5;
+ goto end;
+ }
+ sk_X509_free(signers);
+ }
+ if (rr_print)
+ receipt_request_print(cms);
+
+ } else if (operation == SMIME_VERIFY_RECEIPT) {
+ if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) {
+ BIO_printf(bio_err, "Verification successful\n");
+ } else {
+ BIO_printf(bio_err, "Verification failure\n");
+ goto end;
+ }
+ } else {
+ if (noout) {
+ if (print)
+ CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
+ } else if (outformat == FORMAT_SMIME) {
+ if (to)
+ BIO_printf(out, "To: %s%s", to, mime_eol);
+ if (from)
+ BIO_printf(out, "From: %s%s", from, mime_eol);
+ if (subject)
+ BIO_printf(out, "Subject: %s%s", subject, mime_eol);
+ if (operation == SMIME_RESIGN)
+ ret = SMIME_write_CMS(out, cms, indata, flags);
+ else
+ ret = SMIME_write_CMS(out, cms, in, flags);
+ } else if (outformat == FORMAT_PEM) {
+ ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
+ } else if (outformat == FORMAT_ASN1) {
+ ret = i2d_CMS_bio_stream(out, cms, in, flags);
+ } else {
+ BIO_printf(bio_err, "Bad output format for CMS file\n");
+ goto end;
+ }
+ if (ret <= 0) {
+ ret = 6;
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ if (ret)
+ ERR_print_errors(bio_err);
+ sk_X509_pop_free(encerts, X509_free);
+ sk_X509_pop_free(other, X509_free);
+ X509_VERIFY_PARAM_free(vpm);
+ sk_OPENSSL_STRING_free(sksigners);
+ sk_OPENSSL_STRING_free(skkeys);
+ OPENSSL_free(secret_key);
+ OPENSSL_free(secret_keyid);
+ OPENSSL_free(pwri_tmp);
+ ASN1_OBJECT_free(econtent_type);
+ CMS_ReceiptRequest_free(rr);
+ sk_OPENSSL_STRING_free(rr_to);
+ sk_OPENSSL_STRING_free(rr_from);
+ for (key_param = key_first; key_param;) {
+ cms_key_param *tparam;
+ sk_OPENSSL_STRING_free(key_param->param);
+ tparam = key_param->next;
+ OPENSSL_free(key_param);
+ key_param = tparam;
+ }
+ X509_STORE_free(store);
+ X509_free(cert);
+ X509_free(recip);
+ X509_free(signer);
+ EVP_PKEY_free(key);
+ CMS_ContentInfo_free(cms);
+ CMS_ContentInfo_free(rcms);
+ release_engine(e);
+ BIO_free(rctin);
+ BIO_free(in);
+ BIO_free(indata);
+ BIO_free_all(out);
+ OPENSSL_free(passin);
+ return ret;
+}
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers)
+{
+ int i;
+ BIO *tmp;
+ if (signerfile == NULL)
+ return 1;
+ tmp = BIO_new_file(signerfile, "w");
+ if (tmp == NULL)
+ return 0;
+ for (i = 0; i < sk_X509_num(signers); i++)
+ PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
+ BIO_free(tmp);
+ return 1;
+}
+
+/* Minimal callback just to output policy info (if any) */
+
+static int cms_cb(int ok, X509_STORE_CTX *ctx)
+{
+ int error;
+
+ error = X509_STORE_CTX_get_error(ctx);
+
+ verify_err = error;
+
+ if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
+ && ((error != X509_V_OK) || (ok != 2)))
+ return ok;
+
+ policies_print(ctx);
+
+ return ok;
+
+}
+
+static void gnames_stack_print(STACK_OF(GENERAL_NAMES) *gns)
+{
+ STACK_OF(GENERAL_NAME) *gens;
+ GENERAL_NAME *gen;
+ int i, j;
+
+ for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
+ gens = sk_GENERAL_NAMES_value(gns, i);
+ for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
+ gen = sk_GENERAL_NAME_value(gens, j);
+ BIO_puts(bio_err, " ");
+ GENERAL_NAME_print(bio_err, gen);
+ BIO_puts(bio_err, "\n");
+ }
+ }
+ return;
+}
+
+static void receipt_request_print(CMS_ContentInfo *cms)
+{
+ STACK_OF(CMS_SignerInfo) *sis;
+ CMS_SignerInfo *si;
+ CMS_ReceiptRequest *rr;
+ int allorfirst;
+ STACK_OF(GENERAL_NAMES) *rto, *rlist;
+ ASN1_STRING *scid;
+ int i, rv;
+ sis = CMS_get0_SignerInfos(cms);
+ for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
+ si = sk_CMS_SignerInfo_value(sis, i);
+ rv = CMS_get1_ReceiptRequest(si, &rr);
+ BIO_printf(bio_err, "Signer %d:\n", i + 1);
+ if (rv == 0) {
+ BIO_puts(bio_err, " No Receipt Request\n");
+ } else if (rv < 0) {
+ BIO_puts(bio_err, " Receipt Request Parse Error\n");
+ ERR_print_errors(bio_err);
+ } else {
+ const char *id;
+ int idlen;
+ CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
+ &rlist, &rto);
+ BIO_puts(bio_err, " Signed Content ID:\n");
+ idlen = ASN1_STRING_length(scid);
+ id = (const char *)ASN1_STRING_get0_data(scid);
+ BIO_dump_indent(bio_err, id, idlen, 4);
+ BIO_puts(bio_err, " Receipts From");
+ if (rlist != NULL) {
+ BIO_puts(bio_err, " List:\n");
+ gnames_stack_print(rlist);
+ } else if (allorfirst == 1) {
+ BIO_puts(bio_err, ": First Tier\n");
+ } else if (allorfirst == 0) {
+ BIO_puts(bio_err, ": All\n");
+ } else {
+ BIO_printf(bio_err, " Unknown (%d)\n", allorfirst);
+ }
+ BIO_puts(bio_err, " Receipts To:\n");
+ gnames_stack_print(rto);
+ }
+ CMS_ReceiptRequest_free(rr);
+ }
+}
+
+static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
+{
+ int i;
+ STACK_OF(GENERAL_NAMES) *ret;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ret = sk_GENERAL_NAMES_new_null();
+ if (ret == NULL)
+ goto err;
+ for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
+ char *str = sk_OPENSSL_STRING_value(ns, i);
+ gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
+ if (gen == NULL)
+ goto err;
+ gens = GENERAL_NAMES_new();
+ if (gens == NULL)
+ goto err;
+ if (!sk_GENERAL_NAME_push(gens, gen))
+ goto err;
+ gen = NULL;
+ if (!sk_GENERAL_NAMES_push(ret, gens))
+ goto err;
+ gens = NULL;
+ }
+
+ return ret;
+
+ err:
+ sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
+ GENERAL_NAMES_free(gens);
+ GENERAL_NAME_free(gen);
+ return NULL;
+}
+
+static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
+ *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
+ *rr_from)
+{
+ STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
+ CMS_ReceiptRequest *rr;
+ rct_to = make_names_stack(rr_to);
+ if (rct_to == NULL)
+ goto err;
+ if (rr_from != NULL) {
+ rct_from = make_names_stack(rr_from);
+ if (rct_from == NULL)
+ goto err;
+ } else {
+ rct_from = NULL;
+ }
+ rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
+ rct_to);
+ return rr;
+ err:
+ sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
+ return NULL;
+}
+
+static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
+ STACK_OF(OPENSSL_STRING) *param)
+{
+ char *keyopt;
+ int i;
+ if (sk_OPENSSL_STRING_num(param) <= 0)
+ return 1;
+ for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
+ keyopt = sk_OPENSSL_STRING_value(param, i);
+ if (pkey_ctrl_string(pctx, keyopt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif
diff --git a/freebsd/crypto/openssl/apps/crl.c b/freebsd/crypto/openssl/apps/crl.c
new file mode 100644
index 00000000..54a879d9
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/crl.c
@@ -0,0 +1,344 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY,
+ OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT,
+ OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE,
+ OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD,
+ OPT_NOOUT, OPT_NAMEOPT, OPT_MD
+} OPTION_CHOICE;
+
+const OPTIONS crl_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format; default PEM"},
+ {"in", OPT_IN, '<', "Input file - default stdin"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+ {"out", OPT_OUT, '>', "output file - default stdout"},
+ {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"},
+ {"key", OPT_KEY, '<', "CRL signing Private key to use"},
+ {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
+ {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"},
+ {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"},
+ {"noout", OPT_NOOUT, '-', "No CRL output"},
+ {"fingerprint", OPT_FINGERPRINT, '-', "Print the crl fingerprint"},
+ {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"},
+ {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" },
+ {"gendelta", OPT_GENDELTA, '<', "Other CRL to compare/diff to the Input one"},
+ {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"},
+ {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"verify", OPT_VERIFY, '-', "Verify CRL signature"},
+ {"text", OPT_TEXT, '-', "Print out a text format version"},
+ {"hash", OPT_HASH, '-', "Print hash value"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_MD5
+ {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"},
+#endif
+ {NULL}
+};
+
+int crl_main(int argc, char **argv)
+{
+ X509_CRL *x = NULL;
+ BIO *out = NULL;
+ X509_STORE *store = NULL;
+ X509_STORE_CTX *ctx = NULL;
+ X509_LOOKUP *lookup = NULL;
+ X509_OBJECT *xobj = NULL;
+ EVP_PKEY *pkey;
+ const EVP_MD *digest = EVP_sha1();
+ char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *prog;
+ OPTION_CHOICE o;
+ int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
+ int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
+ int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
+ int i;
+#ifndef OPENSSL_NO_MD5
+ int hash_old = 0;
+#endif
+
+ prog = opt_init(argc, argv, crl_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(crl_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
+ goto opthelp;
+ break;
+ case OPT_KEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_GENDELTA:
+ crldiff = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ do_ver = 1;
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ do_ver = 1;
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_HASH_OLD:
+#ifndef OPENSSL_NO_MD5
+ hash_old = ++num;
+#endif
+ break;
+ case OPT_VERIFY:
+ do_ver = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_HASH:
+ hash = ++num;
+ break;
+ case OPT_ISSUER:
+ issuer = ++num;
+ break;
+ case OPT_LASTUPDATE:
+ lastupdate = ++num;
+ break;
+ case OPT_NEXTUPDATE:
+ nextupdate = ++num;
+ break;
+ case OPT_NOOUT:
+ noout = ++num;
+ break;
+ case OPT_FINGERPRINT:
+ fingerprint = ++num;
+ break;
+ case OPT_CRLNUMBER:
+ crlnumber = ++num;
+ break;
+ case OPT_BADSIG:
+ badsig = 1;
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_unknown(), &digest))
+ goto opthelp;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ x = load_crl(infile, informat);
+ if (x == NULL)
+ goto end;
+
+ if (do_ver) {
+ if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ goto end;
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if (lookup == NULL)
+ goto end;
+ ctx = X509_STORE_CTX_new();
+ if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
+ BIO_printf(bio_err, "Error initialising X509 store\n");
+ goto end;
+ }
+
+ xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509,
+ X509_CRL_get_issuer(x));
+ if (xobj == NULL) {
+ BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
+ goto end;
+ }
+ pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
+ X509_OBJECT_free(xobj);
+ if (!pkey) {
+ BIO_printf(bio_err, "Error getting CRL issuer public key\n");
+ goto end;
+ }
+ i = X509_CRL_verify(x, pkey);
+ EVP_PKEY_free(pkey);
+ if (i < 0)
+ goto end;
+ if (i == 0)
+ BIO_printf(bio_err, "verify failure\n");
+ else
+ BIO_printf(bio_err, "verify OK\n");
+ }
+
+ if (crldiff) {
+ X509_CRL *newcrl, *delta;
+ if (!keyfile) {
+ BIO_puts(bio_err, "Missing CRL signing key\n");
+ goto end;
+ }
+ newcrl = load_crl(crldiff, informat);
+ if (!newcrl)
+ goto end;
+ pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
+ if (!pkey) {
+ X509_CRL_free(newcrl);
+ goto end;
+ }
+ delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
+ X509_CRL_free(newcrl);
+ EVP_PKEY_free(pkey);
+ if (delta) {
+ X509_CRL_free(x);
+ x = delta;
+ } else {
+ BIO_puts(bio_err, "Error creating delta CRL\n");
+ goto end;
+ }
+ }
+
+ if (badsig) {
+ const ASN1_BIT_STRING *sig;
+
+ X509_CRL_get0_signature(x, &sig, NULL);
+ corrupt_signature(sig);
+ }
+
+ if (num) {
+ for (i = 1; i <= num; i++) {
+ if (issuer == i) {
+ print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
+ get_nameopt());
+ }
+ if (crlnumber == i) {
+ ASN1_INTEGER *crlnum;
+ crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
+ BIO_printf(bio_out, "crlNumber=");
+ if (crlnum) {
+ i2a_ASN1_INTEGER(bio_out, crlnum);
+ ASN1_INTEGER_free(crlnum);
+ } else
+ BIO_puts(bio_out, "<NONE>");
+ BIO_printf(bio_out, "\n");
+ }
+ if (hash == i) {
+ BIO_printf(bio_out, "%08lx\n",
+ X509_NAME_hash(X509_CRL_get_issuer(x)));
+ }
+#ifndef OPENSSL_NO_MD5
+ if (hash_old == i) {
+ BIO_printf(bio_out, "%08lx\n",
+ X509_NAME_hash_old(X509_CRL_get_issuer(x)));
+ }
+#endif
+ if (lastupdate == i) {
+ BIO_printf(bio_out, "lastUpdate=");
+ ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x));
+ BIO_printf(bio_out, "\n");
+ }
+ if (nextupdate == i) {
+ BIO_printf(bio_out, "nextUpdate=");
+ if (X509_CRL_get0_nextUpdate(x))
+ ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x));
+ else
+ BIO_printf(bio_out, "NONE");
+ BIO_printf(bio_out, "\n");
+ }
+ if (fingerprint == i) {
+ int j;
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
+
+ if (!X509_CRL_digest(x, digest, md, &n)) {
+ BIO_printf(bio_err, "out of memory\n");
+ goto end;
+ }
+ BIO_printf(bio_out, "%s Fingerprint=",
+ OBJ_nid2sn(EVP_MD_type(digest)));
+ for (j = 0; j < (int)n; j++) {
+ BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
+ ? '\n' : ':');
+ }
+ }
+ }
+ }
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (text)
+ X509_CRL_print_ex(out, x, get_nameopt());
+
+ if (noout) {
+ ret = 0;
+ goto end;
+ }
+
+ if (outformat == FORMAT_ASN1)
+ i = (int)i2d_X509_CRL_bio(out, x);
+ else
+ i = PEM_write_bio_X509_CRL(out, x);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write CRL\n");
+ goto end;
+ }
+ ret = 0;
+
+ end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ BIO_free_all(out);
+ X509_CRL_free(x);
+ X509_STORE_CTX_free(ctx);
+ X509_STORE_free(store);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/crl2p7.c b/freebsd/crypto/openssl/apps/crl2p7.c
new file mode 100644
index 00000000..8108e23a
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/crl2p7.c
@@ -0,0 +1,219 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pem.h>
+#include <openssl/objects.h>
+
+static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE
+} OPTION_CHOICE;
+
+const OPTIONS crl2pkcs7_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"},
+ {"certfile", OPT_CERTFILE, '<',
+ "File of chain of certs to a trusted CA; can be repeated"},
+ {NULL}
+};
+
+int crl2pkcs7_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ PKCS7 *p7 = NULL;
+ PKCS7_SIGNED *p7s = NULL;
+ STACK_OF(OPENSSL_STRING) *certflst = NULL;
+ STACK_OF(X509) *cert_stack = NULL;
+ STACK_OF(X509_CRL) *crl_stack = NULL;
+ X509_CRL *crl = NULL;
+ char *infile = NULL, *outfile = NULL, *prog, *certfile;
+ int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl =
+ 0;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, crl2pkcs7_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(crl2pkcs7_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_NOCRL:
+ nocrl = 1;
+ break;
+ case OPT_CERTFILE:
+ if ((certflst == NULL)
+ && (certflst = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ if (!sk_OPENSSL_STRING_push(certflst, opt_arg()))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (!nocrl) {
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (informat == FORMAT_ASN1)
+ crl = d2i_X509_CRL_bio(in, NULL);
+ else if (informat == FORMAT_PEM)
+ crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+ if (crl == NULL) {
+ BIO_printf(bio_err, "unable to load CRL\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if ((p7 = PKCS7_new()) == NULL)
+ goto end;
+ if ((p7s = PKCS7_SIGNED_new()) == NULL)
+ goto end;
+ p7->type = OBJ_nid2obj(NID_pkcs7_signed);
+ p7->d.sign = p7s;
+ p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data);
+
+ if (!ASN1_INTEGER_set(p7s->version, 1))
+ goto end;
+ if ((crl_stack = sk_X509_CRL_new_null()) == NULL)
+ goto end;
+ p7s->crl = crl_stack;
+ if (crl != NULL) {
+ sk_X509_CRL_push(crl_stack, crl);
+ crl = NULL; /* now part of p7 for OPENSSL_freeing */
+ }
+
+ if ((cert_stack = sk_X509_new_null()) == NULL)
+ goto end;
+ p7s->cert = cert_stack;
+
+ if (certflst != NULL)
+ for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) {
+ certfile = sk_OPENSSL_STRING_value(certflst, i);
+ if (add_certs_from_file(cert_stack, certfile) < 0) {
+ BIO_printf(bio_err, "error loading certificates\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (outformat == FORMAT_ASN1)
+ i = i2d_PKCS7_bio(out, p7);
+ else if (outformat == FORMAT_PEM)
+ i = PEM_write_bio_PKCS7(out, p7);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write pkcs7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ end:
+ sk_OPENSSL_STRING_free(certflst);
+ BIO_free(in);
+ BIO_free_all(out);
+ PKCS7_free(p7);
+ X509_CRL_free(crl);
+
+ return ret;
+}
+
+/*-
+ *----------------------------------------------------------------------
+ * int add_certs_from_file
+ *
+ * Read a list of certificates to be checked from a file.
+ *
+ * Results:
+ * number of certs added if successful, -1 if not.
+ *----------------------------------------------------------------------
+ */
+static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile)
+{
+ BIO *in = NULL;
+ int count = 0;
+ int ret = -1;
+ STACK_OF(X509_INFO) *sk = NULL;
+ X509_INFO *xi;
+
+ in = BIO_new_file(certfile, "r");
+ if (in == NULL) {
+ BIO_printf(bio_err, "error opening the file, %s\n", certfile);
+ goto end;
+ }
+
+ /* This loads from a file, a stack of x509/crl/pkey sets */
+ sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+ if (sk == NULL) {
+ BIO_printf(bio_err, "error reading the file, %s\n", certfile);
+ goto end;
+ }
+
+ /* scan over it and pull out the CRL's */
+ while (sk_X509_INFO_num(sk)) {
+ xi = sk_X509_INFO_shift(sk);
+ if (xi->x509 != NULL) {
+ sk_X509_push(stack, xi->x509);
+ xi->x509 = NULL;
+ count++;
+ }
+ X509_INFO_free(xi);
+ }
+
+ ret = count;
+ end:
+ /* never need to OPENSSL_free x */
+ BIO_free(in);
+ sk_X509_INFO_free(sk);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/dgst.c b/freebsd/crypto/openssl/apps/dgst.c
new file mode 100644
index 00000000..fb4e6643
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/dgst.c
@@ -0,0 +1,494 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#undef BUFSIZE
+#define BUFSIZE 1024*8
+
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+ EVP_PKEY *key, unsigned char *sigin, int siglen,
+ const char *sig_name, const char *md_name,
+ const char *file);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
+ OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
+ OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
+ OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
+ OPT_DIGEST,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS dgst_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
+ {OPT_HELP_STR, 1, '-',
+ " file... files to digest (default is stdin)\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"c", OPT_C, '-', "Print the digest with separating colons"},
+ {"r", OPT_R, '-', "Print the digest in coreutils format"},
+ {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"sign", OPT_SIGN, 's', "Sign digest using private key"},
+ {"verify", OPT_VERIFY, 's',
+ "Verify a signature using public key"},
+ {"prverify", OPT_PRVERIFY, 's',
+ "Verify a signature using private key"},
+ {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"},
+ {"hex", OPT_HEX, '-', "Print as hex dump"},
+ {"binary", OPT_BINARY, '-', "Print in binary form"},
+ {"d", OPT_DEBUG, '-', "Print debug info"},
+ {"debug", OPT_DEBUG, '-', "Print debug info"},
+ {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
+ "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
+ {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
+ {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
+ {"", OPT_DIGEST, '-', "Any supported digest"},
+ OPT_R_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+ {"engine_impl", OPT_ENGINE_IMPL, '-',
+ "Also use engine given by -engine for digest operations"},
+#endif
+ {NULL}
+};
+
+int dgst_main(int argc, char **argv)
+{
+ BIO *in = NULL, *inp, *bmd = NULL, *out = NULL;
+ ENGINE *e = NULL, *impl = NULL;
+ EVP_PKEY *sigkey = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
+ char *hmac_key = NULL;
+ char *mac_name = NULL;
+ char *passinarg = NULL, *passin = NULL;
+ const EVP_MD *md = NULL, *m;
+ const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
+ const char *sigfile = NULL;
+ OPTION_CHOICE o;
+ int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0;
+ int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0;
+ unsigned char *buf = NULL, *sigbuf = NULL;
+ int engine_impl = 0;
+
+ prog = opt_progname(argv[0]);
+ buf = app_malloc(BUFSIZE, "I/O buffer");
+ md = EVP_get_digestbyname(prog);
+
+ prog = opt_init(argc, argv, dgst_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(dgst_options);
+ ret = 0;
+ goto end;
+ case OPT_C:
+ separator = 1;
+ break;
+ case OPT_R:
+ separator = 2;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_SIGN:
+ keyfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_VERIFY:
+ keyfile = opt_arg();
+ want_pub = do_verify = 1;
+ break;
+ case OPT_PRVERIFY:
+ keyfile = opt_arg();
+ do_verify = 1;
+ break;
+ case OPT_SIGNATURE:
+ sigfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
+ goto opthelp;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_ENGINE_IMPL:
+ engine_impl = 1;
+ break;
+ case OPT_HEX:
+ out_bin = 0;
+ break;
+ case OPT_BINARY:
+ out_bin = 1;
+ break;
+ case OPT_DEBUG:
+ debug = 1;
+ break;
+ case OPT_FIPS_FINGERPRINT:
+ hmac_key = "etaonrishdlcupfm";
+ break;
+ case OPT_HMAC:
+ hmac_key = opt_arg();
+ break;
+ case OPT_MAC:
+ mac_name = opt_arg();
+ break;
+ case OPT_SIGOPT:
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_MACOPT:
+ if (!macopts)
+ macopts = sk_OPENSSL_STRING_new_null();
+ if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_DIGEST:
+ if (!opt_md(opt_unknown(), &m))
+ goto opthelp;
+ md = m;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (keyfile != NULL && argc > 1) {
+ BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
+ goto end;
+ }
+
+ if (do_verify && sigfile == NULL) {
+ BIO_printf(bio_err,
+ "No signature to verify: use the -signature option\n");
+ goto end;
+ }
+ if (engine_impl)
+ impl = e;
+
+ in = BIO_new(BIO_s_file());
+ bmd = BIO_new(BIO_f_md());
+ if ((in == NULL) || (bmd == NULL)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (debug) {
+ BIO_set_callback(in, BIO_debug_callback);
+ /* needed for windows 3.1 */
+ BIO_set_callback_arg(in, (char *)bio_err);
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ if (out_bin == -1) {
+ if (keyfile != NULL)
+ out_bin = 1;
+ else
+ out_bin = 0;
+ }
+
+ out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
+ if (out == NULL)
+ goto end;
+
+ if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
+ BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
+ goto end;
+ }
+
+ if (keyfile != NULL) {
+ int type;
+
+ if (want_pub)
+ sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file");
+ else
+ sigkey = load_key(keyfile, keyform, 0, passin, e, "key file");
+ if (sigkey == NULL) {
+ /*
+ * load_[pub]key() has already printed an appropriate message
+ */
+ goto end;
+ }
+ type = EVP_PKEY_id(sigkey);
+ if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
+ /*
+ * We implement PureEdDSA for these which doesn't have a separate
+ * digest, and only supports one shot.
+ */
+ BIO_printf(bio_err, "Key type not supported for this operation\n");
+ goto end;
+ }
+ }
+
+ if (mac_name != NULL) {
+ EVP_PKEY_CTX *mac_ctx = NULL;
+ int r = 0;
+ if (!init_gen_str(&mac_ctx, mac_name, impl, 0))
+ goto mac_end;
+ if (macopts != NULL) {
+ char *macopt;
+ for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
+ macopt = sk_OPENSSL_STRING_value(macopts, i);
+ if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
+ BIO_printf(bio_err,
+ "MAC parameter error \"%s\"\n", macopt);
+ ERR_print_errors(bio_err);
+ goto mac_end;
+ }
+ }
+ }
+ if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
+ BIO_puts(bio_err, "Error generating key\n");
+ ERR_print_errors(bio_err);
+ goto mac_end;
+ }
+ r = 1;
+ mac_end:
+ EVP_PKEY_CTX_free(mac_ctx);
+ if (r == 0)
+ goto end;
+ }
+
+ if (hmac_key != NULL) {
+ sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
+ (unsigned char *)hmac_key, -1);
+ if (sigkey == NULL)
+ goto end;
+ }
+
+ if (sigkey != NULL) {
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ int r;
+ if (!BIO_get_md_ctx(bmd, &mctx)) {
+ BIO_printf(bio_err, "Error getting context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (do_verify)
+ r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
+ else
+ r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
+ if (!r) {
+ BIO_printf(bio_err, "Error setting context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (sigopts != NULL) {
+ char *sigopt;
+ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
+ sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+ if (pkey_ctrl_string(pctx, sigopt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+ }
+ /* we use md as a filter, reading from 'in' */
+ else {
+ EVP_MD_CTX *mctx = NULL;
+ if (!BIO_get_md_ctx(bmd, &mctx)) {
+ BIO_printf(bio_err, "Error getting context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (md == NULL)
+ md = EVP_sha256();
+ if (!EVP_DigestInit_ex(mctx, md, impl)) {
+ BIO_printf(bio_err, "Error setting digest\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (sigfile != NULL && sigkey != NULL) {
+ BIO *sigbio = BIO_new_file(sigfile, "rb");
+ if (sigbio == NULL) {
+ BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ siglen = EVP_PKEY_size(sigkey);
+ sigbuf = app_malloc(siglen, "signature buffer");
+ siglen = BIO_read(sigbio, sigbuf, siglen);
+ BIO_free(sigbio);
+ if (siglen <= 0) {
+ BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ inp = BIO_push(bmd, in);
+
+ if (md == NULL) {
+ EVP_MD_CTX *tctx;
+ BIO_get_md_ctx(bmd, &tctx);
+ md = EVP_MD_CTX_md(tctx);
+ }
+
+ if (argc == 0) {
+ BIO_set_fp(in, stdin, BIO_NOCLOSE);
+ ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
+ siglen, NULL, NULL, "stdin");
+ } else {
+ const char *md_name = NULL, *sig_name = NULL;
+ if (!out_bin) {
+ if (sigkey != NULL) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ameth = EVP_PKEY_get0_asn1(sigkey);
+ if (ameth)
+ EVP_PKEY_asn1_get0_info(NULL, NULL,
+ NULL, NULL, &sig_name, ameth);
+ }
+ if (md != NULL)
+ md_name = EVP_MD_name(md);
+ }
+ ret = 0;
+ for (i = 0; i < argc; i++) {
+ int r;
+ if (BIO_read_filename(in, argv[i]) <= 0) {
+ perror(argv[i]);
+ ret++;
+ continue;
+ } else {
+ r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
+ siglen, sig_name, md_name, argv[i]);
+ }
+ if (r)
+ ret = r;
+ (void)BIO_reset(bmd);
+ }
+ }
+ end:
+ OPENSSL_clear_free(buf, BUFSIZE);
+ BIO_free(in);
+ OPENSSL_free(passin);
+ BIO_free_all(out);
+ EVP_PKEY_free(sigkey);
+ sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(macopts);
+ OPENSSL_free(sigbuf);
+ BIO_free(bmd);
+ release_engine(e);
+ return ret;
+}
+
+int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
+ EVP_PKEY *key, unsigned char *sigin, int siglen,
+ const char *sig_name, const char *md_name,
+ const char *file)
+{
+ size_t len;
+ int i;
+
+ for (;;) {
+ i = BIO_read(bp, (char *)buf, BUFSIZE);
+ if (i < 0) {
+ BIO_printf(bio_err, "Read Error in %s\n", file);
+ ERR_print_errors(bio_err);
+ return 1;
+ }
+ if (i == 0)
+ break;
+ }
+ if (sigin != NULL) {
+ EVP_MD_CTX *ctx;
+ BIO_get_md_ctx(bp, &ctx);
+ i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
+ if (i > 0) {
+ BIO_printf(out, "Verified OK\n");
+ } else if (i == 0) {
+ BIO_printf(out, "Verification Failure\n");
+ return 1;
+ } else {
+ BIO_printf(bio_err, "Error Verifying Data\n");
+ ERR_print_errors(bio_err);
+ return 1;
+ }
+ return 0;
+ }
+ if (key != NULL) {
+ EVP_MD_CTX *ctx;
+ BIO_get_md_ctx(bp, &ctx);
+ len = BUFSIZE;
+ if (!EVP_DigestSignFinal(ctx, buf, &len)) {
+ BIO_printf(bio_err, "Error Signing Data\n");
+ ERR_print_errors(bio_err);
+ return 1;
+ }
+ } else {
+ len = BIO_gets(bp, (char *)buf, BUFSIZE);
+ if ((int)len < 0) {
+ ERR_print_errors(bio_err);
+ return 1;
+ }
+ }
+
+ if (binout) {
+ BIO_write(out, buf, len);
+ } else if (sep == 2) {
+ for (i = 0; i < (int)len; i++)
+ BIO_printf(out, "%02x", buf[i]);
+ BIO_printf(out, " *%s\n", file);
+ } else {
+ if (sig_name != NULL) {
+ BIO_puts(out, sig_name);
+ if (md_name != NULL)
+ BIO_printf(out, "-%s", md_name);
+ BIO_printf(out, "(%s)= ", file);
+ } else if (md_name != NULL) {
+ BIO_printf(out, "%s(%s)= ", md_name, file);
+ } else {
+ BIO_printf(out, "(%s)= ", file);
+ }
+ for (i = 0; i < (int)len; i++) {
+ if (sep && (i != 0))
+ BIO_printf(out, ":");
+ BIO_printf(out, "%02x", buf[i]);
+ }
+ BIO_printf(out, "\n");
+ }
+ return 0;
+}
diff --git a/freebsd/crypto/openssl/apps/dhparam.c b/freebsd/crypto/openssl/apps/dhparam.c
new file mode 100644
index 00000000..505ee4bf
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/dhparam.c
@@ -0,0 +1,381 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_DH
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <time.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/bn.h>
+# include <openssl/dh.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+
+# ifndef OPENSSL_NO_DSA
+# include <openssl/dsa.h>
+# endif
+
+# define DEFBITS 2048
+
+static int dh_cb(int p, int n, BN_GENCB *cb);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
+ OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT,
+ OPT_DSAPARAM, OPT_C, OPT_2, OPT_5,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS dhparam_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"},
+ {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"check", OPT_CHECK, '-', "Check the DH parameters"},
+ {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"},
+ {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"},
+ OPT_R_OPTIONS,
+ {"C", OPT_C, '-', "Print C code"},
+ {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"},
+ {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
+# ifndef OPENSSL_NO_DSA
+ {"dsaparam", OPT_DSAPARAM, '-',
+ "Read or generate DSA parameters, convert to DH"},
+# endif
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int dhparam_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ DH *dh = NULL;
+ char *infile = NULL, *outfile = NULL, *prog;
+ ENGINE *e = NULL;
+#ifndef OPENSSL_NO_DSA
+ int dsaparam = 0;
+#endif
+ int i, text = 0, C = 0, ret = 1, num = 0, g = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, dhparam_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(dhparam_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_DSAPARAM:
+#ifndef OPENSSL_NO_DSA
+ dsaparam = 1;
+#endif
+ break;
+ case OPT_C:
+ C = 1;
+ break;
+ case OPT_2:
+ g = 2;
+ break;
+ case OPT_5:
+ g = 5;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0))
+ goto end;
+
+ if (g && !num)
+ num = DEFBITS;
+
+# ifndef OPENSSL_NO_DSA
+ if (dsaparam && g) {
+ BIO_printf(bio_err,
+ "generator may not be chosen for DSA parameters\n");
+ goto end;
+ }
+# endif
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ /* DH parameters */
+ if (num && !g)
+ g = 2;
+
+ if (num) {
+
+ BN_GENCB *cb;
+ cb = BN_GENCB_new();
+ if (cb == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ BN_GENCB_set(cb, dh_cb, bio_err);
+
+# ifndef OPENSSL_NO_DSA
+ if (dsaparam) {
+ DSA *dsa = DSA_new();
+
+ BIO_printf(bio_err,
+ "Generating DSA parameters, %d bit long prime\n", num);
+ if (dsa == NULL
+ || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
+ cb)) {
+ DSA_free(dsa);
+ BN_GENCB_free(cb);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ dh = DSA_dup_DH(dsa);
+ DSA_free(dsa);
+ if (dh == NULL) {
+ BN_GENCB_free(cb);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else
+# endif
+ {
+ dh = DH_new();
+ BIO_printf(bio_err,
+ "Generating DH parameters, %d bit long safe prime, generator %d\n",
+ num, g);
+ BIO_printf(bio_err, "This is going to take a long time\n");
+ if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) {
+ BN_GENCB_free(cb);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ BN_GENCB_free(cb);
+ } else {
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+# ifndef OPENSSL_NO_DSA
+ if (dsaparam) {
+ DSA *dsa;
+
+ if (informat == FORMAT_ASN1)
+ dsa = d2i_DSAparams_bio(in, NULL);
+ else /* informat == FORMAT_PEM */
+ dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
+
+ if (dsa == NULL) {
+ BIO_printf(bio_err, "unable to load DSA parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ dh = DSA_dup_DH(dsa);
+ DSA_free(dsa);
+ if (dh == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else
+# endif
+ {
+ if (informat == FORMAT_ASN1) {
+ /*
+ * We have no PEM header to determine what type of DH params it
+ * is. We'll just try both.
+ */
+ dh = d2i_DHparams_bio(in, NULL);
+ /* BIO_reset() returns 0 for success for file BIOs only!!! */
+ if (dh == NULL && BIO_reset(in) == 0)
+ dh = d2i_DHxparams_bio(in, NULL);
+ } else {
+ /* informat == FORMAT_PEM */
+ dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
+ }
+
+ if (dh == NULL) {
+ BIO_printf(bio_err, "unable to load DH parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ /* dh != NULL */
+ }
+
+ if (text) {
+ DHparams_print(out, dh);
+ }
+
+ if (check) {
+ if (!DH_check(dh, &i)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (i & DH_CHECK_P_NOT_PRIME)
+ BIO_printf(bio_err, "WARNING: p value is not prime\n");
+ if (i & DH_CHECK_P_NOT_SAFE_PRIME)
+ BIO_printf(bio_err, "WARNING: p value is not a safe prime\n");
+ if (i & DH_CHECK_Q_NOT_PRIME)
+ BIO_printf(bio_err, "WARNING: q value is not a prime\n");
+ if (i & DH_CHECK_INVALID_Q_VALUE)
+ BIO_printf(bio_err, "WARNING: q value is invalid\n");
+ if (i & DH_CHECK_INVALID_J_VALUE)
+ BIO_printf(bio_err, "WARNING: j value is invalid\n");
+ if (i & DH_UNABLE_TO_CHECK_GENERATOR)
+ BIO_printf(bio_err,
+ "WARNING: unable to check the generator value\n");
+ if (i & DH_NOT_SUITABLE_GENERATOR)
+ BIO_printf(bio_err, "WARNING: the g value is not a generator\n");
+ if (i == 0)
+ BIO_printf(bio_err, "DH parameters appear to be ok.\n");
+ if (num != 0 && i != 0) {
+ /*
+ * We have generated parameters but DH_check() indicates they are
+ * invalid! This should never happen!
+ */
+ BIO_printf(bio_err, "ERROR: Invalid parameters generated\n");
+ goto end;
+ }
+ }
+ if (C) {
+ unsigned char *data;
+ int len, bits;
+ const BIGNUM *pbn, *gbn;
+
+ len = DH_size(dh);
+ bits = DH_bits(dh);
+ DH_get0_pqg(dh, &pbn, NULL, &gbn);
+ data = app_malloc(len, "print a BN");
+
+ BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits);
+ print_bignum_var(out, pbn, "dhp", bits, data);
+ print_bignum_var(out, gbn, "dhg", bits, data);
+ BIO_printf(out, " DH *dh = DH_new();\n"
+ " BIGNUM *p, *g;\n"
+ "\n"
+ " if (dh == NULL)\n"
+ " return NULL;\n");
+ BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n",
+ bits, bits);
+ BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n",
+ bits, bits);
+ BIO_printf(out, " if (p == NULL || g == NULL\n"
+ " || !DH_set0_pqg(dh, p, NULL, g)) {\n"
+ " DH_free(dh);\n"
+ " BN_free(p);\n"
+ " BN_free(g);\n"
+ " return NULL;\n"
+ " }\n");
+ if (DH_get_length(dh) > 0)
+ BIO_printf(out,
+ " if (!DH_set_length(dh, %ld)) {\n"
+ " DH_free(dh);\n"
+ " return NULL;\n"
+ " }\n", DH_get_length(dh));
+ BIO_printf(out, " return dh;\n}\n");
+ OPENSSL_free(data);
+ }
+
+ if (!noout) {
+ const BIGNUM *q;
+ DH_get0_pqg(dh, NULL, &q, NULL);
+ if (outformat == FORMAT_ASN1) {
+ if (q != NULL)
+ i = i2d_DHxparams_bio(out, dh);
+ else
+ i = i2d_DHparams_bio(out, dh);
+ } else if (q != NULL) {
+ i = PEM_write_bio_DHxparams(out, dh);
+ } else {
+ i = PEM_write_bio_DHparams(out, dh);
+ }
+ if (!i) {
+ BIO_printf(bio_err, "unable to write DH parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ BIO_free(in);
+ BIO_free_all(out);
+ DH_free(dh);
+ release_engine(e);
+ return ret;
+}
+
+static int dh_cb(int p, int n, BN_GENCB *cb)
+{
+ static const char symbols[] = ".+*\n";
+ char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
+
+ BIO_write(BN_GENCB_get_arg(cb), &c, 1);
+ (void)BIO_flush(BN_GENCB_get_arg(cb));
+ return 1;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/dsa.c b/freebsd/crypto/openssl/apps/dsa.c
new file mode 100644
index 00000000..bec86054
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/dsa.c
@@ -0,0 +1,267 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_DSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/dsa.h>
+# include <openssl/evp.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+# include <openssl/bn.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE,
+ /* Do not change the order here; see case statements below */
+ OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
+ OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN,
+ OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT
+} OPTION_CHOICE;
+
+const OPTIONS dsa_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"},
+ {"in", OPT_IN, 's', "Input key"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"noout", OPT_NOOUT, '-', "Don't print key out"},
+ {"text", OPT_TEXT, '-', "Print the key in text"},
+ {"modulus", OPT_MODULUS, '-', "Print the DSA public value"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+# ifndef OPENSSL_NO_RC4
+ {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
+ {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
+ {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
+# endif
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int dsa_main(int argc, char **argv)
+{
+ BIO *out = NULL;
+ DSA *dsa = NULL;
+ ENGINE *e = NULL;
+ const EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *prog;
+ char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
+ OPTION_CHOICE o;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int i, modulus = 0, pubin = 0, pubout = 0, ret = 1;
+# ifndef OPENSSL_NO_RC4
+ int pvk_encr = 2;
+# endif
+ int private = 0;
+
+ prog = opt_init(argc, argv, dsa_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ ret = 0;
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(dsa_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_PVK_STRONG: /* pvk_encr:= 2 */
+ case OPT_PVK_WEAK: /* pvk_encr:= 1 */
+ case OPT_PVK_NONE: /* pvk_encr:= 0 */
+#ifndef OPENSSL_NO_RC4
+ pvk_encr = (o - OPT_PVK_NONE);
+#endif
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_MODULUS:
+ modulus = 1;
+ break;
+ case OPT_PUBIN:
+ pubin = 1;
+ break;
+ case OPT_PUBOUT:
+ pubout = 1;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = pubin || pubout ? 0 : 1;
+ if (text && !pubin)
+ private = 1;
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ BIO_printf(bio_err, "read DSA key\n");
+ {
+ EVP_PKEY *pkey;
+
+ if (pubin)
+ pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
+ else
+ pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+
+ if (pkey != NULL) {
+ dsa = EVP_PKEY_get1_DSA(pkey);
+ EVP_PKEY_free(pkey);
+ }
+ }
+ if (dsa == NULL) {
+ BIO_printf(bio_err, "unable to load Key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (text) {
+ assert(pubin || private);
+ if (!DSA_print(out, dsa, 0)) {
+ perror(outfile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (modulus) {
+ const BIGNUM *pub_key = NULL;
+ DSA_get0_key(dsa, &pub_key, NULL);
+ BIO_printf(out, "Public Key=");
+ BN_print(out, pub_key);
+ BIO_printf(out, "\n");
+ }
+
+ if (noout) {
+ ret = 0;
+ goto end;
+ }
+ BIO_printf(bio_err, "writing DSA key\n");
+ if (outformat == FORMAT_ASN1) {
+ if (pubin || pubout) {
+ i = i2d_DSA_PUBKEY_bio(out, dsa);
+ } else {
+ assert(private);
+ i = i2d_DSAPrivateKey_bio(out, dsa);
+ }
+ } else if (outformat == FORMAT_PEM) {
+ if (pubin || pubout) {
+ i = PEM_write_bio_DSA_PUBKEY(out, dsa);
+ } else {
+ assert(private);
+ i = PEM_write_bio_DSAPrivateKey(out, dsa, enc,
+ NULL, 0, NULL, passout);
+ }
+# ifndef OPENSSL_NO_RSA
+ } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
+ EVP_PKEY *pk;
+ pk = EVP_PKEY_new();
+ if (pk == NULL)
+ goto end;
+
+ EVP_PKEY_set1_DSA(pk, dsa);
+ if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
+ EVP_PKEY_free(pk);
+ goto end;
+ }
+ assert(private);
+# ifdef OPENSSL_NO_RC4
+ BIO_printf(bio_err, "PVK format not supported\n");
+ EVP_PKEY_free(pk);
+ goto end;
+# else
+ i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
+# endif
+ } else if (pubin || pubout) {
+ i = i2b_PublicKey_bio(out, pk);
+ } else {
+ assert(private);
+ i = i2b_PrivateKey_bio(out, pk);
+ }
+ EVP_PKEY_free(pk);
+# endif
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+ if (i <= 0) {
+ BIO_printf(bio_err, "unable to write private key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ end:
+ BIO_free_all(out);
+ DSA_free(dsa);
+ release_engine(e);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/dsaparam.c b/freebsd/crypto/openssl/apps/dsaparam.c
new file mode 100644
index 00000000..78a5c64c
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/dsaparam.c
@@ -0,0 +1,260 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_DSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <time.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/bn.h>
+# include <openssl/dsa.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+
+static int dsa_cb(int p, int n, BN_GENCB *cb);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
+ OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS dsaparam_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"text", OPT_TEXT, '-', "Print as text"},
+ {"C", OPT_C, '-', "Output C code"},
+ {"noout", OPT_NOOUT, '-', "No output"},
+ {"genkey", OPT_GENKEY, '-', "Generate a DSA key"},
+ OPT_R_OPTIONS,
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int dsaparam_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ DSA *dsa = NULL;
+ BIO *in = NULL, *out = NULL;
+ BN_GENCB *cb = NULL;
+ int numbits = -1, num = 0, genkey = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
+ int ret = 1, i, text = 0, private = 0;
+ char *infile = NULL, *outfile = NULL, *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, dsaparam_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(dsaparam_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_C:
+ C = 1;
+ break;
+ case OPT_GENKEY:
+ genkey = 1;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (argc == 1) {
+ if (!opt_int(argv[0], &num) || num < 0)
+ goto end;
+ /* generate a key */
+ numbits = num;
+ }
+ private = genkey ? 1 : 0;
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (numbits > 0) {
+ if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS)
+ BIO_printf(bio_err,
+ "Warning: It is not recommended to use more than %d bit for DSA keys.\n"
+ " Your key size is %d! Larger key size may behave not as expected.\n",
+ OPENSSL_DSA_MAX_MODULUS_BITS, numbits);
+
+ cb = BN_GENCB_new();
+ if (cb == NULL) {
+ BIO_printf(bio_err, "Error allocating BN_GENCB object\n");
+ goto end;
+ }
+ BN_GENCB_set(cb, dsa_cb, bio_err);
+ dsa = DSA_new();
+ if (dsa == NULL) {
+ BIO_printf(bio_err, "Error allocating DSA object\n");
+ goto end;
+ }
+ BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
+ num);
+ BIO_printf(bio_err, "This could take some time\n");
+ if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "Error, DSA key generation failed\n");
+ goto end;
+ }
+ } else if (informat == FORMAT_ASN1) {
+ dsa = d2i_DSAparams_bio(in, NULL);
+ } else {
+ dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
+ }
+ if (dsa == NULL) {
+ BIO_printf(bio_err, "unable to load DSA parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (text) {
+ DSAparams_print(out, dsa);
+ }
+
+ if (C) {
+ const BIGNUM *p = NULL, *q = NULL, *g = NULL;
+ unsigned char *data;
+ int len, bits_p;
+
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ len = BN_num_bytes(p);
+ bits_p = BN_num_bits(p);
+
+ data = app_malloc(len + 20, "BN space");
+
+ BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p);
+ print_bignum_var(bio_out, p, "dsap", bits_p, data);
+ print_bignum_var(bio_out, q, "dsaq", bits_p, data);
+ print_bignum_var(bio_out, g, "dsag", bits_p, data);
+ BIO_printf(bio_out, " DSA *dsa = DSA_new();\n"
+ " BIGNUM *p, *q, *g;\n"
+ "\n");
+ BIO_printf(bio_out, " if (dsa == NULL)\n"
+ " return NULL;\n");
+ BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n",
+ bits_p, bits_p);
+ BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n",
+ bits_p, bits_p);
+ BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n",
+ bits_p, bits_p);
+ BIO_printf(bio_out, " DSA_free(dsa);\n"
+ " BN_free(p);\n"
+ " BN_free(q);\n"
+ " BN_free(g);\n"
+ " return NULL;\n"
+ " }\n"
+ " return dsa;\n}\n");
+ OPENSSL_free(data);
+ }
+
+ if (outformat == FORMAT_ASN1 && genkey)
+ noout = 1;
+
+ if (!noout) {
+ if (outformat == FORMAT_ASN1)
+ i = i2d_DSAparams_bio(out, dsa);
+ else
+ i = PEM_write_bio_DSAparams(out, dsa);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write DSA parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (genkey) {
+ DSA *dsakey;
+
+ if ((dsakey = DSAparams_dup(dsa)) == NULL)
+ goto end;
+ if (!DSA_generate_key(dsakey)) {
+ ERR_print_errors(bio_err);
+ DSA_free(dsakey);
+ goto end;
+ }
+ assert(private);
+ if (outformat == FORMAT_ASN1)
+ i = i2d_DSAPrivateKey_bio(out, dsakey);
+ else
+ i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL,
+ NULL);
+ DSA_free(dsakey);
+ }
+ ret = 0;
+ end:
+ BN_GENCB_free(cb);
+ BIO_free(in);
+ BIO_free_all(out);
+ DSA_free(dsa);
+ release_engine(e);
+ return ret;
+}
+
+static int dsa_cb(int p, int n, BN_GENCB *cb)
+{
+ static const char symbols[] = ".+*\n";
+ char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
+
+ BIO_write(BN_GENCB_get_arg(cb), &c, 1);
+ (void)BIO_flush(BN_GENCB_get_arg(cb));
+ return 1;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/ec.c b/freebsd/crypto/openssl/apps/ec.c
new file mode 100644
index 00000000..bbeccd97
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ec.c
@@ -0,0 +1,285 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_EC
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/evp.h>
+# include <openssl/pem.h>
+
+static OPT_PAIR conv_forms[] = {
+ {"compressed", POINT_CONVERSION_COMPRESSED},
+ {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
+ {"hybrid", POINT_CONVERSION_HYBRID},
+ {NULL}
+};
+
+static OPT_PAIR param_enc[] = {
+ {"named_curve", OPENSSL_EC_NAMED_CURVE},
+ {"explicit", 0},
+ {NULL}
+};
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
+ OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT,
+ OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER,
+ OPT_NO_PUBLIC, OPT_CHECK
+} OPTION_CHOICE;
+
+const OPTIONS ec_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, 's', "Input file"},
+ {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"noout", OPT_NOOUT, '-', "Don't print key out"},
+ {"text", OPT_TEXT, '-', "Print the key"},
+ {"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
+ {"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"},
+ {"check", OPT_CHECK, '-', "check key consistency"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"param_enc", OPT_PARAM_ENC, 's',
+ "Specifies the way the ec parameters are encoded"},
+ {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int ec_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EC_KEY *eckey = NULL;
+ const EC_GROUP *group;
+ const EVP_CIPHER *enc = NULL;
+ point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
+ char *infile = NULL, *outfile = NULL, *prog;
+ char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
+ OPTION_CHOICE o;
+ int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0;
+ int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0;
+ int no_public = 0, check = 0;
+
+ prog = opt_init(argc, argv, ec_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(ec_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_PARAM_OUT:
+ param_out = 1;
+ break;
+ case OPT_PUBIN:
+ pubin = 1;
+ break;
+ case OPT_PUBOUT:
+ pubout = 1;
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto opthelp;
+ break;
+ case OPT_CONV_FORM:
+ if (!opt_pair(opt_arg(), conv_forms, &i))
+ goto opthelp;
+ new_form = 1;
+ form = i;
+ break;
+ case OPT_PARAM_ENC:
+ if (!opt_pair(opt_arg(), param_enc, &i))
+ goto opthelp;
+ new_asn1_flag = 1;
+ asn1_flag = i;
+ break;
+ case OPT_NO_PUBLIC:
+ no_public = 1;
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = param_out || pubin || pubout ? 0 : 1;
+ if (text && !pubin)
+ private = 1;
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if (informat != FORMAT_ENGINE) {
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+ }
+
+ BIO_printf(bio_err, "read EC key\n");
+ if (informat == FORMAT_ASN1) {
+ if (pubin)
+ eckey = d2i_EC_PUBKEY_bio(in, NULL);
+ else
+ eckey = d2i_ECPrivateKey_bio(in, NULL);
+ } else if (informat == FORMAT_ENGINE) {
+ EVP_PKEY *pkey;
+ if (pubin)
+ pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
+ else
+ pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+ if (pkey != NULL) {
+ eckey = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ }
+ } else {
+ if (pubin)
+ eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
+ else
+ eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin);
+ }
+ if (eckey == NULL) {
+ BIO_printf(bio_err, "unable to load Key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ group = EC_KEY_get0_group(eckey);
+
+ if (new_form)
+ EC_KEY_set_conv_form(eckey, form);
+
+ if (new_asn1_flag)
+ EC_KEY_set_asn1_flag(eckey, asn1_flag);
+
+ if (no_public)
+ EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+
+ if (text) {
+ assert(pubin || private);
+ if (!EC_KEY_print(out, eckey, 0)) {
+ perror(outfile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (check) {
+ if (EC_KEY_check_key(eckey) == 1) {
+ BIO_printf(bio_err, "EC Key valid.\n");
+ } else {
+ BIO_printf(bio_err, "EC Key Invalid!\n");
+ ERR_print_errors(bio_err);
+ }
+ }
+
+ if (noout) {
+ ret = 0;
+ goto end;
+ }
+
+ BIO_printf(bio_err, "writing EC key\n");
+ if (outformat == FORMAT_ASN1) {
+ if (param_out) {
+ i = i2d_ECPKParameters_bio(out, group);
+ } else if (pubin || pubout) {
+ i = i2d_EC_PUBKEY_bio(out, eckey);
+ } else {
+ assert(private);
+ i = i2d_ECPrivateKey_bio(out, eckey);
+ }
+ } else {
+ if (param_out) {
+ i = PEM_write_bio_ECPKParameters(out, group);
+ } else if (pubin || pubout) {
+ i = PEM_write_bio_EC_PUBKEY(out, eckey);
+ } else {
+ assert(private);
+ i = PEM_write_bio_ECPrivateKey(out, eckey, enc,
+ NULL, 0, NULL, passout);
+ }
+ }
+
+ if (!i) {
+ BIO_printf(bio_err, "unable to write private key\n");
+ ERR_print_errors(bio_err);
+ } else {
+ ret = 0;
+ }
+ end:
+ BIO_free(in);
+ BIO_free_all(out);
+ EC_KEY_free(eckey);
+ release_engine(e);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/ecparam.c b/freebsd/crypto/openssl/apps/ecparam.c
new file mode 100644
index 00000000..423b5f33
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ecparam.c
@@ -0,0 +1,452 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_EC
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <time.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/bn.h>
+# include <openssl/ec.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
+ OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
+ OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS ecparam_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
+ {"in", OPT_IN, '<', "Input file - default stdin"},
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"text", OPT_TEXT, '-', "Print the ec parameters in text form"},
+ {"C", OPT_C, '-', "Print a 'C' function creating the parameters"},
+ {"check", OPT_CHECK, '-', "Validate the ec parameters"},
+ {"list_curves", OPT_LIST_CURVES, '-',
+ "Prints a list of all curve 'short names'"},
+ {"no_seed", OPT_NO_SEED, '-',
+ "If 'explicit' parameters are chosen do not use the seed"},
+ {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
+ {"name", OPT_NAME, 's',
+ "Use the ec parameters with specified 'short name'"},
+ {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
+ {"param_enc", OPT_PARAM_ENC, 's',
+ "Specifies the way the ec parameters are encoded"},
+ {"genkey", OPT_GENKEY, '-', "Generate ec key"},
+ OPT_R_OPTIONS,
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+static OPT_PAIR forms[] = {
+ {"compressed", POINT_CONVERSION_COMPRESSED},
+ {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
+ {"hybrid", POINT_CONVERSION_HYBRID},
+ {NULL}
+};
+
+static OPT_PAIR encodings[] = {
+ {"named_curve", OPENSSL_EC_NAMED_CURVE},
+ {"explicit", 0},
+ {NULL}
+};
+
+int ecparam_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
+ BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;
+ BIO *in = NULL, *out = NULL;
+ EC_GROUP *group = NULL;
+ point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
+ char *curve_name = NULL;
+ char *infile = NULL, *outfile = NULL, *prog;
+ unsigned char *buffer = NULL;
+ OPTION_CHOICE o;
+ int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
+ int ret = 1, private = 0;
+ int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
+ int text = 0, i, genkey = 0;
+
+ prog = opt_init(argc, argv, ecparam_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(ecparam_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_C:
+ C = 1;
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ case OPT_LIST_CURVES:
+ list_curves = 1;
+ break;
+ case OPT_NO_SEED:
+ no_seed = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_NAME:
+ curve_name = opt_arg();
+ break;
+ case OPT_CONV_FORM:
+ if (!opt_pair(opt_arg(), forms, &new_form))
+ goto opthelp;
+ form = new_form;
+ new_form = 1;
+ break;
+ case OPT_PARAM_ENC:
+ if (!opt_pair(opt_arg(), encodings, &asn1_flag))
+ goto opthelp;
+ new_asn1_flag = 1;
+ break;
+ case OPT_GENKEY:
+ genkey = 1;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = genkey ? 1 : 0;
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (list_curves) {
+ EC_builtin_curve *curves = NULL;
+ size_t crv_len = EC_get_builtin_curves(NULL, 0);
+ size_t n;
+
+ curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
+ if (!EC_get_builtin_curves(curves, crv_len)) {
+ OPENSSL_free(curves);
+ goto end;
+ }
+
+ for (n = 0; n < crv_len; n++) {
+ const char *comment;
+ const char *sname;
+ comment = curves[n].comment;
+ sname = OBJ_nid2sn(curves[n].nid);
+ if (comment == NULL)
+ comment = "CURVE DESCRIPTION NOT AVAILABLE";
+ if (sname == NULL)
+ sname = "";
+
+ BIO_printf(out, " %-10s: ", sname);
+ BIO_printf(out, "%s\n", comment);
+ }
+
+ OPENSSL_free(curves);
+ ret = 0;
+ goto end;
+ }
+
+ if (curve_name != NULL) {
+ int nid;
+
+ /*
+ * workaround for the SECG curve names secp192r1 and secp256r1 (which
+ * are the same as the curves prime192v1 and prime256v1 defined in
+ * X9.62)
+ */
+ if (strcmp(curve_name, "secp192r1") == 0) {
+ BIO_printf(bio_err, "using curve name prime192v1 "
+ "instead of secp192r1\n");
+ nid = NID_X9_62_prime192v1;
+ } else if (strcmp(curve_name, "secp256r1") == 0) {
+ BIO_printf(bio_err, "using curve name prime256v1 "
+ "instead of secp256r1\n");
+ nid = NID_X9_62_prime256v1;
+ } else {
+ nid = OBJ_sn2nid(curve_name);
+ }
+
+ if (nid == 0)
+ nid = EC_curve_nist2nid(curve_name);
+
+ if (nid == 0) {
+ BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
+ goto end;
+ }
+
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (group == NULL) {
+ BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
+ goto end;
+ }
+ EC_GROUP_set_asn1_flag(group, asn1_flag);
+ EC_GROUP_set_point_conversion_form(group, form);
+ } else if (informat == FORMAT_ASN1) {
+ group = d2i_ECPKParameters_bio(in, NULL);
+ } else {
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
+ }
+ if (group == NULL) {
+ BIO_printf(bio_err, "unable to load elliptic curve parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (new_form)
+ EC_GROUP_set_point_conversion_form(group, form);
+
+ if (new_asn1_flag)
+ EC_GROUP_set_asn1_flag(group, asn1_flag);
+
+ if (no_seed) {
+ EC_GROUP_set_seed(group, NULL, 0);
+ }
+
+ if (text) {
+ if (!ECPKParameters_print(out, group, 0))
+ goto end;
+ }
+
+ if (check) {
+ BIO_printf(bio_err, "checking elliptic curve parameters: ");
+ if (!EC_GROUP_check(group, NULL)) {
+ BIO_printf(bio_err, "failed\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(bio_err, "ok\n");
+
+ }
+
+ if (C) {
+ size_t buf_len = 0, tmp_len = 0;
+ const EC_POINT *point;
+ int is_prime, len = 0;
+ const EC_METHOD *meth = EC_GROUP_method_of(group);
+
+ if ((ec_p = BN_new()) == NULL
+ || (ec_a = BN_new()) == NULL
+ || (ec_b = BN_new()) == NULL
+ || (ec_gen = BN_new()) == NULL
+ || (ec_order = BN_new()) == NULL
+ || (ec_cofactor = BN_new()) == NULL) {
+ perror("Can't allocate BN");
+ goto end;
+ }
+
+ is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
+ if (!is_prime) {
+ BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
+ goto end;
+ }
+
+ if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL))
+ goto end;
+
+ if ((point = EC_GROUP_get0_generator(group)) == NULL)
+ goto end;
+ if (!EC_POINT_point2bn(group, point,
+ EC_GROUP_get_point_conversion_form(group),
+ ec_gen, NULL))
+ goto end;
+ if (!EC_GROUP_get_order(group, ec_order, NULL))
+ goto end;
+ if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
+ goto end;
+
+ if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)
+ goto end;
+
+ len = BN_num_bits(ec_order);
+
+ if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
+ buf_len = tmp_len;
+ if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
+ buf_len = tmp_len;
+ if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
+ buf_len = tmp_len;
+ if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
+ buf_len = tmp_len;
+ if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
+ buf_len = tmp_len;
+ if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
+ buf_len = tmp_len;
+
+ buffer = app_malloc(buf_len, "BN buffer");
+
+ BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len);
+ print_bignum_var(out, ec_p, "ec_p", len, buffer);
+ print_bignum_var(out, ec_a, "ec_a", len, buffer);
+ print_bignum_var(out, ec_b, "ec_b", len, buffer);
+ print_bignum_var(out, ec_gen, "ec_gen", len, buffer);
+ print_bignum_var(out, ec_order, "ec_order", len, buffer);
+ print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer);
+ BIO_printf(out, " int ok = 0;\n"
+ " EC_GROUP *group = NULL;\n"
+ " EC_POINT *point = NULL;\n"
+ " BIGNUM *tmp_1 = NULL;\n"
+ " BIGNUM *tmp_2 = NULL;\n"
+ " BIGNUM *tmp_3 = NULL;\n"
+ "\n");
+
+ BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
+ " goto err;\n"
+ "\n");
+ BIO_printf(out, " /* build generator */\n");
+ BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
+ BIO_printf(out, " if (point == NULL)\n"
+ " goto err;\n");
+ BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n"
+ " goto err;\n", len, len);
+ BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
+ " goto err;\n"
+ "ok = 1;"
+ "\n");
+ BIO_printf(out, "err:\n"
+ " BN_free(tmp_1);\n"
+ " BN_free(tmp_2);\n"
+ " BN_free(tmp_3);\n"
+ " EC_POINT_free(point);\n"
+ " if (!ok) {\n"
+ " EC_GROUP_free(group);\n"
+ " return NULL;\n"
+ " }\n"
+ " return (group);\n"
+ "}\n");
+ }
+
+ if (outformat == FORMAT_ASN1 && genkey)
+ noout = 1;
+
+ if (!noout) {
+ if (outformat == FORMAT_ASN1)
+ i = i2d_ECPKParameters_bio(out, group);
+ else
+ i = PEM_write_bio_ECPKParameters(out, group);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write elliptic "
+ "curve parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (genkey) {
+ EC_KEY *eckey = EC_KEY_new();
+
+ if (eckey == NULL)
+ goto end;
+
+ if (EC_KEY_set_group(eckey, group) == 0) {
+ BIO_printf(bio_err, "unable to set group when generating key\n");
+ EC_KEY_free(eckey);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (new_form)
+ EC_KEY_set_conv_form(eckey, form);
+
+ if (!EC_KEY_generate_key(eckey)) {
+ BIO_printf(bio_err, "unable to generate key\n");
+ EC_KEY_free(eckey);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ assert(private);
+ if (outformat == FORMAT_ASN1)
+ i = i2d_ECPrivateKey_bio(out, eckey);
+ else
+ i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
+ NULL, 0, NULL, NULL);
+ EC_KEY_free(eckey);
+ }
+
+ ret = 0;
+ end:
+ BN_free(ec_p);
+ BN_free(ec_a);
+ BN_free(ec_b);
+ BN_free(ec_gen);
+ BN_free(ec_order);
+ BN_free(ec_cofactor);
+ OPENSSL_free(buffer);
+ EC_GROUP_free(group);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free_all(out);
+ return ret;
+}
+
+#endif
diff --git a/freebsd/crypto/openssl/apps/enc.c b/freebsd/crypto/openssl/apps/enc.c
new file mode 100644
index 00000000..dd09cbac
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/enc.c
@@ -0,0 +1,677 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/rand.h>
+#include <openssl/pem.h>
+#ifndef OPENSSL_NO_COMP
+# include <openssl/comp.h>
+#endif
+#include <ctype.h>
+
+#undef SIZE
+#undef BSIZE
+#define SIZE (512)
+#define BSIZE (8*1024)
+
+static int set_hex(const char *in, unsigned char *out, int size);
+static void show_ciphers(const OBJ_NAME *name, void *bio_);
+
+struct doall_enc_ciphers {
+ BIO *bio;
+ int n;
+};
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_LIST,
+ OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V,
+ OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
+ OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
+ OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS enc_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"ciphers", OPT_LIST, '-', "List ciphers"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"pass", OPT_PASS, 's', "Passphrase source"},
+ {"e", OPT_E, '-', "Encrypt"},
+ {"d", OPT_D, '-', "Decrypt"},
+ {"p", OPT_P, '-', "Print the iv/key"},
+ {"P", OPT_UPPER_P, '-', "Print the iv/key and exit"},
+ {"v", OPT_V, '-', "Verbose output"},
+ {"nopad", OPT_NOPAD, '-', "Disable standard block padding"},
+ {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"},
+ {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"},
+ {"debug", OPT_DEBUG, '-', "Print debug info"},
+ {"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"},
+ {"base64", OPT_A, '-', "Same as option -a"},
+ {"A", OPT_UPPER_A, '-',
+ "Used with -[base64|a] to specify base64 buffer as a single line"},
+ {"bufsize", OPT_BUFSIZE, 's', "Buffer size"},
+ {"k", OPT_K, 's', "Passphrase"},
+ {"kfile", OPT_KFILE, '<', "Read passphrase from file"},
+ {"K", OPT_UPPER_K, 's', "Raw key, in hex"},
+ {"S", OPT_UPPER_S, 's', "Salt, in hex"},
+ {"iv", OPT_IV, 's', "IV in hex"},
+ {"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"},
+ {"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"},
+ {"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"},
+ {"none", OPT_NONE, '-', "Don't encrypt"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+ OPT_R_OPTIONS,
+#ifdef ZLIB
+ {"z", OPT_Z, '-', "Use zlib as the 'encryption'"},
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int enc_main(int argc, char **argv)
+{
+ static char buf[128];
+ static const char magic[] = "Salted__";
+ ENGINE *e = NULL;
+ BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio =
+ NULL, *wbio = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ const EVP_CIPHER *cipher = NULL, *c;
+ const EVP_MD *dgst = NULL;
+ char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
+ char *infile = NULL, *outfile = NULL, *prog;
+ char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
+ char mbuf[sizeof(magic) - 1];
+ OPTION_CHOICE o;
+ int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
+ int enc = 1, printkey = 0, i, k;
+ int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY;
+ int ret = 1, inl, nopad = 0;
+ unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+ unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
+ int pbkdf2 = 0;
+ int iter = 0;
+ long n;
+ struct doall_enc_ciphers dec;
+#ifdef ZLIB
+ int do_zlib = 0;
+ BIO *bzl = NULL;
+#endif
+
+ /* first check the program name */
+ prog = opt_progname(argv[0]);
+ if (strcmp(prog, "base64") == 0) {
+ base64 = 1;
+#ifdef ZLIB
+ } else if (strcmp(prog, "zlib") == 0) {
+ do_zlib = 1;
+#endif
+ } else {
+ cipher = EVP_get_cipherbyname(prog);
+ if (cipher == NULL && strcmp(prog, "enc") != 0) {
+ BIO_printf(bio_err, "%s is not a known cipher\n", prog);
+ goto end;
+ }
+ }
+
+ prog = opt_init(argc, argv, enc_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(enc_options);
+ ret = 0;
+ goto end;
+ case OPT_LIST:
+ BIO_printf(bio_out, "Supported ciphers:\n");
+ dec.bio = bio_out;
+ dec.n = 0;
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
+ show_ciphers, &dec);
+ BIO_printf(bio_out, "\n");
+ ret = 0;
+ goto end;
+ case OPT_E:
+ enc = 1;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASS:
+ passarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_D:
+ enc = 0;
+ break;
+ case OPT_P:
+ printkey = 1;
+ break;
+ case OPT_V:
+ verbose = 1;
+ break;
+ case OPT_NOPAD:
+ nopad = 1;
+ break;
+ case OPT_SALT:
+ nosalt = 0;
+ break;
+ case OPT_NOSALT:
+ nosalt = 1;
+ break;
+ case OPT_DEBUG:
+ debug = 1;
+ break;
+ case OPT_UPPER_P:
+ printkey = 2;
+ break;
+ case OPT_UPPER_A:
+ olb64 = 1;
+ break;
+ case OPT_A:
+ base64 = 1;
+ break;
+ case OPT_Z:
+#ifdef ZLIB
+ do_zlib = 1;
+#endif
+ break;
+ case OPT_BUFSIZE:
+ p = opt_arg();
+ i = (int)strlen(p) - 1;
+ k = i >= 1 && p[i] == 'k';
+ if (k)
+ p[i] = '\0';
+ if (!opt_long(opt_arg(), &n)
+ || n < 0 || (k && n >= LONG_MAX / 1024))
+ goto opthelp;
+ if (k)
+ n *= 1024;
+ bsize = (int)n;
+ break;
+ case OPT_K:
+ str = opt_arg();
+ break;
+ case OPT_KFILE:
+ in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT);
+ if (in == NULL)
+ goto opthelp;
+ i = BIO_gets(in, buf, sizeof(buf));
+ BIO_free(in);
+ in = NULL;
+ if (i <= 0) {
+ BIO_printf(bio_err,
+ "%s Can't read key from %s\n", prog, opt_arg());
+ goto opthelp;
+ }
+ while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n'))
+ buf[i] = '\0';
+ if (i <= 0) {
+ BIO_printf(bio_err, "%s: zero length password\n", prog);
+ goto opthelp;
+ }
+ str = buf;
+ break;
+ case OPT_UPPER_K:
+ hkey = opt_arg();
+ break;
+ case OPT_UPPER_S:
+ hsalt = opt_arg();
+ break;
+ case OPT_IV:
+ hiv = opt_arg();
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_arg(), &dgst))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &c))
+ goto opthelp;
+ cipher = c;
+ break;
+ case OPT_ITER:
+ if (!opt_int(opt_arg(), &iter))
+ goto opthelp;
+ pbkdf2 = 1;
+ break;
+ case OPT_PBKDF2:
+ pbkdf2 = 1;
+ if (iter == 0) /* do not overwrite a chosen value */
+ iter = 10000;
+ break;
+ case OPT_NONE:
+ cipher = NULL;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ }
+ }
+ if (opt_num_rest() != 0) {
+ BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ }
+
+ if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog);
+ goto end;
+ }
+
+ if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) {
+ BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog);
+ goto end;
+ }
+
+ if (dgst == NULL)
+ dgst = EVP_sha256();
+
+ if (iter == 0)
+ iter = 1;
+
+ /* It must be large enough for a base64 encoded line */
+ if (base64 && bsize < 80)
+ bsize = 80;
+ if (verbose)
+ BIO_printf(bio_err, "bufsize=%d\n", bsize);
+
+#ifdef ZLIB
+ if (!do_zlib)
+#endif
+ if (base64) {
+ if (enc)
+ outformat = FORMAT_BASE64;
+ else
+ informat = FORMAT_BASE64;
+ }
+
+ strbuf = app_malloc(SIZE, "strbuf");
+ buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer");
+
+ if (infile == NULL) {
+ in = dup_bio_in(informat);
+ } else {
+ in = bio_open_default(infile, 'r', informat);
+ }
+ if (in == NULL)
+ goto end;
+
+ if (str == NULL && passarg != NULL) {
+ if (!app_passwd(passarg, NULL, &pass, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+ str = pass;
+ }
+
+ if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) {
+ if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ for (;;) {
+ char prompt[200];
+
+ BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:",
+ OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
+ (enc) ? "encryption" : "decryption");
+ strbuf[0] = '\0';
+ i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
+ if (i == 0) {
+ if (strbuf[0] == '\0') {
+ ret = 1;
+ goto end;
+ }
+ str = strbuf;
+ break;
+ }
+ if (i < 0) {
+ BIO_printf(bio_err, "bad password read\n");
+ goto end;
+ }
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "password required\n");
+ goto end;
+ }
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (debug) {
+ BIO_set_callback(in, BIO_debug_callback);
+ BIO_set_callback(out, BIO_debug_callback);
+ BIO_set_callback_arg(in, (char *)bio_err);
+ BIO_set_callback_arg(out, (char *)bio_err);
+ }
+
+ rbio = in;
+ wbio = out;
+
+#ifdef ZLIB
+ if (do_zlib) {
+ if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
+ goto end;
+ if (debug) {
+ BIO_set_callback(bzl, BIO_debug_callback);
+ BIO_set_callback_arg(bzl, (char *)bio_err);
+ }
+ if (enc)
+ wbio = BIO_push(bzl, wbio);
+ else
+ rbio = BIO_push(bzl, rbio);
+ }
+#endif
+
+ if (base64) {
+ if ((b64 = BIO_new(BIO_f_base64())) == NULL)
+ goto end;
+ if (debug) {
+ BIO_set_callback(b64, BIO_debug_callback);
+ BIO_set_callback_arg(b64, (char *)bio_err);
+ }
+ if (olb64)
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ if (enc)
+ wbio = BIO_push(b64, wbio);
+ else
+ rbio = BIO_push(b64, rbio);
+ }
+
+ if (cipher != NULL) {
+ /*
+ * Note that str is NULL if a key was passed on the command line, so
+ * we get no salt in that case. Is this a bug?
+ */
+ if (str != NULL) {
+ /*
+ * Salt handling: if encrypting generate a salt and write to
+ * output BIO. If decrypting read salt from input BIO.
+ */
+ unsigned char *sptr;
+ size_t str_len = strlen(str);
+
+ if (nosalt) {
+ sptr = NULL;
+ } else {
+ if (enc) {
+ if (hsalt) {
+ if (!set_hex(hsalt, salt, sizeof(salt))) {
+ BIO_printf(bio_err, "invalid hex salt value\n");
+ goto end;
+ }
+ } else if (RAND_bytes(salt, sizeof(salt)) <= 0) {
+ goto end;
+ }
+ /*
+ * If -P option then don't bother writing
+ */
+ if ((printkey != 2)
+ && (BIO_write(wbio, magic,
+ sizeof(magic) - 1) != sizeof(magic) - 1
+ || BIO_write(wbio,
+ (char *)salt,
+ sizeof(salt)) != sizeof(salt))) {
+ BIO_printf(bio_err, "error writing output file\n");
+ goto end;
+ }
+ } else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)
+ || BIO_read(rbio,
+ (unsigned char *)salt,
+ sizeof(salt)) != sizeof(salt)) {
+ BIO_printf(bio_err, "error reading input file\n");
+ goto end;
+ } else if (memcmp(mbuf, magic, sizeof(magic) - 1)) {
+ BIO_printf(bio_err, "bad magic number\n");
+ goto end;
+ }
+ sptr = salt;
+ }
+
+ if (pbkdf2 == 1) {
+ /*
+ * derive key and default iv
+ * concatenated into a temporary buffer
+ */
+ unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];
+ int iklen = EVP_CIPHER_key_length(cipher);
+ int ivlen = EVP_CIPHER_iv_length(cipher);
+ /* not needed if HASH_UPDATE() is fixed : */
+ int islen = (sptr != NULL ? sizeof(salt) : 0);
+ if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen,
+ iter, dgst, iklen+ivlen, tmpkeyiv)) {
+ BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n");
+ goto end;
+ }
+ /* split and move data back to global buffer */
+ memcpy(key, tmpkeyiv, iklen);
+ memcpy(iv, tmpkeyiv+iklen, ivlen);
+ } else {
+ BIO_printf(bio_err, "*** WARNING : "
+ "deprecated key derivation used.\n"
+ "Using -iter or -pbkdf2 would be better.\n");
+ if (!EVP_BytesToKey(cipher, dgst, sptr,
+ (unsigned char *)str, str_len,
+ 1, key, iv)) {
+ BIO_printf(bio_err, "EVP_BytesToKey failed\n");
+ goto end;
+ }
+ }
+ /*
+ * zero the complete buffer or the string passed from the command
+ * line.
+ */
+ if (str == strbuf)
+ OPENSSL_cleanse(str, SIZE);
+ else
+ OPENSSL_cleanse(str, str_len);
+ }
+ if (hiv != NULL) {
+ int siz = EVP_CIPHER_iv_length(cipher);
+ if (siz == 0) {
+ BIO_printf(bio_err, "warning: iv not use by this cipher\n");
+ } else if (!set_hex(hiv, iv, siz)) {
+ BIO_printf(bio_err, "invalid hex iv value\n");
+ goto end;
+ }
+ }
+ if ((hiv == NULL) && (str == NULL)
+ && EVP_CIPHER_iv_length(cipher) != 0) {
+ /*
+ * No IV was explicitly set and no IV was generated.
+ * Hence the IV is undefined, making correct decryption impossible.
+ */
+ BIO_printf(bio_err, "iv undefined\n");
+ goto end;
+ }
+ if (hkey != NULL) {
+ if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) {
+ BIO_printf(bio_err, "invalid hex key value\n");
+ goto end;
+ }
+ /* wiping secret data as we no longer need it */
+ OPENSSL_cleanse(hkey, strlen(hkey));
+ }
+
+ if ((benc = BIO_new(BIO_f_cipher())) == NULL)
+ goto end;
+
+ /*
+ * Since we may be changing parameters work on the encryption context
+ * rather than calling BIO_set_cipher().
+ */
+
+ BIO_get_cipher_ctx(benc, &ctx);
+
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) {
+ BIO_printf(bio_err, "Error setting cipher %s\n",
+ EVP_CIPHER_name(cipher));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (nopad)
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
+ BIO_printf(bio_err, "Error setting cipher %s\n",
+ EVP_CIPHER_name(cipher));
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (debug) {
+ BIO_set_callback(benc, BIO_debug_callback);
+ BIO_set_callback_arg(benc, (char *)bio_err);
+ }
+
+ if (printkey) {
+ if (!nosalt) {
+ printf("salt=");
+ for (i = 0; i < (int)sizeof(salt); i++)
+ printf("%02X", salt[i]);
+ printf("\n");
+ }
+ if (EVP_CIPHER_key_length(cipher) > 0) {
+ printf("key=");
+ for (i = 0; i < EVP_CIPHER_key_length(cipher); i++)
+ printf("%02X", key[i]);
+ printf("\n");
+ }
+ if (EVP_CIPHER_iv_length(cipher) > 0) {
+ printf("iv =");
+ for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++)
+ printf("%02X", iv[i]);
+ printf("\n");
+ }
+ if (printkey == 2) {
+ ret = 0;
+ goto end;
+ }
+ }
+ }
+
+ /* Only encrypt/decrypt as we write the file */
+ if (benc != NULL)
+ wbio = BIO_push(benc, wbio);
+
+ for (;;) {
+ inl = BIO_read(rbio, (char *)buff, bsize);
+ if (inl <= 0)
+ break;
+ if (BIO_write(wbio, (char *)buff, inl) != inl) {
+ BIO_printf(bio_err, "error writing output file\n");
+ goto end;
+ }
+ }
+ if (!BIO_flush(wbio)) {
+ BIO_printf(bio_err, "bad decrypt\n");
+ goto end;
+ }
+
+ ret = 0;
+ if (verbose) {
+ BIO_printf(bio_err, "bytes read : %8ju\n", BIO_number_read(in));
+ BIO_printf(bio_err, "bytes written: %8ju\n", BIO_number_written(out));
+ }
+ end:
+ ERR_print_errors(bio_err);
+ OPENSSL_free(strbuf);
+ OPENSSL_free(buff);
+ BIO_free(in);
+ BIO_free_all(out);
+ BIO_free(benc);
+ BIO_free(b64);
+#ifdef ZLIB
+ BIO_free(bzl);
+#endif
+ release_engine(e);
+ OPENSSL_free(pass);
+ return ret;
+}
+
+static void show_ciphers(const OBJ_NAME *name, void *arg)
+{
+ struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg;
+ const EVP_CIPHER *cipher;
+
+ if (!islower((unsigned char)*name->name))
+ return;
+
+ /* Filter out ciphers that we cannot use */
+ cipher = EVP_get_cipherbyname(name->name);
+ if (cipher == NULL ||
+ (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 ||
+ EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)
+ return;
+
+ BIO_printf(dec->bio, "-%-25s", name->name);
+ if (++dec->n == 3) {
+ BIO_printf(dec->bio, "\n");
+ dec->n = 0;
+ } else
+ BIO_printf(dec->bio, " ");
+}
+
+static int set_hex(const char *in, unsigned char *out, int size)
+{
+ int i, n;
+ unsigned char j;
+
+ i = size * 2;
+ n = strlen(in);
+ if (n > i) {
+ BIO_printf(bio_err, "hex string is too long, ignoring excess\n");
+ n = i; /* ignore exceeding part */
+ } else if (n < i) {
+ BIO_printf(bio_err, "hex string is too short, padding with zero bytes to length\n");
+ }
+
+ memset(out, 0, size);
+ for (i = 0; i < n; i++) {
+ j = (unsigned char)*in++;
+ if (!isxdigit(j)) {
+ BIO_printf(bio_err, "non-hex digit\n");
+ return 0;
+ }
+ j = (unsigned char)OPENSSL_hexchar2int(j);
+ if (i & 1)
+ out[i / 2] |= j;
+ else
+ out[i / 2] = (j << 4);
+ }
+ return 1;
+}
diff --git a/freebsd/crypto/openssl/apps/engine.c b/freebsd/crypto/openssl/apps/engine.c
new file mode 100644
index 00000000..bb77255b
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/engine.c
@@ -0,0 +1,491 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_ENGINE
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include "apps.h"
+# include "progs.h"
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <openssl/err.h>
+# include <openssl/engine.h>
+# include <openssl/ssl.h>
+# include <openssl/store.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
+ OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
+} OPTION_CHOICE;
+
+const OPTIONS engine_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"},
+ {OPT_HELP_STR, 1, '-',
+ " engine... Engines to load\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"v", OPT_V, '-', "List 'control commands' For each specified engine"},
+ {"vv", OPT_VV, '-', "Also display each command's description"},
+ {"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
+ {"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
+ {"c", OPT_C, '-', "List the capabilities of specified engine"},
+ {"t", OPT_T, '-', "Check that specified engine is available"},
+ {"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
+ {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
+ {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
+ {OPT_MORE_STR, OPT_EOF, 1,
+ "Commands are like \"SO_PATH:/lib/libdriver.so\""},
+ {NULL}
+};
+
+static int append_buf(char **buf, int *size, const char *s)
+{
+ const int expand = 256;
+ int len = strlen(s) + 1;
+ char *p = *buf;
+
+ if (p == NULL) {
+ *size = ((len + expand - 1) / expand) * expand;
+ p = *buf = app_malloc(*size, "engine buffer");
+ } else {
+ const int blen = strlen(p);
+
+ if (blen > 0)
+ len += 2 + blen;
+
+ if (len > *size) {
+ *size = ((len + expand - 1) / expand) * expand;
+ p = OPENSSL_realloc(p, *size);
+ if (p == NULL) {
+ OPENSSL_free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+ *buf = p;
+ }
+
+ if (blen > 0) {
+ p += blen;
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ }
+
+ strcpy(p, s);
+ return 1;
+}
+
+static int util_flags(BIO *out, unsigned int flags, const char *indent)
+{
+ int started = 0, err = 0;
+ /* Indent before displaying input flags */
+ BIO_printf(out, "%s%s(input flags): ", indent, indent);
+ if (flags == 0) {
+ BIO_printf(out, "<no flags>\n");
+ return 1;
+ }
+ /*
+ * If the object is internal, mark it in a way that shows instead of
+ * having it part of all the other flags, even if it really is.
+ */
+ if (flags & ENGINE_CMD_FLAG_INTERNAL) {
+ BIO_printf(out, "[Internal] ");
+ }
+
+ if (flags & ENGINE_CMD_FLAG_NUMERIC) {
+ BIO_printf(out, "NUMERIC");
+ started = 1;
+ }
+ /*
+ * Now we check that no combinations of the mutually exclusive NUMERIC,
+ * STRING, and NO_INPUT flags have been used. Future flags that can be
+ * OR'd together with these would need to added after these to preserve
+ * the testing logic.
+ */
+ if (flags & ENGINE_CMD_FLAG_STRING) {
+ if (started) {
+ BIO_printf(out, "|");
+ err = 1;
+ }
+ BIO_printf(out, "STRING");
+ started = 1;
+ }
+ if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
+ if (started) {
+ BIO_printf(out, "|");
+ err = 1;
+ }
+ BIO_printf(out, "NO_INPUT");
+ started = 1;
+ }
+ /* Check for unknown flags */
+ flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
+ ~ENGINE_CMD_FLAG_STRING &
+ ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL;
+ if (flags) {
+ if (started)
+ BIO_printf(out, "|");
+ BIO_printf(out, "<0x%04X>", flags);
+ }
+ if (err)
+ BIO_printf(out, " <illegal flags!>");
+ BIO_printf(out, "\n");
+ return 1;
+}
+
+static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent)
+{
+ static const int line_wrap = 78;
+ int num;
+ int ret = 0;
+ char *name = NULL;
+ char *desc = NULL;
+ int flags;
+ int xpos = 0;
+ STACK_OF(OPENSSL_STRING) *cmds = NULL;
+ if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
+ ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
+ 0, NULL, NULL)) <= 0)) {
+ return 1;
+ }
+
+ cmds = sk_OPENSSL_STRING_new_null();
+ if (cmds == NULL)
+ goto err;
+
+ do {
+ int len;
+ /* Get the command input flags */
+ if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
+ NULL, NULL)) < 0)
+ goto err;
+ if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) {
+ /* Get the command name */
+ if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
+ NULL, NULL)) <= 0)
+ goto err;
+ name = app_malloc(len + 1, "name buffer");
+ if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
+ NULL) <= 0)
+ goto err;
+ /* Get the command description */
+ if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
+ NULL, NULL)) < 0)
+ goto err;
+ if (len > 0) {
+ desc = app_malloc(len + 1, "description buffer");
+ if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
+ NULL) <= 0)
+ goto err;
+ }
+ /* Now decide on the output */
+ if (xpos == 0)
+ /* Do an indent */
+ xpos = BIO_puts(out, indent);
+ else
+ /* Otherwise prepend a ", " */
+ xpos += BIO_printf(out, ", ");
+ if (verbose == 1) {
+ /*
+ * We're just listing names, comma-delimited
+ */
+ if ((xpos > (int)strlen(indent)) &&
+ (xpos + (int)strlen(name) > line_wrap)) {
+ BIO_printf(out, "\n");
+ xpos = BIO_puts(out, indent);
+ }
+ xpos += BIO_printf(out, "%s", name);
+ } else {
+ /* We're listing names plus descriptions */
+ BIO_printf(out, "%s: %s\n", name,
+ (desc == NULL) ? "<no description>" : desc);
+ /* ... and sometimes input flags */
+ if ((verbose >= 3) && !util_flags(out, flags, indent))
+ goto err;
+ xpos = 0;
+ }
+ }
+ OPENSSL_free(name);
+ name = NULL;
+ OPENSSL_free(desc);
+ desc = NULL;
+ /* Move to the next command */
+ num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL);
+ } while (num > 0);
+ if (xpos > 0)
+ BIO_printf(out, "\n");
+ ret = 1;
+ err:
+ sk_OPENSSL_STRING_free(cmds);
+ OPENSSL_free(name);
+ OPENSSL_free(desc);
+ return ret;
+}
+
+static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
+ BIO *out, const char *indent)
+{
+ int loop, res, num = sk_OPENSSL_STRING_num(cmds);
+
+ if (num < 0) {
+ BIO_printf(out, "[Error]: internal stack error\n");
+ return;
+ }
+ for (loop = 0; loop < num; loop++) {
+ char buf[256];
+ const char *cmd, *arg;
+ cmd = sk_OPENSSL_STRING_value(cmds, loop);
+ res = 1; /* assume success */
+ /* Check if this command has no ":arg" */
+ if ((arg = strstr(cmd, ":")) == NULL) {
+ if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
+ res = 0;
+ } else {
+ if ((int)(arg - cmd) > 254) {
+ BIO_printf(out, "[Error]: command name too long\n");
+ return;
+ }
+ memcpy(buf, cmd, (int)(arg - cmd));
+ buf[arg - cmd] = '\0';
+ arg++; /* Move past the ":" */
+ /* Call the command with the argument */
+ if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
+ res = 0;
+ }
+ if (res) {
+ BIO_printf(out, "[Success]: %s\n", cmd);
+ } else {
+ BIO_printf(out, "[Failure]: %s\n", cmd);
+ ERR_print_errors(out);
+ }
+ }
+}
+
+struct util_store_cap_data {
+ ENGINE *engine;
+ char **cap_buf;
+ int *cap_size;
+ int ok;
+};
+static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg)
+{
+ struct util_store_cap_data *ctx = arg;
+
+ if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) {
+ char buf[256];
+ BIO_snprintf(buf, sizeof(buf), "STORE(%s)",
+ OSSL_STORE_LOADER_get0_scheme(loader));
+ if (!append_buf(ctx->cap_buf, ctx->cap_size, buf))
+ ctx->ok = 0;
+ }
+}
+
+int engine_main(int argc, char **argv)
+{
+ int ret = 1, i;
+ int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
+ ENGINE *e;
+ STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null();
+ STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null();
+ STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null();
+ BIO *out;
+ const char *indent = " ";
+ OPTION_CHOICE o;
+ char *prog;
+ char *argv1;
+
+ out = dup_bio_out(FORMAT_TEXT);
+ if (engines == NULL || pre_cmds == NULL || post_cmds == NULL)
+ goto end;
+
+ /* Remember the original command name, parse/skip any leading engine
+ * names, and then setup to parse the rest of the line as flags. */
+ prog = argv[0];
+ while ((argv1 = argv[1]) != NULL && *argv1 != '-') {
+ sk_OPENSSL_CSTRING_push(engines, argv1);
+ argc--;
+ argv++;
+ }
+ argv[0] = prog;
+ opt_init(argc, argv, engine_options);
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(engine_options);
+ ret = 0;
+ goto end;
+ case OPT_VVVV:
+ case OPT_VVV:
+ case OPT_VV:
+ case OPT_V:
+ /* Convert to an integer from one to four. */
+ i = (int)(o - OPT_V) + 1;
+ if (verbose < i)
+ verbose = i;
+ break;
+ case OPT_C:
+ list_cap = 1;
+ break;
+ case OPT_TT:
+ test_avail_noise++;
+ /* fall thru */
+ case OPT_T:
+ test_avail++;
+ break;
+ case OPT_PRE:
+ sk_OPENSSL_STRING_push(pre_cmds, opt_arg());
+ break;
+ case OPT_POST:
+ sk_OPENSSL_STRING_push(post_cmds, opt_arg());
+ break;
+ }
+ }
+
+ /* Allow any trailing parameters as engine names. */
+ argc = opt_num_rest();
+ argv = opt_rest();
+ for ( ; *argv; argv++) {
+ if (**argv == '-') {
+ BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n",
+ prog);
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ }
+ sk_OPENSSL_CSTRING_push(engines, *argv);
+ }
+
+ if (sk_OPENSSL_CSTRING_num(engines) == 0) {
+ for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
+ sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e));
+ }
+ }
+
+ ret = 0;
+ for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) {
+ const char *id = sk_OPENSSL_CSTRING_value(engines, i);
+ if ((e = ENGINE_by_id(id)) != NULL) {
+ const char *name = ENGINE_get_name(e);
+ /*
+ * Do "id" first, then "name". Easier to auto-parse.
+ */
+ BIO_printf(out, "(%s) %s\n", id, name);
+ util_do_cmds(e, pre_cmds, out, indent);
+ if (strcmp(ENGINE_get_id(e), id) != 0) {
+ BIO_printf(out, "Loaded: (%s) %s\n",
+ ENGINE_get_id(e), ENGINE_get_name(e));
+ }
+ if (list_cap) {
+ int cap_size = 256;
+ char *cap_buf = NULL;
+ int k, n;
+ const int *nids;
+ ENGINE_CIPHERS_PTR fn_c;
+ ENGINE_DIGESTS_PTR fn_d;
+ ENGINE_PKEY_METHS_PTR fn_pk;
+
+ if (ENGINE_get_RSA(e) != NULL
+ && !append_buf(&cap_buf, &cap_size, "RSA"))
+ goto end;
+ if (ENGINE_get_DSA(e) != NULL
+ && !append_buf(&cap_buf, &cap_size, "DSA"))
+ goto end;
+ if (ENGINE_get_DH(e) != NULL
+ && !append_buf(&cap_buf, &cap_size, "DH"))
+ goto end;
+ if (ENGINE_get_RAND(e) != NULL
+ && !append_buf(&cap_buf, &cap_size, "RAND"))
+ goto end;
+
+ fn_c = ENGINE_get_ciphers(e);
+ if (fn_c == NULL)
+ goto skip_ciphers;
+ n = fn_c(e, NULL, &nids, 0);
+ for (k = 0; k < n; ++k)
+ if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
+ goto end;
+
+ skip_ciphers:
+ fn_d = ENGINE_get_digests(e);
+ if (fn_d == NULL)
+ goto skip_digests;
+ n = fn_d(e, NULL, &nids, 0);
+ for (k = 0; k < n; ++k)
+ if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
+ goto end;
+
+ skip_digests:
+ fn_pk = ENGINE_get_pkey_meths(e);
+ if (fn_pk == NULL)
+ goto skip_pmeths;
+ n = fn_pk(e, NULL, &nids, 0);
+ for (k = 0; k < n; ++k)
+ if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
+ goto end;
+ skip_pmeths:
+ {
+ struct util_store_cap_data store_ctx;
+
+ store_ctx.engine = e;
+ store_ctx.cap_buf = &cap_buf;
+ store_ctx.cap_size = &cap_size;
+ store_ctx.ok = 1;
+
+ OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx);
+ if (!store_ctx.ok)
+ goto end;
+ }
+ if (cap_buf != NULL && (*cap_buf != '\0'))
+ BIO_printf(out, " [%s]\n", cap_buf);
+
+ OPENSSL_free(cap_buf);
+ }
+ if (test_avail) {
+ BIO_printf(out, "%s", indent);
+ if (ENGINE_init(e)) {
+ BIO_printf(out, "[ available ]\n");
+ util_do_cmds(e, post_cmds, out, indent);
+ ENGINE_finish(e);
+ } else {
+ BIO_printf(out, "[ unavailable ]\n");
+ if (test_avail_noise)
+ ERR_print_errors_fp(stdout);
+ ERR_clear_error();
+ }
+ }
+ if ((verbose > 0) && !util_verbose(e, verbose, out, indent))
+ goto end;
+ ENGINE_free(e);
+ } else {
+ ERR_print_errors(bio_err);
+ /* because exit codes above 127 have special meaning on Unix */
+ if (++ret > 127)
+ ret = 127;
+ }
+ }
+
+ end:
+
+ ERR_print_errors(bio_err);
+ sk_OPENSSL_CSTRING_free(engines);
+ sk_OPENSSL_STRING_free(pre_cmds);
+ sk_OPENSSL_STRING_free(post_cmds);
+ BIO_free_all(out);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/errstr.c b/freebsd/crypto/openssl/apps/errstr.c
new file mode 100644
index 00000000..ae430510
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/errstr.c
@@ -0,0 +1,69 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP
+} OPTION_CHOICE;
+
+const OPTIONS errstr_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"},
+ {OPT_HELP_STR, 1, '-', " errnum Error number\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {NULL}
+};
+
+int errstr_main(int argc, char **argv)
+{
+ OPTION_CHOICE o;
+ char buf[256], *prog;
+ int ret = 1;
+ unsigned long l;
+
+ prog = opt_init(argc, argv, errstr_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(errstr_options);
+ ret = 0;
+ goto end;
+ }
+ }
+
+ ret = 0;
+ for (argv = opt_rest(); *argv; argv++) {
+ if (sscanf(*argv, "%lx", &l) == 0) {
+ ret++;
+ } else {
+ /* We're not really an SSL application so this won't auto-init, but
+ * we're still interested in SSL error strings
+ */
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+ ERR_error_string_n(l, buf, sizeof(buf));
+ BIO_printf(bio_out, "%s\n", buf);
+ }
+ }
+ end:
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/gendsa.c b/freebsd/crypto/openssl/apps/gendsa.c
new file mode 100644
index 00000000..ef845c75
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/gendsa.c
@@ -0,0 +1,148 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_DSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <string.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/bn.h>
+# include <openssl/dsa.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS gendsa_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"out", OPT_OUT, '>', "Output the key to the specified file"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ OPT_R_OPTIONS,
+ {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int gendsa_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ BIO *out = NULL, *in = NULL;
+ DSA *dsa = NULL;
+ const EVP_CIPHER *enc = NULL;
+ char *dsaparams = NULL;
+ char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog;
+ OPTION_CHOICE o;
+ int ret = 1, private = 0;
+ const BIGNUM *p = NULL;
+
+ prog = opt_init(argc, argv, gendsa_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ ret = 0;
+ opt_help(gendsa_options);
+ goto end;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+ private = 1;
+
+ if (argc != 1)
+ goto opthelp;
+ dsaparams = *argv;
+
+ if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ in = bio_open_default(dsaparams, 'r', FORMAT_PEM);
+ if (in == NULL)
+ goto end2;
+
+ if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) {
+ BIO_printf(bio_err, "unable to load DSA parameter file\n");
+ goto end;
+ }
+ BIO_free(in);
+ in = NULL;
+
+ out = bio_open_owner(outfile, FORMAT_PEM, private);
+ if (out == NULL)
+ goto end2;
+
+ DSA_get0_pqg(dsa, &p, NULL, NULL);
+
+ if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS)
+ BIO_printf(bio_err,
+ "Warning: It is not recommended to use more than %d bit for DSA keys.\n"
+ " Your key size is %d! Larger key size may behave not as expected.\n",
+ OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p));
+
+ BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
+ if (!DSA_generate_key(dsa))
+ goto end;
+
+ assert(private);
+ if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout))
+ goto end;
+ ret = 0;
+ end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ end2:
+ BIO_free(in);
+ BIO_free_all(out);
+ DSA_free(dsa);
+ release_engine(e);
+ OPENSSL_free(passout);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/genpkey.c b/freebsd/crypto/openssl/apps/genpkey.c
new file mode 100644
index 00000000..d420c885
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/genpkey.c
@@ -0,0 +1,324 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#ifndef OPENSSL_NO_ENGINE
+# include <openssl/engine.h>
+#endif
+
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e);
+static int genpkey_cb(EVP_PKEY_CTX *ctx);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE,
+ OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER
+} OPTION_CHOICE;
+
+const OPTIONS genpkey_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"},
+ {"pass", OPT_PASS, 's', "Output file pass phrase source"},
+ {"paramfile", OPT_PARAMFILE, '<', "Parameters file"},
+ {"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"},
+ {"pkeyopt", OPT_PKEYOPT, 's',
+ "Set the public key algorithm option as opt:value"},
+ {"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"},
+ {"text", OPT_TEXT, '-', "Print the in text"},
+ {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ /* This is deliberately last. */
+ {OPT_HELP_STR, 1, 1,
+ "Order of options may be important! See the documentation.\n"},
+ {NULL}
+};
+
+int genpkey_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog;
+ const EVP_CIPHER *cipher = NULL;
+ OPTION_CHOICE o;
+ int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0;
+ int private = 0;
+
+ prog = opt_init(argc, argv, genpkey_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ ret = 0;
+ opt_help(genpkey_options);
+ goto end;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASS:
+ passarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PARAMFILE:
+ if (do_param == 1)
+ goto opthelp;
+ if (!init_keygen_file(&ctx, opt_arg(), e))
+ goto end;
+ break;
+ case OPT_ALGORITHM:
+ if (!init_gen_str(&ctx, opt_arg(), e, do_param))
+ goto end;
+ break;
+ case OPT_PKEYOPT:
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "%s: No keytype specified.\n", prog);
+ goto opthelp;
+ }
+ if (pkey_ctrl_string(ctx, opt_arg()) <= 0) {
+ BIO_printf(bio_err,
+ "%s: Error setting %s parameter:\n",
+ prog, opt_arg());
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ break;
+ case OPT_GENPARAM:
+ if (ctx != NULL)
+ goto opthelp;
+ do_param = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &cipher)
+ || do_param == 1)
+ goto opthelp;
+ if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE ||
+ EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE ||
+ EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE ||
+ EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) {
+ BIO_printf(bio_err, "%s: cipher mode not supported\n", prog);
+ goto end;
+ }
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = do_param ? 0 : 1;
+
+ if (ctx == NULL)
+ goto opthelp;
+
+ if (!app_passwd(passarg, NULL, &pass, NULL)) {
+ BIO_puts(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ EVP_PKEY_CTX_set_cb(ctx, genpkey_cb);
+ EVP_PKEY_CTX_set_app_data(ctx, bio_err);
+
+ if (do_param) {
+ if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
+ BIO_puts(bio_err, "Error generating parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+ if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
+ BIO_puts(bio_err, "Error generating key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (do_param) {
+ rv = PEM_write_bio_Parameters(out, pkey);
+ } else if (outformat == FORMAT_PEM) {
+ assert(private);
+ rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass);
+ } else if (outformat == FORMAT_ASN1) {
+ assert(private);
+ rv = i2d_PrivateKey_bio(out, pkey);
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+
+ if (rv <= 0) {
+ BIO_puts(bio_err, "Error writing key\n");
+ ERR_print_errors(bio_err);
+ }
+
+ if (text) {
+ if (do_param)
+ rv = EVP_PKEY_print_params(out, pkey, 0, NULL);
+ else
+ rv = EVP_PKEY_print_private(out, pkey, 0, NULL);
+
+ if (rv <= 0) {
+ BIO_puts(bio_err, "Error printing key\n");
+ ERR_print_errors(bio_err);
+ }
+ }
+
+ ret = 0;
+
+ end:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ BIO_free_all(out);
+ BIO_free(in);
+ release_engine(e);
+ OPENSSL_free(pass);
+ return ret;
+}
+
+static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e)
+{
+ BIO *pbio;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ if (*pctx) {
+ BIO_puts(bio_err, "Parameters already set!\n");
+ return 0;
+ }
+
+ pbio = BIO_new_file(file, "r");
+ if (!pbio) {
+ BIO_printf(bio_err, "Can't open parameter file %s\n", file);
+ return 0;
+ }
+
+ pkey = PEM_read_bio_Parameters(pbio, NULL);
+ BIO_free(pbio);
+
+ if (!pkey) {
+ BIO_printf(bio_err, "Error reading parameter file %s\n", file);
+ return 0;
+ }
+
+ ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (ctx == NULL)
+ goto err;
+ if (EVP_PKEY_keygen_init(ctx) <= 0)
+ goto err;
+ EVP_PKEY_free(pkey);
+ *pctx = ctx;
+ return 1;
+
+ err:
+ BIO_puts(bio_err, "Error initializing context\n");
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ return 0;
+
+}
+
+int init_gen_str(EVP_PKEY_CTX **pctx,
+ const char *algname, ENGINE *e, int do_param)
+{
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng = NULL;
+ int pkey_id;
+
+ if (*pctx) {
+ BIO_puts(bio_err, "Algorithm already set!\n");
+ return 0;
+ }
+
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
+
+#ifndef OPENSSL_NO_ENGINE
+ if (!ameth && e)
+ ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
+#endif
+
+ if (!ameth) {
+ BIO_printf(bio_err, "Algorithm %s not found\n", algname);
+ return 0;
+ }
+
+ ERR_clear_error();
+
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(tmpeng);
+#endif
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
+
+ if (!ctx)
+ goto err;
+ if (do_param) {
+ if (EVP_PKEY_paramgen_init(ctx) <= 0)
+ goto err;
+ } else {
+ if (EVP_PKEY_keygen_init(ctx) <= 0)
+ goto err;
+ }
+
+ *pctx = ctx;
+ return 1;
+
+ err:
+ BIO_printf(bio_err, "Error initializing %s context\n", algname);
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(ctx);
+ return 0;
+
+}
+
+static int genpkey_cb(EVP_PKEY_CTX *ctx)
+{
+ char c = '*';
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
+ int p;
+ p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ if (p == 0)
+ c = '.';
+ if (p == 1)
+ c = '+';
+ if (p == 2)
+ c = '*';
+ if (p == 3)
+ c = '\n';
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
+ return 1;
+}
diff --git a/freebsd/crypto/openssl/apps/genrsa.c b/freebsd/crypto/openssl/apps/genrsa.c
new file mode 100644
index 00000000..3becea60
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/genrsa.c
@@ -0,0 +1,203 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_RSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <string.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/bn.h>
+# include <openssl/rsa.h>
+# include <openssl/evp.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+# include <openssl/rand.h>
+
+# define DEFBITS 2048
+# define DEFPRIMES 2
+
+static int genrsa_cb(int p, int n, BN_GENCB *cb);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_3, OPT_F4, OPT_ENGINE,
+ OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS genrsa_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"3", OPT_3, '-', "Use 3 for the E value"},
+ {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
+ {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
+ {"out", OPT_OUT, '>', "Output the key to specified file"},
+ OPT_R_OPTIONS,
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {"primes", OPT_PRIMES, 'p', "Specify number of primes"},
+ {NULL}
+};
+
+int genrsa_main(int argc, char **argv)
+{
+ BN_GENCB *cb = BN_GENCB_new();
+ PW_CB_DATA cb_data;
+ ENGINE *eng = NULL;
+ BIGNUM *bn = BN_new();
+ BIO *out = NULL;
+ const BIGNUM *e;
+ RSA *rsa = NULL;
+ const EVP_CIPHER *enc = NULL;
+ int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES;
+ unsigned long f4 = RSA_F4;
+ char *outfile = NULL, *passoutarg = NULL, *passout = NULL;
+ char *prog, *hexe, *dece;
+ OPTION_CHOICE o;
+
+ if (bn == NULL || cb == NULL)
+ goto end;
+
+ BN_GENCB_set(cb, genrsa_cb, bio_err);
+
+ prog = opt_init(argc, argv, genrsa_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ ret = 0;
+ opt_help(genrsa_options);
+ goto end;
+ case OPT_3:
+ f4 = 3;
+ break;
+ case OPT_F4:
+ f4 = RSA_F4;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ eng = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto end;
+ break;
+ case OPT_PRIMES:
+ if (!opt_int(opt_arg(), &primes))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (argc == 1) {
+ if (!opt_int(argv[0], &num) || num <= 0)
+ goto end;
+ if (num > OPENSSL_RSA_MAX_MODULUS_BITS)
+ BIO_printf(bio_err,
+ "Warning: It is not recommended to use more than %d bit for RSA keys.\n"
+ " Your key size is %d! Larger key size may behave not as expected.\n",
+ OPENSSL_RSA_MAX_MODULUS_BITS, num);
+ } else if (argc > 0) {
+ BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ }
+
+ private = 1;
+ if (!app_passwd(NULL, passoutarg, NULL, &passout)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, FORMAT_PEM, private);
+ if (out == NULL)
+ goto end;
+
+ BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
+ num, primes);
+ rsa = eng ? RSA_new_method(eng) : RSA_new();
+ if (rsa == NULL)
+ goto end;
+
+ if (!BN_set_word(bn, f4)
+ || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb))
+ goto end;
+
+ RSA_get0_key(rsa, NULL, &e, NULL);
+ hexe = BN_bn2hex(e);
+ dece = BN_bn2dec(e);
+ if (hexe && dece) {
+ BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
+ }
+ OPENSSL_free(hexe);
+ OPENSSL_free(dece);
+ cb_data.password = passout;
+ cb_data.prompt_info = outfile;
+ assert(private);
+ if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0,
+ (pem_password_cb *)password_callback,
+ &cb_data))
+ goto end;
+
+ ret = 0;
+ end:
+ BN_free(bn);
+ BN_GENCB_free(cb);
+ RSA_free(rsa);
+ BIO_free_all(out);
+ release_engine(eng);
+ OPENSSL_free(passout);
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ return ret;
+}
+
+static int genrsa_cb(int p, int n, BN_GENCB *cb)
+{
+ char c = '*';
+
+ if (p == 0)
+ c = '.';
+ if (p == 1)
+ c = '+';
+ if (p == 2)
+ c = '*';
+ if (p == 3)
+ c = '\n';
+ BIO_write(BN_GENCB_get_arg(cb), &c, 1);
+ (void)BIO_flush(BN_GENCB_get_arg(cb));
+ return 1;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/nseq.c b/freebsd/crypto/openssl/apps/nseq.c
new file mode 100644
index 00000000..57047f35
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/nseq.c
@@ -0,0 +1,116 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_TOSEQ, OPT_IN, OPT_OUT
+} OPTION_CHOICE;
+
+const OPTIONS nseq_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {NULL}
+};
+
+int nseq_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ X509 *x509 = NULL;
+ NETSCAPE_CERT_SEQUENCE *seq = NULL;
+ OPTION_CHOICE o;
+ int toseq = 0, ret = 1, i;
+ char *infile = NULL, *outfile = NULL, *prog;
+
+ prog = opt_init(argc, argv, nseq_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ ret = 0;
+ opt_help(nseq_options);
+ goto end;
+ case OPT_TOSEQ:
+ toseq = 1;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ in = bio_open_default(infile, 'r', FORMAT_PEM);
+ if (in == NULL)
+ goto end;
+ out = bio_open_default(outfile, 'w', FORMAT_PEM);
+ if (out == NULL)
+ goto end;
+
+ if (toseq) {
+ seq = NETSCAPE_CERT_SEQUENCE_new();
+ if (seq == NULL)
+ goto end;
+ seq->certs = sk_X509_new_null();
+ if (seq->certs == NULL)
+ goto end;
+ while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)))
+ sk_X509_push(seq->certs, x509);
+
+ if (!sk_X509_num(seq->certs)) {
+ BIO_printf(bio_err, "%s: Error reading certs file %s\n",
+ prog, infile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ PEM_write_bio_NETSCAPE_CERT_SEQUENCE(out, seq);
+ ret = 0;
+ goto end;
+ }
+
+ seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL, NULL);
+ if (seq == NULL) {
+ BIO_printf(bio_err, "%s: Error reading sequence file %s\n",
+ prog, infile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ for (i = 0; i < sk_X509_num(seq->certs); i++) {
+ x509 = sk_X509_value(seq->certs, i);
+ dump_cert_text(out, x509);
+ PEM_write_bio_X509(out, x509);
+ }
+ ret = 0;
+ end:
+ BIO_free(in);
+ BIO_free_all(out);
+ NETSCAPE_CERT_SEQUENCE_free(seq);
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/ocsp.c b/freebsd/crypto/openssl/apps/ocsp.c
new file mode 100644
index 00000000..6494fa27
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ocsp.c
@@ -0,0 +1,1595 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_OCSP
+NON_EMPTY_TRANSLATION_UNIT
+#else
+# ifdef OPENSSL_SYS_VMS
+# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
+ * on OpenVMS */
+# endif
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <ctype.h>
+
+/* Needs to be included before the openssl headers */
+# include "apps.h"
+# include "progs.h"
+# include "internal/sockets.h"
+# include <openssl/e_os2.h>
+# include <openssl/crypto.h>
+# include <openssl/err.h>
+# include <openssl/ssl.h>
+# include <openssl/evp.h>
+# include <openssl/bn.h>
+# include <openssl/x509v3.h>
+# include <openssl/rand.h>
+
+# if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_NO_SOCK) \
+ && !defined(OPENSSL_NO_POSIX_IO)
+# define OCSP_DAEMON
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <syslog.h>
+# include <signal.h>
+# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
+# else
+# undef LOG_INFO
+# undef LOG_WARNING
+# undef LOG_ERR
+# define LOG_INFO 0
+# define LOG_WARNING 1
+# define LOG_ERR 2
+# endif
+
+/* Maximum leeway in validity period: default 5 minutes */
+# define MAX_VALIDITY_PERIOD (5 * 60)
+
+static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
+ const EVP_MD *cert_id_md, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids);
+static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
+ const EVP_MD *cert_id_md, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids);
+static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+ STACK_OF(OPENSSL_STRING) *names,
+ STACK_OF(OCSP_CERTID) *ids, long nsec,
+ long maxage);
+static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
+ CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
+ EVP_PKEY *rkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(X509) *rother, unsigned long flags,
+ int nmin, int ndays, int badsig);
+
+static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
+static BIO *init_responder(const char *port);
+static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout);
+static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
+static void log_message(int level, const char *fmt, ...);
+static char *prog;
+static int multi = 0;
+
+# ifdef OCSP_DAEMON
+static int acfd = (int) INVALID_SOCKET;
+static int index_changed(CA_DB *);
+static void spawn_loop(void);
+static int print_syslog(const char *str, size_t len, void *levPtr);
+static void sock_timeout(int signum);
+# endif
+
+# ifndef OPENSSL_NO_SOCK
+static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
+ const char *path,
+ const STACK_OF(CONF_VALUE) *headers,
+ OCSP_REQUEST *req, int req_timeout);
+# endif
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
+ OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE,
+ OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS,
+ OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN,
+ OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER,
+ OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT,
+ OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER,
+ OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH,
+ OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT,
+ OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL,
+ OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER,
+ OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER,
+ OPT_V_ENUM,
+ OPT_MD,
+ OPT_MULTI
+} OPTION_CHOICE;
+
+const OPTIONS ocsp_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"out", OPT_OUTFILE, '>', "Output filename"},
+ {"timeout", OPT_TIMEOUT, 'p',
+ "Connection timeout (in seconds) to the OCSP responder"},
+ {"url", OPT_URL, 's', "Responder URL"},
+ {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
+ {"port", OPT_PORT, 'p', "Port to run responder on"},
+ {"ignore_err", OPT_IGNORE_ERR, '-',
+ "Ignore error on OCSP request or response and continue running"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"},
+ {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"},
+ {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"},
+ {"resp_no_certs", OPT_RESP_NO_CERTS, '-',
+ "Don't include any certificates in response"},
+ {"resp_key_id", OPT_RESP_KEY_ID, '-',
+ "Identify response by signing certificate key ID"},
+# ifdef OCSP_DAEMON
+ {"multi", OPT_MULTI, 'p', "run multiple responder processes"},
+# endif
+ {"no_certs", OPT_NO_CERTS, '-',
+ "Don't include any certificates in signed request"},
+ {"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-',
+ "Don't check signature on response"},
+ {"no_cert_verify", OPT_NO_CERT_VERIFY, '-',
+ "Don't check signing certificate"},
+ {"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"},
+ {"no_cert_checks", OPT_NO_CERT_CHECKS, '-',
+ "Don't do additional checks on signing certificate"},
+ {"no_explicit", OPT_NO_EXPLICIT, '-',
+ "Do not explicitly check the chain, just verify the root"},
+ {"trust_other", OPT_TRUST_OTHER, '-',
+ "Don't verify additional certificates"},
+ {"no_intern", OPT_NO_INTERN, '-',
+ "Don't search certificates contained in response for signer"},
+ {"badsig", OPT_BADSIG, '-',
+ "Corrupt last byte of loaded OSCP response signature (for test)"},
+ {"text", OPT_TEXT, '-', "Print text form of request and response"},
+ {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"},
+ {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"},
+ {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
+ {"respin", OPT_RESPIN, 's', "File with the DER-encoded response"},
+ {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
+ {"VAfile", OPT_VAFILE, '<', "Validator certificates file"},
+ {"sign_other", OPT_SIGN_OTHER, '<',
+ "Additional certificates to include in signed request"},
+ {"verify_other", OPT_VERIFY_OTHER, '<',
+ "Additional certificates to search for signer"},
+ {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"validity_period", OPT_VALIDITY_PERIOD, 'u',
+ "Maximum validity discrepancy in seconds"},
+ {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
+ {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"},
+ {"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"},
+ {"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"},
+ {"path", OPT_PATH, 's', "Path to use in OCSP request"},
+ {"issuer", OPT_ISSUER, '<', "Issuer certificate"},
+ {"cert", OPT_CERT, '<', "Certificate to check"},
+ {"serial", OPT_SERIAL, 's', "Serial number to check"},
+ {"index", OPT_INDEX, '<', "Certificate status index file"},
+ {"CA", OPT_CA, '<', "CA certificate"},
+ {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"},
+ {"nrequest", OPT_REQUEST, 'p',
+ "Number of requests to accept (default unlimited)"},
+ {"ndays", OPT_NDAYS, 'p', "Number of days before next update"},
+ {"rsigner", OPT_RSIGNER, '<',
+ "Responder certificate to sign responses with"},
+ {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"},
+ {"rother", OPT_ROTHER, '<', "Other certificates to include in response"},
+ {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"},
+ {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"},
+ {"header", OPT_HEADER, 's', "key=value header to add"},
+ {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
+ OPT_V_OPTIONS,
+ {NULL}
+};
+
+int ocsp_main(int argc, char **argv)
+{
+ BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
+ const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
+ STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL;
+ int trailing_md = 0;
+ CA_DB *rdb = NULL;
+ EVP_PKEY *key = NULL, *rkey = NULL;
+ OCSP_BASICRESP *bs = NULL;
+ OCSP_REQUEST *req = NULL;
+ OCSP_RESPONSE *resp = NULL;
+ STACK_OF(CONF_VALUE) *headers = NULL;
+ STACK_OF(OCSP_CERTID) *ids = NULL;
+ STACK_OF(OPENSSL_STRING) *reqnames = NULL;
+ STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
+ STACK_OF(X509) *issuers = NULL;
+ X509 *issuer = NULL, *cert = NULL;
+ STACK_OF(X509) *rca_cert = NULL;
+ X509 *signer = NULL, *rsigner = NULL;
+ X509_STORE *store = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ const char *CAfile = NULL, *CApath = NULL;
+ char *header, *value;
+ char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
+ char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
+ char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
+ char *rsignfile = NULL, *rkeyfile = NULL;
+ char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
+ char *signfile = NULL, *keyfile = NULL;
+ char *thost = NULL, *tport = NULL, *tpath = NULL;
+ int noCAfile = 0, noCApath = 0;
+ int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
+ int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
+ int req_text = 0, resp_text = 0, ret = 1;
+ int req_timeout = -1;
+ long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
+ unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
+ OPTION_CHOICE o;
+
+ reqnames = sk_OPENSSL_STRING_new_null();
+ if (reqnames == NULL)
+ goto end;
+ ids = sk_OCSP_CERTID_new_null();
+ if (ids == NULL)
+ goto end;
+ if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
+ return 1;
+
+ prog = opt_init(argc, argv, ocsp_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ ret = 0;
+ opt_help(ocsp_options);
+ goto end;
+ case OPT_OUTFILE:
+ outfile = opt_arg();
+ break;
+ case OPT_TIMEOUT:
+#ifndef OPENSSL_NO_SOCK
+ req_timeout = atoi(opt_arg());
+#endif
+ break;
+ case OPT_URL:
+ OPENSSL_free(thost);
+ OPENSSL_free(tport);
+ OPENSSL_free(tpath);
+ thost = tport = tpath = NULL;
+ if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
+ BIO_printf(bio_err, "%s Error parsing URL\n", prog);
+ goto end;
+ }
+ thost = host;
+ tport = port;
+ tpath = path;
+ break;
+ case OPT_HOST:
+ host = opt_arg();
+ break;
+ case OPT_PORT:
+ port = opt_arg();
+ break;
+ case OPT_IGNORE_ERR:
+ ignore_err = 1;
+ break;
+ case OPT_NOVERIFY:
+ noverify = 1;
+ break;
+ case OPT_NONCE:
+ add_nonce = 2;
+ break;
+ case OPT_NO_NONCE:
+ add_nonce = 0;
+ break;
+ case OPT_RESP_NO_CERTS:
+ rflags |= OCSP_NOCERTS;
+ break;
+ case OPT_RESP_KEY_ID:
+ rflags |= OCSP_RESPID_KEY;
+ break;
+ case OPT_NO_CERTS:
+ sign_flags |= OCSP_NOCERTS;
+ break;
+ case OPT_NO_SIGNATURE_VERIFY:
+ verify_flags |= OCSP_NOSIGS;
+ break;
+ case OPT_NO_CERT_VERIFY:
+ verify_flags |= OCSP_NOVERIFY;
+ break;
+ case OPT_NO_CHAIN:
+ verify_flags |= OCSP_NOCHAIN;
+ break;
+ case OPT_NO_CERT_CHECKS:
+ verify_flags |= OCSP_NOCHECKS;
+ break;
+ case OPT_NO_EXPLICIT:
+ verify_flags |= OCSP_NOEXPLICIT;
+ break;
+ case OPT_TRUST_OTHER:
+ verify_flags |= OCSP_TRUSTOTHER;
+ break;
+ case OPT_NO_INTERN:
+ verify_flags |= OCSP_NOINTERN;
+ break;
+ case OPT_BADSIG:
+ badsig = 1;
+ break;
+ case OPT_TEXT:
+ req_text = resp_text = 1;
+ break;
+ case OPT_REQ_TEXT:
+ req_text = 1;
+ break;
+ case OPT_RESP_TEXT:
+ resp_text = 1;
+ break;
+ case OPT_REQIN:
+ reqin = opt_arg();
+ break;
+ case OPT_RESPIN:
+ respin = opt_arg();
+ break;
+ case OPT_SIGNER:
+ signfile = opt_arg();
+ break;
+ case OPT_VAFILE:
+ verify_certfile = opt_arg();
+ verify_flags |= OCSP_TRUSTOTHER;
+ break;
+ case OPT_SIGN_OTHER:
+ sign_certfile = opt_arg();
+ break;
+ case OPT_VERIFY_OTHER:
+ verify_certfile = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ case OPT_VALIDITY_PERIOD:
+ opt_long(opt_arg(), &nsec);
+ break;
+ case OPT_STATUS_AGE:
+ opt_long(opt_arg(), &maxage);
+ break;
+ case OPT_SIGNKEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_REQOUT:
+ reqout = opt_arg();
+ break;
+ case OPT_RESPOUT:
+ respout = opt_arg();
+ break;
+ case OPT_PATH:
+ path = opt_arg();
+ break;
+ case OPT_ISSUER:
+ issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
+ if (issuer == NULL)
+ goto end;
+ if (issuers == NULL) {
+ if ((issuers = sk_X509_new_null()) == NULL)
+ goto end;
+ }
+ sk_X509_push(issuers, issuer);
+ break;
+ case OPT_CERT:
+ X509_free(cert);
+ cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
+ if (cert == NULL)
+ goto end;
+ if (cert_id_md == NULL)
+ cert_id_md = EVP_sha1();
+ if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
+ goto end;
+ if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
+ goto end;
+ trailing_md = 0;
+ break;
+ case OPT_SERIAL:
+ if (cert_id_md == NULL)
+ cert_id_md = EVP_sha1();
+ if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
+ goto end;
+ if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
+ goto end;
+ trailing_md = 0;
+ break;
+ case OPT_INDEX:
+ ridx_filename = opt_arg();
+ break;
+ case OPT_CA:
+ rca_filename = opt_arg();
+ break;
+ case OPT_NMIN:
+ opt_int(opt_arg(), &nmin);
+ if (ndays == -1)
+ ndays = 0;
+ break;
+ case OPT_REQUEST:
+ opt_int(opt_arg(), &accept_count);
+ break;
+ case OPT_NDAYS:
+ ndays = atoi(opt_arg());
+ break;
+ case OPT_RSIGNER:
+ rsignfile = opt_arg();
+ break;
+ case OPT_RKEY:
+ rkeyfile = opt_arg();
+ break;
+ case OPT_ROTHER:
+ rcertfile = opt_arg();
+ break;
+ case OPT_RMD: /* Response MessageDigest */
+ if (!opt_md(opt_arg(), &rsign_md))
+ goto end;
+ break;
+ case OPT_RSIGOPT:
+ if (rsign_sigopts == NULL)
+ rsign_sigopts = sk_OPENSSL_STRING_new_null();
+ if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg()))
+ goto end;
+ break;
+ case OPT_HEADER:
+ header = opt_arg();
+ value = strchr(header, '=');
+ if (value == NULL) {
+ BIO_printf(bio_err, "Missing = in header key=value\n");
+ goto opthelp;
+ }
+ *value++ = '\0';
+ if (!X509V3_add_value(header, value, &headers))
+ goto end;
+ break;
+ case OPT_MD:
+ if (trailing_md) {
+ BIO_printf(bio_err,
+ "%s: Digest must be before -cert or -serial\n",
+ prog);
+ goto opthelp;
+ }
+ if (!opt_md(opt_unknown(), &cert_id_md))
+ goto opthelp;
+ trailing_md = 1;
+ break;
+ case OPT_MULTI:
+# ifdef OCSP_DAEMON
+ multi = atoi(opt_arg());
+# endif
+ break;
+ }
+ }
+ if (trailing_md) {
+ BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n",
+ prog);
+ goto opthelp;
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ /* Have we anything to do? */
+ if (req == NULL && reqin == NULL
+ && respin == NULL && !(port != NULL && ridx_filename != NULL))
+ goto opthelp;
+
+ out = bio_open_default(outfile, 'w', FORMAT_TEXT);
+ if (out == NULL)
+ goto end;
+
+ if (req == NULL && (add_nonce != 2))
+ add_nonce = 0;
+
+ if (req == NULL && reqin != NULL) {
+ derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
+ if (derbio == NULL)
+ goto end;
+ req = d2i_OCSP_REQUEST_bio(derbio, NULL);
+ BIO_free(derbio);
+ if (req == NULL) {
+ BIO_printf(bio_err, "Error reading OCSP request\n");
+ goto end;
+ }
+ }
+
+ if (req == NULL && port != NULL) {
+ acbio = init_responder(port);
+ if (acbio == NULL)
+ goto end;
+ }
+
+ if (rsignfile != NULL) {
+ if (rkeyfile == NULL)
+ rkeyfile = rsignfile;
+ rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
+ if (rsigner == NULL) {
+ BIO_printf(bio_err, "Error loading responder certificate\n");
+ goto end;
+ }
+ if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
+ NULL, "CA certificate"))
+ goto end;
+ if (rcertfile != NULL) {
+ if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
+ "responder other certificates"))
+ goto end;
+ }
+ rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
+ "responder private key");
+ if (rkey == NULL)
+ goto end;
+ }
+
+ if (ridx_filename != NULL
+ && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) {
+ BIO_printf(bio_err,
+ "Responder mode requires certificate, key, and CA.\n");
+ goto end;
+ }
+
+ if (ridx_filename != NULL) {
+ rdb = load_index(ridx_filename, NULL);
+ if (rdb == NULL || index_index(rdb) <= 0) {
+ ret = 1;
+ goto end;
+ }
+ }
+
+# ifdef OCSP_DAEMON
+ if (multi && acbio != NULL)
+ spawn_loop();
+ if (acbio != NULL && req_timeout > 0)
+ signal(SIGALRM, sock_timeout);
+#endif
+
+ if (acbio != NULL)
+ log_message(LOG_INFO, "waiting for OCSP client connections...");
+
+redo_accept:
+
+ if (acbio != NULL) {
+# ifdef OCSP_DAEMON
+ if (index_changed(rdb)) {
+ CA_DB *newrdb = load_index(ridx_filename, NULL);
+
+ if (newrdb != NULL && index_index(newrdb) > 0) {
+ free_index(rdb);
+ rdb = newrdb;
+ } else {
+ free_index(newrdb);
+ log_message(LOG_ERR, "error reloading updated index: %s",
+ ridx_filename);
+ }
+ }
+# endif
+
+ req = NULL;
+ if (!do_responder(&req, &cbio, acbio, req_timeout))
+ goto redo_accept;
+
+ if (req == NULL) {
+ resp =
+ OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
+ NULL);
+ send_ocsp_response(cbio, resp);
+ goto done_resp;
+ }
+ }
+
+ if (req == NULL
+ && (signfile != NULL || reqout != NULL
+ || host != NULL || add_nonce || ridx_filename != NULL)) {
+ BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
+ goto end;
+ }
+
+ if (req != NULL && add_nonce)
+ OCSP_request_add1_nonce(req, NULL, -1);
+
+ if (signfile != NULL) {
+ if (keyfile == NULL)
+ keyfile = signfile;
+ signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
+ if (signer == NULL) {
+ BIO_printf(bio_err, "Error loading signer certificate\n");
+ goto end;
+ }
+ if (sign_certfile != NULL) {
+ if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
+ "signer certificates"))
+ goto end;
+ }
+ key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
+ "signer private key");
+ if (key == NULL)
+ goto end;
+
+ if (!OCSP_request_sign
+ (req, signer, key, NULL, sign_other, sign_flags)) {
+ BIO_printf(bio_err, "Error signing OCSP request\n");
+ goto end;
+ }
+ }
+
+ if (req_text && req != NULL)
+ OCSP_REQUEST_print(out, req, 0);
+
+ if (reqout != NULL) {
+ derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
+ if (derbio == NULL)
+ goto end;
+ i2d_OCSP_REQUEST_bio(derbio, req);
+ BIO_free(derbio);
+ }
+
+ if (rdb != NULL) {
+ make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey,
+ rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig);
+ if (cbio != NULL)
+ send_ocsp_response(cbio, resp);
+ } else if (host != NULL) {
+# ifndef OPENSSL_NO_SOCK
+ resp = process_responder(req, host, path,
+ port, use_ssl, headers, req_timeout);
+ if (resp == NULL)
+ goto end;
+# else
+ BIO_printf(bio_err,
+ "Error creating connect BIO - sockets not supported.\n");
+ goto end;
+# endif
+ } else if (respin != NULL) {
+ derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
+ if (derbio == NULL)
+ goto end;
+ resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
+ BIO_free(derbio);
+ if (resp == NULL) {
+ BIO_printf(bio_err, "Error reading OCSP response\n");
+ goto end;
+ }
+ } else {
+ ret = 0;
+ goto end;
+ }
+
+ done_resp:
+
+ if (respout != NULL) {
+ derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
+ if (derbio == NULL)
+ goto end;
+ i2d_OCSP_RESPONSE_bio(derbio, resp);
+ BIO_free(derbio);
+ }
+
+ i = OCSP_response_status(resp);
+ if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ BIO_printf(out, "Responder Error: %s (%d)\n",
+ OCSP_response_status_str(i), i);
+ if (!ignore_err)
+ goto end;
+ }
+
+ if (resp_text)
+ OCSP_RESPONSE_print(out, resp, 0);
+
+ /* If running as responder don't verify our own response */
+ if (cbio != NULL) {
+ /* If not unlimited, see if we took all we should. */
+ if (accept_count != -1 && --accept_count <= 0) {
+ ret = 0;
+ goto end;
+ }
+ BIO_free_all(cbio);
+ cbio = NULL;
+ OCSP_REQUEST_free(req);
+ req = NULL;
+ OCSP_RESPONSE_free(resp);
+ resp = NULL;
+ goto redo_accept;
+ }
+ if (ridx_filename != NULL) {
+ ret = 0;
+ goto end;
+ }
+
+ if (store == NULL) {
+ store = setup_verify(CAfile, CApath, noCAfile, noCApath);
+ if (!store)
+ goto end;
+ }
+ if (vpmtouched)
+ X509_STORE_set1_param(store, vpm);
+ if (verify_certfile != NULL) {
+ if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
+ "validator certificate"))
+ goto end;
+ }
+
+ bs = OCSP_response_get1_basic(resp);
+ if (bs == NULL) {
+ BIO_printf(bio_err, "Error parsing response\n");
+ goto end;
+ }
+
+ ret = 0;
+
+ if (!noverify) {
+ if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
+ if (i == -1)
+ BIO_printf(bio_err, "WARNING: no nonce in response\n");
+ else {
+ BIO_printf(bio_err, "Nonce Verify error\n");
+ ret = 1;
+ goto end;
+ }
+ }
+
+ i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
+ if (i <= 0 && issuers) {
+ i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
+ if (i > 0)
+ ERR_clear_error();
+ }
+ if (i <= 0) {
+ BIO_printf(bio_err, "Response Verify Failure\n");
+ ERR_print_errors(bio_err);
+ ret = 1;
+ } else {
+ BIO_printf(bio_err, "Response verify OK\n");
+ }
+ }
+
+ print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);
+
+ end:
+ ERR_print_errors(bio_err);
+ X509_free(signer);
+ X509_STORE_free(store);
+ X509_VERIFY_PARAM_free(vpm);
+ sk_OPENSSL_STRING_free(rsign_sigopts);
+ EVP_PKEY_free(key);
+ EVP_PKEY_free(rkey);
+ X509_free(cert);
+ sk_X509_pop_free(issuers, X509_free);
+ X509_free(rsigner);
+ sk_X509_pop_free(rca_cert, X509_free);
+ free_index(rdb);
+ BIO_free_all(cbio);
+ BIO_free_all(acbio);
+ BIO_free_all(out);
+ OCSP_REQUEST_free(req);
+ OCSP_RESPONSE_free(resp);
+ OCSP_BASICRESP_free(bs);
+ sk_OPENSSL_STRING_free(reqnames);
+ sk_OCSP_CERTID_free(ids);
+ sk_X509_pop_free(sign_other, X509_free);
+ sk_X509_pop_free(verify_other, X509_free);
+ sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
+ OPENSSL_free(thost);
+ OPENSSL_free(tport);
+ OPENSSL_free(tpath);
+
+ return ret;
+}
+
+static void
+log_message(int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+# ifdef OCSP_DAEMON
+ if (multi) {
+ char buf[1024];
+ if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) {
+ syslog(level, "%s", buf);
+ }
+ if (level >= LOG_ERR)
+ ERR_print_errors_cb(print_syslog, &level);
+ }
+# endif
+ if (!multi) {
+ BIO_printf(bio_err, "%s: ", prog);
+ BIO_vprintf(bio_err, fmt, ap);
+ BIO_printf(bio_err, "\n");
+ }
+ va_end(ap);
+}
+
+# ifdef OCSP_DAEMON
+
+static int print_syslog(const char *str, size_t len, void *levPtr)
+{
+ int level = *(int *)levPtr;
+ int ilen = (len > MAXERRLEN) ? MAXERRLEN : len;
+
+ syslog(level, "%.*s", ilen, str);
+
+ return ilen;
+}
+
+static int index_changed(CA_DB *rdb)
+{
+ struct stat sb;
+
+ if (rdb != NULL && stat(rdb->dbfname, &sb) != -1) {
+ if (rdb->dbst.st_mtime != sb.st_mtime
+ || rdb->dbst.st_ctime != sb.st_ctime
+ || rdb->dbst.st_ino != sb.st_ino
+ || rdb->dbst.st_dev != sb.st_dev) {
+ syslog(LOG_INFO, "index file changed, reloading");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void killall(int ret, pid_t *kidpids)
+{
+ int i;
+
+ for (i = 0; i < multi; ++i)
+ if (kidpids[i] != 0)
+ (void)kill(kidpids[i], SIGTERM);
+ sleep(1);
+ exit(ret);
+}
+
+static int termsig = 0;
+
+static void noteterm (int sig)
+{
+ termsig = sig;
+}
+
+/*
+ * Loop spawning up to `multi` child processes, only child processes return
+ * from this function. The parent process loops until receiving a termination
+ * signal, kills extant children and exits without returning.
+ */
+static void spawn_loop(void)
+{
+ pid_t *kidpids = NULL;
+ int status;
+ int procs = 0;
+ int i;
+
+ openlog(prog, LOG_PID, LOG_DAEMON);
+
+ if (setpgid(0, 0)) {
+ syslog(LOG_ERR, "fatal: error detaching from parent process group: %s",
+ strerror(errno));
+ exit(1);
+ }
+ kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array");
+ for (i = 0; i < multi; ++i)
+ kidpids[i] = 0;
+
+ signal(SIGINT, noteterm);
+ signal(SIGTERM, noteterm);
+
+ while (termsig == 0) {
+ pid_t fpid;
+
+ /*
+ * Wait for a child to replace when we're at the limit.
+ * Slow down if a child exited abnormally or waitpid() < 0
+ */
+ while (termsig == 0 && procs >= multi) {
+ if ((fpid = waitpid(-1, &status, 0)) > 0) {
+ for (i = 0; i < procs; ++i) {
+ if (kidpids[i] == fpid) {
+ kidpids[i] = 0;
+ --procs;
+ break;
+ }
+ }
+ if (i >= multi) {
+ syslog(LOG_ERR, "fatal: internal error: "
+ "no matching child slot for pid: %ld",
+ (long) fpid);
+ killall(1, kidpids);
+ }
+ if (status != 0) {
+ if (WIFEXITED(status))
+ syslog(LOG_WARNING, "child process: %ld, exit status: %d",
+ (long)fpid, WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ syslog(LOG_WARNING, "child process: %ld, term signal %d%s",
+ (long)fpid, WTERMSIG(status),
+#ifdef WCOREDUMP
+ WCOREDUMP(status) ? " (core dumped)" :
+#endif
+ "");
+ sleep(1);
+ }
+ break;
+ } else if (errno != EINTR) {
+ syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno));
+ killall(1, kidpids);
+ }
+ }
+ if (termsig)
+ break;
+
+ switch(fpid = fork()) {
+ case -1: /* error */
+ /* System critically low on memory, pause and try again later */
+ sleep(30);
+ break;
+ case 0: /* child */
+ OPENSSL_free(kidpids);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ if (termsig)
+ _exit(0);
+ if (RAND_poll() <= 0) {
+ syslog(LOG_ERR, "fatal: RAND_poll() failed");
+ _exit(1);
+ }
+ return;
+ default: /* parent */
+ for (i = 0; i < multi; ++i) {
+ if (kidpids[i] == 0) {
+ kidpids[i] = fpid;
+ procs++;
+ break;
+ }
+ }
+ if (i >= multi) {
+ syslog(LOG_ERR, "fatal: internal error: no free child slots");
+ killall(1, kidpids);
+ }
+ break;
+ }
+ }
+
+ /* The loop above can only break on termsig */
+ OPENSSL_free(kidpids);
+ syslog(LOG_INFO, "terminating on signal: %d", termsig);
+ killall(0, kidpids);
+}
+# endif
+
+static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
+ const EVP_MD *cert_id_md, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids)
+{
+ OCSP_CERTID *id;
+
+ if (issuer == NULL) {
+ BIO_printf(bio_err, "No issuer certificate specified\n");
+ return 0;
+ }
+ if (*req == NULL)
+ *req = OCSP_REQUEST_new();
+ if (*req == NULL)
+ goto err;
+ id = OCSP_cert_to_id(cert_id_md, cert, issuer);
+ if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
+ goto err;
+ if (!OCSP_request_add0_id(*req, id))
+ goto err;
+ return 1;
+
+ err:
+ BIO_printf(bio_err, "Error Creating OCSP request\n");
+ return 0;
+}
+
+static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
+ const EVP_MD *cert_id_md, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids)
+{
+ OCSP_CERTID *id;
+ X509_NAME *iname;
+ ASN1_BIT_STRING *ikey;
+ ASN1_INTEGER *sno;
+
+ if (issuer == NULL) {
+ BIO_printf(bio_err, "No issuer certificate specified\n");
+ return 0;
+ }
+ if (*req == NULL)
+ *req = OCSP_REQUEST_new();
+ if (*req == NULL)
+ goto err;
+ iname = X509_get_subject_name(issuer);
+ ikey = X509_get0_pubkey_bitstr(issuer);
+ sno = s2i_ASN1_INTEGER(NULL, serial);
+ if (sno == NULL) {
+ BIO_printf(bio_err, "Error converting serial number %s\n", serial);
+ return 0;
+ }
+ id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
+ ASN1_INTEGER_free(sno);
+ if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
+ goto err;
+ if (!OCSP_request_add0_id(*req, id))
+ goto err;
+ return 1;
+
+ err:
+ BIO_printf(bio_err, "Error Creating OCSP request\n");
+ return 0;
+}
+
+static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+ STACK_OF(OPENSSL_STRING) *names,
+ STACK_OF(OCSP_CERTID) *ids, long nsec,
+ long maxage)
+{
+ OCSP_CERTID *id;
+ const char *name;
+ int i, status, reason;
+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+
+ if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names)
+ || !sk_OCSP_CERTID_num(ids))
+ return;
+
+ for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
+ id = sk_OCSP_CERTID_value(ids, i);
+ name = sk_OPENSSL_STRING_value(names, i);
+ BIO_printf(out, "%s: ", name);
+
+ if (!OCSP_resp_find_status(bs, id, &status, &reason,
+ &rev, &thisupd, &nextupd)) {
+ BIO_puts(out, "ERROR: No Status found.\n");
+ continue;
+ }
+
+ /*
+ * Check validity: if invalid write to output BIO so we know which
+ * response this refers to.
+ */
+ if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
+ BIO_puts(out, "WARNING: Status times invalid.\n");
+ ERR_print_errors(out);
+ }
+ BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
+
+ BIO_puts(out, "\tThis Update: ");
+ ASN1_GENERALIZEDTIME_print(out, thisupd);
+ BIO_puts(out, "\n");
+
+ if (nextupd) {
+ BIO_puts(out, "\tNext Update: ");
+ ASN1_GENERALIZEDTIME_print(out, nextupd);
+ BIO_puts(out, "\n");
+ }
+
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
+ continue;
+
+ if (reason != -1)
+ BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason));
+
+ BIO_puts(out, "\tRevocation Time: ");
+ ASN1_GENERALIZEDTIME_print(out, rev);
+ BIO_puts(out, "\n");
+ }
+}
+
+static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
+ CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
+ EVP_PKEY *rkey, const EVP_MD *rmd,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ STACK_OF(X509) *rother, unsigned long flags,
+ int nmin, int ndays, int badsig)
+{
+ ASN1_TIME *thisupd = NULL, *nextupd = NULL;
+ OCSP_CERTID *cid;
+ OCSP_BASICRESP *bs = NULL;
+ int i, id_count;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pkctx = NULL;
+
+ id_count = OCSP_request_onereq_count(req);
+
+ if (id_count <= 0) {
+ *resp =
+ OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
+ goto end;
+ }
+
+ bs = OCSP_BASICRESP_new();
+ thisupd = X509_gmtime_adj(NULL, 0);
+ if (ndays != -1)
+ nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
+
+ /* Examine each certificate id in the request */
+ for (i = 0; i < id_count; i++) {
+ OCSP_ONEREQ *one;
+ ASN1_INTEGER *serial;
+ char **inf;
+ int jj;
+ int found = 0;
+ ASN1_OBJECT *cert_id_md_oid;
+ const EVP_MD *cert_id_md;
+ one = OCSP_request_onereq_get0(req, i);
+ cid = OCSP_onereq_get0_id(one);
+
+ OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid);
+
+ cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
+ if (cert_id_md == NULL) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
+ NULL);
+ goto end;
+ }
+ for (jj = 0; jj < sk_X509_num(ca) && !found; jj++) {
+ X509 *ca_cert = sk_X509_value(ca, jj);
+ OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert);
+
+ if (OCSP_id_issuer_cmp(ca_id, cid) == 0)
+ found = 1;
+
+ OCSP_CERTID_free(ca_id);
+ }
+
+ if (!found) {
+ OCSP_basic_add1_status(bs, cid,
+ V_OCSP_CERTSTATUS_UNKNOWN,
+ 0, NULL, thisupd, nextupd);
+ continue;
+ }
+ OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
+ inf = lookup_serial(db, serial);
+ if (inf == NULL) {
+ OCSP_basic_add1_status(bs, cid,
+ V_OCSP_CERTSTATUS_UNKNOWN,
+ 0, NULL, thisupd, nextupd);
+ } else if (inf[DB_type][0] == DB_TYPE_VAL) {
+ OCSP_basic_add1_status(bs, cid,
+ V_OCSP_CERTSTATUS_GOOD,
+ 0, NULL, thisupd, nextupd);
+ } else if (inf[DB_type][0] == DB_TYPE_REV) {
+ ASN1_OBJECT *inst = NULL;
+ ASN1_TIME *revtm = NULL;
+ ASN1_GENERALIZEDTIME *invtm = NULL;
+ OCSP_SINGLERESP *single;
+ int reason = -1;
+ unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
+ single = OCSP_basic_add1_status(bs, cid,
+ V_OCSP_CERTSTATUS_REVOKED,
+ reason, revtm, thisupd, nextupd);
+ if (invtm != NULL)
+ OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
+ invtm, 0, 0);
+ else if (inst != NULL)
+ OCSP_SINGLERESP_add1_ext_i2d(single,
+ NID_hold_instruction_code, inst,
+ 0, 0);
+ ASN1_OBJECT_free(inst);
+ ASN1_TIME_free(revtm);
+ ASN1_GENERALIZEDTIME_free(invtm);
+ }
+ }
+
+ OCSP_copy_nonce(bs, req);
+
+ mctx = EVP_MD_CTX_new();
+ if ( mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL);
+ goto end;
+ }
+ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
+ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+
+ if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
+ BIO_printf(err, "parameter error \"%s\"\n", sigopt);
+ ERR_print_errors(bio_err);
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
+ NULL);
+ goto end;
+ }
+ }
+ OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags);
+
+ if (badsig) {
+ const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs);
+ corrupt_signature(sig);
+ }
+
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
+
+ end:
+ EVP_MD_CTX_free(mctx);
+ ASN1_TIME_free(thisupd);
+ ASN1_TIME_free(nextupd);
+ OCSP_BASICRESP_free(bs);
+}
+
+static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
+{
+ int i;
+ BIGNUM *bn = NULL;
+ char *itmp, *row[DB_NUMBER], **rrow;
+ for (i = 0; i < DB_NUMBER; i++)
+ row[i] = NULL;
+ bn = ASN1_INTEGER_to_BN(ser, NULL);
+ OPENSSL_assert(bn); /* FIXME: should report an error at this
+ * point and abort */
+ if (BN_is_zero(bn))
+ itmp = OPENSSL_strdup("00");
+ else
+ itmp = BN_bn2hex(bn);
+ row[DB_serial] = itmp;
+ BN_free(bn);
+ rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
+ OPENSSL_free(itmp);
+ return rrow;
+}
+
+/* Quick and dirty OCSP server: read in and parse input request */
+
+static BIO *init_responder(const char *port)
+{
+# ifdef OPENSSL_NO_SOCK
+ BIO_printf(bio_err,
+ "Error setting up accept BIO - sockets not supported.\n");
+ return NULL;
+# else
+ BIO *acbio = NULL, *bufbio = NULL;
+
+ bufbio = BIO_new(BIO_f_buffer());
+ if (bufbio == NULL)
+ goto err;
+ acbio = BIO_new(BIO_s_accept());
+ if (acbio == NULL
+ || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
+ || BIO_set_accept_port(acbio, port) < 0) {
+ log_message(LOG_ERR, "Error setting up accept BIO");
+ goto err;
+ }
+
+ BIO_set_accept_bios(acbio, bufbio);
+ bufbio = NULL;
+ if (BIO_do_accept(acbio) <= 0) {
+ log_message(LOG_ERR, "Error starting accept");
+ goto err;
+ }
+
+ return acbio;
+
+ err:
+ BIO_free_all(acbio);
+ BIO_free(bufbio);
+ return NULL;
+# endif
+}
+
+# ifndef OPENSSL_NO_SOCK
+/*
+ * Decode %xx URL-decoding in-place. Ignores mal-formed sequences.
+ */
+static int urldecode(char *p)
+{
+ unsigned char *out = (unsigned char *)p;
+ unsigned char *save = out;
+
+ for (; *p; p++) {
+ if (*p != '%')
+ *out++ = *p;
+ else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
+ /* Don't check, can't fail because of ixdigit() call. */
+ *out++ = (OPENSSL_hexchar2int(p[1]) << 4)
+ | OPENSSL_hexchar2int(p[2]);
+ p += 2;
+ }
+ else
+ return -1;
+ }
+ *out = '\0';
+ return (int)(out - save);
+}
+# endif
+
+# ifdef OCSP_DAEMON
+static void sock_timeout(int signum)
+{
+ if (acfd != (int)INVALID_SOCKET)
+ (void)shutdown(acfd, SHUT_RD);
+}
+# endif
+
+static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
+ int timeout)
+{
+# ifdef OPENSSL_NO_SOCK
+ return 0;
+# else
+ int len;
+ OCSP_REQUEST *req = NULL;
+ char inbuf[2048], reqbuf[2048];
+ char *p, *q;
+ BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
+ const char *client;
+
+ *preq = NULL;
+
+ /* Connection loss before accept() is routine, ignore silently */
+ if (BIO_do_accept(acbio) <= 0)
+ return 0;
+
+ cbio = BIO_pop(acbio);
+ *pcbio = cbio;
+ client = BIO_get_peer_name(cbio);
+
+# ifdef OCSP_DAEMON
+ if (timeout > 0) {
+ (void) BIO_get_fd(cbio, &acfd);
+ alarm(timeout);
+ }
+# endif
+
+ /* Read the request line. */
+ len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
+ if (len <= 0)
+ goto out;
+
+ if (strncmp(reqbuf, "GET ", 4) == 0) {
+ /* Expecting GET {sp} /URL {sp} HTTP/1.x */
+ for (p = reqbuf + 4; *p == ' '; ++p)
+ continue;
+ if (*p != '/') {
+ log_message(LOG_INFO, "Invalid request -- bad URL: %s", client);
+ goto out;
+ }
+ p++;
+
+ /* Splice off the HTTP version identifier. */
+ for (q = p; *q; q++)
+ if (*q == ' ')
+ break;
+ if (strncmp(q, " HTTP/1.", 8) != 0) {
+ log_message(LOG_INFO,
+ "Invalid request -- bad HTTP version: %s", client);
+ goto out;
+ }
+ *q = '\0';
+
+ /*
+ * Skip "GET / HTTP..." requests often used by load-balancers
+ */
+ if (p[1] == '\0')
+ goto out;
+
+ len = urldecode(p);
+ if (len <= 0) {
+ log_message(LOG_INFO,
+ "Invalid request -- bad URL encoding: %s", client);
+ goto out;
+ }
+ if ((getbio = BIO_new_mem_buf(p, len)) == NULL
+ || (b64 = BIO_new(BIO_f_base64())) == NULL) {
+ log_message(LOG_ERR, "Could not allocate base64 bio: %s", client);
+ goto out;
+ }
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ getbio = BIO_push(b64, getbio);
+ } else if (strncmp(reqbuf, "POST ", 5) != 0) {
+ log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client);
+ goto out;
+ }
+
+ /* Read and skip past the headers. */
+ for (;;) {
+ len = BIO_gets(cbio, inbuf, sizeof(inbuf));
+ if (len <= 0)
+ goto out;
+ if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
+ break;
+ }
+
+# ifdef OCSP_DAEMON
+ /* Clear alarm before we close the client socket */
+ alarm(0);
+ timeout = 0;
+# endif
+
+ /* Try to read OCSP request */
+ if (getbio != NULL) {
+ req = d2i_OCSP_REQUEST_bio(getbio, NULL);
+ BIO_free_all(getbio);
+ } else {
+ req = d2i_OCSP_REQUEST_bio(cbio, NULL);
+ }
+
+ if (req == NULL)
+ log_message(LOG_ERR, "Error parsing OCSP request");
+
+ *preq = req;
+
+out:
+# ifdef OCSP_DAEMON
+ if (timeout > 0)
+ alarm(0);
+ acfd = (int)INVALID_SOCKET;
+# endif
+ return 1;
+# endif
+}
+
+static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
+{
+ char http_resp[] =
+ "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
+ "Content-Length: %d\r\n\r\n";
+ if (cbio == NULL)
+ return 0;
+ BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
+ i2d_OCSP_RESPONSE_bio(cbio, resp);
+ (void)BIO_flush(cbio);
+ return 1;
+}
+
+# ifndef OPENSSL_NO_SOCK
+static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
+ const char *path,
+ const STACK_OF(CONF_VALUE) *headers,
+ OCSP_REQUEST *req, int req_timeout)
+{
+ int fd;
+ int rv;
+ int i;
+ int add_host = 1;
+ OCSP_REQ_CTX *ctx = NULL;
+ OCSP_RESPONSE *rsp = NULL;
+ fd_set confds;
+ struct timeval tv;
+
+ if (req_timeout != -1)
+ BIO_set_nbio(cbio, 1);
+
+ rv = BIO_do_connect(cbio);
+
+ if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
+ BIO_puts(bio_err, "Error connecting BIO\n");
+ return NULL;
+ }
+
+ if (BIO_get_fd(cbio, &fd) < 0) {
+ BIO_puts(bio_err, "Can't get connection fd\n");
+ goto err;
+ }
+
+ if (req_timeout != -1 && rv <= 0) {
+ FD_ZERO(&confds);
+ openssl_fdset(fd, &confds);
+ tv.tv_usec = 0;
+ tv.tv_sec = req_timeout;
+ rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+ if (rv == 0) {
+ BIO_puts(bio_err, "Timeout on connect\n");
+ return NULL;
+ }
+ }
+
+ ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
+ if (ctx == NULL)
+ return NULL;
+
+ for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
+ CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
+ if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
+ add_host = 0;
+ if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
+ goto err;
+ }
+
+ if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
+ goto err;
+
+ if (!OCSP_REQ_CTX_set1_req(ctx, req))
+ goto err;
+
+ for (;;) {
+ rv = OCSP_sendreq_nbio(&rsp, ctx);
+ if (rv != -1)
+ break;
+ if (req_timeout == -1)
+ continue;
+ FD_ZERO(&confds);
+ openssl_fdset(fd, &confds);
+ tv.tv_usec = 0;
+ tv.tv_sec = req_timeout;
+ if (BIO_should_read(cbio)) {
+ rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
+ } else if (BIO_should_write(cbio)) {
+ rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+ } else {
+ BIO_puts(bio_err, "Unexpected retry condition\n");
+ goto err;
+ }
+ if (rv == 0) {
+ BIO_puts(bio_err, "Timeout on request\n");
+ break;
+ }
+ if (rv == -1) {
+ BIO_puts(bio_err, "Select error\n");
+ break;
+ }
+
+ }
+ err:
+ OCSP_REQ_CTX_free(ctx);
+
+ return rsp;
+}
+
+OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
+ const char *host, const char *path,
+ const char *port, int use_ssl,
+ STACK_OF(CONF_VALUE) *headers,
+ int req_timeout)
+{
+ BIO *cbio = NULL;
+ SSL_CTX *ctx = NULL;
+ OCSP_RESPONSE *resp = NULL;
+
+ cbio = BIO_new_connect(host);
+ if (cbio == NULL) {
+ BIO_printf(bio_err, "Error creating connect BIO\n");
+ goto end;
+ }
+ if (port != NULL)
+ BIO_set_conn_port(cbio, port);
+ if (use_ssl == 1) {
+ BIO *sbio;
+ ctx = SSL_CTX_new(TLS_client_method());
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "Error creating SSL context.\n");
+ goto end;
+ }
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+ sbio = BIO_new_ssl(ctx, 1);
+ cbio = BIO_push(sbio, cbio);
+ }
+
+ resp = query_responder(cbio, host, path, headers, req, req_timeout);
+ if (resp == NULL)
+ BIO_printf(bio_err, "Error querying OCSP responder\n");
+ end:
+ BIO_free_all(cbio);
+ SSL_CTX_free(ctx);
+ return resp;
+}
+# endif
+
+#endif
diff --git a/freebsd/crypto/openssl/apps/openssl.c b/freebsd/crypto/openssl/apps/openssl.c
new file mode 100644
index 00000000..0b41ea55
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/openssl.c
@@ -0,0 +1,828 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <internal/cryptlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/conf.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#ifndef OPENSSL_NO_ENGINE
+# include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+#include "s_apps.h"
+/* Needed to get the other O_xxx flags. */
+#ifdef OPENSSL_SYS_VMS
+# include <unixio.h>
+#endif
+#include "apps.h"
+#define INCLUDE_FUNCTION_TABLE
+#include "progs.h"
+
+/* Structure to hold the number of columns to be displayed and the
+ * field width used to display them.
+ */
+typedef struct {
+ int columns;
+ int width;
+} DISPLAY_COLUMNS;
+
+/* Special sentinel to exit the program. */
+#define EXIT_THE_PROGRAM (-1)
+
+/*
+ * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
+ * the base prototypes (we cast each variable inside the function to the
+ * required type of "FUNCTION*"). This removes the necessity for
+ * macro-generated wrapper functions.
+ */
+static LHASH_OF(FUNCTION) *prog_init(void);
+static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
+static void list_pkey(void);
+static void list_pkey_meth(void);
+static void list_type(FUNC_TYPE ft, int one);
+static void list_disabled(void);
+char *default_config_file = NULL;
+
+BIO *bio_in = NULL;
+BIO *bio_out = NULL;
+BIO *bio_err = NULL;
+
+static void calculate_columns(DISPLAY_COLUMNS *dc)
+{
+ FUNCTION *f;
+ int len, maxlen = 0;
+
+ for (f = functions; f->name != NULL; ++f)
+ if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher)
+ if ((len = strlen(f->name)) > maxlen)
+ maxlen = len;
+
+ dc->width = maxlen + 2;
+ dc->columns = (80 - 1) / dc->width;
+}
+
+static int apps_startup(void)
+{
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /* Set non-default library initialisation settings */
+ if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN
+ | OPENSSL_INIT_LOAD_CONFIG, NULL))
+ return 0;
+
+ setup_ui_method();
+
+ return 1;
+}
+
+static void apps_shutdown(void)
+{
+ destroy_ui_method();
+ destroy_prefix_method();
+}
+
+static char *make_config_name(void)
+{
+ const char *t;
+ size_t len;
+ char *p;
+
+ if ((t = getenv("OPENSSL_CONF")) != NULL)
+ return OPENSSL_strdup(t);
+
+ t = X509_get_default_cert_area();
+ len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1;
+ p = app_malloc(len, "config filename buffer");
+ strcpy(p, t);
+#ifndef OPENSSL_SYS_VMS
+ strcat(p, "/");
+#endif
+ strcat(p, OPENSSL_CONF);
+
+ return p;
+}
+
+int main(int argc, char *argv[])
+{
+ FUNCTION f, *fp;
+ LHASH_OF(FUNCTION) *prog = NULL;
+ char **copied_argv = NULL;
+ char *p, *pname;
+ char buf[1024];
+ const char *prompt;
+ ARGS arg;
+ int first, n, i, ret = 0;
+
+ arg.argv = NULL;
+ arg.size = 0;
+
+ /* Set up some of the environment. */
+ default_config_file = make_config_name();
+ bio_in = dup_bio_in(FORMAT_TEXT);
+ bio_out = dup_bio_out(FORMAT_TEXT);
+ bio_err = dup_bio_err(FORMAT_TEXT);
+
+#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
+ copied_argv = argv = copy_argv(&argc, argv);
+#elif defined(_WIN32)
+ /*
+ * Replace argv[] with UTF-8 encoded strings.
+ */
+ win32_utf8argv(&argc, &argv);
+#endif
+
+ p = getenv("OPENSSL_DEBUG_MEMORY");
+ if (p != NULL && strcmp(p, "on") == 0)
+ CRYPTO_set_mem_debug(1);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ if (getenv("OPENSSL_FIPS")) {
+ BIO_printf(bio_err, "FIPS mode not supported.\n");
+ return 1;
+ }
+
+ if (!apps_startup()) {
+ BIO_printf(bio_err,
+ "FATAL: Startup failure (dev note: apps_startup() failed)\n");
+ ERR_print_errors(bio_err);
+ ret = 1;
+ goto end;
+ }
+
+ prog = prog_init();
+ pname = opt_progname(argv[0]);
+
+ /* first check the program name */
+ f.name = pname;
+ fp = lh_FUNCTION_retrieve(prog, &f);
+ if (fp != NULL) {
+ argv[0] = pname;
+ ret = fp->func(argc, argv);
+ goto end;
+ }
+
+ /* If there is stuff on the command line, run with that. */
+ if (argc != 1) {
+ argc--;
+ argv++;
+ ret = do_cmd(prog, argc, argv);
+ if (ret < 0)
+ ret = 0;
+ goto end;
+ }
+
+ /* ok, lets enter interactive mode */
+ for (;;) {
+ ret = 0;
+ /* Read a line, continue reading if line ends with \ */
+ for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) {
+ prompt = first ? "OpenSSL> " : "> ";
+ p[0] = '\0';
+#ifndef READLINE
+ fputs(prompt, stdout);
+ fflush(stdout);
+ if (!fgets(p, n, stdin))
+ goto end;
+ if (p[0] == '\0')
+ goto end;
+ i = strlen(p);
+ if (i <= 1)
+ break;
+ if (p[i - 2] != '\\')
+ break;
+ i -= 2;
+ p += i;
+ n -= i;
+#else
+ {
+ extern char *readline(const char *);
+ extern void add_history(const char *cp);
+ char *text;
+
+ text = readline(prompt);
+ if (text == NULL)
+ goto end;
+ i = strlen(text);
+ if (i == 0 || i > n)
+ break;
+ if (text[i - 1] != '\\') {
+ p += strlen(strcpy(p, text));
+ free(text);
+ add_history(buf);
+ break;
+ }
+
+ text[i - 1] = '\0';
+ p += strlen(strcpy(p, text));
+ free(text);
+ n -= i;
+ }
+#endif
+ }
+
+ if (!chopup_args(&arg, buf)) {
+ BIO_printf(bio_err, "Can't parse (no memory?)\n");
+ break;
+ }
+
+ ret = do_cmd(prog, arg.argc, arg.argv);
+ if (ret == EXIT_THE_PROGRAM) {
+ ret = 0;
+ goto end;
+ }
+ if (ret != 0)
+ BIO_printf(bio_err, "error in %s\n", arg.argv[0]);
+ (void)BIO_flush(bio_out);
+ (void)BIO_flush(bio_err);
+ }
+ ret = 1;
+ end:
+ OPENSSL_free(copied_argv);
+ OPENSSL_free(default_config_file);
+ lh_FUNCTION_free(prog);
+ OPENSSL_free(arg.argv);
+ app_RAND_write();
+
+ BIO_free(bio_in);
+ BIO_free_all(bio_out);
+ apps_shutdown();
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+ if (CRYPTO_mem_leaks(bio_err) <= 0)
+ ret = 1;
+#endif
+ BIO_free(bio_err);
+ EXIT(ret);
+}
+
+static void list_cipher_fn(const EVP_CIPHER *c,
+ const char *from, const char *to, void *arg)
+{
+ if (c != NULL) {
+ BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf(arg, "%s => %s\n", from, to);
+ }
+}
+
+static void list_md_fn(const EVP_MD *m,
+ const char *from, const char *to, void *arg)
+{
+ if (m != NULL) {
+ BIO_printf(arg, "%s\n", EVP_MD_name(m));
+ } else {
+ if (from == NULL)
+ from = "<undefined>";
+ if (to == NULL)
+ to = "<undefined>";
+ BIO_printf((BIO *)arg, "%s => %s\n", from, to);
+ }
+}
+
+static void list_missing_help(void)
+{
+ const FUNCTION *fp;
+ const OPTIONS *o;
+
+ for (fp = functions; fp->name != NULL; fp++) {
+ if ((o = fp->help) != NULL) {
+ /* If there is help, list what flags are not documented. */
+ for ( ; o->name != NULL; o++) {
+ if (o->helpstr == NULL)
+ BIO_printf(bio_out, "%s %s\n", fp->name, o->name);
+ }
+ } else if (fp->func != dgst_main) {
+ /* If not aliased to the dgst command, */
+ BIO_printf(bio_out, "%s *\n", fp->name);
+ }
+ }
+}
+
+static void list_options_for_command(const char *command)
+{
+ const FUNCTION *fp;
+ const OPTIONS *o;
+
+ for (fp = functions; fp->name != NULL; fp++)
+ if (strcmp(fp->name, command) == 0)
+ break;
+ if (fp->name == NULL) {
+ BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
+ command);
+ return;
+ }
+
+ if ((o = fp->help) == NULL)
+ return;
+
+ for ( ; o->name != NULL; o++) {
+ if (o->name == OPT_HELP_STR
+ || o->name == OPT_MORE_STR
+ || o->name[0] == '\0')
+ continue;
+ BIO_printf(bio_out, "%s %c\n", o->name, o->valtype);
+ }
+}
+
+
+/* Unified enum for help and list commands. */
+typedef enum HELPLIST_CHOICE {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE,
+ OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS,
+ OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
+ OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP
+} HELPLIST_CHOICE;
+
+const OPTIONS list_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"1", OPT_ONE, '-', "List in one column"},
+ {"commands", OPT_COMMANDS, '-', "List of standard commands"},
+ {"digest-commands", OPT_DIGEST_COMMANDS, '-',
+ "List of message digest commands"},
+ {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
+ "List of message digest algorithms"},
+ {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"},
+ {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
+ "List of cipher algorithms"},
+ {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
+ "List of public key algorithms"},
+ {"public-key-methods", OPT_PK_METHOD, '-',
+ "List of public key methods"},
+ {"disabled", OPT_DISABLED, '-',
+ "List of disabled features"},
+ {"missing-help", OPT_MISSING_HELP, '-',
+ "List missing detailed help strings"},
+ {"options", OPT_OPTIONS, 's',
+ "List options for specified command"},
+ {NULL}
+};
+
+int list_main(int argc, char **argv)
+{
+ char *prog;
+ HELPLIST_CHOICE o;
+ int one = 0, done = 0;
+
+ prog = opt_init(argc, argv, list_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF: /* Never hit, but suppresses warning */
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ return 1;
+ case OPT_HELP:
+ opt_help(list_options);
+ break;
+ case OPT_ONE:
+ one = 1;
+ break;
+ case OPT_COMMANDS:
+ list_type(FT_general, one);
+ break;
+ case OPT_DIGEST_COMMANDS:
+ list_type(FT_md, one);
+ break;
+ case OPT_DIGEST_ALGORITHMS:
+ EVP_MD_do_all_sorted(list_md_fn, bio_out);
+ break;
+ case OPT_CIPHER_COMMANDS:
+ list_type(FT_cipher, one);
+ break;
+ case OPT_CIPHER_ALGORITHMS:
+ EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
+ break;
+ case OPT_PK_ALGORITHMS:
+ list_pkey();
+ break;
+ case OPT_PK_METHOD:
+ list_pkey_meth();
+ break;
+ case OPT_DISABLED:
+ list_disabled();
+ break;
+ case OPT_MISSING_HELP:
+ list_missing_help();
+ break;
+ case OPT_OPTIONS:
+ list_options_for_command(opt_arg());
+ break;
+ }
+ done = 1;
+ }
+ if (opt_num_rest() != 0) {
+ BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ }
+
+ if (!done)
+ goto opthelp;
+
+ return 0;
+}
+
+typedef enum HELP_CHOICE {
+ OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP
+} HELP_CHOICE;
+
+const OPTIONS help_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"},
+ {OPT_HELP_STR, 1, '-', " help [command]\n"},
+ {"help", OPT_hHELP, '-', "Display this summary"},
+ {NULL}
+};
+
+
+int help_main(int argc, char **argv)
+{
+ FUNCTION *fp;
+ int i, nl;
+ FUNC_TYPE tp;
+ char *prog;
+ HELP_CHOICE o;
+ DISPLAY_COLUMNS dc;
+
+ prog = opt_init(argc, argv, help_options);
+ while ((o = opt_next()) != OPT_hEOF) {
+ switch (o) {
+ case OPT_hERR:
+ case OPT_hEOF:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ return 1;
+ case OPT_hHELP:
+ opt_help(help_options);
+ return 0;
+ }
+ }
+
+ if (opt_num_rest() == 1) {
+ char *new_argv[3];
+
+ new_argv[0] = opt_rest()[0];
+ new_argv[1] = "--help";
+ new_argv[2] = NULL;
+ return do_cmd(prog_init(), 2, new_argv);
+ }
+ if (opt_num_rest() != 0) {
+ BIO_printf(bio_err, "Usage: %s\n", prog);
+ return 1;
+ }
+
+ calculate_columns(&dc);
+ BIO_printf(bio_err, "Standard commands");
+ i = 0;
+ tp = FT_none;
+ for (fp = functions; fp->name != NULL; fp++) {
+ nl = 0;
+ if (i++ % dc.columns == 0) {
+ BIO_printf(bio_err, "\n");
+ nl = 1;
+ }
+ if (fp->type != tp) {
+ tp = fp->type;
+ if (!nl)
+ BIO_printf(bio_err, "\n");
+ if (tp == FT_md) {
+ i = 1;
+ BIO_printf(bio_err,
+ "\nMessage Digest commands (see the `dgst' command for more details)\n");
+ } else if (tp == FT_cipher) {
+ i = 1;
+ BIO_printf(bio_err,
+ "\nCipher commands (see the `enc' command for more details)\n");
+ }
+ }
+ BIO_printf(bio_err, "%-*s", dc.width, fp->name);
+ }
+ BIO_printf(bio_err, "\n\n");
+ return 0;
+}
+
+static void list_type(FUNC_TYPE ft, int one)
+{
+ FUNCTION *fp;
+ int i = 0;
+ DISPLAY_COLUMNS dc = {0};
+
+ if (!one)
+ calculate_columns(&dc);
+
+ for (fp = functions; fp->name != NULL; fp++) {
+ if (fp->type != ft)
+ continue;
+ if (one) {
+ BIO_printf(bio_out, "%s\n", fp->name);
+ } else {
+ if (i % dc.columns == 0 && i > 0)
+ BIO_printf(bio_out, "\n");
+ BIO_printf(bio_out, "%-*s", dc.width, fp->name);
+ i++;
+ }
+ }
+ if (!one)
+ BIO_printf(bio_out, "\n\n");
+}
+
+static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
+{
+ FUNCTION f, *fp;
+
+ if (argc <= 0 || argv[0] == NULL)
+ return 0;
+ f.name = argv[0];
+ fp = lh_FUNCTION_retrieve(prog, &f);
+ if (fp == NULL) {
+ if (EVP_get_digestbyname(argv[0])) {
+ f.type = FT_md;
+ f.func = dgst_main;
+ fp = &f;
+ } else if (EVP_get_cipherbyname(argv[0])) {
+ f.type = FT_cipher;
+ f.func = enc_main;
+ fp = &f;
+ }
+ }
+ if (fp != NULL) {
+ return fp->func(argc, argv);
+ }
+ if ((strncmp(argv[0], "no-", 3)) == 0) {
+ /*
+ * User is asking if foo is unsupported, by trying to "run" the
+ * no-foo command. Strange.
+ */
+ f.name = argv[0] + 3;
+ if (lh_FUNCTION_retrieve(prog, &f) == NULL) {
+ BIO_printf(bio_out, "%s\n", argv[0]);
+ return 0;
+ }
+ BIO_printf(bio_out, "%s\n", argv[0] + 3);
+ return 1;
+ }
+ if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 ||
+ strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0)
+ /* Special value to mean "exit the program. */
+ return EXIT_THE_PROGRAM;
+
+ BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
+ argv[0]);
+ return 1;
+}
+
+static void list_pkey(void)
+{
+ int i;
+
+ for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id, pkey_base_id, pkey_flags;
+ const char *pinfo, *pem_str;
+ ameth = EVP_PKEY_asn1_get0(i);
+ EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
+ &pinfo, &pem_str, ameth);
+ if (pkey_flags & ASN1_PKEY_ALIAS) {
+ BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id));
+ BIO_printf(bio_out, "\tAlias for: %s\n",
+ OBJ_nid2ln(pkey_base_id));
+ } else {
+ BIO_printf(bio_out, "Name: %s\n", pinfo);
+ BIO_printf(bio_out, "\tType: %s Algorithm\n",
+ pkey_flags & ASN1_PKEY_DYNAMIC ?
+ "External" : "Builtin");
+ BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
+ if (pem_str == NULL)
+ pem_str = "(none)";
+ BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
+ }
+
+ }
+}
+
+static void list_pkey_meth(void)
+{
+ size_t i;
+ size_t meth_count = EVP_PKEY_meth_get_count();
+
+ for (i = 0; i < meth_count; i++) {
+ const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i);
+ int pkey_id, pkey_flags;
+
+ EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth);
+ BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id));
+ BIO_printf(bio_out, "\tType: %s Algorithm\n",
+ pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin");
+ }
+}
+
+static int function_cmp(const FUNCTION * a, const FUNCTION * b)
+{
+ return strncmp(a->name, b->name, 8);
+}
+
+static unsigned long function_hash(const FUNCTION * a)
+{
+ return OPENSSL_LH_strhash(a->name);
+}
+
+static int SortFnByName(const void *_f1, const void *_f2)
+{
+ const FUNCTION *f1 = _f1;
+ const FUNCTION *f2 = _f2;
+
+ if (f1->type != f2->type)
+ return f1->type - f2->type;
+ return strcmp(f1->name, f2->name);
+}
+
+static void list_disabled(void)
+{
+ BIO_puts(bio_out, "Disabled algorithms:\n");
+#ifdef OPENSSL_NO_ARIA
+ BIO_puts(bio_out, "ARIA\n");
+#endif
+#ifdef OPENSSL_NO_BF
+ BIO_puts(bio_out, "BF\n");
+#endif
+#ifdef OPENSSL_NO_BLAKE2
+ BIO_puts(bio_out, "BLAKE2\n");
+#endif
+#ifdef OPENSSL_NO_CAMELLIA
+ BIO_puts(bio_out, "CAMELLIA\n");
+#endif
+#ifdef OPENSSL_NO_CAST
+ BIO_puts(bio_out, "CAST\n");
+#endif
+#ifdef OPENSSL_NO_CMAC
+ BIO_puts(bio_out, "CMAC\n");
+#endif
+#ifdef OPENSSL_NO_CMS
+ BIO_puts(bio_out, "CMS\n");
+#endif
+#ifdef OPENSSL_NO_COMP
+ BIO_puts(bio_out, "COMP\n");
+#endif
+#ifdef OPENSSL_NO_DES
+ BIO_puts(bio_out, "DES\n");
+#endif
+#ifdef OPENSSL_NO_DGRAM
+ BIO_puts(bio_out, "DGRAM\n");
+#endif
+#ifdef OPENSSL_NO_DH
+ BIO_puts(bio_out, "DH\n");
+#endif
+#ifdef OPENSSL_NO_DSA
+ BIO_puts(bio_out, "DSA\n");
+#endif
+#if defined(OPENSSL_NO_DTLS)
+ BIO_puts(bio_out, "DTLS\n");
+#endif
+#if defined(OPENSSL_NO_DTLS1)
+ BIO_puts(bio_out, "DTLS1\n");
+#endif
+#if defined(OPENSSL_NO_DTLS1_2)
+ BIO_puts(bio_out, "DTLS1_2\n");
+#endif
+#ifdef OPENSSL_NO_EC
+ BIO_puts(bio_out, "EC\n");
+#endif
+#ifdef OPENSSL_NO_EC2M
+ BIO_puts(bio_out, "EC2M\n");
+#endif
+#ifdef OPENSSL_NO_ENGINE
+ BIO_puts(bio_out, "ENGINE\n");
+#endif
+#ifdef OPENSSL_NO_GOST
+ BIO_puts(bio_out, "GOST\n");
+#endif
+#ifdef OPENSSL_NO_HEARTBEATS
+ BIO_puts(bio_out, "HEARTBEATS\n");
+#endif
+#ifdef OPENSSL_NO_IDEA
+ BIO_puts(bio_out, "IDEA\n");
+#endif
+#ifdef OPENSSL_NO_MD2
+ BIO_puts(bio_out, "MD2\n");
+#endif
+#ifdef OPENSSL_NO_MD4
+ BIO_puts(bio_out, "MD4\n");
+#endif
+#ifdef OPENSSL_NO_MD5
+ BIO_puts(bio_out, "MD5\n");
+#endif
+#ifdef OPENSSL_NO_MDC2
+ BIO_puts(bio_out, "MDC2\n");
+#endif
+#ifdef OPENSSL_NO_OCB
+ BIO_puts(bio_out, "OCB\n");
+#endif
+#ifdef OPENSSL_NO_OCSP
+ BIO_puts(bio_out, "OCSP\n");
+#endif
+#ifdef OPENSSL_NO_PSK
+ BIO_puts(bio_out, "PSK\n");
+#endif
+#ifdef OPENSSL_NO_RC2
+ BIO_puts(bio_out, "RC2\n");
+#endif
+#ifdef OPENSSL_NO_RC4
+ BIO_puts(bio_out, "RC4\n");
+#endif
+#ifdef OPENSSL_NO_RC5
+ BIO_puts(bio_out, "RC5\n");
+#endif
+#ifdef OPENSSL_NO_RMD160
+ BIO_puts(bio_out, "RMD160\n");
+#endif
+#ifdef OPENSSL_NO_RSA
+ BIO_puts(bio_out, "RSA\n");
+#endif
+#ifdef OPENSSL_NO_SCRYPT
+ BIO_puts(bio_out, "SCRYPT\n");
+#endif
+#ifdef OPENSSL_NO_SCTP
+ BIO_puts(bio_out, "SCTP\n");
+#endif
+#ifdef OPENSSL_NO_SEED
+ BIO_puts(bio_out, "SEED\n");
+#endif
+#ifdef OPENSSL_NO_SM2
+ BIO_puts(bio_out, "SM2\n");
+#endif
+#ifdef OPENSSL_NO_SM3
+ BIO_puts(bio_out, "SM3\n");
+#endif
+#ifdef OPENSSL_NO_SM4
+ BIO_puts(bio_out, "SM4\n");
+#endif
+#ifdef OPENSSL_NO_SOCK
+ BIO_puts(bio_out, "SOCK\n");
+#endif
+#ifdef OPENSSL_NO_SRP
+ BIO_puts(bio_out, "SRP\n");
+#endif
+#ifdef OPENSSL_NO_SRTP
+ BIO_puts(bio_out, "SRTP\n");
+#endif
+#ifdef OPENSSL_NO_SSL3
+ BIO_puts(bio_out, "SSL3\n");
+#endif
+#ifdef OPENSSL_NO_TLS1
+ BIO_puts(bio_out, "TLS1\n");
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+ BIO_puts(bio_out, "TLS1_1\n");
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+ BIO_puts(bio_out, "TLS1_2\n");
+#endif
+#ifdef OPENSSL_NO_WHIRLPOOL
+ BIO_puts(bio_out, "WHIRLPOOL\n");
+#endif
+#ifndef ZLIB
+ BIO_puts(bio_out, "ZLIB\n");
+#endif
+}
+
+static LHASH_OF(FUNCTION) *prog_init(void)
+{
+ static LHASH_OF(FUNCTION) *ret = NULL;
+ static int prog_inited = 0;
+ FUNCTION *f;
+ size_t i;
+
+ if (prog_inited)
+ return ret;
+
+ prog_inited = 1;
+
+ /* Sort alphabetically within category. For nicer help displays. */
+ for (i = 0, f = functions; f->name != NULL; ++f, ++i)
+ ;
+ qsort(functions, i, sizeof(*functions), SortFnByName);
+
+ if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL)
+ return NULL;
+
+ for (f = functions; f->name != NULL; f++)
+ (void)lh_FUNCTION_insert(ret, f);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/opt.c b/freebsd/crypto/openssl/apps/opt.c
new file mode 100644
index 00000000..e56b53f9
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/opt.c
@@ -0,0 +1,900 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#include "apps.h"
+#include <string.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+# include OPENSSL_UNISTD
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <openssl/bio.h>
+#include <openssl/x509v3.h>
+
+#define MAX_OPT_HELP_WIDTH 30
+const char OPT_HELP_STR[] = "--";
+const char OPT_MORE_STR[] = "---";
+
+/* Our state */
+static char **argv;
+static int argc;
+static int opt_index;
+static char *arg;
+static char *flag;
+static char *dunno;
+static const OPTIONS *unknown;
+static const OPTIONS *opts;
+static char prog[40];
+
+/*
+ * Return the simple name of the program; removing various platform gunk.
+ */
+#if defined(OPENSSL_SYS_WIN32)
+char *opt_progname(const char *argv0)
+{
+ size_t i, n;
+ const char *p;
+ char *q;
+
+ /* find the last '/', '\' or ':' */
+ for (p = argv0 + strlen(argv0); --p > argv0;)
+ if (*p == '/' || *p == '\\' || *p == ':') {
+ p++;
+ break;
+ }
+
+ /* Strip off trailing nonsense. */
+ n = strlen(p);
+ if (n > 4 &&
+ (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
+ n -= 4;
+
+ /* Copy over the name, in lowercase. */
+ if (n > sizeof(prog) - 1)
+ n = sizeof(prog) - 1;
+ for (q = prog, i = 0; i < n; i++, p++)
+ *q++ = tolower((unsigned char)*p);
+ *q = '\0';
+ return prog;
+}
+
+#elif defined(OPENSSL_SYS_VMS)
+
+char *opt_progname(const char *argv0)
+{
+ const char *p, *q;
+
+ /* Find last special character sys:[foo.bar]openssl */
+ for (p = argv0 + strlen(argv0); --p > argv0;)
+ if (*p == ':' || *p == ']' || *p == '>') {
+ p++;
+ break;
+ }
+
+ q = strrchr(p, '.');
+ strncpy(prog, p, sizeof(prog) - 1);
+ prog[sizeof(prog) - 1] = '\0';
+ if (q != NULL && q - p < sizeof(prog))
+ prog[q - p] = '\0';
+ return prog;
+}
+
+#else
+
+char *opt_progname(const char *argv0)
+{
+ const char *p;
+
+ /* Could use strchr, but this is like the ones above. */
+ for (p = argv0 + strlen(argv0); --p > argv0;)
+ if (*p == '/') {
+ p++;
+ break;
+ }
+ strncpy(prog, p, sizeof(prog) - 1);
+ prog[sizeof(prog) - 1] = '\0';
+ return prog;
+}
+#endif
+
+char *opt_getprog(void)
+{
+ return prog;
+}
+
+/* Set up the arg parsing. */
+char *opt_init(int ac, char **av, const OPTIONS *o)
+{
+ /* Store state. */
+ argc = ac;
+ argv = av;
+ opt_index = 1;
+ opts = o;
+ opt_progname(av[0]);
+ unknown = NULL;
+
+ for (; o->name; ++o) {
+#ifndef NDEBUG
+ const OPTIONS *next;
+ int duplicated, i;
+#endif
+
+ if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR)
+ continue;
+#ifndef NDEBUG
+ i = o->valtype;
+
+ /* Make sure options are legit. */
+ assert(o->name[0] != '-');
+ assert(o->retval > 0);
+ switch (i) {
+ case 0: case '-': case '/': case '<': case '>': case 'E': case 'F':
+ case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's':
+ case 'u': case 'c':
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Make sure there are no duplicates. */
+ for (next = o + 1; next->name; ++next) {
+ /*
+ * Some compilers inline strcmp and the assert string is too long.
+ */
+ duplicated = strcmp(o->name, next->name) == 0;
+ assert(!duplicated);
+ }
+#endif
+ if (o->name[0] == '\0') {
+ assert(unknown == NULL);
+ unknown = o;
+ assert(unknown->valtype == 0 || unknown->valtype == '-');
+ }
+ }
+ return prog;
+}
+
+static OPT_PAIR formats[] = {
+ {"PEM/DER", OPT_FMT_PEMDER},
+ {"pkcs12", OPT_FMT_PKCS12},
+ {"smime", OPT_FMT_SMIME},
+ {"engine", OPT_FMT_ENGINE},
+ {"msblob", OPT_FMT_MSBLOB},
+ {"nss", OPT_FMT_NSS},
+ {"text", OPT_FMT_TEXT},
+ {"http", OPT_FMT_HTTP},
+ {"pvk", OPT_FMT_PVK},
+ {NULL}
+};
+
+/* Print an error message about a failed format parse. */
+int opt_format_error(const char *s, unsigned long flags)
+{
+ OPT_PAIR *ap;
+
+ if (flags == OPT_FMT_PEMDER) {
+ BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n",
+ prog, s);
+ } else {
+ BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n",
+ prog, s);
+ for (ap = formats; ap->name; ap++)
+ if (flags & ap->retval)
+ BIO_printf(bio_err, " %s\n", ap->name);
+ }
+ return 0;
+}
+
+/* Parse a format string, put it into *result; return 0 on failure, else 1. */
+int opt_format(const char *s, unsigned long flags, int *result)
+{
+ switch (*s) {
+ default:
+ return 0;
+ case 'D':
+ case 'd':
+ if ((flags & OPT_FMT_PEMDER) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_ASN1;
+ break;
+ case 'T':
+ case 't':
+ if ((flags & OPT_FMT_TEXT) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_TEXT;
+ break;
+ case 'N':
+ case 'n':
+ if ((flags & OPT_FMT_NSS) == 0)
+ return opt_format_error(s, flags);
+ if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_NSS;
+ break;
+ case 'S':
+ case 's':
+ if ((flags & OPT_FMT_SMIME) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_SMIME;
+ break;
+ case 'M':
+ case 'm':
+ if ((flags & OPT_FMT_MSBLOB) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_MSBLOB;
+ break;
+ case 'E':
+ case 'e':
+ if ((flags & OPT_FMT_ENGINE) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_ENGINE;
+ break;
+ case 'H':
+ case 'h':
+ if ((flags & OPT_FMT_HTTP) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_HTTP;
+ break;
+ case '1':
+ if ((flags & OPT_FMT_PKCS12) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PKCS12;
+ break;
+ case 'P':
+ case 'p':
+ if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) {
+ if ((flags & OPT_FMT_PEMDER) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PEM;
+ } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) {
+ if ((flags & OPT_FMT_PVK) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PVK;
+ } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0
+ || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) {
+ if ((flags & OPT_FMT_PKCS12) == 0)
+ return opt_format_error(s, flags);
+ *result = FORMAT_PKCS12;
+ } else {
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
+/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */
+int opt_cipher(const char *name, const EVP_CIPHER **cipherp)
+{
+ *cipherp = EVP_get_cipherbyname(name);
+ if (*cipherp != NULL)
+ return 1;
+ BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
+ return 0;
+}
+
+/*
+ * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1.
+ */
+int opt_md(const char *name, const EVP_MD **mdp)
+{
+ *mdp = EVP_get_digestbyname(name);
+ if (*mdp != NULL)
+ return 1;
+ BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name);
+ return 0;
+}
+
+/* Look through a list of name/value pairs. */
+int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
+{
+ const OPT_PAIR *pp;
+
+ for (pp = pairs; pp->name; pp++)
+ if (strcmp(pp->name, name) == 0) {
+ *result = pp->retval;
+ return 1;
+ }
+ BIO_printf(bio_err, "%s: Value must be one of:\n", prog);
+ for (pp = pairs; pp->name; pp++)
+ BIO_printf(bio_err, "\t%s\n", pp->name);
+ return 0;
+}
+
+/* Parse an int, put it into *result; return 0 on failure, else 1. */
+int opt_int(const char *value, int *result)
+{
+ long l;
+
+ if (!opt_long(value, &l))
+ return 0;
+ *result = (int)l;
+ if (*result != l) {
+ BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
+ prog, value);
+ return 0;
+ }
+ return 1;
+}
+
+static void opt_number_error(const char *v)
+{
+ size_t i = 0;
+ struct strstr_pair_st {
+ char *prefix;
+ char *name;
+ } b[] = {
+ {"0x", "a hexadecimal"},
+ {"0X", "a hexadecimal"},
+ {"0", "an octal"}
+ };
+
+ for (i = 0; i < OSSL_NELEM(b); i++) {
+ if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) {
+ BIO_printf(bio_err,
+ "%s: Can't parse \"%s\" as %s number\n",
+ prog, v, b[i].name);
+ return;
+ }
+ }
+ BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v);
+ return;
+}
+
+/* Parse a long, put it into *result; return 0 on failure, else 1. */
+int opt_long(const char *value, long *result)
+{
+ int oerrno = errno;
+ long l;
+ char *endp;
+
+ errno = 0;
+ l = strtol(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
+ || (l == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = l;
+ errno = oerrno;
+ return 1;
+}
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
+ defined(INTMAX_MAX) && defined(UINTMAX_MAX)
+
+/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
+int opt_imax(const char *value, intmax_t *result)
+{
+ int oerrno = errno;
+ intmax_t m;
+ char *endp;
+
+ errno = 0;
+ m = strtoimax(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE)
+ || (m == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = m;
+ errno = oerrno;
+ return 1;
+}
+
+/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */
+int opt_umax(const char *value, uintmax_t *result)
+{
+ int oerrno = errno;
+ uintmax_t m;
+ char *endp;
+
+ errno = 0;
+ m = strtoumax(value, &endp, 0);
+ if (*endp
+ || endp == value
+ || (m == UINTMAX_MAX && errno == ERANGE)
+ || (m == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = m;
+ errno = oerrno;
+ return 1;
+}
+#endif
+
+/*
+ * Parse an unsigned long, put it into *result; return 0 on failure, else 1.
+ */
+int opt_ulong(const char *value, unsigned long *result)
+{
+ int oerrno = errno;
+ char *endptr;
+ unsigned long l;
+
+ errno = 0;
+ l = strtoul(value, &endptr, 0);
+ if (*endptr
+ || endptr == value
+ || ((l == ULONG_MAX) && errno == ERANGE)
+ || (l == 0 && errno != 0)) {
+ opt_number_error(value);
+ errno = oerrno;
+ return 0;
+ }
+ *result = l;
+ errno = oerrno;
+ return 1;
+}
+
+/*
+ * We pass opt as an int but cast it to "enum range" so that all the
+ * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch
+ * in gcc do the right thing.
+ */
+enum range { OPT_V_ENUM };
+
+int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
+{
+ int i;
+ ossl_intmax_t t = 0;
+ ASN1_OBJECT *otmp;
+ X509_PURPOSE *xptmp;
+ const X509_VERIFY_PARAM *vtmp;
+
+ assert(vpm != NULL);
+ assert(opt > OPT_V__FIRST);
+ assert(opt < OPT_V__LAST);
+
+ switch ((enum range)opt) {
+ case OPT_V__FIRST:
+ case OPT_V__LAST:
+ return 0;
+ case OPT_V_POLICY:
+ otmp = OBJ_txt2obj(opt_arg(), 0);
+ if (otmp == NULL) {
+ BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_add0_policy(vpm, otmp);
+ break;
+ case OPT_V_PURPOSE:
+ /* purpose name -> purpose index */
+ i = X509_PURPOSE_get_by_sname(opt_arg());
+ if (i < 0) {
+ BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
+ return 0;
+ }
+
+ /* purpose index -> purpose object */
+ xptmp = X509_PURPOSE_get0(i);
+
+ /* purpose object -> purpose value */
+ i = X509_PURPOSE_get_id(xptmp);
+
+ if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
+ BIO_printf(bio_err,
+ "%s: Internal error setting purpose %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ break;
+ case OPT_V_VERIFY_NAME:
+ vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
+ if (vtmp == NULL) {
+ BIO_printf(bio_err, "%s: Invalid verify name %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_set1(vpm, vtmp);
+ break;
+ case OPT_V_VERIFY_DEPTH:
+ i = atoi(opt_arg());
+ if (i >= 0)
+ X509_VERIFY_PARAM_set_depth(vpm, i);
+ break;
+ case OPT_V_VERIFY_AUTH_LEVEL:
+ i = atoi(opt_arg());
+ if (i >= 0)
+ X509_VERIFY_PARAM_set_auth_level(vpm, i);
+ break;
+ case OPT_V_ATTIME:
+ if (!opt_imax(opt_arg(), &t))
+ return 0;
+ if (t != (time_t)t) {
+ BIO_printf(bio_err, "%s: epoch time out of range %s\n",
+ prog, opt_arg());
+ return 0;
+ }
+ X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
+ break;
+ case OPT_V_VERIFY_HOSTNAME:
+ if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
+ return 0;
+ break;
+ case OPT_V_VERIFY_EMAIL:
+ if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
+ return 0;
+ break;
+ case OPT_V_VERIFY_IP:
+ if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
+ return 0;
+ break;
+ case OPT_V_IGNORE_CRITICAL:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
+ break;
+ case OPT_V_ISSUER_CHECKS:
+ /* NOP, deprecated */
+ break;
+ case OPT_V_CRL_CHECK:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
+ break;
+ case OPT_V_CRL_CHECK_ALL:
+ X509_VERIFY_PARAM_set_flags(vpm,
+ X509_V_FLAG_CRL_CHECK |
+ X509_V_FLAG_CRL_CHECK_ALL);
+ break;
+ case OPT_V_POLICY_CHECK:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
+ break;
+ case OPT_V_EXPLICIT_POLICY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
+ break;
+ case OPT_V_INHIBIT_ANY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
+ break;
+ case OPT_V_INHIBIT_MAP:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
+ break;
+ case OPT_V_X509_STRICT:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
+ break;
+ case OPT_V_EXTENDED_CRL:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
+ break;
+ case OPT_V_USE_DELTAS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
+ break;
+ case OPT_V_POLICY_PRINT:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
+ break;
+ case OPT_V_CHECK_SS_SIG:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
+ break;
+ case OPT_V_TRUSTED_FIRST:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
+ break;
+ case OPT_V_SUITEB_128_ONLY:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
+ break;
+ case OPT_V_SUITEB_128:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
+ break;
+ case OPT_V_SUITEB_192:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
+ break;
+ case OPT_V_PARTIAL_CHAIN:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
+ break;
+ case OPT_V_NO_ALT_CHAINS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
+ break;
+ case OPT_V_NO_CHECK_TIME:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
+ break;
+ case OPT_V_ALLOW_PROXY_CERTS:
+ X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
+ break;
+ }
+ return 1;
+
+}
+
+/*
+ * Parse the next flag (and value if specified), return 0 if done, -1 on
+ * error, otherwise the flag's retval.
+ */
+int opt_next(void)
+{
+ char *p;
+ const OPTIONS *o;
+ int ival;
+ long lval;
+ unsigned long ulval;
+ ossl_intmax_t imval;
+ ossl_uintmax_t umval;
+
+ /* Look at current arg; at end of the list? */
+ arg = NULL;
+ p = argv[opt_index];
+ if (p == NULL)
+ return 0;
+
+ /* If word doesn't start with a -, we're done. */
+ if (*p != '-')
+ return 0;
+
+ /* Hit "--" ? We're done. */
+ opt_index++;
+ if (strcmp(p, "--") == 0)
+ return 0;
+
+ /* Allow -nnn and --nnn */
+ if (*++p == '-')
+ p++;
+ flag = p - 1;
+
+ /* If we have --flag=foo, snip it off */
+ if ((arg = strchr(p, '=')) != NULL)
+ *arg++ = '\0';
+ for (o = opts; o->name; ++o) {
+ /* If not this option, move on to the next one. */
+ if (strcmp(p, o->name) != 0)
+ continue;
+
+ /* If it doesn't take a value, make sure none was given. */
+ if (o->valtype == 0 || o->valtype == '-') {
+ if (arg) {
+ BIO_printf(bio_err,
+ "%s: Option -%s does not take a value\n", prog, p);
+ return -1;
+ }
+ return o->retval;
+ }
+
+ /* Want a value; get the next param if =foo not used. */
+ if (arg == NULL) {
+ if (argv[opt_index] == NULL) {
+ BIO_printf(bio_err,
+ "%s: Option -%s needs a value\n", prog, o->name);
+ return -1;
+ }
+ arg = argv[opt_index++];
+ }
+
+ /* Syntax-check value. */
+ switch (o->valtype) {
+ default:
+ case 's':
+ /* Just a string. */
+ break;
+ case '/':
+ if (app_isdir(arg) > 0)
+ break;
+ BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg);
+ return -1;
+ case '<':
+ /* Input file. */
+ break;
+ case '>':
+ /* Output file. */
+ break;
+ case 'p':
+ case 'n':
+ if (!opt_int(arg, &ival)
+ || (o->valtype == 'p' && ival <= 0)) {
+ BIO_printf(bio_err,
+ "%s: Non-positive number \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'M':
+ if (!opt_imax(arg, &imval)) {
+ BIO_printf(bio_err,
+ "%s: Invalid number \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'U':
+ if (!opt_umax(arg, &umval)) {
+ BIO_printf(bio_err,
+ "%s: Invalid number \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'l':
+ if (!opt_long(arg, &lval)) {
+ BIO_printf(bio_err,
+ "%s: Invalid number \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'u':
+ if (!opt_ulong(arg, &ulval)) {
+ BIO_printf(bio_err,
+ "%s: Invalid number \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+ break;
+ case 'c':
+ case 'E':
+ case 'F':
+ case 'f':
+ if (opt_format(arg,
+ o->valtype == 'c' ? OPT_FMT_PDS :
+ o->valtype == 'E' ? OPT_FMT_PDE :
+ o->valtype == 'F' ? OPT_FMT_PEMDER
+ : OPT_FMT_ANY, &ival))
+ break;
+ BIO_printf(bio_err,
+ "%s: Invalid format \"%s\" for -%s\n",
+ prog, arg, o->name);
+ return -1;
+ }
+
+ /* Return the flag value. */
+ return o->retval;
+ }
+ if (unknown != NULL) {
+ dunno = p;
+ return unknown->retval;
+ }
+ BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
+ return -1;
+}
+
+/* Return the most recent flag parameter. */
+char *opt_arg(void)
+{
+ return arg;
+}
+
+/* Return the most recent flag. */
+char *opt_flag(void)
+{
+ return flag;
+}
+
+/* Return the unknown option. */
+char *opt_unknown(void)
+{
+ return dunno;
+}
+
+/* Return the rest of the arguments after parsing flags. */
+char **opt_rest(void)
+{
+ return &argv[opt_index];
+}
+
+/* How many items in remaining args? */
+int opt_num_rest(void)
+{
+ int i = 0;
+ char **pp;
+
+ for (pp = opt_rest(); *pp; pp++, i++)
+ continue;
+ return i;
+}
+
+/* Return a string describing the parameter type. */
+static const char *valtype2param(const OPTIONS *o)
+{
+ switch (o->valtype) {
+ case 0:
+ case '-':
+ return "";
+ case 's':
+ return "val";
+ case '/':
+ return "dir";
+ case '<':
+ return "infile";
+ case '>':
+ return "outfile";
+ case 'p':
+ return "+int";
+ case 'n':
+ return "int";
+ case 'l':
+ return "long";
+ case 'u':
+ return "ulong";
+ case 'E':
+ return "PEM|DER|ENGINE";
+ case 'F':
+ return "PEM|DER";
+ case 'f':
+ return "format";
+ case 'M':
+ return "intmax";
+ case 'U':
+ return "uintmax";
+ }
+ return "parm";
+}
+
+void opt_help(const OPTIONS *list)
+{
+ const OPTIONS *o;
+ int i;
+ int standard_prolog;
+ int width = 5;
+ char start[80 + 1];
+ char *p;
+ const char *help;
+
+ /* Starts with its own help message? */
+ standard_prolog = list[0].name != OPT_HELP_STR;
+
+ /* Find the widest help. */
+ for (o = list; o->name; o++) {
+ if (o->name == OPT_MORE_STR)
+ continue;
+ i = 2 + (int)strlen(o->name);
+ if (o->valtype != '-')
+ i += 1 + strlen(valtype2param(o));
+ if (i < MAX_OPT_HELP_WIDTH && i > width)
+ width = i;
+ assert(i < (int)sizeof(start));
+ }
+
+ if (standard_prolog)
+ BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n",
+ prog);
+
+ /* Now let's print. */
+ for (o = list; o->name; o++) {
+ help = o->helpstr ? o->helpstr : "(No additional info)";
+ if (o->name == OPT_HELP_STR) {
+ BIO_printf(bio_err, help, prog);
+ continue;
+ }
+
+ /* Pad out prefix */
+ memset(start, ' ', sizeof(start) - 1);
+ start[sizeof(start) - 1] = '\0';
+
+ if (o->name == OPT_MORE_STR) {
+ /* Continuation of previous line; pad and print. */
+ start[width] = '\0';
+ BIO_printf(bio_err, "%s %s\n", start, help);
+ continue;
+ }
+
+ /* Build up the "-flag [param]" part. */
+ p = start;
+ *p++ = ' ';
+ *p++ = '-';
+ if (o->name[0])
+ p += strlen(strcpy(p, o->name));
+ else
+ *p++ = '*';
+ if (o->valtype != '-') {
+ *p++ = ' ';
+ p += strlen(strcpy(p, valtype2param(o)));
+ }
+ *p = ' ';
+ if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
+ *p = '\0';
+ BIO_printf(bio_err, "%s\n", start);
+ memset(start, ' ', sizeof(start));
+ }
+ start[width] = '\0';
+ BIO_printf(bio_err, "%s %s\n", start, help);
+ }
+}
diff --git a/freebsd/crypto/openssl/apps/passwd.c b/freebsd/crypto/openssl/apps/passwd.c
new file mode 100644
index 00000000..81d99190
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/passwd.c
@@ -0,0 +1,855 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+
+#include "apps.h"
+#include "progs.h"
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_DES
+# include <openssl/des.h>
+#endif
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+static unsigned const char cov_2char[64] = {
+ /* from crypto/des/fcrypt.c */
+ 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
+ 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
+ 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
+};
+
+static const char ascii_dollar[] = { 0x24, 0x00 };
+
+typedef enum {
+ passwd_unset = 0,
+ passwd_crypt,
+ passwd_md5,
+ passwd_apr1,
+ passwd_sha256,
+ passwd_sha512,
+ passwd_aixmd5
+} passwd_modes;
+
+static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
+ char *passwd, BIO *out, int quiet, int table,
+ int reverse, size_t pw_maxlen, passwd_modes mode);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_IN,
+ OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
+ OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS passwd_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Read passwords from file"},
+ {"noverify", OPT_NOVERIFY, '-',
+ "Never verify when reading password from terminal"},
+ {"quiet", OPT_QUIET, '-', "No warnings"},
+ {"table", OPT_TABLE, '-', "Format output as table"},
+ {"reverse", OPT_REVERSE, '-', "Switch table columns"},
+ {"salt", OPT_SALT, 's', "Use provided salt"},
+ {"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
+ {"6", OPT_6, '-', "SHA512-based password algorithm"},
+ {"5", OPT_5, '-', "SHA256-based password algorithm"},
+ {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"},
+ {"1", OPT_1, '-', "MD5-based password algorithm"},
+ {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"},
+#ifndef OPENSSL_NO_DES
+ {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"},
+#endif
+ OPT_R_OPTIONS,
+ {NULL}
+};
+
+int passwd_main(int argc, char **argv)
+{
+ BIO *in = NULL;
+ char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL;
+ char *salt_malloc = NULL, *passwd_malloc = NULL, *prog;
+ OPTION_CHOICE o;
+ int in_stdin = 0, pw_source_defined = 0;
+#ifndef OPENSSL_NO_UI_CONSOLE
+ int in_noverify = 0;
+#endif
+ int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
+ int ret = 1;
+ passwd_modes mode = passwd_unset;
+ size_t passwd_malloc_size = 0;
+ size_t pw_maxlen = 256; /* arbitrary limit, should be enough for most
+ * passwords */
+
+ prog = opt_init(argc, argv, passwd_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(passwd_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ if (pw_source_defined)
+ goto opthelp;
+ infile = opt_arg();
+ pw_source_defined = 1;
+ break;
+ case OPT_NOVERIFY:
+#ifndef OPENSSL_NO_UI_CONSOLE
+ in_noverify = 1;
+#endif
+ break;
+ case OPT_QUIET:
+ quiet = 1;
+ break;
+ case OPT_TABLE:
+ table = 1;
+ break;
+ case OPT_REVERSE:
+ reverse = 1;
+ break;
+ case OPT_1:
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_md5;
+ break;
+ case OPT_5:
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_sha256;
+ break;
+ case OPT_6:
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_sha512;
+ break;
+ case OPT_APR1:
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_apr1;
+ break;
+ case OPT_AIXMD5:
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_aixmd5;
+ break;
+ case OPT_CRYPT:
+#ifndef OPENSSL_NO_DES
+ if (mode != passwd_unset)
+ goto opthelp;
+ mode = passwd_crypt;
+#endif
+ break;
+ case OPT_SALT:
+ passed_salt = 1;
+ salt = opt_arg();
+ break;
+ case OPT_STDIN:
+ if (pw_source_defined)
+ goto opthelp;
+ in_stdin = 1;
+ pw_source_defined = 1;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (*argv != NULL) {
+ if (pw_source_defined)
+ goto opthelp;
+ pw_source_defined = 1;
+ passwds = argv;
+ }
+
+ if (mode == passwd_unset) {
+ /* use default */
+ mode = passwd_crypt;
+ }
+
+#ifdef OPENSSL_NO_DES
+ if (mode == passwd_crypt)
+ goto opthelp;
+#endif
+
+ if (infile != NULL && in_stdin) {
+ BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog);
+ goto end;
+ }
+
+ if (infile != NULL || in_stdin) {
+ /*
+ * If in_stdin is true, we know that infile is NULL, and that
+ * bio_open_default() will give us back an alias for stdin.
+ */
+ in = bio_open_default(infile, 'r', FORMAT_TEXT);
+ if (in == NULL)
+ goto end;
+ }
+
+ if (mode == passwd_crypt)
+ pw_maxlen = 8;
+
+ if (passwds == NULL) {
+ /* no passwords on the command line */
+
+ passwd_malloc_size = pw_maxlen + 2;
+ /* longer than necessary so that we can warn about truncation */
+ passwd = passwd_malloc =
+ app_malloc(passwd_malloc_size, "password buffer");
+ }
+
+ if ((in == NULL) && (passwds == NULL)) {
+ /*
+ * we use the following method to make sure what
+ * in the 'else' section is always compiled, to
+ * avoid rot of not-frequently-used code.
+ */
+ if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ /* build a null-terminated list */
+ static char *passwds_static[2] = { NULL, NULL };
+
+ passwds = passwds_static;
+ if (in == NULL) {
+ if (EVP_read_pw_string
+ (passwd_malloc, passwd_malloc_size, "Password: ",
+ !(passed_salt || in_noverify)) != 0)
+ goto end;
+ }
+ passwds[0] = passwd_malloc;
+ } else {
+#endif
+ BIO_printf(bio_err, "password required\n");
+ goto end;
+ }
+ }
+
+ if (in == NULL) {
+ assert(passwds != NULL);
+ assert(*passwds != NULL);
+
+ do { /* loop over list of passwords */
+ passwd = *passwds++;
+ if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out,
+ quiet, table, reverse, pw_maxlen, mode))
+ goto end;
+ } while (*passwds != NULL);
+ } else {
+ /* in != NULL */
+ int done;
+
+ assert(passwd != NULL);
+ do {
+ int r = BIO_gets(in, passwd, pw_maxlen + 1);
+ if (r > 0) {
+ char *c = (strchr(passwd, '\n'));
+ if (c != NULL) {
+ *c = 0; /* truncate at newline */
+ } else {
+ /* ignore rest of line */
+ char trash[BUFSIZ];
+ do
+ r = BIO_gets(in, trash, sizeof(trash));
+ while ((r > 0) && (!strchr(trash, '\n')));
+ }
+
+ if (!do_passwd
+ (passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet,
+ table, reverse, pw_maxlen, mode))
+ goto end;
+ }
+ done = (r <= 0);
+ } while (!done);
+ }
+ ret = 0;
+
+ end:
+#if 0
+ ERR_print_errors(bio_err);
+#endif
+ OPENSSL_free(salt_malloc);
+ OPENSSL_free(passwd_malloc);
+ BIO_free(in);
+ return ret;
+}
+
+/*
+ * MD5-based password algorithm (should probably be available as a library
+ * function; then the static buffer would not be acceptable). For magic
+ * string "1", this should be compatible to the MD5-based BSD password
+ * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
+ * Apache password algorithm. (Apparently, the Apache password algorithm is
+ * identical except that the 'magic' string was changed -- the laziest
+ * application of the NIH principle I've ever encountered.)
+ */
+static char *md5crypt(const char *passwd, const char *magic, const char *salt)
+{
+ /* "$apr1$..salt..$.......md5hash..........\0" */
+ static char out_buf[6 + 9 + 24 + 2];
+ unsigned char buf[MD5_DIGEST_LENGTH];
+ char ascii_magic[5]; /* "apr1" plus '\0' */
+ char ascii_salt[9]; /* Max 8 chars plus '\0' */
+ char *ascii_passwd = NULL;
+ char *salt_out;
+ int n;
+ unsigned int i;
+ EVP_MD_CTX *md = NULL, *md2 = NULL;
+ size_t passwd_len, salt_len, magic_len;
+
+ passwd_len = strlen(passwd);
+
+ out_buf[0] = 0;
+ magic_len = strlen(magic);
+ OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
+#ifdef CHARSET_EBCDIC
+ if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */
+ ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
+#endif
+
+ /* The salt gets truncated to 8 chars */
+ OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
+ salt_len = strlen(ascii_salt);
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
+#endif
+
+#ifdef CHARSET_EBCDIC
+ ascii_passwd = OPENSSL_strdup(passwd);
+ if (ascii_passwd == NULL)
+ return NULL;
+ ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
+ passwd = ascii_passwd;
+#endif
+
+ if (magic_len > 0) {
+ OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
+
+ if (magic_len > 4) /* assert it's "1" or "apr1" */
+ goto err;
+
+ OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
+ OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
+ }
+
+ OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
+
+ if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */
+ goto err;
+
+ salt_out = out_buf;
+ if (magic_len > 0)
+ salt_out += 2 + magic_len;
+
+ if (salt_len > 8)
+ goto err;
+
+ md = EVP_MD_CTX_new();
+ if (md == NULL
+ || !EVP_DigestInit_ex(md, EVP_md5(), NULL)
+ || !EVP_DigestUpdate(md, passwd, passwd_len))
+ goto err;
+
+ if (magic_len > 0)
+ if (!EVP_DigestUpdate(md, ascii_dollar, 1)
+ || !EVP_DigestUpdate(md, ascii_magic, magic_len)
+ || !EVP_DigestUpdate(md, ascii_dollar, 1))
+ goto err;
+
+ if (!EVP_DigestUpdate(md, ascii_salt, salt_len))
+ goto err;
+
+ md2 = EVP_MD_CTX_new();
+ if (md2 == NULL
+ || !EVP_DigestInit_ex(md2, EVP_md5(), NULL)
+ || !EVP_DigestUpdate(md2, passwd, passwd_len)
+ || !EVP_DigestUpdate(md2, ascii_salt, salt_len)
+ || !EVP_DigestUpdate(md2, passwd, passwd_len)
+ || !EVP_DigestFinal_ex(md2, buf, NULL))
+ goto err;
+
+ for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) {
+ if (!EVP_DigestUpdate(md, buf, sizeof(buf)))
+ goto err;
+ }
+ if (!EVP_DigestUpdate(md, buf, i))
+ goto err;
+
+ n = passwd_len;
+ while (n) {
+ if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1))
+ goto err;
+ n >>= 1;
+ }
+ if (!EVP_DigestFinal_ex(md, buf, NULL))
+ return NULL;
+
+ for (i = 0; i < 1000; i++) {
+ if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
+ goto err;
+ if (!EVP_DigestUpdate(md2,
+ (i & 1) ? (unsigned const char *)passwd : buf,
+ (i & 1) ? passwd_len : sizeof(buf)))
+ goto err;
+ if (i % 3) {
+ if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
+ goto err;
+ }
+ if (i % 7) {
+ if (!EVP_DigestUpdate(md2, passwd, passwd_len))
+ goto err;
+ }
+ if (!EVP_DigestUpdate(md2,
+ (i & 1) ? buf : (unsigned const char *)passwd,
+ (i & 1) ? sizeof(buf) : passwd_len))
+ goto err;
+ if (!EVP_DigestFinal_ex(md2, buf, NULL))
+ goto err;
+ }
+ EVP_MD_CTX_free(md2);
+ EVP_MD_CTX_free(md);
+ md2 = NULL;
+ md = NULL;
+
+ {
+ /* transform buf into output string */
+ unsigned char buf_perm[sizeof(buf)];
+ int dest, source;
+ char *output;
+
+ /* silly output permutation */
+ for (dest = 0, source = 0; dest < 14;
+ dest++, source = (source + 6) % 17)
+ buf_perm[dest] = buf[source];
+ buf_perm[14] = buf[5];
+ buf_perm[15] = buf[11];
+# ifndef PEDANTIC /* Unfortunately, this generates a "no
+ * effect" warning */
+ assert(16 == sizeof(buf_perm));
+# endif
+
+ output = salt_out + salt_len;
+ assert(output == out_buf + strlen(out_buf));
+
+ *output++ = ascii_dollar[0];
+
+ for (i = 0; i < 15; i += 3) {
+ *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
+ *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
+ (buf_perm[i + 2] >> 6)];
+ *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
+ (buf_perm[i + 1] >> 4)];
+ *output++ = cov_2char[buf_perm[i] >> 2];
+ }
+ assert(i == 15);
+ *output++ = cov_2char[buf_perm[i] & 0x3f];
+ *output++ = cov_2char[buf_perm[i] >> 6];
+ *output = 0;
+ assert(strlen(out_buf) < sizeof(out_buf));
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
+#endif
+ }
+
+ return out_buf;
+
+ err:
+ OPENSSL_free(ascii_passwd);
+ EVP_MD_CTX_free(md2);
+ EVP_MD_CTX_free(md);
+ return NULL;
+}
+
+/*
+ * SHA based password algorithm, describe by Ulrich Drepper here:
+ * https://www.akkadia.org/drepper/SHA-crypt.txt
+ * (note that it's in the public domain)
+ */
+static char *shacrypt(const char *passwd, const char *magic, const char *salt)
+{
+ /* Prefix for optional rounds specification. */
+ static const char rounds_prefix[] = "rounds=";
+ /* Maximum salt string length. */
+# define SALT_LEN_MAX 16
+ /* Default number of rounds if not explicitly specified. */
+# define ROUNDS_DEFAULT 5000
+ /* Minimum number of rounds. */
+# define ROUNDS_MIN 1000
+ /* Maximum number of rounds. */
+# define ROUNDS_MAX 999999999
+
+ /* "$6$rounds=<N>$......salt......$...shahash(up to 86 chars)...\0" */
+ static char out_buf[3 + 17 + 17 + 86 + 1];
+ unsigned char buf[SHA512_DIGEST_LENGTH];
+ unsigned char temp_buf[SHA512_DIGEST_LENGTH];
+ size_t buf_size = 0;
+ char ascii_magic[2];
+ char ascii_salt[17]; /* Max 16 chars plus '\0' */
+ char *ascii_passwd = NULL;
+ size_t n;
+ EVP_MD_CTX *md = NULL, *md2 = NULL;
+ const EVP_MD *sha = NULL;
+ size_t passwd_len, salt_len, magic_len;
+ unsigned int rounds = 5000; /* Default */
+ char rounds_custom = 0;
+ char *p_bytes = NULL;
+ char *s_bytes = NULL;
+ char *cp = NULL;
+
+ passwd_len = strlen(passwd);
+ magic_len = strlen(magic);
+
+ /* assert it's "5" or "6" */
+ if (magic_len != 1)
+ return NULL;
+
+ switch (magic[0]) {
+ case '5':
+ sha = EVP_sha256();
+ buf_size = 32;
+ break;
+ case '6':
+ sha = EVP_sha512();
+ buf_size = 64;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (strncmp(salt, rounds_prefix, sizeof(rounds_prefix) - 1) == 0) {
+ const char *num = salt + sizeof(rounds_prefix) - 1;
+ char *endp;
+ unsigned long int srounds = strtoul (num, &endp, 10);
+ if (*endp == '$') {
+ salt = endp + 1;
+ if (srounds > ROUNDS_MAX)
+ rounds = ROUNDS_MAX;
+ else if (srounds < ROUNDS_MIN)
+ rounds = ROUNDS_MIN;
+ else
+ rounds = (unsigned int)srounds;
+ rounds_custom = 1;
+ } else {
+ return NULL;
+ }
+ }
+
+ OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
+#ifdef CHARSET_EBCDIC
+ if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */
+ ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
+#endif
+
+ /* The salt gets truncated to 16 chars */
+ OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
+ salt_len = strlen(ascii_salt);
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
+#endif
+
+#ifdef CHARSET_EBCDIC
+ ascii_passwd = OPENSSL_strdup(passwd);
+ if (ascii_passwd == NULL)
+ return NULL;
+ ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
+ passwd = ascii_passwd;
+#endif
+
+ out_buf[0] = 0;
+ OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
+ OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
+ OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
+ if (rounds_custom) {
+ char tmp_buf[80]; /* "rounds=999999999" */
+ sprintf(tmp_buf, "rounds=%u", rounds);
+#ifdef CHARSET_EBCDIC
+ /* In case we're really on a ASCII based platform and just pretend */
+ if (tmp_buf[0] != 0x72) /* ASCII 'r' */
+ ebcdic2ascii(tmp_buf, tmp_buf, strlen(tmp_buf));
+#endif
+ OPENSSL_strlcat(out_buf, tmp_buf, sizeof(out_buf));
+ OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
+ }
+ OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
+
+ /* assert "$5$rounds=999999999$......salt......" */
+ if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len )
+ goto err;
+
+ md = EVP_MD_CTX_new();
+ if (md == NULL
+ || !EVP_DigestInit_ex(md, sha, NULL)
+ || !EVP_DigestUpdate(md, passwd, passwd_len)
+ || !EVP_DigestUpdate(md, ascii_salt, salt_len))
+ goto err;
+
+ md2 = EVP_MD_CTX_new();
+ if (md2 == NULL
+ || !EVP_DigestInit_ex(md2, sha, NULL)
+ || !EVP_DigestUpdate(md2, passwd, passwd_len)
+ || !EVP_DigestUpdate(md2, ascii_salt, salt_len)
+ || !EVP_DigestUpdate(md2, passwd, passwd_len)
+ || !EVP_DigestFinal_ex(md2, buf, NULL))
+ goto err;
+
+ for (n = passwd_len; n > buf_size; n -= buf_size) {
+ if (!EVP_DigestUpdate(md, buf, buf_size))
+ goto err;
+ }
+ if (!EVP_DigestUpdate(md, buf, n))
+ goto err;
+
+ n = passwd_len;
+ while (n) {
+ if (!EVP_DigestUpdate(md,
+ (n & 1) ? buf : (unsigned const char *)passwd,
+ (n & 1) ? buf_size : passwd_len))
+ goto err;
+ n >>= 1;
+ }
+ if (!EVP_DigestFinal_ex(md, buf, NULL))
+ return NULL;
+
+ /* P sequence */
+ if (!EVP_DigestInit_ex(md2, sha, NULL))
+ goto err;
+
+ for (n = passwd_len; n > 0; n--)
+ if (!EVP_DigestUpdate(md2, passwd, passwd_len))
+ goto err;
+
+ if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
+ return NULL;
+
+ if ((p_bytes = OPENSSL_zalloc(passwd_len)) == NULL)
+ goto err;
+ for (cp = p_bytes, n = passwd_len; n > buf_size; n -= buf_size, cp += buf_size)
+ memcpy(cp, temp_buf, buf_size);
+ memcpy(cp, temp_buf, n);
+
+ /* S sequence */
+ if (!EVP_DigestInit_ex(md2, sha, NULL))
+ goto err;
+
+ for (n = 16 + buf[0]; n > 0; n--)
+ if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
+ goto err;
+
+ if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
+ return NULL;
+
+ if ((s_bytes = OPENSSL_zalloc(salt_len)) == NULL)
+ goto err;
+ for (cp = s_bytes, n = salt_len; n > buf_size; n -= buf_size, cp += buf_size)
+ memcpy(cp, temp_buf, buf_size);
+ memcpy(cp, temp_buf, n);
+
+ for (n = 0; n < rounds; n++) {
+ if (!EVP_DigestInit_ex(md2, sha, NULL))
+ goto err;
+ if (!EVP_DigestUpdate(md2,
+ (n & 1) ? (unsigned const char *)p_bytes : buf,
+ (n & 1) ? passwd_len : buf_size))
+ goto err;
+ if (n % 3) {
+ if (!EVP_DigestUpdate(md2, s_bytes, salt_len))
+ goto err;
+ }
+ if (n % 7) {
+ if (!EVP_DigestUpdate(md2, p_bytes, passwd_len))
+ goto err;
+ }
+ if (!EVP_DigestUpdate(md2,
+ (n & 1) ? buf : (unsigned const char *)p_bytes,
+ (n & 1) ? buf_size : passwd_len))
+ goto err;
+ if (!EVP_DigestFinal_ex(md2, buf, NULL))
+ goto err;
+ }
+ EVP_MD_CTX_free(md2);
+ EVP_MD_CTX_free(md);
+ md2 = NULL;
+ md = NULL;
+ OPENSSL_free(p_bytes);
+ OPENSSL_free(s_bytes);
+ p_bytes = NULL;
+ s_bytes = NULL;
+
+ cp = out_buf + strlen(out_buf);
+ *cp++ = ascii_dollar[0];
+
+# define b64_from_24bit(B2, B1, B0, N) \
+ do { \
+ unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
+ int i = (N); \
+ while (i-- > 0) \
+ { \
+ *cp++ = cov_2char[w & 0x3f]; \
+ w >>= 6; \
+ } \
+ } while (0)
+
+ switch (magic[0]) {
+ case '5':
+ b64_from_24bit (buf[0], buf[10], buf[20], 4);
+ b64_from_24bit (buf[21], buf[1], buf[11], 4);
+ b64_from_24bit (buf[12], buf[22], buf[2], 4);
+ b64_from_24bit (buf[3], buf[13], buf[23], 4);
+ b64_from_24bit (buf[24], buf[4], buf[14], 4);
+ b64_from_24bit (buf[15], buf[25], buf[5], 4);
+ b64_from_24bit (buf[6], buf[16], buf[26], 4);
+ b64_from_24bit (buf[27], buf[7], buf[17], 4);
+ b64_from_24bit (buf[18], buf[28], buf[8], 4);
+ b64_from_24bit (buf[9], buf[19], buf[29], 4);
+ b64_from_24bit (0, buf[31], buf[30], 3);
+ break;
+ case '6':
+ b64_from_24bit (buf[0], buf[21], buf[42], 4);
+ b64_from_24bit (buf[22], buf[43], buf[1], 4);
+ b64_from_24bit (buf[44], buf[2], buf[23], 4);
+ b64_from_24bit (buf[3], buf[24], buf[45], 4);
+ b64_from_24bit (buf[25], buf[46], buf[4], 4);
+ b64_from_24bit (buf[47], buf[5], buf[26], 4);
+ b64_from_24bit (buf[6], buf[27], buf[48], 4);
+ b64_from_24bit (buf[28], buf[49], buf[7], 4);
+ b64_from_24bit (buf[50], buf[8], buf[29], 4);
+ b64_from_24bit (buf[9], buf[30], buf[51], 4);
+ b64_from_24bit (buf[31], buf[52], buf[10], 4);
+ b64_from_24bit (buf[53], buf[11], buf[32], 4);
+ b64_from_24bit (buf[12], buf[33], buf[54], 4);
+ b64_from_24bit (buf[34], buf[55], buf[13], 4);
+ b64_from_24bit (buf[56], buf[14], buf[35], 4);
+ b64_from_24bit (buf[15], buf[36], buf[57], 4);
+ b64_from_24bit (buf[37], buf[58], buf[16], 4);
+ b64_from_24bit (buf[59], buf[17], buf[38], 4);
+ b64_from_24bit (buf[18], buf[39], buf[60], 4);
+ b64_from_24bit (buf[40], buf[61], buf[19], 4);
+ b64_from_24bit (buf[62], buf[20], buf[41], 4);
+ b64_from_24bit (0, 0, buf[63], 2);
+ break;
+ default:
+ goto err;
+ }
+ *cp = '\0';
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
+#endif
+
+ return out_buf;
+
+ err:
+ EVP_MD_CTX_free(md2);
+ EVP_MD_CTX_free(md);
+ OPENSSL_free(p_bytes);
+ OPENSSL_free(s_bytes);
+ OPENSSL_free(ascii_passwd);
+ return NULL;
+}
+
+static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
+ char *passwd, BIO *out, int quiet, int table,
+ int reverse, size_t pw_maxlen, passwd_modes mode)
+{
+ char *hash = NULL;
+
+ assert(salt_p != NULL);
+ assert(salt_malloc_p != NULL);
+
+ /* first make sure we have a salt */
+ if (!passed_salt) {
+ size_t saltlen = 0;
+ size_t i;
+
+#ifndef OPENSSL_NO_DES
+ if (mode == passwd_crypt)
+ saltlen = 2;
+#endif /* !OPENSSL_NO_DES */
+
+ if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5)
+ saltlen = 8;
+
+ if (mode == passwd_sha256 || mode == passwd_sha512)
+ saltlen = 16;
+
+ assert(saltlen != 0);
+
+ if (*salt_malloc_p == NULL)
+ *salt_p = *salt_malloc_p = app_malloc(saltlen + 1, "salt buffer");
+ if (RAND_bytes((unsigned char *)*salt_p, saltlen) <= 0)
+ goto end;
+
+ for (i = 0; i < saltlen; i++)
+ (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
+ (*salt_p)[i] = 0;
+# ifdef CHARSET_EBCDIC
+ /* The password encryption funtion will convert back to ASCII */
+ ascii2ebcdic(*salt_p, *salt_p, saltlen);
+# endif
+ }
+
+ assert(*salt_p != NULL);
+
+ /* truncate password if necessary */
+ if ((strlen(passwd) > pw_maxlen)) {
+ if (!quiet)
+ /*
+ * XXX: really we should know how to print a size_t, not cast it
+ */
+ BIO_printf(bio_err,
+ "Warning: truncating password to %u characters\n",
+ (unsigned)pw_maxlen);
+ passwd[pw_maxlen] = 0;
+ }
+ assert(strlen(passwd) <= pw_maxlen);
+
+ /* now compute password hash */
+#ifndef OPENSSL_NO_DES
+ if (mode == passwd_crypt)
+ hash = DES_crypt(passwd, *salt_p);
+#endif
+ if (mode == passwd_md5 || mode == passwd_apr1)
+ hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p);
+ if (mode == passwd_aixmd5)
+ hash = md5crypt(passwd, "", *salt_p);
+ if (mode == passwd_sha256 || mode == passwd_sha512)
+ hash = shacrypt(passwd, (mode == passwd_sha256 ? "5" : "6"), *salt_p);
+ assert(hash != NULL);
+
+ if (table && !reverse)
+ BIO_printf(out, "%s\t%s\n", passwd, hash);
+ else if (table && reverse)
+ BIO_printf(out, "%s\t%s\n", hash, passwd);
+ else
+ BIO_printf(out, "%s\n", hash);
+ return 1;
+
+ end:
+ return 0;
+}
diff --git a/freebsd/crypto/openssl/apps/pkcs12.c b/freebsd/crypto/openssl/apps/pkcs12.c
new file mode 100644
index 00000000..66a4bac7
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkcs12.c
@@ -0,0 +1,963 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#if defined(OPENSSL_NO_DES)
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/crypto.h>
+# include <openssl/err.h>
+# include <openssl/pem.h>
+# include <openssl/pkcs12.h>
+
+# define NOKEYS 0x1
+# define NOCERTS 0x2
+# define INFO 0x4
+# define CLCERTS 0x8
+# define CACERTS 0x10
+
+#define PASSWD_BUF_SIZE 2048
+
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain);
+int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
+ const char *pass, int passlen, int options,
+ char *pempass, const EVP_CIPHER *enc);
+int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
+ const char *pass, int passlen, int options,
+ char *pempass, const EVP_CIPHER *enc);
+int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags,
+ const char *pass, int passlen,
+ int options, char *pempass, const EVP_CIPHER *enc);
+int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
+ const char *name);
+void hex_prin(BIO *out, unsigned char *buf, int len);
+static int alg_print(const X509_ALGOR *alg);
+int cert_load(BIO *in, STACK_OF(X509) *sk);
+static int set_pbe(int *ppbe, const char *str);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
+ OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
+ OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
+ OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
+ OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
+ OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
+ OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS pkcs12_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
+ {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"},
+ {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"},
+ {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
+ {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
+ {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
+ {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"},
+ {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
+ {"chain", OPT_CHAIN, '-', "Add certificate chain"},
+ {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
+ {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"},
+# ifndef OPENSSL_NO_RC2
+ {"descert", OPT_DESCERT, '-',
+ "Encrypt output with 3DES (default RC2-40)"},
+ {"certpbe", OPT_CERTPBE, 's',
+ "Certificate PBE algorithm (default RC2-40)"},
+# else
+ {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"},
+ {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"},
+# endif
+ {"export", OPT_EXPORT, '-', "Output PKCS12 file"},
+ {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
+ {"maciter", OPT_MACITER, '-', "Use MAC iteration"},
+ {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"},
+ {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
+ {"LMK", OPT_LMK, '-',
+ "Add local machine keyset attribute to private key"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt private keys"},
+ {"macalg", OPT_MACALG, 's',
+ "Digest algorithm used in MAC (default SHA1)"},
+ {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
+ OPT_R_OPTIONS,
+ {"inkey", OPT_INKEY, 's', "Private key if not infile"},
+ {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
+ {"name", OPT_NAME, 's', "Use name as friendly name"},
+ {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
+ {"caname", OPT_CANAME, 's',
+ "Use name as CA friendly name (can be repeated)"},
+ {"in", OPT_IN, '<', "Input filename"},
+ {"out", OPT_OUT, '>', "Output filename"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"password", OPT_PASSWORD, 's', "Set import/export password source"},
+ {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
+ {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int pkcs12_main(int argc, char **argv)
+{
+ char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
+ char *name = NULL, *csp_name = NULL;
+ char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
+ int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
+ int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
+# ifndef OPENSSL_NO_RC2
+ int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
+# else
+ int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+# endif
+ int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ int ret = 1, macver = 1, add_lmk = 0, private = 0;
+ int noprompt = 0;
+ char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
+ char *passin = NULL, *passout = NULL, *macalg = NULL;
+ char *cpass = NULL, *mpass = NULL, *badpass = NULL;
+ const char *CApath = NULL, *CAfile = NULL, *prog;
+ int noCApath = 0, noCAfile = 0;
+ ENGINE *e = NULL;
+ BIO *in = NULL, *out = NULL;
+ PKCS12 *p12 = NULL;
+ STACK_OF(OPENSSL_STRING) *canames = NULL;
+ const EVP_CIPHER *enc = EVP_des_ede3_cbc();
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, pkcs12_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkcs12_options);
+ ret = 0;
+ goto end;
+ case OPT_NOKEYS:
+ options |= NOKEYS;
+ break;
+ case OPT_KEYEX:
+ keytype = KEY_EX;
+ break;
+ case OPT_KEYSIG:
+ keytype = KEY_SIG;
+ break;
+ case OPT_NOCERTS:
+ options |= NOCERTS;
+ break;
+ case OPT_CLCERTS:
+ options |= CLCERTS;
+ break;
+ case OPT_CACERTS:
+ options |= CACERTS;
+ break;
+ case OPT_NOOUT:
+ options |= (NOKEYS | NOCERTS);
+ break;
+ case OPT_INFO:
+ options |= INFO;
+ break;
+ case OPT_CHAIN:
+ chain = 1;
+ break;
+ case OPT_TWOPASS:
+ twopass = 1;
+ break;
+ case OPT_NOMACVER:
+ macver = 0;
+ break;
+ case OPT_DESCERT:
+ cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ break;
+ case OPT_EXPORT:
+ export_cert = 1;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto opthelp;
+ break;
+ case OPT_NOITER:
+ iter = 1;
+ break;
+ case OPT_MACITER:
+ maciter = PKCS12_DEFAULT_ITER;
+ break;
+ case OPT_NOMACITER:
+ maciter = 1;
+ break;
+ case OPT_NOMAC:
+ maciter = -1;
+ break;
+ case OPT_MACALG:
+ macalg = opt_arg();
+ break;
+ case OPT_NODES:
+ enc = NULL;
+ break;
+ case OPT_CERTPBE:
+ if (!set_pbe(&cert_pbe, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_KEYPBE:
+ if (!set_pbe(&key_pbe, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_INKEY:
+ keyname = opt_arg();
+ break;
+ case OPT_CERTFILE:
+ certfile = opt_arg();
+ break;
+ case OPT_NAME:
+ name = opt_arg();
+ break;
+ case OPT_LMK:
+ add_lmk = 1;
+ break;
+ case OPT_CSP:
+ csp_name = opt_arg();
+ break;
+ case OPT_CANAME:
+ if (canames == NULL
+ && (canames = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(canames, opt_arg());
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_PASSWORD:
+ passarg = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = 1;
+
+ if (passarg != NULL) {
+ if (export_cert)
+ passoutarg = passarg;
+ else
+ passinarg = passarg;
+ }
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if (cpass == NULL) {
+ if (export_cert)
+ cpass = passout;
+ else
+ cpass = passin;
+ }
+
+ if (cpass != NULL) {
+ mpass = cpass;
+ noprompt = 1;
+ } else {
+ cpass = pass;
+ mpass = macpass;
+ }
+
+ if (twopass) {
+ /* To avoid bit rot */
+ if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ if (EVP_read_pw_string(
+ macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ goto end;
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "Unsupported option -twopass\n");
+ goto end;
+ }
+ }
+
+ if (export_cert) {
+ EVP_PKEY *key = NULL;
+ X509 *ucert = NULL, *x = NULL;
+ STACK_OF(X509) *certs = NULL;
+ const EVP_MD *macmd = NULL;
+ unsigned char *catmp = NULL;
+ int i;
+
+ if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
+ BIO_printf(bio_err, "Nothing to do!\n");
+ goto export_end;
+ }
+
+ if (options & NOCERTS)
+ chain = 0;
+
+ if (!(options & NOKEYS)) {
+ key = load_key(keyname ? keyname : infile,
+ FORMAT_PEM, 1, passin, e, "private key");
+ if (key == NULL)
+ goto export_end;
+ }
+
+ /* Load in all certs in input file */
+ if (!(options & NOCERTS)) {
+ if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
+ "certificates"))
+ goto export_end;
+
+ if (key != NULL) {
+ /* Look for matching private key */
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ x = sk_X509_value(certs, i);
+ if (X509_check_private_key(x, key)) {
+ ucert = x;
+ /* Zero keyid and alias */
+ X509_keyid_set1(ucert, NULL, 0);
+ X509_alias_set1(ucert, NULL, 0);
+ /* Remove from list */
+ (void)sk_X509_delete(certs, i);
+ break;
+ }
+ }
+ if (ucert == NULL) {
+ BIO_printf(bio_err,
+ "No certificate matches private key\n");
+ goto export_end;
+ }
+ }
+
+ }
+
+ /* Add any more certificates asked for */
+ if (certfile != NULL) {
+ if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
+ "certificates from certfile"))
+ goto export_end;
+ }
+
+ /* If chaining get chain from user cert */
+ if (chain) {
+ int vret;
+ STACK_OF(X509) *chain2;
+ X509_STORE *store;
+ if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath))
+ == NULL)
+ goto export_end;
+
+ vret = get_cert_chain(ucert, store, &chain2);
+ X509_STORE_free(store);
+
+ if (vret == X509_V_OK) {
+ /* Exclude verified certificate */
+ for (i = 1; i < sk_X509_num(chain2); i++)
+ sk_X509_push(certs, sk_X509_value(chain2, i));
+ /* Free first certificate */
+ X509_free(sk_X509_value(chain2, 0));
+ sk_X509_free(chain2);
+ } else {
+ if (vret != X509_V_ERR_UNSPECIFIED)
+ BIO_printf(bio_err, "Error %s getting chain.\n",
+ X509_verify_cert_error_string(vret));
+ else
+ ERR_print_errors(bio_err);
+ goto export_end;
+ }
+ }
+
+ /* Add any CA names */
+
+ for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
+ catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
+ X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
+ }
+
+ if (csp_name != NULL && key != NULL)
+ EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
+ MBSTRING_ASC, (unsigned char *)csp_name,
+ -1);
+
+ if (add_lmk && key != NULL)
+ EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
+
+ if (!noprompt) {
+ /* To avoid bit rot */
+ if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ if (EVP_read_pw_string(pass, sizeof(pass),
+ "Enter Export Password:", 1)) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ goto export_end;
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "Password required\n");
+ goto export_end;
+ }
+ }
+
+ if (!twopass)
+ OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
+
+ p12 = PKCS12_create(cpass, name, key, ucert, certs,
+ key_pbe, cert_pbe, iter, -1, keytype);
+
+ if (!p12) {
+ ERR_print_errors(bio_err);
+ goto export_end;
+ }
+
+ if (macalg) {
+ if (!opt_md(macalg, &macmd))
+ goto opthelp;
+ }
+
+ if (maciter != -1)
+ PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
+
+ assert(private);
+
+ out = bio_open_owner(outfile, FORMAT_PKCS12, private);
+ if (out == NULL)
+ goto end;
+
+ i2d_PKCS12_bio(out, p12);
+
+ ret = 0;
+
+ export_end:
+
+ EVP_PKEY_free(key);
+ sk_X509_pop_free(certs, X509_free);
+ X509_free(ucert);
+
+ goto end;
+
+ }
+
+ in = bio_open_default(infile, 'r', FORMAT_PKCS12);
+ if (in == NULL)
+ goto end;
+ out = bio_open_owner(outfile, FORMAT_PEM, private);
+ if (out == NULL)
+ goto end;
+
+ if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (!noprompt) {
+ if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:",
+ 0)) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ goto end;
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "Password required\n");
+ goto end;
+ }
+ }
+
+ if (!twopass)
+ OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
+
+ if ((options & INFO) && PKCS12_mac_present(p12)) {
+ const ASN1_INTEGER *tmaciter;
+ const X509_ALGOR *macalgid;
+ const ASN1_OBJECT *macobj;
+ const ASN1_OCTET_STRING *tmac;
+ const ASN1_OCTET_STRING *tsalt;
+
+ PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12);
+ /* current hash algorithms do not use parameters so extract just name,
+ in future alg_print() may be needed */
+ X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
+ BIO_puts(bio_err, "MAC: ");
+ i2a_ASN1_OBJECT(bio_err, macobj);
+ BIO_printf(bio_err, ", Iteration %ld\n",
+ tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
+ BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
+ tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
+ tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
+ }
+ if (macver) {
+ /* If we enter empty password try no password first */
+ if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
+ /* If mac and crypto pass the same set it to NULL too */
+ if (!twopass)
+ cpass = NULL;
+ } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
+ /*
+ * May be UTF8 from previous version of OpenSSL:
+ * convert to a UTF8 form which will translate
+ * to the same Unicode password.
+ */
+ unsigned char *utmp;
+ int utmplen;
+ utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
+ if (utmp == NULL)
+ goto end;
+ badpass = OPENSSL_uni2utf8(utmp, utmplen);
+ OPENSSL_free(utmp);
+ if (!PKCS12_verify_mac(p12, badpass, -1)) {
+ BIO_printf(bio_err, "Mac verify error: invalid password?\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Warning: using broken algorithm\n");
+ if (!twopass)
+ cpass = badpass;
+ }
+ }
+ }
+
+ assert(private);
+ if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
+ BIO_printf(bio_err, "Error outputting keys and certificates\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ end:
+ PKCS12_free(p12);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free_all(out);
+ sk_OPENSSL_STRING_free(canames);
+ OPENSSL_free(badpass);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+ return ret;
+}
+
+int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
+ int passlen, int options, char *pempass,
+ const EVP_CIPHER *enc)
+{
+ STACK_OF(PKCS7) *asafes = NULL;
+ STACK_OF(PKCS12_SAFEBAG) *bags;
+ int i, bagnid;
+ int ret = 0;
+ PKCS7 *p7;
+
+ if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
+ return 0;
+ for (i = 0; i < sk_PKCS7_num(asafes); i++) {
+ p7 = sk_PKCS7_value(asafes, i);
+ bagnid = OBJ_obj2nid(p7->type);
+ if (bagnid == NID_pkcs7_data) {
+ bags = PKCS12_unpack_p7data(p7);
+ if (options & INFO)
+ BIO_printf(bio_err, "PKCS7 Data\n");
+ } else if (bagnid == NID_pkcs7_encrypted) {
+ if (options & INFO) {
+ BIO_printf(bio_err, "PKCS7 Encrypted data: ");
+ alg_print(p7->d.encrypted->enc_data->algorithm);
+ }
+ bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
+ } else {
+ continue;
+ }
+ if (!bags)
+ goto err;
+ if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
+ options, pempass, enc)) {
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ goto err;
+ }
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ bags = NULL;
+ }
+ ret = 1;
+
+ err:
+ sk_PKCS7_pop_free(asafes, PKCS7_free);
+ return ret;
+}
+
+int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
+ const char *pass, int passlen, int options,
+ char *pempass, const EVP_CIPHER *enc)
+{
+ int i;
+ for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
+ if (!dump_certs_pkeys_bag(out,
+ sk_PKCS12_SAFEBAG_value(bags, i),
+ pass, passlen, options, pempass, enc))
+ return 0;
+ }
+ return 1;
+}
+
+int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
+ const char *pass, int passlen, int options,
+ char *pempass, const EVP_CIPHER *enc)
+{
+ EVP_PKEY *pkey;
+ PKCS8_PRIV_KEY_INFO *p8;
+ const PKCS8_PRIV_KEY_INFO *p8c;
+ X509 *x509;
+ const STACK_OF(X509_ATTRIBUTE) *attrs;
+ int ret = 0;
+
+ attrs = PKCS12_SAFEBAG_get0_attrs(bag);
+
+ switch (PKCS12_SAFEBAG_get_nid(bag)) {
+ case NID_keyBag:
+ if (options & INFO)
+ BIO_printf(bio_err, "Key bag\n");
+ if (options & NOKEYS)
+ return 1;
+ print_attribs(out, attrs, "Bag Attributes");
+ p8c = PKCS12_SAFEBAG_get0_p8inf(bag);
+ if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL)
+ return 0;
+ print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes");
+ ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
+ EVP_PKEY_free(pkey);
+ break;
+
+ case NID_pkcs8ShroudedKeyBag:
+ if (options & INFO) {
+ const X509_SIG *tp8;
+ const X509_ALGOR *tp8alg;
+
+ BIO_printf(bio_err, "Shrouded Keybag: ");
+ tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
+ X509_SIG_get0(tp8, &tp8alg, NULL);
+ alg_print(tp8alg);
+ }
+ if (options & NOKEYS)
+ return 1;
+ print_attribs(out, attrs, "Bag Attributes");
+ if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
+ return 0;
+ if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return 0;
+ }
+ print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
+ EVP_PKEY_free(pkey);
+ break;
+
+ case NID_certBag:
+ if (options & INFO)
+ BIO_printf(bio_err, "Certificate bag\n");
+ if (options & NOCERTS)
+ return 1;
+ if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
+ if (options & CACERTS)
+ return 1;
+ } else if (options & CLCERTS)
+ return 1;
+ print_attribs(out, attrs, "Bag Attributes");
+ if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
+ return 1;
+ if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
+ return 0;
+ dump_cert_text(out, x509);
+ ret = PEM_write_bio_X509(out, x509);
+ X509_free(x509);
+ break;
+
+ case NID_safeContentsBag:
+ if (options & INFO)
+ BIO_printf(bio_err, "Safe Contents bag\n");
+ print_attribs(out, attrs, "Bag Attributes");
+ return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
+ pass, passlen, options, pempass, enc);
+
+ default:
+ BIO_printf(bio_err, "Warning unsupported bag type: ");
+ i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
+ BIO_printf(bio_err, "\n");
+ return 1;
+ }
+ return ret;
+}
+
+/* Given a single certificate return a verified chain or NULL if error */
+
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain)
+{
+ X509_STORE_CTX *store_ctx = NULL;
+ STACK_OF(X509) *chn = NULL;
+ int i = 0;
+
+ store_ctx = X509_STORE_CTX_new();
+ if (store_ctx == NULL) {
+ i = X509_V_ERR_UNSPECIFIED;
+ goto end;
+ }
+ if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
+ i = X509_V_ERR_UNSPECIFIED;
+ goto end;
+ }
+
+
+ if (X509_verify_cert(store_ctx) > 0)
+ chn = X509_STORE_CTX_get1_chain(store_ctx);
+ else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
+ i = X509_V_ERR_UNSPECIFIED;
+
+end:
+ X509_STORE_CTX_free(store_ctx);
+ *chain = chn;
+ return i;
+}
+
+static int alg_print(const X509_ALGOR *alg)
+{
+ int pbenid, aparamtype;
+ const ASN1_OBJECT *aoid;
+ const void *aparam;
+ PBEPARAM *pbe = NULL;
+
+ X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
+
+ pbenid = OBJ_obj2nid(aoid);
+
+ BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid));
+
+ /*
+ * If PBE algorithm is PBES2 decode algorithm parameters
+ * for additional details.
+ */
+ if (pbenid == NID_pbes2) {
+ PBE2PARAM *pbe2 = NULL;
+ int encnid;
+ if (aparamtype == V_ASN1_SEQUENCE)
+ pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
+ if (pbe2 == NULL) {
+ BIO_puts(bio_err, ", <unsupported parameters>");
+ goto done;
+ }
+ X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
+ pbenid = OBJ_obj2nid(aoid);
+ X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
+ encnid = OBJ_obj2nid(aoid);
+ BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid),
+ OBJ_nid2sn(encnid));
+ /* If KDF is PBKDF2 decode parameters */
+ if (pbenid == NID_id_pbkdf2) {
+ PBKDF2PARAM *kdf = NULL;
+ int prfnid;
+ if (aparamtype == V_ASN1_SEQUENCE)
+ kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
+ if (kdf == NULL) {
+ BIO_puts(bio_err, ", <unsupported parameters>");
+ goto done;
+ }
+
+ if (kdf->prf == NULL) {
+ prfnid = NID_hmacWithSHA1;
+ } else {
+ X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
+ prfnid = OBJ_obj2nid(aoid);
+ }
+ BIO_printf(bio_err, ", Iteration %ld, PRF %s",
+ ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
+ PBKDF2PARAM_free(kdf);
+#ifndef OPENSSL_NO_SCRYPT
+ } else if (pbenid == NID_id_scrypt) {
+ SCRYPT_PARAMS *kdf = NULL;
+
+ if (aparamtype == V_ASN1_SEQUENCE)
+ kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
+ if (kdf == NULL) {
+ BIO_puts(bio_err, ", <unsupported parameters>");
+ goto done;
+ }
+ BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
+ "Block size(r): %ld, Paralelizm(p): %ld",
+ ASN1_STRING_length(kdf->salt),
+ ASN1_INTEGER_get(kdf->costParameter),
+ ASN1_INTEGER_get(kdf->blockSize),
+ ASN1_INTEGER_get(kdf->parallelizationParameter));
+ SCRYPT_PARAMS_free(kdf);
+#endif
+ }
+ PBE2PARAM_free(pbe2);
+ } else {
+ if (aparamtype == V_ASN1_SEQUENCE)
+ pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
+ if (pbe == NULL) {
+ BIO_puts(bio_err, ", <unsupported parameters>");
+ goto done;
+ }
+ BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
+ PBEPARAM_free(pbe);
+ }
+ done:
+ BIO_puts(bio_err, "\n");
+ return 1;
+}
+
+/* Load all certificates from a given file */
+
+int cert_load(BIO *in, STACK_OF(X509) *sk)
+{
+ int ret;
+ X509 *cert;
+ ret = 0;
+ while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
+ ret = 1;
+ sk_X509_push(sk, cert);
+ }
+ if (ret)
+ ERR_clear_error();
+ return ret;
+}
+
+/* Generalised attribute print: handle PKCS#8 and bag attributes */
+
+int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
+ const char *name)
+{
+ X509_ATTRIBUTE *attr;
+ ASN1_TYPE *av;
+ char *value;
+ int i, attr_nid;
+ if (!attrlst) {
+ BIO_printf(out, "%s: <No Attributes>\n", name);
+ return 1;
+ }
+ if (!sk_X509_ATTRIBUTE_num(attrlst)) {
+ BIO_printf(out, "%s: <Empty Attributes>\n", name);
+ return 1;
+ }
+ BIO_printf(out, "%s\n", name);
+ for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
+ ASN1_OBJECT *attr_obj;
+ attr = sk_X509_ATTRIBUTE_value(attrlst, i);
+ attr_obj = X509_ATTRIBUTE_get0_object(attr);
+ attr_nid = OBJ_obj2nid(attr_obj);
+ BIO_printf(out, " ");
+ if (attr_nid == NID_undef) {
+ i2a_ASN1_OBJECT(out, attr_obj);
+ BIO_printf(out, ": ");
+ } else {
+ BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
+ }
+
+ if (X509_ATTRIBUTE_count(attr)) {
+ av = X509_ATTRIBUTE_get0_type(attr, 0);
+ switch (av->type) {
+ case V_ASN1_BMPSTRING:
+ value = OPENSSL_uni2asc(av->value.bmpstring->data,
+ av->value.bmpstring->length);
+ BIO_printf(out, "%s\n", value);
+ OPENSSL_free(value);
+ break;
+
+ case V_ASN1_OCTET_STRING:
+ hex_prin(out, av->value.octet_string->data,
+ av->value.octet_string->length);
+ BIO_printf(out, "\n");
+ break;
+
+ case V_ASN1_BIT_STRING:
+ hex_prin(out, av->value.bit_string->data,
+ av->value.bit_string->length);
+ BIO_printf(out, "\n");
+ break;
+
+ default:
+ BIO_printf(out, "<Unsupported tag %d>\n", av->type);
+ break;
+ }
+ } else {
+ BIO_printf(out, "<No Values>\n");
+ }
+ }
+ return 1;
+}
+
+void hex_prin(BIO *out, unsigned char *buf, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ BIO_printf(out, "%02X ", buf[i]);
+}
+
+static int set_pbe(int *ppbe, const char *str)
+{
+ if (!str)
+ return 0;
+ if (strcmp(str, "NONE") == 0) {
+ *ppbe = -1;
+ return 1;
+ }
+ *ppbe = OBJ_txt2nid(str);
+ if (*ppbe == NID_undef) {
+ BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
+ return 0;
+ }
+ return 1;
+}
+
+#endif
diff --git a/freebsd/crypto/openssl/apps/pkcs7.c b/freebsd/crypto/openssl/apps/pkcs7.c
new file mode 100644
index 00000000..6e5c4739
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkcs7.c
@@ -0,0 +1,200 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pem.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT,
+ OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE
+} OPTION_CHOICE;
+
+const OPTIONS pkcs7_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"noout", OPT_NOOUT, '-', "Don't output encoded data"},
+ {"text", OPT_TEXT, '-', "Print full details of certificates"},
+ {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"},
+ {"print_certs", OPT_PRINT_CERTS, '-',
+ "Print_certs print any certs or crl in the input"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int pkcs7_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ PKCS7 *p7 = NULL;
+ BIO *in = NULL, *out = NULL;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM;
+ char *infile = NULL, *outfile = NULL, *prog;
+ int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, pkcs7_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkcs7_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_PRINT:
+ p7_print = 1;
+ break;
+ case OPT_PRINT_CERTS:
+ print_certs = 1;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (informat == FORMAT_ASN1)
+ p7 = d2i_PKCS7_bio(in, NULL);
+ else
+ p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "unable to load PKCS7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (p7_print)
+ PKCS7_print_ctx(out, p7, 0, NULL);
+
+ if (print_certs) {
+ STACK_OF(X509) *certs = NULL;
+ STACK_OF(X509_CRL) *crls = NULL;
+
+ i = OBJ_obj2nid(p7->type);
+ switch (i) {
+ case NID_pkcs7_signed:
+ if (p7->d.sign != NULL) {
+ certs = p7->d.sign->cert;
+ crls = p7->d.sign->crl;
+ }
+ break;
+ case NID_pkcs7_signedAndEnveloped:
+ if (p7->d.signed_and_enveloped != NULL) {
+ certs = p7->d.signed_and_enveloped->cert;
+ crls = p7->d.signed_and_enveloped->crl;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (certs != NULL) {
+ X509 *x;
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ x = sk_X509_value(certs, i);
+ if (text)
+ X509_print(out, x);
+ else
+ dump_cert_text(out, x);
+
+ if (!noout)
+ PEM_write_bio_X509(out, x);
+ BIO_puts(out, "\n");
+ }
+ }
+ if (crls != NULL) {
+ X509_CRL *crl;
+
+ for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+ crl = sk_X509_CRL_value(crls, i);
+
+ X509_CRL_print_ex(out, crl, get_nameopt());
+
+ if (!noout)
+ PEM_write_bio_X509_CRL(out, crl);
+ BIO_puts(out, "\n");
+ }
+ }
+
+ ret = 0;
+ goto end;
+ }
+
+ if (!noout) {
+ if (outformat == FORMAT_ASN1)
+ i = i2d_PKCS7_bio(out, p7);
+ else
+ i = PEM_write_bio_PKCS7(out, p7);
+
+ if (!i) {
+ BIO_printf(bio_err, "unable to write pkcs7 object\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ PKCS7_free(p7);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free_all(out);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/pkcs8.c b/freebsd/crypto/openssl/apps/pkcs8.c
new file mode 100644
index 00000000..97924228
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkcs8.c
@@ -0,0 +1,361 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pkcs12.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
+ OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT,
+#ifndef OPENSSL_NO_SCRYPT
+ OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P,
+#endif
+ OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
+ OPT_TRADITIONAL,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS pkcs8_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"},
+ {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
+ {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
+ {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
+ OPT_R_OPTIONS,
+ {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"},
+ {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"},
+ {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"},
+ {"iter", OPT_ITER, 'p', "Specify the iteration count"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+#ifndef OPENSSL_NO_SCRYPT
+ {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"},
+ {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"},
+ {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"},
+ {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"},
+#endif
+ {NULL}
+};
+
+int pkcs8_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+ PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+ X509_SIG *p8 = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ char *infile = NULL, *outfile = NULL;
+ char *passinarg = NULL, *passoutarg = NULL, *prog;
+#ifndef OPENSSL_NO_UI_CONSOLE
+ char pass[APP_PASS_LEN];
+#endif
+ char *passin = NULL, *passout = NULL, *p8pass = NULL;
+ OPTION_CHOICE o;
+ int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
+ int private = 0, traditional = 0;
+#ifndef OPENSSL_NO_SCRYPT
+ long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
+#endif
+
+ prog = opt_init(argc, argv, pkcs8_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkcs8_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_TOPK8:
+ topk8 = 1;
+ break;
+ case OPT_NOITER:
+ iter = 1;
+ break;
+ case OPT_NOCRYPT:
+ nocrypt = 1;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
+ break;
+ case OPT_V2:
+ if (!opt_cipher(opt_arg(), &cipher))
+ goto opthelp;
+ break;
+ case OPT_V1:
+ pbe_nid = OBJ_txt2nid(opt_arg());
+ if (pbe_nid == NID_undef) {
+ BIO_printf(bio_err,
+ "%s: Unknown PBE algorithm %s\n", prog, opt_arg());
+ goto opthelp;
+ }
+ break;
+ case OPT_V2PRF:
+ pbe_nid = OBJ_txt2nid(opt_arg());
+ if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) {
+ BIO_printf(bio_err,
+ "%s: Unknown PRF algorithm %s\n", prog, opt_arg());
+ goto opthelp;
+ }
+ if (cipher == NULL)
+ cipher = EVP_aes_256_cbc();
+ break;
+ case OPT_ITER:
+ if (!opt_int(opt_arg(), &iter))
+ goto opthelp;
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+#ifndef OPENSSL_NO_SCRYPT
+ case OPT_SCRYPT:
+ scrypt_N = 16384;
+ scrypt_r = 8;
+ scrypt_p = 1;
+ if (cipher == NULL)
+ cipher = EVP_aes_256_cbc();
+ break;
+ case OPT_SCRYPT_N:
+ if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0)
+ goto opthelp;
+ break;
+ case OPT_SCRYPT_R:
+ if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0)
+ goto opthelp;
+ break;
+ case OPT_SCRYPT_P:
+ if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0)
+ goto opthelp;
+ break;
+#endif
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = 1;
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if ((pbe_nid == -1) && cipher == NULL)
+ cipher = EVP_aes_256_cbc();
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (topk8) {
+ pkey = load_key(infile, informat, 1, passin, e, "key");
+ if (pkey == NULL)
+ goto end;
+ if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) {
+ BIO_printf(bio_err, "Error converting key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (nocrypt) {
+ assert(private);
+ if (outformat == FORMAT_PEM) {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ } else if (outformat == FORMAT_ASN1) {
+ i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+ } else {
+ X509_ALGOR *pbe;
+ if (cipher) {
+#ifndef OPENSSL_NO_SCRYPT
+ if (scrypt_N && scrypt_r && scrypt_p)
+ pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL,
+ scrypt_N, scrypt_r, scrypt_p);
+ else
+#endif
+ pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL,
+ pbe_nid);
+ } else {
+ pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0);
+ }
+ if (pbe == NULL) {
+ BIO_printf(bio_err, "Error setting PBE algorithm\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (passout != NULL) {
+ p8pass = passout;
+ } else if (1) {
+ /* To avoid bit rot */
+#ifndef OPENSSL_NO_UI_CONSOLE
+ p8pass = pass;
+ if (EVP_read_pw_string
+ (pass, sizeof(pass), "Enter Encryption Password:", 1)) {
+ X509_ALGOR_free(pbe);
+ goto end;
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "Password required\n");
+ goto end;
+ }
+ p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe);
+ if (p8 == NULL) {
+ X509_ALGOR_free(pbe);
+ BIO_printf(bio_err, "Error encrypting key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ assert(private);
+ if (outformat == FORMAT_PEM)
+ PEM_write_bio_PKCS8(out, p8);
+ else if (outformat == FORMAT_ASN1)
+ i2d_PKCS8_bio(out, p8);
+ else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+ }
+
+ ret = 0;
+ goto end;
+ }
+
+ if (nocrypt) {
+ if (informat == FORMAT_PEM) {
+ p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
+ } else if (informat == FORMAT_ASN1) {
+ p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+ } else {
+ if (informat == FORMAT_PEM) {
+ p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
+ } else if (informat == FORMAT_ASN1) {
+ p8 = d2i_PKCS8_bio(in, NULL);
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+
+ if (p8 == NULL) {
+ BIO_printf(bio_err, "Error reading key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (passin != NULL) {
+ p8pass = passin;
+ } else if (1) {
+#ifndef OPENSSL_NO_UI_CONSOLE
+ p8pass = pass;
+ if (EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0)) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ goto end;
+ }
+ } else {
+#endif
+ BIO_printf(bio_err, "Password required\n");
+ goto end;
+ }
+ p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
+ }
+
+ if (p8inf == NULL) {
+ BIO_printf(bio_err, "Error decrypting key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if ((pkey = EVP_PKCS82PKEY(p8inf)) == NULL) {
+ BIO_printf(bio_err, "Error converting key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ assert(private);
+ if (outformat == FORMAT_PEM) {
+ if (traditional)
+ PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0,
+ NULL, passout);
+ else
+ PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
+ } else if (outformat == FORMAT_ASN1) {
+ i2d_PrivateKey_bio(out, pkey);
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+ ret = 0;
+
+ end:
+ X509_SIG_free(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ EVP_PKEY_free(pkey);
+ release_engine(e);
+ BIO_free_all(out);
+ BIO_free(in);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/pkey.c b/freebsd/crypto/openssl/apps/pkey.c
new file mode 100644
index 00000000..d220fde5
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkey.c
@@ -0,0 +1,245 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE,
+ OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB,
+ OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK
+} OPTION_CHOICE;
+
+const OPTIONS pkey_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"},
+ {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"in", OPT_IN, 's', "Input key"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"pubin", OPT_PUBIN, '-',
+ "Read public key from input (default is private key)"},
+ {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
+ {"text_pub", OPT_TEXT_PUB, '-', "Only output public key components"},
+ {"text", OPT_TEXT, '-', "Output in plaintext as well"},
+ {"noout", OPT_NOOUT, '-', "Don't output the key"},
+ {"", OPT_MD, '-', "Any supported cipher"},
+ {"traditional", OPT_TRADITIONAL, '-',
+ "Use traditional format for private keys"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"check", OPT_CHECK, '-', "Check key consistency"},
+ {"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"},
+ {NULL}
+};
+
+int pkey_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL;
+ char *passinarg = NULL, *passoutarg = NULL, *prog;
+ OPTION_CHOICE o;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM;
+ int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1;
+ int private = 0, traditional = 0, check = 0, pub_check = 0;
+
+ prog = opt_init(argc, argv, pkey_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkey_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PUBIN:
+ pubin = pubout = pubtext = 1;
+ break;
+ case OPT_PUBOUT:
+ pubout = 1;
+ break;
+ case OPT_TEXT_PUB:
+ pubtext = text = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TRADITIONAL:
+ traditional = 1;
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ case OPT_PUB_CHECK:
+ pub_check = 1;
+ break;
+ case OPT_MD:
+ if (!opt_cipher(opt_unknown(), &cipher))
+ goto opthelp;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = !noout && !pubout ? 1 : 0;
+ if (text && !pubtext)
+ private = 1;
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (pubin)
+ pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key");
+ else
+ pkey = load_key(infile, informat, 1, passin, e, "key");
+ if (pkey == NULL)
+ goto end;
+
+ if (check || pub_check) {
+ int r;
+ EVP_PKEY_CTX *ctx;
+
+ ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (ctx == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (check)
+ r = EVP_PKEY_check(ctx);
+ else
+ r = EVP_PKEY_public_check(ctx);
+
+ if (r == 1) {
+ BIO_printf(out, "Key is valid\n");
+ } else {
+ /*
+ * Note: at least for RSA keys if this function returns
+ * -1, there will be no error reasons.
+ */
+ unsigned long err;
+
+ BIO_printf(out, "Key is invalid\n");
+
+ while ((err = ERR_peek_error()) != 0) {
+ BIO_printf(out, "Detailed error: %s\n",
+ ERR_reason_error_string(err));
+ ERR_get_error(); /* remove err from error stack */
+ }
+ }
+ EVP_PKEY_CTX_free(ctx);
+ }
+
+ if (!noout) {
+ if (outformat == FORMAT_PEM) {
+ if (pubout) {
+ if (!PEM_write_bio_PUBKEY(out, pkey))
+ goto end;
+ } else {
+ assert(private);
+ if (traditional) {
+ if (!PEM_write_bio_PrivateKey_traditional(out, pkey, cipher,
+ NULL, 0, NULL,
+ passout))
+ goto end;
+ } else {
+ if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
+ NULL, 0, NULL, passout))
+ goto end;
+ }
+ }
+ } else if (outformat == FORMAT_ASN1) {
+ if (pubout) {
+ if (!i2d_PUBKEY_bio(out, pkey))
+ goto end;
+ } else {
+ assert(private);
+ if (!i2d_PrivateKey_bio(out, pkey))
+ goto end;
+ }
+ } else {
+ BIO_printf(bio_err, "Bad format specified for key\n");
+ goto end;
+ }
+ }
+
+ if (text) {
+ if (pubtext) {
+ if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0)
+ goto end;
+ } else {
+ assert(private);
+ if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)
+ goto end;
+ }
+ }
+
+ ret = 0;
+
+ end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ EVP_PKEY_free(pkey);
+ release_engine(e);
+ BIO_free_all(out);
+ BIO_free(in);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/pkeyparam.c b/freebsd/crypto/openssl/apps/pkeyparam.c
new file mode 100644
index 00000000..b58b445c
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkeyparam.c
@@ -0,0 +1,144 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
+ OPT_ENGINE, OPT_CHECK
+} OPTION_CHOICE;
+
+const OPTIONS pkeyparam_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"text", OPT_TEXT, '-', "Print parameters as text"},
+ {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"check", OPT_CHECK, '-', "Check key param consistency"},
+ {NULL}
+};
+
+int pkeyparam_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ BIO *in = NULL, *out = NULL;
+ EVP_PKEY *pkey = NULL;
+ int text = 0, noout = 0, ret = 1, check = 0;
+ OPTION_CHOICE o;
+ char *infile = NULL, *outfile = NULL, *prog;
+
+ prog = opt_init(argc, argv, pkeyparam_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkeyparam_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ in = bio_open_default(infile, 'r', FORMAT_PEM);
+ if (in == NULL)
+ goto end;
+ out = bio_open_default(outfile, 'w', FORMAT_PEM);
+ if (out == NULL)
+ goto end;
+ pkey = PEM_read_bio_Parameters(in, NULL);
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "Error reading parameters\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (check) {
+ int r;
+ EVP_PKEY_CTX *ctx;
+
+ ctx = EVP_PKEY_CTX_new(pkey, e);
+ if (ctx == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ r = EVP_PKEY_param_check(ctx);
+
+ if (r == 1) {
+ BIO_printf(out, "Parameters are valid\n");
+ } else {
+ /*
+ * Note: at least for RSA keys if this function returns
+ * -1, there will be no error reasons.
+ */
+ unsigned long err;
+
+ BIO_printf(out, "Parameters are invalid\n");
+
+ while ((err = ERR_peek_error()) != 0) {
+ BIO_printf(out, "Detailed error: %s\n",
+ ERR_reason_error_string(err));
+ ERR_get_error(); /* remove err from error stack */
+ }
+ }
+ EVP_PKEY_CTX_free(ctx);
+ }
+
+ if (!noout)
+ PEM_write_bio_Parameters(out, pkey);
+
+ if (text)
+ EVP_PKEY_print_params(out, pkey, 0, NULL);
+
+ ret = 0;
+
+ end:
+ EVP_PKEY_free(pkey);
+ release_engine(e);
+ BIO_free_all(out);
+ BIO_free(in);
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/pkeyutl.c b/freebsd/crypto/openssl/apps/pkeyutl.c
new file mode 100644
index 00000000..ff88c782
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/pkeyutl.c
@@ -0,0 +1,527 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "progs.h"
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+
+#define KEY_NONE 0
+#define KEY_PRIVKEY 1
+#define KEY_PUBKEY 2
+#define KEY_CERT 3
+
+static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
+ const char *keyfile, int keyform, int key_type,
+ char *passinarg, int pkey_op, ENGINE *e,
+ const int impl);
+
+static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
+ ENGINE *e);
+
+static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
+ unsigned char *out, size_t *poutlen,
+ const unsigned char *in, size_t inlen);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
+ OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
+ OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
+ OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
+ OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS pkeyutl_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file - default stdin"},
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"pubin", OPT_PUBIN, '-', "Input is a public key"},
+ {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
+ {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"},
+ {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
+ {"sign", OPT_SIGN, '-', "Sign input data with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"verifyrecover", OPT_VERIFYRECOVER, '-',
+ "Verify with public key, recover original data"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
+ {"derive", OPT_DERIVE, '-', "Derive shared secret"},
+ {"kdf", OPT_KDF, 's', "Use KDF algorithm"},
+ {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
+ {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
+ {"inkey", OPT_INKEY, 's', "Input private key file"},
+ {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ OPT_R_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"engine_impl", OPT_ENGINE_IMPL, '-',
+ "Also use engine given by -engine for crypto operations"},
+#endif
+ {NULL}
+};
+
+int pkeyutl_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
+ char hexdump = 0, asn1parse = 0, rev = 0, *prog;
+ unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
+ OPTION_CHOICE o;
+ int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM;
+ int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
+ int engine_impl = 0;
+ int ret = 1, rv = -1;
+ size_t buf_outlen;
+ const char *inkey = NULL;
+ const char *peerkey = NULL;
+ const char *kdfalg = NULL;
+ int kdflen = 0;
+ STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
+
+ prog = opt_init(argc, argv, pkeyutl_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(pkeyutl_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_SIGFILE:
+ sigfile = opt_arg();
+ break;
+ case OPT_ENGINE_IMPL:
+ engine_impl = 1;
+ break;
+ case OPT_INKEY:
+ inkey = opt_arg();
+ break;
+ case OPT_PEERKEY:
+ peerkey = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PEERFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform))
+ goto opthelp;
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
+ goto opthelp;
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PUBIN:
+ key_type = KEY_PUBKEY;
+ break;
+ case OPT_CERTIN:
+ key_type = KEY_CERT;
+ break;
+ case OPT_ASN1PARSE:
+ asn1parse = 1;
+ break;
+ case OPT_HEXDUMP:
+ hexdump = 1;
+ break;
+ case OPT_SIGN:
+ pkey_op = EVP_PKEY_OP_SIGN;
+ break;
+ case OPT_VERIFY:
+ pkey_op = EVP_PKEY_OP_VERIFY;
+ break;
+ case OPT_VERIFYRECOVER:
+ pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
+ break;
+ case OPT_ENCRYPT:
+ pkey_op = EVP_PKEY_OP_ENCRYPT;
+ break;
+ case OPT_DECRYPT:
+ pkey_op = EVP_PKEY_OP_DECRYPT;
+ break;
+ case OPT_DERIVE:
+ pkey_op = EVP_PKEY_OP_DERIVE;
+ break;
+ case OPT_KDF:
+ pkey_op = EVP_PKEY_OP_DERIVE;
+ key_type = KEY_NONE;
+ kdfalg = opt_arg();
+ break;
+ case OPT_KDFLEN:
+ kdflen = atoi(opt_arg());
+ break;
+ case OPT_REV:
+ rev = 1;
+ break;
+ case OPT_PKEYOPT:
+ if ((pkeyopts == NULL &&
+ (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
+ sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
+ BIO_puts(bio_err, "out of memory\n");
+ goto end;
+ }
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (kdfalg != NULL) {
+ if (kdflen == 0) {
+ BIO_printf(bio_err,
+ "%s: no KDF length given (-kdflen parameter).\n", prog);
+ goto opthelp;
+ }
+ } else if (inkey == NULL) {
+ BIO_printf(bio_err,
+ "%s: no private key given (-inkey parameter).\n", prog);
+ goto opthelp;
+ } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
+ BIO_printf(bio_err,
+ "%s: no peer key given (-peerkey parameter).\n", prog);
+ goto opthelp;
+ }
+ ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
+ passinarg, pkey_op, e, engine_impl);
+ if (ctx == NULL) {
+ BIO_printf(bio_err, "%s: Error initializing context\n", prog);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
+ BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (pkeyopts != NULL) {
+ int num = sk_OPENSSL_STRING_num(pkeyopts);
+ int i;
+
+ for (i = 0; i < num; ++i) {
+ const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
+
+ if (pkey_ctrl_string(ctx, opt) <= 0) {
+ BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
+ prog, opt);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+
+ if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
+ BIO_printf(bio_err,
+ "%s: Signature file specified for non verify\n", prog);
+ goto end;
+ }
+
+ if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
+ BIO_printf(bio_err,
+ "%s: No signature file specified for verify\n", prog);
+ goto end;
+ }
+
+ if (pkey_op != EVP_PKEY_OP_DERIVE) {
+ in = bio_open_default(infile, 'r', FORMAT_BINARY);
+ if (in == NULL)
+ goto end;
+ }
+ out = bio_open_default(outfile, 'w', FORMAT_BINARY);
+ if (out == NULL)
+ goto end;
+
+ if (sigfile != NULL) {
+ BIO *sigbio = BIO_new_file(sigfile, "rb");
+
+ if (sigbio == NULL) {
+ BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
+ goto end;
+ }
+ siglen = bio_to_mem(&sig, keysize * 10, sigbio);
+ BIO_free(sigbio);
+ if (siglen < 0) {
+ BIO_printf(bio_err, "Error reading signature data\n");
+ goto end;
+ }
+ }
+
+ if (in != NULL) {
+ /* Read the input data */
+ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
+ if (buf_inlen < 0) {
+ BIO_printf(bio_err, "Error reading input Data\n");
+ goto end;
+ }
+ if (rev) {
+ size_t i;
+ unsigned char ctmp;
+ size_t l = (size_t)buf_inlen;
+ for (i = 0; i < l / 2; i++) {
+ ctmp = buf_in[i];
+ buf_in[i] = buf_in[l - 1 - i];
+ buf_in[l - 1 - i] = ctmp;
+ }
+ }
+ }
+
+ /* Sanity check the input */
+ if (buf_inlen > EVP_MAX_MD_SIZE
+ && (pkey_op == EVP_PKEY_OP_SIGN
+ || pkey_op == EVP_PKEY_OP_VERIFY
+ || pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) {
+ BIO_printf(bio_err,
+ "Error: The input data looks too long to be a hash\n");
+ goto end;
+ }
+
+ if (pkey_op == EVP_PKEY_OP_VERIFY) {
+ rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
+ buf_in, (size_t)buf_inlen);
+ if (rv == 1) {
+ BIO_puts(out, "Signature Verified Successfully\n");
+ ret = 0;
+ } else {
+ BIO_puts(out, "Signature Verification Failure\n");
+ }
+ goto end;
+ }
+ if (kdflen != 0) {
+ buf_outlen = kdflen;
+ rv = 1;
+ } else {
+ rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
+ buf_in, (size_t)buf_inlen);
+ }
+ if (rv > 0 && buf_outlen != 0) {
+ buf_out = app_malloc(buf_outlen, "buffer output");
+ rv = do_keyop(ctx, pkey_op,
+ buf_out, (size_t *)&buf_outlen,
+ buf_in, (size_t)buf_inlen);
+ }
+ if (rv <= 0) {
+ if (pkey_op != EVP_PKEY_OP_DERIVE) {
+ BIO_puts(bio_err, "Public Key operation error\n");
+ } else {
+ BIO_puts(bio_err, "Key derivation failed\n");
+ }
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+
+ if (asn1parse) {
+ if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
+ ERR_print_errors(bio_err);
+ } else if (hexdump) {
+ BIO_dump(out, (char *)buf_out, buf_outlen);
+ } else {
+ BIO_write(out, buf_out, buf_outlen);
+ }
+
+ end:
+ EVP_PKEY_CTX_free(ctx);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free_all(out);
+ OPENSSL_free(buf_in);
+ OPENSSL_free(buf_out);
+ OPENSSL_free(sig);
+ sk_OPENSSL_STRING_free(pkeyopts);
+ return ret;
+}
+
+static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
+ const char *keyfile, int keyform, int key_type,
+ char *passinarg, int pkey_op, ENGINE *e,
+ const int engine_impl)
+{
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ ENGINE *impl = NULL;
+ char *passin = NULL;
+ int rv = -1;
+ X509 *x;
+ if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
+ || (pkey_op == EVP_PKEY_OP_DERIVE))
+ && (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
+ BIO_printf(bio_err, "A private key is needed for this operation\n");
+ goto end;
+ }
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+ switch (key_type) {
+ case KEY_PRIVKEY:
+ pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
+ break;
+
+ case KEY_PUBKEY:
+ pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key");
+ break;
+
+ case KEY_CERT:
+ x = load_cert(keyfile, keyform, "Certificate");
+ if (x) {
+ pkey = X509_get_pubkey(x);
+ X509_free(x);
+ }
+ break;
+
+ case KEY_NONE:
+ break;
+
+ }
+
+#ifndef OPENSSL_NO_ENGINE
+ if (engine_impl)
+ impl = e;
+#endif
+
+ if (kdfalg != NULL) {
+ int kdfnid = OBJ_sn2nid(kdfalg);
+
+ if (kdfnid == NID_undef) {
+ kdfnid = OBJ_ln2nid(kdfalg);
+ if (kdfnid == NID_undef) {
+ BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n",
+ kdfalg);
+ goto end;
+ }
+ }
+ ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
+ } else {
+ if (pkey == NULL)
+ goto end;
+ *pkeysize = EVP_PKEY_size(pkey);
+ ctx = EVP_PKEY_CTX_new(pkey, impl);
+ EVP_PKEY_free(pkey);
+ }
+
+ if (ctx == NULL)
+ goto end;
+
+ switch (pkey_op) {
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_PKEY_sign_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_VERIFY:
+ rv = EVP_PKEY_verify_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ rv = EVP_PKEY_verify_recover_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_ENCRYPT:
+ rv = EVP_PKEY_encrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DECRYPT:
+ rv = EVP_PKEY_decrypt_init(ctx);
+ break;
+
+ case EVP_PKEY_OP_DERIVE:
+ rv = EVP_PKEY_derive_init(ctx);
+ break;
+ }
+
+ if (rv <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ }
+
+ end:
+ OPENSSL_free(passin);
+ return ctx;
+
+}
+
+static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
+ ENGINE *e)
+{
+ EVP_PKEY *peer = NULL;
+ ENGINE *engine = NULL;
+ int ret;
+
+ if (peerform == FORMAT_ENGINE)
+ engine = e;
+ peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key");
+ if (peer == NULL) {
+ BIO_printf(bio_err, "Error reading peer key %s\n", file);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ ret = EVP_PKEY_derive_set_peer(ctx, peer);
+
+ EVP_PKEY_free(peer);
+ if (ret <= 0)
+ ERR_print_errors(bio_err);
+ return ret;
+}
+
+static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
+ unsigned char *out, size_t *poutlen,
+ const unsigned char *in, size_t inlen)
+{
+ int rv = 0;
+ switch (pkey_op) {
+ case EVP_PKEY_OP_VERIFYRECOVER:
+ rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
+ break;
+
+ case EVP_PKEY_OP_SIGN:
+ rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
+ break;
+
+ case EVP_PKEY_OP_ENCRYPT:
+ rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
+ break;
+
+ case EVP_PKEY_OP_DECRYPT:
+ rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
+ break;
+
+ case EVP_PKEY_OP_DERIVE:
+ rv = EVP_PKEY_derive(ctx, out, poutlen);
+ break;
+
+ }
+ return rv;
+}
diff --git a/freebsd/crypto/openssl/apps/prime.c b/freebsd/crypto/openssl/apps/prime.c
new file mode 100644
index 00000000..c13bc3e2
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/prime.c
@@ -0,0 +1,135 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bn.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS
+} OPTION_CHOICE;
+
+const OPTIONS prime_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"},
+ {OPT_HELP_STR, 1, '-',
+ " number Number to check for primality\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"hex", OPT_HEX, '-', "Hex output"},
+ {"generate", OPT_GENERATE, '-', "Generate a prime"},
+ {"bits", OPT_BITS, 'p', "Size of number in bits"},
+ {"safe", OPT_SAFE, '-',
+ "When used with -generate, generate a safe prime"},
+ {"checks", OPT_CHECKS, 'p', "Number of checks"},
+ {NULL}
+};
+
+int prime_main(int argc, char **argv)
+{
+ BIGNUM *bn = NULL;
+ int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1;
+ char *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, prime_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(prime_options);
+ ret = 0;
+ goto end;
+ case OPT_HEX:
+ hex = 1;
+ break;
+ case OPT_GENERATE:
+ generate = 1;
+ break;
+ case OPT_BITS:
+ bits = atoi(opt_arg());
+ break;
+ case OPT_SAFE:
+ safe = 1;
+ break;
+ case OPT_CHECKS:
+ checks = atoi(opt_arg());
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (generate) {
+ if (argc != 0) {
+ BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ }
+ } else if (argc == 0) {
+ BIO_printf(bio_err, "%s: No prime specified\n", prog);
+ goto opthelp;
+ }
+
+ if (generate) {
+ char *s;
+
+ if (!bits) {
+ BIO_printf(bio_err, "Specify the number of bits.\n");
+ goto end;
+ }
+ bn = BN_new();
+ if (bn == NULL) {
+ BIO_printf(bio_err, "Out of memory.\n");
+ goto end;
+ }
+ if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) {
+ BIO_printf(bio_err, "Failed to generate prime.\n");
+ goto end;
+ }
+ s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn);
+ if (s == NULL) {
+ BIO_printf(bio_err, "Out of memory.\n");
+ goto end;
+ }
+ BIO_printf(bio_out, "%s\n", s);
+ OPENSSL_free(s);
+ } else {
+ for ( ; *argv; argv++) {
+ int r;
+
+ if (hex)
+ r = BN_hex2bn(&bn, argv[0]);
+ else
+ r = BN_dec2bn(&bn, argv[0]);
+
+ if (!r) {
+ BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]);
+ goto end;
+ }
+
+ BN_print(bio_out, bn);
+ BIO_printf(bio_out, " (%s) %s prime\n",
+ argv[0],
+ BN_is_prime_ex(bn, checks, NULL, NULL)
+ ? "is" : "is not");
+ }
+ }
+
+ ret = 0;
+ end:
+ BN_free(bn);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/progs.h b/freebsd/crypto/openssl/apps/progs.h
new file mode 100644
index 00000000..0733d273
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/progs.h
@@ -0,0 +1,508 @@
+/* $FreeBSD$ */
+/*
+ * WARNING: do not edit!
+ * Generated by apps/progs.pl
+ *
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+typedef enum FUNC_TYPE {
+ FT_none, FT_general, FT_md, FT_cipher, FT_pkey,
+ FT_md_alg, FT_cipher_alg
+} FUNC_TYPE;
+
+typedef struct function_st {
+ FUNC_TYPE type;
+ const char *name;
+ int (*func)(int argc, char *argv[]);
+ const OPTIONS *help;
+} FUNCTION;
+
+DEFINE_LHASH_OF(FUNCTION);
+
+extern int asn1parse_main(int argc, char *argv[]);
+extern int ca_main(int argc, char *argv[]);
+extern int ciphers_main(int argc, char *argv[]);
+extern int cms_main(int argc, char *argv[]);
+extern int crl_main(int argc, char *argv[]);
+extern int crl2pkcs7_main(int argc, char *argv[]);
+extern int dgst_main(int argc, char *argv[]);
+extern int dhparam_main(int argc, char *argv[]);
+extern int dsa_main(int argc, char *argv[]);
+extern int dsaparam_main(int argc, char *argv[]);
+extern int ec_main(int argc, char *argv[]);
+extern int ecparam_main(int argc, char *argv[]);
+extern int enc_main(int argc, char *argv[]);
+extern int engine_main(int argc, char *argv[]);
+extern int errstr_main(int argc, char *argv[]);
+extern int gendsa_main(int argc, char *argv[]);
+extern int genpkey_main(int argc, char *argv[]);
+extern int genrsa_main(int argc, char *argv[]);
+extern int help_main(int argc, char *argv[]);
+extern int list_main(int argc, char *argv[]);
+extern int nseq_main(int argc, char *argv[]);
+extern int ocsp_main(int argc, char *argv[]);
+extern int passwd_main(int argc, char *argv[]);
+extern int pkcs12_main(int argc, char *argv[]);
+extern int pkcs7_main(int argc, char *argv[]);
+extern int pkcs8_main(int argc, char *argv[]);
+extern int pkey_main(int argc, char *argv[]);
+extern int pkeyparam_main(int argc, char *argv[]);
+extern int pkeyutl_main(int argc, char *argv[]);
+extern int prime_main(int argc, char *argv[]);
+extern int rand_main(int argc, char *argv[]);
+extern int rehash_main(int argc, char *argv[]);
+extern int req_main(int argc, char *argv[]);
+extern int rsa_main(int argc, char *argv[]);
+extern int rsautl_main(int argc, char *argv[]);
+extern int s_client_main(int argc, char *argv[]);
+extern int s_server_main(int argc, char *argv[]);
+extern int s_time_main(int argc, char *argv[]);
+extern int sess_id_main(int argc, char *argv[]);
+extern int smime_main(int argc, char *argv[]);
+extern int speed_main(int argc, char *argv[]);
+extern int spkac_main(int argc, char *argv[]);
+extern int srp_main(int argc, char *argv[]);
+extern int storeutl_main(int argc, char *argv[]);
+extern int ts_main(int argc, char *argv[]);
+extern int verify_main(int argc, char *argv[]);
+extern int version_main(int argc, char *argv[]);
+extern int x509_main(int argc, char *argv[]);
+
+extern const OPTIONS asn1parse_options[];
+extern const OPTIONS ca_options[];
+extern const OPTIONS ciphers_options[];
+extern const OPTIONS cms_options[];
+extern const OPTIONS crl_options[];
+extern const OPTIONS crl2pkcs7_options[];
+extern const OPTIONS dgst_options[];
+extern const OPTIONS dhparam_options[];
+extern const OPTIONS dsa_options[];
+extern const OPTIONS dsaparam_options[];
+extern const OPTIONS ec_options[];
+extern const OPTIONS ecparam_options[];
+extern const OPTIONS enc_options[];
+extern const OPTIONS engine_options[];
+extern const OPTIONS errstr_options[];
+extern const OPTIONS gendsa_options[];
+extern const OPTIONS genpkey_options[];
+extern const OPTIONS genrsa_options[];
+extern const OPTIONS help_options[];
+extern const OPTIONS list_options[];
+extern const OPTIONS nseq_options[];
+extern const OPTIONS ocsp_options[];
+extern const OPTIONS passwd_options[];
+extern const OPTIONS pkcs12_options[];
+extern const OPTIONS pkcs7_options[];
+extern const OPTIONS pkcs8_options[];
+extern const OPTIONS pkey_options[];
+extern const OPTIONS pkeyparam_options[];
+extern const OPTIONS pkeyutl_options[];
+extern const OPTIONS prime_options[];
+extern const OPTIONS rand_options[];
+extern const OPTIONS rehash_options[];
+extern const OPTIONS req_options[];
+extern const OPTIONS rsa_options[];
+extern const OPTIONS rsautl_options[];
+extern const OPTIONS s_client_options[];
+extern const OPTIONS s_server_options[];
+extern const OPTIONS s_time_options[];
+extern const OPTIONS sess_id_options[];
+extern const OPTIONS smime_options[];
+extern const OPTIONS speed_options[];
+extern const OPTIONS spkac_options[];
+extern const OPTIONS srp_options[];
+extern const OPTIONS storeutl_options[];
+extern const OPTIONS ts_options[];
+extern const OPTIONS verify_options[];
+extern const OPTIONS version_options[];
+extern const OPTIONS x509_options[];
+
+#ifdef INCLUDE_FUNCTION_TABLE
+static FUNCTION functions[] = {
+ {FT_general, "asn1parse", asn1parse_main, asn1parse_options},
+ {FT_general, "ca", ca_main, ca_options},
+#ifndef OPENSSL_NO_SOCK
+ {FT_general, "ciphers", ciphers_main, ciphers_options},
+#endif
+#ifndef OPENSSL_NO_CMS
+ {FT_general, "cms", cms_main, cms_options},
+#endif
+ {FT_general, "crl", crl_main, crl_options},
+ {FT_general, "crl2pkcs7", crl2pkcs7_main, crl2pkcs7_options},
+ {FT_general, "dgst", dgst_main, dgst_options},
+#ifndef OPENSSL_NO_DH
+ {FT_general, "dhparam", dhparam_main, dhparam_options},
+#endif
+#ifndef OPENSSL_NO_DSA
+ {FT_general, "dsa", dsa_main, dsa_options},
+#endif
+#ifndef OPENSSL_NO_DSA
+ {FT_general, "dsaparam", dsaparam_main, dsaparam_options},
+#endif
+#ifndef OPENSSL_NO_EC
+ {FT_general, "ec", ec_main, ec_options},
+#endif
+#ifndef OPENSSL_NO_EC
+ {FT_general, "ecparam", ecparam_main, ecparam_options},
+#endif
+ {FT_general, "enc", enc_main, enc_options},
+#ifndef OPENSSL_NO_ENGINE
+ {FT_general, "engine", engine_main, engine_options},
+#endif
+ {FT_general, "errstr", errstr_main, errstr_options},
+#ifndef OPENSSL_NO_DSA
+ {FT_general, "gendsa", gendsa_main, gendsa_options},
+#endif
+ {FT_general, "genpkey", genpkey_main, genpkey_options},
+#ifndef OPENSSL_NO_RSA
+ {FT_general, "genrsa", genrsa_main, genrsa_options},
+#endif
+ {FT_general, "help", help_main, help_options},
+ {FT_general, "list", list_main, list_options},
+ {FT_general, "nseq", nseq_main, nseq_options},
+#ifndef OPENSSL_NO_OCSP
+ {FT_general, "ocsp", ocsp_main, ocsp_options},
+#endif
+ {FT_general, "passwd", passwd_main, passwd_options},
+#ifndef OPENSSL_NO_DES
+ {FT_general, "pkcs12", pkcs12_main, pkcs12_options},
+#endif
+ {FT_general, "pkcs7", pkcs7_main, pkcs7_options},
+ {FT_general, "pkcs8", pkcs8_main, pkcs8_options},
+ {FT_general, "pkey", pkey_main, pkey_options},
+ {FT_general, "pkeyparam", pkeyparam_main, pkeyparam_options},
+ {FT_general, "pkeyutl", pkeyutl_main, pkeyutl_options},
+ {FT_general, "prime", prime_main, prime_options},
+ {FT_general, "rand", rand_main, rand_options},
+ {FT_general, "rehash", rehash_main, rehash_options},
+ {FT_general, "req", req_main, req_options},
+ {FT_general, "rsa", rsa_main, rsa_options},
+#ifndef OPENSSL_NO_RSA
+ {FT_general, "rsautl", rsautl_main, rsautl_options},
+#endif
+#ifndef OPENSSL_NO_SOCK
+ {FT_general, "s_client", s_client_main, s_client_options},
+#endif
+#ifndef OPENSSL_NO_SOCK
+ {FT_general, "s_server", s_server_main, s_server_options},
+#endif
+#ifndef OPENSSL_NO_SOCK
+ {FT_general, "s_time", s_time_main, s_time_options},
+#endif
+ {FT_general, "sess_id", sess_id_main, sess_id_options},
+ {FT_general, "smime", smime_main, smime_options},
+ {FT_general, "speed", speed_main, speed_options},
+ {FT_general, "spkac", spkac_main, spkac_options},
+#ifndef OPENSSL_NO_SRP
+ {FT_general, "srp", srp_main, srp_options},
+#endif
+ {FT_general, "storeutl", storeutl_main, storeutl_options},
+#ifndef OPENSSL_NO_TS
+ {FT_general, "ts", ts_main, ts_options},
+#endif
+ {FT_general, "verify", verify_main, verify_options},
+ {FT_general, "version", version_main, version_options},
+ {FT_general, "x509", x509_main, x509_options},
+#ifndef OPENSSL_NO_MD2
+ {FT_md, "md2", dgst_main},
+#endif
+#ifndef OPENSSL_NO_MD4
+ {FT_md, "md4", dgst_main},
+#endif
+ {FT_md, "md5", dgst_main},
+#ifndef OPENSSL_NO_GOST
+ {FT_md, "gost", dgst_main},
+#endif
+ {FT_md, "sha1", dgst_main},
+ {FT_md, "sha224", dgst_main},
+ {FT_md, "sha256", dgst_main},
+ {FT_md, "sha384", dgst_main},
+ {FT_md, "sha512", dgst_main},
+ {FT_md, "sha512-224", dgst_main},
+ {FT_md, "sha512-256", dgst_main},
+ {FT_md, "sha3-224", dgst_main},
+ {FT_md, "sha3-256", dgst_main},
+ {FT_md, "sha3-384", dgst_main},
+ {FT_md, "sha3-512", dgst_main},
+ {FT_md, "shake128", dgst_main},
+ {FT_md, "shake256", dgst_main},
+#ifndef OPENSSL_NO_MDC2
+ {FT_md, "mdc2", dgst_main},
+#endif
+#ifndef OPENSSL_NO_RMD160
+ {FT_md, "rmd160", dgst_main},
+#endif
+#ifndef OPENSSL_NO_BLAKE2
+ {FT_md, "blake2b512", dgst_main},
+#endif
+#ifndef OPENSSL_NO_BLAKE2
+ {FT_md, "blake2s256", dgst_main},
+#endif
+#ifndef OPENSSL_NO_SM3
+ {FT_md, "sm3", dgst_main},
+#endif
+ {FT_cipher, "aes-128-cbc", enc_main, enc_options},
+ {FT_cipher, "aes-128-ecb", enc_main, enc_options},
+ {FT_cipher, "aes-192-cbc", enc_main, enc_options},
+ {FT_cipher, "aes-192-ecb", enc_main, enc_options},
+ {FT_cipher, "aes-256-cbc", enc_main, enc_options},
+ {FT_cipher, "aes-256-ecb", enc_main, enc_options},
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-ctr", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-cfb1", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-128-cfb8", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-ctr", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-cfb1", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-192-cfb8", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-ctr", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-cfb1", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_ARIA
+ {FT_cipher, "aria-256-cfb8", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-128-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-128-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-192-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-192-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-256-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+ {FT_cipher, "camellia-256-ecb", enc_main, enc_options},
+#endif
+ {FT_cipher, "base64", enc_main, enc_options},
+#ifdef ZLIB
+ {FT_cipher, "zlib", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des3", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "desx", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {FT_cipher, "idea", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {FT_cipher, "seed", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC4
+ {FT_cipher, "rc4", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC4
+ {FT_cipher, "rc4-40", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_BF
+ {FT_cipher, "bf", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {FT_cipher, "rc5", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede3", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede3-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede3-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_DES
+ {FT_cipher, "des-ede3-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {FT_cipher, "idea-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {FT_cipher, "idea-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {FT_cipher, "idea-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {FT_cipher, "idea-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {FT_cipher, "seed-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {FT_cipher, "seed-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {FT_cipher, "seed-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {FT_cipher, "seed-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-64-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC2
+ {FT_cipher, "rc2-40-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_BF
+ {FT_cipher, "bf-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_BF
+ {FT_cipher, "bf-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_BF
+ {FT_cipher, "bf-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_BF
+ {FT_cipher, "bf-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast5-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast5-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast5-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast5-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {FT_cipher, "cast-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {FT_cipher, "rc5-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {FT_cipher, "rc5-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {FT_cipher, "rc5-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {FT_cipher, "rc5-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SM4
+ {FT_cipher, "sm4-cbc", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SM4
+ {FT_cipher, "sm4-ecb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SM4
+ {FT_cipher, "sm4-cfb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SM4
+ {FT_cipher, "sm4-ofb", enc_main, enc_options},
+#endif
+#ifndef OPENSSL_NO_SM4
+ {FT_cipher, "sm4-ctr", enc_main, enc_options},
+#endif
+ {0, NULL, NULL}
+};
+#endif
diff --git a/freebsd/crypto/openssl/apps/rand.c b/freebsd/crypto/openssl/apps/rand.c
new file mode 100644
index 00000000..af38f69d
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/rand.c
@@ -0,0 +1,135 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "progs.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS rand_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"out", OPT_OUT, '>', "Output file"},
+ OPT_R_OPTIONS,
+ {"base64", OPT_BASE64, '-', "Base64 encode output"},
+ {"hex", OPT_HEX, '-', "Hex encode output"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int rand_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ BIO *out = NULL;
+ char *outfile = NULL, *prog;
+ OPTION_CHOICE o;
+ int format = FORMAT_BINARY, i, num = -1, r, ret = 1;
+
+ prog = opt_init(argc, argv, rand_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(rand_options);
+ ret = 0;
+ goto end;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_BASE64:
+ format = FORMAT_BASE64;
+ break;
+ case OPT_HEX:
+ format = FORMAT_TEXT;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc == 1) {
+ if (!opt_int(argv[0], &num) || num <= 0)
+ goto end;
+ } else if (argc > 0) {
+ BIO_printf(bio_err, "Extra arguments given.\n");
+ goto opthelp;
+ }
+
+ out = bio_open_default(outfile, 'w', format);
+ if (out == NULL)
+ goto end;
+
+ if (format == FORMAT_BASE64) {
+ BIO *b64 = BIO_new(BIO_f_base64());
+ if (b64 == NULL)
+ goto end;
+ out = BIO_push(b64, out);
+ }
+
+ while (num > 0) {
+ unsigned char buf[4096];
+ int chunk;
+
+ chunk = num;
+ if (chunk > (int)sizeof(buf))
+ chunk = sizeof(buf);
+ r = RAND_bytes(buf, chunk);
+ if (r <= 0)
+ goto end;
+ if (format != FORMAT_TEXT) {
+ if (BIO_write(out, buf, chunk) != chunk)
+ goto end;
+ } else {
+ for (i = 0; i < chunk; i++)
+ if (BIO_printf(out, "%02x", buf[i]) != 2)
+ goto end;
+ }
+ num -= chunk;
+ }
+ if (format == FORMAT_TEXT)
+ BIO_puts(out, "\n");
+ if (BIO_flush(out) <= 0)
+ goto end;
+
+ ret = 0;
+
+ end:
+ if (ret != 0)
+ ERR_print_errors(bio_err);
+ release_engine(e);
+ BIO_free_all(out);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/rehash.c b/freebsd/crypto/openssl/apps/rehash.c
new file mode 100644
index 00000000..b90cd08f
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/rehash.c
@@ -0,0 +1,514 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2013-2014 Timo Teräs <timo.teras@gmail.com>
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include "progs.h"
+
+#if defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) || \
+ (defined(__VMS) && defined(__DECC) && __CRTL_VER >= 80300000)
+# include <unistd.h>
+# include <stdio.h>
+# include <limits.h>
+# include <errno.h>
+# include <string.h>
+# include <ctype.h>
+# include <sys/stat.h>
+
+/*
+ * Make sure that the processing of symbol names is treated the same as when
+ * libcrypto is built. This is done automatically for public headers (see
+ * include/openssl/__DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H),
+ * but not for internal headers.
+ */
+# ifdef __VMS
+# pragma names save
+# pragma names as_is,shortened
+# endif
+
+# include "internal/o_dir.h"
+
+# ifdef __VMS
+# pragma names restore
+# endif
+
+# include <openssl/evp.h>
+# include <openssl/pem.h>
+# include <openssl/x509.h>
+
+
+# ifndef PATH_MAX
+# define PATH_MAX 4096
+# endif
+# ifndef NAME_MAX
+# define NAME_MAX 255
+# endif
+# define MAX_COLLISIONS 256
+
+typedef struct hentry_st {
+ struct hentry_st *next;
+ char *filename;
+ unsigned short old_id;
+ unsigned char need_symlink;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+} HENTRY;
+
+typedef struct bucket_st {
+ struct bucket_st *next;
+ HENTRY *first_entry, *last_entry;
+ unsigned int hash;
+ unsigned short type;
+ unsigned short num_needed;
+} BUCKET;
+
+enum Type {
+ /* Keep in sync with |suffixes|, below. */
+ TYPE_CERT=0, TYPE_CRL=1
+};
+
+enum Hash {
+ HASH_OLD, HASH_NEW, HASH_BOTH
+};
+
+
+static int evpmdsize;
+static const EVP_MD *evpmd;
+static int remove_links = 1;
+static int verbose = 0;
+static BUCKET *hash_table[257];
+
+static const char *suffixes[] = { "", "r" };
+static const char *extensions[] = { "pem", "crt", "cer", "crl" };
+
+
+static void bit_set(unsigned char *set, unsigned int bit)
+{
+ set[bit >> 3] |= 1 << (bit & 0x7);
+}
+
+static int bit_isset(unsigned char *set, unsigned int bit)
+{
+ return set[bit >> 3] & (1 << (bit & 0x7));
+}
+
+
+/*
+ * Process an entry; return number of errors.
+ */
+static int add_entry(enum Type type, unsigned int hash, const char *filename,
+ const unsigned char *digest, int need_symlink,
+ unsigned short old_id)
+{
+ static BUCKET nilbucket;
+ static HENTRY nilhentry;
+ BUCKET *bp;
+ HENTRY *ep, *found = NULL;
+ unsigned int ndx = (type + hash) % OSSL_NELEM(hash_table);
+
+ for (bp = hash_table[ndx]; bp; bp = bp->next)
+ if (bp->type == type && bp->hash == hash)
+ break;
+ if (bp == NULL) {
+ bp = app_malloc(sizeof(*bp), "hash bucket");
+ *bp = nilbucket;
+ bp->next = hash_table[ndx];
+ bp->type = type;
+ bp->hash = hash;
+ hash_table[ndx] = bp;
+ }
+
+ for (ep = bp->first_entry; ep; ep = ep->next) {
+ if (digest && memcmp(digest, ep->digest, evpmdsize) == 0) {
+ BIO_printf(bio_err,
+ "%s: warning: skipping duplicate %s in %s\n",
+ opt_getprog(),
+ type == TYPE_CERT ? "certificate" : "CRL", filename);
+ return 0;
+ }
+ if (strcmp(filename, ep->filename) == 0) {
+ found = ep;
+ if (digest == NULL)
+ break;
+ }
+ }
+ ep = found;
+ if (ep == NULL) {
+ if (bp->num_needed >= MAX_COLLISIONS) {
+ BIO_printf(bio_err,
+ "%s: error: hash table overflow for %s\n",
+ opt_getprog(), filename);
+ return 1;
+ }
+ ep = app_malloc(sizeof(*ep), "collision bucket");
+ *ep = nilhentry;
+ ep->old_id = ~0;
+ ep->filename = OPENSSL_strdup(filename);
+ if (bp->last_entry)
+ bp->last_entry->next = ep;
+ if (bp->first_entry == NULL)
+ bp->first_entry = ep;
+ bp->last_entry = ep;
+ }
+
+ if (old_id < ep->old_id)
+ ep->old_id = old_id;
+ if (need_symlink && !ep->need_symlink) {
+ ep->need_symlink = 1;
+ bp->num_needed++;
+ memcpy(ep->digest, digest, evpmdsize);
+ }
+ return 0;
+}
+
+/*
+ * Check if a symlink goes to the right spot; return 0 if okay.
+ * This can be -1 if bad filename, or an error count.
+ */
+static int handle_symlink(const char *filename, const char *fullpath)
+{
+ unsigned int hash = 0;
+ int i, type, id;
+ unsigned char ch;
+ char linktarget[PATH_MAX], *endptr;
+ ossl_ssize_t n;
+
+ for (i = 0; i < 8; i++) {
+ ch = filename[i];
+ if (!isxdigit(ch))
+ return -1;
+ hash <<= 4;
+ hash += OPENSSL_hexchar2int(ch);
+ }
+ if (filename[i++] != '.')
+ return -1;
+ for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) {
+ const char *suffix = suffixes[type];
+ if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
+ break;
+ }
+ i += strlen(suffixes[type]);
+
+ id = strtoul(&filename[i], &endptr, 10);
+ if (*endptr != '\0')
+ return -1;
+
+ n = readlink(fullpath, linktarget, sizeof(linktarget));
+ if (n < 0 || n >= (int)sizeof(linktarget))
+ return -1;
+ linktarget[n] = 0;
+
+ return add_entry(type, hash, linktarget, NULL, 0, id);
+}
+
+/*
+ * process a file, return number of errors.
+ */
+static int do_file(const char *filename, const char *fullpath, enum Hash h)
+{
+ STACK_OF (X509_INFO) *inf = NULL;
+ X509_INFO *x;
+ X509_NAME *name = NULL;
+ BIO *b;
+ const char *ext;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ int type, errs = 0;
+ size_t i;
+
+ /* Does it end with a recognized extension? */
+ if ((ext = strrchr(filename, '.')) == NULL)
+ goto end;
+ for (i = 0; i < OSSL_NELEM(extensions); i++) {
+ if (strcasecmp(extensions[i], ext + 1) == 0)
+ break;
+ }
+ if (i >= OSSL_NELEM(extensions))
+ goto end;
+
+ /* Does it have X.509 data in it? */
+ if ((b = BIO_new_file(fullpath, "r")) == NULL) {
+ BIO_printf(bio_err, "%s: error: skipping %s, cannot open file\n",
+ opt_getprog(), filename);
+ errs++;
+ goto end;
+ }
+ inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
+ BIO_free(b);
+ if (inf == NULL)
+ goto end;
+
+ if (sk_X509_INFO_num(inf) != 1) {
+ BIO_printf(bio_err,
+ "%s: warning: skipping %s,"
+ "it does not contain exactly one certificate or CRL\n",
+ opt_getprog(), filename);
+ /* This is not an error. */
+ goto end;
+ }
+ x = sk_X509_INFO_value(inf, 0);
+ if (x->x509 != NULL) {
+ type = TYPE_CERT;
+ name = X509_get_subject_name(x->x509);
+ X509_digest(x->x509, evpmd, digest, NULL);
+ } else if (x->crl != NULL) {
+ type = TYPE_CRL;
+ name = X509_CRL_get_issuer(x->crl);
+ X509_CRL_digest(x->crl, evpmd, digest, NULL);
+ } else {
+ ++errs;
+ goto end;
+ }
+ if (name != NULL) {
+ if ((h == HASH_NEW) || (h == HASH_BOTH))
+ errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0);
+ if ((h == HASH_OLD) || (h == HASH_BOTH))
+ errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0);
+ }
+
+end:
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ return errs;
+}
+
+static void str_free(char *s)
+{
+ OPENSSL_free(s);
+}
+
+static int ends_with_dirsep(const char *path)
+{
+ if (*path != '\0')
+ path += strlen(path) - 1;
+# if defined __VMS
+ if (*path == ']' || *path == '>' || *path == ':')
+ return 1;
+# elif defined _WIN32
+ if (*path == '\\')
+ return 1;
+# endif
+ return *path == '/';
+}
+
+/*
+ * Process a directory; return number of errors found.
+ */
+static int do_dir(const char *dirname, enum Hash h)
+{
+ BUCKET *bp, *nextbp;
+ HENTRY *ep, *nextep;
+ OPENSSL_DIR_CTX *d = NULL;
+ struct stat st;
+ unsigned char idmask[MAX_COLLISIONS / 8];
+ int n, numfiles, nextid, buflen, errs = 0;
+ size_t i;
+ const char *pathsep;
+ const char *filename;
+ char *buf, *copy = NULL;
+ STACK_OF(OPENSSL_STRING) *files = NULL;
+
+ if (app_access(dirname, W_OK) < 0) {
+ BIO_printf(bio_err, "Skipping %s, can't write\n", dirname);
+ return 1;
+ }
+ buflen = strlen(dirname);
+ pathsep = (buflen && !ends_with_dirsep(dirname)) ? "/": "";
+ buflen += NAME_MAX + 1 + 1;
+ buf = app_malloc(buflen, "filename buffer");
+
+ if (verbose)
+ BIO_printf(bio_out, "Doing %s\n", dirname);
+
+ if ((files = sk_OPENSSL_STRING_new_null()) == NULL) {
+ BIO_printf(bio_err, "Skipping %s, out of memory\n", dirname);
+ errs = 1;
+ goto err;
+ }
+ while ((filename = OPENSSL_DIR_read(&d, dirname)) != NULL) {
+ if ((copy = OPENSSL_strdup(filename)) == NULL
+ || sk_OPENSSL_STRING_push(files, copy) == 0) {
+ OPENSSL_free(copy);
+ BIO_puts(bio_err, "out of memory\n");
+ errs = 1;
+ goto err;
+ }
+ }
+ OPENSSL_DIR_end(&d);
+ sk_OPENSSL_STRING_sort(files);
+
+ numfiles = sk_OPENSSL_STRING_num(files);
+ for (n = 0; n < numfiles; ++n) {
+ filename = sk_OPENSSL_STRING_value(files, n);
+ if (BIO_snprintf(buf, buflen, "%s%s%s",
+ dirname, pathsep, filename) >= buflen)
+ continue;
+ if (lstat(buf, &st) < 0)
+ continue;
+ if (S_ISLNK(st.st_mode) && handle_symlink(filename, buf) == 0)
+ continue;
+ errs += do_file(filename, buf, h);
+ }
+
+ for (i = 0; i < OSSL_NELEM(hash_table); i++) {
+ for (bp = hash_table[i]; bp; bp = nextbp) {
+ nextbp = bp->next;
+ nextid = 0;
+ memset(idmask, 0, (bp->num_needed + 7) / 8);
+ for (ep = bp->first_entry; ep; ep = ep->next)
+ if (ep->old_id < bp->num_needed)
+ bit_set(idmask, ep->old_id);
+
+ for (ep = bp->first_entry; ep; ep = nextep) {
+ nextep = ep->next;
+ if (ep->old_id < bp->num_needed) {
+ /* Link exists, and is used as-is */
+ BIO_snprintf(buf, buflen, "%08x.%s%d", bp->hash,
+ suffixes[bp->type], ep->old_id);
+ if (verbose)
+ BIO_printf(bio_out, "link %s -> %s\n",
+ ep->filename, buf);
+ } else if (ep->need_symlink) {
+ /* New link needed (it may replace something) */
+ while (bit_isset(idmask, nextid))
+ nextid++;
+
+ BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
+ dirname, pathsep, &n, bp->hash,
+ suffixes[bp->type], nextid);
+ if (verbose)
+ BIO_printf(bio_out, "link %s -> %s\n",
+ ep->filename, &buf[n]);
+ if (unlink(buf) < 0 && errno != ENOENT) {
+ BIO_printf(bio_err,
+ "%s: Can't unlink %s, %s\n",
+ opt_getprog(), buf, strerror(errno));
+ errs++;
+ }
+ if (symlink(ep->filename, buf) < 0) {
+ BIO_printf(bio_err,
+ "%s: Can't symlink %s, %s\n",
+ opt_getprog(), ep->filename,
+ strerror(errno));
+ errs++;
+ }
+ bit_set(idmask, nextid);
+ } else if (remove_links) {
+ /* Link to be deleted */
+ BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
+ dirname, pathsep, &n, bp->hash,
+ suffixes[bp->type], ep->old_id);
+ if (verbose)
+ BIO_printf(bio_out, "unlink %s\n",
+ &buf[n]);
+ if (unlink(buf) < 0 && errno != ENOENT) {
+ BIO_printf(bio_err,
+ "%s: Can't unlink %s, %s\n",
+ opt_getprog(), buf, strerror(errno));
+ errs++;
+ }
+ }
+ OPENSSL_free(ep->filename);
+ OPENSSL_free(ep);
+ }
+ OPENSSL_free(bp);
+ }
+ hash_table[i] = NULL;
+ }
+
+ err:
+ sk_OPENSSL_STRING_pop_free(files, str_free);
+ OPENSSL_free(buf);
+ return errs;
+}
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE
+} OPTION_CHOICE;
+
+const OPTIONS rehash_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"h", OPT_HELP, '-', "Display this summary"},
+ {"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"},
+ {"old", OPT_OLD, '-', "Use old-style hash to generate links"},
+ {"n", OPT_N, '-', "Do not remove existing links"},
+ {"v", OPT_VERBOSE, '-', "Verbose output"},
+ {NULL}
+};
+
+
+int rehash_main(int argc, char **argv)
+{
+ const char *env, *prog;
+ char *e, *m;
+ int errs = 0;
+ OPTION_CHOICE o;
+ enum Hash h = HASH_NEW;
+
+ prog = opt_init(argc, argv, rehash_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(rehash_options);
+ goto end;
+ case OPT_COMPAT:
+ h = HASH_BOTH;
+ break;
+ case OPT_OLD:
+ h = HASH_OLD;
+ break;
+ case OPT_N:
+ remove_links = 0;
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ evpmd = EVP_sha1();
+ evpmdsize = EVP_MD_size(evpmd);
+
+ if (*argv != NULL) {
+ while (*argv != NULL)
+ errs += do_dir(*argv++, h);
+ } else if ((env = getenv(X509_get_default_cert_dir_env())) != NULL) {
+ char lsc[2] = { LIST_SEPARATOR_CHAR, '\0' };
+ m = OPENSSL_strdup(env);
+ for (e = strtok(m, lsc); e != NULL; e = strtok(NULL, lsc))
+ errs += do_dir(e, h);
+ OPENSSL_free(m);
+ } else {
+ errs += do_dir(X509_get_default_cert_dir(), h);
+ }
+
+ end:
+ return errs;
+}
+
+#else
+const OPTIONS rehash_options[] = {
+ {NULL}
+};
+
+int rehash_main(int argc, char **argv)
+{
+ BIO_printf(bio_err, "Not available; use c_rehash script\n");
+ return 1;
+}
+
+#endif /* defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) */
diff --git a/freebsd/crypto/openssl/apps/req.c b/freebsd/crypto/openssl/apps/req.c
new file mode 100644
index 00000000..0308a607
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/req.c
@@ -0,0 +1,1666 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <ctype.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#include <openssl/bn.h>
+#include <openssl/lhash.h>
+#ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+# include <openssl/dsa.h>
+#endif
+
+#define SECTION "req"
+
+#define BITS "default_bits"
+#define KEYFILE "default_keyfile"
+#define PROMPT "prompt"
+#define DISTINGUISHED_NAME "distinguished_name"
+#define ATTRIBUTES "attributes"
+#define V3_EXTENSIONS "x509_extensions"
+#define REQ_EXTENSIONS "req_extensions"
+#define STRING_MASK "string_mask"
+#define UTF8_IN "utf8"
+
+#define DEFAULT_KEY_LENGTH 2048
+#define MIN_KEY_LENGTH 512
+
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn,
+ int attribs, unsigned long chtype);
+static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype,
+ int multirdn);
+static int prompt_info(X509_REQ *req,
+ STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
+ STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
+ int attribs, unsigned long chtype);
+static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
+ STACK_OF(CONF_VALUE) *attr, int attribs,
+ unsigned long chtype);
+static int add_attribute_object(X509_REQ *req, char *text, const char *def,
+ char *value, int nid, int n_min, int n_max,
+ unsigned long chtype);
+static int add_DN_object(X509_NAME *n, char *text, const char *def,
+ char *value, int nid, int n_min, int n_max,
+ unsigned long chtype, int mval);
+static int genpkey_cb(EVP_PKEY_CTX *ctx);
+static int build_data(char *text, const char *def,
+ char *value, int n_min, int n_max,
+ char *buf, const int buf_size,
+ const char *desc1, const char *desc2
+ );
+static int req_check_len(int len, int n_min, int n_max);
+static int check_end(const char *str, const char *end);
+static int join(char buf[], size_t buf_size, const char *name,
+ const char *tail, const char *desc);
+static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
+ int *pkey_type, long *pkeylen,
+ char **palgnam, ENGINE *keygen_engine);
+static CONF *req_conf = NULL;
+static CONF *addext_conf = NULL;
+static int batch = 0;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY,
+ OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT,
+ OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
+ OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
+ OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
+ OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
+ OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS,
+ OPT_REQEXTS, OPT_PRECERT, OPT_MD,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS req_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"key", OPT_KEY, 's', "Private key to use"},
+ {"keyform", OPT_KEYFORM, 'f', "Key file format"},
+ {"pubkey", OPT_PUBKEY, '-', "Output public key"},
+ {"new", OPT_NEW, '-', "New request"},
+ {"config", OPT_CONFIG, '<', "Request template file"},
+ {"keyout", OPT_KEYOUT, '>', "File to send the key to"},
+ {"passin", OPT_PASSIN, 's', "Private key password source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ OPT_R_OPTIONS,
+ {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"},
+ {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"batch", OPT_BATCH, '-',
+ "Do not ask anything during request generation"},
+ {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"},
+ {"modulus", OPT_MODULUS, '-', "RSA modulus"},
+ {"verify", OPT_VERIFY, '-', "Verify signature on REQ"},
+ {"nodes", OPT_NODES, '-', "Don't encrypt the output key"},
+ {"noout", OPT_NOOUT, '-', "Do not output REQ"},
+ {"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"reqopt", OPT_REQOPT, 's', "Various request text options"},
+ {"text", OPT_TEXT, '-', "Text form of request"},
+ {"x509", OPT_X509, '-',
+ "Output a x509 structure instead of a cert request"},
+ {OPT_MORE_STR, 1, 1, "(Required by some CA's)"},
+ {"subj", OPT_SUBJ, 's', "Set or modify request subject"},
+ {"subject", OPT_SUBJECT, '-', "Output the request's subject"},
+ {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
+ "Enable support for multivalued RDNs"},
+ {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
+ {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
+ {"addext", OPT_ADDEXT, 's',
+ "Additional cert extension key=value pair (may be given more than once)"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Cert extension section (override value in config file)"},
+ {"reqexts", OPT_REQEXTS, 's',
+ "Request extension section (override value in config file)"},
+ {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"keygen_engine", OPT_KEYGEN_ENGINE, 's',
+ "Specify engine to be used for key generation operations"},
+#endif
+ {NULL}
+};
+
+
+/*
+ * An LHASH of strings, where each string is an extension name.
+ */
+static unsigned long ext_name_hash(const OPENSSL_STRING *a)
+{
+ return OPENSSL_LH_strhash((const char *)a);
+}
+
+static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
+{
+ return strcmp((const char *)a, (const char *)b);
+}
+
+static void exts_cleanup(OPENSSL_STRING *x)
+{
+ OPENSSL_free((char *)x);
+}
+
+/*
+ * Is the |kv| key already duplicated? This is remarkably tricky to get
+ * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax
+ * error.
+ */
+static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
+{
+ char *p;
+ size_t off;
+
+ /* Check syntax. */
+ /* Skip leading whitespace, make a copy. */
+ while (*kv && isspace(*kv))
+ if (*++kv == '\0')
+ return 1;
+ if ((p = strchr(kv, '=')) == NULL)
+ return 1;
+ off = p - kv;
+ if ((kv = OPENSSL_strdup(kv)) == NULL)
+ return -1;
+
+ /* Skip trailing space before the equal sign. */
+ for (p = kv + off; p > kv; --p)
+ if (!isspace(p[-1]))
+ break;
+ if (p == kv) {
+ OPENSSL_free(kv);
+ return 1;
+ }
+ *p = '\0';
+
+ /* Finally have a clean "key"; see if it's there [by attempt to add it]. */
+ if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
+ != NULL || lh_OPENSSL_STRING_error(addexts)) {
+ OPENSSL_free(p != NULL ? p : kv);
+ return -1;
+ }
+
+ return 0;
+}
+
+int req_main(int argc, char **argv)
+{
+ ASN1_INTEGER *serial = NULL;
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL, *gen_eng = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *genctx = NULL;
+ STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
+ LHASH_OF(OPENSSL_STRING) *addexts = NULL;
+ X509 *x509ss = NULL;
+ X509_REQ *req = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ const EVP_MD *md_alg = NULL, *digest = NULL;
+ BIO *addext_bio = NULL;
+ char *extensions = NULL, *infile = NULL;
+ char *outfile = NULL, *keyfile = NULL;
+ char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
+ char *passin = NULL, *passout = NULL;
+ char *nofree_passin = NULL, *nofree_passout = NULL;
+ char *req_exts = NULL, *subj = NULL;
+ char *template = default_config_file, *keyout = NULL;
+ const char *keyalg = NULL;
+ OPTION_CHOICE o;
+ int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0;
+ int pkey_type = -1, private = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM;
+ int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0;
+ int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
+ long newkey = -1;
+ unsigned long chtype = MBSTRING_ASC, reqflag = 0;
+
+#ifndef OPENSSL_NO_DES
+ cipher = EVP_des_ede3_cbc();
+#endif
+
+ prog = opt_init(argc, argv, req_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(req_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
+ goto opthelp;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_KEYGEN_ENGINE:
+#ifndef OPENSSL_NO_ENGINE
+ gen_eng = ENGINE_by_id(opt_arg());
+ if (gen_eng == NULL) {
+ BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
+ goto opthelp;
+ }
+#endif
+ break;
+ case OPT_KEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_PUBKEY:
+ pubkey = 1;
+ break;
+ case OPT_NEW:
+ newreq = 1;
+ break;
+ case OPT_CONFIG:
+ template = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_KEYOUT:
+ keyout = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passargin = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passargout = opt_arg();
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_NEWKEY:
+ keyalg = opt_arg();
+ newreq = 1;
+ break;
+ case OPT_PKEYOPT:
+ if (!pkeyopts)
+ pkeyopts = sk_OPENSSL_STRING_new_null();
+ if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_SIGOPT:
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_BATCH:
+ batch = 1;
+ break;
+ case OPT_NEWHDR:
+ newhdr = 1;
+ break;
+ case OPT_MODULUS:
+ modulus = 1;
+ break;
+ case OPT_VERIFY:
+ verify = 1;
+ break;
+ case OPT_NODES:
+ nodes = 1;
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_VERBOSE:
+ verbose = 1;
+ break;
+ case OPT_UTF8:
+ chtype = MBSTRING_UTF8;
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_REQOPT:
+ if (!set_cert_ex(&reqflag, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_X509:
+ x509 = 1;
+ break;
+ case OPT_DAYS:
+ days = atoi(opt_arg());
+ break;
+ case OPT_SET_SERIAL:
+ if (serial != NULL) {
+ BIO_printf(bio_err, "Serial number supplied twice\n");
+ goto opthelp;
+ }
+ serial = s2i_ASN1_INTEGER(NULL, opt_arg());
+ if (serial == NULL)
+ goto opthelp;
+ break;
+ case OPT_SUBJECT:
+ subject = 1;
+ break;
+ case OPT_SUBJ:
+ subj = opt_arg();
+ break;
+ case OPT_MULTIVALUE_RDN:
+ multirdn = 1;
+ break;
+ case OPT_ADDEXT:
+ p = opt_arg();
+ if (addexts == NULL) {
+ addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp);
+ addext_bio = BIO_new(BIO_s_mem());
+ if (addexts == NULL || addext_bio == NULL)
+ goto end;
+ }
+ i = duplicated(addexts, p);
+ if (i == 1)
+ goto opthelp;
+ if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
+ goto end;
+ break;
+ case OPT_EXTENSIONS:
+ extensions = opt_arg();
+ break;
+ case OPT_REQEXTS:
+ req_exts = opt_arg();
+ break;
+ case OPT_PRECERT:
+ newreq = precert = 1;
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_unknown(), &md_alg))
+ goto opthelp;
+ digest = md_alg;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (days && !x509)
+ BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n");
+ if (x509 && infile == NULL)
+ newreq = 1;
+
+ /* TODO: simplify this as pkey is still always NULL here */
+ private = newreq && (pkey == NULL) ? 1 : 0;
+
+ if (!app_passwd(passargin, passargout, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Using configuration from %s\n", template);
+ req_conf = app_load_config(template);
+ if (addext_bio) {
+ if (verbose)
+ BIO_printf(bio_err,
+ "Using additional configuration from command line\n");
+ addext_conf = app_load_config_bio(addext_bio, NULL);
+ }
+ if (template != default_config_file && !app_load_modules(req_conf))
+ goto end;
+
+ if (req_conf != NULL) {
+ p = NCONF_get_string(req_conf, NULL, "oid_file");
+ if (p == NULL)
+ ERR_clear_error();
+ if (p != NULL) {
+ BIO *oid_bio;
+
+ oid_bio = BIO_new_file(p, "r");
+ if (oid_bio == NULL) {
+ /*-
+ BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
+ ERR_print_errors(bio_err);
+ */
+ } else {
+ OBJ_create_objects(oid_bio);
+ BIO_free(oid_bio);
+ }
+ }
+ }
+ if (!add_oid_section(req_conf))
+ goto end;
+
+ if (md_alg == NULL) {
+ p = NCONF_get_string(req_conf, SECTION, "default_md");
+ if (p == NULL) {
+ ERR_clear_error();
+ } else {
+ if (!opt_md(p, &md_alg))
+ goto opthelp;
+ digest = md_alg;
+ }
+ }
+
+ if (extensions == NULL) {
+ extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
+ if (extensions == NULL)
+ ERR_clear_error();
+ }
+ if (extensions != NULL) {
+ /* Check syntax of file */
+ X509V3_CTX ctx;
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, req_conf);
+ if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
+ BIO_printf(bio_err,
+ "Error Loading extension section %s\n", extensions);
+ goto end;
+ }
+ }
+ if (addext_conf != NULL) {
+ /* Check syntax of command line extensions */
+ X509V3_CTX ctx;
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, addext_conf);
+ if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
+ BIO_printf(bio_err, "Error Loading command line extensions\n");
+ goto end;
+ }
+ }
+
+ if (passin == NULL) {
+ passin = nofree_passin =
+ NCONF_get_string(req_conf, SECTION, "input_password");
+ if (passin == NULL)
+ ERR_clear_error();
+ }
+
+ if (passout == NULL) {
+ passout = nofree_passout =
+ NCONF_get_string(req_conf, SECTION, "output_password");
+ if (passout == NULL)
+ ERR_clear_error();
+ }
+
+ p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
+ if (p == NULL)
+ ERR_clear_error();
+
+ if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) {
+ BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
+ goto end;
+ }
+
+ if (chtype != MBSTRING_UTF8) {
+ p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
+ if (p == NULL)
+ ERR_clear_error();
+ else if (strcmp(p, "yes") == 0)
+ chtype = MBSTRING_UTF8;
+ }
+
+ if (req_exts == NULL) {
+ req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
+ if (req_exts == NULL)
+ ERR_clear_error();
+ }
+ if (req_exts != NULL) {
+ /* Check syntax of file */
+ X509V3_CTX ctx;
+ X509V3_set_ctx_test(&ctx);
+ X509V3_set_nconf(&ctx, req_conf);
+ if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
+ BIO_printf(bio_err,
+ "Error Loading request extension section %s\n",
+ req_exts);
+ goto end;
+ }
+ }
+
+ if (keyfile != NULL) {
+ pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key");
+ if (pkey == NULL) {
+ /* load_key() has already printed an appropriate message */
+ goto end;
+ } else {
+ app_RAND_load_conf(req_conf, SECTION);
+ }
+ }
+
+ if (newreq && (pkey == NULL)) {
+ app_RAND_load_conf(req_conf, SECTION);
+
+ if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) {
+ newkey = DEFAULT_KEY_LENGTH;
+ }
+
+ if (keyalg != NULL) {
+ genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey,
+ &keyalgstr, gen_eng);
+ if (genctx == NULL)
+ goto end;
+ }
+
+ if (newkey < MIN_KEY_LENGTH
+ && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
+ BIO_printf(bio_err, "private key length is too short,\n");
+ BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n",
+ MIN_KEY_LENGTH, newkey);
+ goto end;
+ }
+
+ if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS)
+ BIO_printf(bio_err,
+ "Warning: It is not recommended to use more than %d bit for RSA keys.\n"
+ " Your key size is %ld! Larger key size may behave not as expected.\n",
+ OPENSSL_RSA_MAX_MODULUS_BITS, newkey);
+
+#ifndef OPENSSL_NO_DSA
+ if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS)
+ BIO_printf(bio_err,
+ "Warning: It is not recommended to use more than %d bit for DSA keys.\n"
+ " Your key size is %ld! Larger key size may behave not as expected.\n",
+ OPENSSL_DSA_MAX_MODULUS_BITS, newkey);
+#endif
+
+ if (genctx == NULL) {
+ genctx = set_keygen_ctx(NULL, &pkey_type, &newkey,
+ &keyalgstr, gen_eng);
+ if (!genctx)
+ goto end;
+ }
+
+ if (pkeyopts != NULL) {
+ char *genopt;
+ for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) {
+ genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
+ if (pkey_ctrl_string(genctx, genopt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", genopt);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+
+ if (pkey_type == EVP_PKEY_EC) {
+ BIO_printf(bio_err, "Generating an EC private key\n");
+ } else {
+ BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr);
+ }
+
+ EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
+ EVP_PKEY_CTX_set_app_data(genctx, bio_err);
+
+ if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
+ BIO_puts(bio_err, "Error Generating Key\n");
+ goto end;
+ }
+
+ EVP_PKEY_CTX_free(genctx);
+ genctx = NULL;
+
+ if (keyout == NULL) {
+ keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
+ if (keyout == NULL)
+ ERR_clear_error();
+ }
+
+ if (keyout == NULL)
+ BIO_printf(bio_err, "writing new private key to stdout\n");
+ else
+ BIO_printf(bio_err, "writing new private key to '%s'\n", keyout);
+ out = bio_open_owner(keyout, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
+ if (p == NULL) {
+ ERR_clear_error();
+ p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
+ if (p == NULL)
+ ERR_clear_error();
+ }
+ if ((p != NULL) && (strcmp(p, "no") == 0))
+ cipher = NULL;
+ if (nodes)
+ cipher = NULL;
+
+ i = 0;
+ loop:
+ assert(private);
+ if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
+ NULL, 0, NULL, passout)) {
+ if ((ERR_GET_REASON(ERR_peek_error()) ==
+ PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
+ ERR_clear_error();
+ i++;
+ goto loop;
+ }
+ goto end;
+ }
+ BIO_free(out);
+ out = NULL;
+ BIO_printf(bio_err, "-----\n");
+ }
+
+ if (!newreq) {
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (informat == FORMAT_ASN1)
+ req = d2i_X509_REQ_bio(in, NULL);
+ else
+ req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
+ if (req == NULL) {
+ BIO_printf(bio_err, "unable to load X509 request\n");
+ goto end;
+ }
+ }
+
+ if (newreq || x509) {
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "you need to specify a private key\n");
+ goto end;
+ }
+
+ if (req == NULL) {
+ req = X509_REQ_new();
+ if (req == NULL) {
+ goto end;
+ }
+
+ i = make_REQ(req, pkey, subj, multirdn, !x509, chtype);
+ subj = NULL; /* done processing '-subj' option */
+ if (!i) {
+ BIO_printf(bio_err, "problems making Certificate Request\n");
+ goto end;
+ }
+ }
+ if (x509) {
+ EVP_PKEY *tmppkey;
+ X509V3_CTX ext_ctx;
+ if ((x509ss = X509_new()) == NULL)
+ goto end;
+
+ /* Set version to V3 */
+ if ((extensions != NULL || addext_conf != NULL)
+ && !X509_set_version(x509ss, 2))
+ goto end;
+ if (serial != NULL) {
+ if (!X509_set_serialNumber(x509ss, serial))
+ goto end;
+ } else {
+ if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
+ goto end;
+ }
+
+ if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
+ goto end;
+ if (days == 0) {
+ /* set default days if it's not specified */
+ days = 30;
+ }
+ if (!set_cert_times(x509ss, NULL, NULL, days))
+ goto end;
+ if (!X509_set_subject_name
+ (x509ss, X509_REQ_get_subject_name(req)))
+ goto end;
+ tmppkey = X509_REQ_get0_pubkey(req);
+ if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
+ goto end;
+
+ /* Set up V3 context struct */
+
+ X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
+ X509V3_set_nconf(&ext_ctx, req_conf);
+
+ /* Add extensions */
+ if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf,
+ &ext_ctx, extensions,
+ x509ss)) {
+ BIO_printf(bio_err, "Error Loading extension section %s\n",
+ extensions);
+ goto end;
+ }
+ if (addext_conf != NULL
+ && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default",
+ x509ss)) {
+ BIO_printf(bio_err, "Error Loading command line extensions\n");
+ goto end;
+ }
+
+ /* If a pre-cert was requested, we need to add a poison extension */
+ if (precert) {
+ if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0)
+ != 1) {
+ BIO_printf(bio_err, "Error adding poison extension\n");
+ goto end;
+ }
+ }
+
+ i = do_X509_sign(x509ss, pkey, digest, sigopts);
+ if (!i) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+ X509V3_CTX ext_ctx;
+
+ /* Set up V3 context struct */
+
+ X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
+ X509V3_set_nconf(&ext_ctx, req_conf);
+
+ /* Add extensions */
+ if (req_exts != NULL
+ && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx,
+ req_exts, req)) {
+ BIO_printf(bio_err, "Error Loading extension section %s\n",
+ req_exts);
+ goto end;
+ }
+ if (addext_conf != NULL
+ && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default",
+ req)) {
+ BIO_printf(bio_err, "Error Loading command line extensions\n");
+ goto end;
+ }
+ i = do_X509_REQ_sign(req, pkey, digest, sigopts);
+ if (!i) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+
+ if (subj && x509) {
+ BIO_printf(bio_err, "Cannot modify certificate subject\n");
+ goto end;
+ }
+
+ if (subj && !x509) {
+ if (verbose) {
+ BIO_printf(bio_err, "Modifying Request's Subject\n");
+ print_name(bio_err, "old subject=",
+ X509_REQ_get_subject_name(req), get_nameopt());
+ }
+
+ if (build_subject(req, subj, chtype, multirdn) == 0) {
+ BIO_printf(bio_err, "ERROR: cannot modify subject\n");
+ ret = 1;
+ goto end;
+ }
+
+ if (verbose) {
+ print_name(bio_err, "new subject=",
+ X509_REQ_get_subject_name(req), get_nameopt());
+ }
+ }
+
+ if (verify && !x509) {
+ EVP_PKEY *tpubkey = pkey;
+
+ if (tpubkey == NULL) {
+ tpubkey = X509_REQ_get0_pubkey(req);
+ if (tpubkey == NULL)
+ goto end;
+ }
+
+ i = X509_REQ_verify(req, tpubkey);
+
+ if (i < 0) {
+ goto end;
+ } else if (i == 0) {
+ BIO_printf(bio_err, "verify failure\n");
+ ERR_print_errors(bio_err);
+ } else { /* if (i > 0) */
+ BIO_printf(bio_err, "verify OK\n");
+ }
+ }
+
+ if (noout && !text && !modulus && !subject && !pubkey) {
+ ret = 0;
+ goto end;
+ }
+
+ out = bio_open_default(outfile,
+ keyout != NULL && outfile != NULL &&
+ strcmp(keyout, outfile) == 0 ? 'a' : 'w',
+ outformat);
+ if (out == NULL)
+ goto end;
+
+ if (pubkey) {
+ EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req);
+
+ if (tpubkey == NULL) {
+ BIO_printf(bio_err, "Error getting public key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ PEM_write_bio_PUBKEY(out, tpubkey);
+ }
+
+ if (text) {
+ if (x509)
+ X509_print_ex(out, x509ss, get_nameopt(), reqflag);
+ else
+ X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
+ }
+
+ if (subject) {
+ if (x509)
+ print_name(out, "subject=", X509_get_subject_name(x509ss),
+ get_nameopt());
+ else
+ print_name(out, "subject=", X509_REQ_get_subject_name(req),
+ get_nameopt());
+ }
+
+ if (modulus) {
+ EVP_PKEY *tpubkey;
+
+ if (x509)
+ tpubkey = X509_get0_pubkey(x509ss);
+ else
+ tpubkey = X509_REQ_get0_pubkey(req);
+ if (tpubkey == NULL) {
+ fprintf(stdout, "Modulus=unavailable\n");
+ goto end;
+ }
+ fprintf(stdout, "Modulus=");
+#ifndef OPENSSL_NO_RSA
+ if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
+ const BIGNUM *n;
+ RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
+ BN_print(out, n);
+ } else
+#endif
+ fprintf(stdout, "Wrong Algorithm type");
+ fprintf(stdout, "\n");
+ }
+
+ if (!noout && !x509) {
+ if (outformat == FORMAT_ASN1)
+ i = i2d_X509_REQ_bio(out, req);
+ else if (newhdr)
+ i = PEM_write_bio_X509_REQ_NEW(out, req);
+ else
+ i = PEM_write_bio_X509_REQ(out, req);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write X509 request\n");
+ goto end;
+ }
+ }
+ if (!noout && x509 && (x509ss != NULL)) {
+ if (outformat == FORMAT_ASN1)
+ i = i2d_X509_bio(out, x509ss);
+ else
+ i = PEM_write_bio_X509(out, x509ss);
+ if (!i) {
+ BIO_printf(bio_err, "unable to write X509 certificate\n");
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ if (ret) {
+ ERR_print_errors(bio_err);
+ }
+ NCONF_free(req_conf);
+ NCONF_free(addext_conf);
+ BIO_free(addext_bio);
+ BIO_free(in);
+ BIO_free_all(out);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(genctx);
+ sk_OPENSSL_STRING_free(pkeyopts);
+ sk_OPENSSL_STRING_free(sigopts);
+ lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
+ lh_OPENSSL_STRING_free(addexts);
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_free(gen_eng);
+#endif
+ OPENSSL_free(keyalgstr);
+ X509_REQ_free(req);
+ X509_free(x509ss);
+ ASN1_INTEGER_free(serial);
+ release_engine(e);
+ if (passin != nofree_passin)
+ OPENSSL_free(passin);
+ if (passout != nofree_passout)
+ OPENSSL_free(passout);
+ return ret;
+}
+
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
+ int attribs, unsigned long chtype)
+{
+ int ret = 0, i;
+ char no_prompt = 0;
+ STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
+ char *tmp, *dn_sect, *attr_sect;
+
+ tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
+ if (tmp == NULL)
+ ERR_clear_error();
+ if ((tmp != NULL) && strcmp(tmp, "no") == 0)
+ no_prompt = 1;
+
+ dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
+ if (dn_sect == NULL) {
+ BIO_printf(bio_err, "unable to find '%s' in config\n",
+ DISTINGUISHED_NAME);
+ goto err;
+ }
+ dn_sk = NCONF_get_section(req_conf, dn_sect);
+ if (dn_sk == NULL) {
+ BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
+ goto err;
+ }
+
+ attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
+ if (attr_sect == NULL) {
+ ERR_clear_error();
+ attr_sk = NULL;
+ } else {
+ attr_sk = NCONF_get_section(req_conf, attr_sect);
+ if (attr_sk == NULL) {
+ BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
+ goto err;
+ }
+ }
+
+ /* setup version number */
+ if (!X509_REQ_set_version(req, 0L))
+ goto err; /* version 1 */
+
+ if (subj)
+ i = build_subject(req, subj, chtype, multirdn);
+ else if (no_prompt)
+ i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
+ else
+ i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs,
+ chtype);
+ if (!i)
+ goto err;
+
+ if (!X509_REQ_set_pubkey(req, pkey))
+ goto err;
+
+ ret = 1;
+ err:
+ return ret;
+}
+
+/*
+ * subject is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where characters may be escaped by \
+ */
+static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype,
+ int multirdn)
+{
+ X509_NAME *n;
+
+ if ((n = parse_name(subject, chtype, multirdn)) == NULL)
+ return 0;
+
+ if (!X509_REQ_set_subject_name(req, n)) {
+ X509_NAME_free(n);
+ return 0;
+ }
+ X509_NAME_free(n);
+ return 1;
+}
+
+static int prompt_info(X509_REQ *req,
+ STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
+ STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
+ int attribs, unsigned long chtype)
+{
+ int i;
+ char *p, *q;
+ char buf[100];
+ int nid, mval;
+ long n_min, n_max;
+ char *type, *value;
+ const char *def;
+ CONF_VALUE *v;
+ X509_NAME *subj;
+ subj = X509_REQ_get_subject_name(req);
+
+ if (!batch) {
+ BIO_printf(bio_err,
+ "You are about to be asked to enter information that will be incorporated\n");
+ BIO_printf(bio_err, "into your certificate request.\n");
+ BIO_printf(bio_err,
+ "What you are about to enter is what is called a Distinguished Name or a DN.\n");
+ BIO_printf(bio_err,
+ "There are quite a few fields but you can leave some blank\n");
+ BIO_printf(bio_err,
+ "For some fields there will be a default value,\n");
+ BIO_printf(bio_err,
+ "If you enter '.', the field will be left blank.\n");
+ BIO_printf(bio_err, "-----\n");
+ }
+
+ if (sk_CONF_VALUE_num(dn_sk)) {
+ i = -1;
+ start:
+ for ( ; ; ) {
+ i++;
+ if (sk_CONF_VALUE_num(dn_sk) <= i)
+ break;
+
+ v = sk_CONF_VALUE_value(dn_sk, i);
+ p = q = NULL;
+ type = v->name;
+ if (!check_end(type, "_min") || !check_end(type, "_max") ||
+ !check_end(type, "_default") || !check_end(type, "_value"))
+ continue;
+ /*
+ * Skip past any leading X. X: X, etc to allow for multiple
+ * instances
+ */
+ for (p = v->name; *p; p++)
+ if ((*p == ':') || (*p == ',') || (*p == '.')) {
+ p++;
+ if (*p)
+ type = p;
+ break;
+ }
+ if (*type == '+') {
+ mval = -1;
+ type++;
+ } else {
+ mval = 0;
+ }
+ /* If OBJ not recognised ignore it */
+ if ((nid = OBJ_txt2nid(type)) == NID_undef)
+ goto start;
+ if (!join(buf, sizeof(buf), v->name, "_default", "Name"))
+ return 0;
+ if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
+ ERR_clear_error();
+ def = "";
+ }
+
+ if (!join(buf, sizeof(buf), v->name, "_value", "Name"))
+ return 0;
+ if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
+ ERR_clear_error();
+ value = NULL;
+ }
+
+ if (!join(buf, sizeof(buf), v->name, "_min", "Name"))
+ return 0;
+ if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
+ ERR_clear_error();
+ n_min = -1;
+ }
+
+
+ if (!join(buf, sizeof(buf), v->name, "_max", "Name"))
+ return 0;
+ if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
+ ERR_clear_error();
+ n_max = -1;
+ }
+
+ if (!add_DN_object(subj, v->value, def, value, nid,
+ n_min, n_max, chtype, mval))
+ return 0;
+ }
+ if (X509_NAME_entry_count(subj) == 0) {
+ BIO_printf(bio_err,
+ "error, no objects specified in config file\n");
+ return 0;
+ }
+
+ if (attribs) {
+ if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0)
+ && (!batch)) {
+ BIO_printf(bio_err,
+ "\nPlease enter the following 'extra' attributes\n");
+ BIO_printf(bio_err,
+ "to be sent with your certificate request\n");
+ }
+
+ i = -1;
+ start2:
+ for ( ; ; ) {
+ i++;
+ if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
+ break;
+
+ v = sk_CONF_VALUE_value(attr_sk, i);
+ type = v->name;
+ if ((nid = OBJ_txt2nid(type)) == NID_undef)
+ goto start2;
+
+ if (!join(buf, sizeof(buf), type, "_default", "Name"))
+ return 0;
+ if ((def = NCONF_get_string(req_conf, attr_sect, buf))
+ == NULL) {
+ ERR_clear_error();
+ def = "";
+ }
+
+ if (!join(buf, sizeof(buf), type, "_value", "Name"))
+ return 0;
+ if ((value = NCONF_get_string(req_conf, attr_sect, buf))
+ == NULL) {
+ ERR_clear_error();
+ value = NULL;
+ }
+
+ if (!join(buf, sizeof(buf), type,"_min", "Name"))
+ return 0;
+ if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
+ ERR_clear_error();
+ n_min = -1;
+ }
+
+ if (!join(buf, sizeof(buf), type, "_max", "Name"))
+ return 0;
+ if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
+ ERR_clear_error();
+ n_max = -1;
+ }
+
+ if (!add_attribute_object(req,
+ v->value, def, value, nid, n_min,
+ n_max, chtype))
+ return 0;
+ }
+ }
+ } else {
+ BIO_printf(bio_err, "No template, please set one up.\n");
+ return 0;
+ }
+
+ return 1;
+
+}
+
+static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
+ STACK_OF(CONF_VALUE) *attr_sk, int attribs,
+ unsigned long chtype)
+{
+ int i, spec_char, plus_char;
+ char *p, *q;
+ char *type;
+ CONF_VALUE *v;
+ X509_NAME *subj;
+
+ subj = X509_REQ_get_subject_name(req);
+
+ for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
+ int mval;
+ v = sk_CONF_VALUE_value(dn_sk, i);
+ p = q = NULL;
+ type = v->name;
+ /*
+ * Skip past any leading X. X: X, etc to allow for multiple instances
+ */
+ for (p = v->name; *p; p++) {
+#ifndef CHARSET_EBCDIC
+ spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
+#else
+ spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
+ || (*p == os_toascii['.']));
+#endif
+ if (spec_char) {
+ p++;
+ if (*p)
+ type = p;
+ break;
+ }
+ }
+#ifndef CHARSET_EBCDIC
+ plus_char = (*type == '+');
+#else
+ plus_char = (*type == os_toascii['+']);
+#endif
+ if (plus_char) {
+ type++;
+ mval = -1;
+ } else {
+ mval = 0;
+ }
+ if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
+ (unsigned char *)v->value, -1, -1,
+ mval))
+ return 0;
+
+ }
+
+ if (!X509_NAME_entry_count(subj)) {
+ BIO_printf(bio_err, "error, no objects specified in config file\n");
+ return 0;
+ }
+ if (attribs) {
+ for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
+ v = sk_CONF_VALUE_value(attr_sk, i);
+ if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
+ (unsigned char *)v->value, -1))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int add_DN_object(X509_NAME *n, char *text, const char *def,
+ char *value, int nid, int n_min, int n_max,
+ unsigned long chtype, int mval)
+{
+ int ret = 0;
+ char buf[1024];
+
+ ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf),
+ "DN value", "DN default");
+ if ((ret == 0) || (ret == 1))
+ return ret;
+ ret = 1;
+
+ if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
+ (unsigned char *)buf, -1, -1, mval))
+ ret = 0;
+
+ return ret;
+}
+
+static int add_attribute_object(X509_REQ *req, char *text, const char *def,
+ char *value, int nid, int n_min,
+ int n_max, unsigned long chtype)
+{
+ int ret = 0;
+ char buf[1024];
+
+ ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf),
+ "Attribute value", "Attribute default");
+ if ((ret == 0) || (ret == 1))
+ return ret;
+ ret = 1;
+
+ if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
+ (unsigned char *)buf, -1)) {
+ BIO_printf(bio_err, "Error adding attribute\n");
+ ERR_print_errors(bio_err);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+static int build_data(char *text, const char *def,
+ char *value, int n_min, int n_max,
+ char *buf, const int buf_size,
+ const char *desc1, const char *desc2
+ )
+{
+ int i;
+ start:
+ if (!batch)
+ BIO_printf(bio_err, "%s [%s]:", text, def);
+ (void)BIO_flush(bio_err);
+ if (value != NULL) {
+ if (!join(buf, buf_size, value, "\n", desc1))
+ return 0;
+ BIO_printf(bio_err, "%s\n", value);
+ } else {
+ buf[0] = '\0';
+ if (!batch) {
+ if (!fgets(buf, buf_size, stdin))
+ return 0;
+ } else {
+ buf[0] = '\n';
+ buf[1] = '\0';
+ }
+ }
+
+ if (buf[0] == '\0')
+ return 0;
+ if (buf[0] == '\n') {
+ if ((def == NULL) || (def[0] == '\0'))
+ return 1;
+ if (!join(buf, buf_size, def, "\n", desc2))
+ return 0;
+ } else if ((buf[0] == '.') && (buf[1] == '\n')) {
+ return 1;
+ }
+
+ i = strlen(buf);
+ if (buf[i - 1] != '\n') {
+ BIO_printf(bio_err, "weird input :-(\n");
+ return 0;
+ }
+ buf[--i] = '\0';
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(buf, buf, i);
+#endif
+ if (!req_check_len(i, n_min, n_max)) {
+ if (batch || value)
+ return 0;
+ goto start;
+ }
+ return 2;
+}
+
+static int req_check_len(int len, int n_min, int n_max)
+{
+ if ((n_min > 0) && (len < n_min)) {
+ BIO_printf(bio_err,
+ "string is too short, it needs to be at least %d bytes long\n",
+ n_min);
+ return 0;
+ }
+ if ((n_max >= 0) && (len > n_max)) {
+ BIO_printf(bio_err,
+ "string is too long, it needs to be no more than %d bytes long\n",
+ n_max);
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if the end of a string matches 'end' */
+static int check_end(const char *str, const char *end)
+{
+ size_t elen, slen;
+ const char *tmp;
+
+ elen = strlen(end);
+ slen = strlen(str);
+ if (elen > slen)
+ return 1;
+ tmp = str + slen - elen;
+ return strcmp(tmp, end);
+}
+
+/*
+ * Merge the two strings together into the result buffer checking for
+ * overflow and producing an error message if there is.
+ */
+static int join(char buf[], size_t buf_size, const char *name,
+ const char *tail, const char *desc)
+{
+ const size_t name_len = strlen(name), tail_len = strlen(tail);
+
+ if (name_len + tail_len + 1 > buf_size) {
+ BIO_printf(bio_err, "%s '%s' too long\n", desc, name);
+ return 0;
+ }
+ memcpy(buf, name, name_len);
+ memcpy(buf + name_len, tail, tail_len + 1);
+ return 1;
+}
+
+static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
+ int *pkey_type, long *pkeylen,
+ char **palgnam, ENGINE *keygen_engine)
+{
+ EVP_PKEY_CTX *gctx = NULL;
+ EVP_PKEY *param = NULL;
+ long keylen = -1;
+ BIO *pbio = NULL;
+ const char *paramfile = NULL;
+
+ if (gstr == NULL) {
+ *pkey_type = EVP_PKEY_RSA;
+ keylen = *pkeylen;
+ } else if (gstr[0] >= '0' && gstr[0] <= '9') {
+ *pkey_type = EVP_PKEY_RSA;
+ keylen = atol(gstr);
+ *pkeylen = keylen;
+ } else if (strncmp(gstr, "param:", 6) == 0) {
+ paramfile = gstr + 6;
+ } else {
+ const char *p = strchr(gstr, ':');
+ int len;
+ ENGINE *tmpeng;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+
+ if (p != NULL)
+ len = p - gstr;
+ else
+ len = strlen(gstr);
+ /*
+ * The lookup of a the string will cover all engines so keep a note
+ * of the implementation.
+ */
+
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);
+
+ if (ameth == NULL) {
+ BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr);
+ return NULL;
+ }
+
+ EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth);
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(tmpeng);
+#endif
+ if (*pkey_type == EVP_PKEY_RSA) {
+ if (p != NULL) {
+ keylen = atol(p + 1);
+ *pkeylen = keylen;
+ } else {
+ keylen = *pkeylen;
+ }
+ } else if (p != NULL) {
+ paramfile = p + 1;
+ }
+ }
+
+ if (paramfile != NULL) {
+ pbio = BIO_new_file(paramfile, "r");
+ if (pbio == NULL) {
+ BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile);
+ return NULL;
+ }
+ param = PEM_read_bio_Parameters(pbio, NULL);
+
+ if (param == NULL) {
+ X509 *x;
+
+ (void)BIO_reset(pbio);
+ x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
+ if (x != NULL) {
+ param = X509_get_pubkey(x);
+ X509_free(x);
+ }
+ }
+
+ BIO_free(pbio);
+
+ if (param == NULL) {
+ BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile);
+ return NULL;
+ }
+ if (*pkey_type == -1) {
+ *pkey_type = EVP_PKEY_id(param);
+ } else if (*pkey_type != EVP_PKEY_base_id(param)) {
+ BIO_printf(bio_err, "Key Type does not match parameters\n");
+ EVP_PKEY_free(param);
+ return NULL;
+ }
+ }
+
+ if (palgnam != NULL) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ ENGINE *tmpeng;
+ const char *anam;
+
+ ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type);
+ if (ameth == NULL) {
+ BIO_puts(bio_err, "Internal error: can't find key algorithm\n");
+ return NULL;
+ }
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
+ *palgnam = OPENSSL_strdup(anam);
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(tmpeng);
+#endif
+ }
+
+ if (param != NULL) {
+ gctx = EVP_PKEY_CTX_new(param, keygen_engine);
+ *pkeylen = EVP_PKEY_bits(param);
+ EVP_PKEY_free(param);
+ } else {
+ gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine);
+ }
+
+ if (gctx == NULL) {
+ BIO_puts(bio_err, "Error allocating keygen context\n");
+ ERR_print_errors(bio_err);
+ return NULL;
+ }
+
+ if (EVP_PKEY_keygen_init(gctx) <= 0) {
+ BIO_puts(bio_err, "Error initializing keygen context\n");
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(gctx);
+ return NULL;
+ }
+#ifndef OPENSSL_NO_RSA
+ if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
+ if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
+ BIO_puts(bio_err, "Error setting RSA keysize\n");
+ ERR_print_errors(bio_err);
+ EVP_PKEY_CTX_free(gctx);
+ return NULL;
+ }
+ }
+#endif
+
+ return gctx;
+}
+
+static int genpkey_cb(EVP_PKEY_CTX *ctx)
+{
+ char c = '*';
+ BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
+ int p;
+ p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ if (p == 0)
+ c = '.';
+ if (p == 1)
+ c = '+';
+ if (p == 2)
+ c = '*';
+ if (p == 3)
+ c = '\n';
+ BIO_write(b, &c, 1);
+ (void)BIO_flush(b);
+ return 1;
+}
+
+static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
+ const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ EVP_PKEY_CTX *pkctx = NULL;
+ int i, def_nid;
+
+ if (ctx == NULL)
+ return 0;
+ /*
+ * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory
+ * for this algorithm.
+ */
+ if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2
+ && def_nid == NID_undef) {
+ /* The signing algorithm requires there to be no digest */
+ md = NULL;
+ }
+ if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
+ return 0;
+ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
+ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+ if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
+ BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+
+ rv = do_sign_init(mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_sign_ctx(x, mctx);
+ EVP_MD_CTX_free(mctx);
+ return rv > 0 ? 1 : 0;
+}
+
+int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ rv = do_sign_init(mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_REQ_sign_ctx(x, mctx);
+ EVP_MD_CTX_free(mctx);
+ return rv > 0 ? 1 : 0;
+}
+
+int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+ STACK_OF(OPENSSL_STRING) *sigopts)
+{
+ int rv;
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ rv = do_sign_init(mctx, pkey, md, sigopts);
+ if (rv > 0)
+ rv = X509_CRL_sign_ctx(x, mctx);
+ EVP_MD_CTX_free(mctx);
+ return rv > 0 ? 1 : 0;
+}
diff --git a/freebsd/crypto/openssl/apps/rsa.c b/freebsd/crypto/openssl/apps/rsa.c
new file mode 100644
index 00000000..eb4774bb
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/rsa.c
@@ -0,0 +1,318 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_RSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/rsa.h>
+# include <openssl/evp.h>
+# include <openssl/x509.h>
+# include <openssl/pem.h>
+# include <openssl/bn.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
+ OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN,
+ OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT,
+ /* Do not change the order here; see case statements below */
+ OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
+ OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER
+} OPTION_CHOICE;
+
+const OPTIONS rsa_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
+ {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
+ {"in", OPT_IN, 's', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
+ {"pubout", OPT_PUBOUT, '-', "Output a public key"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"},
+ {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"},
+ {"noout", OPT_NOOUT, '-', "Don't print key out"},
+ {"text", OPT_TEXT, '-', "Print the key in text"},
+ {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
+ {"check", OPT_CHECK, '-', "Verify key consistency"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
+ {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
+ {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
+ {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
+# endif
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int rsa_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ BIO *out = NULL;
+ RSA *rsa = NULL;
+ const EVP_CIPHER *enc = NULL;
+ char *infile = NULL, *outfile = NULL, *prog;
+ char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
+ int i, private = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0;
+ int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1;
+# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
+ int pvk_encr = 2;
+# endif
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, rsa_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(rsa_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PUBIN:
+ pubin = 1;
+ break;
+ case OPT_PUBOUT:
+ pubout = 1;
+ break;
+ case OPT_RSAPUBKEY_IN:
+ pubin = 2;
+ break;
+ case OPT_RSAPUBKEY_OUT:
+ pubout = 2;
+ break;
+ case OPT_PVK_STRONG: /* pvk_encr:= 2 */
+ case OPT_PVK_WEAK: /* pvk_encr:= 1 */
+ case OPT_PVK_NONE: /* pvk_encr:= 0 */
+# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
+ pvk_encr = (o - OPT_PVK_NONE);
+# endif
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_MODULUS:
+ modulus = 1;
+ break;
+ case OPT_CHECK:
+ check = 1;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &enc))
+ goto opthelp;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ private = (text && !pubin) || (!pubout && !noout) ? 1 : 0;
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+ if (check && pubin) {
+ BIO_printf(bio_err, "Only private keys can be checked\n");
+ goto end;
+ }
+
+ {
+ EVP_PKEY *pkey;
+
+ if (pubin) {
+ int tmpformat = -1;
+ if (pubin == 2) {
+ if (informat == FORMAT_PEM)
+ tmpformat = FORMAT_PEMRSA;
+ else if (informat == FORMAT_ASN1)
+ tmpformat = FORMAT_ASN1RSA;
+ } else {
+ tmpformat = informat;
+ }
+
+ pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key");
+ } else {
+ pkey = load_key(infile, informat, 1, passin, e, "Private Key");
+ }
+
+ if (pkey != NULL)
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ }
+
+ if (rsa == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ out = bio_open_owner(outfile, outformat, private);
+ if (out == NULL)
+ goto end;
+
+ if (text) {
+ assert(pubin || private);
+ if (!RSA_print(out, rsa, 0)) {
+ perror(outfile);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (modulus) {
+ const BIGNUM *n;
+ RSA_get0_key(rsa, &n, NULL, NULL);
+ BIO_printf(out, "Modulus=");
+ BN_print(out, n);
+ BIO_printf(out, "\n");
+ }
+
+ if (check) {
+ int r = RSA_check_key_ex(rsa, NULL);
+
+ if (r == 1) {
+ BIO_printf(out, "RSA key ok\n");
+ } else if (r == 0) {
+ unsigned long err;
+
+ while ((err = ERR_peek_error()) != 0 &&
+ ERR_GET_LIB(err) == ERR_LIB_RSA &&
+ ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX &&
+ ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) {
+ BIO_printf(out, "RSA key error: %s\n",
+ ERR_reason_error_string(err));
+ ERR_get_error(); /* remove err from error stack */
+ }
+ } else if (r == -1) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (noout) {
+ ret = 0;
+ goto end;
+ }
+ BIO_printf(bio_err, "writing RSA key\n");
+ if (outformat == FORMAT_ASN1) {
+ if (pubout || pubin) {
+ if (pubout == 2)
+ i = i2d_RSAPublicKey_bio(out, rsa);
+ else
+ i = i2d_RSA_PUBKEY_bio(out, rsa);
+ } else {
+ assert(private);
+ i = i2d_RSAPrivateKey_bio(out, rsa);
+ }
+ } else if (outformat == FORMAT_PEM) {
+ if (pubout || pubin) {
+ if (pubout == 2)
+ i = PEM_write_bio_RSAPublicKey(out, rsa);
+ else
+ i = PEM_write_bio_RSA_PUBKEY(out, rsa);
+ } else {
+ assert(private);
+ i = PEM_write_bio_RSAPrivateKey(out, rsa,
+ enc, NULL, 0, NULL, passout);
+ }
+# ifndef OPENSSL_NO_DSA
+ } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
+ EVP_PKEY *pk;
+ pk = EVP_PKEY_new();
+ if (pk == NULL)
+ goto end;
+
+ EVP_PKEY_set1_RSA(pk, rsa);
+ if (outformat == FORMAT_PVK) {
+ if (pubin) {
+ BIO_printf(bio_err, "PVK form impossible with public key input\n");
+ EVP_PKEY_free(pk);
+ goto end;
+ }
+ assert(private);
+# ifdef OPENSSL_NO_RC4
+ BIO_printf(bio_err, "PVK format not supported\n");
+ EVP_PKEY_free(pk);
+ goto end;
+# else
+ i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
+# endif
+ } else if (pubin || pubout) {
+ i = i2b_PublicKey_bio(out, pk);
+ } else {
+ assert(private);
+ i = i2b_PrivateKey_bio(out, pk);
+ }
+ EVP_PKEY_free(pk);
+# endif
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+ if (i <= 0) {
+ BIO_printf(bio_err, "unable to write key\n");
+ ERR_print_errors(bio_err);
+ } else {
+ ret = 0;
+ }
+ end:
+ release_engine(e);
+ BIO_free_all(out);
+ RSA_free(rsa);
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/rsautl.c b/freebsd/crypto/openssl/apps/rsautl.c
new file mode 100644
index 00000000..f5275636
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/rsautl.c
@@ -0,0 +1,284 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_RSA
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include "apps.h"
+# include "progs.h"
+# include <string.h>
+# include <openssl/err.h>
+# include <openssl/pem.h>
+# include <openssl/rsa.h>
+
+# define RSA_SIGN 1
+# define RSA_VERIFY 2
+# define RSA_ENCRYPT 3
+# define RSA_DECRYPT 4
+
+# define KEY_PRIVKEY 1
+# define KEY_PUBKEY 2
+# define KEY_CERT 3
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
+ OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
+ OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
+ OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS rsautl_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"inkey", OPT_INKEY, 's', "Input key"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
+ {"pubin", OPT_PUBIN, '-', "Input is an RSA public"},
+ {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
+ {"ssl", OPT_SSL, '-', "Use SSL v2 padding"},
+ {"raw", OPT_RAW, '-', "Use no padding"},
+ {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"},
+ {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"},
+ {"sign", OPT_SIGN, '-', "Sign with private key"},
+ {"verify", OPT_VERIFY, '-', "Verify with public key"},
+ {"asn1parse", OPT_ASN1PARSE, '-',
+ "Run output through asn1parse; useful with -verify"},
+ {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
+ {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"},
+ {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ OPT_R_OPTIONS,
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int rsautl_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+ RSA *rsa = NULL;
+ X509 *x;
+ char *infile = NULL, *outfile = NULL, *keyfile = NULL;
+ char *passinarg = NULL, *passin = NULL, *prog;
+ char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
+ unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING;
+ int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1;
+ int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, rsautl_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(rsautl_options);
+ ret = 0;
+ goto end;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_ASN1PARSE:
+ asn1parse = 1;
+ break;
+ case OPT_HEXDUMP:
+ hexdump = 1;
+ break;
+ case OPT_RAW:
+ pad = RSA_NO_PADDING;
+ break;
+ case OPT_OAEP:
+ pad = RSA_PKCS1_OAEP_PADDING;
+ break;
+ case OPT_SSL:
+ pad = RSA_SSLV23_PADDING;
+ break;
+ case OPT_PKCS:
+ pad = RSA_PKCS1_PADDING;
+ break;
+ case OPT_X931:
+ pad = RSA_X931_PADDING;
+ break;
+ case OPT_SIGN:
+ rsa_mode = RSA_SIGN;
+ need_priv = 1;
+ break;
+ case OPT_VERIFY:
+ rsa_mode = RSA_VERIFY;
+ break;
+ case OPT_REV:
+ rev = 1;
+ break;
+ case OPT_ENCRYPT:
+ rsa_mode = RSA_ENCRYPT;
+ break;
+ case OPT_DECRYPT:
+ rsa_mode = RSA_DECRYPT;
+ need_priv = 1;
+ break;
+ case OPT_PUBIN:
+ key_type = KEY_PUBKEY;
+ break;
+ case OPT_CERTIN:
+ key_type = KEY_CERT;
+ break;
+ case OPT_INKEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (need_priv && (key_type != KEY_PRIVKEY)) {
+ BIO_printf(bio_err, "A private key is needed for this operation\n");
+ goto end;
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ switch (key_type) {
+ case KEY_PRIVKEY:
+ pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
+ break;
+
+ case KEY_PUBKEY:
+ pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key");
+ break;
+
+ case KEY_CERT:
+ x = load_cert(keyfile, keyformat, "Certificate");
+ if (x) {
+ pkey = X509_get_pubkey(x);
+ X509_free(x);
+ }
+ break;
+ }
+
+ if (pkey == NULL)
+ return 1;
+
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+
+ if (rsa == NULL) {
+ BIO_printf(bio_err, "Error getting RSA key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ in = bio_open_default(infile, 'r', FORMAT_BINARY);
+ if (in == NULL)
+ goto end;
+ out = bio_open_default(outfile, 'w', FORMAT_BINARY);
+ if (out == NULL)
+ goto end;
+
+ keysize = RSA_size(rsa);
+
+ rsa_in = app_malloc(keysize * 2, "hold rsa key");
+ rsa_out = app_malloc(keysize, "output rsa key");
+
+ /* Read the input data */
+ rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
+ if (rsa_inlen < 0) {
+ BIO_printf(bio_err, "Error reading input Data\n");
+ goto end;
+ }
+ if (rev) {
+ int i;
+ unsigned char ctmp;
+ for (i = 0; i < rsa_inlen / 2; i++) {
+ ctmp = rsa_in[i];
+ rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
+ rsa_in[rsa_inlen - 1 - i] = ctmp;
+ }
+ }
+ switch (rsa_mode) {
+
+ case RSA_VERIFY:
+ rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ break;
+
+ case RSA_SIGN:
+ rsa_outlen =
+ RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ break;
+
+ case RSA_ENCRYPT:
+ rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ break;
+
+ case RSA_DECRYPT:
+ rsa_outlen =
+ RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
+ break;
+ }
+
+ if (rsa_outlen < 0) {
+ BIO_printf(bio_err, "RSA operation error\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ if (asn1parse) {
+ if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
+ ERR_print_errors(bio_err);
+ }
+ } else if (hexdump) {
+ BIO_dump(out, (char *)rsa_out, rsa_outlen);
+ } else {
+ BIO_write(out, rsa_out, rsa_outlen);
+ }
+ end:
+ RSA_free(rsa);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free_all(out);
+ OPENSSL_free(rsa_in);
+ OPENSSL_free(rsa_out);
+ OPENSSL_free(passin);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/s_apps.h b/freebsd/crypto/openssl/apps/s_apps.h
new file mode 100644
index 00000000..0a3bc962
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_apps.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+# include <conio.h>
+#endif
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
+# define _kbhit kbhit
+#endif
+
+#define PORT "4433"
+#define PROTOCOL "tcp"
+
+typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
+int do_server(int *accept_sock, const char *host, const char *port,
+ int family, int type, int protocol, do_server_cb cb,
+ unsigned char *context, int naccept, BIO *bio_s_out);
+#ifdef HEADER_X509_H
+int verify_callback(int ok, X509_STORE_CTX *ctx);
+#endif
+#ifdef HEADER_SSL_H
+int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+ STACK_OF(X509) *chain, int build_chain);
+int ssl_print_sigalgs(BIO *out, SSL *s);
+int ssl_print_point_formats(BIO *out, SSL *s);
+int ssl_print_groups(BIO *out, SSL *s, int noshared);
+#endif
+int ssl_print_tmp_key(BIO *out, SSL *s);
+int init_client(int *sock, const char *host, const char *port,
+ const char *bindhost, const char *bindport,
+ int family, int type, int protocol);
+int should_retry(int i);
+
+long bio_dump_callback(BIO *bio, int cmd, const char *argp,
+ int argi, long argl, long ret);
+
+#ifdef HEADER_SSL_H
+void apps_ssl_info_callback(const SSL *s, int where, int ret);
+void msg_cb(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg);
+void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data,
+ int len, void *arg);
+#endif
+
+int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len);
+int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len);
+
+#ifdef __VMS /* 31 char symbol name limit */
+# define generate_stateless_cookie_callback generate_stateless_cookie_cb
+# define verify_stateless_cookie_callback verify_stateless_cookie_cb
+#endif
+
+int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
+ size_t *cookie_len);
+int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ size_t cookie_len);
+
+typedef struct ssl_excert_st SSL_EXCERT;
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
+void ssl_excert_free(SSL_EXCERT *exc);
+int args_excert(int option, SSL_EXCERT **pexc);
+int load_excert(SSL_EXCERT **pexc);
+void print_verify_detail(SSL *s, BIO *bio);
+void print_ssl_summary(SSL *s);
+#ifdef HEADER_SSL_H
+int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx);
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls,
+ int crl_download);
+int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath,
+ const char *vfyCAfile, const char *chCApath,
+ const char *chCAfile, STACK_OF(X509_CRL) *crls,
+ int crl_download);
+void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose);
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file);
+void print_ca_names(BIO *bio, SSL *s);
+#endif
diff --git a/freebsd/crypto/openssl/apps/s_cb.c b/freebsd/crypto/openssl/apps/s_cb.c
new file mode 100644
index 00000000..ace2df34
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_cb.c
@@ -0,0 +1,1483 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* callback functions used by s_client, s_server, and s_time */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for memcpy() and strcmp() */
+#include "apps.h"
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+#endif
+#include "s_apps.h"
+
+#define COOKIE_SECRET_LENGTH 16
+
+VERIFY_CB_ARGS verify_args = { 0, 0, X509_V_OK, 0 };
+
+#ifndef OPENSSL_NO_SOCK
+static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
+static int cookie_initialized = 0;
+#endif
+static BIO *bio_keylog = NULL;
+
+static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
+{
+ for ( ; list->name; ++list)
+ if (list->retval == val)
+ return list->name;
+ return def;
+}
+
+int verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ X509 *err_cert;
+ int err, depth;
+
+ err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+ depth = X509_STORE_CTX_get_error_depth(ctx);
+
+ if (!verify_args.quiet || !ok) {
+ BIO_printf(bio_err, "depth=%d ", depth);
+ if (err_cert != NULL) {
+ X509_NAME_print_ex(bio_err,
+ X509_get_subject_name(err_cert),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ } else {
+ BIO_puts(bio_err, "<no cert>\n");
+ }
+ }
+ if (!ok) {
+ BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
+ X509_verify_cert_error_string(err));
+ if (verify_args.depth >= depth) {
+ if (!verify_args.return_error)
+ ok = 1;
+ verify_args.error = err;
+ } else {
+ ok = 0;
+ verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (err) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ BIO_puts(bio_err, "issuer= ");
+ X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ break;
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ BIO_printf(bio_err, "notBefore=");
+ ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
+ BIO_printf(bio_err, "\n");
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ BIO_printf(bio_err, "notAfter=");
+ ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
+ BIO_printf(bio_err, "\n");
+ break;
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ if (!verify_args.quiet)
+ policies_print(ctx);
+ break;
+ }
+ if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
+ policies_print(ctx);
+ if (ok && !verify_args.quiet)
+ BIO_printf(bio_err, "verify return:%d\n", ok);
+ return ok;
+}
+
+int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
+{
+ if (cert_file != NULL) {
+ if (SSL_CTX_use_certificate_file(ctx, cert_file,
+ SSL_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "unable to get certificate from '%s'\n",
+ cert_file);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (key_file == NULL)
+ key_file = cert_file;
+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "unable to get private key from '%s'\n",
+ key_file);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /*
+ * If we are using DSA, we can copy the parameters from the private
+ * key
+ */
+
+ /*
+ * Now we know that a key and cert have been set against the SSL
+ * context
+ */
+ if (!SSL_CTX_check_private_key(ctx)) {
+ BIO_printf(bio_err,
+ "Private key does not match the certificate public key\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+ STACK_OF(X509) *chain, int build_chain)
+{
+ int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
+ if (cert == NULL)
+ return 1;
+ if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
+ BIO_printf(bio_err, "error setting certificate\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
+ BIO_printf(bio_err, "error setting private key\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /*
+ * Now we know that a key and cert have been set against the SSL context
+ */
+ if (!SSL_CTX_check_private_key(ctx)) {
+ BIO_printf(bio_err,
+ "Private key does not match the certificate public key\n");
+ return 0;
+ }
+ if (chain && !SSL_CTX_set1_chain(ctx, chain)) {
+ BIO_printf(bio_err, "error setting certificate chain\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) {
+ BIO_printf(bio_err, "error building certificate chain\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ return 1;
+}
+
+static STRINT_PAIR cert_type_list[] = {
+ {"RSA sign", TLS_CT_RSA_SIGN},
+ {"DSA sign", TLS_CT_DSS_SIGN},
+ {"RSA fixed DH", TLS_CT_RSA_FIXED_DH},
+ {"DSS fixed DH", TLS_CT_DSS_FIXED_DH},
+ {"ECDSA sign", TLS_CT_ECDSA_SIGN},
+ {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH},
+ {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH},
+ {"GOST01 Sign", TLS_CT_GOST01_SIGN},
+ {NULL}
+};
+
+static void ssl_print_client_cert_types(BIO *bio, SSL *s)
+{
+ const unsigned char *p;
+ int i;
+ int cert_type_num = SSL_get0_certificate_types(s, &p);
+ if (!cert_type_num)
+ return;
+ BIO_puts(bio, "Client Certificate Types: ");
+ for (i = 0; i < cert_type_num; i++) {
+ unsigned char cert_type = p[i];
+ const char *cname = lookup((int)cert_type, cert_type_list, NULL);
+
+ if (i)
+ BIO_puts(bio, ", ");
+ if (cname != NULL)
+ BIO_puts(bio, cname);
+ else
+ BIO_printf(bio, "UNKNOWN (%d),", cert_type);
+ }
+ BIO_puts(bio, "\n");
+}
+
+static const char *get_sigtype(int nid)
+{
+ switch (nid) {
+ case EVP_PKEY_RSA:
+ return "RSA";
+
+ case EVP_PKEY_RSA_PSS:
+ return "RSA-PSS";
+
+ case EVP_PKEY_DSA:
+ return "DSA";
+
+ case EVP_PKEY_EC:
+ return "ECDSA";
+
+ case NID_ED25519:
+ return "Ed25519";
+
+ case NID_ED448:
+ return "Ed448";
+
+ case NID_id_GostR3410_2001:
+ return "gost2001";
+
+ case NID_id_GostR3410_2012_256:
+ return "gost2012_256";
+
+ case NID_id_GostR3410_2012_512:
+ return "gost2012_512";
+
+ default:
+ return NULL;
+ }
+}
+
+static int do_print_sigalgs(BIO *out, SSL *s, int shared)
+{
+ int i, nsig, client;
+ client = SSL_is_server(s) ? 0 : 1;
+ if (shared)
+ nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
+ else
+ nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+ if (nsig == 0)
+ return 1;
+
+ if (shared)
+ BIO_puts(out, "Shared ");
+
+ if (client)
+ BIO_puts(out, "Requested ");
+ BIO_puts(out, "Signature Algorithms: ");
+ for (i = 0; i < nsig; i++) {
+ int hash_nid, sign_nid;
+ unsigned char rhash, rsign;
+ const char *sstr = NULL;
+ if (shared)
+ SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+ &rsign, &rhash);
+ else
+ SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
+ if (i)
+ BIO_puts(out, ":");
+ sstr = get_sigtype(sign_nid);
+ if (sstr)
+ BIO_printf(out, "%s", sstr);
+ else
+ BIO_printf(out, "0x%02X", (int)rsign);
+ if (hash_nid != NID_undef)
+ BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid));
+ else if (sstr == NULL)
+ BIO_printf(out, "+0x%02X", (int)rhash);
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+int ssl_print_sigalgs(BIO *out, SSL *s)
+{
+ int nid;
+ if (!SSL_is_server(s))
+ ssl_print_client_cert_types(out, s);
+ do_print_sigalgs(out, s, 0);
+ do_print_sigalgs(out, s, 1);
+ if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef)
+ BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid));
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int ssl_print_point_formats(BIO *out, SSL *s)
+{
+ int i, nformats;
+ const char *pformats;
+ nformats = SSL_get0_ec_point_formats(s, &pformats);
+ if (nformats <= 0)
+ return 1;
+ BIO_puts(out, "Supported Elliptic Curve Point Formats: ");
+ for (i = 0; i < nformats; i++, pformats++) {
+ if (i)
+ BIO_puts(out, ":");
+ switch (*pformats) {
+ case TLSEXT_ECPOINTFORMAT_uncompressed:
+ BIO_puts(out, "uncompressed");
+ break;
+
+ case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime:
+ BIO_puts(out, "ansiX962_compressed_prime");
+ break;
+
+ case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2:
+ BIO_puts(out, "ansiX962_compressed_char2");
+ break;
+
+ default:
+ BIO_printf(out, "unknown(%d)", (int)*pformats);
+ break;
+
+ }
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+int ssl_print_groups(BIO *out, SSL *s, int noshared)
+{
+ int i, ngroups, *groups, nid;
+ const char *gname;
+
+ ngroups = SSL_get1_groups(s, NULL);
+ if (ngroups <= 0)
+ return 1;
+ groups = app_malloc(ngroups * sizeof(int), "groups to print");
+ SSL_get1_groups(s, groups);
+
+ BIO_puts(out, "Supported Elliptic Groups: ");
+ for (i = 0; i < ngroups; i++) {
+ if (i)
+ BIO_puts(out, ":");
+ nid = groups[i];
+ /* If unrecognised print out hex version */
+ if (nid & TLSEXT_nid_unknown) {
+ BIO_printf(out, "0x%04X", nid & 0xFFFF);
+ } else {
+ /* TODO(TLS1.3): Get group name here */
+ /* Use NIST name for curve if it exists */
+ gname = EC_curve_nid2nist(nid);
+ if (gname == NULL)
+ gname = OBJ_nid2sn(nid);
+ BIO_printf(out, "%s", gname);
+ }
+ }
+ OPENSSL_free(groups);
+ if (noshared) {
+ BIO_puts(out, "\n");
+ return 1;
+ }
+ BIO_puts(out, "\nShared Elliptic groups: ");
+ ngroups = SSL_get_shared_group(s, -1);
+ for (i = 0; i < ngroups; i++) {
+ if (i)
+ BIO_puts(out, ":");
+ nid = SSL_get_shared_group(s, i);
+ /* TODO(TLS1.3): Convert for DH groups */
+ gname = EC_curve_nid2nist(nid);
+ if (gname == NULL)
+ gname = OBJ_nid2sn(nid);
+ BIO_printf(out, "%s", gname);
+ }
+ if (ngroups == 0)
+ BIO_puts(out, "NONE");
+ BIO_puts(out, "\n");
+ return 1;
+}
+#endif
+
+int ssl_print_tmp_key(BIO *out, SSL *s)
+{
+ EVP_PKEY *key;
+
+ if (!SSL_get_peer_tmp_key(s, &key))
+ return 1;
+ BIO_puts(out, "Server Temp Key: ");
+ switch (EVP_PKEY_id(key)) {
+ case EVP_PKEY_RSA:
+ BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key));
+ break;
+
+ case EVP_PKEY_DH:
+ BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
+ break;
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ {
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
+ int nid;
+ const char *cname;
+ nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ EC_KEY_free(ec);
+ cname = EC_curve_nid2nist(nid);
+ if (cname == NULL)
+ cname = OBJ_nid2sn(nid);
+ BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
+ }
+ break;
+#endif
+ default:
+ BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)),
+ EVP_PKEY_bits(key));
+ }
+ EVP_PKEY_free(key);
+ return 1;
+}
+
+long bio_dump_callback(BIO *bio, int cmd, const char *argp,
+ int argi, long argl, long ret)
+{
+ BIO *out;
+
+ out = (BIO *)BIO_get_callback_arg(bio);
+ if (out == NULL)
+ return ret;
+
+ if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
+ BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
+ (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
+ BIO_dump(out, argp, (int)ret);
+ return ret;
+ } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
+ BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
+ (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
+ BIO_dump(out, argp, (int)ret);
+ }
+ return ret;
+}
+
+void apps_ssl_info_callback(const SSL *s, int where, int ret)
+{
+ const char *str;
+ int w;
+
+ w = where & ~SSL_ST_MASK;
+
+ if (w & SSL_ST_CONNECT)
+ str = "SSL_connect";
+ else if (w & SSL_ST_ACCEPT)
+ str = "SSL_accept";
+ else
+ str = "undefined";
+
+ if (where & SSL_CB_LOOP) {
+ BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
+ } else if (where & SSL_CB_ALERT) {
+ str = (where & SSL_CB_READ) ? "read" : "write";
+ BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n",
+ str,
+ SSL_alert_type_string_long(ret),
+ SSL_alert_desc_string_long(ret));
+ } else if (where & SSL_CB_EXIT) {
+ if (ret == 0)
+ BIO_printf(bio_err, "%s:failed in %s\n",
+ str, SSL_state_string_long(s));
+ else if (ret < 0)
+ BIO_printf(bio_err, "%s:error in %s\n",
+ str, SSL_state_string_long(s));
+ }
+}
+
+static STRINT_PAIR ssl_versions[] = {
+ {"SSL 3.0", SSL3_VERSION},
+ {"TLS 1.0", TLS1_VERSION},
+ {"TLS 1.1", TLS1_1_VERSION},
+ {"TLS 1.2", TLS1_2_VERSION},
+ {"TLS 1.3", TLS1_3_VERSION},
+ {"DTLS 1.0", DTLS1_VERSION},
+ {"DTLS 1.0 (bad)", DTLS1_BAD_VER},
+ {NULL}
+};
+
+static STRINT_PAIR alert_types[] = {
+ {" close_notify", 0},
+ {" end_of_early_data", 1},
+ {" unexpected_message", 10},
+ {" bad_record_mac", 20},
+ {" decryption_failed", 21},
+ {" record_overflow", 22},
+ {" decompression_failure", 30},
+ {" handshake_failure", 40},
+ {" bad_certificate", 42},
+ {" unsupported_certificate", 43},
+ {" certificate_revoked", 44},
+ {" certificate_expired", 45},
+ {" certificate_unknown", 46},
+ {" illegal_parameter", 47},
+ {" unknown_ca", 48},
+ {" access_denied", 49},
+ {" decode_error", 50},
+ {" decrypt_error", 51},
+ {" export_restriction", 60},
+ {" protocol_version", 70},
+ {" insufficient_security", 71},
+ {" internal_error", 80},
+ {" inappropriate_fallback", 86},
+ {" user_canceled", 90},
+ {" no_renegotiation", 100},
+ {" missing_extension", 109},
+ {" unsupported_extension", 110},
+ {" certificate_unobtainable", 111},
+ {" unrecognized_name", 112},
+ {" bad_certificate_status_response", 113},
+ {" bad_certificate_hash_value", 114},
+ {" unknown_psk_identity", 115},
+ {" certificate_required", 116},
+ {NULL}
+};
+
+static STRINT_PAIR handshakes[] = {
+ {", HelloRequest", SSL3_MT_HELLO_REQUEST},
+ {", ClientHello", SSL3_MT_CLIENT_HELLO},
+ {", ServerHello", SSL3_MT_SERVER_HELLO},
+ {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST},
+ {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET},
+ {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA},
+ {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS},
+ {", Certificate", SSL3_MT_CERTIFICATE},
+ {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE},
+ {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST},
+ {", ServerHelloDone", SSL3_MT_SERVER_DONE},
+ {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY},
+ {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE},
+ {", Finished", SSL3_MT_FINISHED},
+ {", CertificateUrl", SSL3_MT_CERTIFICATE_URL},
+ {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS},
+ {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA},
+ {", KeyUpdate", SSL3_MT_KEY_UPDATE},
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {", NextProto", SSL3_MT_NEXT_PROTO},
+#endif
+ {", MessageHash", SSL3_MT_MESSAGE_HASH},
+ {NULL}
+};
+
+void msg_cb(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg)
+{
+ BIO *bio = arg;
+ const char *str_write_p = write_p ? ">>>" : "<<<";
+ const char *str_version = lookup(version, ssl_versions, "???");
+ const char *str_content_type = "", *str_details1 = "", *str_details2 = "";
+ const unsigned char* bp = buf;
+
+ if (version == SSL3_VERSION ||
+ version == TLS1_VERSION ||
+ version == TLS1_1_VERSION ||
+ version == TLS1_2_VERSION ||
+ version == TLS1_3_VERSION ||
+ version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
+ switch (content_type) {
+ case 20:
+ str_content_type = ", ChangeCipherSpec";
+ break;
+ case 21:
+ str_content_type = ", Alert";
+ str_details1 = ", ???";
+ if (len == 2) {
+ switch (bp[0]) {
+ case 1:
+ str_details1 = ", warning";
+ break;
+ case 2:
+ str_details1 = ", fatal";
+ break;
+ }
+ str_details2 = lookup((int)bp[1], alert_types, " ???");
+ }
+ break;
+ case 22:
+ str_content_type = ", Handshake";
+ str_details1 = "???";
+ if (len > 0)
+ str_details1 = lookup((int)bp[0], handshakes, "???");
+ break;
+ case 23:
+ str_content_type = ", ApplicationData";
+ break;
+#ifndef OPENSSL_NO_HEARTBEATS
+ case 24:
+ str_details1 = ", Heartbeat";
+
+ if (len > 0) {
+ switch (bp[0]) {
+ case 1:
+ str_details1 = ", HeartbeatRequest";
+ break;
+ case 2:
+ str_details1 = ", HeartbeatResponse";
+ break;
+ }
+ }
+ break;
+#endif
+ }
+ }
+
+ BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version,
+ str_content_type, (unsigned long)len, str_details1,
+ str_details2);
+
+ if (len > 0) {
+ size_t num, i;
+
+ BIO_printf(bio, " ");
+ num = len;
+ for (i = 0; i < num; i++) {
+ if (i % 16 == 0 && i > 0)
+ BIO_printf(bio, "\n ");
+ BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]);
+ }
+ if (i < len)
+ BIO_printf(bio, " ...");
+ BIO_printf(bio, "\n");
+ }
+ (void)BIO_flush(bio);
+}
+
+static STRINT_PAIR tlsext_types[] = {
+ {"server name", TLSEXT_TYPE_server_name},
+ {"max fragment length", TLSEXT_TYPE_max_fragment_length},
+ {"client certificate URL", TLSEXT_TYPE_client_certificate_url},
+ {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys},
+ {"truncated HMAC", TLSEXT_TYPE_truncated_hmac},
+ {"status request", TLSEXT_TYPE_status_request},
+ {"user mapping", TLSEXT_TYPE_user_mapping},
+ {"client authz", TLSEXT_TYPE_client_authz},
+ {"server authz", TLSEXT_TYPE_server_authz},
+ {"cert type", TLSEXT_TYPE_cert_type},
+ {"supported_groups", TLSEXT_TYPE_supported_groups},
+ {"EC point formats", TLSEXT_TYPE_ec_point_formats},
+ {"SRP", TLSEXT_TYPE_srp},
+ {"signature algorithms", TLSEXT_TYPE_signature_algorithms},
+ {"use SRTP", TLSEXT_TYPE_use_srtp},
+ {"heartbeat", TLSEXT_TYPE_heartbeat},
+ {"session ticket", TLSEXT_TYPE_session_ticket},
+ {"renegotiation info", TLSEXT_TYPE_renegotiate},
+ {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
+ {"TLS padding", TLSEXT_TYPE_padding},
+#ifdef TLSEXT_TYPE_next_proto_neg
+ {"next protocol", TLSEXT_TYPE_next_proto_neg},
+#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+ {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac},
+#endif
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+ {"application layer protocol negotiation",
+ TLSEXT_TYPE_application_layer_protocol_negotiation},
+#endif
+#ifdef TLSEXT_TYPE_extended_master_secret
+ {"extended master secret", TLSEXT_TYPE_extended_master_secret},
+#endif
+ {"key share", TLSEXT_TYPE_key_share},
+ {"supported versions", TLSEXT_TYPE_supported_versions},
+ {"psk", TLSEXT_TYPE_psk},
+ {"psk kex modes", TLSEXT_TYPE_psk_kex_modes},
+ {"certificate authorities", TLSEXT_TYPE_certificate_authorities},
+ {"post handshake auth", TLSEXT_TYPE_post_handshake_auth},
+ {NULL}
+};
+
+void tlsext_cb(SSL *s, int client_server, int type,
+ const unsigned char *data, int len, void *arg)
+{
+ BIO *bio = arg;
+ const char *extname = lookup(type, tlsext_types, "unknown");
+
+ BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
+ client_server ? "server" : "client", extname, type, len);
+ BIO_dump(bio, (const char *)data, len);
+ (void)BIO_flush(bio);
+}
+
+#ifndef OPENSSL_NO_SOCK
+int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len)
+{
+ unsigned char *buffer;
+ size_t length = 0;
+ unsigned short port;
+ BIO_ADDR *lpeer = NULL, *peer = NULL;
+
+ /* Initialize a random secret */
+ if (!cookie_initialized) {
+ if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) {
+ BIO_printf(bio_err, "error setting random cookie secret\n");
+ return 0;
+ }
+ cookie_initialized = 1;
+ }
+
+ if (SSL_is_dtls(ssl)) {
+ lpeer = peer = BIO_ADDR_new();
+ if (peer == NULL) {
+ BIO_printf(bio_err, "memory full\n");
+ return 0;
+ }
+
+ /* Read peer information */
+ (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer);
+ } else {
+ peer = ourpeer;
+ }
+
+ /* Create buffer with peer's address and port */
+ if (!BIO_ADDR_rawaddress(peer, NULL, &length)) {
+ BIO_printf(bio_err, "Failed getting peer address\n");
+ return 0;
+ }
+ OPENSSL_assert(length != 0);
+ port = BIO_ADDR_rawport(peer);
+ length += sizeof(port);
+ buffer = app_malloc(length, "cookie generate buffer");
+
+ memcpy(buffer, &port, sizeof(port));
+ BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL);
+
+ /* Calculate HMAC of buffer using the secret */
+ HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
+ buffer, length, cookie, cookie_len);
+
+ OPENSSL_free(buffer);
+ BIO_ADDR_free(lpeer);
+
+ return 1;
+}
+
+int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len)
+{
+ unsigned char result[EVP_MAX_MD_SIZE];
+ unsigned int resultlength;
+
+ /* Note: we check cookie_initialized because if it's not,
+ * it cannot be valid */
+ if (cookie_initialized
+ && generate_cookie_callback(ssl, result, &resultlength)
+ && cookie_len == resultlength
+ && memcmp(result, cookie, resultlength) == 0)
+ return 1;
+
+ return 0;
+}
+
+int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
+ size_t *cookie_len)
+{
+ unsigned int temp;
+ int res = generate_cookie_callback(ssl, cookie, &temp);
+ *cookie_len = temp;
+ return res;
+}
+
+int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ size_t cookie_len)
+{
+ return verify_cookie_callback(ssl, cookie, cookie_len);
+}
+
+#endif
+
+/*
+ * Example of extended certificate handling. Where the standard support of
+ * one certificate per algorithm is not sufficient an application can decide
+ * which certificate(s) to use at runtime based on whatever criteria it deems
+ * appropriate.
+ */
+
+/* Linked list of certificates, keys and chains */
+struct ssl_excert_st {
+ int certform;
+ const char *certfile;
+ int keyform;
+ const char *keyfile;
+ const char *chainfile;
+ X509 *cert;
+ EVP_PKEY *key;
+ STACK_OF(X509) *chain;
+ int build_chain;
+ struct ssl_excert_st *next, *prev;
+};
+
+static STRINT_PAIR chain_flags[] = {
+ {"Overall Validity", CERT_PKEY_VALID},
+ {"Sign with EE key", CERT_PKEY_SIGN},
+ {"EE signature", CERT_PKEY_EE_SIGNATURE},
+ {"CA signature", CERT_PKEY_CA_SIGNATURE},
+ {"EE key parameters", CERT_PKEY_EE_PARAM},
+ {"CA key parameters", CERT_PKEY_CA_PARAM},
+ {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN},
+ {"Issuer Name", CERT_PKEY_ISSUER_NAME},
+ {"Certificate Type", CERT_PKEY_CERT_TYPE},
+ {NULL}
+};
+
+static void print_chain_flags(SSL *s, int flags)
+{
+ STRINT_PAIR *pp;
+
+ for (pp = chain_flags; pp->name; ++pp)
+ BIO_printf(bio_err, "\t%s: %s\n",
+ pp->name,
+ (flags & pp->retval) ? "OK" : "NOT OK");
+ BIO_printf(bio_err, "\tSuite B: ");
+ if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
+ BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
+ else
+ BIO_printf(bio_err, "not tested\n");
+}
+
+/*
+ * Very basic selection callback: just use any certificate chain reported as
+ * valid. More sophisticated could prioritise according to local policy.
+ */
+static int set_cert_cb(SSL *ssl, void *arg)
+{
+ int i, rv;
+ SSL_EXCERT *exc = arg;
+#ifdef CERT_CB_TEST_RETRY
+ static int retry_cnt;
+ if (retry_cnt < 5) {
+ retry_cnt++;
+ BIO_printf(bio_err,
+ "Certificate callback retry test: count %d\n",
+ retry_cnt);
+ return -1;
+ }
+#endif
+ SSL_certs_clear(ssl);
+
+ if (exc == NULL)
+ return 1;
+
+ /*
+ * Go to end of list and traverse backwards since we prepend newer
+ * entries this retains the original order.
+ */
+ while (exc->next != NULL)
+ exc = exc->next;
+
+ i = 0;
+
+ while (exc != NULL) {
+ i++;
+ rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
+ BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
+ X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
+ get_nameopt());
+ BIO_puts(bio_err, "\n");
+ print_chain_flags(ssl, rv);
+ if (rv & CERT_PKEY_VALID) {
+ if (!SSL_use_certificate(ssl, exc->cert)
+ || !SSL_use_PrivateKey(ssl, exc->key)) {
+ return 0;
+ }
+ /*
+ * NB: we wouldn't normally do this as it is not efficient
+ * building chains on each connection better to cache the chain
+ * in advance.
+ */
+ if (exc->build_chain) {
+ if (!SSL_build_cert_chain(ssl, 0))
+ return 0;
+ } else if (exc->chain != NULL) {
+ SSL_set1_chain(ssl, exc->chain);
+ }
+ }
+ exc = exc->prev;
+ }
+ return 1;
+}
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc)
+{
+ SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc);
+}
+
+static int ssl_excert_prepend(SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert");
+
+ memset(exc, 0, sizeof(*exc));
+
+ exc->next = *pexc;
+ *pexc = exc;
+
+ if (exc->next) {
+ exc->certform = exc->next->certform;
+ exc->keyform = exc->next->keyform;
+ exc->next->prev = exc;
+ } else {
+ exc->certform = FORMAT_PEM;
+ exc->keyform = FORMAT_PEM;
+ }
+ return 1;
+
+}
+
+void ssl_excert_free(SSL_EXCERT *exc)
+{
+ SSL_EXCERT *curr;
+
+ if (exc == NULL)
+ return;
+ while (exc) {
+ X509_free(exc->cert);
+ EVP_PKEY_free(exc->key);
+ sk_X509_pop_free(exc->chain, X509_free);
+ curr = exc;
+ exc = exc->next;
+ OPENSSL_free(curr);
+ }
+}
+
+int load_excert(SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = *pexc;
+ if (exc == NULL)
+ return 1;
+ /* If nothing in list, free and set to NULL */
+ if (exc->certfile == NULL && exc->next == NULL) {
+ ssl_excert_free(exc);
+ *pexc = NULL;
+ return 1;
+ }
+ for (; exc; exc = exc->next) {
+ if (exc->certfile == NULL) {
+ BIO_printf(bio_err, "Missing filename\n");
+ return 0;
+ }
+ exc->cert = load_cert(exc->certfile, exc->certform,
+ "Server Certificate");
+ if (exc->cert == NULL)
+ return 0;
+ if (exc->keyfile != NULL) {
+ exc->key = load_key(exc->keyfile, exc->keyform,
+ 0, NULL, NULL, "Server Key");
+ } else {
+ exc->key = load_key(exc->certfile, exc->certform,
+ 0, NULL, NULL, "Server Key");
+ }
+ if (exc->key == NULL)
+ return 0;
+ if (exc->chainfile != NULL) {
+ if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL,
+ "Server Chain"))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+enum range { OPT_X_ENUM };
+
+int args_excert(int opt, SSL_EXCERT **pexc)
+{
+ SSL_EXCERT *exc = *pexc;
+
+ assert(opt > OPT_X__FIRST);
+ assert(opt < OPT_X__LAST);
+
+ if (exc == NULL) {
+ if (!ssl_excert_prepend(&exc)) {
+ BIO_printf(bio_err, " %s: Error initialising xcert\n",
+ opt_getprog());
+ goto err;
+ }
+ *pexc = exc;
+ }
+
+ switch ((enum range)opt) {
+ case OPT_X__FIRST:
+ case OPT_X__LAST:
+ return 0;
+ case OPT_X_CERT:
+ if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) {
+ BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
+ goto err;
+ }
+ *pexc = exc;
+ exc->certfile = opt_arg();
+ break;
+ case OPT_X_KEY:
+ if (exc->keyfile != NULL) {
+ BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog());
+ goto err;
+ }
+ exc->keyfile = opt_arg();
+ break;
+ case OPT_X_CHAIN:
+ if (exc->chainfile != NULL) {
+ BIO_printf(bio_err, "%s: Chain already specified\n",
+ opt_getprog());
+ goto err;
+ }
+ exc->chainfile = opt_arg();
+ break;
+ case OPT_X_CHAIN_BUILD:
+ exc->build_chain = 1;
+ break;
+ case OPT_X_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform))
+ return 0;
+ break;
+ case OPT_X_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform))
+ return 0;
+ break;
+ }
+ return 1;
+
+ err:
+ ERR_print_errors(bio_err);
+ ssl_excert_free(exc);
+ *pexc = NULL;
+ return 0;
+}
+
+static void print_raw_cipherlist(SSL *s)
+{
+ const unsigned char *rlist;
+ static const unsigned char scsv_id[] = { 0, 0xFF };
+ size_t i, rlistlen, num;
+ if (!SSL_is_server(s))
+ return;
+ num = SSL_get0_raw_cipherlist(s, NULL);
+ OPENSSL_assert(num == 2);
+ rlistlen = SSL_get0_raw_cipherlist(s, &rlist);
+ BIO_puts(bio_err, "Client cipher list: ");
+ for (i = 0; i < rlistlen; i += num, rlist += num) {
+ const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist);
+ if (i)
+ BIO_puts(bio_err, ":");
+ if (c != NULL) {
+ BIO_puts(bio_err, SSL_CIPHER_get_name(c));
+ } else if (memcmp(rlist, scsv_id, num) == 0) {
+ BIO_puts(bio_err, "SCSV");
+ } else {
+ size_t j;
+ BIO_puts(bio_err, "0x");
+ for (j = 0; j < num; j++)
+ BIO_printf(bio_err, "%02X", rlist[j]);
+ }
+ }
+ BIO_puts(bio_err, "\n");
+}
+
+/*
+ * Hex encoder for TLSA RRdata, not ':' delimited.
+ */
+static char *hexencode(const unsigned char *data, size_t len)
+{
+ static const char *hex = "0123456789abcdef";
+ char *out;
+ char *cp;
+ size_t outlen = 2 * len + 1;
+ int ilen = (int) outlen;
+
+ if (outlen < len || ilen < 0 || outlen != (size_t)ilen) {
+ BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n",
+ opt_getprog(), len);
+ exit(1);
+ }
+ cp = out = app_malloc(ilen, "TLSA hex data buffer");
+
+ while (len-- > 0) {
+ *cp++ = hex[(*data >> 4) & 0x0f];
+ *cp++ = hex[*data++ & 0x0f];
+ }
+ *cp = '\0';
+ return out;
+}
+
+void print_verify_detail(SSL *s, BIO *bio)
+{
+ int mdpth;
+ EVP_PKEY *mspki;
+ long verify_err = SSL_get_verify_result(s);
+
+ if (verify_err == X509_V_OK) {
+ const char *peername = SSL_get0_peername(s);
+
+ BIO_printf(bio, "Verification: OK\n");
+ if (peername != NULL)
+ BIO_printf(bio, "Verified peername: %s\n", peername);
+ } else {
+ const char *reason = X509_verify_cert_error_string(verify_err);
+
+ BIO_printf(bio, "Verification error: %s\n", reason);
+ }
+
+ if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
+ uint8_t usage, selector, mtype;
+ const unsigned char *data = NULL;
+ size_t dlen = 0;
+ char *hexdata;
+
+ mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen);
+
+ /*
+ * The TLSA data field can be quite long when it is a certificate,
+ * public key or even a SHA2-512 digest. Because the initial octets of
+ * ASN.1 certificates and public keys contain mostly boilerplate OIDs
+ * and lengths, we show the last 12 bytes of the data instead, as these
+ * are more likely to distinguish distinct TLSA records.
+ */
+#define TLSA_TAIL_SIZE 12
+ if (dlen > TLSA_TAIL_SIZE)
+ hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
+ else
+ hexdata = hexencode(data, dlen);
+ BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
+ usage, selector, mtype,
+ (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
+ (mspki != NULL) ? "signed the certificate" :
+ mdpth ? "matched TA certificate" : "matched EE certificate",
+ mdpth);
+ OPENSSL_free(hexdata);
+ }
+}
+
+void print_ssl_summary(SSL *s)
+{
+ const SSL_CIPHER *c;
+ X509 *peer;
+
+ BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
+ print_raw_cipherlist(s);
+ c = SSL_get_current_cipher(s);
+ BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
+ do_print_sigalgs(bio_err, s, 0);
+ peer = SSL_get_peer_certificate(s);
+ if (peer != NULL) {
+ int nid;
+
+ BIO_puts(bio_err, "Peer certificate: ");
+ X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
+ 0, get_nameopt());
+ BIO_puts(bio_err, "\n");
+ if (SSL_get_peer_signature_nid(s, &nid))
+ BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
+ if (SSL_get_peer_signature_type_nid(s, &nid))
+ BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
+ print_verify_detail(s, bio_err);
+ } else {
+ BIO_puts(bio_err, "No peer certificate\n");
+ }
+ X509_free(peer);
+#ifndef OPENSSL_NO_EC
+ ssl_print_point_formats(bio_err, s);
+ if (SSL_is_server(s))
+ ssl_print_groups(bio_err, s, 1);
+ else
+ ssl_print_tmp_key(bio_err, s);
+#else
+ if (!SSL_is_server(s))
+ ssl_print_tmp_key(bio_err, s);
+#endif
+}
+
+int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
+ SSL_CTX *ctx)
+{
+ int i;
+
+ SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+ for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
+ const char *flag = sk_OPENSSL_STRING_value(str, i);
+ const char *arg = sk_OPENSSL_STRING_value(str, i + 1);
+ if (SSL_CONF_cmd(cctx, flag, arg) <= 0) {
+ if (arg != NULL)
+ BIO_printf(bio_err, "Error with command: \"%s %s\"\n",
+ flag, arg);
+ else
+ BIO_printf(bio_err, "Error with command: \"%s\"\n", flag);
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ }
+ if (!SSL_CONF_CTX_finish(cctx)) {
+ BIO_puts(bio_err, "Error finishing context\n");
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ return 1;
+}
+
+static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
+{
+ X509_CRL *crl;
+ int i;
+ for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+ crl = sk_X509_CRL_value(crls, i);
+ X509_STORE_add_crl(st, crl);
+ }
+ return 1;
+}
+
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
+{
+ X509_STORE *st;
+ st = SSL_CTX_get_cert_store(ctx);
+ add_crls_store(st, crls);
+ if (crl_download)
+ store_setup_crl_download(st);
+ return 1;
+}
+
+int ssl_load_stores(SSL_CTX *ctx,
+ const char *vfyCApath, const char *vfyCAfile,
+ const char *chCApath, const char *chCAfile,
+ STACK_OF(X509_CRL) *crls, int crl_download)
+{
+ X509_STORE *vfy = NULL, *ch = NULL;
+ int rv = 0;
+ if (vfyCApath != NULL || vfyCAfile != NULL) {
+ vfy = X509_STORE_new();
+ if (vfy == NULL)
+ goto err;
+ if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
+ goto err;
+ add_crls_store(vfy, crls);
+ SSL_CTX_set1_verify_cert_store(ctx, vfy);
+ if (crl_download)
+ store_setup_crl_download(vfy);
+ }
+ if (chCApath != NULL || chCAfile != NULL) {
+ ch = X509_STORE_new();
+ if (ch == NULL)
+ goto err;
+ if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
+ goto err;
+ SSL_CTX_set1_chain_cert_store(ctx, ch);
+ }
+ rv = 1;
+ err:
+ X509_STORE_free(vfy);
+ X509_STORE_free(ch);
+ return rv;
+}
+
+/* Verbose print out of security callback */
+
+typedef struct {
+ BIO *out;
+ int verbose;
+ int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
+ void *other, void *ex);
+} security_debug_ex;
+
+static STRINT_PAIR callback_types[] = {
+ {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED},
+ {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED},
+ {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK},
+#ifndef OPENSSL_NO_DH
+ {"Temp DH key bits", SSL_SECOP_TMP_DH},
+#endif
+ {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED},
+ {"Shared Curve", SSL_SECOP_CURVE_SHARED},
+ {"Check Curve", SSL_SECOP_CURVE_CHECK},
+ {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED},
+ {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED},
+ {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK},
+ {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
+ {"Certificate chain EE key", SSL_SECOP_EE_KEY},
+ {"Certificate chain CA key", SSL_SECOP_CA_KEY},
+ {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY},
+ {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY},
+ {"Certificate chain CA digest", SSL_SECOP_CA_MD},
+ {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD},
+ {"SSL compression", SSL_SECOP_COMPRESSION},
+ {"Session ticket", SSL_SECOP_TICKET},
+ {NULL}
+};
+
+static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex)
+{
+ security_debug_ex *sdb = ex;
+ int rv, show_bits = 1, cert_md = 0;
+ const char *nm;
+ rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
+ if (rv == 1 && sdb->verbose < 2)
+ return 1;
+ BIO_puts(sdb->out, "Security callback: ");
+
+ nm = lookup(op, callback_types, NULL);
+ switch (op) {
+ case SSL_SECOP_TICKET:
+ case SSL_SECOP_COMPRESSION:
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_VERSION:
+ BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_CA_MD:
+ case SSL_SECOP_PEER_CA_MD:
+ cert_md = 1;
+ break;
+ }
+ if (nm != NULL)
+ BIO_printf(sdb->out, "%s=", nm);
+
+ switch (op & SSL_SECOP_OTHER_TYPE) {
+
+ case SSL_SECOP_OTHER_CIPHER:
+ BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
+ break;
+
+#ifndef OPENSSL_NO_EC
+ case SSL_SECOP_OTHER_CURVE:
+ {
+ const char *cname;
+ cname = EC_curve_nid2nist(nid);
+ if (cname == NULL)
+ cname = OBJ_nid2sn(nid);
+ BIO_puts(sdb->out, cname);
+ }
+ break;
+#endif
+#ifndef OPENSSL_NO_DH
+ case SSL_SECOP_OTHER_DH:
+ {
+ DH *dh = other;
+ BIO_printf(sdb->out, "%d", DH_bits(dh));
+ break;
+ }
+#endif
+ case SSL_SECOP_OTHER_CERT:
+ {
+ if (cert_md) {
+ int sig_nid = X509_get_signature_nid(other);
+ BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
+ } else {
+ EVP_PKEY *pkey = X509_get0_pubkey(other);
+ const char *algname = "";
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
+ &algname, EVP_PKEY_get0_asn1(pkey));
+ BIO_printf(sdb->out, "%s, bits=%d",
+ algname, EVP_PKEY_bits(pkey));
+ }
+ break;
+ }
+ case SSL_SECOP_OTHER_SIGALG:
+ {
+ const unsigned char *salg = other;
+ const char *sname = NULL;
+ switch (salg[1]) {
+ case TLSEXT_signature_anonymous:
+ sname = "anonymous";
+ break;
+ case TLSEXT_signature_rsa:
+ sname = "RSA";
+ break;
+ case TLSEXT_signature_dsa:
+ sname = "DSA";
+ break;
+ case TLSEXT_signature_ecdsa:
+ sname = "ECDSA";
+ break;
+ }
+
+ BIO_puts(sdb->out, OBJ_nid2sn(nid));
+ if (sname)
+ BIO_printf(sdb->out, ", algorithm=%s", sname);
+ else
+ BIO_printf(sdb->out, ", algid=%d", salg[1]);
+ break;
+ }
+
+ }
+
+ if (show_bits)
+ BIO_printf(sdb->out, ", security bits=%d", bits);
+ BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
+ return rv;
+}
+
+void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
+{
+ static security_debug_ex sdb;
+
+ sdb.out = bio_err;
+ sdb.verbose = verbose;
+ sdb.old_cb = SSL_CTX_get_security_callback(ctx);
+ SSL_CTX_set_security_callback(ctx, security_callback_debug);
+ SSL_CTX_set0_security_ex_data(ctx, &sdb);
+}
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
+ return;
+ }
+
+ /*
+ * There might be concurrent writers to the keylog file, so we must ensure
+ * that the given line is written at once.
+ */
+ BIO_printf(bio_keylog, "%s\n", line);
+ (void)BIO_flush(bio_keylog);
+}
+
+int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
+{
+ /* Close any open files */
+ BIO_free_all(bio_keylog);
+ bio_keylog = NULL;
+
+ if (ctx == NULL || keylog_file == NULL) {
+ /* Keylogging is disabled, OK. */
+ return 0;
+ }
+
+ /*
+ * Append rather than write in order to allow concurrent modification.
+ * Furthermore, this preserves existing keylog files which is useful when
+ * the tool is run multiple times.
+ */
+ bio_keylog = BIO_new_file(keylog_file, "a");
+ if (bio_keylog == NULL) {
+ BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
+ return 1;
+ }
+
+ /* Write a header for seekable, empty files (this excludes pipes). */
+ if (BIO_tell(bio_keylog) == 0) {
+ BIO_puts(bio_keylog,
+ "# SSL/TLS secrets log file, generated by OpenSSL\n");
+ (void)BIO_flush(bio_keylog);
+ }
+ SSL_CTX_set_keylog_callback(ctx, keylog_callback);
+ return 0;
+}
+
+void print_ca_names(BIO *bio, SSL *s)
+{
+ const char *cs = SSL_is_server(s) ? "server" : "client";
+ const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s);
+ int i;
+
+ if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
+ BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
+ return;
+ }
+
+ BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs);
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt());
+ BIO_write(bio, "\n", 1);
+ }
+}
diff --git a/freebsd/crypto/openssl/apps/s_client.c b/freebsd/crypto/openssl/apps/s_client.c
new file mode 100644
index 00000000..2c08d94d
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_client.c
@@ -0,0 +1,3464 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "e_os.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_SOCK
+
+/*
+ * With IPv6, it looks like Digital has mixed up the proper order of
+ * recursive header file inclusion, resulting in the compiler complaining
+ * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
+ * needed to have fileno() declared correctly... So let's define u_int
+ */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
+# define __U_INT
+typedef unsigned int u_int;
+#endif
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/rand.h>
+#include <openssl/ocsp.h>
+#include <openssl/bn.h>
+#include <openssl/async.h>
+#ifndef OPENSSL_NO_SRP
+# include <openssl/srp.h>
+#endif
+#ifndef OPENSSL_NO_CT
+# include <openssl/ct.h>
+#endif
+#include "s_apps.h"
+#include "timeouts.h"
+#include "internal/sockets.h"
+
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+# endif
+#endif
+
+#undef BUFSIZZ
+#define BUFSIZZ 1024*8
+#define S_CLIENT_IRC_READ_TIMEOUT 8
+
+static char *prog;
+static int c_debug = 0;
+static int c_showcerts = 0;
+static char *keymatexportlabel = NULL;
+static int keymatexportlen = 20;
+static BIO *bio_c_out = NULL;
+static int c_quiet = 0;
+static char *sess_out = NULL;
+static SSL_SESSION *psksess = NULL;
+
+static void print_stuff(BIO *berr, SSL *con, int full);
+#ifndef OPENSSL_NO_OCSP
+static int ocsp_resp_cb(SSL *s, void *arg);
+#endif
+static int ldap_ExtendedResponse_parse(const char *buf, long rem);
+
+static int saved_errno;
+
+static void save_errno(void)
+{
+ saved_errno = errno;
+ errno = 0;
+}
+
+static int restore_errno(void)
+{
+ int ret = errno;
+ errno = saved_errno;
+ return ret;
+}
+
+static void do_ssl_shutdown(SSL *ssl)
+{
+ int ret;
+
+ do {
+ /* We only do unidirectional shutdown */
+ ret = SSL_shutdown(ssl);
+ if (ret < 0) {
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ASYNC:
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /* We just do busy waiting. Nothing clever */
+ continue;
+ }
+ ret = 0;
+ }
+ } while (ret < 0);
+}
+
+/* Default PSK identity and key */
+static char *psk_identity = "Client_identity";
+
+#ifndef OPENSSL_NO_PSK
+static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len,
+ unsigned char *psk,
+ unsigned int max_psk_len)
+{
+ int ret;
+ long key_len;
+ unsigned char *key;
+
+ if (c_debug)
+ BIO_printf(bio_c_out, "psk_client_cb\n");
+ if (!hint) {
+ /* no ServerKeyExchange message */
+ if (c_debug)
+ BIO_printf(bio_c_out,
+ "NULL received PSK identity hint, continuing anyway\n");
+ } else if (c_debug) {
+ BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint);
+ }
+
+ /*
+ * lookup PSK identity and PSK key based on the given identity hint here
+ */
+ ret = BIO_snprintf(identity, max_identity_len, "%s", psk_identity);
+ if (ret < 0 || (unsigned int)ret > max_identity_len)
+ goto out_err;
+ if (c_debug)
+ BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity,
+ ret);
+
+ /* convert the PSK key to binary */
+ key = OPENSSL_hexstr2buf(psk_key, &key_len);
+ if (key == NULL) {
+ BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
+ psk_key);
+ return 0;
+ }
+ if (max_psk_len > INT_MAX || key_len > (long)max_psk_len) {
+ BIO_printf(bio_err,
+ "psk buffer of callback is too small (%d) for key (%ld)\n",
+ max_psk_len, key_len);
+ OPENSSL_free(key);
+ return 0;
+ }
+
+ memcpy(psk, key, key_len);
+ OPENSSL_free(key);
+
+ if (c_debug)
+ BIO_printf(bio_c_out, "created PSK len=%ld\n", key_len);
+
+ return key_len;
+ out_err:
+ if (c_debug)
+ BIO_printf(bio_err, "Error in PSK client callback\n");
+ return 0;
+}
+#endif
+
+const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
+const unsigned char tls13_aes256gcmsha384_id[] = { 0x13, 0x02 };
+
+static int psk_use_session_cb(SSL *s, const EVP_MD *md,
+ const unsigned char **id, size_t *idlen,
+ SSL_SESSION **sess)
+{
+ SSL_SESSION *usesess = NULL;
+ const SSL_CIPHER *cipher = NULL;
+
+ if (psksess != NULL) {
+ SSL_SESSION_up_ref(psksess);
+ usesess = psksess;
+ } else {
+ long key_len;
+ unsigned char *key = OPENSSL_hexstr2buf(psk_key, &key_len);
+
+ if (key == NULL) {
+ BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
+ psk_key);
+ return 0;
+ }
+
+ /* We default to SHA-256 */
+ cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
+ if (cipher == NULL) {
+ BIO_printf(bio_err, "Error finding suitable ciphersuite\n");
+ OPENSSL_free(key);
+ return 0;
+ }
+
+ usesess = SSL_SESSION_new();
+ if (usesess == NULL
+ || !SSL_SESSION_set1_master_key(usesess, key, key_len)
+ || !SSL_SESSION_set_cipher(usesess, cipher)
+ || !SSL_SESSION_set_protocol_version(usesess, TLS1_3_VERSION)) {
+ OPENSSL_free(key);
+ goto err;
+ }
+ OPENSSL_free(key);
+ }
+
+ cipher = SSL_SESSION_get0_cipher(usesess);
+ if (cipher == NULL)
+ goto err;
+
+ if (md != NULL && SSL_CIPHER_get_handshake_digest(cipher) != md) {
+ /* PSK not usable, ignore it */
+ *id = NULL;
+ *idlen = 0;
+ *sess = NULL;
+ SSL_SESSION_free(usesess);
+ } else {
+ *sess = usesess;
+ *id = (unsigned char *)psk_identity;
+ *idlen = strlen(psk_identity);
+ }
+
+ return 1;
+
+ err:
+ SSL_SESSION_free(usesess);
+ return 0;
+}
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+ BIO *biodebug;
+ int ack;
+} tlsextctx;
+
+static int ssl_servername_cb(SSL *s, int *ad, void *arg)
+{
+ tlsextctx *p = (tlsextctx *) arg;
+ const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
+ if (SSL_get_servername_type(s) != -1)
+ p->ack = !SSL_session_reused(s) && hn != NULL;
+ else
+ BIO_printf(bio_err, "Can't use SSL_get_servername\n");
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#ifndef OPENSSL_NO_SRP
+
+/* This is a context that we pass to all callbacks */
+typedef struct srp_arg_st {
+ char *srppassin;
+ char *srplogin;
+ int msg; /* copy from c_msg */
+ int debug; /* copy from c_debug */
+ int amp; /* allow more groups */
+ int strength; /* minimal size for N */
+} SRP_ARG;
+
+# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
+
+static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g)
+{
+ BN_CTX *bn_ctx = BN_CTX_new();
+ BIGNUM *p = BN_new();
+ BIGNUM *r = BN_new();
+ int ret =
+ g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
+ BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
+ p != NULL && BN_rshift1(p, N) &&
+ /* p = (N-1)/2 */
+ BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
+ r != NULL &&
+ /* verify g^((N-1)/2) == -1 (mod N) */
+ BN_mod_exp(r, g, p, N, bn_ctx) &&
+ BN_add_word(r, 1) && BN_cmp(r, N) == 0;
+
+ BN_free(r);
+ BN_free(p);
+ BN_CTX_free(bn_ctx);
+ return ret;
+}
+
+/*-
+ * This callback is used here for two purposes:
+ * - extended debugging
+ * - making some primality tests for unknown groups
+ * The callback is only called for a non default group.
+ *
+ * An application does not need the call back at all if
+ * only the standard groups are used. In real life situations,
+ * client and server already share well known groups,
+ * thus there is no need to verify them.
+ * Furthermore, in case that a server actually proposes a group that
+ * is not one of those defined in RFC 5054, it is more appropriate
+ * to add the group to a static list and then compare since
+ * primality tests are rather cpu consuming.
+ */
+
+static int ssl_srp_verify_param_cb(SSL *s, void *arg)
+{
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ BIGNUM *N = NULL, *g = NULL;
+
+ if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL))
+ return 0;
+ if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) {
+ BIO_printf(bio_err, "SRP parameters:\n");
+ BIO_printf(bio_err, "\tN=");
+ BN_print(bio_err, N);
+ BIO_printf(bio_err, "\n\tg=");
+ BN_print(bio_err, g);
+ BIO_printf(bio_err, "\n");
+ }
+
+ if (SRP_check_known_gN_param(g, N))
+ return 1;
+
+ if (srp_arg->amp == 1) {
+ if (srp_arg->debug)
+ BIO_printf(bio_err,
+ "SRP param N and g are not known params, going to check deeper.\n");
+
+ /*
+ * The srp_moregroups is a real debugging feature. Implementors
+ * should rather add the value to the known ones. The minimal size
+ * has already been tested.
+ */
+ if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
+ return 1;
+ }
+ BIO_printf(bio_err, "SRP param N and g rejected.\n");
+ return 0;
+}
+
+# define PWD_STRLEN 1024
+
+static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
+{
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
+ PW_CB_DATA cb_tmp;
+ int l;
+
+ cb_tmp.password = (char *)srp_arg->srppassin;
+ cb_tmp.prompt_info = "SRP user";
+ if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
+ BIO_printf(bio_err, "Can't read Password\n");
+ OPENSSL_free(pass);
+ return NULL;
+ }
+ *(pass + l) = '\0';
+
+ return pass;
+}
+
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/* This the context that we pass to next_proto_cb */
+typedef struct tlsextnextprotoctx_st {
+ unsigned char *data;
+ size_t len;
+ int status;
+} tlsextnextprotoctx;
+
+static tlsextnextprotoctx next_proto;
+
+static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ void *arg)
+{
+ tlsextnextprotoctx *ctx = arg;
+
+ if (!c_quiet) {
+ /* We can assume that |in| is syntactically valid. */
+ unsigned i;
+ BIO_printf(bio_c_out, "Protocols advertised by server: ");
+ for (i = 0; i < inlen;) {
+ if (i)
+ BIO_write(bio_c_out, ", ", 2);
+ BIO_write(bio_c_out, &in[i + 1], in[i]);
+ i += in[i] + 1;
+ }
+ BIO_write(bio_c_out, "\n", 1);
+ }
+
+ ctx->status =
+ SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
+
+static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type,
+ const unsigned char *in, size_t inlen,
+ int *al, void *arg)
+{
+ char pem_name[100];
+ unsigned char ext_buf[4 + 65536];
+
+ /* Reconstruct the type/len fields prior to extension data */
+ inlen &= 0xffff; /* for formal memcmpy correctness */
+ ext_buf[0] = (unsigned char)(ext_type >> 8);
+ ext_buf[1] = (unsigned char)(ext_type);
+ ext_buf[2] = (unsigned char)(inlen >> 8);
+ ext_buf[3] = (unsigned char)(inlen);
+ memcpy(ext_buf + 4, in, inlen);
+
+ BIO_snprintf(pem_name, sizeof(pem_name), "SERVERINFO FOR EXTENSION %d",
+ ext_type);
+ PEM_write_bio(bio_c_out, pem_name, "", ext_buf, 4 + inlen);
+ return 1;
+}
+
+/*
+ * Hex decoder that tolerates optional whitespace. Returns number of bytes
+ * produced, advances inptr to end of input string.
+ */
+static ossl_ssize_t hexdecode(const char **inptr, void *result)
+{
+ unsigned char **out = (unsigned char **)result;
+ const char *in = *inptr;
+ unsigned char *ret = app_malloc(strlen(in) / 2, "hexdecode");
+ unsigned char *cp = ret;
+ uint8_t byte;
+ int nibble = 0;
+
+ if (ret == NULL)
+ return -1;
+
+ for (byte = 0; *in; ++in) {
+ int x;
+
+ if (isspace(_UC(*in)))
+ continue;
+ x = OPENSSL_hexchar2int(*in);
+ if (x < 0) {
+ OPENSSL_free(ret);
+ return 0;
+ }
+ byte |= (char)x;
+ if ((nibble ^= 1) == 0) {
+ *cp++ = byte;
+ byte = 0;
+ } else {
+ byte <<= 4;
+ }
+ }
+ if (nibble != 0) {
+ OPENSSL_free(ret);
+ return 0;
+ }
+ *inptr = in;
+
+ return cp - (*out = ret);
+}
+
+/*
+ * Decode unsigned 0..255, returns 1 on success, <= 0 on failure. Advances
+ * inptr to next field skipping leading whitespace.
+ */
+static ossl_ssize_t checked_uint8(const char **inptr, void *out)
+{
+ uint8_t *result = (uint8_t *)out;
+ const char *in = *inptr;
+ char *endp;
+ long v;
+ int e;
+
+ save_errno();
+ v = strtol(in, &endp, 10);
+ e = restore_errno();
+
+ if (((v == LONG_MIN || v == LONG_MAX) && e == ERANGE) ||
+ endp == in || !isspace(_UC(*endp)) ||
+ v != (*result = (uint8_t) v)) {
+ return -1;
+ }
+ for (in = endp; isspace(_UC(*in)); ++in)
+ continue;
+
+ *inptr = in;
+ return 1;
+}
+
+struct tlsa_field {
+ void *var;
+ const char *name;
+ ossl_ssize_t (*parser)(const char **, void *);
+};
+
+static int tlsa_import_rr(SSL *con, const char *rrdata)
+{
+ /* Not necessary to re-init these values; the "parsers" do that. */
+ static uint8_t usage;
+ static uint8_t selector;
+ static uint8_t mtype;
+ static unsigned char *data;
+ static struct tlsa_field tlsa_fields[] = {
+ { &usage, "usage", checked_uint8 },
+ { &selector, "selector", checked_uint8 },
+ { &mtype, "mtype", checked_uint8 },
+ { &data, "data", hexdecode },
+ { NULL, }
+ };
+ struct tlsa_field *f;
+ int ret;
+ const char *cp = rrdata;
+ ossl_ssize_t len = 0;
+
+ for (f = tlsa_fields; f->var; ++f) {
+ /* Returns number of bytes produced, advances cp to next field */
+ if ((len = f->parser(&cp, f->var)) <= 0) {
+ BIO_printf(bio_err, "%s: warning: bad TLSA %s field in: %s\n",
+ prog, f->name, rrdata);
+ return 0;
+ }
+ }
+ /* The data field is last, so len is its length */
+ ret = SSL_dane_tlsa_add(con, usage, selector, mtype, data, len);
+ OPENSSL_free(data);
+
+ if (ret == 0) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "%s: warning: unusable TLSA rrdata: %s\n",
+ prog, rrdata);
+ return 0;
+ }
+ if (ret < 0) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err, "%s: warning: error loading TLSA rrdata: %s\n",
+ prog, rrdata);
+ return 0;
+ }
+ return ret;
+}
+
+static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset)
+{
+ int num = sk_OPENSSL_STRING_num(rrset);
+ int count = 0;
+ int i;
+
+ for (i = 0; i < num; ++i) {
+ char *rrdata = sk_OPENSSL_STRING_value(rrset, i);
+ if (tlsa_import_rr(con, rrdata) > 0)
+ ++count;
+ }
+ return count > 0;
+}
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX,
+ OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT,
+ OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN,
+ OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
+ OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO,
+ OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF,
+ OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG,
+ OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG,
+ OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE,
+ OPT_PSK_IDENTITY, OPT_PSK, OPT_PSK_SESS,
+#ifndef OPENSSL_NO_SRP
+ OPT_SRPUSER, OPT_SRPPASS, OPT_SRP_STRENGTH, OPT_SRP_LATEUSER,
+ OPT_SRP_MOREGROUPS,
+#endif
+ OPT_SSL3, OPT_SSL_CONFIG,
+ OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
+ OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS,
+ OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH,
+ OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE,
+ OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC,
+ OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST,
+ OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
+ OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
+ OPT_V_ENUM,
+ OPT_X_ENUM,
+ OPT_S_ENUM,
+ OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN,
+#ifndef OPENSSL_NO_CT
+ OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
+#endif
+ OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
+ OPT_ENABLE_PHA,
+ OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS s_client_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"host", OPT_HOST, 's', "Use -connect instead"},
+ {"port", OPT_PORT, 'p', "Use -connect instead"},
+ {"connect", OPT_CONNECT, 's',
+ "TCP/IP where to connect (default is :" PORT ")"},
+ {"bind", OPT_BIND, 's', "bind local address for connection"},
+ {"proxy", OPT_PROXY, 's',
+ "Connect to via specified proxy to the real server"},
+#ifdef AF_UNIX
+ {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"},
+#endif
+ {"4", OPT_4, '-', "Use IPv4 only"},
+#ifdef AF_INET6
+ {"6", OPT_6, '-', "Use IPv6 only"},
+#endif
+ {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
+ {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"},
+ {"certform", OPT_CERTFORM, 'F',
+ "Certificate format (PEM or DER) PEM default"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"},
+ {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"},
+ {"pass", OPT_PASS, 's', "Private key file pass phrase source"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"requestCAfile", OPT_REQCAFILE, '<',
+ "PEM format file of CA names to send to the server"},
+ {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"},
+ {"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's',
+ "DANE TLSA rrdata presentation form"},
+ {"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-',
+ "Disable name checks when matching DANE-EE(3) TLSA records"},
+ {"reconnect", OPT_RECONNECT, '-',
+ "Drop and re-make the connection with the same Session-ID"},
+ {"showcerts", OPT_SHOWCERTS, '-',
+ "Show all certificates sent by the server"},
+ {"debug", OPT_DEBUG, '-', "Extra output"},
+ {"msg", OPT_MSG, '-', "Show protocol messages"},
+ {"msgfile", OPT_MSGFILE, '>',
+ "File to send output of -msg or -trace, instead of stdout"},
+ {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"},
+ {"state", OPT_STATE, '-', "Print the ssl states"},
+ {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
+ {"quiet", OPT_QUIET, '-', "No s_client output"},
+ {"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"},
+ {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Don't ignore input eof"},
+ {"starttls", OPT_STARTTLS, 's',
+ "Use the appropriate STARTTLS command before starting TLS"},
+ {"xmpphost", OPT_XMPPHOST, 's',
+ "Alias of -name option for \"-starttls xmpp[-server]\""},
+ OPT_R_OPTIONS,
+ {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
+ {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_USE_SRTP, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
+#endif
+ {"keymatexport", OPT_KEYMATEXPORT, 's',
+ "Export keying material using label"},
+ {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
+ "Export len bytes of keying material (default 20)"},
+ {"maxfraglen", OPT_MAXFRAGLEN, 'p',
+ "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
+ {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
+ {"name", OPT_PROTOHOST, 's',
+ "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
+ {"CRL", OPT_CRL, '<', "CRL file to use"},
+ {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"},
+ {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
+ {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
+ "Close connection on verification error"},
+ {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
+ {"brief", OPT_BRIEF, '-',
+ "Restrict output to brief summary of connection parameters"},
+ {"prexit", OPT_PREXIT, '-',
+ "Print session information when the program exits"},
+ {"security_debug", OPT_SECURITY_DEBUG, '-',
+ "Enable security debug messages"},
+ {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
+ "Output more security debug output"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "Certificate chain file (in PEM format)"},
+ {"chainCApath", OPT_CHAINCAPATH, '/',
+ "Use dir as certificate store path to build CA certificate chain"},
+ {"verifyCApath", OPT_VERIFYCAPATH, '/',
+ "Use dir as certificate store path to verify CA certificate"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
+ {"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"},
+ {"servername", OPT_SERVERNAME, 's',
+ "Set TLS extension servername (SNI) in ClientHello (default)"},
+ {"noservername", OPT_NOSERVERNAME, '-',
+ "Do not send the server name (SNI) extension in the ClientHello"},
+ {"tlsextdebug", OPT_TLSEXTDEBUG, '-',
+ "Hex dump of all TLS extensions received"},
+#ifndef OPENSSL_NO_OCSP
+ {"status", OPT_STATUS, '-', "Request certificate status from server"},
+#endif
+ {"serverinfo", OPT_SERVERINFO, 's',
+ "types Send empty ClientHello extensions (comma-separated numbers)"},
+ {"alpn", OPT_ALPN, 's',
+ "Enable ALPN extension, considering named protocols supported (comma-separated list)"},
+ {"async", OPT_ASYNC, '-', "Support asynchronous operation"},
+ {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"},
+ {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
+ {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
+ "Size used to split data for encrypt pipelines"},
+ {"max_pipelines", OPT_MAX_PIPELINES, 'p',
+ "Maximum number of encrypt/decrypt pipelines to be used"},
+ {"read_buf", OPT_READ_BUF, 'p',
+ "Default read buffer size to be used for connections"},
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ OPT_X_OPTIONS,
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {"tls1", OPT_TLS1, '-', "Just use TLSv1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+ {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+ {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"},
+#endif
+#ifndef OPENSSL_NO_DTLS
+ {"dtls", OPT_DTLS, '-', "Use any version of DTLS"},
+ {"timeout", OPT_TIMEOUT, '-',
+ "Enable send/receive timeout on DTLS connections"},
+ {"mtu", OPT_MTU, 'p', "Set the link layer MTU"},
+#endif
+#ifndef OPENSSL_NO_DTLS1
+ {"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"},
+#endif
+#ifndef OPENSSL_NO_DTLS1_2
+ {"dtls1_2", OPT_DTLS1_2, '-', "Just use DTLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_SCTP
+ {"sctp", OPT_SCTP, '-', "Use SCTP"},
+#endif
+#ifndef OPENSSL_NO_SSL_TRACE
+ {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"},
+#endif
+#ifdef WATT32
+ {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"},
+#endif
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+ {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"},
+ {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
+ {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
+#ifndef OPENSSL_NO_SRP
+ {"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"},
+ {"srppass", OPT_SRPPASS, 's', "Password for 'user'"},
+ {"srp_lateuser", OPT_SRP_LATEUSER, '-',
+ "SRP username into second ClientHello message"},
+ {"srp_moregroups", OPT_SRP_MOREGROUPS, '-',
+ "Tolerate other than the known g N values."},
+ {"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"},
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {"nextprotoneg", OPT_NEXTPROTONEG, 's',
+ "Enable NPN extension, considering named protocols supported (comma-separated list)"},
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+ {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's',
+ "Specify engine to be used for client certificate operations"},
+#endif
+#ifndef OPENSSL_NO_CT
+ {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"},
+ {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"},
+ {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"},
+#endif
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+ {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
+ {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
+ {NULL, OPT_EOF, 0x00, NULL}
+};
+
+typedef enum PROTOCOL_choice {
+ PROTO_OFF,
+ PROTO_SMTP,
+ PROTO_POP3,
+ PROTO_IMAP,
+ PROTO_FTP,
+ PROTO_TELNET,
+ PROTO_XMPP,
+ PROTO_XMPP_SERVER,
+ PROTO_CONNECT,
+ PROTO_IRC,
+ PROTO_MYSQL,
+ PROTO_POSTGRES,
+ PROTO_LMTP,
+ PROTO_NNTP,
+ PROTO_SIEVE,
+ PROTO_LDAP
+} PROTOCOL_CHOICE;
+
+static const OPT_PAIR services[] = {
+ {"smtp", PROTO_SMTP},
+ {"pop3", PROTO_POP3},
+ {"imap", PROTO_IMAP},
+ {"ftp", PROTO_FTP},
+ {"xmpp", PROTO_XMPP},
+ {"xmpp-server", PROTO_XMPP_SERVER},
+ {"telnet", PROTO_TELNET},
+ {"irc", PROTO_IRC},
+ {"mysql", PROTO_MYSQL},
+ {"postgres", PROTO_POSTGRES},
+ {"lmtp", PROTO_LMTP},
+ {"nntp", PROTO_NNTP},
+ {"sieve", PROTO_SIEVE},
+ {"ldap", PROTO_LDAP},
+ {NULL, 0}
+};
+
+#define IS_INET_FLAG(o) \
+ (o == OPT_4 || o == OPT_6 || o == OPT_HOST || o == OPT_PORT || o == OPT_CONNECT)
+#define IS_UNIX_FLAG(o) (o == OPT_UNIX)
+
+#define IS_PROT_FLAG(o) \
+ (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \
+ || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2)
+
+/* Free |*dest| and optionally set it to a copy of |source|. */
+static void freeandcopy(char **dest, const char *source)
+{
+ OPENSSL_free(*dest);
+ *dest = NULL;
+ if (source != NULL)
+ *dest = OPENSSL_strdup(source);
+}
+
+static int new_session_cb(SSL *s, SSL_SESSION *sess)
+{
+
+ if (sess_out != NULL) {
+ BIO *stmp = BIO_new_file(sess_out, "w");
+
+ if (stmp == NULL) {
+ BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
+ } else {
+ PEM_write_bio_SSL_SESSION(stmp, sess);
+ BIO_free(stmp);
+ }
+ }
+
+ /*
+ * Session data gets dumped on connection for TLSv1.2 and below, and on
+ * arrival of the NewSessionTicket for TLSv1.3.
+ */
+ if (SSL_version(s) == TLS1_3_VERSION) {
+ BIO_printf(bio_c_out,
+ "---\nPost-Handshake New Session Ticket arrived:\n");
+ SSL_SESSION_print(bio_c_out, sess);
+ BIO_printf(bio_c_out, "---\n");
+ }
+
+ /*
+ * We always return a "fail" response so that the session gets freed again
+ * because we haven't used the reference.
+ */
+ return 0;
+}
+
+int s_client_main(int argc, char **argv)
+{
+ BIO *sbio;
+ EVP_PKEY *key = NULL;
+ SSL *con = NULL;
+ SSL_CTX *ctx = NULL;
+ STACK_OF(X509) *chain = NULL;
+ X509 *cert = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ SSL_EXCERT *exc = NULL;
+ SSL_CONF_CTX *cctx = NULL;
+ STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
+ char *dane_tlsa_domain = NULL;
+ STACK_OF(OPENSSL_STRING) *dane_tlsa_rrset = NULL;
+ int dane_ee_no_name = 0;
+ STACK_OF(X509_CRL) *crls = NULL;
+ const SSL_METHOD *meth = TLS_client_method();
+ const char *CApath = NULL, *CAfile = NULL;
+ char *cbuf = NULL, *sbuf = NULL;
+ char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL;
+ char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
+ char *chCApath = NULL, *chCAfile = NULL, *host = NULL;
+ char *port = OPENSSL_strdup(PORT);
+ char *bindhost = NULL, *bindport = NULL;
+ char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *ReqCAfile = NULL;
+ char *sess_in = NULL, *crl_file = NULL, *p;
+ const char *protohost = NULL;
+ struct timeval timeout, *timeoutp;
+ fd_set readfds, writefds;
+ int noCApath = 0, noCAfile = 0;
+ int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM;
+ int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0;
+ int prexit = 0;
+ int sdebug = 0;
+ int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0;
+ int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0;
+ int sbuf_len, sbuf_off, cmdletters = 1;
+ int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
+ int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
+ int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
+ int at_eof = 0;
+#endif
+ int read_buf_len = 0;
+ int fallback_scsv = 0;
+ OPTION_CHOICE o;
+#ifndef OPENSSL_NO_DTLS
+ int enable_timeouts = 0;
+ long socket_mtu = 0;
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *ssl_client_engine = NULL;
+#endif
+ ENGINE *e = NULL;
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+ struct timeval tv;
+#endif
+ const char *servername = NULL;
+ int noservername = 0;
+ const char *alpn_in = NULL;
+ tlsextctx tlsextcbp = { NULL, 0 };
+ const char *ssl_config = NULL;
+#define MAX_SI_TYPES 100
+ unsigned short serverinfo_types[MAX_SI_TYPES];
+ int serverinfo_count = 0, start = 0, len;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ const char *next_proto_neg_in = NULL;
+#endif
+#ifndef OPENSSL_NO_SRP
+ char *srppass = NULL;
+ int srp_lateuser = 0;
+ SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 };
+#endif
+#ifndef OPENSSL_NO_SRTP
+ char *srtp_profiles = NULL;
+#endif
+#ifndef OPENSSL_NO_CT
+ char *ctlog_file = NULL;
+ int ct_validation = 0;
+#endif
+ int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0;
+ int async = 0;
+ unsigned int max_send_fragment = 0;
+ unsigned int split_send_fragment = 0, max_pipelines = 0;
+ enum { use_inet, use_unix, use_unknown } connect_type = use_unknown;
+ int count4or6 = 0;
+ uint8_t maxfraglen = 0;
+ int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0;
+ int c_tlsextdebug = 0;
+#ifndef OPENSSL_NO_OCSP
+ int c_status_req = 0;
+#endif
+ BIO *bio_c_msg = NULL;
+ const char *keylog_file = NULL, *early_data_file = NULL;
+#ifndef OPENSSL_NO_DTLS
+ int isdtls = 0;
+#endif
+ char *psksessf = NULL;
+ int enable_pha = 0;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+/* Known false-positive of MemorySanitizer. */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+ __msan_unpoison(&readfds, sizeof(readfds));
+ __msan_unpoison(&writefds, sizeof(writefds));
+# endif
+#endif
+
+ prog = opt_progname(argv[0]);
+ c_quiet = 0;
+ c_debug = 0;
+ c_showcerts = 0;
+ c_nbio = 0;
+ vpm = X509_VERIFY_PARAM_new();
+ cctx = SSL_CONF_CTX_new();
+
+ if (vpm == NULL || cctx == NULL) {
+ BIO_printf(bio_err, "%s: out of memory\n", prog);
+ goto end;
+ }
+
+ cbuf = app_malloc(BUFSIZZ, "cbuf");
+ sbuf = app_malloc(BUFSIZZ, "sbuf");
+ mbuf = app_malloc(BUFSIZZ, "mbuf");
+
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT | SSL_CONF_FLAG_CMDLINE);
+
+ prog = opt_init(argc, argv, s_client_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ /* Check for intermixing flags. */
+ if (connect_type == use_unix && IS_INET_FLAG(o)) {
+ BIO_printf(bio_err,
+ "%s: Intermixed protocol flags (unix and internet domains)\n",
+ prog);
+ goto end;
+ }
+ if (connect_type == use_inet && IS_UNIX_FLAG(o)) {
+ BIO_printf(bio_err,
+ "%s: Intermixed protocol flags (internet and unix domains)\n",
+ prog);
+ goto end;
+ }
+
+ if (IS_PROT_FLAG(o) && ++prot_opt > 1) {
+ BIO_printf(bio_err, "Cannot supply multiple protocol flags\n");
+ goto end;
+ }
+ if (IS_NO_PROT_FLAG(o))
+ no_prot_opt++;
+ if (prot_opt == 1 && no_prot_opt) {
+ BIO_printf(bio_err,
+ "Cannot supply both a protocol flag and '-no_<prot>'\n");
+ goto end;
+ }
+
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(s_client_options);
+ ret = 0;
+ goto end;
+ case OPT_4:
+ connect_type = use_inet;
+ socket_family = AF_INET;
+ count4or6++;
+ break;
+#ifdef AF_INET6
+ case OPT_6:
+ connect_type = use_inet;
+ socket_family = AF_INET6;
+ count4or6++;
+ break;
+#endif
+ case OPT_HOST:
+ connect_type = use_inet;
+ freeandcopy(&host, opt_arg());
+ break;
+ case OPT_PORT:
+ connect_type = use_inet;
+ freeandcopy(&port, opt_arg());
+ break;
+ case OPT_CONNECT:
+ connect_type = use_inet;
+ freeandcopy(&connectstr, opt_arg());
+ break;
+ case OPT_BIND:
+ freeandcopy(&bindstr, opt_arg());
+ break;
+ case OPT_PROXY:
+ proxystr = opt_arg();
+ starttls_proto = PROTO_CONNECT;
+ break;
+#ifdef AF_UNIX
+ case OPT_UNIX:
+ connect_type = use_unix;
+ socket_family = AF_UNIX;
+ freeandcopy(&host, opt_arg());
+ break;
+#endif
+ case OPT_XMPPHOST:
+ /* fall through, since this is an alias */
+ case OPT_PROTOHOST:
+ protohost = opt_arg();
+ break;
+ case OPT_VERIFY:
+ verify = SSL_VERIFY_PEER;
+ verify_args.depth = atoi(opt_arg());
+ if (!c_quiet)
+ BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth);
+ break;
+ case OPT_CERT:
+ cert_file = opt_arg();
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto end;
+ break;
+ case OPT_CRL:
+ crl_file = opt_arg();
+ break;
+ case OPT_CRL_DOWNLOAD:
+ crl_download = 1;
+ break;
+ case OPT_SESS_OUT:
+ sess_out = opt_arg();
+ break;
+ case OPT_SESS_IN:
+ sess_in = opt_arg();
+ break;
+ case OPT_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format))
+ goto opthelp;
+ break;
+ case OPT_CRLFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format))
+ goto opthelp;
+ break;
+ case OPT_VERIFY_RET_ERROR:
+ verify_args.return_error = 1;
+ break;
+ case OPT_VERIFY_QUIET:
+ verify_args.quiet = 1;
+ break;
+ case OPT_BRIEF:
+ c_brief = verify_args.quiet = c_quiet = 1;
+ break;
+ case OPT_S_CASES:
+ if (ssl_args == NULL)
+ ssl_args = sk_OPENSSL_STRING_new_null();
+ if (ssl_args == NULL
+ || !sk_OPENSSL_STRING_push(ssl_args, opt_flag())
+ || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) {
+ BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
+ goto end;
+ }
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ case OPT_X_CASES:
+ if (!args_excert(o, &exc))
+ goto end;
+ break;
+ case OPT_PREXIT:
+ prexit = 1;
+ break;
+ case OPT_CRLF:
+ crlf = 1;
+ break;
+ case OPT_QUIET:
+ c_quiet = c_ign_eof = 1;
+ break;
+ case OPT_NBIO:
+ c_nbio = 1;
+ break;
+ case OPT_NOCMDS:
+ cmdletters = 0;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 1);
+ break;
+ case OPT_SSL_CLIENT_ENGINE:
+#ifndef OPENSSL_NO_ENGINE
+ ssl_client_engine = ENGINE_by_id(opt_arg());
+ if (ssl_client_engine == NULL) {
+ BIO_printf(bio_err, "Error getting client auth engine\n");
+ goto opthelp;
+ }
+#endif
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_IGN_EOF:
+ c_ign_eof = 1;
+ break;
+ case OPT_NO_IGN_EOF:
+ c_ign_eof = 0;
+ break;
+ case OPT_DEBUG:
+ c_debug = 1;
+ break;
+ case OPT_TLSEXTDEBUG:
+ c_tlsextdebug = 1;
+ break;
+ case OPT_STATUS:
+#ifndef OPENSSL_NO_OCSP
+ c_status_req = 1;
+#endif
+ break;
+ case OPT_WDEBUG:
+#ifdef WATT32
+ dbug_init();
+#endif
+ break;
+ case OPT_MSG:
+ c_msg = 1;
+ break;
+ case OPT_MSGFILE:
+ bio_c_msg = BIO_new_file(opt_arg(), "w");
+ break;
+ case OPT_TRACE:
+#ifndef OPENSSL_NO_SSL_TRACE
+ c_msg = 2;
+#endif
+ break;
+ case OPT_SECURITY_DEBUG:
+ sdebug = 1;
+ break;
+ case OPT_SECURITY_DEBUG_VERBOSE:
+ sdebug = 2;
+ break;
+ case OPT_SHOWCERTS:
+ c_showcerts = 1;
+ break;
+ case OPT_NBIO_TEST:
+ nbio_test = 1;
+ break;
+ case OPT_STATE:
+ state = 1;
+ break;
+ case OPT_PSK_IDENTITY:
+ psk_identity = opt_arg();
+ break;
+ case OPT_PSK:
+ for (p = psk_key = opt_arg(); *p; p++) {
+ if (isxdigit(_UC(*p)))
+ continue;
+ BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key);
+ goto end;
+ }
+ break;
+ case OPT_PSK_SESS:
+ psksessf = opt_arg();
+ break;
+#ifndef OPENSSL_NO_SRP
+ case OPT_SRPUSER:
+ srp_arg.srplogin = opt_arg();
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+ break;
+ case OPT_SRPPASS:
+ srppass = opt_arg();
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+ break;
+ case OPT_SRP_STRENGTH:
+ srp_arg.strength = atoi(opt_arg());
+ BIO_printf(bio_err, "SRP minimal length for N is %d\n",
+ srp_arg.strength);
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+ break;
+ case OPT_SRP_LATEUSER:
+ srp_lateuser = 1;
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+ break;
+ case OPT_SRP_MOREGROUPS:
+ srp_arg.amp = 1;
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+ break;
+#endif
+ case OPT_SSL_CONFIG:
+ ssl_config = opt_arg();
+ break;
+ case OPT_SSL3:
+ min_version = SSL3_VERSION;
+ max_version = SSL3_VERSION;
+ break;
+ case OPT_TLS1_3:
+ min_version = TLS1_3_VERSION;
+ max_version = TLS1_3_VERSION;
+ break;
+ case OPT_TLS1_2:
+ min_version = TLS1_2_VERSION;
+ max_version = TLS1_2_VERSION;
+ break;
+ case OPT_TLS1_1:
+ min_version = TLS1_1_VERSION;
+ max_version = TLS1_1_VERSION;
+ break;
+ case OPT_TLS1:
+ min_version = TLS1_VERSION;
+ max_version = TLS1_VERSION;
+ break;
+ case OPT_DTLS:
+#ifndef OPENSSL_NO_DTLS
+ meth = DTLS_client_method();
+ socket_type = SOCK_DGRAM;
+ isdtls = 1;
+#endif
+ break;
+ case OPT_DTLS1:
+#ifndef OPENSSL_NO_DTLS1
+ meth = DTLS_client_method();
+ min_version = DTLS1_VERSION;
+ max_version = DTLS1_VERSION;
+ socket_type = SOCK_DGRAM;
+ isdtls = 1;
+#endif
+ break;
+ case OPT_DTLS1_2:
+#ifndef OPENSSL_NO_DTLS1_2
+ meth = DTLS_client_method();
+ min_version = DTLS1_2_VERSION;
+ max_version = DTLS1_2_VERSION;
+ socket_type = SOCK_DGRAM;
+ isdtls = 1;
+#endif
+ break;
+ case OPT_SCTP:
+#ifndef OPENSSL_NO_SCTP
+ protocol = IPPROTO_SCTP;
+#endif
+ break;
+ case OPT_TIMEOUT:
+#ifndef OPENSSL_NO_DTLS
+ enable_timeouts = 1;
+#endif
+ break;
+ case OPT_MTU:
+#ifndef OPENSSL_NO_DTLS
+ socket_mtu = atol(opt_arg());
+#endif
+ break;
+ case OPT_FALLBACKSCSV:
+ fallback_scsv = 1;
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format))
+ goto opthelp;
+ break;
+ case OPT_PASS:
+ passarg = opt_arg();
+ break;
+ case OPT_CERT_CHAIN:
+ chain_file = opt_arg();
+ break;
+ case OPT_KEY:
+ key_file = opt_arg();
+ break;
+ case OPT_RECONNECT:
+ reconnect = 5;
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_CHAINCAPATH:
+ chCApath = opt_arg();
+ break;
+ case OPT_VERIFYCAPATH:
+ vfyCApath = opt_arg();
+ break;
+ case OPT_BUILD_CHAIN:
+ build_chain = 1;
+ break;
+ case OPT_REQCAFILE:
+ ReqCAfile = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+#ifndef OPENSSL_NO_CT
+ case OPT_NOCT:
+ ct_validation = 0;
+ break;
+ case OPT_CT:
+ ct_validation = 1;
+ break;
+ case OPT_CTLOG_FILE:
+ ctlog_file = opt_arg();
+ break;
+#endif
+ case OPT_CHAINCAFILE:
+ chCAfile = opt_arg();
+ break;
+ case OPT_VERIFYCAFILE:
+ vfyCAfile = opt_arg();
+ break;
+ case OPT_DANE_TLSA_DOMAIN:
+ dane_tlsa_domain = opt_arg();
+ break;
+ case OPT_DANE_TLSA_RRDATA:
+ if (dane_tlsa_rrset == NULL)
+ dane_tlsa_rrset = sk_OPENSSL_STRING_new_null();
+ if (dane_tlsa_rrset == NULL ||
+ !sk_OPENSSL_STRING_push(dane_tlsa_rrset, opt_arg())) {
+ BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
+ goto end;
+ }
+ break;
+ case OPT_DANE_EE_NO_NAME:
+ dane_ee_no_name = 1;
+ break;
+ case OPT_NEXTPROTONEG:
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ next_proto_neg_in = opt_arg();
+#endif
+ break;
+ case OPT_ALPN:
+ alpn_in = opt_arg();
+ break;
+ case OPT_SERVERINFO:
+ p = opt_arg();
+ len = strlen(p);
+ for (start = 0, i = 0; i <= len; ++i) {
+ if (i == len || p[i] == ',') {
+ serverinfo_types[serverinfo_count] = atoi(p + start);
+ if (++serverinfo_count == MAX_SI_TYPES)
+ break;
+ start = i + 1;
+ }
+ }
+ break;
+ case OPT_STARTTLS:
+ if (!opt_pair(opt_arg(), services, &starttls_proto))
+ goto end;
+ break;
+ case OPT_SERVERNAME:
+ servername = opt_arg();
+ break;
+ case OPT_NOSERVERNAME:
+ noservername = 1;
+ break;
+ case OPT_USE_SRTP:
+#ifndef OPENSSL_NO_SRTP
+ srtp_profiles = opt_arg();
+#endif
+ break;
+ case OPT_KEYMATEXPORT:
+ keymatexportlabel = opt_arg();
+ break;
+ case OPT_KEYMATEXPORTLEN:
+ keymatexportlen = atoi(opt_arg());
+ break;
+ case OPT_ASYNC:
+ async = 1;
+ break;
+ case OPT_MAXFRAGLEN:
+ len = atoi(opt_arg());
+ switch (len) {
+ case 512:
+ maxfraglen = TLSEXT_max_fragment_length_512;
+ break;
+ case 1024:
+ maxfraglen = TLSEXT_max_fragment_length_1024;
+ break;
+ case 2048:
+ maxfraglen = TLSEXT_max_fragment_length_2048;
+ break;
+ case 4096:
+ maxfraglen = TLSEXT_max_fragment_length_4096;
+ break;
+ default:
+ BIO_printf(bio_err,
+ "%s: Max Fragment Len %u is out of permitted values",
+ prog, len);
+ goto opthelp;
+ }
+ break;
+ case OPT_MAX_SEND_FRAG:
+ max_send_fragment = atoi(opt_arg());
+ break;
+ case OPT_SPLIT_SEND_FRAG:
+ split_send_fragment = atoi(opt_arg());
+ break;
+ case OPT_MAX_PIPELINES:
+ max_pipelines = atoi(opt_arg());
+ break;
+ case OPT_READ_BUF:
+ read_buf_len = atoi(opt_arg());
+ break;
+ case OPT_KEYLOG_FILE:
+ keylog_file = opt_arg();
+ break;
+ case OPT_EARLY_DATA:
+ early_data_file = opt_arg();
+ break;
+ case OPT_ENABLE_PHA:
+ enable_pha = 1;
+ break;
+ }
+ }
+ if (count4or6 >= 2) {
+ BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog);
+ goto opthelp;
+ }
+ if (noservername) {
+ if (servername != NULL) {
+ BIO_printf(bio_err,
+ "%s: Can't use -servername and -noservername together\n",
+ prog);
+ goto opthelp;
+ }
+ if (dane_tlsa_domain != NULL) {
+ BIO_printf(bio_err,
+ "%s: Can't use -dane_tlsa_domain and -noservername together\n",
+ prog);
+ goto opthelp;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc == 1) {
+ /* If there's a positional argument, it's the equivalent of
+ * OPT_CONNECT.
+ * Don't allow -connect and a separate argument.
+ */
+ if (connectstr != NULL) {
+ BIO_printf(bio_err,
+ "%s: must not provide both -connect option and target parameter\n",
+ prog);
+ goto opthelp;
+ }
+ connect_type = use_inet;
+ freeandcopy(&connectstr, *opt_rest());
+ } else if (argc != 0) {
+ goto opthelp;
+ }
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
+ BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n");
+ goto opthelp;
+ }
+#endif
+ if (proxystr != NULL) {
+ int res;
+ char *tmp_host = host, *tmp_port = port;
+ if (connectstr == NULL) {
+ BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
+ goto opthelp;
+ }
+ res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
+ if (tmp_host != host)
+ OPENSSL_free(tmp_host);
+ if (tmp_port != port)
+ OPENSSL_free(tmp_port);
+ if (!res) {
+ BIO_printf(bio_err,
+ "%s: -proxy argument malformed or ambiguous\n", prog);
+ goto end;
+ }
+ } else {
+ int res = 1;
+ char *tmp_host = host, *tmp_port = port;
+ if (connectstr != NULL)
+ res = BIO_parse_hostserv(connectstr, &host, &port,
+ BIO_PARSE_PRIO_HOST);
+ if (tmp_host != host)
+ OPENSSL_free(tmp_host);
+ if (tmp_port != port)
+ OPENSSL_free(tmp_port);
+ if (!res) {
+ BIO_printf(bio_err,
+ "%s: -connect argument or target parameter malformed or ambiguous\n",
+ prog);
+ goto end;
+ }
+ }
+
+ if (bindstr != NULL) {
+ int res;
+ res = BIO_parse_hostserv(bindstr, &bindhost, &bindport,
+ BIO_PARSE_PRIO_HOST);
+ if (!res) {
+ BIO_printf(bio_err,
+ "%s: -bind argument parameter malformed or ambiguous\n",
+ prog);
+ goto end;
+ }
+ }
+
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) {
+ BIO_printf(bio_err,
+ "Can't use unix sockets and datagrams together\n");
+ goto end;
+ }
+#endif
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ if (socket_type != SOCK_DGRAM) {
+ BIO_printf(bio_err, "Can't use -sctp without DTLS\n");
+ goto end;
+ }
+ /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */
+ socket_type = SOCK_STREAM;
+ }
+#endif
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ next_proto.status = -1;
+ if (next_proto_neg_in) {
+ next_proto.data =
+ next_protos_parse(&next_proto.len, next_proto_neg_in);
+ if (next_proto.data == NULL) {
+ BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
+ goto end;
+ }
+ } else
+ next_proto.data = NULL;
+#endif
+
+ if (!app_passwd(passarg, NULL, &pass, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ if (key_file == NULL)
+ key_file = cert_file;
+
+ if (key_file != NULL) {
+ key = load_key(key_file, key_format, 0, pass, e,
+ "client certificate private key file");
+ if (key == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (cert_file != NULL) {
+ cert = load_cert(cert_file, cert_format, "client certificate file");
+ if (cert == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (chain_file != NULL) {
+ if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL,
+ "client certificate chain"))
+ goto end;
+ }
+
+ if (crl_file != NULL) {
+ X509_CRL *crl;
+ crl = load_crl(crl_file, crl_format);
+ if (crl == NULL) {
+ BIO_puts(bio_err, "Error loading CRL\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ crls = sk_X509_CRL_new_null();
+ if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
+ BIO_puts(bio_err, "Error adding CRL\n");
+ ERR_print_errors(bio_err);
+ X509_CRL_free(crl);
+ goto end;
+ }
+ }
+
+ if (!load_excert(&exc))
+ goto end;
+
+ if (bio_c_out == NULL) {
+ if (c_quiet && !c_debug) {
+ bio_c_out = BIO_new(BIO_s_null());
+ if (c_msg && bio_c_msg == NULL)
+ bio_c_msg = dup_bio_out(FORMAT_TEXT);
+ } else if (bio_c_out == NULL)
+ bio_c_out = dup_bio_out(FORMAT_TEXT);
+ }
+#ifndef OPENSSL_NO_SRP
+ if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+#endif
+
+ ctx = SSL_CTX_new(meth);
+ if (ctx == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
+
+ if (sdebug)
+ ssl_ctx_security_debug(ctx, sdebug);
+
+ if (!config_ctx(cctx, ssl_args, ctx))
+ goto end;
+
+ if (ssl_config != NULL) {
+ if (SSL_CTX_config(ctx, ssl_config) == 0) {
+ BIO_printf(bio_err, "Error using configuration \"%s\"\n",
+ ssl_config);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (min_version != 0
+ && SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
+ goto end;
+ if (max_version != 0
+ && SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
+ goto end;
+
+ if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
+ BIO_printf(bio_err, "Error setting verify params\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (async) {
+ SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
+ }
+
+ if (max_send_fragment > 0
+ && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
+ BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
+ prog, max_send_fragment);
+ goto end;
+ }
+
+ if (split_send_fragment > 0
+ && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) {
+ BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n",
+ prog, split_send_fragment);
+ goto end;
+ }
+
+ if (max_pipelines > 0
+ && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) {
+ BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n",
+ prog, max_pipelines);
+ goto end;
+ }
+
+ if (read_buf_len > 0) {
+ SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+ }
+
+ if (maxfraglen > 0
+ && !SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen)) {
+ BIO_printf(bio_err,
+ "%s: Max Fragment Length code %u is out of permitted values"
+ "\n", prog, maxfraglen);
+ goto end;
+ }
+
+ if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ crls, crl_download)) {
+ BIO_printf(bio_err, "Error loading store locations\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (ReqCAfile != NULL) {
+ STACK_OF(X509_NAME) *nm = sk_X509_NAME_new_null();
+
+ if (nm == NULL || !SSL_add_file_cert_subjects_to_stack(nm, ReqCAfile)) {
+ sk_X509_NAME_pop_free(nm, X509_NAME_free);
+ BIO_printf(bio_err, "Error loading CA names\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ SSL_CTX_set0_CA_list(ctx, nm);
+ }
+#ifndef OPENSSL_NO_ENGINE
+ if (ssl_client_engine) {
+ if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
+ BIO_puts(bio_err, "Error setting client auth engine\n");
+ ERR_print_errors(bio_err);
+ ENGINE_free(ssl_client_engine);
+ goto end;
+ }
+ ENGINE_free(ssl_client_engine);
+ }
+#endif
+
+#ifndef OPENSSL_NO_PSK
+ if (psk_key != NULL) {
+ if (c_debug)
+ BIO_printf(bio_c_out, "PSK key given, setting client callback\n");
+ SSL_CTX_set_psk_client_callback(ctx, psk_client_cb);
+ }
+#endif
+ if (psksessf != NULL) {
+ BIO *stmp = BIO_new_file(psksessf, "r");
+
+ if (stmp == NULL) {
+ BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
+ BIO_free(stmp);
+ if (psksess == NULL) {
+ BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (psk_key != NULL || psksess != NULL)
+ SSL_CTX_set_psk_use_session_callback(ctx, psk_use_session_cb);
+
+#ifndef OPENSSL_NO_SRTP
+ if (srtp_profiles != NULL) {
+ /* Returns 0 on success! */
+ if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) {
+ BIO_printf(bio_err, "Error setting SRTP profile\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+#endif
+
+ if (exc != NULL)
+ ssl_ctx_set_excert(ctx, exc);
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ if (next_proto.data != NULL)
+ SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
+#endif
+ if (alpn_in) {
+ size_t alpn_len;
+ unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);
+
+ if (alpn == NULL) {
+ BIO_printf(bio_err, "Error parsing -alpn argument\n");
+ goto end;
+ }
+ /* Returns 0 on success! */
+ if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0) {
+ BIO_printf(bio_err, "Error setting ALPN\n");
+ goto end;
+ }
+ OPENSSL_free(alpn);
+ }
+
+ for (i = 0; i < serverinfo_count; i++) {
+ if (!SSL_CTX_add_client_custom_ext(ctx,
+ serverinfo_types[i],
+ NULL, NULL, NULL,
+ serverinfo_cli_parse_cb, NULL)) {
+ BIO_printf(bio_err,
+ "Warning: Unable to add custom extension %u, skipping\n",
+ serverinfo_types[i]);
+ }
+ }
+
+ if (state)
+ SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
+
+#ifndef OPENSSL_NO_CT
+ /* Enable SCT processing, without early connection termination */
+ if (ct_validation &&
+ !SSL_CTX_enable_ct(ctx, SSL_CT_VALIDATION_PERMISSIVE)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (!ctx_set_ctlog_list_file(ctx, ctlog_file)) {
+ if (ct_validation) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ /*
+ * If CT validation is not enabled, the log list isn't needed so don't
+ * show errors or abort. We try to load it regardless because then we
+ * can show the names of the logs any SCTs came from (SCTs may be seen
+ * even with validation disabled).
+ */
+ ERR_clear_error();
+ }
+#endif
+
+ SSL_CTX_set_verify(ctx, verify, verify_callback);
+
+ if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ ssl_ctx_add_crls(ctx, crls, crl_download);
+
+ if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain))
+ goto end;
+
+ if (!noservername) {
+ tlsextcbp.biodebug = bio_err;
+ SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
+ }
+# ifndef OPENSSL_NO_SRP
+ if (srp_arg.srplogin) {
+ if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
+ BIO_printf(bio_err, "Unable to set SRP username\n");
+ goto end;
+ }
+ srp_arg.msg = c_msg;
+ srp_arg.debug = c_debug;
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
+ SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
+ SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
+ if (c_msg || c_debug || srp_arg.amp == 0)
+ SSL_CTX_set_srp_verify_param_callback(ctx,
+ ssl_srp_verify_param_cb);
+ }
+# endif
+
+ if (dane_tlsa_domain != NULL) {
+ if (SSL_CTX_dane_enable(ctx) <= 0) {
+ BIO_printf(bio_err,
+ "%s: Error enabling DANE TLSA authentication.\n",
+ prog);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ /*
+ * In TLSv1.3 NewSessionTicket messages arrive after the handshake and can
+ * come at any time. Therefore we use a callback to write out the session
+ * when we know about it. This approach works for < TLSv1.3 as well.
+ */
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT
+ | SSL_SESS_CACHE_NO_INTERNAL_STORE);
+ SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
+
+ if (set_keylog_file(ctx, keylog_file))
+ goto end;
+
+ con = SSL_new(ctx);
+ if (con == NULL)
+ goto end;
+
+ if (enable_pha)
+ SSL_set_post_handshake_auth(con, 1);
+
+ if (sess_in != NULL) {
+ SSL_SESSION *sess;
+ BIO *stmp = BIO_new_file(sess_in, "r");
+ if (stmp == NULL) {
+ BIO_printf(bio_err, "Can't open session file %s\n", sess_in);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
+ BIO_free(stmp);
+ if (sess == NULL) {
+ BIO_printf(bio_err, "Can't open session file %s\n", sess_in);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (!SSL_set_session(con, sess)) {
+ BIO_printf(bio_err, "Can't set session\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ SSL_SESSION_free(sess);
+ }
+
+ if (fallback_scsv)
+ SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV);
+
+ if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
+ if (servername == NULL)
+ servername = (host == NULL) ? "localhost" : host;
+ if (!SSL_set_tlsext_host_name(con, servername)) {
+ BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (dane_tlsa_domain != NULL) {
+ if (SSL_dane_enable(con, dane_tlsa_domain) <= 0) {
+ BIO_printf(bio_err, "%s: Error enabling DANE TLSA "
+ "authentication.\n", prog);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (dane_tlsa_rrset == NULL) {
+ BIO_printf(bio_err, "%s: DANE TLSA authentication requires at "
+ "least one -dane_tlsa_rrdata option.\n", prog);
+ goto end;
+ }
+ if (tlsa_import_rrset(con, dane_tlsa_rrset) <= 0) {
+ BIO_printf(bio_err, "%s: Failed to import any TLSA "
+ "records.\n", prog);
+ goto end;
+ }
+ if (dane_ee_no_name)
+ SSL_dane_set_flags(con, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
+ } else if (dane_tlsa_rrset != NULL) {
+ BIO_printf(bio_err, "%s: DANE TLSA authentication requires the "
+ "-dane_tlsa_domain option.\n", prog);
+ goto end;
+ }
+
+ re_start:
+ if (init_client(&s, host, port, bindhost, bindport, socket_family,
+ socket_type, protocol) == 0) {
+ BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
+ BIO_closesocket(s);
+ goto end;
+ }
+ BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
+
+ if (c_nbio) {
+ if (!BIO_socket_nbio(s, 1)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(bio_c_out, "Turned on non blocking io\n");
+ }
+#ifndef OPENSSL_NO_DTLS
+ if (isdtls) {
+ union BIO_sock_info_u peer_info;
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP)
+ sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
+ else
+#endif
+ sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+
+ if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ BIO_closesocket(s);
+ goto end;
+ }
+ if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
+ BIO_printf(bio_err, "getsockname:errno=%d\n",
+ get_last_socket_error());
+ BIO_ADDR_free(peer_info.addr);
+ BIO_closesocket(s);
+ goto end;
+ }
+
+ (void)BIO_ctrl_set_connected(sbio, peer_info.addr);
+ BIO_ADDR_free(peer_info.addr);
+ peer_info.addr = NULL;
+
+ if (enable_timeouts) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = DGRAM_RCV_TIMEOUT;
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = DGRAM_SND_TIMEOUT;
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
+ }
+
+ if (socket_mtu) {
+ if (socket_mtu < DTLS_get_link_min_mtu(con)) {
+ BIO_printf(bio_err, "MTU too small. Must be at least %ld\n",
+ DTLS_get_link_min_mtu(con));
+ BIO_free(sbio);
+ goto shut;
+ }
+ SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
+ if (!DTLS_set_link_mtu(con, socket_mtu)) {
+ BIO_printf(bio_err, "Failed to set MTU\n");
+ BIO_free(sbio);
+ goto shut;
+ }
+ } else {
+ /* want to do MTU discovery */
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
+ }
+ } else
+#endif /* OPENSSL_NO_DTLS */
+ sbio = BIO_new_socket(s, BIO_NOCLOSE);
+
+ if (nbio_test) {
+ BIO *test;
+
+ test = BIO_new(BIO_f_nbio_test());
+ sbio = BIO_push(test, sbio);
+ }
+
+ if (c_debug) {
+ BIO_set_callback(sbio, bio_dump_callback);
+ BIO_set_callback_arg(sbio, (char *)bio_c_out);
+ }
+ if (c_msg) {
+#ifndef OPENSSL_NO_SSL_TRACE
+ if (c_msg == 2)
+ SSL_set_msg_callback(con, SSL_trace);
+ else
+#endif
+ SSL_set_msg_callback(con, msg_cb);
+ SSL_set_msg_callback_arg(con, bio_c_msg ? bio_c_msg : bio_c_out);
+ }
+
+ if (c_tlsextdebug) {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_c_out);
+ }
+#ifndef OPENSSL_NO_OCSP
+ if (c_status_req) {
+ SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
+ SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
+ SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
+ }
+#endif
+
+ SSL_set_bio(con, sbio, sbio);
+ SSL_set_connect_state(con);
+
+ /* ok, lets connect */
+ if (fileno_stdin() > SSL_get_fd(con))
+ width = fileno_stdin() + 1;
+ else
+ width = SSL_get_fd(con) + 1;
+
+ read_tty = 1;
+ write_tty = 0;
+ tty_on = 0;
+ read_ssl = 1;
+ write_ssl = 1;
+
+ cbuf_len = 0;
+ cbuf_off = 0;
+ sbuf_len = 0;
+ sbuf_off = 0;
+
+ switch ((PROTOCOL_CHOICE) starttls_proto) {
+ case PROTO_OFF:
+ break;
+ case PROTO_LMTP:
+ case PROTO_SMTP:
+ {
+ /*
+ * This is an ugly hack that does a lot of assumptions. We do
+ * have to handle multi-line responses which may come in a single
+ * packet or not. We therefore have to use BIO_gets() which does
+ * need a buffering BIO. So during the initial chitchat we do
+ * push a buffering BIO into the chain that is removed again
+ * later on to not disturb the rest of the s_client operation.
+ */
+ int foundit = 0;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ /* Wait for multi-line response to end from LMTP or SMTP */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ } while (mbuf_len > 3 && mbuf[3] == '-');
+ if (protohost == NULL)
+ protohost = "mail.example.com";
+ if (starttls_proto == (int)PROTO_LMTP)
+ BIO_printf(fbio, "LHLO %s\r\n", protohost);
+ else
+ BIO_printf(fbio, "EHLO %s\r\n", protohost);
+ (void)BIO_flush(fbio);
+ /*
+ * Wait for multi-line response to end LHLO LMTP or EHLO SMTP
+ * response.
+ */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (strstr(mbuf, "STARTTLS"))
+ foundit = 1;
+ } while (mbuf_len > 3 && mbuf[3] == '-');
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (!foundit)
+ BIO_printf(bio_err,
+ "Didn't find STARTTLS in server response,"
+ " trying anyway...\n");
+ BIO_printf(sbio, "STARTTLS\r\n");
+ BIO_read(sbio, sbuf, BUFSIZZ);
+ }
+ break;
+ case PROTO_POP3:
+ {
+ BIO_read(sbio, mbuf, BUFSIZZ);
+ BIO_printf(sbio, "STLS\r\n");
+ mbuf_len = BIO_read(sbio, sbuf, BUFSIZZ);
+ if (mbuf_len < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto end;
+ }
+ }
+ break;
+ case PROTO_IMAP:
+ {
+ int foundit = 0;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ BIO_gets(fbio, mbuf, BUFSIZZ);
+ /* STARTTLS command requires CAPABILITY... */
+ BIO_printf(fbio, ". CAPABILITY\r\n");
+ (void)BIO_flush(fbio);
+ /* wait for multi-line CAPABILITY response */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (strstr(mbuf, "STARTTLS"))
+ foundit = 1;
+ }
+ while (mbuf_len > 3 && mbuf[0] != '.');
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (!foundit)
+ BIO_printf(bio_err,
+ "Didn't find STARTTLS in server response,"
+ " trying anyway...\n");
+ BIO_printf(sbio, ". STARTTLS\r\n");
+ BIO_read(sbio, sbuf, BUFSIZZ);
+ }
+ break;
+ case PROTO_FTP:
+ {
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ /* wait for multi-line response to end from FTP */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ }
+ while (mbuf_len > 3 && mbuf[3] == '-');
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ BIO_printf(sbio, "AUTH TLS\r\n");
+ BIO_read(sbio, sbuf, BUFSIZZ);
+ }
+ break;
+ case PROTO_XMPP:
+ case PROTO_XMPP_SERVER:
+ {
+ int seen = 0;
+ BIO_printf(sbio, "<stream:stream "
+ "xmlns:stream='http://etherx.jabber.org/streams' "
+ "xmlns='jabber:%s' to='%s' version='1.0'>",
+ starttls_proto == PROTO_XMPP ? "client" : "server",
+ protohost ? protohost : host);
+ seen = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (seen < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto end;
+ }
+ mbuf[seen] = '\0';
+ while (!strstr
+ (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")
+ && !strstr(mbuf,
+ "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\""))
+ {
+ seen = BIO_read(sbio, mbuf, BUFSIZZ);
+
+ if (seen <= 0)
+ goto shut;
+
+ mbuf[seen] = '\0';
+ }
+ BIO_printf(sbio,
+ "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
+ seen = BIO_read(sbio, sbuf, BUFSIZZ);
+ if (seen < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto shut;
+ }
+ sbuf[seen] = '\0';
+ if (!strstr(sbuf, "<proceed"))
+ goto shut;
+ mbuf[0] = '\0';
+ }
+ break;
+ case PROTO_TELNET:
+ {
+ static const unsigned char tls_do[] = {
+ /* IAC DO START_TLS */
+ 255, 253, 46
+ };
+ static const unsigned char tls_will[] = {
+ /* IAC WILL START_TLS */
+ 255, 251, 46
+ };
+ static const unsigned char tls_follows[] = {
+ /* IAC SB START_TLS FOLLOWS IAC SE */
+ 255, 250, 46, 1, 255, 240
+ };
+ int bytes;
+
+ /* Telnet server should demand we issue START_TLS */
+ bytes = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (bytes != 3 || memcmp(mbuf, tls_do, 3) != 0)
+ goto shut;
+ /* Agree to issue START_TLS and send the FOLLOWS sub-command */
+ BIO_write(sbio, tls_will, 3);
+ BIO_write(sbio, tls_follows, 6);
+ (void)BIO_flush(sbio);
+ /* Telnet server also sent the FOLLOWS sub-command */
+ bytes = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (bytes != 6 || memcmp(mbuf, tls_follows, 6) != 0)
+ goto shut;
+ }
+ break;
+ case PROTO_CONNECT:
+ {
+ enum {
+ error_proto, /* Wrong protocol, not even HTTP */
+ error_connect, /* CONNECT failed */
+ success
+ } foundit = error_connect;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr);
+ (void)BIO_flush(fbio);
+ /*
+ * The first line is the HTTP response. According to RFC 7230,
+ * it's formated exactly like this:
+ *
+ * HTTP/d.d ddd Reason text\r\n
+ */
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (mbuf_len < (int)strlen("HTTP/1.0 200")) {
+ BIO_printf(bio_err,
+ "%s: HTTP CONNECT failed, insufficient response "
+ "from proxy (got %d octets)\n", prog, mbuf_len);
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ goto shut;
+ }
+ if (mbuf[8] != ' ') {
+ BIO_printf(bio_err,
+ "%s: HTTP CONNECT failed, incorrect response "
+ "from proxy\n", prog);
+ foundit = error_proto;
+ } else if (mbuf[9] != '2') {
+ BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog,
+ &mbuf[9]);
+ } else {
+ foundit = success;
+ }
+ if (foundit != error_proto) {
+ /* Read past all following headers */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ } while (mbuf_len > 2);
+ }
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (foundit != success) {
+ goto shut;
+ }
+ }
+ break;
+ case PROTO_IRC:
+ {
+ int numeric;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ BIO_printf(fbio, "STARTTLS\r\n");
+ (void)BIO_flush(fbio);
+ width = SSL_get_fd(con) + 1;
+
+ do {
+ numeric = 0;
+
+ FD_ZERO(&readfds);
+ openssl_fdset(SSL_get_fd(con), &readfds);
+ timeout.tv_sec = S_CLIENT_IRC_READ_TIMEOUT;
+ timeout.tv_usec = 0;
+ /*
+ * If the IRCd doesn't respond within
+ * S_CLIENT_IRC_READ_TIMEOUT seconds, assume
+ * it doesn't support STARTTLS. Many IRCds
+ * will not give _any_ sort of response to a
+ * STARTTLS command when it's not supported.
+ */
+ if (!BIO_get_buffer_num_lines(fbio)
+ && !BIO_pending(fbio)
+ && !BIO_pending(sbio)
+ && select(width, (void *)&readfds, NULL, NULL,
+ &timeout) < 1) {
+ BIO_printf(bio_err,
+ "Timeout waiting for response (%d seconds).\n",
+ S_CLIENT_IRC_READ_TIMEOUT);
+ break;
+ }
+
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (mbuf_len < 1 || sscanf(mbuf, "%*s %d", &numeric) != 1)
+ break;
+ /* :example.net 451 STARTTLS :You have not registered */
+ /* :example.net 421 STARTTLS :Unknown command */
+ if ((numeric == 451 || numeric == 421)
+ && strstr(mbuf, "STARTTLS") != NULL) {
+ BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf);
+ break;
+ }
+ if (numeric == 691) {
+ BIO_printf(bio_err, "STARTTLS negotiation failed: ");
+ ERR_print_errors(bio_err);
+ break;
+ }
+ } while (numeric != 670);
+
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (numeric != 670) {
+ BIO_printf(bio_err, "Server does not support STARTTLS.\n");
+ ret = 1;
+ goto shut;
+ }
+ }
+ break;
+ case PROTO_MYSQL:
+ {
+ /* SSL request packet */
+ static const unsigned char ssl_req[] = {
+ /* payload_length, sequence_id */
+ 0x20, 0x00, 0x00, 0x01,
+ /* payload */
+ /* capability flags, CLIENT_SSL always set */
+ 0x85, 0xae, 0x7f, 0x00,
+ /* max-packet size */
+ 0x00, 0x00, 0x00, 0x01,
+ /* character set */
+ 0x21,
+ /* string[23] reserved (all [0]) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ int bytes = 0;
+ int ssl_flg = 0x800;
+ int pos;
+ const unsigned char *packet = (const unsigned char *)sbuf;
+
+ /* Receiving Initial Handshake packet. */
+ bytes = BIO_read(sbio, (void *)packet, BUFSIZZ);
+ if (bytes < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto shut;
+ /* Packet length[3], Packet number[1] + minimum payload[17] */
+ } else if (bytes < 21) {
+ BIO_printf(bio_err, "MySQL packet too short.\n");
+ goto shut;
+ } else if (bytes != (4 + packet[0] +
+ (packet[1] << 8) +
+ (packet[2] << 16))) {
+ BIO_printf(bio_err, "MySQL packet length does not match.\n");
+ goto shut;
+ /* protocol version[1] */
+ } else if (packet[4] != 0xA) {
+ BIO_printf(bio_err,
+ "Only MySQL protocol version 10 is supported.\n");
+ goto shut;
+ }
+
+ pos = 5;
+ /* server version[string+NULL] */
+ for (;;) {
+ if (pos >= bytes) {
+ BIO_printf(bio_err, "Cannot confirm server version. ");
+ goto shut;
+ } else if (packet[pos++] == '\0') {
+ break;
+ }
+ }
+
+ /* make sure we have at least 15 bytes left in the packet */
+ if (pos + 15 > bytes) {
+ BIO_printf(bio_err,
+ "MySQL server handshake packet is broken.\n");
+ goto shut;
+ }
+
+ pos += 12; /* skip over conn id[4] + SALT[8] */
+ if (packet[pos++] != '\0') { /* verify filler */
+ BIO_printf(bio_err,
+ "MySQL packet is broken.\n");
+ goto shut;
+ }
+
+ /* capability flags[2] */
+ if (!((packet[pos] + (packet[pos + 1] << 8)) & ssl_flg)) {
+ BIO_printf(bio_err, "MySQL server does not support SSL.\n");
+ goto shut;
+ }
+
+ /* Sending SSL Handshake packet. */
+ BIO_write(sbio, ssl_req, sizeof(ssl_req));
+ (void)BIO_flush(sbio);
+ }
+ break;
+ case PROTO_POSTGRES:
+ {
+ static const unsigned char ssl_request[] = {
+ /* Length SSLRequest */
+ 0, 0, 0, 8, 4, 210, 22, 47
+ };
+ int bytes;
+
+ /* Send SSLRequest packet */
+ BIO_write(sbio, ssl_request, 8);
+ (void)BIO_flush(sbio);
+
+ /* Reply will be a single S if SSL is enabled */
+ bytes = BIO_read(sbio, sbuf, BUFSIZZ);
+ if (bytes != 1 || sbuf[0] != 'S')
+ goto shut;
+ }
+ break;
+ case PROTO_NNTP:
+ {
+ int foundit = 0;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ BIO_gets(fbio, mbuf, BUFSIZZ);
+ /* STARTTLS command requires CAPABILITIES... */
+ BIO_printf(fbio, "CAPABILITIES\r\n");
+ (void)BIO_flush(fbio);
+ /* wait for multi-line CAPABILITIES response */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ if (strstr(mbuf, "STARTTLS"))
+ foundit = 1;
+ } while (mbuf_len > 1 && mbuf[0] != '.');
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (!foundit)
+ BIO_printf(bio_err,
+ "Didn't find STARTTLS in server response,"
+ " trying anyway...\n");
+ BIO_printf(sbio, "STARTTLS\r\n");
+ mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (mbuf_len < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto end;
+ }
+ mbuf[mbuf_len] = '\0';
+ if (strstr(mbuf, "382") == NULL) {
+ BIO_printf(bio_err, "STARTTLS failed: %s", mbuf);
+ goto shut;
+ }
+ }
+ break;
+ case PROTO_SIEVE:
+ {
+ int foundit = 0;
+ BIO *fbio = BIO_new(BIO_f_buffer());
+
+ BIO_push(fbio, sbio);
+ /* wait for multi-line response to end from Sieve */
+ do {
+ mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+ /*
+ * According to RFC 5804 § 1.7, capability
+ * is case-insensitive, make it uppercase
+ */
+ if (mbuf_len > 1 && mbuf[0] == '"') {
+ make_uppercase(mbuf);
+ if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0)
+ foundit = 1;
+ }
+ } while (mbuf_len > 1 && mbuf[0] == '"');
+ (void)BIO_flush(fbio);
+ BIO_pop(fbio);
+ BIO_free(fbio);
+ if (!foundit)
+ BIO_printf(bio_err,
+ "Didn't find STARTTLS in server response,"
+ " trying anyway...\n");
+ BIO_printf(sbio, "STARTTLS\r\n");
+ mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (mbuf_len < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto end;
+ }
+ mbuf[mbuf_len] = '\0';
+ if (mbuf_len < 2) {
+ BIO_printf(bio_err, "STARTTLS failed: %s", mbuf);
+ goto shut;
+ }
+ /*
+ * According to RFC 5804 § 2.2, response codes are case-
+ * insensitive, make it uppercase but preserve the response.
+ */
+ strncpy(sbuf, mbuf, 2);
+ make_uppercase(sbuf);
+ if (strncmp(sbuf, "OK", 2) != 0) {
+ BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf);
+ goto shut;
+ }
+ }
+ break;
+ case PROTO_LDAP:
+ {
+ /* StartTLS Operation according to RFC 4511 */
+ static char ldap_tls_genconf[] = "asn1=SEQUENCE:LDAPMessage\n"
+ "[LDAPMessage]\n"
+ "messageID=INTEGER:1\n"
+ "extendedReq=EXPLICIT:23A,IMPLICIT:0C,"
+ "FORMAT:ASCII,OCT:1.3.6.1.4.1.1466.20037\n";
+ long errline = -1;
+ char *genstr = NULL;
+ int result = -1;
+ ASN1_TYPE *atyp = NULL;
+ BIO *ldapbio = BIO_new(BIO_s_mem());
+ CONF *cnf = NCONF_new(NULL);
+
+ if (cnf == NULL) {
+ BIO_free(ldapbio);
+ goto end;
+ }
+ BIO_puts(ldapbio, ldap_tls_genconf);
+ if (NCONF_load_bio(cnf, ldapbio, &errline) <= 0) {
+ BIO_free(ldapbio);
+ NCONF_free(cnf);
+ if (errline <= 0) {
+ BIO_printf(bio_err, "NCONF_load_bio failed\n");
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Error on line %ld\n", errline);
+ goto end;
+ }
+ }
+ BIO_free(ldapbio);
+ genstr = NCONF_get_string(cnf, "default", "asn1");
+ if (genstr == NULL) {
+ NCONF_free(cnf);
+ BIO_printf(bio_err, "NCONF_get_string failed\n");
+ goto end;
+ }
+ atyp = ASN1_generate_nconf(genstr, cnf);
+ if (atyp == NULL) {
+ NCONF_free(cnf);
+ BIO_printf(bio_err, "ASN1_generate_nconf failed\n");
+ goto end;
+ }
+ NCONF_free(cnf);
+
+ /* Send SSLRequest packet */
+ BIO_write(sbio, atyp->value.sequence->data,
+ atyp->value.sequence->length);
+ (void)BIO_flush(sbio);
+ ASN1_TYPE_free(atyp);
+
+ mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
+ if (mbuf_len < 0) {
+ BIO_printf(bio_err, "BIO_read failed\n");
+ goto end;
+ }
+ result = ldap_ExtendedResponse_parse(mbuf, mbuf_len);
+ if (result < 0) {
+ BIO_printf(bio_err, "ldap_ExtendedResponse_parse failed\n");
+ goto shut;
+ } else if (result > 0) {
+ BIO_printf(bio_err, "STARTTLS failed, LDAP Result Code: %i\n",
+ result);
+ goto shut;
+ }
+ mbuf_len = 0;
+ }
+ break;
+ }
+
+ if (early_data_file != NULL
+ && ((SSL_get0_session(con) != NULL
+ && SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0)
+ || (psksess != NULL
+ && SSL_SESSION_get_max_early_data(psksess) > 0))) {
+ BIO *edfile = BIO_new_file(early_data_file, "r");
+ size_t readbytes, writtenbytes;
+ int finish = 0;
+
+ if (edfile == NULL) {
+ BIO_printf(bio_err, "Cannot open early data file\n");
+ goto shut;
+ }
+
+ while (!finish) {
+ if (!BIO_read_ex(edfile, cbuf, BUFSIZZ, &readbytes))
+ finish = 1;
+
+ while (!SSL_write_early_data(con, cbuf, readbytes, &writtenbytes)) {
+ switch (SSL_get_error(con, 0)) {
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ASYNC:
+ case SSL_ERROR_WANT_READ:
+ /* Just keep trying - busy waiting */
+ continue;
+ default:
+ BIO_printf(bio_err, "Error writing early data\n");
+ BIO_free(edfile);
+ ERR_print_errors(bio_err);
+ goto shut;
+ }
+ }
+ }
+
+ BIO_free(edfile);
+ }
+
+ for (;;) {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+
+ if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
+ timeoutp = &timeout;
+ else
+ timeoutp = NULL;
+
+ if (!SSL_is_init_finished(con) && SSL_total_renegotiations(con) == 0
+ && SSL_get_key_update_type(con) == SSL_KEY_UPDATE_NONE) {
+ in_init = 1;
+ tty_on = 0;
+ } else {
+ tty_on = 1;
+ if (in_init) {
+ in_init = 0;
+
+ if (c_brief) {
+ BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
+ print_ssl_summary(con);
+ }
+
+ print_stuff(bio_c_out, con, full_log);
+ if (full_log > 0)
+ full_log--;
+
+ if (starttls_proto) {
+ BIO_write(bio_err, mbuf, mbuf_len);
+ /* We don't need to know any more */
+ if (!reconnect)
+ starttls_proto = PROTO_OFF;
+ }
+
+ if (reconnect) {
+ reconnect--;
+ BIO_printf(bio_c_out,
+ "drop connection and then reconnect\n");
+ do_ssl_shutdown(con);
+ SSL_set_connect_state(con);
+ BIO_closesocket(SSL_get_fd(con));
+ goto re_start;
+ }
+ }
+ }
+
+ ssl_pending = read_ssl && SSL_has_pending(con);
+
+ if (!ssl_pending) {
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
+ if (tty_on) {
+ /*
+ * Note that select() returns when read _would not block_,
+ * and EOF satisfies that. To avoid a CPU-hogging loop,
+ * set the flag so we exit.
+ */
+ if (read_tty && !at_eof)
+ openssl_fdset(fileno_stdin(), &readfds);
+#if !defined(OPENSSL_SYS_VMS)
+ if (write_tty)
+ openssl_fdset(fileno_stdout(), &writefds);
+#endif
+ }
+ if (read_ssl)
+ openssl_fdset(SSL_get_fd(con), &readfds);
+ if (write_ssl)
+ openssl_fdset(SSL_get_fd(con), &writefds);
+#else
+ if (!tty_on || !write_tty) {
+ if (read_ssl)
+ openssl_fdset(SSL_get_fd(con), &readfds);
+ if (write_ssl)
+ openssl_fdset(SSL_get_fd(con), &writefds);
+ }
+#endif
+
+ /*
+ * Note: under VMS with SOCKETSHR the second parameter is
+ * currently of type (int *) whereas under other systems it is
+ * (void *) if you don't have a cast it will choke the compiler:
+ * if you do have a cast then you can either go for (int *) or
+ * (void *).
+ */
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+ /*
+ * Under Windows/DOS we make the assumption that we can always
+ * write to the tty: therefore if we need to write to the tty we
+ * just fall through. Otherwise we timeout the select every
+ * second and see if there are any keypresses. Note: this is a
+ * hack, in a proper Windows application we wouldn't do this.
+ */
+ i = 0;
+ if (!write_tty) {
+ if (read_tty) {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ i = select(width, (void *)&readfds, (void *)&writefds,
+ NULL, &tv);
+ if (!i && (!has_stdin_waiting() || !read_tty))
+ continue;
+ } else
+ i = select(width, (void *)&readfds, (void *)&writefds,
+ NULL, timeoutp);
+ }
+#else
+ i = select(width, (void *)&readfds, (void *)&writefds,
+ NULL, timeoutp);
+#endif
+ if (i < 0) {
+ BIO_printf(bio_err, "bad select %d\n",
+ get_last_socket_error());
+ goto shut;
+ }
+ }
+
+ if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0)
+ BIO_printf(bio_err, "TIMEOUT occurred\n");
+
+ if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) {
+ k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len);
+ switch (SSL_get_error(con, k)) {
+ case SSL_ERROR_NONE:
+ cbuf_off += k;
+ cbuf_len -= k;
+ if (k <= 0)
+ goto end;
+ /* we have done a write(con,NULL,0); */
+ if (cbuf_len <= 0) {
+ read_tty = 1;
+ write_ssl = 0;
+ } else { /* if (cbuf_len > 0) */
+
+ read_tty = 0;
+ write_ssl = 1;
+ }
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_printf(bio_c_out, "write W BLOCK\n");
+ write_ssl = 1;
+ read_tty = 0;
+ break;
+ case SSL_ERROR_WANT_ASYNC:
+ BIO_printf(bio_c_out, "write A BLOCK\n");
+ wait_for_async(con);
+ write_ssl = 1;
+ read_tty = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_printf(bio_c_out, "write R BLOCK\n");
+ write_tty = 0;
+ read_ssl = 1;
+ write_ssl = 0;
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_printf(bio_c_out, "write X BLOCK\n");
+ break;
+ case SSL_ERROR_ZERO_RETURN:
+ if (cbuf_len != 0) {
+ BIO_printf(bio_c_out, "shutdown\n");
+ ret = 0;
+ goto shut;
+ } else {
+ read_tty = 1;
+ write_ssl = 0;
+ break;
+ }
+
+ case SSL_ERROR_SYSCALL:
+ if ((k != 0) || (cbuf_len != 0)) {
+ BIO_printf(bio_err, "write:errno=%d\n",
+ get_last_socket_error());
+ goto shut;
+ } else {
+ read_tty = 1;
+ write_ssl = 0;
+ }
+ break;
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /* This shouldn't ever happen in s_client - treat as an error */
+ case SSL_ERROR_SSL:
+ ERR_print_errors(bio_err);
+ goto shut;
+ }
+ }
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VMS)
+ /* Assume Windows/DOS/BeOS can always write */
+ else if (!ssl_pending && write_tty)
+#else
+ else if (!ssl_pending && FD_ISSET(fileno_stdout(), &writefds))
+#endif
+ {
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(&(sbuf[sbuf_off]), &(sbuf[sbuf_off]), sbuf_len);
+#endif
+ i = raw_write_stdout(&(sbuf[sbuf_off]), sbuf_len);
+
+ if (i <= 0) {
+ BIO_printf(bio_c_out, "DONE\n");
+ ret = 0;
+ goto shut;
+ }
+
+ sbuf_len -= i;
+ sbuf_off += i;
+ if (sbuf_len <= 0) {
+ read_ssl = 1;
+ write_tty = 0;
+ }
+ } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) {
+#ifdef RENEG
+ {
+ static int iiii;
+ if (++iiii == 52) {
+ SSL_renegotiate(con);
+ iiii = 0;
+ }
+ }
+#endif
+ k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );
+
+ switch (SSL_get_error(con, k)) {
+ case SSL_ERROR_NONE:
+ if (k <= 0)
+ goto end;
+ sbuf_off = 0;
+ sbuf_len = k;
+
+ read_ssl = 0;
+ write_tty = 1;
+ break;
+ case SSL_ERROR_WANT_ASYNC:
+ BIO_printf(bio_c_out, "read A BLOCK\n");
+ wait_for_async(con);
+ write_tty = 0;
+ read_ssl = 1;
+ if ((read_tty == 0) && (write_ssl == 0))
+ write_ssl = 1;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_printf(bio_c_out, "read W BLOCK\n");
+ write_ssl = 1;
+ read_tty = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_printf(bio_c_out, "read R BLOCK\n");
+ write_tty = 0;
+ read_ssl = 1;
+ if ((read_tty == 0) && (write_ssl == 0))
+ write_ssl = 1;
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_printf(bio_c_out, "read X BLOCK\n");
+ break;
+ case SSL_ERROR_SYSCALL:
+ ret = get_last_socket_error();
+ if (c_brief)
+ BIO_puts(bio_err, "CONNECTION CLOSED BY SERVER\n");
+ else
+ BIO_printf(bio_err, "read:errno=%d\n", ret);
+ goto shut;
+ case SSL_ERROR_ZERO_RETURN:
+ BIO_printf(bio_c_out, "closed\n");
+ ret = 0;
+ goto shut;
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /* This shouldn't ever happen in s_client. Treat as an error */
+ case SSL_ERROR_SSL:
+ ERR_print_errors(bio_err);
+ goto shut;
+ }
+ }
+/* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */
+#if defined(OPENSSL_SYS_MSDOS)
+ else if (has_stdin_waiting())
+#else
+ else if (FD_ISSET(fileno_stdin(), &readfds))
+#endif
+ {
+ if (crlf) {
+ int j, lf_num;
+
+ i = raw_read_stdin(cbuf, BUFSIZZ / 2);
+ lf_num = 0;
+ /* both loops are skipped when i <= 0 */
+ for (j = 0; j < i; j++)
+ if (cbuf[j] == '\n')
+ lf_num++;
+ for (j = i - 1; j >= 0; j--) {
+ cbuf[j + lf_num] = cbuf[j];
+ if (cbuf[j] == '\n') {
+ lf_num--;
+ i++;
+ cbuf[j + lf_num] = '\r';
+ }
+ }
+ assert(lf_num == 0);
+ } else
+ i = raw_read_stdin(cbuf, BUFSIZZ);
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
+ if (i == 0)
+ at_eof = 1;
+#endif
+
+ if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) {
+ BIO_printf(bio_err, "DONE\n");
+ ret = 0;
+ goto shut;
+ }
+
+ if ((!c_ign_eof) && (cbuf[0] == 'R' && cmdletters)) {
+ BIO_printf(bio_err, "RENEGOTIATING\n");
+ SSL_renegotiate(con);
+ cbuf_len = 0;
+ }
+
+ if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' )
+ && cmdletters) {
+ BIO_printf(bio_err, "KEYUPDATE\n");
+ SSL_key_update(con,
+ cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED
+ : SSL_KEY_UPDATE_NOT_REQUESTED);
+ cbuf_len = 0;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) {
+ BIO_printf(bio_err, "HEARTBEATING\n");
+ SSL_heartbeat(con);
+ cbuf_len = 0;
+ }
+#endif
+ else {
+ cbuf_len = i;
+ cbuf_off = 0;
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(cbuf, cbuf, i);
+#endif
+ }
+
+ write_ssl = 1;
+ read_tty = 0;
+ }
+ }
+
+ ret = 0;
+ shut:
+ if (in_init)
+ print_stuff(bio_c_out, con, full_log);
+ do_ssl_shutdown(con);
+
+ /*
+ * If we ended with an alert being sent, but still with data in the
+ * network buffer to be read, then calling BIO_closesocket() will
+ * result in a TCP-RST being sent. On some platforms (notably
+ * Windows) then this will result in the peer immediately abandoning
+ * the connection including any buffered alert data before it has
+ * had a chance to be read. Shutting down the sending side first,
+ * and then closing the socket sends TCP-FIN first followed by
+ * TCP-RST. This seems to allow the peer to read the alert data.
+ */
+ shutdown(SSL_get_fd(con), 1); /* SHUT_WR */
+ /*
+ * We just said we have nothing else to say, but it doesn't mean that
+ * the other side has nothing. It's even recommended to consume incoming
+ * data. [In testing context this ensures that alerts are passed on...]
+ */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000; /* some extreme round-trip */
+ do {
+ FD_ZERO(&readfds);
+ openssl_fdset(s, &readfds);
+ } while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0
+ && BIO_read(sbio, sbuf, BUFSIZZ) > 0);
+
+ BIO_closesocket(SSL_get_fd(con));
+ end:
+ if (con != NULL) {
+ if (prexit != 0)
+ print_stuff(bio_c_out, con, 1);
+ SSL_free(con);
+ }
+ SSL_SESSION_free(psksess);
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ OPENSSL_free(next_proto.data);
+#endif
+ SSL_CTX_free(ctx);
+ set_keylog_file(NULL, NULL);
+ X509_free(cert);
+ sk_X509_CRL_pop_free(crls, X509_CRL_free);
+ EVP_PKEY_free(key);
+ sk_X509_pop_free(chain, X509_free);
+ OPENSSL_free(pass);
+#ifndef OPENSSL_NO_SRP
+ OPENSSL_free(srp_arg.srppassin);
+#endif
+ OPENSSL_free(connectstr);
+ OPENSSL_free(bindstr);
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ X509_VERIFY_PARAM_free(vpm);
+ ssl_excert_free(exc);
+ sk_OPENSSL_STRING_free(ssl_args);
+ sk_OPENSSL_STRING_free(dane_tlsa_rrset);
+ SSL_CONF_CTX_free(cctx);
+ OPENSSL_clear_free(cbuf, BUFSIZZ);
+ OPENSSL_clear_free(sbuf, BUFSIZZ);
+ OPENSSL_clear_free(mbuf, BUFSIZZ);
+ release_engine(e);
+ BIO_free(bio_c_out);
+ bio_c_out = NULL;
+ BIO_free(bio_c_msg);
+ bio_c_msg = NULL;
+ return ret;
+}
+
+static void print_stuff(BIO *bio, SSL *s, int full)
+{
+ X509 *peer = NULL;
+ STACK_OF(X509) *sk;
+ const SSL_CIPHER *c;
+ int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
+ long verify_result;
+#ifndef OPENSSL_NO_COMP
+ const COMP_METHOD *comp, *expansion;
+#endif
+ unsigned char *exportedkeymat;
+#ifndef OPENSSL_NO_CT
+ const SSL_CTX *ctx = SSL_get_SSL_CTX(s);
+#endif
+
+ if (full) {
+ int got_a_chain = 0;
+
+ sk = SSL_get_peer_cert_chain(s);
+ if (sk != NULL) {
+ got_a_chain = 1;
+
+ BIO_printf(bio, "---\nCertificate chain\n");
+ for (i = 0; i < sk_X509_num(sk); i++) {
+ BIO_printf(bio, "%2d s:", i);
+ X509_NAME_print_ex(bio, X509_get_subject_name(sk_X509_value(sk, i)), 0, get_nameopt());
+ BIO_puts(bio, "\n");
+ BIO_printf(bio, " i:");
+ X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt());
+ BIO_puts(bio, "\n");
+ if (c_showcerts)
+ PEM_write_bio_X509(bio, sk_X509_value(sk, i));
+ }
+ }
+
+ BIO_printf(bio, "---\n");
+ peer = SSL_get_peer_certificate(s);
+ if (peer != NULL) {
+ BIO_printf(bio, "Server certificate\n");
+
+ /* Redundant if we showed the whole chain */
+ if (!(c_showcerts && got_a_chain))
+ PEM_write_bio_X509(bio, peer);
+ dump_cert_text(bio, peer);
+ } else {
+ BIO_printf(bio, "no peer certificate available\n");
+ }
+ print_ca_names(bio, s);
+
+ ssl_print_sigalgs(bio, s);
+ ssl_print_tmp_key(bio, s);
+
+#ifndef OPENSSL_NO_CT
+ /*
+ * When the SSL session is anonymous, or resumed via an abbreviated
+ * handshake, no SCTs are provided as part of the handshake. While in
+ * a resumed session SCTs may be present in the session's certificate,
+ * no callbacks are invoked to revalidate these, and in any case that
+ * set of SCTs may be incomplete. Thus it makes little sense to
+ * attempt to display SCTs from a resumed session's certificate, and of
+ * course none are associated with an anonymous peer.
+ */
+ if (peer != NULL && !SSL_session_reused(s) && SSL_ct_is_enabled(s)) {
+ const STACK_OF(SCT) *scts = SSL_get0_peer_scts(s);
+ int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
+
+ BIO_printf(bio, "---\nSCTs present (%i)\n", sct_count);
+ if (sct_count > 0) {
+ const CTLOG_STORE *log_store = SSL_CTX_get0_ctlog_store(ctx);
+
+ BIO_printf(bio, "---\n");
+ for (i = 0; i < sct_count; ++i) {
+ SCT *sct = sk_SCT_value(scts, i);
+
+ BIO_printf(bio, "SCT validation status: %s\n",
+ SCT_validation_status_string(sct));
+ SCT_print(sct, bio, 0, log_store);
+ if (i < sct_count - 1)
+ BIO_printf(bio, "\n---\n");
+ }
+ BIO_printf(bio, "\n");
+ }
+ }
+#endif
+
+ BIO_printf(bio,
+ "---\nSSL handshake has read %ju bytes "
+ "and written %ju bytes\n",
+ BIO_number_read(SSL_get_rbio(s)),
+ BIO_number_written(SSL_get_wbio(s)));
+ }
+ print_verify_detail(s, bio);
+ BIO_printf(bio, (SSL_session_reused(s) ? "---\nReused, " : "---\nNew, "));
+ c = SSL_get_current_cipher(s);
+ BIO_printf(bio, "%s, Cipher is %s\n",
+ SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
+ if (peer != NULL) {
+ EVP_PKEY *pktmp;
+
+ pktmp = X509_get0_pubkey(peer);
+ BIO_printf(bio, "Server public key is %d bit\n",
+ EVP_PKEY_bits(pktmp));
+ }
+ BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
+ SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
+#ifndef OPENSSL_NO_COMP
+ comp = SSL_get_current_compression(s);
+ expansion = SSL_get_current_expansion(s);
+ BIO_printf(bio, "Compression: %s\n",
+ comp ? SSL_COMP_get_name(comp) : "NONE");
+ BIO_printf(bio, "Expansion: %s\n",
+ expansion ? SSL_COMP_get_name(expansion) : "NONE");
+#endif
+
+#ifdef SSL_DEBUG
+ {
+ /* Print out local port of connection: useful for debugging */
+ int sock;
+ union BIO_sock_info_u info;
+
+ sock = SSL_get_fd(s);
+ if ((info.addr = BIO_ADDR_new()) != NULL
+ && BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &info)) {
+ BIO_printf(bio_c_out, "LOCAL PORT is %u\n",
+ ntohs(BIO_ADDR_rawport(info.addr)));
+ }
+ BIO_ADDR_free(info.addr);
+ }
+#endif
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ if (next_proto.status != -1) {
+ const unsigned char *proto;
+ unsigned int proto_len;
+ SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
+ BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
+ BIO_write(bio, proto, proto_len);
+ BIO_write(bio, "\n", 1);
+ }
+#endif
+ {
+ const unsigned char *proto;
+ unsigned int proto_len;
+ SSL_get0_alpn_selected(s, &proto, &proto_len);
+ if (proto_len > 0) {
+ BIO_printf(bio, "ALPN protocol: ");
+ BIO_write(bio, proto, proto_len);
+ BIO_write(bio, "\n", 1);
+ } else
+ BIO_printf(bio, "No ALPN negotiated\n");
+ }
+
+#ifndef OPENSSL_NO_SRTP
+ {
+ SRTP_PROTECTION_PROFILE *srtp_profile =
+ SSL_get_selected_srtp_profile(s);
+
+ if (srtp_profile)
+ BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n",
+ srtp_profile->name);
+ }
+#endif
+
+ if (istls13) {
+ switch (SSL_get_early_data_status(s)) {
+ case SSL_EARLY_DATA_NOT_SENT:
+ BIO_printf(bio, "Early data was not sent\n");
+ break;
+
+ case SSL_EARLY_DATA_REJECTED:
+ BIO_printf(bio, "Early data was rejected\n");
+ break;
+
+ case SSL_EARLY_DATA_ACCEPTED:
+ BIO_printf(bio, "Early data was accepted\n");
+ break;
+
+ }
+
+ /*
+ * We also print the verify results when we dump session information,
+ * but in TLSv1.3 we may not get that right away (or at all) depending
+ * on when we get a NewSessionTicket. Therefore we print it now as well.
+ */
+ verify_result = SSL_get_verify_result(s);
+ BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result,
+ X509_verify_cert_error_string(verify_result));
+ } else {
+ /* In TLSv1.3 we do this on arrival of a NewSessionTicket */
+ SSL_SESSION_print(bio, SSL_get_session(s));
+ }
+
+ if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) {
+ BIO_printf(bio, "Keying material exporter:\n");
+ BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
+ BIO_printf(bio, " Length: %i bytes\n", keymatexportlen);
+ exportedkeymat = app_malloc(keymatexportlen, "export key");
+ if (!SSL_export_keying_material(s, exportedkeymat,
+ keymatexportlen,
+ keymatexportlabel,
+ strlen(keymatexportlabel),
+ NULL, 0, 0)) {
+ BIO_printf(bio, " Error\n");
+ } else {
+ BIO_printf(bio, " Keying material: ");
+ for (i = 0; i < keymatexportlen; i++)
+ BIO_printf(bio, "%02X", exportedkeymat[i]);
+ BIO_printf(bio, "\n");
+ }
+ OPENSSL_free(exportedkeymat);
+ }
+ BIO_printf(bio, "---\n");
+ X509_free(peer);
+ /* flush, or debugging output gets mixed with http response */
+ (void)BIO_flush(bio);
+}
+
+# ifndef OPENSSL_NO_OCSP
+static int ocsp_resp_cb(SSL *s, void *arg)
+{
+ const unsigned char *p;
+ int len;
+ OCSP_RESPONSE *rsp;
+ len = SSL_get_tlsext_status_ocsp_resp(s, &p);
+ BIO_puts(arg, "OCSP response: ");
+ if (p == NULL) {
+ BIO_puts(arg, "no response sent\n");
+ return 1;
+ }
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
+ if (rsp == NULL) {
+ BIO_puts(arg, "response parse error\n");
+ BIO_dump_indent(arg, (char *)p, len, 4);
+ return 0;
+ }
+ BIO_puts(arg, "\n======================================\n");
+ OCSP_RESPONSE_print(arg, rsp, 0);
+ BIO_puts(arg, "======================================\n");
+ OCSP_RESPONSE_free(rsp);
+ return 1;
+}
+# endif
+
+static int ldap_ExtendedResponse_parse(const char *buf, long rem)
+{
+ const unsigned char *cur, *end;
+ long len;
+ int tag, xclass, inf, ret = -1;
+
+ cur = (const unsigned char *)buf;
+ end = cur + rem;
+
+ /*
+ * From RFC 4511:
+ *
+ * LDAPMessage ::= SEQUENCE {
+ * messageID MessageID,
+ * protocolOp CHOICE {
+ * ...
+ * extendedResp ExtendedResponse,
+ * ... },
+ * controls [0] Controls OPTIONAL }
+ *
+ * ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+ * COMPONENTS OF LDAPResult,
+ * responseName [10] LDAPOID OPTIONAL,
+ * responseValue [11] OCTET STRING OPTIONAL }
+ *
+ * LDAPResult ::= SEQUENCE {
+ * resultCode ENUMERATED {
+ * success (0),
+ * ...
+ * other (80),
+ * ... },
+ * matchedDN LDAPDN,
+ * diagnosticMessage LDAPString,
+ * referral [3] Referral OPTIONAL }
+ */
+
+ /* pull SEQUENCE */
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
+ if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE ||
+ (rem = end - cur, len > rem)) {
+ BIO_printf(bio_err, "Unexpected LDAP response\n");
+ goto end;
+ }
+
+ rem = len; /* ensure that we don't overstep the SEQUENCE */
+
+ /* pull MessageID */
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
+ if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_INTEGER ||
+ (rem = end - cur, len > rem)) {
+ BIO_printf(bio_err, "No MessageID\n");
+ goto end;
+ }
+
+ cur += len; /* shall we check for MessageId match or just skip? */
+
+ /* pull [APPLICATION 24] */
+ rem = end - cur;
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
+ if (inf != V_ASN1_CONSTRUCTED || xclass != V_ASN1_APPLICATION ||
+ tag != 24) {
+ BIO_printf(bio_err, "Not ExtendedResponse\n");
+ goto end;
+ }
+
+ /* pull resultCode */
+ rem = end - cur;
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
+ if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_ENUMERATED || len == 0 ||
+ (rem = end - cur, len > rem)) {
+ BIO_printf(bio_err, "Not LDAPResult\n");
+ goto end;
+ }
+
+ /* len should always be one, but just in case... */
+ for (ret = 0, inf = 0; inf < len; inf++) {
+ ret <<= 8;
+ ret |= cur[inf];
+ }
+ /* There is more data, but we don't care... */
+ end:
+ return ret;
+}
+
+#endif /* OPENSSL_NO_SOCK */
diff --git a/freebsd/crypto/openssl/apps/s_server.c b/freebsd/crypto/openssl/apps/s_server.c
new file mode 100644
index 00000000..acf9a7af
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_server.c
@@ -0,0 +1,3617 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(_WIN32)
+/* Included before async.h to avoid some warnings */
+# include <windows.h>
+#endif
+
+#include <openssl/e_os2.h>
+#include <openssl/async.h>
+#include <openssl/ssl.h>
+
+#ifndef OPENSSL_NO_SOCK
+
+/*
+ * With IPv6, it looks like Digital has mixed up the proper order of
+ * recursive header file inclusion, resulting in the compiler complaining
+ * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
+ * needed to have fileno() declared correctly... So let's define u_int
+ */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
+# define __U_INT
+typedef unsigned int u_int;
+#endif
+
+#include <openssl/bn.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/ocsp.h>
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_SRP
+# include <openssl/srp.h>
+#endif
+#include "s_apps.h"
+#include "timeouts.h"
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+#include "internal/sockets.h"
+
+static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
+static int sv_body(int s, int stype, int prot, unsigned char *context);
+static int www_body(int s, int stype, int prot, unsigned char *context);
+static int rev_body(int s, int stype, int prot, unsigned char *context);
+static void close_accept_socket(void);
+static int init_ssl_connection(SSL *s);
+static void print_stats(BIO *bp, SSL_CTX *ctx);
+static int generate_session_id(SSL *ssl, unsigned char *id,
+ unsigned int *id_len);
+static void init_session_cache_ctx(SSL_CTX *sctx);
+static void free_sessions(void);
+#ifndef OPENSSL_NO_DH
+static DH *load_dh_param(const char *dhfile);
+#endif
+static void print_connection_info(SSL *con);
+
+static const int bufsize = 16 * 1024;
+static int accept_socket = -1;
+
+#define TEST_CERT "server.pem"
+#define TEST_CERT2 "server2.pem"
+
+static int s_nbio = 0;
+static int s_nbio_test = 0;
+static int s_crlf = 0;
+static SSL_CTX *ctx = NULL;
+static SSL_CTX *ctx2 = NULL;
+static int www = 0;
+
+static BIO *bio_s_out = NULL;
+static BIO *bio_s_msg = NULL;
+static int s_debug = 0;
+static int s_tlsextdebug = 0;
+static int s_msg = 0;
+static int s_quiet = 0;
+static int s_ign_eof = 0;
+static int s_brief = 0;
+
+static char *keymatexportlabel = NULL;
+static int keymatexportlen = 20;
+
+static int async = 0;
+
+static const char *session_id_prefix = NULL;
+
+#ifndef OPENSSL_NO_DTLS
+static int enable_timeouts = 0;
+static long socket_mtu;
+#endif
+
+/*
+ * We define this but make it always be 0 in no-dtls builds to simplify the
+ * code.
+ */
+static int dtlslisten = 0;
+static int stateless = 0;
+
+static int early_data = 0;
+static SSL_SESSION *psksess = NULL;
+
+static char *psk_identity = "Client_identity";
+char *psk_key = NULL; /* by default PSK is not used */
+
+#ifndef OPENSSL_NO_PSK
+static unsigned int psk_server_cb(SSL *ssl, const char *identity,
+ unsigned char *psk,
+ unsigned int max_psk_len)
+{
+ long key_len = 0;
+ unsigned char *key;
+
+ if (s_debug)
+ BIO_printf(bio_s_out, "psk_server_cb\n");
+ if (identity == NULL) {
+ BIO_printf(bio_err, "Error: client did not send PSK identity\n");
+ goto out_err;
+ }
+ if (s_debug)
+ BIO_printf(bio_s_out, "identity_len=%d identity=%s\n",
+ (int)strlen(identity), identity);
+
+ /* here we could lookup the given identity e.g. from a database */
+ if (strcmp(identity, psk_identity) != 0) {
+ BIO_printf(bio_s_out, "PSK warning: client identity not what we expected"
+ " (got '%s' expected '%s')\n", identity, psk_identity);
+ } else {
+ if (s_debug)
+ BIO_printf(bio_s_out, "PSK client identity found\n");
+ }
+
+ /* convert the PSK key to binary */
+ key = OPENSSL_hexstr2buf(psk_key, &key_len);
+ if (key == NULL) {
+ BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
+ psk_key);
+ return 0;
+ }
+ if (key_len > (int)max_psk_len) {
+ BIO_printf(bio_err,
+ "psk buffer of callback is too small (%d) for key (%ld)\n",
+ max_psk_len, key_len);
+ OPENSSL_free(key);
+ return 0;
+ }
+
+ memcpy(psk, key, key_len);
+ OPENSSL_free(key);
+
+ if (s_debug)
+ BIO_printf(bio_s_out, "fetched PSK len=%ld\n", key_len);
+ return key_len;
+ out_err:
+ if (s_debug)
+ BIO_printf(bio_err, "Error in PSK server callback\n");
+ (void)BIO_flush(bio_err);
+ (void)BIO_flush(bio_s_out);
+ return 0;
+}
+#endif
+
+#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01")
+#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02")
+
+static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
+ size_t identity_len, SSL_SESSION **sess)
+{
+ SSL_SESSION *tmpsess = NULL;
+ unsigned char *key;
+ long key_len;
+ const SSL_CIPHER *cipher = NULL;
+
+ if (strlen(psk_identity) != identity_len
+ || memcmp(psk_identity, identity, identity_len) != 0) {
+ *sess = NULL;
+ return 1;
+ }
+
+ if (psksess != NULL) {
+ SSL_SESSION_up_ref(psksess);
+ *sess = psksess;
+ return 1;
+ }
+
+ key = OPENSSL_hexstr2buf(psk_key, &key_len);
+ if (key == NULL) {
+ BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
+ psk_key);
+ return 0;
+ }
+
+ /* We default to SHA256 */
+ cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id);
+ if (cipher == NULL) {
+ BIO_printf(bio_err, "Error finding suitable ciphersuite\n");
+ OPENSSL_free(key);
+ return 0;
+ }
+
+ tmpsess = SSL_SESSION_new();
+ if (tmpsess == NULL
+ || !SSL_SESSION_set1_master_key(tmpsess, key, key_len)
+ || !SSL_SESSION_set_cipher(tmpsess, cipher)
+ || !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) {
+ OPENSSL_free(key);
+ return 0;
+ }
+ OPENSSL_free(key);
+ *sess = tmpsess;
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+/* This is a context that we pass to callbacks */
+typedef struct srpsrvparm_st {
+ char *login;
+ SRP_VBASE *vb;
+ SRP_user_pwd *user;
+} srpsrvparm;
+static srpsrvparm srp_callback_parm;
+
+/*
+ * This callback pretends to require some asynchronous logic in order to
+ * obtain a verifier. When the callback is called for a new connection we
+ * return with a negative value. This will provoke the accept etc to return
+ * with an LOOKUP_X509. The main logic of the reinvokes the suspended call
+ * (which would normally occur after a worker has finished) and we set the
+ * user parameters.
+ */
+static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
+{
+ srpsrvparm *p = (srpsrvparm *) arg;
+ int ret = SSL3_AL_FATAL;
+
+ if (p->login == NULL && p->user == NULL) {
+ p->login = SSL_get_srp_username(s);
+ BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+ return -1;
+ }
+
+ if (p->user == NULL) {
+ BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
+ goto err;
+ }
+
+ if (SSL_set_srp_server_param
+ (s, p->user->N, p->user->g, p->user->s, p->user->v,
+ p->user->info) < 0) {
+ *ad = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ BIO_printf(bio_err,
+ "SRP parameters set: username = \"%s\" info=\"%s\" \n",
+ p->login, p->user->info);
+ ret = SSL_ERROR_NONE;
+
+ err:
+ SRP_user_pwd_free(p->user);
+ p->user = NULL;
+ p->login = NULL;
+ return ret;
+}
+
+#endif
+
+static int local_argc = 0;
+static char **local_argv;
+
+#ifdef CHARSET_EBCDIC
+static int ebcdic_new(BIO *bi);
+static int ebcdic_free(BIO *a);
+static int ebcdic_read(BIO *b, char *out, int outl);
+static int ebcdic_write(BIO *b, const char *in, int inl);
+static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr);
+static int ebcdic_gets(BIO *bp, char *buf, int size);
+static int ebcdic_puts(BIO *bp, const char *str);
+
+# define BIO_TYPE_EBCDIC_FILTER (18|0x0200)
+static BIO_METHOD *methods_ebcdic = NULL;
+
+/* This struct is "unwarranted chumminess with the compiler." */
+typedef struct {
+ size_t alloced;
+ char buff[1];
+} EBCDIC_OUTBUFF;
+
+static const BIO_METHOD *BIO_f_ebcdic_filter()
+{
+ if (methods_ebcdic == NULL) {
+ methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER,
+ "EBCDIC/ASCII filter");
+ if (methods_ebcdic == NULL
+ || !BIO_meth_set_write(methods_ebcdic, ebcdic_write)
+ || !BIO_meth_set_read(methods_ebcdic, ebcdic_read)
+ || !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts)
+ || !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets)
+ || !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl)
+ || !BIO_meth_set_create(methods_ebcdic, ebcdic_new)
+ || !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free))
+ return NULL;
+ }
+ return methods_ebcdic;
+}
+
+static int ebcdic_new(BIO *bi)
+{
+ EBCDIC_OUTBUFF *wbuf;
+
+ wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf");
+ wbuf->alloced = 1024;
+ wbuf->buff[0] = '\0';
+
+ BIO_set_data(bi, wbuf);
+ BIO_set_init(bi, 1);
+ return 1;
+}
+
+static int ebcdic_free(BIO *a)
+{
+ EBCDIC_OUTBUFF *wbuf;
+
+ if (a == NULL)
+ return 0;
+ wbuf = BIO_get_data(a);
+ OPENSSL_free(wbuf);
+ BIO_set_data(a, NULL);
+ BIO_set_init(a, 0);
+
+ return 1;
+}
+
+static int ebcdic_read(BIO *b, char *out, int outl)
+{
+ int ret = 0;
+ BIO *next = BIO_next(b);
+
+ if (out == NULL || outl == 0)
+ return 0;
+ if (next == NULL)
+ return 0;
+
+ ret = BIO_read(next, out, outl);
+ if (ret > 0)
+ ascii2ebcdic(out, out, ret);
+ return ret;
+}
+
+static int ebcdic_write(BIO *b, const char *in, int inl)
+{
+ EBCDIC_OUTBUFF *wbuf;
+ BIO *next = BIO_next(b);
+ int ret = 0;
+ int num;
+
+ if ((in == NULL) || (inl <= 0))
+ return 0;
+ if (next == NULL)
+ return 0;
+
+ wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b);
+
+ if (inl > (num = wbuf->alloced)) {
+ num = num + num; /* double the size */
+ if (num < inl)
+ num = inl;
+ OPENSSL_free(wbuf);
+ wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf");
+
+ wbuf->alloced = num;
+ wbuf->buff[0] = '\0';
+
+ BIO_set_data(b, wbuf);
+ }
+
+ ebcdic2ascii(wbuf->buff, in, inl);
+
+ ret = BIO_write(next, wbuf->buff, inl);
+
+ return ret;
+}
+
+static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ long ret;
+ BIO *next = BIO_next(b);
+
+ if (next == NULL)
+ return 0;
+ switch (cmd) {
+ case BIO_CTRL_DUP:
+ ret = 0L;
+ break;
+ default:
+ ret = BIO_ctrl(next, cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static int ebcdic_gets(BIO *bp, char *buf, int size)
+{
+ int i, ret = 0;
+ BIO *next = BIO_next(bp);
+
+ if (next == NULL)
+ return 0;
+/* return(BIO_gets(bp->next_bio,buf,size));*/
+ for (i = 0; i < size - 1; ++i) {
+ ret = ebcdic_read(bp, &buf[i], 1);
+ if (ret <= 0)
+ break;
+ else if (buf[i] == '\n') {
+ ++i;
+ break;
+ }
+ }
+ if (i < size)
+ buf[i] = '\0';
+ return (ret < 0 && i == 0) ? ret : i;
+}
+
+static int ebcdic_puts(BIO *bp, const char *str)
+{
+ if (BIO_next(bp) == NULL)
+ return 0;
+ return ebcdic_write(bp, str, strlen(str));
+}
+#endif
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+ char *servername;
+ BIO *biodebug;
+ int extension_error;
+} tlsextctx;
+
+static int ssl_servername_cb(SSL *s, int *ad, void *arg)
+{
+ tlsextctx *p = (tlsextctx *) arg;
+ const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
+
+ if (servername != NULL && p->biodebug != NULL) {
+ const char *cp = servername;
+ unsigned char uc;
+
+ BIO_printf(p->biodebug, "Hostname in TLS extension: \"");
+ while ((uc = *cp++) != 0)
+ BIO_printf(p->biodebug,
+ isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc);
+ BIO_printf(p->biodebug, "\"\n");
+ }
+
+ if (p->servername == NULL)
+ return SSL_TLSEXT_ERR_NOACK;
+
+ if (servername != NULL) {
+ if (strcasecmp(servername, p->servername))
+ return p->extension_error;
+ if (ctx2 != NULL) {
+ BIO_printf(p->biodebug, "Switching server context.\n");
+ SSL_set_SSL_CTX(s, ctx2);
+ }
+ }
+ return SSL_TLSEXT_ERR_OK;
+}
+
+/* Structure passed to cert status callback */
+typedef struct tlsextstatusctx_st {
+ int timeout;
+ /* File to load OCSP Response from (or NULL if no file) */
+ char *respin;
+ /* Default responder to use */
+ char *host, *path, *port;
+ int use_ssl;
+ int verbose;
+} tlsextstatusctx;
+
+static tlsextstatusctx tlscstatp = { -1 };
+
+#ifndef OPENSSL_NO_OCSP
+
+/*
+ * Helper function to get an OCSP_RESPONSE from a responder. This is a
+ * simplified version. It examines certificates each time and makes one OCSP
+ * responder query for each request. A full version would store details such as
+ * the OCSP certificate IDs and minimise the number of OCSP responses by caching
+ * them until they were considered "expired".
+ */
+static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
+ OCSP_RESPONSE **resp)
+{
+ char *host = NULL, *port = NULL, *path = NULL;
+ int use_ssl;
+ STACK_OF(OPENSSL_STRING) *aia = NULL;
+ X509 *x = NULL;
+ X509_STORE_CTX *inctx = NULL;
+ X509_OBJECT *obj;
+ OCSP_REQUEST *req = NULL;
+ OCSP_CERTID *id = NULL;
+ STACK_OF(X509_EXTENSION) *exts;
+ int ret = SSL_TLSEXT_ERR_NOACK;
+ int i;
+
+ /* Build up OCSP query from server certificate */
+ x = SSL_get_certificate(s);
+ aia = X509_get1_ocsp(x);
+ if (aia != NULL) {
+ if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
+ &host, &port, &path, &use_ssl)) {
+ BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
+ goto err;
+ }
+ if (srctx->verbose)
+ BIO_printf(bio_err, "cert_status: AIA URL: %s\n",
+ sk_OPENSSL_STRING_value(aia, 0));
+ } else {
+ if (srctx->host == NULL) {
+ BIO_puts(bio_err,
+ "cert_status: no AIA and no default responder URL\n");
+ goto done;
+ }
+ host = srctx->host;
+ path = srctx->path;
+ port = srctx->port;
+ use_ssl = srctx->use_ssl;
+ }
+
+ inctx = X509_STORE_CTX_new();
+ if (inctx == NULL)
+ goto err;
+ if (!X509_STORE_CTX_init(inctx,
+ SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
+ NULL, NULL))
+ goto err;
+ obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509,
+ X509_get_issuer_name(x));
+ if (obj == NULL) {
+ BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
+ goto done;
+ }
+ id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
+ X509_OBJECT_free(obj);
+ if (id == NULL)
+ goto err;
+ req = OCSP_REQUEST_new();
+ if (req == NULL)
+ goto err;
+ if (!OCSP_request_add0_id(req, id))
+ goto err;
+ id = NULL;
+ /* Add any extensions to the request */
+ SSL_get_tlsext_status_exts(s, &exts);
+ for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ if (!OCSP_REQUEST_add_ext(req, ext, -1))
+ goto err;
+ }
+ *resp = process_responder(req, host, path, port, use_ssl, NULL,
+ srctx->timeout);
+ if (*resp == NULL) {
+ BIO_puts(bio_err, "cert_status: error querying responder\n");
+ goto done;
+ }
+
+ ret = SSL_TLSEXT_ERR_OK;
+ goto done;
+
+ err:
+ ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+ done:
+ /*
+ * If we parsed aia we need to free; otherwise they were copied and we
+ * don't
+ */
+ if (aia != NULL) {
+ OPENSSL_free(host);
+ OPENSSL_free(path);
+ OPENSSL_free(port);
+ X509_email_free(aia);
+ }
+ OCSP_CERTID_free(id);
+ OCSP_REQUEST_free(req);
+ X509_STORE_CTX_free(inctx);
+ return ret;
+}
+
+/*
+ * Certificate Status callback. This is called when a client includes a
+ * certificate status request extension. The response is either obtained from a
+ * file, or from an OCSP responder.
+ */
+static int cert_status_cb(SSL *s, void *arg)
+{
+ tlsextstatusctx *srctx = arg;
+ OCSP_RESPONSE *resp = NULL;
+ unsigned char *rspder = NULL;
+ int rspderlen;
+ int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ if (srctx->verbose)
+ BIO_puts(bio_err, "cert_status: callback called\n");
+
+ if (srctx->respin != NULL) {
+ BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1);
+ if (derbio == NULL) {
+ BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n");
+ goto err;
+ }
+ resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
+ BIO_free(derbio);
+ if (resp == NULL) {
+ BIO_puts(bio_err, "cert_status: Error reading OCSP response\n");
+ goto err;
+ }
+ } else {
+ ret = get_ocsp_resp_from_responder(s, srctx, &resp);
+ if (ret != SSL_TLSEXT_ERR_OK)
+ goto err;
+ }
+
+ rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
+ if (rspderlen <= 0)
+ goto err;
+
+ SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
+ if (srctx->verbose) {
+ BIO_puts(bio_err, "cert_status: ocsp response sent:\n");
+ OCSP_RESPONSE_print(bio_err, resp, 2);
+ }
+
+ ret = SSL_TLSEXT_ERR_OK;
+
+ err:
+ if (ret != SSL_TLSEXT_ERR_OK)
+ ERR_print_errors(bio_err);
+
+ OCSP_RESPONSE_free(resp);
+
+ return ret;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/* This is the context that we pass to next_proto_cb */
+typedef struct tlsextnextprotoctx_st {
+ unsigned char *data;
+ size_t len;
+} tlsextnextprotoctx;
+
+static int next_proto_cb(SSL *s, const unsigned char **data,
+ unsigned int *len, void *arg)
+{
+ tlsextnextprotoctx *next_proto = arg;
+
+ *data = next_proto->data;
+ *len = next_proto->len;
+
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
+
+/* This the context that we pass to alpn_cb */
+typedef struct tlsextalpnctx_st {
+ unsigned char *data;
+ size_t len;
+} tlsextalpnctx;
+
+static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen, void *arg)
+{
+ tlsextalpnctx *alpn_ctx = arg;
+
+ if (!s_quiet) {
+ /* We can assume that |in| is syntactically valid. */
+ unsigned int i;
+ BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
+ for (i = 0; i < inlen;) {
+ if (i)
+ BIO_write(bio_s_out, ", ", 2);
+ BIO_write(bio_s_out, &in[i + 1], in[i]);
+ i += in[i] + 1;
+ }
+ BIO_write(bio_s_out, "\n", 1);
+ }
+
+ if (SSL_select_next_proto
+ ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
+ inlen) != OPENSSL_NPN_NEGOTIATED) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+
+ if (!s_quiet) {
+ BIO_printf(bio_s_out, "ALPN protocols selected: ");
+ BIO_write(bio_s_out, *out, *outlen);
+ BIO_write(bio_s_out, "\n", 1);
+ }
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
+{
+ /* disable resumption for sessions with forward secure ciphers */
+ return is_forward_secure;
+}
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE,
+ OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
+ OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL,
+ OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM,
+ OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT,
+ OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT,
+ OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
+ OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
+ OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE,
+ OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
+ OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
+ OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
+ OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE,
+ OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
+ OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK,
+ OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW,
+ OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG,
+ OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
+ OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
+ OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS,
+ OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
+ OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
+ OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
+ OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
+ OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY,
+ OPT_R_ENUM,
+ OPT_S_ENUM,
+ OPT_V_ENUM,
+ OPT_X_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS s_server_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"port", OPT_PORT, 'p',
+ "TCP/IP port to listen on for connections (default is " PORT ")"},
+ {"accept", OPT_ACCEPT, 's',
+ "TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"},
+#ifdef AF_UNIX
+ {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"},
+#endif
+ {"4", OPT_4, '-', "Use IPv4 only"},
+ {"6", OPT_6, '-', "Use IPv6 only"},
+#ifdef AF_UNIX
+ {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
+#endif
+ {"context", OPT_CONTEXT, 's', "Set session ID context"},
+ {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"},
+ {"Verify", OPT_UPPER_V_VERIFY, 'n',
+ "Turn on peer certificate verification, must have a cert"},
+ {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
+ {"serverinfo", OPT_SERVERINFO, 's',
+ "PEM serverinfo file for certificate"},
+ {"certform", OPT_CERTFORM, 'F',
+ "Certificate format (PEM or DER) PEM default"},
+ {"key", OPT_KEY, 's',
+ "Private Key if not in -cert; default is " TEST_CERT},
+ {"keyform", OPT_KEYFORM, 'f',
+ "Key format (PEM, DER or ENGINE) PEM default"},
+ {"pass", OPT_PASS, 's', "Private key file pass phrase source"},
+ {"dcert", OPT_DCERT, '<',
+ "Second certificate file to use (usually for DSA)"},
+ {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
+ {"dcertform", OPT_DCERTFORM, 'F',
+ "Second certificate format (PEM or DER) PEM default"},
+ {"dkey", OPT_DKEY, '<',
+ "Second private key file to use (usually for DSA)"},
+ {"dkeyform", OPT_DKEYFORM, 'F',
+ "Second key format (PEM, DER or ENGINE) PEM default"},
+ {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"},
+ {"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"},
+ {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
+ {"debug", OPT_DEBUG, '-', "Print more output"},
+ {"msg", OPT_MSG, '-', "Show protocol messages"},
+ {"msgfile", OPT_MSGFILE, '>',
+ "File to send output of -msg or -trace, instead of stdout"},
+ {"state", OPT_STATE, '-', "Print the SSL states"},
+ {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
+ {"quiet", OPT_QUIET, '-', "No server output"},
+ {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
+ "Disable caching and tickets if ephemeral (EC)DH is used"},
+ {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
+ {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
+ {"servername", OPT_SERVERNAME, 's',
+ "Servername for HostName TLS extension"},
+ {"servername_fatal", OPT_SERVERNAME_FATAL, '-',
+ "mismatch send fatal alert (default warning alert)"},
+ {"cert2", OPT_CERT2, '<',
+ "Certificate file to use for servername; default is" TEST_CERT2},
+ {"key2", OPT_KEY2, '<',
+ "-Private Key file to use for servername if not in -cert2"},
+ {"tlsextdebug", OPT_TLSEXTDEBUG, '-',
+ "Hex dump of all TLS extensions received"},
+ {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
+ {"id_prefix", OPT_ID_PREFIX, 's',
+ "Generate SSL/TLS session IDs prefixed by arg"},
+ OPT_R_OPTIONS,
+ {"keymatexport", OPT_KEYMATEXPORT, 's',
+ "Export keying material using label"},
+ {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
+ "Export len bytes of keying material (default 20)"},
+ {"CRL", OPT_CRL, '<', "CRL file to use"},
+ {"crl_download", OPT_CRL_DOWNLOAD, '-',
+ "Download CRL from distribution points"},
+ {"cert_chain", OPT_CERT_CHAIN, '<',
+ "certificate chain file in PEM format"},
+ {"dcert_chain", OPT_DCERT_CHAIN, '<',
+ "second certificate chain file in PEM format"},
+ {"chainCApath", OPT_CHAINCAPATH, '/',
+ "use dir as certificate store path to build CA certificate chain"},
+ {"verifyCApath", OPT_VERIFYCAPATH, '/',
+ "use dir as certificate store path to verify CA certificate"},
+ {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"},
+ {"ext_cache", OPT_EXT_CACHE, '-',
+ "Disable internal cache, setup and use external cache"},
+ {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
+ {"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
+ "Close connection on verification error"},
+ {"verify_quiet", OPT_VERIFY_QUIET, '-',
+ "No verify output except verify errors"},
+ {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
+ {"chainCAfile", OPT_CHAINCAFILE, '<',
+ "CA file for certificate chain (PEM format)"},
+ {"verifyCAfile", OPT_VERIFYCAFILE, '<',
+ "CA file for certificate verification (PEM format)"},
+ {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"},
+ {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"},
+#ifndef OPENSSL_NO_OCSP
+ {"status", OPT_STATUS, '-', "Request certificate status from server"},
+ {"status_verbose", OPT_STATUS_VERBOSE, '-',
+ "Print more output in certificate status callback"},
+ {"status_timeout", OPT_STATUS_TIMEOUT, 'n',
+ "Status request responder timeout"},
+ {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"},
+ {"status_file", OPT_STATUS_FILE, '<',
+ "File containing DER encoded OCSP Response"},
+#endif
+#ifndef OPENSSL_NO_SSL_TRACE
+ {"trace", OPT_TRACE, '-', "trace protocol messages"},
+#endif
+ {"security_debug", OPT_SECURITY_DEBUG, '-',
+ "Print output from SSL/TLS security framework"},
+ {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
+ "Print more output from SSL/TLS security framework"},
+ {"brief", OPT_BRIEF, '-',
+ "Restrict output to brief summary of connection parameters"},
+ {"rev", OPT_REV, '-',
+ "act as a simple test server which just sends back with the received text reversed"},
+ {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"},
+ {"ssl_config", OPT_SSL_CONFIG, 's',
+ "Configure SSL_CTX using the configuration 'val'"},
+ {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
+ {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
+ "Size used to split data for encrypt pipelines"},
+ {"max_pipelines", OPT_MAX_PIPELINES, 'p',
+ "Maximum number of encrypt/decrypt pipelines to be used"},
+ {"read_buf", OPT_READ_BUF, 'p',
+ "Default read buffer size to be used for connections"},
+ OPT_S_OPTIONS,
+ OPT_V_OPTIONS,
+ OPT_X_OPTIONS,
+ {"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
+ {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"},
+#ifndef OPENSSL_NO_PSK
+ {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"},
+#endif
+ {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
+ {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
+#ifndef OPENSSL_NO_SRP
+ {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"},
+ {"srpuserseed", OPT_SRPUSERSEED, 's',
+ "A seed string for a default user salt"},
+#endif
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+ {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+ {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ {"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"},
+#endif
+#ifndef OPENSSL_NO_DTLS
+ {"dtls", OPT_DTLS, '-', "Use any DTLS version"},
+ {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
+ {"mtu", OPT_MTU, 'p', "Set link layer MTU"},
+ {"listen", OPT_LISTEN, '-',
+ "Listen for a DTLS ClientHello with a cookie and then connect"},
+#endif
+ {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
+#ifndef OPENSSL_NO_DTLS1
+ {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
+#endif
+#ifndef OPENSSL_NO_DTLS1_2
+ {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
+#endif
+#ifndef OPENSSL_NO_SCTP
+ {"sctp", OPT_SCTP, '-', "Use SCTP"},
+#endif
+#ifndef OPENSSL_NO_DH
+ {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {"nextprotoneg", OPT_NEXTPROTONEG, 's',
+ "Set the advertised protocols for the NPN extension (comma-separated list)"},
+#endif
+#ifndef OPENSSL_NO_SRTP
+ {"use_srtp", OPT_SRTP_PROFILES, 's',
+ "Offer SRTP key management with a colon-separated profile list"},
+#endif
+ {"alpn", OPT_ALPN, 's',
+ "Set the advertised protocols for the ALPN extension (comma-separated list)"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
+ {"max_early_data", OPT_MAX_EARLY, 'n',
+ "The maximum number of bytes of early data as advertised in tickets"},
+ {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
+ "The maximum number of bytes of early data (hard limit)"},
+ {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
+ {"num_tickets", OPT_S_NUM_TICKETS, 'n',
+ "The number of TLSv1.3 session tickets that a server will automatically issue" },
+ {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
+ {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
+ {NULL, OPT_EOF, 0, NULL}
+};
+
+#define IS_PROT_FLAG(o) \
+ (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \
+ || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2)
+
+int s_server_main(int argc, char *argv[])
+{
+ ENGINE *engine = NULL;
+ EVP_PKEY *s_key = NULL, *s_dkey = NULL;
+ SSL_CONF_CTX *cctx = NULL;
+ const SSL_METHOD *meth = TLS_server_method();
+ SSL_EXCERT *exc = NULL;
+ STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
+ STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
+ STACK_OF(X509_CRL) *crls = NULL;
+ X509 *s_cert = NULL, *s_dcert = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
+ char *dpassarg = NULL, *dpass = NULL;
+ char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
+ char *crl_file = NULL, *prog;
+#ifdef AF_UNIX
+ int unlink_unix_path = 0;
+#endif
+ do_server_cb server_cb;
+ int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0;
+#ifndef OPENSSL_NO_DH
+ char *dhfile = NULL;
+ int no_dhe = 0;
+#endif
+ int nocert = 0, ret = 1;
+ int noCApath = 0, noCAfile = 0;
+ int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
+ int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
+ int rev = 0, naccept = -1, sdebug = 0;
+ int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
+ int state = 0, crl_format = FORMAT_PEM, crl_download = 0;
+ char *host = NULL;
+ char *port = BUF_strdup(PORT);
+ unsigned char *context = NULL;
+ OPTION_CHOICE o;
+ EVP_PKEY *s_key2 = NULL;
+ X509 *s_cert2 = NULL;
+ tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
+ const char *ssl_config = NULL;
+ int read_buf_len = 0;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ const char *next_proto_neg_in = NULL;
+ tlsextnextprotoctx next_proto = { NULL, 0 };
+#endif
+ const char *alpn_in = NULL;
+ tlsextalpnctx alpn_ctx = { NULL, 0 };
+#ifndef OPENSSL_NO_PSK
+ /* by default do not send a PSK identity hint */
+ char *psk_identity_hint = NULL;
+#endif
+ char *p;
+#ifndef OPENSSL_NO_SRP
+ char *srpuserseed = NULL;
+ char *srp_verifier_file = NULL;
+#endif
+#ifndef OPENSSL_NO_SRTP
+ char *srtp_profiles = NULL;
+#endif
+ int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0;
+ int s_server_verify = SSL_VERIFY_NONE;
+ int s_server_session_id_context = 1; /* anything will do */
+ const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL;
+ const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL;
+ char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
+#ifndef OPENSSL_NO_OCSP
+ int s_tlsextstatus = 0;
+#endif
+ int no_resume_ephemeral = 0;
+ unsigned int max_send_fragment = 0;
+ unsigned int split_send_fragment = 0, max_pipelines = 0;
+ const char *s_serverinfo_file = NULL;
+ const char *keylog_file = NULL;
+ int max_early_data = -1, recv_max_early_data = -1;
+ char *psksessf = NULL;
+
+ /* Init of few remaining global variables */
+ local_argc = argc;
+ local_argv = argv;
+
+ ctx = ctx2 = NULL;
+ s_nbio = s_nbio_test = 0;
+ www = 0;
+ bio_s_out = NULL;
+ s_debug = 0;
+ s_msg = 0;
+ s_quiet = 0;
+ s_brief = 0;
+ async = 0;
+
+ cctx = SSL_CONF_CTX_new();
+ vpm = X509_VERIFY_PARAM_new();
+ if (cctx == NULL || vpm == NULL)
+ goto end;
+ SSL_CONF_CTX_set_flags(cctx,
+ SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE);
+
+ prog = opt_init(argc, argv, s_server_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ if (IS_PROT_FLAG(o) && ++prot_opt > 1) {
+ BIO_printf(bio_err, "Cannot supply multiple protocol flags\n");
+ goto end;
+ }
+ if (IS_NO_PROT_FLAG(o))
+ no_prot_opt++;
+ if (prot_opt == 1 && no_prot_opt) {
+ BIO_printf(bio_err,
+ "Cannot supply both a protocol flag and '-no_<prot>'\n");
+ goto end;
+ }
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(s_server_options);
+ ret = 0;
+ goto end;
+
+ case OPT_4:
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX) {
+ OPENSSL_free(host); host = NULL;
+ OPENSSL_free(port); port = NULL;
+ }
+#endif
+ socket_family = AF_INET;
+ break;
+ case OPT_6:
+ if (1) {
+#ifdef AF_INET6
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX) {
+ OPENSSL_free(host); host = NULL;
+ OPENSSL_free(port); port = NULL;
+ }
+#endif
+ socket_family = AF_INET6;
+ } else {
+#endif
+ BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog);
+ goto end;
+ }
+ break;
+ case OPT_PORT:
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX) {
+ socket_family = AF_UNSPEC;
+ }
+#endif
+ OPENSSL_free(port); port = NULL;
+ OPENSSL_free(host); host = NULL;
+ if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) {
+ BIO_printf(bio_err,
+ "%s: -port argument malformed or ambiguous\n",
+ port);
+ goto end;
+ }
+ break;
+ case OPT_ACCEPT:
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX) {
+ socket_family = AF_UNSPEC;
+ }
+#endif
+ OPENSSL_free(port); port = NULL;
+ OPENSSL_free(host); host = NULL;
+ if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) {
+ BIO_printf(bio_err,
+ "%s: -accept argument malformed or ambiguous\n",
+ port);
+ goto end;
+ }
+ break;
+#ifdef AF_UNIX
+ case OPT_UNIX:
+ socket_family = AF_UNIX;
+ OPENSSL_free(host); host = BUF_strdup(opt_arg());
+ OPENSSL_free(port); port = NULL;
+ break;
+ case OPT_UNLINK:
+ unlink_unix_path = 1;
+ break;
+#endif
+ case OPT_NACCEPT:
+ naccept = atol(opt_arg());
+ break;
+ case OPT_VERIFY:
+ s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+ verify_args.depth = atoi(opt_arg());
+ if (!s_quiet)
+ BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth);
+ break;
+ case OPT_UPPER_V_VERIFY:
+ s_server_verify =
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
+ SSL_VERIFY_CLIENT_ONCE;
+ verify_args.depth = atoi(opt_arg());
+ if (!s_quiet)
+ BIO_printf(bio_err,
+ "verify depth is %d, must return a certificate\n",
+ verify_args.depth);
+ break;
+ case OPT_CONTEXT:
+ context = (unsigned char *)opt_arg();
+ break;
+ case OPT_CERT:
+ s_cert_file = opt_arg();
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto end;
+ break;
+ case OPT_CRL:
+ crl_file = opt_arg();
+ break;
+ case OPT_CRL_DOWNLOAD:
+ crl_download = 1;
+ break;
+ case OPT_SERVERINFO:
+ s_serverinfo_file = opt_arg();
+ break;
+ case OPT_CERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format))
+ goto opthelp;
+ break;
+ case OPT_KEY:
+ s_key_file = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format))
+ goto opthelp;
+ break;
+ case OPT_PASS:
+ passarg = opt_arg();
+ break;
+ case OPT_CERT_CHAIN:
+ s_chain_file = opt_arg();
+ break;
+ case OPT_DHPARAM:
+#ifndef OPENSSL_NO_DH
+ dhfile = opt_arg();
+#endif
+ break;
+ case OPT_DCERTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
+ goto opthelp;
+ break;
+ case OPT_DCERT:
+ s_dcert_file = opt_arg();
+ break;
+ case OPT_DKEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format))
+ goto opthelp;
+ break;
+ case OPT_DPASS:
+ dpassarg = opt_arg();
+ break;
+ case OPT_DKEY:
+ s_dkey_file = opt_arg();
+ break;
+ case OPT_DCERT_CHAIN:
+ s_dchain_file = opt_arg();
+ break;
+ case OPT_NOCERT:
+ nocert = 1;
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_CHAINCAPATH:
+ chCApath = opt_arg();
+ break;
+ case OPT_VERIFYCAPATH:
+ vfyCApath = opt_arg();
+ break;
+ case OPT_NO_CACHE:
+ no_cache = 1;
+ break;
+ case OPT_EXT_CACHE:
+ ext_cache = 1;
+ break;
+ case OPT_CRLFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format))
+ goto opthelp;
+ break;
+ case OPT_S_CASES:
+ case OPT_S_NUM_TICKETS:
+ case OPT_ANTI_REPLAY:
+ case OPT_NO_ANTI_REPLAY:
+ if (ssl_args == NULL)
+ ssl_args = sk_OPENSSL_STRING_new_null();
+ if (ssl_args == NULL
+ || !sk_OPENSSL_STRING_push(ssl_args, opt_flag())
+ || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) {
+ BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
+ goto end;
+ }
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ case OPT_X_CASES:
+ if (!args_excert(o, &exc))
+ goto end;
+ break;
+ case OPT_VERIFY_RET_ERROR:
+ verify_args.return_error = 1;
+ break;
+ case OPT_VERIFY_QUIET:
+ verify_args.quiet = 1;
+ break;
+ case OPT_BUILD_CHAIN:
+ build_chain = 1;
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_CHAINCAFILE:
+ chCAfile = opt_arg();
+ break;
+ case OPT_VERIFYCAFILE:
+ vfyCAfile = opt_arg();
+ break;
+ case OPT_NBIO:
+ s_nbio = 1;
+ break;
+ case OPT_NBIO_TEST:
+ s_nbio = s_nbio_test = 1;
+ break;
+ case OPT_IGN_EOF:
+ s_ign_eof = 1;
+ break;
+ case OPT_NO_IGN_EOF:
+ s_ign_eof = 0;
+ break;
+ case OPT_DEBUG:
+ s_debug = 1;
+ break;
+ case OPT_TLSEXTDEBUG:
+ s_tlsextdebug = 1;
+ break;
+ case OPT_STATUS:
+#ifndef OPENSSL_NO_OCSP
+ s_tlsextstatus = 1;
+#endif
+ break;
+ case OPT_STATUS_VERBOSE:
+#ifndef OPENSSL_NO_OCSP
+ s_tlsextstatus = tlscstatp.verbose = 1;
+#endif
+ break;
+ case OPT_STATUS_TIMEOUT:
+#ifndef OPENSSL_NO_OCSP
+ s_tlsextstatus = 1;
+ tlscstatp.timeout = atoi(opt_arg());
+#endif
+ break;
+ case OPT_STATUS_URL:
+#ifndef OPENSSL_NO_OCSP
+ s_tlsextstatus = 1;
+ if (!OCSP_parse_url(opt_arg(),
+ &tlscstatp.host,
+ &tlscstatp.port,
+ &tlscstatp.path, &tlscstatp.use_ssl)) {
+ BIO_printf(bio_err, "Error parsing URL\n");
+ goto end;
+ }
+#endif
+ break;
+ case OPT_STATUS_FILE:
+#ifndef OPENSSL_NO_OCSP
+ s_tlsextstatus = 1;
+ tlscstatp.respin = opt_arg();
+#endif
+ break;
+ case OPT_MSG:
+ s_msg = 1;
+ break;
+ case OPT_MSGFILE:
+ bio_s_msg = BIO_new_file(opt_arg(), "w");
+ break;
+ case OPT_TRACE:
+#ifndef OPENSSL_NO_SSL_TRACE
+ s_msg = 2;
+#endif
+ break;
+ case OPT_SECURITY_DEBUG:
+ sdebug = 1;
+ break;
+ case OPT_SECURITY_DEBUG_VERBOSE:
+ sdebug = 2;
+ break;
+ case OPT_STATE:
+ state = 1;
+ break;
+ case OPT_CRLF:
+ s_crlf = 1;
+ break;
+ case OPT_QUIET:
+ s_quiet = 1;
+ break;
+ case OPT_BRIEF:
+ s_quiet = s_brief = verify_args.quiet = 1;
+ break;
+ case OPT_NO_DHE:
+#ifndef OPENSSL_NO_DH
+ no_dhe = 1;
+#endif
+ break;
+ case OPT_NO_RESUME_EPHEMERAL:
+ no_resume_ephemeral = 1;
+ break;
+ case OPT_PSK_IDENTITY:
+ psk_identity = opt_arg();
+ break;
+ case OPT_PSK_HINT:
+#ifndef OPENSSL_NO_PSK
+ psk_identity_hint = opt_arg();
+#endif
+ break;
+ case OPT_PSK:
+ for (p = psk_key = opt_arg(); *p; p++) {
+ if (isxdigit(_UC(*p)))
+ continue;
+ BIO_printf(bio_err, "Not a hex number '%s'\n", *argv);
+ goto end;
+ }
+ break;
+ case OPT_PSK_SESS:
+ psksessf = opt_arg();
+ break;
+ case OPT_SRPVFILE:
+#ifndef OPENSSL_NO_SRP
+ srp_verifier_file = opt_arg();
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+#endif
+ break;
+ case OPT_SRPUSERSEED:
+#ifndef OPENSSL_NO_SRP
+ srpuserseed = opt_arg();
+ if (min_version < TLS1_VERSION)
+ min_version = TLS1_VERSION;
+#endif
+ break;
+ case OPT_REV:
+ rev = 1;
+ break;
+ case OPT_WWW:
+ www = 1;
+ break;
+ case OPT_UPPER_WWW:
+ www = 2;
+ break;
+ case OPT_HTTP:
+ www = 3;
+ break;
+ case OPT_SSL_CONFIG:
+ ssl_config = opt_arg();
+ break;
+ case OPT_SSL3:
+ min_version = SSL3_VERSION;
+ max_version = SSL3_VERSION;
+ break;
+ case OPT_TLS1_3:
+ min_version = TLS1_3_VERSION;
+ max_version = TLS1_3_VERSION;
+ break;
+ case OPT_TLS1_2:
+ min_version = TLS1_2_VERSION;
+ max_version = TLS1_2_VERSION;
+ break;
+ case OPT_TLS1_1:
+ min_version = TLS1_1_VERSION;
+ max_version = TLS1_1_VERSION;
+ break;
+ case OPT_TLS1:
+ min_version = TLS1_VERSION;
+ max_version = TLS1_VERSION;
+ break;
+ case OPT_DTLS:
+#ifndef OPENSSL_NO_DTLS
+ meth = DTLS_server_method();
+ socket_type = SOCK_DGRAM;
+#endif
+ break;
+ case OPT_DTLS1:
+#ifndef OPENSSL_NO_DTLS
+ meth = DTLS_server_method();
+ min_version = DTLS1_VERSION;
+ max_version = DTLS1_VERSION;
+ socket_type = SOCK_DGRAM;
+#endif
+ break;
+ case OPT_DTLS1_2:
+#ifndef OPENSSL_NO_DTLS
+ meth = DTLS_server_method();
+ min_version = DTLS1_2_VERSION;
+ max_version = DTLS1_2_VERSION;
+ socket_type = SOCK_DGRAM;
+#endif
+ break;
+ case OPT_SCTP:
+#ifndef OPENSSL_NO_SCTP
+ protocol = IPPROTO_SCTP;
+#endif
+ break;
+ case OPT_TIMEOUT:
+#ifndef OPENSSL_NO_DTLS
+ enable_timeouts = 1;
+#endif
+ break;
+ case OPT_MTU:
+#ifndef OPENSSL_NO_DTLS
+ socket_mtu = atol(opt_arg());
+#endif
+ break;
+ case OPT_LISTEN:
+#ifndef OPENSSL_NO_DTLS
+ dtlslisten = 1;
+#endif
+ break;
+ case OPT_STATELESS:
+ stateless = 1;
+ break;
+ case OPT_ID_PREFIX:
+ session_id_prefix = opt_arg();
+ break;
+ case OPT_ENGINE:
+ engine = setup_engine(opt_arg(), 1);
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_SERVERNAME:
+ tlsextcbp.servername = opt_arg();
+ break;
+ case OPT_SERVERNAME_FATAL:
+ tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL;
+ break;
+ case OPT_CERT2:
+ s_cert_file2 = opt_arg();
+ break;
+ case OPT_KEY2:
+ s_key_file2 = opt_arg();
+ break;
+ case OPT_NEXTPROTONEG:
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ next_proto_neg_in = opt_arg();
+#endif
+ break;
+ case OPT_ALPN:
+ alpn_in = opt_arg();
+ break;
+ case OPT_SRTP_PROFILES:
+#ifndef OPENSSL_NO_SRTP
+ srtp_profiles = opt_arg();
+#endif
+ break;
+ case OPT_KEYMATEXPORT:
+ keymatexportlabel = opt_arg();
+ break;
+ case OPT_KEYMATEXPORTLEN:
+ keymatexportlen = atoi(opt_arg());
+ break;
+ case OPT_ASYNC:
+ async = 1;
+ break;
+ case OPT_MAX_SEND_FRAG:
+ max_send_fragment = atoi(opt_arg());
+ break;
+ case OPT_SPLIT_SEND_FRAG:
+ split_send_fragment = atoi(opt_arg());
+ break;
+ case OPT_MAX_PIPELINES:
+ max_pipelines = atoi(opt_arg());
+ break;
+ case OPT_READ_BUF:
+ read_buf_len = atoi(opt_arg());
+ break;
+ case OPT_KEYLOG_FILE:
+ keylog_file = opt_arg();
+ break;
+ case OPT_MAX_EARLY:
+ max_early_data = atoi(opt_arg());
+ if (max_early_data < 0) {
+ BIO_printf(bio_err, "Invalid value for max_early_data\n");
+ goto end;
+ }
+ break;
+ case OPT_RECV_MAX_EARLY:
+ recv_max_early_data = atoi(opt_arg());
+ if (recv_max_early_data < 0) {
+ BIO_printf(bio_err, "Invalid value for recv_max_early_data\n");
+ goto end;
+ }
+ break;
+ case OPT_EARLY_DATA:
+ early_data = 1;
+ if (max_early_data == -1)
+ max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
+ BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n");
+ goto opthelp;
+ }
+#endif
+#ifndef OPENSSL_NO_DTLS
+ if (www && socket_type == SOCK_DGRAM) {
+ BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n");
+ goto end;
+ }
+
+ if (dtlslisten && socket_type != SOCK_DGRAM) {
+ BIO_printf(bio_err, "Can only use -listen with DTLS\n");
+ goto end;
+ }
+#endif
+
+ if (stateless && socket_type != SOCK_STREAM) {
+ BIO_printf(bio_err, "Can only use --stateless with TLS\n");
+ goto end;
+ }
+
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) {
+ BIO_printf(bio_err,
+ "Can't use unix sockets and datagrams together\n");
+ goto end;
+ }
+#endif
+ if (early_data && (www > 0 || rev)) {
+ BIO_printf(bio_err,
+ "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n");
+ goto end;
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ if (socket_type != SOCK_DGRAM) {
+ BIO_printf(bio_err, "Can't use -sctp without DTLS\n");
+ goto end;
+ }
+ /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */
+ socket_type = SOCK_STREAM;
+ }
+#endif
+
+ if (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ if (s_key_file == NULL)
+ s_key_file = s_cert_file;
+
+ if (s_key_file2 == NULL)
+ s_key_file2 = s_cert_file2;
+
+ if (!load_excert(&exc))
+ goto end;
+
+ if (nocert == 0) {
+ s_key = load_key(s_key_file, s_key_format, 0, pass, engine,
+ "server certificate private key file");
+ if (s_key == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ s_cert = load_cert(s_cert_file, s_cert_format,
+ "server certificate file");
+
+ if (s_cert == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (s_chain_file != NULL) {
+ if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL,
+ "server certificate chain"))
+ goto end;
+ }
+
+ if (tlsextcbp.servername != NULL) {
+ s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine,
+ "second server certificate private key file");
+ if (s_key2 == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ s_cert2 = load_cert(s_cert_file2, s_cert_format,
+ "second server certificate file");
+
+ if (s_cert2 == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ }
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ if (next_proto_neg_in) {
+ next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
+ if (next_proto.data == NULL)
+ goto end;
+ }
+#endif
+ alpn_ctx.data = NULL;
+ if (alpn_in) {
+ alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in);
+ if (alpn_ctx.data == NULL)
+ goto end;
+ }
+
+ if (crl_file != NULL) {
+ X509_CRL *crl;
+ crl = load_crl(crl_file, crl_format);
+ if (crl == NULL) {
+ BIO_puts(bio_err, "Error loading CRL\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ crls = sk_X509_CRL_new_null();
+ if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
+ BIO_puts(bio_err, "Error adding CRL\n");
+ ERR_print_errors(bio_err);
+ X509_CRL_free(crl);
+ goto end;
+ }
+ }
+
+ if (s_dcert_file != NULL) {
+
+ if (s_dkey_file == NULL)
+ s_dkey_file = s_dcert_file;
+
+ s_dkey = load_key(s_dkey_file, s_dkey_format,
+ 0, dpass, engine, "second certificate private key file");
+ if (s_dkey == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ s_dcert = load_cert(s_dcert_file, s_dcert_format,
+ "second server certificate file");
+
+ if (s_dcert == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (s_dchain_file != NULL) {
+ if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL,
+ "second server certificate chain"))
+ goto end;
+ }
+
+ }
+
+ if (bio_s_out == NULL) {
+ if (s_quiet && !s_debug) {
+ bio_s_out = BIO_new(BIO_s_null());
+ if (s_msg && bio_s_msg == NULL)
+ bio_s_msg = dup_bio_out(FORMAT_TEXT);
+ } else {
+ if (bio_s_out == NULL)
+ bio_s_out = dup_bio_out(FORMAT_TEXT);
+ }
+ }
+#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
+ if (nocert)
+#endif
+ {
+ s_cert_file = NULL;
+ s_key_file = NULL;
+ s_dcert_file = NULL;
+ s_dkey_file = NULL;
+ s_cert_file2 = NULL;
+ s_key_file2 = NULL;
+ }
+
+ ctx = SSL_CTX_new(meth);
+ if (ctx == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
+
+ if (sdebug)
+ ssl_ctx_security_debug(ctx, sdebug);
+
+ if (!config_ctx(cctx, ssl_args, ctx))
+ goto end;
+
+ if (ssl_config) {
+ if (SSL_CTX_config(ctx, ssl_config) == 0) {
+ BIO_printf(bio_err, "Error using configuration \"%s\"\n",
+ ssl_config);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (min_version != 0
+ && SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
+ goto end;
+ if (max_version != 0
+ && SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
+ goto end;
+
+ if (session_id_prefix) {
+ if (strlen(session_id_prefix) >= 32)
+ BIO_printf(bio_err,
+ "warning: id_prefix is too long, only one new session will be possible\n");
+ if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) {
+ BIO_printf(bio_err, "error setting 'id_prefix'\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
+ }
+ SSL_CTX_set_quiet_shutdown(ctx, 1);
+ if (exc != NULL)
+ ssl_ctx_set_excert(ctx, exc);
+
+ if (state)
+ SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
+ if (no_cache)
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+ else if (ext_cache)
+ init_session_cache_ctx(ctx);
+ else
+ SSL_CTX_sess_set_cache_size(ctx, 128);
+
+ if (async) {
+ SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
+ }
+
+ if (max_send_fragment > 0
+ && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
+ BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
+ prog, max_send_fragment);
+ goto end;
+ }
+
+ if (split_send_fragment > 0
+ && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) {
+ BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n",
+ prog, split_send_fragment);
+ goto end;
+ }
+ if (max_pipelines > 0
+ && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) {
+ BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n",
+ prog, max_pipelines);
+ goto end;
+ }
+
+ if (read_buf_len > 0) {
+ SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+ }
+#ifndef OPENSSL_NO_SRTP
+ if (srtp_profiles != NULL) {
+ /* Returns 0 on success! */
+ if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) {
+ BIO_printf(bio_err, "Error setting SRTP profile\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+#endif
+
+ if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
+ BIO_printf(bio_err, "Error setting verify params\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ ssl_ctx_add_crls(ctx, crls, 0);
+
+ if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+ crls, crl_download)) {
+ BIO_printf(bio_err, "Error loading store locations\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (s_cert2) {
+ ctx2 = SSL_CTX_new(meth);
+ if (ctx2 == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (ctx2 != NULL) {
+ BIO_printf(bio_s_out, "Setting secondary ctx parameters\n");
+
+ if (sdebug)
+ ssl_ctx_security_debug(ctx, sdebug);
+
+ if (session_id_prefix) {
+ if (strlen(session_id_prefix) >= 32)
+ BIO_printf(bio_err,
+ "warning: id_prefix is too long, only one new session will be possible\n");
+ if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) {
+ BIO_printf(bio_err, "error setting 'id_prefix'\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
+ }
+ SSL_CTX_set_quiet_shutdown(ctx2, 1);
+ if (exc != NULL)
+ ssl_ctx_set_excert(ctx2, exc);
+
+ if (state)
+ SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback);
+
+ if (no_cache)
+ SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF);
+ else if (ext_cache)
+ init_session_cache_ctx(ctx2);
+ else
+ SSL_CTX_sess_set_cache_size(ctx2, 128);
+
+ if (async)
+ SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
+
+ if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile,
+ noCApath)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) {
+ BIO_printf(bio_err, "Error setting verify params\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ ssl_ctx_add_crls(ctx2, crls, 0);
+ if (!config_ctx(cctx, ssl_args, ctx2))
+ goto end;
+ }
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ if (next_proto.data)
+ SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb,
+ &next_proto);
+#endif
+ if (alpn_ctx.data)
+ SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
+
+#ifndef OPENSSL_NO_DH
+ if (!no_dhe) {
+ DH *dh = NULL;
+
+ if (dhfile != NULL)
+ dh = load_dh_param(dhfile);
+ else if (s_cert_file != NULL)
+ dh = load_dh_param(s_cert_file);
+
+ if (dh != NULL) {
+ BIO_printf(bio_s_out, "Setting temp DH parameters\n");
+ } else {
+ BIO_printf(bio_s_out, "Using default temp DH parameters\n");
+ }
+ (void)BIO_flush(bio_s_out);
+
+ if (dh == NULL) {
+ SSL_CTX_set_dh_auto(ctx, 1);
+ } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
+ BIO_puts(bio_err, "Error setting temp DH parameters\n");
+ ERR_print_errors(bio_err);
+ DH_free(dh);
+ goto end;
+ }
+
+ if (ctx2 != NULL) {
+ if (!dhfile) {
+ DH *dh2 = load_dh_param(s_cert_file2);
+ if (dh2 != NULL) {
+ BIO_printf(bio_s_out, "Setting temp DH parameters\n");
+ (void)BIO_flush(bio_s_out);
+
+ DH_free(dh);
+ dh = dh2;
+ }
+ }
+ if (dh == NULL) {
+ SSL_CTX_set_dh_auto(ctx2, 1);
+ } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
+ BIO_puts(bio_err, "Error setting temp DH parameters\n");
+ ERR_print_errors(bio_err);
+ DH_free(dh);
+ goto end;
+ }
+ }
+ DH_free(dh);
+ }
+#endif
+
+ if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
+ goto end;
+
+ if (s_serverinfo_file != NULL
+ && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (ctx2 != NULL
+ && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain))
+ goto end;
+
+ if (s_dcert != NULL) {
+ if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
+ goto end;
+ }
+
+ if (no_resume_ephemeral) {
+ SSL_CTX_set_not_resumable_session_callback(ctx,
+ not_resumable_sess_cb);
+
+ if (ctx2 != NULL)
+ SSL_CTX_set_not_resumable_session_callback(ctx2,
+ not_resumable_sess_cb);
+ }
+#ifndef OPENSSL_NO_PSK
+ if (psk_key != NULL) {
+ if (s_debug)
+ BIO_printf(bio_s_out, "PSK key given, setting server callback\n");
+ SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
+ }
+
+ if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
+ BIO_printf(bio_err, "error setting PSK identity hint to context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+#endif
+ if (psksessf != NULL) {
+ BIO *stmp = BIO_new_file(psksessf, "r");
+
+ if (stmp == NULL) {
+ BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
+ BIO_free(stmp);
+ if (psksess == NULL) {
+ BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ }
+
+ if (psk_key != NULL || psksess != NULL)
+ SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb);
+
+ SSL_CTX_set_verify(ctx, s_server_verify, verify_callback);
+ if (!SSL_CTX_set_session_id_context(ctx,
+ (void *)&s_server_session_id_context,
+ sizeof(s_server_session_id_context))) {
+ BIO_printf(bio_err, "error setting session id context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ /* Set DTLS cookie generation and verification callbacks */
+ SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
+ SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
+
+ /* Set TLS1.3 cookie generation and verification callbacks */
+ SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback);
+ SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback);
+
+ if (ctx2 != NULL) {
+ SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback);
+ if (!SSL_CTX_set_session_id_context(ctx2,
+ (void *)&s_server_session_id_context,
+ sizeof(s_server_session_id_context))) {
+ BIO_printf(bio_err, "error setting session id context\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ tlsextcbp.biodebug = bio_s_out;
+ SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp);
+ SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
+ }
+
+#ifndef OPENSSL_NO_SRP
+ if (srp_verifier_file != NULL) {
+ srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
+ srp_callback_parm.user = NULL;
+ srp_callback_parm.login = NULL;
+ if ((ret =
+ SRP_VBASE_init(srp_callback_parm.vb,
+ srp_verifier_file)) != SRP_NO_ERROR) {
+ BIO_printf(bio_err,
+ "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
+ srp_verifier_file, ret);
+ goto end;
+ }
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback);
+ SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);
+ SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
+ } else
+#endif
+ if (CAfile != NULL) {
+ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
+
+ if (ctx2)
+ SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile));
+ }
+#ifndef OPENSSL_NO_OCSP
+ if (s_tlsextstatus) {
+ SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
+ SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp);
+ if (ctx2) {
+ SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb);
+ SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp);
+ }
+ }
+#endif
+ if (set_keylog_file(ctx, keylog_file))
+ goto end;
+
+ if (max_early_data >= 0)
+ SSL_CTX_set_max_early_data(ctx, max_early_data);
+ if (recv_max_early_data >= 0)
+ SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data);
+
+ if (rev)
+ server_cb = rev_body;
+ else if (www)
+ server_cb = www_body;
+ else
+ server_cb = sv_body;
+#ifdef AF_UNIX
+ if (socket_family == AF_UNIX
+ && unlink_unix_path)
+ unlink(host);
+#endif
+ do_server(&accept_socket, host, port, socket_family, socket_type, protocol,
+ server_cb, context, naccept, bio_s_out);
+ print_stats(bio_s_out, ctx);
+ ret = 0;
+ end:
+ SSL_CTX_free(ctx);
+ SSL_SESSION_free(psksess);
+ set_keylog_file(NULL, NULL);
+ X509_free(s_cert);
+ sk_X509_CRL_pop_free(crls, X509_CRL_free);
+ X509_free(s_dcert);
+ EVP_PKEY_free(s_key);
+ EVP_PKEY_free(s_dkey);
+ sk_X509_pop_free(s_chain, X509_free);
+ sk_X509_pop_free(s_dchain, X509_free);
+ OPENSSL_free(pass);
+ OPENSSL_free(dpass);
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ X509_VERIFY_PARAM_free(vpm);
+ free_sessions();
+ OPENSSL_free(tlscstatp.host);
+ OPENSSL_free(tlscstatp.port);
+ OPENSSL_free(tlscstatp.path);
+ SSL_CTX_free(ctx2);
+ X509_free(s_cert2);
+ EVP_PKEY_free(s_key2);
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ OPENSSL_free(next_proto.data);
+#endif
+ OPENSSL_free(alpn_ctx.data);
+ ssl_excert_free(exc);
+ sk_OPENSSL_STRING_free(ssl_args);
+ SSL_CONF_CTX_free(cctx);
+ release_engine(engine);
+ BIO_free(bio_s_out);
+ bio_s_out = NULL;
+ BIO_free(bio_s_msg);
+ bio_s_msg = NULL;
+#ifdef CHARSET_EBCDIC
+ BIO_meth_free(methods_ebcdic);
+#endif
+ return ret;
+}
+
+static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
+{
+ BIO_printf(bio, "%4ld items in the session cache\n",
+ SSL_CTX_sess_number(ssl_ctx));
+ BIO_printf(bio, "%4ld client connects (SSL_connect())\n",
+ SSL_CTX_sess_connect(ssl_ctx));
+ BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n",
+ SSL_CTX_sess_connect_renegotiate(ssl_ctx));
+ BIO_printf(bio, "%4ld client connects that finished\n",
+ SSL_CTX_sess_connect_good(ssl_ctx));
+ BIO_printf(bio, "%4ld server accepts (SSL_accept())\n",
+ SSL_CTX_sess_accept(ssl_ctx));
+ BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n",
+ SSL_CTX_sess_accept_renegotiate(ssl_ctx));
+ BIO_printf(bio, "%4ld server accepts that finished\n",
+ SSL_CTX_sess_accept_good(ssl_ctx));
+ BIO_printf(bio, "%4ld session cache hits\n", SSL_CTX_sess_hits(ssl_ctx));
+ BIO_printf(bio, "%4ld session cache misses\n",
+ SSL_CTX_sess_misses(ssl_ctx));
+ BIO_printf(bio, "%4ld session cache timeouts\n",
+ SSL_CTX_sess_timeouts(ssl_ctx));
+ BIO_printf(bio, "%4ld callback cache hits\n",
+ SSL_CTX_sess_cb_hits(ssl_ctx));
+ BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n",
+ SSL_CTX_sess_cache_full(ssl_ctx),
+ SSL_CTX_sess_get_cache_size(ssl_ctx));
+}
+
+static int sv_body(int s, int stype, int prot, unsigned char *context)
+{
+ char *buf = NULL;
+ fd_set readfds;
+ int ret = 1, width;
+ int k, i;
+ unsigned long l;
+ SSL *con = NULL;
+ BIO *sbio;
+ struct timeval timeout;
+#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS))
+ struct timeval *timeoutp;
+#endif
+#ifndef OPENSSL_NO_DTLS
+# ifndef OPENSSL_NO_SCTP
+ int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP);
+# else
+ int isdtls = (stype == SOCK_DGRAM);
+# endif
+#endif
+
+ buf = app_malloc(bufsize, "server buffer");
+ if (s_nbio) {
+ if (!BIO_socket_nbio(s, 1))
+ ERR_print_errors(bio_err);
+ else if (!s_quiet)
+ BIO_printf(bio_err, "Turned on non blocking io\n");
+ }
+
+ con = SSL_new(ctx);
+ if (con == NULL) {
+ ret = -1;
+ goto err;
+ }
+
+ if (s_tlsextdebug) {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+
+ if (context != NULL
+ && !SSL_set_session_id_context(con, context,
+ strlen((char *)context))) {
+ BIO_printf(bio_err, "Error setting session id context\n");
+ ret = -1;
+ goto err;
+ }
+
+ if (!SSL_clear(con)) {
+ BIO_printf(bio_err, "Error clearing SSL connection\n");
+ ret = -1;
+ goto err;
+ }
+#ifndef OPENSSL_NO_DTLS
+ if (isdtls) {
+# ifndef OPENSSL_NO_SCTP
+ if (prot == IPPROTO_SCTP)
+ sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
+ else
+# endif
+ sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+
+ if (enable_timeouts) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = DGRAM_RCV_TIMEOUT;
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = DGRAM_SND_TIMEOUT;
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
+ }
+
+ if (socket_mtu) {
+ if (socket_mtu < DTLS_get_link_min_mtu(con)) {
+ BIO_printf(bio_err, "MTU too small. Must be at least %ld\n",
+ DTLS_get_link_min_mtu(con));
+ ret = -1;
+ BIO_free(sbio);
+ goto err;
+ }
+ SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
+ if (!DTLS_set_link_mtu(con, socket_mtu)) {
+ BIO_printf(bio_err, "Failed to set MTU\n");
+ ret = -1;
+ BIO_free(sbio);
+ goto err;
+ }
+ } else
+ /* want to do MTU discovery */
+ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
+
+# ifndef OPENSSL_NO_SCTP
+ if (prot != IPPROTO_SCTP)
+# endif
+ /* Turn on cookie exchange. Not necessary for SCTP */
+ SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
+ } else
+#endif
+ sbio = BIO_new_socket(s, BIO_NOCLOSE);
+
+ if (sbio == NULL) {
+ BIO_printf(bio_err, "Unable to create BIO\n");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
+ if (s_nbio_test) {
+ BIO *test;
+
+ test = BIO_new(BIO_f_nbio_test());
+ sbio = BIO_push(test, sbio);
+ }
+
+ SSL_set_bio(con, sbio, sbio);
+ SSL_set_accept_state(con);
+ /* SSL_set_fd(con,s); */
+
+ if (s_debug) {
+ BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
+ }
+ if (s_msg) {
+#ifndef OPENSSL_NO_SSL_TRACE
+ if (s_msg == 2)
+ SSL_set_msg_callback(con, SSL_trace);
+ else
+#endif
+ SSL_set_msg_callback(con, msg_cb);
+ SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
+ }
+
+ if (s_tlsextdebug) {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+
+ if (early_data) {
+ int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR;
+ size_t readbytes;
+
+ while (edret != SSL_READ_EARLY_DATA_FINISH) {
+ for (;;) {
+ edret = SSL_read_early_data(con, buf, bufsize, &readbytes);
+ if (edret != SSL_READ_EARLY_DATA_ERROR)
+ break;
+
+ switch (SSL_get_error(con, 0)) {
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_ASYNC:
+ case SSL_ERROR_WANT_READ:
+ /* Just keep trying - busy waiting */
+ continue;
+ default:
+ BIO_printf(bio_err, "Error reading early data\n");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ }
+ if (readbytes > 0) {
+ if (write_header) {
+ BIO_printf(bio_s_out, "Early data received:\n");
+ write_header = 0;
+ }
+ raw_write_stdout(buf, (unsigned int)readbytes);
+ (void)BIO_flush(bio_s_out);
+ }
+ }
+ if (write_header) {
+ if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT)
+ BIO_printf(bio_s_out, "No early data received\n");
+ else
+ BIO_printf(bio_s_out, "Early data was rejected\n");
+ } else {
+ BIO_printf(bio_s_out, "\nEnd of early data\n");
+ }
+ if (SSL_is_init_finished(con))
+ print_connection_info(con);
+ }
+
+ if (fileno_stdin() > s)
+ width = fileno_stdin() + 1;
+ else
+ width = s + 1;
+ for (;;) {
+ int read_from_terminal;
+ int read_from_sslcon;
+
+ read_from_terminal = 0;
+ read_from_sslcon = SSL_has_pending(con)
+ || (async && SSL_waiting_for_async(con));
+
+ if (!read_from_sslcon) {
+ FD_ZERO(&readfds);
+#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
+ openssl_fdset(fileno_stdin(), &readfds);
+#endif
+ openssl_fdset(s, &readfds);
+ /*
+ * Note: under VMS with SOCKETSHR the second parameter is
+ * currently of type (int *) whereas under other systems it is
+ * (void *) if you don't have a cast it will choke the compiler:
+ * if you do have a cast then you can either go for (int *) or
+ * (void *).
+ */
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
+ /*
+ * Under DOS (non-djgpp) and Windows we can't select on stdin:
+ * only on sockets. As a workaround we timeout the select every
+ * second and check for any keypress. In a proper Windows
+ * application we wouldn't do this because it is inefficient.
+ */
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ i = select(width, (void *)&readfds, NULL, NULL, &timeout);
+ if (has_stdin_waiting())
+ read_from_terminal = 1;
+ if ((i < 0) || (!i && !read_from_terminal))
+ continue;
+#else
+ if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
+ timeoutp = &timeout;
+ else
+ timeoutp = NULL;
+
+ i = select(width, (void *)&readfds, NULL, NULL, timeoutp);
+
+ if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0)
+ BIO_printf(bio_err, "TIMEOUT occurred\n");
+
+ if (i <= 0)
+ continue;
+ if (FD_ISSET(fileno_stdin(), &readfds))
+ read_from_terminal = 1;
+#endif
+ if (FD_ISSET(s, &readfds))
+ read_from_sslcon = 1;
+ }
+ if (read_from_terminal) {
+ if (s_crlf) {
+ int j, lf_num;
+
+ i = raw_read_stdin(buf, bufsize / 2);
+ lf_num = 0;
+ /* both loops are skipped when i <= 0 */
+ for (j = 0; j < i; j++)
+ if (buf[j] == '\n')
+ lf_num++;
+ for (j = i - 1; j >= 0; j--) {
+ buf[j + lf_num] = buf[j];
+ if (buf[j] == '\n') {
+ lf_num--;
+ i++;
+ buf[j + lf_num] = '\r';
+ }
+ }
+ assert(lf_num == 0);
+ } else {
+ i = raw_read_stdin(buf, bufsize);
+ }
+
+ if (!s_quiet && !s_brief) {
+ if ((i <= 0) || (buf[0] == 'Q')) {
+ BIO_printf(bio_s_out, "DONE\n");
+ (void)BIO_flush(bio_s_out);
+ BIO_closesocket(s);
+ close_accept_socket();
+ ret = -11;
+ goto err;
+ }
+ if ((i <= 0) || (buf[0] == 'q')) {
+ BIO_printf(bio_s_out, "DONE\n");
+ (void)BIO_flush(bio_s_out);
+ if (SSL_version(con) != DTLS1_VERSION)
+ BIO_closesocket(s);
+ /*
+ * close_accept_socket(); ret= -11;
+ */
+ goto err;
+ }
+#ifndef OPENSSL_NO_HEARTBEATS
+ if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
+ BIO_printf(bio_err, "HEARTBEATING\n");
+ SSL_heartbeat(con);
+ i = 0;
+ continue;
+ }
+#endif
+ if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
+ SSL_renegotiate(con);
+ i = SSL_do_handshake(con);
+ printf("SSL_do_handshake -> %d\n", i);
+ i = 0; /* 13; */
+ continue;
+ }
+ if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
+ SSL_set_verify(con,
+ SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
+ NULL);
+ SSL_renegotiate(con);
+ i = SSL_do_handshake(con);
+ printf("SSL_do_handshake -> %d\n", i);
+ i = 0; /* 13; */
+ continue;
+ }
+ if ((buf[0] == 'K' || buf[0] == 'k')
+ && ((buf[1] == '\n') || (buf[1] == '\r'))) {
+ SSL_key_update(con, buf[0] == 'K' ?
+ SSL_KEY_UPDATE_REQUESTED
+ : SSL_KEY_UPDATE_NOT_REQUESTED);
+ i = SSL_do_handshake(con);
+ printf("SSL_do_handshake -> %d\n", i);
+ i = 0;
+ continue;
+ }
+ if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) {
+ SSL_set_verify(con, SSL_VERIFY_PEER, NULL);
+ i = SSL_verify_client_post_handshake(con);
+ if (i == 0) {
+ printf("Failed to initiate request\n");
+ ERR_print_errors(bio_err);
+ } else {
+ i = SSL_do_handshake(con);
+ printf("SSL_do_handshake -> %d\n", i);
+ i = 0;
+ }
+ continue;
+ }
+ if (buf[0] == 'P') {
+ static const char *str = "Lets print some clear text\n";
+ BIO_write(SSL_get_wbio(con), str, strlen(str));
+ }
+ if (buf[0] == 'S') {
+ print_stats(bio_s_out, SSL_get_SSL_CTX(con));
+ }
+ }
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(buf, buf, i);
+#endif
+ l = k = 0;
+ for (;;) {
+ /* should do a select for the write */
+#ifdef RENEG
+ static count = 0;
+ if (++count == 100) {
+ count = 0;
+ SSL_renegotiate(con);
+ }
+#endif
+ k = SSL_write(con, &(buf[l]), (unsigned int)i);
+#ifndef OPENSSL_NO_SRP
+ while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during write\n");
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ k = SSL_write(con, &(buf[l]), (unsigned int)i);
+ }
+#endif
+ switch (SSL_get_error(con, k)) {
+ case SSL_ERROR_NONE:
+ break;
+ case SSL_ERROR_WANT_ASYNC:
+ BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
+ (void)BIO_flush(bio_s_out);
+ wait_for_async(con);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_printf(bio_s_out, "Write BLOCK\n");
+ (void)BIO_flush(bio_s_out);
+ break;
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /*
+ * This shouldn't ever happen in s_server. Treat as an error
+ */
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ BIO_printf(bio_s_out, "ERROR\n");
+ (void)BIO_flush(bio_s_out);
+ ERR_print_errors(bio_err);
+ ret = 1;
+ goto err;
+ /* break; */
+ case SSL_ERROR_ZERO_RETURN:
+ BIO_printf(bio_s_out, "DONE\n");
+ (void)BIO_flush(bio_s_out);
+ ret = 1;
+ goto err;
+ }
+ if (k > 0) {
+ l += k;
+ i -= k;
+ }
+ if (i <= 0)
+ break;
+ }
+ }
+ if (read_from_sslcon) {
+ /*
+ * init_ssl_connection handles all async events itself so if we're
+ * waiting for async then we shouldn't go back into
+ * init_ssl_connection
+ */
+ if ((!async || !SSL_waiting_for_async(con))
+ && !SSL_is_init_finished(con)) {
+ i = init_ssl_connection(con);
+
+ if (i < 0) {
+ ret = 0;
+ goto err;
+ } else if (i == 0) {
+ ret = 1;
+ goto err;
+ }
+ } else {
+ again:
+ i = SSL_read(con, (char *)buf, bufsize);
+#ifndef OPENSSL_NO_SRP
+ while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ i = SSL_read(con, (char *)buf, bufsize);
+ }
+#endif
+ switch (SSL_get_error(con, i)) {
+ case SSL_ERROR_NONE:
+#ifdef CHARSET_EBCDIC
+ ascii2ebcdic(buf, buf, i);
+#endif
+ raw_write_stdout(buf, (unsigned int)i);
+ (void)BIO_flush(bio_s_out);
+ if (SSL_has_pending(con))
+ goto again;
+ break;
+ case SSL_ERROR_WANT_ASYNC:
+ BIO_printf(bio_s_out, "Read BLOCK (Async)\n");
+ (void)BIO_flush(bio_s_out);
+ wait_for_async(con);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ BIO_printf(bio_s_out, "Read BLOCK\n");
+ (void)BIO_flush(bio_s_out);
+ break;
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ /*
+ * This shouldn't ever happen in s_server. Treat as an error
+ */
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ BIO_printf(bio_s_out, "ERROR\n");
+ (void)BIO_flush(bio_s_out);
+ ERR_print_errors(bio_err);
+ ret = 1;
+ goto err;
+ case SSL_ERROR_ZERO_RETURN:
+ BIO_printf(bio_s_out, "DONE\n");
+ (void)BIO_flush(bio_s_out);
+ ret = 1;
+ goto err;
+ }
+ }
+ }
+ }
+ err:
+ if (con != NULL) {
+ BIO_printf(bio_s_out, "shutting down SSL\n");
+ SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ SSL_free(con);
+ }
+ BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
+ OPENSSL_clear_free(buf, bufsize);
+ return ret;
+}
+
+static void close_accept_socket(void)
+{
+ BIO_printf(bio_err, "shutdown accept socket\n");
+ if (accept_socket >= 0) {
+ BIO_closesocket(accept_socket);
+ }
+}
+
+static int is_retryable(SSL *con, int i)
+{
+ int err = SSL_get_error(con, i);
+
+ /* If it's not a fatal error, it must be retryable */
+ return (err != SSL_ERROR_SSL)
+ && (err != SSL_ERROR_SYSCALL)
+ && (err != SSL_ERROR_ZERO_RETURN);
+}
+
+static int init_ssl_connection(SSL *con)
+{
+ int i;
+ long verify_err;
+ int retry = 0;
+
+ if (dtlslisten || stateless) {
+ BIO_ADDR *client = NULL;
+
+ if (dtlslisten) {
+ if ((client = BIO_ADDR_new()) == NULL) {
+ BIO_printf(bio_err, "ERROR - memory\n");
+ return 0;
+ }
+ i = DTLSv1_listen(con, client);
+ } else {
+ i = SSL_stateless(con);
+ }
+ if (i > 0) {
+ BIO *wbio;
+ int fd = -1;
+
+ if (dtlslisten) {
+ wbio = SSL_get_wbio(con);
+ if (wbio) {
+ BIO_get_fd(wbio, &fd);
+ }
+
+ if (!wbio || BIO_connect(fd, client, 0) == 0) {
+ BIO_printf(bio_err, "ERROR - unable to connect\n");
+ BIO_ADDR_free(client);
+ return 0;
+ }
+ BIO_ADDR_free(client);
+ dtlslisten = 0;
+ } else {
+ stateless = 0;
+ }
+ i = SSL_accept(con);
+ } else {
+ BIO_ADDR_free(client);
+ }
+ } else {
+ do {
+ i = SSL_accept(con);
+
+ if (i <= 0)
+ retry = is_retryable(con, i);
+#ifdef CERT_CB_TEST_RETRY
+ {
+ while (i <= 0
+ && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
+ && SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) {
+ BIO_printf(bio_err,
+ "LOOKUP from certificate callback during accept\n");
+ i = SSL_accept(con);
+ if (i <= 0)
+ retry = is_retryable(con, i);
+ }
+ }
+#endif
+
+#ifndef OPENSSL_NO_SRP
+ while (i <= 0
+ && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
+ srp_callback_parm.login);
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ i = SSL_accept(con);
+ if (i <= 0)
+ retry = is_retryable(con, i);
+ }
+#endif
+ } while (i < 0 && SSL_waiting_for_async(con));
+ }
+
+ if (i <= 0) {
+ if (((dtlslisten || stateless) && i == 0)
+ || (!dtlslisten && !stateless && retry)) {
+ BIO_printf(bio_s_out, "DELAY\n");
+ return 1;
+ }
+
+ BIO_printf(bio_err, "ERROR\n");
+
+ verify_err = SSL_get_verify_result(con);
+ if (verify_err != X509_V_OK) {
+ BIO_printf(bio_err, "verify error:%s\n",
+ X509_verify_cert_error_string(verify_err));
+ }
+ /* Always print any error messages */
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ print_connection_info(con);
+ return 1;
+}
+
+static void print_connection_info(SSL *con)
+{
+ const char *str;
+ X509 *peer;
+ char buf[BUFSIZ];
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ const unsigned char *next_proto_neg;
+ unsigned next_proto_neg_len;
+#endif
+ unsigned char *exportedkeymat;
+ int i;
+
+ if (s_brief)
+ print_ssl_summary(con);
+
+ PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
+
+ peer = SSL_get_peer_certificate(con);
+ if (peer != NULL) {
+ BIO_printf(bio_s_out, "Client certificate\n");
+ PEM_write_bio_X509(bio_s_out, peer);
+ dump_cert_text(bio_s_out, peer);
+ X509_free(peer);
+ peer = NULL;
+ }
+
+ if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL)
+ BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
+ str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
+ ssl_print_sigalgs(bio_s_out, con);
+#ifndef OPENSSL_NO_EC
+ ssl_print_point_formats(bio_s_out, con);
+ ssl_print_groups(bio_s_out, con, 0);
+#endif
+ print_ca_names(bio_s_out, con);
+ BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
+ if (next_proto_neg) {
+ BIO_printf(bio_s_out, "NEXTPROTO is ");
+ BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len);
+ BIO_printf(bio_s_out, "\n");
+ }
+#endif
+#ifndef OPENSSL_NO_SRTP
+ {
+ SRTP_PROTECTION_PROFILE *srtp_profile
+ = SSL_get_selected_srtp_profile(con);
+
+ if (srtp_profile)
+ BIO_printf(bio_s_out, "SRTP Extension negotiated, profile=%s\n",
+ srtp_profile->name);
+ }
+#endif
+ if (SSL_session_reused(con))
+ BIO_printf(bio_s_out, "Reused session-id\n");
+ BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
+ SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
+ if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION))
+ BIO_printf(bio_s_out, "Renegotiation is DISABLED\n");
+
+ if (keymatexportlabel != NULL) {
+ BIO_printf(bio_s_out, "Keying material exporter:\n");
+ BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
+ BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen);
+ exportedkeymat = app_malloc(keymatexportlen, "export key");
+ if (!SSL_export_keying_material(con, exportedkeymat,
+ keymatexportlen,
+ keymatexportlabel,
+ strlen(keymatexportlabel),
+ NULL, 0, 0)) {
+ BIO_printf(bio_s_out, " Error\n");
+ } else {
+ BIO_printf(bio_s_out, " Keying material: ");
+ for (i = 0; i < keymatexportlen; i++)
+ BIO_printf(bio_s_out, "%02X", exportedkeymat[i]);
+ BIO_printf(bio_s_out, "\n");
+ }
+ OPENSSL_free(exportedkeymat);
+ }
+
+ (void)BIO_flush(bio_s_out);
+}
+
+#ifndef OPENSSL_NO_DH
+static DH *load_dh_param(const char *dhfile)
+{
+ DH *ret = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(dhfile, "r")) == NULL)
+ goto err;
+ ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+ err:
+ BIO_free(bio);
+ return ret;
+}
+#endif
+
+static int www_body(int s, int stype, int prot, unsigned char *context)
+{
+ char *buf = NULL;
+ int ret = 1;
+ int i, j, k, dot;
+ SSL *con;
+ const SSL_CIPHER *c;
+ BIO *io, *ssl_bio, *sbio;
+#ifdef RENEG
+ int total_bytes = 0;
+#endif
+ int width;
+ fd_set readfds;
+
+ /* Set width for a select call if needed */
+ width = s + 1;
+
+ buf = app_malloc(bufsize, "server www buffer");
+ io = BIO_new(BIO_f_buffer());
+ ssl_bio = BIO_new(BIO_f_ssl());
+ if ((io == NULL) || (ssl_bio == NULL))
+ goto err;
+
+ if (s_nbio) {
+ if (!BIO_socket_nbio(s, 1))
+ ERR_print_errors(bio_err);
+ else if (!s_quiet)
+ BIO_printf(bio_err, "Turned on non blocking io\n");
+ }
+
+ /* lets make the output buffer a reasonable size */
+ if (!BIO_set_write_buffer_size(io, bufsize))
+ goto err;
+
+ if ((con = SSL_new(ctx)) == NULL)
+ goto err;
+
+ if (s_tlsextdebug) {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+
+ if (context != NULL
+ && !SSL_set_session_id_context(con, context,
+ strlen((char *)context))) {
+ SSL_free(con);
+ goto err;
+ }
+
+ sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ if (s_nbio_test) {
+ BIO *test;
+
+ test = BIO_new(BIO_f_nbio_test());
+ sbio = BIO_push(test, sbio);
+ }
+ SSL_set_bio(con, sbio, sbio);
+ SSL_set_accept_state(con);
+
+ /* No need to free |con| after this. Done by BIO_free(ssl_bio) */
+ BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
+ BIO_push(io, ssl_bio);
+#ifdef CHARSET_EBCDIC
+ io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+#endif
+
+ if (s_debug) {
+ BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
+ }
+ if (s_msg) {
+#ifndef OPENSSL_NO_SSL_TRACE
+ if (s_msg == 2)
+ SSL_set_msg_callback(con, SSL_trace);
+ else
+#endif
+ SSL_set_msg_callback(con, msg_cb);
+ SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
+ }
+
+ for (;;) {
+ i = BIO_gets(io, buf, bufsize - 1);
+ if (i < 0) { /* error */
+ if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
+ if (!s_quiet)
+ ERR_print_errors(bio_err);
+ goto err;
+ } else {
+ BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+ if (BIO_should_io_special(io)
+ && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ continue;
+ }
+#endif
+#if !defined(OPENSSL_SYS_MSDOS)
+ sleep(1);
+#endif
+ continue;
+ }
+ } else if (i == 0) { /* end of input */
+ ret = 1;
+ goto end;
+ }
+
+ /* else we have data */
+ if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) ||
+ ((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) {
+ char *p;
+ X509 *peer = NULL;
+ STACK_OF(SSL_CIPHER) *sk;
+ static const char *space = " ";
+
+ if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) {
+ if (strncmp("GET /renegcert", buf, 14) == 0)
+ SSL_set_verify(con,
+ SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
+ NULL);
+ i = SSL_renegotiate(con);
+ BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i);
+ /* Send the HelloRequest */
+ i = SSL_do_handshake(con);
+ if (i <= 0) {
+ BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n",
+ SSL_get_error(con, i));
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ /* Wait for a ClientHello to come back */
+ FD_ZERO(&readfds);
+ openssl_fdset(s, &readfds);
+ i = select(width, (void *)&readfds, NULL, NULL, NULL);
+ if (i <= 0 || !FD_ISSET(s, &readfds)) {
+ BIO_printf(bio_s_out,
+ "Error waiting for client response\n");
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ /*
+ * We're not actually expecting any data here and we ignore
+ * any that is sent. This is just to force the handshake that
+ * we're expecting to come from the client. If they haven't
+ * sent one there's not much we can do.
+ */
+ BIO_gets(io, buf, bufsize - 1);
+ }
+
+ BIO_puts(io,
+ "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
+ BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n");
+ BIO_puts(io, "<pre>\n");
+ /* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */
+ BIO_puts(io, "\n");
+ for (i = 0; i < local_argc; i++) {
+ const char *myp;
+ for (myp = local_argv[i]; *myp; myp++)
+ switch (*myp) {
+ case '<':
+ BIO_puts(io, "&lt;");
+ break;
+ case '>':
+ BIO_puts(io, "&gt;");
+ break;
+ case '&':
+ BIO_puts(io, "&amp;");
+ break;
+ default:
+ BIO_write(io, myp, 1);
+ break;
+ }
+ BIO_write(io, " ", 1);
+ }
+ BIO_puts(io, "\n");
+
+ BIO_printf(io,
+ "Secure Renegotiation IS%s supported\n",
+ SSL_get_secure_renegotiation_support(con) ?
+ "" : " NOT");
+
+ /*
+ * The following is evil and should not really be done
+ */
+ BIO_printf(io, "Ciphers supported in s_server binary\n");
+ sk = SSL_get_ciphers(con);
+ j = sk_SSL_CIPHER_num(sk);
+ for (i = 0; i < j; i++) {
+ c = sk_SSL_CIPHER_value(sk, i);
+ BIO_printf(io, "%-11s:%-25s ",
+ SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
+ if ((((i + 1) % 2) == 0) && (i + 1 != j))
+ BIO_puts(io, "\n");
+ }
+ BIO_puts(io, "\n");
+ p = SSL_get_shared_ciphers(con, buf, bufsize);
+ if (p != NULL) {
+ BIO_printf(io,
+ "---\nCiphers common between both SSL end points:\n");
+ j = i = 0;
+ while (*p) {
+ if (*p == ':') {
+ BIO_write(io, space, 26 - j);
+ i++;
+ j = 0;
+ BIO_write(io, ((i % 3) ? " " : "\n"), 1);
+ } else {
+ BIO_write(io, p, 1);
+ j++;
+ }
+ p++;
+ }
+ BIO_puts(io, "\n");
+ }
+ ssl_print_sigalgs(io, con);
+#ifndef OPENSSL_NO_EC
+ ssl_print_groups(io, con, 0);
+#endif
+ print_ca_names(io, con);
+ BIO_printf(io, (SSL_session_reused(con)
+ ? "---\nReused, " : "---\nNew, "));
+ c = SSL_get_current_cipher(con);
+ BIO_printf(io, "%s, Cipher is %s\n",
+ SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
+ SSL_SESSION_print(io, SSL_get_session(con));
+ BIO_printf(io, "---\n");
+ print_stats(io, SSL_get_SSL_CTX(con));
+ BIO_printf(io, "---\n");
+ peer = SSL_get_peer_certificate(con);
+ if (peer != NULL) {
+ BIO_printf(io, "Client certificate\n");
+ X509_print(io, peer);
+ PEM_write_bio_X509(io, peer);
+ X509_free(peer);
+ peer = NULL;
+ } else {
+ BIO_puts(io, "no client certificate available\n");
+ }
+ BIO_puts(io, "</pre></BODY></HTML>\r\n\r\n");
+ break;
+ } else if ((www == 2 || www == 3)
+ && (strncmp("GET /", buf, 5) == 0)) {
+ BIO *file;
+ char *p, *e;
+ static const char *text =
+ "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
+
+ /* skip the '/' */
+ p = &(buf[5]);
+
+ dot = 1;
+ for (e = p; *e != '\0'; e++) {
+ if (e[0] == ' ')
+ break;
+
+ switch (dot) {
+ case 1:
+ dot = (e[0] == '.') ? 2 : 0;
+ break;
+ case 2:
+ dot = (e[0] == '.') ? 3 : 0;
+ break;
+ case 3:
+ dot = (e[0] == '/') ? -1 : 0;
+ break;
+ }
+ if (dot == 0)
+ dot = (e[0] == '/') ? 1 : 0;
+ }
+ dot = (dot == 3) || (dot == -1); /* filename contains ".."
+ * component */
+
+ if (*e == '\0') {
+ BIO_puts(io, text);
+ BIO_printf(io, "'%s' is an invalid file name\r\n", p);
+ break;
+ }
+ *e = '\0';
+
+ if (dot) {
+ BIO_puts(io, text);
+ BIO_printf(io, "'%s' contains '..' reference\r\n", p);
+ break;
+ }
+
+ if (*p == '/') {
+ BIO_puts(io, text);
+ BIO_printf(io, "'%s' is an invalid path\r\n", p);
+ break;
+ }
+
+ /* if a directory, do the index thang */
+ if (app_isdir(p) > 0) {
+ BIO_puts(io, text);
+ BIO_printf(io, "'%s' is a directory\r\n", p);
+ break;
+ }
+
+ if ((file = BIO_new_file(p, "r")) == NULL) {
+ BIO_puts(io, text);
+ BIO_printf(io, "Error opening '%s'\r\n", p);
+ ERR_print_errors(io);
+ break;
+ }
+
+ if (!s_quiet)
+ BIO_printf(bio_err, "FILE:%s\n", p);
+
+ if (www == 2) {
+ i = strlen(p);
+ if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) ||
+ ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) ||
+ ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0)))
+ BIO_puts(io,
+ "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
+ else
+ BIO_puts(io,
+ "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
+ }
+ /* send the file */
+ for (;;) {
+ i = BIO_read(file, buf, bufsize);
+ if (i <= 0)
+ break;
+
+#ifdef RENEG
+ total_bytes += i;
+ BIO_printf(bio_err, "%d\n", i);
+ if (total_bytes > 3 * 1024) {
+ total_bytes = 0;
+ BIO_printf(bio_err, "RENEGOTIATE\n");
+ SSL_renegotiate(con);
+ }
+#endif
+
+ for (j = 0; j < i;) {
+#ifdef RENEG
+ static count = 0;
+ if (++count == 13) {
+ SSL_renegotiate(con);
+ }
+#endif
+ k = BIO_write(io, &(buf[j]), i - j);
+ if (k <= 0) {
+ if (!BIO_should_retry(io)
+ && !SSL_waiting_for_async(con))
+ goto write_error;
+ else {
+ BIO_printf(bio_s_out, "rwrite W BLOCK\n");
+ }
+ } else {
+ j += k;
+ }
+ }
+ }
+ write_error:
+ BIO_free(file);
+ break;
+ }
+ }
+
+ for (;;) {
+ i = (int)BIO_flush(io);
+ if (i <= 0) {
+ if (!BIO_should_retry(io))
+ break;
+ } else
+ break;
+ }
+ end:
+ /* make sure we re-use sessions */
+ SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+
+ err:
+ OPENSSL_free(buf);
+ BIO_free_all(io);
+ return ret;
+}
+
+static int rev_body(int s, int stype, int prot, unsigned char *context)
+{
+ char *buf = NULL;
+ int i;
+ int ret = 1;
+ SSL *con;
+ BIO *io, *ssl_bio, *sbio;
+
+ buf = app_malloc(bufsize, "server rev buffer");
+ io = BIO_new(BIO_f_buffer());
+ ssl_bio = BIO_new(BIO_f_ssl());
+ if ((io == NULL) || (ssl_bio == NULL))
+ goto err;
+
+ /* lets make the output buffer a reasonable size */
+ if (!BIO_set_write_buffer_size(io, bufsize))
+ goto err;
+
+ if ((con = SSL_new(ctx)) == NULL)
+ goto err;
+
+ if (s_tlsextdebug) {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+ if (context != NULL
+ && !SSL_set_session_id_context(con, context,
+ strlen((char *)context))) {
+ SSL_free(con);
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
+ sbio = BIO_new_socket(s, BIO_NOCLOSE);
+ SSL_set_bio(con, sbio, sbio);
+ SSL_set_accept_state(con);
+
+ /* No need to free |con| after this. Done by BIO_free(ssl_bio) */
+ BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
+ BIO_push(io, ssl_bio);
+#ifdef CHARSET_EBCDIC
+ io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+#endif
+
+ if (s_debug) {
+ BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+ BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
+ }
+ if (s_msg) {
+#ifndef OPENSSL_NO_SSL_TRACE
+ if (s_msg == 2)
+ SSL_set_msg_callback(con, SSL_trace);
+ else
+#endif
+ SSL_set_msg_callback(con, msg_cb);
+ SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
+ }
+
+ for (;;) {
+ i = BIO_do_handshake(io);
+ if (i > 0)
+ break;
+ if (!BIO_should_retry(io)) {
+ BIO_puts(bio_err, "CONNECTION FAILURE\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (BIO_should_io_special(io)
+ && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ continue;
+ }
+#endif
+ }
+ BIO_printf(bio_err, "CONNECTION ESTABLISHED\n");
+ print_ssl_summary(con);
+
+ for (;;) {
+ i = BIO_gets(io, buf, bufsize - 1);
+ if (i < 0) { /* error */
+ if (!BIO_should_retry(io)) {
+ if (!s_quiet)
+ ERR_print_errors(bio_err);
+ goto err;
+ } else {
+ BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+ if (BIO_should_io_special(io)
+ && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+ SRP_user_pwd_free(srp_callback_parm.user);
+ srp_callback_parm.user =
+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ continue;
+ }
+#endif
+#if !defined(OPENSSL_SYS_MSDOS)
+ sleep(1);
+#endif
+ continue;
+ }
+ } else if (i == 0) { /* end of input */
+ ret = 1;
+ BIO_printf(bio_err, "CONNECTION CLOSED\n");
+ goto end;
+ } else {
+ char *p = buf + i - 1;
+ while (i && (*p == '\n' || *p == '\r')) {
+ p--;
+ i--;
+ }
+ if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) {
+ ret = 1;
+ BIO_printf(bio_err, "CONNECTION CLOSED\n");
+ goto end;
+ }
+ BUF_reverse((unsigned char *)buf, NULL, i);
+ buf[i] = '\n';
+ BIO_write(io, buf, i + 1);
+ for (;;) {
+ i = BIO_flush(io);
+ if (i > 0)
+ break;
+ if (!BIO_should_retry(io))
+ goto end;
+ }
+ }
+ }
+ end:
+ /* make sure we re-use sessions */
+ SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+
+ err:
+
+ OPENSSL_free(buf);
+ BIO_free_all(io);
+ return ret;
+}
+
+#define MAX_SESSION_ID_ATTEMPTS 10
+static int generate_session_id(SSL *ssl, unsigned char *id,
+ unsigned int *id_len)
+{
+ unsigned int count = 0;
+ do {
+ if (RAND_bytes(id, *id_len) <= 0)
+ return 0;
+ /*
+ * Prefix the session_id with the required prefix. NB: If our prefix
+ * is too long, clip it - but there will be worse effects anyway, eg.
+ * the server could only possibly create 1 session ID (ie. the
+ * prefix!) so all future session negotiations will fail due to
+ * conflicts.
+ */
+ memcpy(id, session_id_prefix,
+ (strlen(session_id_prefix) < *id_len) ?
+ strlen(session_id_prefix) : *id_len);
+ }
+ while (SSL_has_matching_session_id(ssl, id, *id_len) &&
+ (++count < MAX_SESSION_ID_ATTEMPTS));
+ if (count >= MAX_SESSION_ID_ATTEMPTS)
+ return 0;
+ return 1;
+}
+
+/*
+ * By default s_server uses an in-memory cache which caches SSL_SESSION
+ * structures without any serialisation. This hides some bugs which only
+ * become apparent in deployed servers. By implementing a basic external
+ * session cache some issues can be debugged using s_server.
+ */
+
+typedef struct simple_ssl_session_st {
+ unsigned char *id;
+ unsigned int idlen;
+ unsigned char *der;
+ int derlen;
+ struct simple_ssl_session_st *next;
+} simple_ssl_session;
+
+static simple_ssl_session *first = NULL;
+
+static int add_session(SSL *ssl, SSL_SESSION *session)
+{
+ simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session");
+ unsigned char *p;
+
+ SSL_SESSION_get_id(session, &sess->idlen);
+ sess->derlen = i2d_SSL_SESSION(session, NULL);
+ if (sess->derlen < 0) {
+ BIO_printf(bio_err, "Error encoding session\n");
+ OPENSSL_free(sess);
+ return 0;
+ }
+
+ sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
+ sess->der = app_malloc(sess->derlen, "get session buffer");
+ if (!sess->id) {
+ BIO_printf(bio_err, "Out of memory adding to external cache\n");
+ OPENSSL_free(sess->id);
+ OPENSSL_free(sess->der);
+ OPENSSL_free(sess);
+ return 0;
+ }
+ p = sess->der;
+
+ /* Assume it still works. */
+ if (i2d_SSL_SESSION(session, &p) != sess->derlen) {
+ BIO_printf(bio_err, "Unexpected session encoding length\n");
+ OPENSSL_free(sess->id);
+ OPENSSL_free(sess->der);
+ OPENSSL_free(sess);
+ return 0;
+ }
+
+ sess->next = first;
+ first = sess;
+ BIO_printf(bio_err, "New session added to external cache\n");
+ return 0;
+}
+
+static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen,
+ int *do_copy)
+{
+ simple_ssl_session *sess;
+ *do_copy = 0;
+ for (sess = first; sess; sess = sess->next) {
+ if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
+ const unsigned char *p = sess->der;
+ BIO_printf(bio_err, "Lookup session: cache hit\n");
+ return d2i_SSL_SESSION(NULL, &p, sess->derlen);
+ }
+ }
+ BIO_printf(bio_err, "Lookup session: cache miss\n");
+ return NULL;
+}
+
+static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
+{
+ simple_ssl_session *sess, *prev = NULL;
+ const unsigned char *id;
+ unsigned int idlen;
+ id = SSL_SESSION_get_id(session, &idlen);
+ for (sess = first; sess; sess = sess->next) {
+ if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) {
+ if (prev)
+ prev->next = sess->next;
+ else
+ first = sess->next;
+ OPENSSL_free(sess->id);
+ OPENSSL_free(sess->der);
+ OPENSSL_free(sess);
+ return;
+ }
+ prev = sess;
+ }
+}
+
+static void init_session_cache_ctx(SSL_CTX *sctx)
+{
+ SSL_CTX_set_session_cache_mode(sctx,
+ SSL_SESS_CACHE_NO_INTERNAL |
+ SSL_SESS_CACHE_SERVER);
+ SSL_CTX_sess_set_new_cb(sctx, add_session);
+ SSL_CTX_sess_set_get_cb(sctx, get_session);
+ SSL_CTX_sess_set_remove_cb(sctx, del_session);
+}
+
+static void free_sessions(void)
+{
+ simple_ssl_session *sess, *tsess;
+ for (sess = first; sess;) {
+ OPENSSL_free(sess->id);
+ OPENSSL_free(sess->der);
+ tsess = sess;
+ sess = sess->next;
+ OPENSSL_free(tsess);
+ }
+ first = NULL;
+}
+
+#endif /* OPENSSL_NO_SOCK */
diff --git a/freebsd/crypto/openssl/apps/s_socket.c b/freebsd/crypto/openssl/apps/s_socket.c
new file mode 100644
index 00000000..497eb290
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_socket.c
@@ -0,0 +1,397 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* socket-related functions used by s_client and s_server */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <openssl/opensslconf.h>
+
+/*
+ * With IPv6, it looks like Digital has mixed up the proper order of
+ * recursive header file inclusion, resulting in the compiler complaining
+ * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
+ * needed to have fileno() declared correctly... So let's define u_int
+ */
+#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
+# define __U_INT
+typedef unsigned int u_int;
+#endif
+
+#ifndef OPENSSL_NO_SOCK
+
+# include "apps.h"
+# include "s_apps.h"
+# include "internal/sockets.h"
+
+# include <openssl/bio.h>
+# include <openssl/err.h>
+
+/* Keep track of our peer's address for the cookie callback */
+BIO_ADDR *ourpeer = NULL;
+
+/*
+ * init_client - helper routine to set up socket communication
+ * @sock: pointer to storage of resulting socket.
+ * @host: the host name or path (for AF_UNIX) to connect to.
+ * @port: the port to connect to (ignored for AF_UNIX).
+ * @bindhost: source host or path (for AF_UNIX).
+ * @bindport: source port (ignored for AF_UNIX).
+ * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
+ * AF_UNSPEC
+ * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
+ * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
+ *
+ * This will create a socket and use it to connect to a host:port, or if
+ * family == AF_UNIX, to the path found in host.
+ *
+ * If the host has more than one address, it will try them one by one until
+ * a successful connection is established. The resulting socket will be
+ * found in *sock on success, it will be given INVALID_SOCKET otherwise.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int init_client(int *sock, const char *host, const char *port,
+ const char *bindhost, const char *bindport,
+ int family, int type, int protocol)
+{
+ BIO_ADDRINFO *res = NULL;
+ BIO_ADDRINFO *bindaddr = NULL;
+ const BIO_ADDRINFO *ai = NULL;
+ const BIO_ADDRINFO *bi = NULL;
+ int found = 0;
+ int ret;
+
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol,
+ &res);
+ if (ret == 0) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ if (bindhost != NULL || bindport != NULL) {
+ ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT,
+ family, type, protocol, &bindaddr);
+ if (ret == 0) {
+ ERR_print_errors (bio_err);
+ goto out;
+ }
+ }
+
+ ret = 0;
+ for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
+ /* Admittedly, these checks are quite paranoid, we should not get
+ * anything in the BIO_ADDRINFO chain that we haven't
+ * asked for. */
+ OPENSSL_assert((family == AF_UNSPEC
+ || family == BIO_ADDRINFO_family(ai))
+ && (type == 0 || type == BIO_ADDRINFO_socktype(ai))
+ && (protocol == 0
+ || protocol == BIO_ADDRINFO_protocol(ai)));
+
+ if (bindaddr != NULL) {
+ for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) {
+ if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai))
+ break;
+ }
+ if (bi == NULL)
+ continue;
+ ++found;
+ }
+
+ *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai),
+ BIO_ADDRINFO_protocol(ai), 0);
+ if (*sock == INVALID_SOCKET) {
+ /* Maybe the kernel doesn't support the socket family, even if
+ * BIO_lookup() added it in the returned result...
+ */
+ continue;
+ }
+
+ if (bi != NULL) {
+ if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi),
+ BIO_SOCK_REUSEADDR)) {
+ BIO_closesocket(*sock);
+ *sock = INVALID_SOCKET;
+ break;
+ }
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ /*
+ * For SCTP we have to set various options on the socket prior to
+ * connecting. This is done automatically by BIO_new_dgram_sctp().
+ * We don't actually need the created BIO though so we free it again
+ * immediately.
+ */
+ BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE);
+
+ if (tmpbio == NULL) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+ BIO_free(tmpbio);
+ }
+#endif
+
+ if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
+ protocol == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
+ BIO_closesocket(*sock);
+ *sock = INVALID_SOCKET;
+ continue;
+ }
+
+ /* Success, don't try any more addresses */
+ break;
+ }
+
+ if (*sock == INVALID_SOCKET) {
+ if (bindaddr != NULL && !found) {
+ BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n",
+ BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " :
+ BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " :
+ BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "",
+ bindhost != NULL ? bindhost : "",
+ bindport != NULL ? ":" : "",
+ bindport != NULL ? bindport : "");
+ ERR_clear_error();
+ ret = 0;
+ }
+ ERR_print_errors(bio_err);
+ } else {
+ /* Remove any stale errors from previous connection attempts */
+ ERR_clear_error();
+ ret = 1;
+ }
+out:
+ if (bindaddr != NULL) {
+ BIO_ADDRINFO_free (bindaddr);
+ }
+ BIO_ADDRINFO_free(res);
+ return ret;
+}
+
+/*
+ * do_server - helper routine to perform a server operation
+ * @accept_sock: pointer to storage of resulting socket.
+ * @host: the host name or path (for AF_UNIX) to connect to.
+ * @port: the port to connect to (ignored for AF_UNIX).
+ * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
+ * AF_UNSPEC
+ * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
+ * @cb: pointer to a function that receives the accepted socket and
+ * should perform the communication with the connecting client.
+ * @context: pointer to memory that's passed verbatim to the cb function.
+ * @naccept: number of times an incoming connect should be accepted. If -1,
+ * unlimited number.
+ *
+ * This will create a socket and use it to listen to a host:port, or if
+ * family == AF_UNIX, to the path found in host, then start accepting
+ * incoming connections and run cb on the resulting socket.
+ *
+ * 0 on failure, something other on success.
+ */
+int do_server(int *accept_sock, const char *host, const char *port,
+ int family, int type, int protocol, do_server_cb cb,
+ unsigned char *context, int naccept, BIO *bio_s_out)
+{
+ int asock = 0;
+ int sock;
+ int i;
+ BIO_ADDRINFO *res = NULL;
+ const BIO_ADDRINFO *next;
+ int sock_family, sock_type, sock_protocol, sock_port;
+ const BIO_ADDR *sock_address;
+ int sock_options = BIO_SOCK_REUSEADDR;
+ int ret = 0;
+
+ if (BIO_sock_init() != 1)
+ return 0;
+
+ if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol,
+ &res)) {
+ ERR_print_errors(bio_err);
+ return 0;
+ }
+
+ /* Admittedly, these checks are quite paranoid, we should not get
+ * anything in the BIO_ADDRINFO chain that we haven't asked for */
+ OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
+ && (type == 0 || type == BIO_ADDRINFO_socktype(res))
+ && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res)));
+
+ sock_family = BIO_ADDRINFO_family(res);
+ sock_type = BIO_ADDRINFO_socktype(res);
+ sock_protocol = BIO_ADDRINFO_protocol(res);
+ sock_address = BIO_ADDRINFO_address(res);
+ next = BIO_ADDRINFO_next(res);
+ if (sock_family == AF_INET6)
+ sock_options |= BIO_SOCK_V6_ONLY;
+ if (next != NULL
+ && BIO_ADDRINFO_socktype(next) == sock_type
+ && BIO_ADDRINFO_protocol(next) == sock_protocol) {
+ if (sock_family == AF_INET
+ && BIO_ADDRINFO_family(next) == AF_INET6) {
+ sock_family = AF_INET6;
+ sock_address = BIO_ADDRINFO_address(next);
+ } else if (sock_family == AF_INET6
+ && BIO_ADDRINFO_family(next) == AF_INET) {
+ sock_options &= ~BIO_SOCK_V6_ONLY;
+ }
+ }
+
+ asock = BIO_socket(sock_family, sock_type, sock_protocol, 0);
+ if (asock == INVALID_SOCKET
+ || !BIO_listen(asock, sock_address, sock_options)) {
+ BIO_ADDRINFO_free(res);
+ ERR_print_errors(bio_err);
+ if (asock != INVALID_SOCKET)
+ BIO_closesocket(asock);
+ goto end;
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (protocol == IPPROTO_SCTP) {
+ /*
+ * For SCTP we have to set various options on the socket prior to
+ * accepting. This is done automatically by BIO_new_dgram_sctp().
+ * We don't actually need the created BIO though so we free it again
+ * immediately.
+ */
+ BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE);
+
+ if (tmpbio == NULL) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_free(tmpbio);
+ }
+#endif
+
+ sock_port = BIO_ADDR_rawport(sock_address);
+
+ BIO_ADDRINFO_free(res);
+ res = NULL;
+
+ if (sock_port == 0) {
+ /* dynamically allocated port, report which one */
+ union BIO_sock_info_u info;
+ char *hostname = NULL;
+ char *service = NULL;
+ int success = 0;
+
+ if ((info.addr = BIO_ADDR_new()) != NULL
+ && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info)
+ && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL
+ && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL
+ && BIO_printf(bio_s_out,
+ strchr(hostname, ':') == NULL
+ ? /* IPv4 */ "ACCEPT %s:%s\n"
+ : /* IPv6 */ "ACCEPT [%s]:%s\n",
+ hostname, service) > 0)
+ success = 1;
+
+ (void)BIO_flush(bio_s_out);
+ OPENSSL_free(hostname);
+ OPENSSL_free(service);
+ BIO_ADDR_free(info.addr);
+ if (!success) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ } else {
+ (void)BIO_printf(bio_s_out, "ACCEPT\n");
+ (void)BIO_flush(bio_s_out);
+ }
+
+ if (accept_sock != NULL)
+ *accept_sock = asock;
+ for (;;) {
+ char sink[64];
+ struct timeval timeout;
+ fd_set readfds;
+
+ if (type == SOCK_STREAM) {
+ BIO_ADDR_free(ourpeer);
+ ourpeer = BIO_ADDR_new();
+ if (ourpeer == NULL) {
+ BIO_closesocket(asock);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ do {
+ sock = BIO_accept_ex(asock, ourpeer, 0);
+ } while (sock < 0 && BIO_sock_should_retry(sock));
+ if (sock < 0) {
+ ERR_print_errors(bio_err);
+ BIO_closesocket(asock);
+ break;
+ }
+ BIO_set_tcp_ndelay(sock, 1);
+ i = (*cb)(sock, type, protocol, context);
+
+ /*
+ * If we ended with an alert being sent, but still with data in the
+ * network buffer to be read, then calling BIO_closesocket() will
+ * result in a TCP-RST being sent. On some platforms (notably
+ * Windows) then this will result in the peer immediately abandoning
+ * the connection including any buffered alert data before it has
+ * had a chance to be read. Shutting down the sending side first,
+ * and then closing the socket sends TCP-FIN first followed by
+ * TCP-RST. This seems to allow the peer to read the alert data.
+ */
+ shutdown(sock, 1); /* SHUT_WR */
+ /*
+ * We just said we have nothing else to say, but it doesn't mean
+ * that the other side has nothing. It's even recommended to
+ * consume incoming data. [In testing context this ensures that
+ * alerts are passed on...]
+ */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000; /* some extreme round-trip */
+ do {
+ FD_ZERO(&readfds);
+ openssl_fdset(sock, &readfds);
+ } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0
+ && readsocket(sock, sink, sizeof(sink)) > 0);
+
+ BIO_closesocket(sock);
+ } else {
+ i = (*cb)(asock, type, protocol, context);
+ }
+
+ if (naccept != -1)
+ naccept--;
+ if (i < 0 || naccept == 0) {
+ BIO_closesocket(asock);
+ ret = i;
+ break;
+ }
+ }
+ end:
+# ifdef AF_UNIX
+ if (family == AF_UNIX)
+ unlink(host);
+# endif
+ BIO_ADDR_free(ourpeer);
+ ourpeer = NULL;
+ return ret;
+}
+
+#endif /* OPENSSL_NO_SOCK */
diff --git a/freebsd/crypto/openssl/apps/s_time.c b/freebsd/crypto/openssl/apps/s_time.c
new file mode 100644
index 00000000..e807cb38
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/s_time.c
@@ -0,0 +1,407 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_SOCK
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/pem.h>
+#include "s_apps.h"
+#include <openssl/err.h>
+#include <internal/sockets.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+# include OPENSSL_UNISTD
+#endif
+
+#define SSL_CONNECT_NAME "localhost:4433"
+
+#define SECONDS 30
+#define SECONDSSTR "30"
+
+static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx);
+
+/*
+ * Define a HTTP get command globally.
+ * Also define the size of the command, this is two bytes less than
+ * the size of the string because the %s is replaced by the URL.
+ */
+static const char fmt_http_get_cmd[] = "GET %s HTTP/1.0\r\n\r\n";
+static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY,
+ OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE,
+ OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
+ OPT_WWW
+} OPTION_CHOICE;
+
+const OPTIONS s_time_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"connect", OPT_CONNECT, 's',
+ "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
+ {"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"},
+ {"ciphersuites", OPT_CIPHERSUITES, 's',
+ "Specify TLSv1.3 ciphersuites to be used"},
+ {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"},
+ {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
+ {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"new", OPT_NEW, '-', "Just time new connections"},
+ {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
+ {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
+ {"verify", OPT_VERIFY, 'p',
+ "Turn on peer certificate verification, set depth"},
+ {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR},
+ {"www", OPT_WWW, 's', "Fetch specified page from the site"},
+#ifndef OPENSSL_NO_SSL3
+ {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
+#endif
+ {NULL}
+};
+
+#define START 0
+#define STOP 1
+
+static double tm_Time_F(int s)
+{
+ return app_tminterval(s, 1);
+}
+
+int s_time_main(int argc, char **argv)
+{
+ char buf[1024 * 8];
+ SSL *scon = NULL;
+ SSL_CTX *ctx = NULL;
+ const SSL_METHOD *meth = NULL;
+ char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL;
+ char *www_path = NULL;
+ char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
+ double totalTime = 0.0;
+ int noCApath = 0, noCAfile = 0;
+ int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0;
+ long bytes_read = 0, finishtime = 0;
+ OPTION_CHOICE o;
+ int max_version = 0, ver, buf_len;
+ size_t buf_size;
+
+ meth = TLS_client_method();
+
+ prog = opt_init(argc, argv, s_time_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(s_time_options);
+ ret = 0;
+ goto end;
+ case OPT_CONNECT:
+ host = opt_arg();
+ break;
+ case OPT_REUSE:
+ perform = 2;
+ break;
+ case OPT_NEW:
+ perform = 1;
+ break;
+ case OPT_VERIFY:
+ if (!opt_int(opt_arg(), &verify_args.depth))
+ goto opthelp;
+ BIO_printf(bio_err, "%s: verify depth is %d\n",
+ prog, verify_args.depth);
+ break;
+ case OPT_CERT:
+ certfile = opt_arg();
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto end;
+ break;
+ case OPT_KEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_CIPHER:
+ cipher = opt_arg();
+ break;
+ case OPT_CIPHERSUITES:
+ ciphersuites = opt_arg();
+ break;
+ case OPT_BUGS:
+ st_bugs = 1;
+ break;
+ case OPT_TIME:
+ if (!opt_int(opt_arg(), &maxtime))
+ goto opthelp;
+ break;
+ case OPT_WWW:
+ www_path = opt_arg();
+ buf_size = strlen(www_path) + fmt_http_get_cmd_size;
+ if (buf_size > sizeof(buf)) {
+ BIO_printf(bio_err, "%s: -www option is too long\n", prog);
+ goto end;
+ }
+ break;
+ case OPT_SSL3:
+ max_version = SSL3_VERSION;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (cipher == NULL)
+ cipher = getenv("SSL_CIPHER");
+
+ if ((ctx = SSL_CTX_new(meth)) == NULL)
+ goto end;
+
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+ SSL_CTX_set_quiet_shutdown(ctx, 1);
+ if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
+ goto end;
+
+ if (st_bugs)
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
+ if (cipher != NULL && !SSL_CTX_set_cipher_list(ctx, cipher))
+ goto end;
+ if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites))
+ goto end;
+ if (!set_cert_stuff(ctx, certfile, keyfile))
+ goto end;
+
+ if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (!(perform & 1))
+ goto next;
+ printf("Collecting connection statistics for %d seconds\n", maxtime);
+
+ /* Loop and time how long it takes to make connections */
+
+ bytes_read = 0;
+ finishtime = (long)time(NULL) + maxtime;
+ tm_Time_F(START);
+ for (;;) {
+ if (finishtime < (long)time(NULL))
+ break;
+
+ if ((scon = doConnection(NULL, host, ctx)) == NULL)
+ goto end;
+
+ if (www_path != NULL) {
+ buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd,
+ www_path);
+ if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
+ goto end;
+ while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
+ bytes_read += i;
+ }
+ SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ BIO_closesocket(SSL_get_fd(scon));
+
+ nConn += 1;
+ if (SSL_session_reused(scon)) {
+ ver = 'r';
+ } else {
+ ver = SSL_version(scon);
+ if (ver == TLS1_VERSION)
+ ver = 't';
+ else if (ver == SSL3_VERSION)
+ ver = '3';
+ else
+ ver = '*';
+ }
+ fputc(ver, stdout);
+ fflush(stdout);
+
+ SSL_free(scon);
+ scon = NULL;
+ }
+ totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
+
+ i = (int)((long)time(NULL) - finishtime + maxtime);
+ printf
+ ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
+ nConn, totalTime, ((double)nConn / totalTime), bytes_read);
+ printf
+ ("%d connections in %ld real seconds, %ld bytes read per connection\n",
+ nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
+
+ /*
+ * Now loop and time connections using the same session id over and over
+ */
+
+ next:
+ if (!(perform & 2))
+ goto end;
+ printf("\n\nNow timing with session id reuse.\n");
+
+ /* Get an SSL object so we can reuse the session id */
+ if ((scon = doConnection(NULL, host, ctx)) == NULL) {
+ BIO_printf(bio_err, "Unable to get connection\n");
+ goto end;
+ }
+
+ if (www_path != NULL) {
+ buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path);
+ if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
+ goto end;
+ while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
+ continue;
+ }
+ SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ BIO_closesocket(SSL_get_fd(scon));
+
+ nConn = 0;
+ totalTime = 0.0;
+
+ finishtime = (long)time(NULL) + maxtime;
+
+ printf("starting\n");
+ bytes_read = 0;
+ tm_Time_F(START);
+
+ for (;;) {
+ if (finishtime < (long)time(NULL))
+ break;
+
+ if ((doConnection(scon, host, ctx)) == NULL)
+ goto end;
+
+ if (www_path != NULL) {
+ buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd,
+ www_path);
+ if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
+ goto end;
+ while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
+ bytes_read += i;
+ }
+ SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ BIO_closesocket(SSL_get_fd(scon));
+
+ nConn += 1;
+ if (SSL_session_reused(scon)) {
+ ver = 'r';
+ } else {
+ ver = SSL_version(scon);
+ if (ver == TLS1_VERSION)
+ ver = 't';
+ else if (ver == SSL3_VERSION)
+ ver = '3';
+ else
+ ver = '*';
+ }
+ fputc(ver, stdout);
+ fflush(stdout);
+ }
+ totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
+
+ printf
+ ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
+ nConn, totalTime, ((double)nConn / totalTime), bytes_read);
+ printf
+ ("%d connections in %ld real seconds, %ld bytes read per connection\n",
+ nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
+
+ ret = 0;
+
+ end:
+ SSL_free(scon);
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+/*-
+ * doConnection - make a connection
+ */
+static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
+{
+ BIO *conn;
+ SSL *serverCon;
+ int i;
+
+ if ((conn = BIO_new(BIO_s_connect())) == NULL)
+ return NULL;
+
+ BIO_set_conn_hostname(conn, host);
+ BIO_set_conn_mode(conn, BIO_SOCK_NODELAY);
+
+ if (scon == NULL)
+ serverCon = SSL_new(ctx);
+ else {
+ serverCon = scon;
+ SSL_set_connect_state(serverCon);
+ }
+
+ SSL_set_bio(serverCon, conn, conn);
+
+ /* ok, lets connect */
+ i = SSL_connect(serverCon);
+ if (i <= 0) {
+ BIO_printf(bio_err, "ERROR\n");
+ if (verify_args.error != X509_V_OK)
+ BIO_printf(bio_err, "verify error:%s\n",
+ X509_verify_cert_error_string(verify_args.error));
+ else
+ ERR_print_errors(bio_err);
+ if (scon == NULL)
+ SSL_free(serverCon);
+ return NULL;
+ }
+
+#if defined(SOL_SOCKET) && defined(SO_LINGER)
+ {
+ struct linger no_linger;
+ int fd;
+
+ no_linger.l_onoff = 1;
+ no_linger.l_linger = 0;
+ fd = SSL_get_fd(serverCon);
+ if (fd >= 0)
+ (void)setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&no_linger,
+ sizeof(no_linger));
+ }
+#endif
+
+ return serverCon;
+}
+#endif /* OPENSSL_NO_SOCK */
diff --git a/freebsd/crypto/openssl/apps/sess_id.c b/freebsd/crypto/openssl/apps/sess_id.c
new file mode 100644
index 00000000..537fdab4
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/sess_id.c
@@ -0,0 +1,193 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
+ OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT
+} OPTION_CHOICE;
+
+const OPTIONS sess_id_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
+ {"outform", OPT_OUTFORM, 'f',
+ "Output format - default PEM (PEM, DER or NSS)"},
+ {"in", OPT_IN, 's', "Input file - default stdin"},
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"text", OPT_TEXT, '-', "Print ssl session id details"},
+ {"cert", OPT_CERT, '-', "Output certificate "},
+ {"noout", OPT_NOOUT, '-', "Don't output the encoded session info"},
+ {"context", OPT_CONTEXT, 's', "Set the session ID context"},
+ {NULL}
+};
+
+static SSL_SESSION *load_sess_id(char *file, int format);
+
+int sess_id_main(int argc, char **argv)
+{
+ SSL_SESSION *x = NULL;
+ X509 *peer = NULL;
+ BIO *out = NULL;
+ char *infile = NULL, *outfile = NULL, *context = NULL, *prog;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM;
+ int cert = 0, noout = 0, text = 0, ret = 1, i, num = 0;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, sess_id_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(sess_id_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
+ goto opthelp;
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER | OPT_FMT_NSS,
+ &outformat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_TEXT:
+ text = ++num;
+ break;
+ case OPT_CERT:
+ cert = ++num;
+ break;
+ case OPT_NOOUT:
+ noout = ++num;
+ break;
+ case OPT_CONTEXT:
+ context = opt_arg();
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ x = load_sess_id(infile, informat);
+ if (x == NULL) {
+ goto end;
+ }
+ peer = SSL_SESSION_get0_peer(x);
+
+ if (context != NULL) {
+ size_t ctx_len = strlen(context);
+ if (ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ BIO_printf(bio_err, "Context too long\n");
+ goto end;
+ }
+ if (!SSL_SESSION_set1_id_context(x, (unsigned char *)context,
+ ctx_len)) {
+ BIO_printf(bio_err, "Error setting id context\n");
+ goto end;
+ }
+ }
+
+ if (!noout || text) {
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+ }
+
+ if (text) {
+ SSL_SESSION_print(out, x);
+
+ if (cert) {
+ if (peer == NULL)
+ BIO_puts(out, "No certificate present\n");
+ else
+ X509_print(out, peer);
+ }
+ }
+
+ if (!noout && !cert) {
+ if (outformat == FORMAT_ASN1) {
+ i = i2d_SSL_SESSION_bio(out, x);
+ } else if (outformat == FORMAT_PEM) {
+ i = PEM_write_bio_SSL_SESSION(out, x);
+ } else if (outformat == FORMAT_NSS) {
+ i = SSL_SESSION_print_keylog(out, x);
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+ if (!i) {
+ BIO_printf(bio_err, "unable to write SSL_SESSION\n");
+ goto end;
+ }
+ } else if (!noout && (peer != NULL)) { /* just print the certificate */
+ if (outformat == FORMAT_ASN1) {
+ i = (int)i2d_X509_bio(out, peer);
+ } else if (outformat == FORMAT_PEM) {
+ i = PEM_write_bio_X509(out, peer);
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+ if (!i) {
+ BIO_printf(bio_err, "unable to write X509\n");
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ BIO_free_all(out);
+ SSL_SESSION_free(x);
+ return ret;
+}
+
+static SSL_SESSION *load_sess_id(char *infile, int format)
+{
+ SSL_SESSION *x = NULL;
+ BIO *in = NULL;
+
+ in = bio_open_default(infile, 'r', format);
+ if (in == NULL)
+ goto end;
+ if (format == FORMAT_ASN1)
+ x = d2i_SSL_SESSION_bio(in, NULL);
+ else
+ x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
+ if (x == NULL) {
+ BIO_printf(bio_err, "unable to load SSL_SESSION\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ end:
+ BIO_free(in);
+ return x;
+}
diff --git a/freebsd/crypto/openssl/apps/smime.c b/freebsd/crypto/openssl/apps/smime.c
new file mode 100644
index 00000000..0b96a717
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/smime.c
@@ -0,0 +1,649 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* S/MIME utility function */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers);
+static int smime_cb(int ok, X509_STORE_CTX *ctx);
+
+#define SMIME_OP 0x10
+#define SMIME_IP 0x20
+#define SMIME_SIGNERS 0x40
+#define SMIME_ENCRYPT (1 | SMIME_OP)
+#define SMIME_DECRYPT (2 | SMIME_IP)
+#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_VERIFY (4 | SMIME_IP)
+#define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP)
+#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY,
+ OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN,
+ OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP,
+ OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF,
+ OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN,
+ OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
+ OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
+ OPT_R_ENUM,
+ OPT_V_ENUM,
+ OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT,
+ OPT_OUTFORM, OPT_CONTENT
+} OPTION_CHOICE;
+
+const OPTIONS smime_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
+ {OPT_HELP_STR, 1, '-',
+ " cert.pem... recipient certs for encryption\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
+ {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
+ {"sign", OPT_SIGN, '-', "Sign message"},
+ {"verify", OPT_VERIFY, '-', "Verify signed message"},
+ {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"},
+ {"nointern", OPT_NOINTERN, '-',
+ "Don't search certificates in message for signer"},
+ {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
+ {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
+ {"nocerts", OPT_NOCERTS, '-',
+ "Don't include signers certificate when signing"},
+ {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
+ {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
+ {"binary", OPT_BINARY, '-', "Don't translate message to text"},
+ {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate file"},
+ {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
+ {"inkey", OPT_INKEY, 's',
+ "Input private key (if not signer or recipient)"},
+ {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"outform", OPT_OUTFORM, 'c',
+ "Output format SMIME (default), PEM or DER"},
+ {"content", OPT_CONTENT, '<',
+ "Supply or override content for detached signature"},
+ {"to", OPT_TO, 's', "To address"},
+ {"from", OPT_FROM, 's', "From address"},
+ {"subject", OPT_SUBJECT, 's', "Subject"},
+ {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
+ {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"},
+ {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+ {"nochain", OPT_NOCHAIN, '-',
+ "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" },
+ {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
+ {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
+ {"indef", OPT_INDEF, '-', "Same as -stream" },
+ {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+ {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"},
+ OPT_R_OPTIONS,
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
+ {"", OPT_CIPHER, '-', "Any supported cipher"},
+ OPT_V_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int smime_main(int argc, char **argv)
+{
+ BIO *in = NULL, *out = NULL, *indata = NULL;
+ EVP_PKEY *key = NULL;
+ PKCS7 *p7 = NULL;
+ STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
+ STACK_OF(X509) *encerts = NULL, *other = NULL;
+ X509 *cert = NULL, *recip = NULL, *signer = NULL;
+ X509_STORE *store = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ const EVP_MD *sign_md = NULL;
+ const char *CAfile = NULL, *CApath = NULL, *prog = NULL;
+ char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
+ char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL;
+ char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL;
+ OPTION_CHOICE o;
+ int noCApath = 0, noCAfile = 0;
+ int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0;
+ int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
+ FORMAT_PEM;
+ int vpmtouched = 0, rv = 0;
+ ENGINE *e = NULL;
+ const char *mime_eol = "\n";
+
+ if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
+ return 1;
+
+ prog = opt_init(argc, argv, smime_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(smime_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_ENCRYPT:
+ operation = SMIME_ENCRYPT;
+ break;
+ case OPT_DECRYPT:
+ operation = SMIME_DECRYPT;
+ break;
+ case OPT_SIGN:
+ operation = SMIME_SIGN;
+ break;
+ case OPT_RESIGN:
+ operation = SMIME_RESIGN;
+ break;
+ case OPT_VERIFY:
+ operation = SMIME_VERIFY;
+ break;
+ case OPT_PK7OUT:
+ operation = SMIME_PK7OUT;
+ break;
+ case OPT_TEXT:
+ flags |= PKCS7_TEXT;
+ break;
+ case OPT_NOINTERN:
+ flags |= PKCS7_NOINTERN;
+ break;
+ case OPT_NOVERIFY:
+ flags |= PKCS7_NOVERIFY;
+ break;
+ case OPT_NOCHAIN:
+ flags |= PKCS7_NOCHAIN;
+ break;
+ case OPT_NOCERTS:
+ flags |= PKCS7_NOCERTS;
+ break;
+ case OPT_NOATTR:
+ flags |= PKCS7_NOATTR;
+ break;
+ case OPT_NODETACH:
+ flags &= ~PKCS7_DETACHED;
+ break;
+ case OPT_NOSMIMECAP:
+ flags |= PKCS7_NOSMIMECAP;
+ break;
+ case OPT_BINARY:
+ flags |= PKCS7_BINARY;
+ break;
+ case OPT_NOSIGS:
+ flags |= PKCS7_NOSIGS;
+ break;
+ case OPT_STREAM:
+ case OPT_INDEF:
+ indef = 1;
+ break;
+ case OPT_NOINDEF:
+ indef = 0;
+ break;
+ case OPT_CRLFEOL:
+ flags |= PKCS7_CRLFEOL;
+ mime_eol = "\r\n";
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_TO:
+ to = opt_arg();
+ break;
+ case OPT_FROM:
+ from = opt_arg();
+ break;
+ case OPT_SUBJECT:
+ subject = opt_arg();
+ break;
+ case OPT_SIGNER:
+ /* If previous -signer argument add signer to list */
+ if (signerfile != NULL) {
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (keyfile == NULL)
+ keyfile = signerfile;
+ if (skkeys == NULL
+ && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ keyfile = NULL;
+ }
+ signerfile = opt_arg();
+ break;
+ case OPT_RECIP:
+ recipfile = opt_arg();
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_arg(), &sign_md))
+ goto opthelp;
+ break;
+ case OPT_CIPHER:
+ if (!opt_cipher(opt_unknown(), &cipher))
+ goto opthelp;
+ break;
+ case OPT_INKEY:
+ /* If previous -inkey argument add signer to list */
+ if (keyfile != NULL) {
+ if (signerfile == NULL) {
+ BIO_printf(bio_err,
+ "%s: Must have -signer before -inkey\n", prog);
+ goto opthelp;
+ }
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ signerfile = NULL;
+ if (skkeys == NULL
+ && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ }
+ keyfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
+ goto opthelp;
+ break;
+ case OPT_CERTFILE:
+ certfile = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_CONTENT:
+ contfile = opt_arg();
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto opthelp;
+ vpmtouched++;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
+ BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
+ goto opthelp;
+ }
+
+ if (operation & SMIME_SIGNERS) {
+ /* Check to see if any final signer needs to be appended */
+ if (keyfile && !signerfile) {
+ BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+ goto opthelp;
+ }
+ if (signerfile != NULL) {
+ if (sksigners == NULL
+ && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ sk_OPENSSL_STRING_push(sksigners, signerfile);
+ if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+ goto end;
+ if (!keyfile)
+ keyfile = signerfile;
+ sk_OPENSSL_STRING_push(skkeys, keyfile);
+ }
+ if (sksigners == NULL) {
+ BIO_printf(bio_err, "No signer certificate specified\n");
+ goto opthelp;
+ }
+ signerfile = NULL;
+ keyfile = NULL;
+ } else if (operation == SMIME_DECRYPT) {
+ if (recipfile == NULL && keyfile == NULL) {
+ BIO_printf(bio_err,
+ "No recipient certificate or key specified\n");
+ goto opthelp;
+ }
+ } else if (operation == SMIME_ENCRYPT) {
+ if (argc == 0) {
+ BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
+ goto opthelp;
+ }
+ } else if (!operation) {
+ goto opthelp;
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ ret = 2;
+
+ if (!(operation & SMIME_SIGNERS))
+ flags &= ~PKCS7_DETACHED;
+
+ if (!(operation & SMIME_OP)) {
+ if (flags & PKCS7_BINARY)
+ outformat = FORMAT_BINARY;
+ }
+
+ if (!(operation & SMIME_IP)) {
+ if (flags & PKCS7_BINARY)
+ informat = FORMAT_BINARY;
+ }
+
+ if (operation == SMIME_ENCRYPT) {
+ if (cipher == NULL) {
+#ifndef OPENSSL_NO_DES
+ cipher = EVP_des_ede3_cbc();
+#else
+ BIO_printf(bio_err, "No cipher selected\n");
+ goto end;
+#endif
+ }
+ encerts = sk_X509_new_null();
+ if (encerts == NULL)
+ goto end;
+ while (*argv != NULL) {
+ cert = load_cert(*argv, FORMAT_PEM,
+ "recipient certificate file");
+ if (cert == NULL)
+ goto end;
+ sk_X509_push(encerts, cert);
+ cert = NULL;
+ argv++;
+ }
+ }
+
+ if (certfile != NULL) {
+ if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
+ "certificate file")) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
+ if ((recip = load_cert(recipfile, FORMAT_PEM,
+ "recipient certificate file")) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (operation == SMIME_DECRYPT) {
+ if (keyfile == NULL)
+ keyfile = recipfile;
+ } else if (operation == SMIME_SIGN) {
+ if (keyfile == NULL)
+ keyfile = signerfile;
+ } else {
+ keyfile = NULL;
+ }
+
+ if (keyfile != NULL) {
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ if (key == NULL)
+ goto end;
+ }
+
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+
+ if (operation & SMIME_IP) {
+ if (informat == FORMAT_SMIME) {
+ p7 = SMIME_read_PKCS7(in, &indata);
+ } else if (informat == FORMAT_PEM) {
+ p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+ } else if (informat == FORMAT_ASN1) {
+ p7 = d2i_PKCS7_bio(in, NULL);
+ } else {
+ BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
+ goto end;
+ }
+
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "Error reading S/MIME message\n");
+ goto end;
+ }
+ if (contfile != NULL) {
+ BIO_free(indata);
+ if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
+ BIO_printf(bio_err, "Can't read content file %s\n", contfile);
+ goto end;
+ }
+ }
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (operation == SMIME_VERIFY) {
+ if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ goto end;
+ X509_STORE_set_verify_cb(store, smime_cb);
+ if (vpmtouched)
+ X509_STORE_set1_param(store, vpm);
+ }
+
+ ret = 3;
+
+ if (operation == SMIME_ENCRYPT) {
+ if (indef)
+ flags |= PKCS7_STREAM;
+ p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+ } else if (operation & SMIME_SIGNERS) {
+ int i;
+ /*
+ * If detached data content we only enable streaming if S/MIME output
+ * format.
+ */
+ if (operation == SMIME_SIGN) {
+ if (flags & PKCS7_DETACHED) {
+ if (outformat == FORMAT_SMIME)
+ flags |= PKCS7_STREAM;
+ } else if (indef) {
+ flags |= PKCS7_STREAM;
+ }
+ flags |= PKCS7_PARTIAL;
+ p7 = PKCS7_sign(NULL, NULL, other, in, flags);
+ if (p7 == NULL)
+ goto end;
+ if (flags & PKCS7_NOCERTS) {
+ for (i = 0; i < sk_X509_num(other); i++) {
+ X509 *x = sk_X509_value(other, i);
+ PKCS7_add_certificate(p7, x);
+ }
+ }
+ } else {
+ flags |= PKCS7_REUSE_DIGEST;
+ }
+ for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
+ signerfile = sk_OPENSSL_STRING_value(sksigners, i);
+ keyfile = sk_OPENSSL_STRING_value(skkeys, i);
+ signer = load_cert(signerfile, FORMAT_PEM,
+ "signer certificate");
+ if (signer == NULL)
+ goto end;
+ key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
+ if (key == NULL)
+ goto end;
+ if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
+ goto end;
+ X509_free(signer);
+ signer = NULL;
+ EVP_PKEY_free(key);
+ key = NULL;
+ }
+ /* If not streaming or resigning finalize structure */
+ if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
+ if (!PKCS7_final(p7, in, flags))
+ goto end;
+ }
+ }
+
+ if (p7 == NULL) {
+ BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
+ goto end;
+ }
+
+ ret = 4;
+ if (operation == SMIME_DECRYPT) {
+ if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
+ BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
+ goto end;
+ }
+ } else if (operation == SMIME_VERIFY) {
+ STACK_OF(X509) *signers;
+ if (PKCS7_verify(p7, other, store, indata, out, flags))
+ BIO_printf(bio_err, "Verification successful\n");
+ else {
+ BIO_printf(bio_err, "Verification failure\n");
+ goto end;
+ }
+ signers = PKCS7_get0_signers(p7, other, flags);
+ if (!save_certs(signerfile, signers)) {
+ BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
+ ret = 5;
+ goto end;
+ }
+ sk_X509_free(signers);
+ } else if (operation == SMIME_PK7OUT) {
+ PEM_write_bio_PKCS7(out, p7);
+ } else {
+ if (to)
+ BIO_printf(out, "To: %s%s", to, mime_eol);
+ if (from)
+ BIO_printf(out, "From: %s%s", from, mime_eol);
+ if (subject)
+ BIO_printf(out, "Subject: %s%s", subject, mime_eol);
+ if (outformat == FORMAT_SMIME) {
+ if (operation == SMIME_RESIGN)
+ rv = SMIME_write_PKCS7(out, p7, indata, flags);
+ else
+ rv = SMIME_write_PKCS7(out, p7, in, flags);
+ } else if (outformat == FORMAT_PEM) {
+ rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags);
+ } else if (outformat == FORMAT_ASN1) {
+ rv = i2d_PKCS7_bio_stream(out, p7, in, flags);
+ } else {
+ BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
+ goto end;
+ }
+ if (rv == 0) {
+ BIO_printf(bio_err, "Error writing output\n");
+ ret = 3;
+ goto end;
+ }
+ }
+ ret = 0;
+ end:
+ if (ret)
+ ERR_print_errors(bio_err);
+ sk_X509_pop_free(encerts, X509_free);
+ sk_X509_pop_free(other, X509_free);
+ X509_VERIFY_PARAM_free(vpm);
+ sk_OPENSSL_STRING_free(sksigners);
+ sk_OPENSSL_STRING_free(skkeys);
+ X509_STORE_free(store);
+ X509_free(cert);
+ X509_free(recip);
+ X509_free(signer);
+ EVP_PKEY_free(key);
+ PKCS7_free(p7);
+ release_engine(e);
+ BIO_free(in);
+ BIO_free(indata);
+ BIO_free_all(out);
+ OPENSSL_free(passin);
+ return ret;
+}
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers)
+{
+ int i;
+ BIO *tmp;
+
+ if (signerfile == NULL)
+ return 1;
+ tmp = BIO_new_file(signerfile, "w");
+ if (tmp == NULL)
+ return 0;
+ for (i = 0; i < sk_X509_num(signers); i++)
+ PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
+ BIO_free(tmp);
+ return 1;
+}
+
+/* Minimal callback just to output policy info (if any) */
+
+static int smime_cb(int ok, X509_STORE_CTX *ctx)
+{
+ int error;
+
+ error = X509_STORE_CTX_get_error(ctx);
+
+ if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
+ && ((error != X509_V_OK) || (ok != 2)))
+ return ok;
+
+ policies_print(ctx);
+
+ return ok;
+}
diff --git a/freebsd/crypto/openssl/apps/speed.c b/freebsd/crypto/openssl/apps/speed.c
new file mode 100644
index 00000000..10cabd0e
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/speed.c
@@ -0,0 +1,3693 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#undef SECONDS
+#define SECONDS 3
+#define RSA_SECONDS 10
+#define DSA_SECONDS 10
+#define ECDSA_SECONDS 10
+#define ECDH_SECONDS 10
+#define EdDSA_SECONDS 10
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/async.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+# include OPENSSL_UNISTD
+#endif
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DES
+# include <openssl/des.h>
+#endif
+#include <openssl/aes.h>
+#ifndef OPENSSL_NO_CAMELLIA
+# include <openssl/camellia.h>
+#endif
+#ifndef OPENSSL_NO_MD2
+# include <openssl/md2.h>
+#endif
+#ifndef OPENSSL_NO_MDC2
+# include <openssl/mdc2.h>
+#endif
+#ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
+#endif
+#ifndef OPENSSL_NO_MD5
+# include <openssl/md5.h>
+#endif
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#ifndef OPENSSL_NO_RMD160
+# include <openssl/ripemd.h>
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+# include <openssl/whrlpool.h>
+#endif
+#ifndef OPENSSL_NO_RC4
+# include <openssl/rc4.h>
+#endif
+#ifndef OPENSSL_NO_RC5
+# include <openssl/rc5.h>
+#endif
+#ifndef OPENSSL_NO_RC2
+# include <openssl/rc2.h>
+#endif
+#ifndef OPENSSL_NO_IDEA
+# include <openssl/idea.h>
+#endif
+#ifndef OPENSSL_NO_SEED
+# include <openssl/seed.h>
+#endif
+#ifndef OPENSSL_NO_BF
+# include <openssl/blowfish.h>
+#endif
+#ifndef OPENSSL_NO_CAST
+# include <openssl/cast.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+# include "./testrsa.h"
+#endif
+#include <openssl/x509.h>
+#ifndef OPENSSL_NO_DSA
+# include <openssl/dsa.h>
+# include "./testdsa.h"
+#endif
+#ifndef OPENSSL_NO_EC
+# include <openssl/ec.h>
+#endif
+#include <openssl/modes.h>
+
+#ifndef HAVE_FORK
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
+# define HAVE_FORK 0
+# else
+# define HAVE_FORK 1
+# endif
+#endif
+
+#if HAVE_FORK
+# undef NO_FORK
+#else
+# define NO_FORK
+#endif
+
+#define MAX_MISALIGNMENT 63
+#define MAX_ECDH_SIZE 256
+#define MISALIGN 64
+
+typedef struct openssl_speed_sec_st {
+ int sym;
+ int rsa;
+ int dsa;
+ int ecdsa;
+ int ecdh;
+ int eddsa;
+} openssl_speed_sec_t;
+
+static volatile int run = 0;
+
+static int mr = 0;
+static int usertime = 1;
+
+#ifndef OPENSSL_NO_MD2
+static int EVP_Digest_MD2_loop(void *args);
+#endif
+
+#ifndef OPENSSL_NO_MDC2
+static int EVP_Digest_MDC2_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_MD4
+static int EVP_Digest_MD4_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_MD5
+static int MD5_loop(void *args);
+static int HMAC_loop(void *args);
+#endif
+static int SHA1_loop(void *args);
+static int SHA256_loop(void *args);
+static int SHA512_loop(void *args);
+#ifndef OPENSSL_NO_WHIRLPOOL
+static int WHIRLPOOL_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_RMD160
+static int EVP_Digest_RMD160_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_RC4
+static int RC4_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_DES
+static int DES_ncbc_encrypt_loop(void *args);
+static int DES_ede3_cbc_encrypt_loop(void *args);
+#endif
+static int AES_cbc_128_encrypt_loop(void *args);
+static int AES_cbc_192_encrypt_loop(void *args);
+static int AES_ige_128_encrypt_loop(void *args);
+static int AES_cbc_256_encrypt_loop(void *args);
+static int AES_ige_192_encrypt_loop(void *args);
+static int AES_ige_256_encrypt_loop(void *args);
+static int CRYPTO_gcm128_aad_loop(void *args);
+static int RAND_bytes_loop(void *args);
+static int EVP_Update_loop(void *args);
+static int EVP_Update_loop_ccm(void *args);
+static int EVP_Update_loop_aead(void *args);
+static int EVP_Digest_loop(void *args);
+#ifndef OPENSSL_NO_RSA
+static int RSA_sign_loop(void *args);
+static int RSA_verify_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_DSA
+static int DSA_sign_loop(void *args);
+static int DSA_verify_loop(void *args);
+#endif
+#ifndef OPENSSL_NO_EC
+static int ECDSA_sign_loop(void *args);
+static int ECDSA_verify_loop(void *args);
+static int EdDSA_sign_loop(void *args);
+static int EdDSA_verify_loop(void *args);
+#endif
+
+static double Time_F(int s);
+static void print_message(const char *s, long num, int length, int tm);
+static void pkey_print_message(const char *str, const char *str2,
+ long num, unsigned int bits, int sec);
+static void print_result(int alg, int run_no, int count, double time_used);
+#ifndef NO_FORK
+static int do_multi(int multi, int size_num);
+#endif
+
+static const int lengths_list[] = {
+ 16, 64, 256, 1024, 8 * 1024, 16 * 1024
+};
+static const int *lengths = lengths_list;
+
+static const int aead_lengths_list[] = {
+ 2, 31, 136, 1024, 8 * 1024, 16 * 1024
+};
+
+#define START 0
+#define STOP 1
+
+#ifdef SIGALRM
+
+static void alarmed(int sig)
+{
+ signal(SIGALRM, alarmed);
+ run = 0;
+}
+
+static double Time_F(int s)
+{
+ double ret = app_tminterval(s, usertime);
+ if (s == STOP)
+ alarm(0);
+ return ret;
+}
+
+#elif defined(_WIN32)
+
+# define SIGALRM -1
+
+static unsigned int lapse;
+static volatile unsigned int schlock;
+static void alarm_win32(unsigned int secs)
+{
+ lapse = secs * 1000;
+}
+
+# define alarm alarm_win32
+
+static DWORD WINAPI sleepy(VOID * arg)
+{
+ schlock = 1;
+ Sleep(lapse);
+ run = 0;
+ return 0;
+}
+
+static double Time_F(int s)
+{
+ double ret;
+ static HANDLE thr;
+
+ if (s == START) {
+ schlock = 0;
+ thr = CreateThread(NULL, 4096, sleepy, NULL, 0, NULL);
+ if (thr == NULL) {
+ DWORD err = GetLastError();
+ BIO_printf(bio_err, "unable to CreateThread (%lu)", err);
+ ExitProcess(err);
+ }
+ while (!schlock)
+ Sleep(0); /* scheduler spinlock */
+ ret = app_tminterval(s, usertime);
+ } else {
+ ret = app_tminterval(s, usertime);
+ if (run)
+ TerminateThread(thr, 0);
+ CloseHandle(thr);
+ }
+
+ return ret;
+}
+#else
+static double Time_F(int s)
+{
+ return app_tminterval(s, usertime);
+}
+#endif
+
+static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
+ const openssl_speed_sec_t *seconds);
+
+#define found(value, pairs, result)\
+ opt_found(value, result, pairs, OSSL_NELEM(pairs))
+static int opt_found(const char *name, unsigned int *result,
+ const OPT_PAIR pairs[], unsigned int nbelem)
+{
+ unsigned int idx;
+
+ for (idx = 0; idx < nbelem; ++idx, pairs++)
+ if (strcmp(name, pairs->name) == 0) {
+ *result = pairs->retval;
+ return 1;
+ }
+ return 0;
+}
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
+ OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
+ OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD
+} OPTION_CHOICE;
+
+const OPTIONS speed_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
+ {"decrypt", OPT_DECRYPT, '-',
+ "Time decryption instead of encryption (only EVP)"},
+ {"aead", OPT_AEAD, '-',
+ "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
+ {"mb", OPT_MB, '-',
+ "Enable (tls1>=1) multi-block mode on EVP-named cipher"},
+ {"mr", OPT_MR, '-', "Produce machine readable output"},
+#ifndef NO_FORK
+ {"multi", OPT_MULTI, 'p', "Run benchmarks in parallel"},
+#endif
+#ifndef OPENSSL_NO_ASYNC
+ {"async_jobs", OPT_ASYNCJOBS, 'p',
+ "Enable async mode and start specified number of jobs"},
+#endif
+ OPT_R_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"elapsed", OPT_ELAPSED, '-',
+ "Use wall-clock time instead of CPU user time as divisor"},
+ {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
+ {"seconds", OPT_SECONDS, 'p',
+ "Run benchmarks for specified amount of seconds"},
+ {"bytes", OPT_BYTES, 'p',
+ "Run [non-PKI] benchmarks on custom-sized buffer"},
+ {"misalign", OPT_MISALIGN, 'p',
+ "Use specified offset to mis-align buffers"},
+ {NULL}
+};
+
+#define D_MD2 0
+#define D_MDC2 1
+#define D_MD4 2
+#define D_MD5 3
+#define D_HMAC 4
+#define D_SHA1 5
+#define D_RMD160 6
+#define D_RC4 7
+#define D_CBC_DES 8
+#define D_EDE3_DES 9
+#define D_CBC_IDEA 10
+#define D_CBC_SEED 11
+#define D_CBC_RC2 12
+#define D_CBC_RC5 13
+#define D_CBC_BF 14
+#define D_CBC_CAST 15
+#define D_CBC_128_AES 16
+#define D_CBC_192_AES 17
+#define D_CBC_256_AES 18
+#define D_CBC_128_CML 19
+#define D_CBC_192_CML 20
+#define D_CBC_256_CML 21
+#define D_EVP 22
+#define D_SHA256 23
+#define D_SHA512 24
+#define D_WHIRLPOOL 25
+#define D_IGE_128_AES 26
+#define D_IGE_192_AES 27
+#define D_IGE_256_AES 28
+#define D_GHASH 29
+#define D_RAND 30
+/* name of algorithms to test */
+static const char *names[] = {
+ "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4",
+ "des cbc", "des ede3", "idea cbc", "seed cbc",
+ "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
+ "aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
+ "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
+ "evp", "sha256", "sha512", "whirlpool",
+ "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
+ "rand"
+};
+#define ALGOR_NUM OSSL_NELEM(names)
+
+/* list of configured algorithm (remaining) */
+static const OPT_PAIR doit_choices[] = {
+#ifndef OPENSSL_NO_MD2
+ {"md2", D_MD2},
+#endif
+#ifndef OPENSSL_NO_MDC2
+ {"mdc2", D_MDC2},
+#endif
+#ifndef OPENSSL_NO_MD4
+ {"md4", D_MD4},
+#endif
+#ifndef OPENSSL_NO_MD5
+ {"md5", D_MD5},
+ {"hmac", D_HMAC},
+#endif
+ {"sha1", D_SHA1},
+ {"sha256", D_SHA256},
+ {"sha512", D_SHA512},
+#ifndef OPENSSL_NO_WHIRLPOOL
+ {"whirlpool", D_WHIRLPOOL},
+#endif
+#ifndef OPENSSL_NO_RMD160
+ {"ripemd", D_RMD160},
+ {"rmd160", D_RMD160},
+ {"ripemd160", D_RMD160},
+#endif
+#ifndef OPENSSL_NO_RC4
+ {"rc4", D_RC4},
+#endif
+#ifndef OPENSSL_NO_DES
+ {"des-cbc", D_CBC_DES},
+ {"des-ede3", D_EDE3_DES},
+#endif
+ {"aes-128-cbc", D_CBC_128_AES},
+ {"aes-192-cbc", D_CBC_192_AES},
+ {"aes-256-cbc", D_CBC_256_AES},
+ {"aes-128-ige", D_IGE_128_AES},
+ {"aes-192-ige", D_IGE_192_AES},
+ {"aes-256-ige", D_IGE_256_AES},
+#ifndef OPENSSL_NO_RC2
+ {"rc2-cbc", D_CBC_RC2},
+ {"rc2", D_CBC_RC2},
+#endif
+#ifndef OPENSSL_NO_RC5
+ {"rc5-cbc", D_CBC_RC5},
+ {"rc5", D_CBC_RC5},
+#endif
+#ifndef OPENSSL_NO_IDEA
+ {"idea-cbc", D_CBC_IDEA},
+ {"idea", D_CBC_IDEA},
+#endif
+#ifndef OPENSSL_NO_SEED
+ {"seed-cbc", D_CBC_SEED},
+ {"seed", D_CBC_SEED},
+#endif
+#ifndef OPENSSL_NO_BF
+ {"bf-cbc", D_CBC_BF},
+ {"blowfish", D_CBC_BF},
+ {"bf", D_CBC_BF},
+#endif
+#ifndef OPENSSL_NO_CAST
+ {"cast-cbc", D_CBC_CAST},
+ {"cast", D_CBC_CAST},
+ {"cast5", D_CBC_CAST},
+#endif
+ {"ghash", D_GHASH},
+ {"rand", D_RAND}
+};
+
+static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+
+#ifndef OPENSSL_NO_DSA
+# define R_DSA_512 0
+# define R_DSA_1024 1
+# define R_DSA_2048 2
+static const OPT_PAIR dsa_choices[] = {
+ {"dsa512", R_DSA_512},
+ {"dsa1024", R_DSA_1024},
+ {"dsa2048", R_DSA_2048}
+};
+# define DSA_NUM OSSL_NELEM(dsa_choices)
+
+static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_DSA */
+
+#define R_RSA_512 0
+#define R_RSA_1024 1
+#define R_RSA_2048 2
+#define R_RSA_3072 3
+#define R_RSA_4096 4
+#define R_RSA_7680 5
+#define R_RSA_15360 6
+#ifndef OPENSSL_NO_RSA
+static const OPT_PAIR rsa_choices[] = {
+ {"rsa512", R_RSA_512},
+ {"rsa1024", R_RSA_1024},
+ {"rsa2048", R_RSA_2048},
+ {"rsa3072", R_RSA_3072},
+ {"rsa4096", R_RSA_4096},
+ {"rsa7680", R_RSA_7680},
+ {"rsa15360", R_RSA_15360}
+};
+# define RSA_NUM OSSL_NELEM(rsa_choices)
+
+static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_RSA */
+
+#define R_EC_P160 0
+#define R_EC_P192 1
+#define R_EC_P224 2
+#define R_EC_P256 3
+#define R_EC_P384 4
+#define R_EC_P521 5
+#define R_EC_K163 6
+#define R_EC_K233 7
+#define R_EC_K283 8
+#define R_EC_K409 9
+#define R_EC_K571 10
+#define R_EC_B163 11
+#define R_EC_B233 12
+#define R_EC_B283 13
+#define R_EC_B409 14
+#define R_EC_B571 15
+#define R_EC_BRP256R1 16
+#define R_EC_BRP256T1 17
+#define R_EC_BRP384R1 18
+#define R_EC_BRP384T1 19
+#define R_EC_BRP512R1 20
+#define R_EC_BRP512T1 21
+#define R_EC_X25519 22
+#define R_EC_X448 23
+#ifndef OPENSSL_NO_EC
+static OPT_PAIR ecdsa_choices[] = {
+ {"ecdsap160", R_EC_P160},
+ {"ecdsap192", R_EC_P192},
+ {"ecdsap224", R_EC_P224},
+ {"ecdsap256", R_EC_P256},
+ {"ecdsap384", R_EC_P384},
+ {"ecdsap521", R_EC_P521},
+ {"ecdsak163", R_EC_K163},
+ {"ecdsak233", R_EC_K233},
+ {"ecdsak283", R_EC_K283},
+ {"ecdsak409", R_EC_K409},
+ {"ecdsak571", R_EC_K571},
+ {"ecdsab163", R_EC_B163},
+ {"ecdsab233", R_EC_B233},
+ {"ecdsab283", R_EC_B283},
+ {"ecdsab409", R_EC_B409},
+ {"ecdsab571", R_EC_B571},
+ {"ecdsabrp256r1", R_EC_BRP256R1},
+ {"ecdsabrp256t1", R_EC_BRP256T1},
+ {"ecdsabrp384r1", R_EC_BRP384R1},
+ {"ecdsabrp384t1", R_EC_BRP384T1},
+ {"ecdsabrp512r1", R_EC_BRP512R1},
+ {"ecdsabrp512t1", R_EC_BRP512T1}
+};
+# define ECDSA_NUM OSSL_NELEM(ecdsa_choices)
+
+static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
+
+static const OPT_PAIR ecdh_choices[] = {
+ {"ecdhp160", R_EC_P160},
+ {"ecdhp192", R_EC_P192},
+ {"ecdhp224", R_EC_P224},
+ {"ecdhp256", R_EC_P256},
+ {"ecdhp384", R_EC_P384},
+ {"ecdhp521", R_EC_P521},
+ {"ecdhk163", R_EC_K163},
+ {"ecdhk233", R_EC_K233},
+ {"ecdhk283", R_EC_K283},
+ {"ecdhk409", R_EC_K409},
+ {"ecdhk571", R_EC_K571},
+ {"ecdhb163", R_EC_B163},
+ {"ecdhb233", R_EC_B233},
+ {"ecdhb283", R_EC_B283},
+ {"ecdhb409", R_EC_B409},
+ {"ecdhb571", R_EC_B571},
+ {"ecdhbrp256r1", R_EC_BRP256R1},
+ {"ecdhbrp256t1", R_EC_BRP256T1},
+ {"ecdhbrp384r1", R_EC_BRP384R1},
+ {"ecdhbrp384t1", R_EC_BRP384T1},
+ {"ecdhbrp512r1", R_EC_BRP512R1},
+ {"ecdhbrp512t1", R_EC_BRP512T1},
+ {"ecdhx25519", R_EC_X25519},
+ {"ecdhx448", R_EC_X448}
+};
+# define EC_NUM OSSL_NELEM(ecdh_choices)
+
+static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
+
+#define R_EC_Ed25519 0
+#define R_EC_Ed448 1
+static OPT_PAIR eddsa_choices[] = {
+ {"ed25519", R_EC_Ed25519},
+ {"ed448", R_EC_Ed448}
+};
+# define EdDSA_NUM OSSL_NELEM(eddsa_choices)
+
+static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_EC */
+
+#ifndef SIGALRM
+# define COND(d) (count < (d))
+# define COUNT(d) (d)
+#else
+# define COND(unused_cond) (run && count<0x7fffffff)
+# define COUNT(d) (count)
+#endif /* SIGALRM */
+
+typedef struct loopargs_st {
+ ASYNC_JOB *inprogress_job;
+ ASYNC_WAIT_CTX *wait_ctx;
+ unsigned char *buf;
+ unsigned char *buf2;
+ unsigned char *buf_malloc;
+ unsigned char *buf2_malloc;
+ unsigned char *key;
+ unsigned int siglen;
+ size_t sigsize;
+#ifndef OPENSSL_NO_RSA
+ RSA *rsa_key[RSA_NUM];
+#endif
+#ifndef OPENSSL_NO_DSA
+ DSA *dsa_key[DSA_NUM];
+#endif
+#ifndef OPENSSL_NO_EC
+ EC_KEY *ecdsa[ECDSA_NUM];
+ EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
+ EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
+ unsigned char *secret_a;
+ unsigned char *secret_b;
+ size_t outlen[EC_NUM];
+#endif
+ EVP_CIPHER_CTX *ctx;
+ HMAC_CTX *hctx;
+ GCM128_CONTEXT *gcm_ctx;
+} loopargs_t;
+static int run_benchmark(int async_jobs, int (*loop_function) (void *),
+ loopargs_t * loopargs);
+
+static unsigned int testnum;
+
+/* Nb of iterations to do per algorithm and key-size */
+static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+
+#ifndef OPENSSL_NO_MD2
+static int EVP_Digest_MD2_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char md2[MD2_DIGEST_LENGTH];
+ int count;
+
+ for (count = 0; COND(c[D_MD2][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(),
+ NULL))
+ return -1;
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_MDC2
+static int EVP_Digest_MDC2_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char mdc2[MDC2_DIGEST_LENGTH];
+ int count;
+
+ for (count = 0; COND(c[D_MDC2][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(),
+ NULL))
+ return -1;
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_MD4
+static int EVP_Digest_MD4_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char md4[MD4_DIGEST_LENGTH];
+ int count;
+
+ for (count = 0; COND(c[D_MD4][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(),
+ NULL))
+ return -1;
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_MD5
+static int MD5_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char md5[MD5_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_MD5][testnum]); count++)
+ MD5(buf, lengths[testnum], md5);
+ return count;
+}
+
+static int HMAC_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ HMAC_CTX *hctx = tempargs->hctx;
+ unsigned char hmac[MD5_DIGEST_LENGTH];
+ int count;
+
+ for (count = 0; COND(c[D_HMAC][testnum]); count++) {
+ HMAC_Init_ex(hctx, NULL, 0, NULL, NULL);
+ HMAC_Update(hctx, buf, lengths[testnum]);
+ HMAC_Final(hctx, hmac, NULL);
+ }
+ return count;
+}
+#endif
+
+static int SHA1_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char sha[SHA_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_SHA1][testnum]); count++)
+ SHA1(buf, lengths[testnum], sha);
+ return count;
+}
+
+static int SHA256_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char sha256[SHA256_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_SHA256][testnum]); count++)
+ SHA256(buf, lengths[testnum], sha256);
+ return count;
+}
+
+static int SHA512_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char sha512[SHA512_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_SHA512][testnum]); count++)
+ SHA512(buf, lengths[testnum], sha512);
+ return count;
+}
+
+#ifndef OPENSSL_NO_WHIRLPOOL
+static int WHIRLPOOL_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++)
+ WHIRLPOOL(buf, lengths[testnum], whirlpool);
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_RMD160
+static int EVP_Digest_RMD160_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
+ int count;
+ for (count = 0; COND(c[D_RMD160][testnum]); count++) {
+ if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]),
+ NULL, EVP_ripemd160(), NULL))
+ return -1;
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_RC4
+static RC4_KEY rc4_ks;
+static int RC4_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_RC4][testnum]); count++)
+ RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf);
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_DES
+static unsigned char DES_iv[8];
+static DES_key_schedule sch;
+static DES_key_schedule sch2;
+static DES_key_schedule sch3;
+static int DES_ncbc_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_CBC_DES][testnum]); count++)
+ DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch,
+ &DES_iv, DES_ENCRYPT);
+ return count;
+}
+
+static int DES_ede3_cbc_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_EDE3_DES][testnum]); count++)
+ DES_ede3_cbc_encrypt(buf, buf, lengths[testnum],
+ &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT);
+ return count;
+}
+#endif
+
+#define MAX_BLOCK_SIZE 128
+
+static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
+static AES_KEY aes_ks1, aes_ks2, aes_ks3;
+static int AES_cbc_128_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++)
+ AES_cbc_encrypt(buf, buf,
+ (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int AES_cbc_192_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++)
+ AES_cbc_encrypt(buf, buf,
+ (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int AES_cbc_256_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+ for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++)
+ AES_cbc_encrypt(buf, buf,
+ (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int AES_ige_128_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ int count;
+ for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++)
+ AES_ige_encrypt(buf, buf2,
+ (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int AES_ige_192_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ int count;
+ for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++)
+ AES_ige_encrypt(buf, buf2,
+ (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int AES_ige_256_encrypt_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ int count;
+ for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++)
+ AES_ige_encrypt(buf, buf2,
+ (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
+ return count;
+}
+
+static int CRYPTO_gcm128_aad_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx;
+ int count;
+ for (count = 0; COND(c[D_GHASH][testnum]); count++)
+ CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]);
+ return count;
+}
+
+static int RAND_bytes_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ int count;
+
+ for (count = 0; COND(c[D_RAND][testnum]); count++)
+ RAND_bytes(buf, lengths[testnum]);
+ return count;
+}
+
+static long save_count = 0;
+static int decrypt = 0;
+static int EVP_Update_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_CIPHER_CTX *ctx = tempargs->ctx;
+ int outl, count, rc;
+#ifndef SIGALRM
+ int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+ if (decrypt) {
+ for (count = 0; COND(nb_iter); count++) {
+ rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ if (rc != 1) {
+ /* reset iv in case of counter overflow */
+ EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
+ }
+ }
+ } else {
+ for (count = 0; COND(nb_iter); count++) {
+ rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ if (rc != 1) {
+ /* reset iv in case of counter overflow */
+ EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
+ }
+ }
+ }
+ if (decrypt)
+ EVP_DecryptFinal_ex(ctx, buf, &outl);
+ else
+ EVP_EncryptFinal_ex(ctx, buf, &outl);
+ return count;
+}
+
+/*
+ * CCM does not support streaming. For the purpose of performance measurement,
+ * each message is encrypted using the same (key,iv)-pair. Do not use this
+ * code in your application.
+ */
+static int EVP_Update_loop_ccm(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_CIPHER_CTX *ctx = tempargs->ctx;
+ int outl, count;
+ unsigned char tag[12];
+#ifndef SIGALRM
+ int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+ if (decrypt) {
+ for (count = 0; COND(nb_iter); count++) {
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag);
+ /* reset iv */
+ EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ /* counter is reset on every update */
+ EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ }
+ } else {
+ for (count = 0; COND(nb_iter); count++) {
+ /* restore iv length field */
+ EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
+ /* counter is reset on every update */
+ EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ }
+ }
+ if (decrypt)
+ EVP_DecryptFinal_ex(ctx, buf, &outl);
+ else
+ EVP_EncryptFinal_ex(ctx, buf, &outl);
+ return count;
+}
+
+/*
+ * To make AEAD benchmarking more relevant perform TLS-like operations,
+ * 13-byte AAD followed by payload. But don't use TLS-formatted AAD, as
+ * payload length is not actually limited by 16KB...
+ */
+static int EVP_Update_loop_aead(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_CIPHER_CTX *ctx = tempargs->ctx;
+ int outl, count;
+ unsigned char aad[13] = { 0xcc };
+ unsigned char faketag[16] = { 0xcc };
+#ifndef SIGALRM
+ int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+ if (decrypt) {
+ for (count = 0; COND(nb_iter); count++) {
+ EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ sizeof(faketag), faketag);
+ EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
+ }
+ } else {
+ for (count = 0; COND(nb_iter); count++) {
+ EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
+ EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+ EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+ EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
+ }
+ }
+ return count;
+}
+
+static const EVP_MD *evp_md = NULL;
+static int EVP_Digest_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int count;
+#ifndef SIGALRM
+ int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+
+ for (count = 0; COND(nb_iter); count++) {
+ if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL))
+ return -1;
+ }
+ return count;
+}
+
+#ifndef OPENSSL_NO_RSA
+static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */
+
+static int RSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ unsigned int *rsa_num = &tempargs->siglen;
+ RSA **rsa_key = tempargs->rsa_key;
+ int ret, count;
+ for (count = 0; COND(rsa_c[testnum][0]); count++) {
+ ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "RSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int RSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ unsigned int rsa_num = tempargs->siglen;
+ RSA **rsa_key = tempargs->rsa_key;
+ int ret, count;
+ for (count = 0; COND(rsa_c[testnum][1]); count++) {
+ ret =
+ RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+ if (ret <= 0) {
+ BIO_printf(bio_err, "RSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+static long dsa_c[DSA_NUM][2];
+static int DSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ DSA **dsa_key = tempargs->dsa_key;
+ unsigned int *siglen = &tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(dsa_c[testnum][0]); count++) {
+ ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "DSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int DSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ DSA **dsa_key = tempargs->dsa_key;
+ unsigned int siglen = tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(dsa_c[testnum][1]); count++) {
+ ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ if (ret <= 0) {
+ BIO_printf(bio_err, "DSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+static long ecdsa_c[ECDSA_NUM][2];
+static int ECDSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EC_KEY **ecdsa = tempargs->ecdsa;
+ unsigned char *ecdsasig = tempargs->buf2;
+ unsigned int *ecdsasiglen = &tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
+ ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "ECDSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int ECDSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EC_KEY **ecdsa = tempargs->ecdsa;
+ unsigned char *ecdsasig = tempargs->buf2;
+ unsigned int ecdsasiglen = tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
+ ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
+ if (ret != 1) {
+ BIO_printf(bio_err, "ECDSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+/* ******************************************************************** */
+static long ecdh_c[EC_NUM][1];
+
+static int ECDH_EVP_derive_key_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum];
+ unsigned char *derived_secret = tempargs->secret_a;
+ int count;
+ size_t *outlen = &(tempargs->outlen[testnum]);
+
+ for (count = 0; COND(ecdh_c[testnum][0]); count++)
+ EVP_PKEY_derive(ctx, derived_secret, outlen);
+
+ return count;
+}
+
+static long eddsa_c[EdDSA_NUM][2];
+static int EdDSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
+ unsigned char *eddsasig = tempargs->buf2;
+ size_t *eddsasigsize = &tempargs->sigsize;
+ int ret, count;
+
+ for (count = 0; COND(eddsa_c[testnum][0]); count++) {
+ ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
+ if (ret == 0) {
+ BIO_printf(bio_err, "EdDSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int EdDSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **) args;
+ unsigned char *buf = tempargs->buf;
+ EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
+ unsigned char *eddsasig = tempargs->buf2;
+ size_t eddsasigsize = tempargs->sigsize;
+ int ret, count;
+
+ for (count = 0; COND(eddsa_c[testnum][1]); count++) {
+ ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
+ if (ret != 1) {
+ BIO_printf(bio_err, "EdDSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif /* OPENSSL_NO_EC */
+
+static int run_benchmark(int async_jobs,
+ int (*loop_function) (void *), loopargs_t * loopargs)
+{
+ int job_op_count = 0;
+ int total_op_count = 0;
+ int num_inprogress = 0;
+ int error = 0, i = 0, ret = 0;
+ OSSL_ASYNC_FD job_fd = 0;
+ size_t num_job_fds = 0;
+
+ run = 1;
+
+ if (async_jobs == 0) {
+ return loop_function((void *)&loopargs);
+ }
+
+ for (i = 0; i < async_jobs && !error; i++) {
+ loopargs_t *looparg_item = loopargs + i;
+
+ /* Copy pointer content (looparg_t item address) into async context */
+ ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx,
+ &job_op_count, loop_function,
+ (void *)&looparg_item, sizeof(looparg_item));
+ switch (ret) {
+ case ASYNC_PAUSE:
+ ++num_inprogress;
+ break;
+ case ASYNC_FINISH:
+ if (job_op_count == -1) {
+ error = 1;
+ } else {
+ total_op_count += job_op_count;
+ }
+ break;
+ case ASYNC_NO_JOBS:
+ case ASYNC_ERR:
+ BIO_printf(bio_err, "Failure in the job\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ }
+
+ while (num_inprogress > 0) {
+#if defined(OPENSSL_SYS_WINDOWS)
+ DWORD avail = 0;
+#elif defined(OPENSSL_SYS_UNIX)
+ int select_result = 0;
+ OSSL_ASYNC_FD max_fd = 0;
+ fd_set waitfdset;
+
+ FD_ZERO(&waitfdset);
+
+ for (i = 0; i < async_jobs && num_inprogress > 0; i++) {
+ if (loopargs[i].inprogress_job == NULL)
+ continue;
+
+ if (!ASYNC_WAIT_CTX_get_all_fds
+ (loopargs[i].wait_ctx, NULL, &num_job_fds)
+ || num_job_fds > 1) {
+ BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
+ &num_job_fds);
+ FD_SET(job_fd, &waitfdset);
+ if (job_fd > max_fd)
+ max_fd = job_fd;
+ }
+
+ if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) {
+ BIO_printf(bio_err,
+ "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). "
+ "Decrease the value of async_jobs\n",
+ max_fd, FD_SETSIZE);
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+
+ select_result = select(max_fd + 1, &waitfdset, NULL, NULL, NULL);
+ if (select_result == -1 && errno == EINTR)
+ continue;
+
+ if (select_result == -1) {
+ BIO_printf(bio_err, "Failure in the select\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+
+ if (select_result == 0)
+ continue;
+#endif
+
+ for (i = 0; i < async_jobs; i++) {
+ if (loopargs[i].inprogress_job == NULL)
+ continue;
+
+ if (!ASYNC_WAIT_CTX_get_all_fds
+ (loopargs[i].wait_ctx, NULL, &num_job_fds)
+ || num_job_fds > 1) {
+ BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
+ &num_job_fds);
+
+#if defined(OPENSSL_SYS_UNIX)
+ if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset))
+ continue;
+#elif defined(OPENSSL_SYS_WINDOWS)
+ if (num_job_fds == 1
+ && !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL)
+ && avail > 0)
+ continue;
+#endif
+
+ ret = ASYNC_start_job(&loopargs[i].inprogress_job,
+ loopargs[i].wait_ctx, &job_op_count,
+ loop_function, (void *)(loopargs + i),
+ sizeof(loopargs_t));
+ switch (ret) {
+ case ASYNC_PAUSE:
+ break;
+ case ASYNC_FINISH:
+ if (job_op_count == -1) {
+ error = 1;
+ } else {
+ total_op_count += job_op_count;
+ }
+ --num_inprogress;
+ loopargs[i].inprogress_job = NULL;
+ break;
+ case ASYNC_NO_JOBS:
+ case ASYNC_ERR:
+ --num_inprogress;
+ loopargs[i].inprogress_job = NULL;
+ BIO_printf(bio_err, "Failure in the job\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ }
+ }
+
+ return error ? -1 : total_op_count;
+}
+
+int speed_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ loopargs_t *loopargs = NULL;
+ const char *prog;
+ const char *engine_id = NULL;
+ const EVP_CIPHER *evp_cipher = NULL;
+ double d = 0.0;
+ OPTION_CHOICE o;
+ int async_init = 0, multiblock = 0, pr_header = 0;
+ int doit[ALGOR_NUM] = { 0 };
+ int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
+ long count = 0;
+ unsigned int size_num = OSSL_NELEM(lengths_list);
+ unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0;
+ int keylen;
+ int buflen;
+#ifndef NO_FORK
+ int multi = 0;
+#endif
+#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
+ || !defined(OPENSSL_NO_EC)
+ long rsa_count = 1;
+#endif
+ openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
+ ECDSA_SECONDS, ECDH_SECONDS,
+ EdDSA_SECONDS };
+
+ /* What follows are the buffers and key material. */
+#ifndef OPENSSL_NO_RC5
+ RC5_32_KEY rc5_ks;
+#endif
+#ifndef OPENSSL_NO_RC2
+ RC2_KEY rc2_ks;
+#endif
+#ifndef OPENSSL_NO_IDEA
+ IDEA_KEY_SCHEDULE idea_ks;
+#endif
+#ifndef OPENSSL_NO_SEED
+ SEED_KEY_SCHEDULE seed_ks;
+#endif
+#ifndef OPENSSL_NO_BF
+ BF_KEY bf_ks;
+#endif
+#ifndef OPENSSL_NO_CAST
+ CAST_KEY cast_ks;
+#endif
+ static const unsigned char key16[16] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
+ };
+ static const unsigned char key24[24] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
+ };
+ static const unsigned char key32[32] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
+ 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
+ };
+#ifndef OPENSSL_NO_CAMELLIA
+ static const unsigned char ckey24[24] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
+ };
+ static const unsigned char ckey32[32] = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
+ 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
+ };
+ CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
+#endif
+#ifndef OPENSSL_NO_DES
+ static DES_cblock key = {
+ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
+ };
+ static DES_cblock key2 = {
+ 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
+ };
+ static DES_cblock key3 = {
+ 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
+ };
+#endif
+#ifndef OPENSSL_NO_RSA
+ static const unsigned int rsa_bits[RSA_NUM] = {
+ 512, 1024, 2048, 3072, 4096, 7680, 15360
+ };
+ static const unsigned char *rsa_data[RSA_NUM] = {
+ test512, test1024, test2048, test3072, test4096, test7680, test15360
+ };
+ static const int rsa_data_length[RSA_NUM] = {
+ sizeof(test512), sizeof(test1024),
+ sizeof(test2048), sizeof(test3072),
+ sizeof(test4096), sizeof(test7680),
+ sizeof(test15360)
+ };
+ int rsa_doit[RSA_NUM] = { 0 };
+ int primes = RSA_DEFAULT_PRIME_NUM;
+#endif
+#ifndef OPENSSL_NO_DSA
+ static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
+ int dsa_doit[DSA_NUM] = { 0 };
+#endif
+#ifndef OPENSSL_NO_EC
+ /*
+ * We only test over the following curves as they are representative, To
+ * add tests over more curves, simply add the curve NID and curve name to
+ * the following arrays and increase the |ecdh_choices| list accordingly.
+ */
+ static const struct {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ } test_curves[] = {
+ /* Prime Curves */
+ {"secp160r1", NID_secp160r1, 160},
+ {"nistp192", NID_X9_62_prime192v1, 192},
+ {"nistp224", NID_secp224r1, 224},
+ {"nistp256", NID_X9_62_prime256v1, 256},
+ {"nistp384", NID_secp384r1, 384},
+ {"nistp521", NID_secp521r1, 521},
+ /* Binary Curves */
+ {"nistk163", NID_sect163k1, 163},
+ {"nistk233", NID_sect233k1, 233},
+ {"nistk283", NID_sect283k1, 283},
+ {"nistk409", NID_sect409k1, 409},
+ {"nistk571", NID_sect571k1, 571},
+ {"nistb163", NID_sect163r2, 163},
+ {"nistb233", NID_sect233r1, 233},
+ {"nistb283", NID_sect283r1, 283},
+ {"nistb409", NID_sect409r1, 409},
+ {"nistb571", NID_sect571r1, 571},
+ {"brainpoolP256r1", NID_brainpoolP256r1, 256},
+ {"brainpoolP256t1", NID_brainpoolP256t1, 256},
+ {"brainpoolP384r1", NID_brainpoolP384r1, 384},
+ {"brainpoolP384t1", NID_brainpoolP384t1, 384},
+ {"brainpoolP512r1", NID_brainpoolP512r1, 512},
+ {"brainpoolP512t1", NID_brainpoolP512t1, 512},
+ /* Other and ECDH only ones */
+ {"X25519", NID_X25519, 253},
+ {"X448", NID_X448, 448}
+ };
+ static const struct {
+ const char *name;
+ unsigned int nid;
+ unsigned int bits;
+ size_t sigsize;
+ } test_ed_curves[] = {
+ /* EdDSA */
+ {"Ed25519", NID_ED25519, 253, 64},
+ {"Ed448", NID_ED448, 456, 114}
+ };
+ int ecdsa_doit[ECDSA_NUM] = { 0 };
+ int ecdh_doit[EC_NUM] = { 0 };
+ int eddsa_doit[EdDSA_NUM] = { 0 };
+ OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM);
+ OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM);
+#endif /* ndef OPENSSL_NO_EC */
+
+ prog = opt_init(argc, argv, speed_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opterr:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(speed_options);
+ ret = 0;
+ goto end;
+ case OPT_ELAPSED:
+ usertime = 0;
+ break;
+ case OPT_EVP:
+ evp_md = NULL;
+ evp_cipher = EVP_get_cipherbyname(opt_arg());
+ if (evp_cipher == NULL)
+ evp_md = EVP_get_digestbyname(opt_arg());
+ if (evp_cipher == NULL && evp_md == NULL) {
+ BIO_printf(bio_err,
+ "%s: %s is an unknown cipher or digest\n",
+ prog, opt_arg());
+ goto end;
+ }
+ doit[D_EVP] = 1;
+ break;
+ case OPT_DECRYPT:
+ decrypt = 1;
+ break;
+ case OPT_ENGINE:
+ /*
+ * In a forked execution, an engine might need to be
+ * initialised by each child process, not by the parent.
+ * So store the name here and run setup_engine() later on.
+ */
+ engine_id = opt_arg();
+ break;
+ case OPT_MULTI:
+#ifndef NO_FORK
+ multi = atoi(opt_arg());
+#endif
+ break;
+ case OPT_ASYNCJOBS:
+#ifndef OPENSSL_NO_ASYNC
+ async_jobs = atoi(opt_arg());
+ if (!ASYNC_is_capable()) {
+ BIO_printf(bio_err,
+ "%s: async_jobs specified but async not supported\n",
+ prog);
+ goto opterr;
+ }
+ if (async_jobs > 99999) {
+ BIO_printf(bio_err, "%s: too many async_jobs\n", prog);
+ goto opterr;
+ }
+#endif
+ break;
+ case OPT_MISALIGN:
+ if (!opt_int(opt_arg(), &misalign))
+ goto end;
+ if (misalign > MISALIGN) {
+ BIO_printf(bio_err,
+ "%s: Maximum offset is %d\n", prog, MISALIGN);
+ goto opterr;
+ }
+ break;
+ case OPT_MR:
+ mr = 1;
+ break;
+ case OPT_MB:
+ multiblock = 1;
+#ifdef OPENSSL_NO_MULTIBLOCK
+ BIO_printf(bio_err,
+ "%s: -mb specified but multi-block support is disabled\n",
+ prog);
+ goto end;
+#endif
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_PRIMES:
+ if (!opt_int(opt_arg(), &primes))
+ goto end;
+ break;
+ case OPT_SECONDS:
+ seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
+ = seconds.ecdh = seconds.eddsa = atoi(opt_arg());
+ break;
+ case OPT_BYTES:
+ lengths_single = atoi(opt_arg());
+ lengths = &lengths_single;
+ size_num = 1;
+ break;
+ case OPT_AEAD:
+ aead = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ /* Remaining arguments are algorithms. */
+ for (; *argv; argv++) {
+ if (found(*argv, doit_choices, &i)) {
+ doit[i] = 1;
+ continue;
+ }
+#ifndef OPENSSL_NO_DES
+ if (strcmp(*argv, "des") == 0) {
+ doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
+ continue;
+ }
+#endif
+ if (strcmp(*argv, "sha") == 0) {
+ doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1;
+ continue;
+ }
+#ifndef OPENSSL_NO_RSA
+ if (strcmp(*argv, "openssl") == 0)
+ continue;
+ if (strcmp(*argv, "rsa") == 0) {
+ for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++)
+ rsa_doit[loop] = 1;
+ continue;
+ }
+ if (found(*argv, rsa_choices, &i)) {
+ rsa_doit[i] = 1;
+ continue;
+ }
+#endif
+#ifndef OPENSSL_NO_DSA
+ if (strcmp(*argv, "dsa") == 0) {
+ dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] =
+ dsa_doit[R_DSA_2048] = 1;
+ continue;
+ }
+ if (found(*argv, dsa_choices, &i)) {
+ dsa_doit[i] = 2;
+ continue;
+ }
+#endif
+ if (strcmp(*argv, "aes") == 0) {
+ doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
+ continue;
+ }
+#ifndef OPENSSL_NO_CAMELLIA
+ if (strcmp(*argv, "camellia") == 0) {
+ doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
+ continue;
+ }
+#endif
+#ifndef OPENSSL_NO_EC
+ if (strcmp(*argv, "ecdsa") == 0) {
+ for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
+ ecdsa_doit[loop] = 1;
+ continue;
+ }
+ if (found(*argv, ecdsa_choices, &i)) {
+ ecdsa_doit[i] = 2;
+ continue;
+ }
+ if (strcmp(*argv, "ecdh") == 0) {
+ for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
+ ecdh_doit[loop] = 1;
+ continue;
+ }
+ if (found(*argv, ecdh_choices, &i)) {
+ ecdh_doit[i] = 2;
+ continue;
+ }
+ if (strcmp(*argv, "eddsa") == 0) {
+ for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
+ eddsa_doit[loop] = 1;
+ continue;
+ }
+ if (found(*argv, eddsa_choices, &i)) {
+ eddsa_doit[i] = 2;
+ continue;
+ }
+#endif
+ BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv);
+ goto end;
+ }
+
+ /* Sanity checks */
+ if (aead) {
+ if (evp_cipher == NULL) {
+ BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n");
+ goto end;
+ } else if (!(EVP_CIPHER_flags(evp_cipher) &
+ EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ BIO_printf(bio_err, "%s is not an AEAD cipher\n",
+ OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+ goto end;
+ }
+ }
+ if (multiblock) {
+ if (evp_cipher == NULL) {
+ BIO_printf(bio_err,"-mb can be used only with a multi-block"
+ " capable cipher\n");
+ goto end;
+ } else if (!(EVP_CIPHER_flags(evp_cipher) &
+ EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+ BIO_printf(bio_err, "%s is not a multi-block capable\n",
+ OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+ goto end;
+ } else if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with -mb");
+ goto end;
+ }
+ }
+
+ /* Initialize the job pool if async mode is enabled */
+ if (async_jobs > 0) {
+ async_init = ASYNC_init_thread(async_jobs, async_jobs);
+ if (!async_init) {
+ BIO_printf(bio_err, "Error creating the ASYNC job pool\n");
+ goto end;
+ }
+ }
+
+ loopargs_len = (async_jobs == 0 ? 1 : async_jobs);
+ loopargs =
+ app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs");
+ memset(loopargs, 0, loopargs_len * sizeof(loopargs_t));
+
+ for (i = 0; i < loopargs_len; i++) {
+ if (async_jobs > 0) {
+ loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new();
+ if (loopargs[i].wait_ctx == NULL) {
+ BIO_printf(bio_err, "Error creating the ASYNC_WAIT_CTX\n");
+ goto end;
+ }
+ }
+
+ buflen = lengths[size_num - 1];
+ if (buflen < 36) /* size of random vector in RSA bencmark */
+ buflen = 36;
+ buflen += MAX_MISALIGNMENT + 1;
+ loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
+ loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
+ memset(loopargs[i].buf_malloc, 0, buflen);
+ memset(loopargs[i].buf2_malloc, 0, buflen);
+
+ /* Align the start of buffers on a 64 byte boundary */
+ loopargs[i].buf = loopargs[i].buf_malloc + misalign;
+ loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign;
+#ifndef OPENSSL_NO_EC
+ loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
+ loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
+#endif
+ }
+
+#ifndef NO_FORK
+ if (multi && do_multi(multi, size_num))
+ goto show_res;
+#endif
+
+ /* Initialize the engine after the fork */
+ e = setup_engine(engine_id, 0);
+
+ /* No parameters; turn on everything. */
+ if ((argc == 0) && !doit[D_EVP]) {
+ for (i = 0; i < ALGOR_NUM; i++)
+ if (i != D_EVP)
+ doit[i] = 1;
+#ifndef OPENSSL_NO_RSA
+ for (i = 0; i < RSA_NUM; i++)
+ rsa_doit[i] = 1;
+#endif
+#ifndef OPENSSL_NO_DSA
+ for (i = 0; i < DSA_NUM; i++)
+ dsa_doit[i] = 1;
+#endif
+#ifndef OPENSSL_NO_EC
+ for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
+ ecdsa_doit[loop] = 1;
+ for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
+ ecdh_doit[loop] = 1;
+ for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
+ eddsa_doit[loop] = 1;
+#endif
+ }
+ for (i = 0; i < ALGOR_NUM; i++)
+ if (doit[i])
+ pr_header++;
+
+ if (usertime == 0 && !mr)
+ BIO_printf(bio_err,
+ "You have chosen to measure elapsed time "
+ "instead of user CPU time.\n");
+
+#ifndef OPENSSL_NO_RSA
+ for (i = 0; i < loopargs_len; i++) {
+ if (primes > RSA_DEFAULT_PRIME_NUM) {
+ /* for multi-prime RSA, skip this */
+ break;
+ }
+ for (k = 0; k < RSA_NUM; k++) {
+ const unsigned char *p;
+
+ p = rsa_data[k];
+ loopargs[i].rsa_key[k] =
+ d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]);
+ if (loopargs[i].rsa_key[k] == NULL) {
+ BIO_printf(bio_err,
+ "internal error loading RSA key number %d\n", k);
+ goto end;
+ }
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_DSA
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].dsa_key[0] = get_dsa(512);
+ loopargs[i].dsa_key[1] = get_dsa(1024);
+ loopargs[i].dsa_key[2] = get_dsa(2048);
+ }
+#endif
+#ifndef OPENSSL_NO_DES
+ DES_set_key_unchecked(&key, &sch);
+ DES_set_key_unchecked(&key2, &sch2);
+ DES_set_key_unchecked(&key3, &sch3);
+#endif
+ AES_set_encrypt_key(key16, 128, &aes_ks1);
+ AES_set_encrypt_key(key24, 192, &aes_ks2);
+ AES_set_encrypt_key(key32, 256, &aes_ks3);
+#ifndef OPENSSL_NO_CAMELLIA
+ Camellia_set_key(key16, 128, &camellia_ks1);
+ Camellia_set_key(ckey24, 192, &camellia_ks2);
+ Camellia_set_key(ckey32, 256, &camellia_ks3);
+#endif
+#ifndef OPENSSL_NO_IDEA
+ IDEA_set_encrypt_key(key16, &idea_ks);
+#endif
+#ifndef OPENSSL_NO_SEED
+ SEED_set_key(key16, &seed_ks);
+#endif
+#ifndef OPENSSL_NO_RC4
+ RC4_set_key(&rc4_ks, 16, key16);
+#endif
+#ifndef OPENSSL_NO_RC2
+ RC2_set_key(&rc2_ks, 16, key16, 128);
+#endif
+#ifndef OPENSSL_NO_RC5
+ RC5_32_set_key(&rc5_ks, 16, key16, 12);
+#endif
+#ifndef OPENSSL_NO_BF
+ BF_set_key(&bf_ks, 16, key16);
+#endif
+#ifndef OPENSSL_NO_CAST
+ CAST_set_key(&cast_ks, 16, key16);
+#endif
+#ifndef SIGALRM
+# ifndef OPENSSL_NO_DES
+ BIO_printf(bio_err, "First we calculate the approximate speed ...\n");
+ count = 10;
+ do {
+ long it;
+ count *= 2;
+ Time_F(START);
+ for (it = count; it; it--)
+ DES_ecb_encrypt((DES_cblock *)loopargs[0].buf,
+ (DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT);
+ d = Time_F(STOP);
+ } while (d < 3);
+ save_count = count;
+ c[D_MD2][0] = count / 10;
+ c[D_MDC2][0] = count / 10;
+ c[D_MD4][0] = count;
+ c[D_MD5][0] = count;
+ c[D_HMAC][0] = count;
+ c[D_SHA1][0] = count;
+ c[D_RMD160][0] = count;
+ c[D_RC4][0] = count * 5;
+ c[D_CBC_DES][0] = count;
+ c[D_EDE3_DES][0] = count / 3;
+ c[D_CBC_IDEA][0] = count;
+ c[D_CBC_SEED][0] = count;
+ c[D_CBC_RC2][0] = count;
+ c[D_CBC_RC5][0] = count;
+ c[D_CBC_BF][0] = count;
+ c[D_CBC_CAST][0] = count;
+ c[D_CBC_128_AES][0] = count;
+ c[D_CBC_192_AES][0] = count;
+ c[D_CBC_256_AES][0] = count;
+ c[D_CBC_128_CML][0] = count;
+ c[D_CBC_192_CML][0] = count;
+ c[D_CBC_256_CML][0] = count;
+ c[D_SHA256][0] = count;
+ c[D_SHA512][0] = count;
+ c[D_WHIRLPOOL][0] = count;
+ c[D_IGE_128_AES][0] = count;
+ c[D_IGE_192_AES][0] = count;
+ c[D_IGE_256_AES][0] = count;
+ c[D_GHASH][0] = count;
+ c[D_RAND][0] = count;
+
+ for (i = 1; i < size_num; i++) {
+ long l0, l1;
+
+ l0 = (long)lengths[0];
+ l1 = (long)lengths[i];
+
+ c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1;
+ c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1;
+ c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1;
+ c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1;
+ c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1;
+ c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1;
+ c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1;
+ c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1;
+ c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1;
+ c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1;
+ c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1;
+ c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1;
+
+ l0 = (long)lengths[i - 1];
+
+ c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1;
+ c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1;
+ c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1;
+ c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1;
+ c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1;
+ c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1;
+ c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1;
+ c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1;
+ c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1;
+ c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1;
+ c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1;
+ c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1;
+ c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1;
+ c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1;
+ c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1;
+ c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1;
+ c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1;
+ c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1;
+ }
+
+# ifndef OPENSSL_NO_RSA
+ rsa_c[R_RSA_512][0] = count / 2000;
+ rsa_c[R_RSA_512][1] = count / 400;
+ for (i = 1; i < RSA_NUM; i++) {
+ rsa_c[i][0] = rsa_c[i - 1][0] / 8;
+ rsa_c[i][1] = rsa_c[i - 1][1] / 4;
+ if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0)
+ rsa_doit[i] = 0;
+ else {
+ if (rsa_c[i][0] == 0) {
+ rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
+ rsa_c[i][1] = 20;
+ }
+ }
+ }
+# endif
+
+# ifndef OPENSSL_NO_DSA
+ dsa_c[R_DSA_512][0] = count / 1000;
+ dsa_c[R_DSA_512][1] = count / 1000 / 2;
+ for (i = 1; i < DSA_NUM; i++) {
+ dsa_c[i][0] = dsa_c[i - 1][0] / 4;
+ dsa_c[i][1] = dsa_c[i - 1][1] / 4;
+ if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0)
+ dsa_doit[i] = 0;
+ else {
+ if (dsa_c[i][0] == 0) {
+ dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
+ dsa_c[i][1] = 1;
+ }
+ }
+ }
+# endif
+
+# ifndef OPENSSL_NO_EC
+ ecdsa_c[R_EC_P160][0] = count / 1000;
+ ecdsa_c[R_EC_P160][1] = count / 1000 / 2;
+ for (i = R_EC_P192; i <= R_EC_P521; i++) {
+ ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
+ ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
+ if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
+ ecdsa_doit[i] = 0;
+ else {
+ if (ecdsa_c[i][0] == 0) {
+ ecdsa_c[i][0] = 1;
+ ecdsa_c[i][1] = 1;
+ }
+ }
+ }
+ ecdsa_c[R_EC_K163][0] = count / 1000;
+ ecdsa_c[R_EC_K163][1] = count / 1000 / 2;
+ for (i = R_EC_K233; i <= R_EC_K571; i++) {
+ ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
+ ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
+ if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
+ ecdsa_doit[i] = 0;
+ else {
+ if (ecdsa_c[i][0] == 0) {
+ ecdsa_c[i][0] = 1;
+ ecdsa_c[i][1] = 1;
+ }
+ }
+ }
+ ecdsa_c[R_EC_B163][0] = count / 1000;
+ ecdsa_c[R_EC_B163][1] = count / 1000 / 2;
+ for (i = R_EC_B233; i <= R_EC_B571; i++) {
+ ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
+ ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
+ if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
+ ecdsa_doit[i] = 0;
+ else {
+ if (ecdsa_c[i][0] == 0) {
+ ecdsa_c[i][0] = 1;
+ ecdsa_c[i][1] = 1;
+ }
+ }
+ }
+
+ ecdh_c[R_EC_P160][0] = count / 1000;
+ for (i = R_EC_P192; i <= R_EC_P521; i++) {
+ ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
+ if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+ ecdh_doit[i] = 0;
+ else {
+ if (ecdh_c[i][0] == 0) {
+ ecdh_c[i][0] = 1;
+ }
+ }
+ }
+ ecdh_c[R_EC_K163][0] = count / 1000;
+ for (i = R_EC_K233; i <= R_EC_K571; i++) {
+ ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
+ if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+ ecdh_doit[i] = 0;
+ else {
+ if (ecdh_c[i][0] == 0) {
+ ecdh_c[i][0] = 1;
+ }
+ }
+ }
+ ecdh_c[R_EC_B163][0] = count / 1000;
+ for (i = R_EC_B233; i <= R_EC_B571; i++) {
+ ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
+ if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+ ecdh_doit[i] = 0;
+ else {
+ if (ecdh_c[i][0] == 0) {
+ ecdh_c[i][0] = 1;
+ }
+ }
+ }
+ /* repeated code good to factorize */
+ ecdh_c[R_EC_BRP256R1][0] = count / 1000;
+ for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) {
+ ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
+ if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+ ecdh_doit[i] = 0;
+ else {
+ if (ecdh_c[i][0] == 0) {
+ ecdh_c[i][0] = 1;
+ }
+ }
+ }
+ ecdh_c[R_EC_BRP256T1][0] = count / 1000;
+ for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) {
+ ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
+ if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+ ecdh_doit[i] = 0;
+ else {
+ if (ecdh_c[i][0] == 0) {
+ ecdh_c[i][0] = 1;
+ }
+ }
+ }
+ /* default iteration count for the last two EC Curves */
+ ecdh_c[R_EC_X25519][0] = count / 1800;
+ ecdh_c[R_EC_X448][0] = count / 7200;
+
+ eddsa_c[R_EC_Ed25519][0] = count / 1800;
+ eddsa_c[R_EC_Ed448][0] = count / 7200;
+# endif
+
+# else
+/* not worth fixing */
+# error "You cannot disable DES on systems without SIGALRM."
+# endif /* OPENSSL_NO_DES */
+#elif SIGALRM > 0
+ signal(SIGALRM, alarmed);
+#endif /* SIGALRM */
+
+#ifndef OPENSSL_NO_MD2
+ if (doit[D_MD2]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_MD2, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_MDC2
+ if (doit[D_MDC2]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_MDC2, testnum, count, d);
+ }
+ }
+#endif
+
+#ifndef OPENSSL_NO_MD4
+ if (doit[D_MD4]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_MD4, testnum, count, d);
+ }
+ }
+#endif
+
+#ifndef OPENSSL_NO_MD5
+ if (doit[D_MD5]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, MD5_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_MD5, testnum, count, d);
+ }
+ }
+
+ if (doit[D_HMAC]) {
+ static const char hmac_key[] = "This is a key...";
+ int len = strlen(hmac_key);
+
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].hctx = HMAC_CTX_new();
+ if (loopargs[i].hctx == NULL) {
+ BIO_printf(bio_err, "HMAC malloc failure, exiting...");
+ exit(1);
+ }
+
+ HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL);
+ }
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, HMAC_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_HMAC, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++) {
+ HMAC_CTX_free(loopargs[i].hctx);
+ }
+ }
+#endif
+ if (doit[D_SHA1]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SHA1_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_SHA1, testnum, count, d);
+ }
+ }
+ if (doit[D_SHA256]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_SHA256], c[D_SHA256][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SHA256_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_SHA256, testnum, count, d);
+ }
+ }
+ if (doit[D_SHA512]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_SHA512], c[D_SHA512][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, SHA512_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_SHA512, testnum, count, d);
+ }
+ }
+#ifndef OPENSSL_NO_WHIRLPOOL
+ if (doit[D_WHIRLPOOL]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_WHIRLPOOL, testnum, count, d);
+ }
+ }
+#endif
+
+#ifndef OPENSSL_NO_RMD160
+ if (doit[D_RMD160]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_RMD160], c[D_RMD160][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_RMD160, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_RC4
+ if (doit[D_RC4]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, RC4_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_RC4, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_DES
+ if (doit[D_CBC_DES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_CBC_DES, testnum, count, d);
+ }
+ }
+
+ if (doit[D_EDE3_DES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_EDE3_DES, testnum, count, d);
+ }
+ }
+#endif
+
+ if (doit[D_CBC_128_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_CBC_128_AES, testnum, count, d);
+ }
+ }
+ if (doit[D_CBC_192_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_CBC_192_AES, testnum, count, d);
+ }
+ }
+ if (doit[D_CBC_256_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_CBC_256_AES, testnum, count, d);
+ }
+ }
+
+ if (doit[D_IGE_128_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_IGE_128_AES, testnum, count, d);
+ }
+ }
+ if (doit[D_IGE_192_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_IGE_192_AES, testnum, count, d);
+ }
+ }
+ if (doit[D_IGE_256_AES]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_IGE_256_AES, testnum, count, d);
+ }
+ }
+ if (doit[D_GHASH]) {
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].gcm_ctx =
+ CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
+ CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx,
+ (unsigned char *)"0123456789ab", 12);
+ }
+
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_GHASH], c[D_GHASH][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_GHASH, testnum, count, d);
+ }
+ for (i = 0; i < loopargs_len; i++)
+ CRYPTO_gcm128_release(loopargs[i].gcm_ctx);
+ }
+#ifndef OPENSSL_NO_CAMELLIA
+ if (doit[D_CBC_128_CML]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_128_CML]);
+ doit[D_CBC_128_CML] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_128_CML][testnum]); count++)
+ Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &camellia_ks1,
+ iv, CAMELLIA_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_128_CML, testnum, count, d);
+ }
+ }
+ if (doit[D_CBC_192_CML]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_192_CML]);
+ doit[D_CBC_192_CML] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum],
+ lengths[testnum], seconds.sym);
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported, exiting...");
+ exit(1);
+ }
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_192_CML][testnum]); count++)
+ Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &camellia_ks2,
+ iv, CAMELLIA_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_192_CML, testnum, count, d);
+ }
+ }
+ if (doit[D_CBC_256_CML]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_256_CML]);
+ doit[D_CBC_256_CML] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_256_CML][testnum]); count++)
+ Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &camellia_ks3,
+ iv, CAMELLIA_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_256_CML, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_IDEA
+ if (doit[D_CBC_IDEA]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_IDEA]);
+ doit[D_CBC_IDEA] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_IDEA][testnum]); count++)
+ IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &idea_ks,
+ iv, IDEA_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_IDEA, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_SEED
+ if (doit[D_CBC_SEED]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_SEED]);
+ doit[D_CBC_SEED] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_SEED][testnum]); count++)
+ SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &seed_ks, iv, 1);
+ d = Time_F(STOP);
+ print_result(D_CBC_SEED, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_RC2
+ if (doit[D_CBC_RC2]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_RC2]);
+ doit[D_CBC_RC2] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum],
+ lengths[testnum], seconds.sym);
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported, exiting...");
+ exit(1);
+ }
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_RC2][testnum]); count++)
+ RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &rc2_ks,
+ iv, RC2_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_RC2, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_RC5
+ if (doit[D_CBC_RC5]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_RC5]);
+ doit[D_CBC_RC5] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum],
+ lengths[testnum], seconds.sym);
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported, exiting...");
+ exit(1);
+ }
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_RC5][testnum]); count++)
+ RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &rc5_ks,
+ iv, RC5_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_RC5, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_BF
+ if (doit[D_CBC_BF]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_BF]);
+ doit[D_CBC_BF] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_BF], c[D_CBC_BF][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_BF][testnum]); count++)
+ BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &bf_ks,
+ iv, BF_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_BF, testnum, count, d);
+ }
+ }
+#endif
+#ifndef OPENSSL_NO_CAST
+ if (doit[D_CBC_CAST]) {
+ if (async_jobs > 0) {
+ BIO_printf(bio_err, "Async mode is not supported with %s\n",
+ names[D_CBC_CAST]);
+ doit[D_CBC_CAST] = 0;
+ }
+ for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+ print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum],
+ lengths[testnum], seconds.sym);
+ Time_F(START);
+ for (count = 0, run = 1; COND(c[D_CBC_CAST][testnum]); count++)
+ CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
+ (size_t)lengths[testnum], &cast_ks,
+ iv, CAST_ENCRYPT);
+ d = Time_F(STOP);
+ print_result(D_CBC_CAST, testnum, count, d);
+ }
+ }
+#endif
+ if (doit[D_RAND]) {
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_RAND, testnum, count, d);
+ }
+ }
+
+ if (doit[D_EVP]) {
+ if (evp_cipher != NULL) {
+ int (*loopfunc)(void *args) = EVP_Update_loop;
+
+ if (multiblock && (EVP_CIPHER_flags(evp_cipher) &
+ EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+ multiblock_speed(evp_cipher, lengths_single, &seconds);
+ ret = 0;
+ goto end;
+ }
+
+ names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+
+ if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
+ loopfunc = EVP_Update_loop_ccm;
+ } else if (aead && (EVP_CIPHER_flags(evp_cipher) &
+ EVP_CIPH_FLAG_AEAD_CIPHER)) {
+ loopfunc = EVP_Update_loop_aead;
+ if (lengths == lengths_list) {
+ lengths = aead_lengths_list;
+ size_num = OSSL_NELEM(aead_lengths_list);
+ }
+ }
+
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_EVP], save_count, lengths[testnum],
+ seconds.sym);
+
+ for (k = 0; k < loopargs_len; k++) {
+ loopargs[k].ctx = EVP_CIPHER_CTX_new();
+ EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL,
+ iv, decrypt ? 0 : 1);
+
+ EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
+
+ keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
+ loopargs[k].key = app_malloc(keylen, "evp_cipher key");
+ EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key);
+ EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+ loopargs[k].key, NULL, -1);
+ OPENSSL_clear_free(loopargs[k].key, keylen);
+ }
+
+ Time_F(START);
+ count = run_benchmark(async_jobs, loopfunc, loopargs);
+ d = Time_F(STOP);
+ for (k = 0; k < loopargs_len; k++) {
+ EVP_CIPHER_CTX_free(loopargs[k].ctx);
+ }
+ print_result(D_EVP, testnum, count, d);
+ }
+ } else if (evp_md != NULL) {
+ names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
+
+ for (testnum = 0; testnum < size_num; testnum++) {
+ print_message(names[D_EVP], save_count, lengths[testnum],
+ seconds.sym);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs);
+ d = Time_F(STOP);
+ print_result(D_EVP, testnum, count, d);
+ }
+ }
+ }
+
+ for (i = 0; i < loopargs_len; i++)
+ if (RAND_bytes(loopargs[i].buf, 36) <= 0)
+ goto end;
+
+#ifndef OPENSSL_NO_RSA
+ for (testnum = 0; testnum < RSA_NUM; testnum++) {
+ int st = 0;
+ if (!rsa_doit[testnum])
+ continue;
+ for (i = 0; i < loopargs_len; i++) {
+ if (primes > 2) {
+ /* we haven't set keys yet, generate multi-prime RSA keys */
+ BIGNUM *bn = BN_new();
+
+ if (bn == NULL)
+ goto end;
+ if (!BN_set_word(bn, RSA_F4)) {
+ BN_free(bn);
+ goto end;
+ }
+
+ BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n",
+ rsa_choices[testnum].name);
+
+ loopargs[i].rsa_key[testnum] = RSA_new();
+ if (loopargs[i].rsa_key[testnum] == NULL) {
+ BN_free(bn);
+ goto end;
+ }
+
+ if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum],
+ rsa_bits[testnum],
+ primes, bn, NULL)) {
+ BN_free(bn);
+ goto end;
+ }
+ BN_free(bn);
+ }
+ st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
+ &loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "RSA sign failure. No RSA sign will be done.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ pkey_print_message("private", "rsa",
+ rsa_c[testnum][0], rsa_bits[testnum],
+ seconds.rsa);
+ /* RSA_blinding_on(rsa_key[testnum],NULL); */
+ Time_F(START);
+ count = run_benchmark(async_jobs, RSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R1:%ld:%d:%.2f\n"
+ : "%ld %u bits private RSA's in %.2fs\n",
+ count, rsa_bits[testnum], d);
+ rsa_results[testnum][0] = (double)count / d;
+ rsa_count = count;
+ }
+
+ for (i = 0; i < loopargs_len; i++) {
+ st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
+ loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
+ if (st <= 0)
+ break;
+ }
+ if (st <= 0) {
+ BIO_printf(bio_err,
+ "RSA verify failure. No RSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ rsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("public", "rsa",
+ rsa_c[testnum][1], rsa_bits[testnum],
+ seconds.rsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, RSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R2:%ld:%d:%.2f\n"
+ : "%ld %u bits public RSA's in %.2fs\n",
+ count, rsa_bits[testnum], d);
+ rsa_results[testnum][1] = (double)count / d;
+ }
+
+ if (rsa_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ for (testnum++; testnum < RSA_NUM; testnum++)
+ rsa_doit[testnum] = 0;
+ }
+ }
+#endif /* OPENSSL_NO_RSA */
+
+ for (i = 0; i < loopargs_len; i++)
+ if (RAND_bytes(loopargs[i].buf, 36) <= 0)
+ goto end;
+
+#ifndef OPENSSL_NO_DSA
+ for (testnum = 0; testnum < DSA_NUM; testnum++) {
+ int st = 0;
+ if (!dsa_doit[testnum])
+ continue;
+
+ /* DSA_generate_key(dsa_key[testnum]); */
+ /* DSA_sign_setup(dsa_key[testnum],NULL); */
+ for (i = 0; i < loopargs_len; i++) {
+ st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
+ &loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "DSA sign failure. No DSA sign will be done.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ pkey_print_message("sign", "dsa",
+ dsa_c[testnum][0], dsa_bits[testnum],
+ seconds.dsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, DSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R3:%ld:%u:%.2f\n"
+ : "%ld %u bits DSA signs in %.2fs\n",
+ count, dsa_bits[testnum], d);
+ dsa_results[testnum][0] = (double)count / d;
+ rsa_count = count;
+ }
+
+ for (i = 0; i < loopargs_len; i++) {
+ st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
+ loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
+ if (st <= 0)
+ break;
+ }
+ if (st <= 0) {
+ BIO_printf(bio_err,
+ "DSA verify failure. No DSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ dsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", "dsa",
+ dsa_c[testnum][1], dsa_bits[testnum],
+ seconds.dsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, DSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R4:%ld:%u:%.2f\n"
+ : "%ld %u bits DSA verify in %.2fs\n",
+ count, dsa_bits[testnum], d);
+ dsa_results[testnum][1] = (double)count / d;
+ }
+
+ if (rsa_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ for (testnum++; testnum < DSA_NUM; testnum++)
+ dsa_doit[testnum] = 0;
+ }
+ }
+#endif /* OPENSSL_NO_DSA */
+
+#ifndef OPENSSL_NO_EC
+ for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
+ int st = 1;
+
+ if (!ecdsa_doit[testnum])
+ continue; /* Ignore Curve */
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].ecdsa[testnum] =
+ EC_KEY_new_by_curve_name(test_curves[testnum].nid);
+ if (loopargs[i].ecdsa[testnum] == NULL) {
+ st = 0;
+ break;
+ }
+ }
+ if (st == 0) {
+ BIO_printf(bio_err, "ECDSA failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ for (i = 0; i < loopargs_len; i++) {
+ EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL);
+ /* Perform ECDSA signature test */
+ EC_KEY_generate_key(loopargs[i].ecdsa[testnum]);
+ st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
+ &loopargs[i].siglen,
+ loopargs[i].ecdsa[testnum]);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "ECDSA sign failure. No ECDSA sign will be done.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ pkey_print_message("sign", "ecdsa",
+ ecdsa_c[testnum][0],
+ test_curves[testnum].bits, seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+
+ BIO_printf(bio_err,
+ mr ? "+R5:%ld:%u:%.2f\n" :
+ "%ld %u bits ECDSA signs in %.2fs \n",
+ count, test_curves[testnum].bits, d);
+ ecdsa_results[testnum][0] = (double)count / d;
+ rsa_count = count;
+ }
+
+ /* Perform ECDSA verification test */
+ for (i = 0; i < loopargs_len; i++) {
+ st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
+ loopargs[i].siglen,
+ loopargs[i].ecdsa[testnum]);
+ if (st != 1)
+ break;
+ }
+ if (st != 1) {
+ BIO_printf(bio_err,
+ "ECDSA verify failure. No ECDSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ ecdsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", "ecdsa",
+ ecdsa_c[testnum][1],
+ test_curves[testnum].bits, seconds.ecdsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R6:%ld:%u:%.2f\n"
+ : "%ld %u bits ECDSA verify in %.2fs\n",
+ count, test_curves[testnum].bits, d);
+ ecdsa_results[testnum][1] = (double)count / d;
+ }
+
+ if (rsa_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ for (testnum++; testnum < ECDSA_NUM; testnum++)
+ ecdsa_doit[testnum] = 0;
+ }
+ }
+ }
+
+ for (testnum = 0; testnum < EC_NUM; testnum++) {
+ int ecdh_checks = 1;
+
+ if (!ecdh_doit[testnum])
+ continue;
+
+ for (i = 0; i < loopargs_len; i++) {
+ EVP_PKEY_CTX *kctx = NULL;
+ EVP_PKEY_CTX *test_ctx = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *key_A = NULL;
+ EVP_PKEY *key_B = NULL;
+ size_t outlen;
+ size_t test_outlen;
+
+ /* Ensure that the error queue is empty */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "WARNING: the error queue contains previous unhandled errors.\n");
+ ERR_print_errors(bio_err);
+ }
+
+ /* Let's try to create a ctx directly from the NID: this works for
+ * curves like Curve25519 that are not implemented through the low
+ * level EC interface.
+ * If this fails we try creating a EVP_PKEY_EC generic param ctx,
+ * then we set the curve by NID before deriving the actual keygen
+ * ctx for that specific curve. */
+ kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */
+ if (!kctx) {
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *params = NULL;
+
+ /* If we reach this code EVP_PKEY_CTX_new_id() failed and a
+ * "int_ctx_new:unsupported algorithm" error was added to the
+ * error queue.
+ * We remove it from the error queue as we are handling it. */
+ unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */
+ if (error == ERR_peek_last_error() && /* oldest and latest errors match */
+ /* check that the error origin matches */
+ ERR_GET_LIB(error) == ERR_LIB_EVP &&
+ ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW &&
+ ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM)
+ ERR_get_error(); /* pop error from queue */
+ if (ERR_peek_error()) {
+ BIO_printf(bio_err,
+ "Unhandled error in the error queue during ECDH init.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+
+ if ( /* Create the context for parameter generation */
+ !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
+ /* Initialise the parameter generation */
+ !EVP_PKEY_paramgen_init(pctx) ||
+ /* Set the curve by NID */
+ !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+ test_curves
+ [testnum].nid) ||
+ /* Create the parameter object params */
+ !EVP_PKEY_paramgen(pctx, &params)) {
+ ecdh_checks = 0;
+ BIO_printf(bio_err, "ECDH EC params init failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+ /* Create the context for the key generation */
+ kctx = EVP_PKEY_CTX_new(params, NULL);
+
+ EVP_PKEY_free(params);
+ params = NULL;
+ EVP_PKEY_CTX_free(pctx);
+ pctx = NULL;
+ }
+ if (kctx == NULL || /* keygen ctx is not null */
+ !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) {
+ ecdh_checks = 0;
+ BIO_printf(bio_err, "ECDH keygen failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+
+ if (!EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */
+ !EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */
+ !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
+ !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */
+ !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */
+ !EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */
+ outlen == 0 || /* ensure outlen is a valid size */
+ outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) {
+ ecdh_checks = 0;
+ BIO_printf(bio_err, "ECDH key generation failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+
+ /* Here we perform a test run, comparing the output of a*B and b*A;
+ * we try this here and assume that further EVP_PKEY_derive calls
+ * never fail, so we can skip checks in the actually benchmarked
+ * code, for maximum performance. */
+ if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */
+ !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */
+ !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */
+ !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */
+ !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */
+ !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */
+ test_outlen != outlen /* compare output length */ ) {
+ ecdh_checks = 0;
+ BIO_printf(bio_err, "ECDH computation failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+
+ /* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */
+ if (CRYPTO_memcmp(loopargs[i].secret_a,
+ loopargs[i].secret_b, outlen)) {
+ ecdh_checks = 0;
+ BIO_printf(bio_err, "ECDH computations don't match.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ break;
+ }
+
+ loopargs[i].ecdh_ctx[testnum] = ctx;
+ loopargs[i].outlen[testnum] = outlen;
+
+ EVP_PKEY_free(key_A);
+ EVP_PKEY_free(key_B);
+ EVP_PKEY_CTX_free(kctx);
+ kctx = NULL;
+ EVP_PKEY_CTX_free(test_ctx);
+ test_ctx = NULL;
+ }
+ if (ecdh_checks != 0) {
+ pkey_print_message("", "ecdh",
+ ecdh_c[testnum][0],
+ test_curves[testnum].bits, seconds.ecdh);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R7:%ld:%d:%.2f\n" :
+ "%ld %u-bits ECDH ops in %.2fs\n", count,
+ test_curves[testnum].bits, d);
+ ecdh_results[testnum][0] = (double)count / d;
+ rsa_count = count;
+ }
+
+ if (rsa_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++)
+ ecdh_doit[testnum] = 0;
+ }
+ }
+
+ for (testnum = 0; testnum < EdDSA_NUM; testnum++) {
+ int st = 1;
+ EVP_PKEY *ed_pkey = NULL;
+ EVP_PKEY_CTX *ed_pctx = NULL;
+
+ if (!eddsa_doit[testnum])
+ continue; /* Ignore Curve */
+ for (i = 0; i < loopargs_len; i++) {
+ loopargs[i].eddsa_ctx[testnum] = EVP_MD_CTX_new();
+ if (loopargs[i].eddsa_ctx[testnum] == NULL) {
+ st = 0;
+ break;
+ }
+
+ if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL))
+ == NULL
+ || !EVP_PKEY_keygen_init(ed_pctx)
+ || !EVP_PKEY_keygen(ed_pctx, &ed_pkey)) {
+ st = 0;
+ EVP_PKEY_CTX_free(ed_pctx);
+ break;
+ }
+ EVP_PKEY_CTX_free(ed_pctx);
+
+ if (!EVP_DigestSignInit(loopargs[i].eddsa_ctx[testnum], NULL, NULL,
+ NULL, ed_pkey)) {
+ st = 0;
+ EVP_PKEY_free(ed_pkey);
+ break;
+ }
+ EVP_PKEY_free(ed_pkey);
+ }
+ if (st == 0) {
+ BIO_printf(bio_err, "EdDSA failure.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ for (i = 0; i < loopargs_len; i++) {
+ /* Perform EdDSA signature test */
+ loopargs[i].sigsize = test_ed_curves[testnum].sigsize;
+ st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum],
+ loopargs[i].buf2, &loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st == 0)
+ break;
+ }
+ if (st == 0) {
+ BIO_printf(bio_err,
+ "EdDSA sign failure. No EdDSA sign will be done.\n");
+ ERR_print_errors(bio_err);
+ rsa_count = 1;
+ } else {
+ pkey_print_message("sign", test_ed_curves[testnum].name,
+ eddsa_c[testnum][0],
+ test_ed_curves[testnum].bits, seconds.eddsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs);
+ d = Time_F(STOP);
+
+ BIO_printf(bio_err,
+ mr ? "+R8:%ld:%u:%s:%.2f\n" :
+ "%ld %u bits %s signs in %.2fs \n",
+ count, test_ed_curves[testnum].bits,
+ test_ed_curves[testnum].name, d);
+ eddsa_results[testnum][0] = (double)count / d;
+ rsa_count = count;
+ }
+
+ /* Perform EdDSA verification test */
+ for (i = 0; i < loopargs_len; i++) {
+ st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
+ loopargs[i].buf2, loopargs[i].sigsize,
+ loopargs[i].buf, 20);
+ if (st != 1)
+ break;
+ }
+ if (st != 1) {
+ BIO_printf(bio_err,
+ "EdDSA verify failure. No EdDSA verify will be done.\n");
+ ERR_print_errors(bio_err);
+ eddsa_doit[testnum] = 0;
+ } else {
+ pkey_print_message("verify", test_ed_curves[testnum].name,
+ eddsa_c[testnum][1],
+ test_ed_curves[testnum].bits, seconds.eddsa);
+ Time_F(START);
+ count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ mr ? "+R9:%ld:%u:%s:%.2f\n"
+ : "%ld %u bits %s verify in %.2fs\n",
+ count, test_ed_curves[testnum].bits,
+ test_ed_curves[testnum].name, d);
+ eddsa_results[testnum][1] = (double)count / d;
+ }
+
+ if (rsa_count <= 1) {
+ /* if longer than 10s, don't do any more */
+ for (testnum++; testnum < EdDSA_NUM; testnum++)
+ eddsa_doit[testnum] = 0;
+ }
+ }
+ }
+
+#endif /* OPENSSL_NO_EC */
+#ifndef NO_FORK
+ show_res:
+#endif
+ if (!mr) {
+ printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
+ printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
+ printf("options:");
+ printf("%s ", BN_options());
+#ifndef OPENSSL_NO_MD2
+ printf("%s ", MD2_options());
+#endif
+#ifndef OPENSSL_NO_RC4
+ printf("%s ", RC4_options());
+#endif
+#ifndef OPENSSL_NO_DES
+ printf("%s ", DES_options());
+#endif
+ printf("%s ", AES_options());
+#ifndef OPENSSL_NO_IDEA
+ printf("%s ", IDEA_options());
+#endif
+#ifndef OPENSSL_NO_BF
+ printf("%s ", BF_options());
+#endif
+ printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ }
+
+ if (pr_header) {
+ if (mr)
+ printf("+H");
+ else {
+ printf
+ ("The 'numbers' are in 1000s of bytes per second processed.\n");
+ printf("type ");
+ }
+ for (testnum = 0; testnum < size_num; testnum++)
+ printf(mr ? ":%d" : "%7d bytes", lengths[testnum]);
+ printf("\n");
+ }
+
+ for (k = 0; k < ALGOR_NUM; k++) {
+ if (!doit[k])
+ continue;
+ if (mr)
+ printf("+F:%u:%s", k, names[k]);
+ else
+ printf("%-13s", names[k]);
+ for (testnum = 0; testnum < size_num; testnum++) {
+ if (results[k][testnum] > 10000 && !mr)
+ printf(" %11.2fk", results[k][testnum] / 1e3);
+ else
+ printf(mr ? ":%.2f" : " %11.2f ", results[k][testnum]);
+ }
+ printf("\n");
+ }
+#ifndef OPENSSL_NO_RSA
+ testnum = 1;
+ for (k = 0; k < RSA_NUM; k++) {
+ if (!rsa_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%18ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+ if (mr)
+ printf("+F2:%u:%u:%f:%f\n",
+ k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]);
+ else
+ printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+ rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
+ rsa_results[k][0], rsa_results[k][1]);
+ }
+#endif
+#ifndef OPENSSL_NO_DSA
+ testnum = 1;
+ for (k = 0; k < DSA_NUM; k++) {
+ if (!dsa_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%18ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+ if (mr)
+ printf("+F3:%u:%u:%f:%f\n",
+ k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]);
+ else
+ printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+ dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1],
+ dsa_results[k][0], dsa_results[k][1]);
+ }
+#endif
+#ifndef OPENSSL_NO_EC
+ testnum = 1;
+ for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) {
+ if (!ecdsa_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%30ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+
+ if (mr)
+ printf("+F4:%u:%u:%f:%f\n",
+ k, test_curves[k].bits,
+ ecdsa_results[k][0], ecdsa_results[k][1]);
+ else
+ printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+ test_curves[k].bits, test_curves[k].name,
+ 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
+ ecdsa_results[k][0], ecdsa_results[k][1]);
+ }
+
+ testnum = 1;
+ for (k = 0; k < EC_NUM; k++) {
+ if (!ecdh_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%30sop op/s\n", " ");
+ testnum = 0;
+ }
+ if (mr)
+ printf("+F5:%u:%u:%f:%f\n",
+ k, test_curves[k].bits,
+ ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
+
+ else
+ printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
+ test_curves[k].bits, test_curves[k].name,
+ 1.0 / ecdh_results[k][0], ecdh_results[k][0]);
+ }
+
+ testnum = 1;
+ for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) {
+ if (!eddsa_doit[k])
+ continue;
+ if (testnum && !mr) {
+ printf("%30ssign verify sign/s verify/s\n", " ");
+ testnum = 0;
+ }
+
+ if (mr)
+ printf("+F6:%u:%u:%s:%f:%f\n",
+ k, test_ed_curves[k].bits, test_ed_curves[k].name,
+ eddsa_results[k][0], eddsa_results[k][1]);
+ else
+ printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+ test_ed_curves[k].bits, test_ed_curves[k].name,
+ 1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
+ eddsa_results[k][0], eddsa_results[k][1]);
+ }
+#endif
+
+ ret = 0;
+
+ end:
+ ERR_print_errors(bio_err);
+ for (i = 0; i < loopargs_len; i++) {
+ OPENSSL_free(loopargs[i].buf_malloc);
+ OPENSSL_free(loopargs[i].buf2_malloc);
+
+#ifndef OPENSSL_NO_RSA
+ for (k = 0; k < RSA_NUM; k++)
+ RSA_free(loopargs[i].rsa_key[k]);
+#endif
+#ifndef OPENSSL_NO_DSA
+ for (k = 0; k < DSA_NUM; k++)
+ DSA_free(loopargs[i].dsa_key[k]);
+#endif
+#ifndef OPENSSL_NO_EC
+ for (k = 0; k < ECDSA_NUM; k++)
+ EC_KEY_free(loopargs[i].ecdsa[k]);
+ for (k = 0; k < EC_NUM; k++)
+ EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
+ for (k = 0; k < EdDSA_NUM; k++)
+ EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
+ OPENSSL_free(loopargs[i].secret_a);
+ OPENSSL_free(loopargs[i].secret_b);
+#endif
+ }
+
+ if (async_jobs > 0) {
+ for (i = 0; i < loopargs_len; i++)
+ ASYNC_WAIT_CTX_free(loopargs[i].wait_ctx);
+ }
+
+ if (async_init) {
+ ASYNC_cleanup_thread();
+ }
+ OPENSSL_free(loopargs);
+ release_engine(e);
+ return ret;
+}
+
+static void print_message(const char *s, long num, int length, int tm)
+{
+#ifdef SIGALRM
+ BIO_printf(bio_err,
+ mr ? "+DT:%s:%d:%d\n"
+ : "Doing %s for %ds on %d size blocks: ", s, tm, length);
+ (void)BIO_flush(bio_err);
+ alarm(tm);
+#else
+ BIO_printf(bio_err,
+ mr ? "+DN:%s:%ld:%d\n"
+ : "Doing %s %ld times on %d size blocks: ", s, num, length);
+ (void)BIO_flush(bio_err);
+#endif
+}
+
+static void pkey_print_message(const char *str, const char *str2, long num,
+ unsigned int bits, int tm)
+{
+#ifdef SIGALRM
+ BIO_printf(bio_err,
+ mr ? "+DTP:%d:%s:%s:%d\n"
+ : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm);
+ (void)BIO_flush(bio_err);
+ alarm(tm);
+#else
+ BIO_printf(bio_err,
+ mr ? "+DNP:%ld:%d:%s:%s\n"
+ : "Doing %ld %u bits %s %s's: ", num, bits, str, str2);
+ (void)BIO_flush(bio_err);
+#endif
+}
+
+static void print_result(int alg, int run_no, int count, double time_used)
+{
+ if (count == -1) {
+ BIO_puts(bio_err, "EVP error!\n");
+ exit(1);
+ }
+ BIO_printf(bio_err,
+ mr ? "+R:%d:%s:%f\n"
+ : "%d %s's in %.2fs\n", count, names[alg], time_used);
+ results[alg][run_no] = ((double)count) / time_used * lengths[run_no];
+}
+
+#ifndef NO_FORK
+static char *sstrsep(char **string, const char *delim)
+{
+ char isdelim[256];
+ char *token = *string;
+
+ if (**string == 0)
+ return NULL;
+
+ memset(isdelim, 0, sizeof(isdelim));
+ isdelim[0] = 1;
+
+ while (*delim) {
+ isdelim[(unsigned char)(*delim)] = 1;
+ delim++;
+ }
+
+ while (!isdelim[(unsigned char)(**string)]) {
+ (*string)++;
+ }
+
+ if (**string) {
+ **string = 0;
+ (*string)++;
+ }
+
+ return token;
+}
+
+static int do_multi(int multi, int size_num)
+{
+ int n;
+ int fd[2];
+ int *fds;
+ static char sep[] = ":";
+
+ fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi");
+ for (n = 0; n < multi; ++n) {
+ if (pipe(fd) == -1) {
+ BIO_printf(bio_err, "pipe failure\n");
+ exit(1);
+ }
+ fflush(stdout);
+ (void)BIO_flush(bio_err);
+ if (fork()) {
+ close(fd[1]);
+ fds[n] = fd[0];
+ } else {
+ close(fd[0]);
+ close(1);
+ if (dup(fd[1]) == -1) {
+ BIO_printf(bio_err, "dup failed\n");
+ exit(1);
+ }
+ close(fd[1]);
+ mr = 1;
+ usertime = 0;
+ free(fds);
+ return 0;
+ }
+ printf("Forked child %d\n", n);
+ }
+
+ /* for now, assume the pipe is long enough to take all the output */
+ for (n = 0; n < multi; ++n) {
+ FILE *f;
+ char buf[1024];
+ char *p;
+
+ f = fdopen(fds[n], "r");
+ while (fgets(buf, sizeof(buf), f)) {
+ p = strchr(buf, '\n');
+ if (p)
+ *p = '\0';
+ if (buf[0] != '+') {
+ BIO_printf(bio_err,
+ "Don't understand line '%s' from child %d\n", buf,
+ n);
+ continue;
+ }
+ printf("Got: %s from %d\n", buf, n);
+ if (strncmp(buf, "+F:", 3) == 0) {
+ int alg;
+ int j;
+
+ p = buf + 3;
+ alg = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+ for (j = 0; j < size_num; ++j)
+ results[alg][j] += atof(sstrsep(&p, sep));
+ } else if (strncmp(buf, "+F2:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ rsa_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ rsa_results[k][1] += d;
+ }
+# ifndef OPENSSL_NO_DSA
+ else if (strncmp(buf, "+F3:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ dsa_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ dsa_results[k][1] += d;
+ }
+# endif
+# ifndef OPENSSL_NO_EC
+ else if (strncmp(buf, "+F4:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ ecdsa_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ ecdsa_results[k][1] += d;
+ } else if (strncmp(buf, "+F5:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ ecdh_results[k][0] += d;
+ } else if (strncmp(buf, "+F6:", 4) == 0) {
+ int k;
+ double d;
+
+ p = buf + 4;
+ k = atoi(sstrsep(&p, sep));
+ sstrsep(&p, sep);
+
+ d = atof(sstrsep(&p, sep));
+ eddsa_results[k][0] += d;
+
+ d = atof(sstrsep(&p, sep));
+ eddsa_results[k][1] += d;
+ }
+# endif
+
+ else if (strncmp(buf, "+H:", 3) == 0) {
+ ;
+ } else
+ BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
+ n);
+ }
+
+ fclose(f);
+ }
+ free(fds);
+ return 1;
+}
+#endif
+
+static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
+ const openssl_speed_sec_t *seconds)
+{
+ static const int mblengths_list[] =
+ { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 };
+ const int *mblengths = mblengths_list;
+ int j, count, keylen, num = OSSL_NELEM(mblengths_list);
+ const char *alg_name;
+ unsigned char *inp, *out, *key, no_key[32], no_iv[16];
+ EVP_CIPHER_CTX *ctx;
+ double d = 0.0;
+
+ if (lengths_single) {
+ mblengths = &lengths_single;
+ num = 1;
+ }
+
+ inp = app_malloc(mblengths[num - 1], "multiblock input buffer");
+ out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer");
+ ctx = EVP_CIPHER_CTX_new();
+ EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv);
+
+ keylen = EVP_CIPHER_CTX_key_length(ctx);
+ key = app_malloc(keylen, "evp_cipher key");
+ EVP_CIPHER_CTX_rand_key(ctx, key);
+ EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
+ OPENSSL_clear_free(key, keylen);
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key);
+ alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+
+ for (j = 0; j < num; j++) {
+ print_message(alg_name, 0, mblengths[j], seconds->sym);
+ Time_F(START);
+ for (count = 0, run = 1; run && count < 0x7fffffff; count++) {
+ unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
+ size_t len = mblengths[j];
+ int packlen;
+
+ memset(aad, 0, 8); /* avoid uninitialized values */
+ aad[8] = 23; /* SSL3_RT_APPLICATION_DATA */
+ aad[9] = 3; /* version */
+ aad[10] = 2;
+ aad[11] = 0; /* length */
+ aad[12] = 0;
+ mb_param.out = NULL;
+ mb_param.inp = aad;
+ mb_param.len = len;
+ mb_param.interleave = 8;
+
+ packlen = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
+ sizeof(mb_param), &mb_param);
+
+ if (packlen > 0) {
+ mb_param.out = out;
+ mb_param.inp = inp;
+ mb_param.len = len;
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+ sizeof(mb_param), &mb_param);
+ } else {
+ int pad;
+
+ RAND_bytes(out, 16);
+ len += 16;
+ aad[11] = (unsigned char)(len >> 8);
+ aad[12] = (unsigned char)(len);
+ pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD,
+ EVP_AEAD_TLS1_AAD_LEN, aad);
+ EVP_Cipher(ctx, out, inp, len + pad);
+ }
+ }
+ d = Time_F(STOP);
+ BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n"
+ : "%d %s's in %.2fs\n", count, "evp", d);
+ results[D_EVP][j] = ((double)count) / d * mblengths[j];
+ }
+
+ if (mr) {
+ fprintf(stdout, "+H");
+ for (j = 0; j < num; j++)
+ fprintf(stdout, ":%d", mblengths[j]);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "+F:%d:%s", D_EVP, alg_name);
+ for (j = 0; j < num; j++)
+ fprintf(stdout, ":%.2f", results[D_EVP][j]);
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stdout,
+ "The 'numbers' are in 1000s of bytes per second processed.\n");
+ fprintf(stdout, "type ");
+ for (j = 0; j < num; j++)
+ fprintf(stdout, "%7d bytes", mblengths[j]);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%-24s", alg_name);
+
+ for (j = 0; j < num; j++) {
+ if (results[D_EVP][j] > 10000)
+ fprintf(stdout, " %11.2fk", results[D_EVP][j] / 1e3);
+ else
+ fprintf(stdout, " %11.2f ", results[D_EVP][j]);
+ }
+ fprintf(stdout, "\n");
+ }
+
+ OPENSSL_free(inp);
+ OPENSSL_free(out);
+ EVP_CIPHER_CTX_free(ctx);
+}
diff --git a/freebsd/crypto/openssl/apps/spkac.c b/freebsd/crypto/openssl/apps/spkac.c
new file mode 100644
index 00000000..a235bfc0
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/spkac.c
@@ -0,0 +1,204 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT,
+ OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC,
+ OPT_SPKSECT, OPT_KEYFORM
+} OPTION_CHOICE;
+
+const OPTIONS spkac_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"key", OPT_KEY, '<', "Create SPKAC using private key"},
+ {"keyform", OPT_KEYFORM, 'f', "Private key file format - default PEM (PEM, DER, or ENGINE)"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"challenge", OPT_CHALLENGE, 's', "Challenge string"},
+ {"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"},
+ {"noout", OPT_NOOUT, '-', "Don't print SPKAC"},
+ {"pubkey", OPT_PUBKEY, '-', "Output public key"},
+ {"verify", OPT_VERIFY, '-', "Verify SPKAC signature"},
+ {"spksect", OPT_SPKSECT, 's',
+ "Specify the name of an SPKAC-dedicated section of configuration"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int spkac_main(int argc, char **argv)
+{
+ BIO *out = NULL;
+ CONF *conf = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+ NETSCAPE_SPKI *spki = NULL;
+ char *challenge = NULL, *keyfile = NULL;
+ char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL;
+ char *spkstr = NULL, *prog;
+ const char *spkac = "SPKAC", *spksect = "default";
+ int i, ret = 1, verify = 0, noout = 0, pubkey = 0;
+ int keyformat = FORMAT_PEM;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, spkac_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(spkac_options);
+ ret = 0;
+ goto end;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_PUBKEY:
+ pubkey = 1;
+ break;
+ case OPT_VERIFY:
+ verify = 1;
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_KEY:
+ keyfile = opt_arg();
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
+ goto opthelp;
+ break;
+ case OPT_CHALLENGE:
+ challenge = opt_arg();
+ break;
+ case OPT_SPKAC:
+ spkac = opt_arg();
+ break;
+ case OPT_SPKSECT:
+ spksect = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ if (argc != 0)
+ goto opthelp;
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ if (keyfile != NULL) {
+ pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL,
+ keyformat, 1, passin, e, "private key");
+ if (pkey == NULL)
+ goto end;
+ spki = NETSCAPE_SPKI_new();
+ if (spki == NULL)
+ goto end;
+ if (challenge != NULL)
+ ASN1_STRING_set(spki->spkac->challenge,
+ challenge, (int)strlen(challenge));
+ NETSCAPE_SPKI_set_pubkey(spki, pkey);
+ NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
+ spkstr = NETSCAPE_SPKI_b64_encode(spki);
+ if (spkstr == NULL)
+ goto end;
+
+ out = bio_open_default(outfile, 'w', FORMAT_TEXT);
+ if (out == NULL) {
+ OPENSSL_free(spkstr);
+ goto end;
+ }
+ BIO_printf(out, "SPKAC=%s\n", spkstr);
+ OPENSSL_free(spkstr);
+ ret = 0;
+ goto end;
+ }
+
+ if ((conf = app_load_config(infile)) == NULL)
+ goto end;
+
+ spkstr = NCONF_get_string(conf, spksect, spkac);
+
+ if (spkstr == NULL) {
+ BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
+
+ if (spki == NULL) {
+ BIO_printf(bio_err, "Error loading SPKAC\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ out = bio_open_default(outfile, 'w', FORMAT_TEXT);
+ if (out == NULL)
+ goto end;
+
+ if (!noout)
+ NETSCAPE_SPKI_print(out, spki);
+ pkey = NETSCAPE_SPKI_get_pubkey(spki);
+ if (verify) {
+ i = NETSCAPE_SPKI_verify(spki, pkey);
+ if (i > 0) {
+ BIO_printf(bio_err, "Signature OK\n");
+ } else {
+ BIO_printf(bio_err, "Signature Failure\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+ if (pubkey)
+ PEM_write_bio_PUBKEY(out, pkey);
+
+ ret = 0;
+
+ end:
+ NCONF_free(conf);
+ NETSCAPE_SPKI_free(spki);
+ BIO_free_all(out);
+ EVP_PKEY_free(pkey);
+ release_engine(e);
+ OPENSSL_free(passin);
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/srp.c b/freebsd/crypto/openssl/apps/srp.c
new file mode 100644
index 00000000..0c7dad72
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/srp.c
@@ -0,0 +1,615 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Christophe Renou and Peter Sylvester,
+ * for the EdelKey project.
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_SRP
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <openssl/conf.h>
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/txt_db.h>
+# include <openssl/buffer.h>
+# include <openssl/srp.h>
+# include "apps.h"
+# include "progs.h"
+
+# define BASE_SECTION "srp"
+# define CONFIG_FILE "openssl.cnf"
+
+
+# define ENV_DATABASE "srpvfile"
+# define ENV_DEFAULT_SRP "default_srp"
+
+static int get_index(CA_DB *db, char *id, char type)
+{
+ char **pp;
+ int i;
+ if (id == NULL)
+ return -1;
+ if (type == DB_SRP_INDEX) {
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+ if (pp[DB_srptype][0] == DB_SRP_INDEX
+ && strcmp(id, pp[DB_srpid]) == 0)
+ return i;
+ }
+ } else {
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] != DB_SRP_INDEX
+ && strcmp(id, pp[DB_srpid]) == 0)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static void print_entry(CA_DB *db, int indx, int verbose, char *s)
+{
+ if (indx >= 0 && verbose) {
+ int j;
+ char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx);
+ BIO_printf(bio_err, "%s \"%s\"\n", s, pp[DB_srpid]);
+ for (j = 0; j < DB_NUMBER; j++) {
+ BIO_printf(bio_err, " %d = \"%s\"\n", j, pp[j]);
+ }
+ }
+}
+
+static void print_index(CA_DB *db, int indexindex, int verbose)
+{
+ print_entry(db, indexindex, verbose, "g N entry");
+}
+
+static void print_user(CA_DB *db, int userindex, int verbose)
+{
+ if (verbose > 0) {
+ char **pp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+ if (pp[DB_srptype][0] != 'I') {
+ print_entry(db, userindex, verbose, "User entry");
+ print_entry(db, get_index(db, pp[DB_srpgN], 'I'), verbose,
+ "g N entry");
+ }
+
+ }
+}
+
+static int update_index(CA_DB *db, char **row)
+{
+ char **irow;
+ int i;
+
+ irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row pointers");
+ for (i = 0; i < DB_NUMBER; i++)
+ irow[i] = row[i];
+ irow[DB_NUMBER] = NULL;
+
+ if (!TXT_DB_insert(db->db, irow)) {
+ BIO_printf(bio_err, "failed to update srpvfile\n");
+ BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
+ OPENSSL_free(irow);
+ return 0;
+ }
+ return 1;
+}
+
+static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
+{
+ char *entry = NCONF_get_string(conf, section, tag);
+ if (entry == NULL)
+ BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag);
+ return entry;
+}
+
+static char *srp_verify_user(const char *user, const char *srp_verifier,
+ char *srp_usersalt, const char *g, const char *N,
+ const char *passin, int verbose)
+{
+ char password[1025];
+ PW_CB_DATA cb_tmp;
+ char *verifier = NULL;
+ char *gNid = NULL;
+ int len;
+
+ cb_tmp.prompt_info = user;
+ cb_tmp.password = passin;
+
+ len = password_callback(password, sizeof(password)-1, 0, &cb_tmp);
+ if (len > 0) {
+ password[len] = 0;
+ if (verbose)
+ BIO_printf(bio_err,
+ "Validating\n user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",
+ user, srp_verifier, srp_usersalt, g, N);
+ if (verbose > 1)
+ BIO_printf(bio_err, "Pass %s\n", password);
+
+ OPENSSL_assert(srp_usersalt != NULL);
+ if ((gNid = SRP_create_verifier(user, password, &srp_usersalt,
+ &verifier, N, g)) == NULL) {
+ BIO_printf(bio_err, "Internal error validating SRP verifier\n");
+ } else {
+ if (strcmp(verifier, srp_verifier))
+ gNid = NULL;
+ OPENSSL_free(verifier);
+ }
+ OPENSSL_cleanse(password, len);
+ }
+ return gNid;
+}
+
+static char *srp_create_user(char *user, char **srp_verifier,
+ char **srp_usersalt, char *g, char *N,
+ char *passout, int verbose)
+{
+ char password[1025];
+ PW_CB_DATA cb_tmp;
+ char *gNid = NULL;
+ char *salt = NULL;
+ int len;
+ cb_tmp.prompt_info = user;
+ cb_tmp.password = passout;
+
+ len = password_callback(password, sizeof(password)-1, 1, &cb_tmp);
+ if (len > 0) {
+ password[len] = 0;
+ if (verbose)
+ BIO_printf(bio_err, "Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",
+ user, g, N);
+ if ((gNid = SRP_create_verifier(user, password, &salt,
+ srp_verifier, N, g)) == NULL) {
+ BIO_printf(bio_err, "Internal error creating SRP verifier\n");
+ } else {
+ *srp_usersalt = salt;
+ }
+ OPENSSL_cleanse(password, len);
+ if (verbose > 1)
+ BIO_printf(bio_err, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n",
+ gNid, salt, *srp_verifier);
+
+ }
+ return gNid;
+}
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD,
+ OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO,
+ OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS srp_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"},
+ {"config", OPT_CONFIG, '<', "A config file"},
+ {"name", OPT_NAME, 's', "The particular srp definition to use"},
+ {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"},
+ {"add", OPT_ADD, '-', "Add a user and srp verifier"},
+ {"modify", OPT_MODIFY, '-',
+ "Modify the srp verifier of an existing user"},
+ {"delete", OPT_DELETE, '-', "Delete user from verifier file"},
+ {"list", OPT_LIST, '-', "List users"},
+ {"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"},
+ {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+ OPT_R_OPTIONS,
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {NULL}
+};
+
+int srp_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ CA_DB *db = NULL;
+ CONF *conf = NULL;
+ int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i;
+ int doupdatedb = 0, mode = OPT_ERR;
+ char *user = NULL, *passinarg = NULL, *passoutarg = NULL;
+ char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;
+ char *section = NULL;
+ char **gNrow = NULL, *configfile = NULL;
+ char *srpvfile = NULL, **pp, *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, srp_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(srp_options);
+ ret = 0;
+ goto end;
+ case OPT_VERBOSE:
+ verbose++;
+ break;
+ case OPT_CONFIG:
+ configfile = opt_arg();
+ break;
+ case OPT_NAME:
+ section = opt_arg();
+ break;
+ case OPT_SRPVFILE:
+ srpvfile = opt_arg();
+ break;
+ case OPT_ADD:
+ case OPT_DELETE:
+ case OPT_MODIFY:
+ case OPT_LIST:
+ if (mode != OPT_ERR) {
+ BIO_printf(bio_err,
+ "%s: Only one of -add/-delete/-modify/-list\n",
+ prog);
+ goto opthelp;
+ }
+ mode = o;
+ break;
+ case OPT_GN:
+ gN = opt_arg();
+ break;
+ case OPT_USERINFO:
+ userinfo = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (srpvfile != NULL && configfile != NULL) {
+ BIO_printf(bio_err,
+ "-srpvfile and -configfile cannot be specified together.\n");
+ goto end;
+ }
+ if (mode == OPT_ERR) {
+ BIO_printf(bio_err,
+ "Exactly one of the options -add, -delete, -modify -list must be specified.\n");
+ goto opthelp;
+ }
+ if (mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD) {
+ if (argc == 0) {
+ BIO_printf(bio_err, "Need at least one user.\n");
+ goto opthelp;
+ }
+ user = *argv++;
+ }
+ if ((passinarg != NULL || passoutarg != NULL) && argc != 1) {
+ BIO_printf(bio_err,
+ "-passin, -passout arguments only valid with one user.\n");
+ goto opthelp;
+ }
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if (srpvfile == NULL) {
+ if (configfile == NULL)
+ configfile = default_config_file;
+
+ if (verbose)
+ BIO_printf(bio_err, "Using configuration from %s\n",
+ configfile);
+ conf = app_load_config(configfile);
+ if (conf == NULL)
+ goto end;
+ if (configfile != default_config_file && !app_load_modules(conf))
+ goto end;
+
+ /* Lets get the config section we are using */
+ if (section == NULL) {
+ if (verbose)
+ BIO_printf(bio_err,
+ "trying to read " ENV_DEFAULT_SRP
+ " in " BASE_SECTION "\n");
+
+ section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP);
+ if (section == NULL)
+ goto end;
+ }
+
+ app_RAND_load_conf(conf, BASE_SECTION);
+
+ if (verbose)
+ BIO_printf(bio_err,
+ "trying to read " ENV_DATABASE " in section \"%s\"\n",
+ section);
+
+ srpvfile = lookup_conf(conf, section, ENV_DATABASE);
+ if (srpvfile == NULL)
+ goto end;
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
+ srpvfile);
+
+ db = load_index(srpvfile, NULL);
+ if (db == NULL)
+ goto end;
+
+ /* Lets check some fields */
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] == DB_SRP_INDEX) {
+ maxgN = i;
+ if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0)
+ gNindex = i;
+
+ print_index(db, i, verbose > 1);
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Database initialised\n");
+
+ if (gNindex >= 0) {
+ gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
+ print_entry(db, gNindex, verbose > 1, "Default g and N");
+ } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {
+ BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
+ goto end;
+ } else {
+ if (verbose)
+ BIO_printf(bio_err, "Database has no g N information.\n");
+ gNrow = NULL;
+ }
+
+ if (verbose > 1)
+ BIO_printf(bio_err, "Starting user processing\n");
+
+ while (mode == OPT_LIST || user != NULL) {
+ int userindex = -1;
+
+ if (user != NULL && verbose > 1)
+ BIO_printf(bio_err, "Processing user \"%s\"\n", user);
+ if ((userindex = get_index(db, user, 'U')) >= 0)
+ print_user(db, userindex, (verbose > 0) || mode == OPT_LIST);
+
+ if (mode == OPT_LIST) {
+ if (user == NULL) {
+ BIO_printf(bio_err, "List all users\n");
+
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+ print_user(db, i, 1);
+ } else if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, ignored. t\n", user);
+ errors++;
+ }
+ } else if (mode == OPT_ADD) {
+ if (userindex >= 0) {
+ /* reactivation of a new user */
+ char **row =
+ sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+ BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
+ row[DB_srptype][0] = 'V';
+
+ doupdatedb = 1;
+ } else {
+ char *row[DB_NUMBER];
+ char *gNid;
+ row[DB_srpverifier] = NULL;
+ row[DB_srpsalt] = NULL;
+ row[DB_srpinfo] = NULL;
+ if (!
+ (gNid =
+ srp_create_user(user, &(row[DB_srpverifier]),
+ &(row[DB_srpsalt]),
+ gNrow ? gNrow[DB_srpsalt] : gN,
+ gNrow ? gNrow[DB_srpverifier] : NULL,
+ passout, verbose))) {
+ BIO_printf(bio_err,
+ "Cannot create srp verifier for user \"%s\", operation abandoned .\n",
+ user);
+ errors++;
+ goto end;
+ }
+ row[DB_srpid] = OPENSSL_strdup(user);
+ row[DB_srptype] = OPENSSL_strdup("v");
+ row[DB_srpgN] = OPENSSL_strdup(gNid);
+
+ if ((row[DB_srpid] == NULL)
+ || (row[DB_srpgN] == NULL)
+ || (row[DB_srptype] == NULL)
+ || (row[DB_srpverifier] == NULL)
+ || (row[DB_srpsalt] == NULL)
+ || (userinfo
+ && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL))
+ || !update_index(db, row)) {
+ OPENSSL_free(row[DB_srpid]);
+ OPENSSL_free(row[DB_srpgN]);
+ OPENSSL_free(row[DB_srpinfo]);
+ OPENSSL_free(row[DB_srptype]);
+ OPENSSL_free(row[DB_srpverifier]);
+ OPENSSL_free(row[DB_srpsalt]);
+ goto end;
+ }
+ doupdatedb = 1;
+ }
+ } else if (mode == OPT_MODIFY) {
+ if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, operation ignored.\n",
+ user);
+ errors++;
+ } else {
+
+ char **row =
+ sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+ char type = row[DB_srptype][0];
+ if (type == 'v') {
+ BIO_printf(bio_err,
+ "user \"%s\" already updated, operation ignored.\n",
+ user);
+ errors++;
+ } else {
+ char *gNid;
+
+ if (row[DB_srptype][0] == 'V') {
+ int user_gN;
+ char **irow = NULL;
+ if (verbose)
+ BIO_printf(bio_err,
+ "Verifying password for user \"%s\"\n",
+ user);
+ if ((user_gN =
+ get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
+ irow =
+ sk_OPENSSL_PSTRING_value(db->db->data,
+ userindex);
+
+ if (!srp_verify_user
+ (user, row[DB_srpverifier], row[DB_srpsalt],
+ irow ? irow[DB_srpsalt] : row[DB_srpgN],
+ irow ? irow[DB_srpverifier] : NULL, passin,
+ verbose)) {
+ BIO_printf(bio_err,
+ "Invalid password for user \"%s\", operation abandoned.\n",
+ user);
+ errors++;
+ goto end;
+ }
+ }
+ if (verbose)
+ BIO_printf(bio_err, "Password for user \"%s\" ok.\n",
+ user);
+
+ if (!
+ (gNid =
+ srp_create_user(user, &(row[DB_srpverifier]),
+ &(row[DB_srpsalt]),
+ gNrow ? gNrow[DB_srpsalt] : NULL,
+ gNrow ? gNrow[DB_srpverifier] : NULL,
+ passout, verbose))) {
+ BIO_printf(bio_err,
+ "Cannot create srp verifier for user \"%s\", operation abandoned.\n",
+ user);
+ errors++;
+ goto end;
+ }
+
+ row[DB_srptype][0] = 'v';
+ row[DB_srpgN] = OPENSSL_strdup(gNid);
+
+ if (row[DB_srpid] == NULL
+ || row[DB_srpgN] == NULL
+ || row[DB_srptype] == NULL
+ || row[DB_srpverifier] == NULL
+ || row[DB_srpsalt] == NULL
+ || (userinfo
+ && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo))
+ == NULL)))
+ goto end;
+
+ doupdatedb = 1;
+ }
+ }
+ } else if (mode == OPT_DELETE) {
+ if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, operation ignored. t\n",
+ user);
+ errors++;
+ } else {
+ char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+ BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
+ xpp[DB_srptype][0] = 'R';
+ doupdatedb = 1;
+ }
+ }
+ user = *argv++;
+ if (user == NULL) {
+ /* no more processing in any mode if no users left */
+ break;
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "User procession done.\n");
+
+ if (doupdatedb) {
+ /* Lets check some fields */
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] == 'v') {
+ pp[DB_srptype][0] = 'V';
+ print_user(db, i, verbose);
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Trying to update srpvfile.\n");
+ if (!save_index(srpvfile, "new", db))
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "Temporary srpvfile created.\n");
+ if (!rotate_index(srpvfile, "new", "old"))
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "srpvfile updated.\n");
+ }
+
+ ret = (errors != 0);
+ end:
+ if (errors != 0)
+ if (verbose)
+ BIO_printf(bio_err, "User errors %d.\n", errors);
+
+ if (verbose)
+ BIO_printf(bio_err, "SRP terminating with code %d.\n", ret);
+
+ OPENSSL_free(passin);
+ OPENSSL_free(passout);
+ if (ret)
+ ERR_print_errors(bio_err);
+ NCONF_free(conf);
+ free_index(db);
+ release_engine(e);
+ return ret;
+}
+#endif
diff --git a/freebsd/crypto/openssl/apps/storeutl.c b/freebsd/crypto/openssl/apps/storeutl.c
new file mode 100644
index 00000000..fdbd1511
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/storeutl.c
@@ -0,0 +1,475 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#include "apps.h"
+#include "progs.h"
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/store.h>
+#include <openssl/x509v3.h> /* s2i_ASN1_INTEGER */
+
+static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
+ int expected, int criterion, OSSL_STORE_SEARCH *search,
+ int text, int noout, int recursive, int indent, BIO *out,
+ const char *prog);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
+ OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE,
+ OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
+ OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
+ OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
+ OPT_MD
+} OPTION_CHOICE;
+
+const OPTIONS storeutl_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"text", OPT_TEXT, '-', "Print a text form of the objects"},
+ {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
+ {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
+ {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
+ {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
+ {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"},
+ {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"},
+ {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"},
+ {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"},
+ {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"r", OPT_RECURSIVE, '-', "Recurse through names"},
+ {NULL}
+};
+
+int storeutl_main(int argc, char *argv[])
+{
+ int ret = 1, noout = 0, text = 0, recursive = 0;
+ char *outfile = NULL, *passin = NULL, *passinarg = NULL;
+ BIO *out = NULL;
+ ENGINE *e = NULL;
+ OPTION_CHOICE o;
+ char *prog = opt_init(argc, argv, storeutl_options);
+ PW_CB_DATA pw_cb_data;
+ int expected = 0;
+ int criterion = 0;
+ X509_NAME *subject = NULL, *issuer = NULL;
+ ASN1_INTEGER *serial = NULL;
+ unsigned char *fingerprint = NULL;
+ size_t fingerprintlen = 0;
+ char *alias = NULL;
+ OSSL_STORE_SEARCH *search = NULL;
+ const EVP_MD *digest = NULL;
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(storeutl_options);
+ ret = 0;
+ goto end;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_NOOUT:
+ noout = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_RECURSIVE:
+ recursive = 1;
+ break;
+ case OPT_SEARCHFOR_CERTS:
+ case OPT_SEARCHFOR_KEYS:
+ case OPT_SEARCHFOR_CRLS:
+ if (expected != 0) {
+ BIO_printf(bio_err, "%s: only one search type can be given.\n",
+ prog);
+ goto end;
+ }
+ {
+ static const struct {
+ enum OPTION_choice choice;
+ int type;
+ } map[] = {
+ {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT},
+ {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY},
+ {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL},
+ };
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(map); i++) {
+ if (o == map[i].choice) {
+ expected = map[i].type;
+ break;
+ }
+ }
+ /*
+ * If expected wasn't set at this point, it means the map
+ * isn't syncronised with the possible options leading here.
+ */
+ OPENSSL_assert(expected != 0);
+ }
+ break;
+ case OPT_CRITERION_SUBJECT:
+ if (criterion != 0) {
+ BIO_printf(bio_err, "%s: criterion already given.\n",
+ prog);
+ goto end;
+ }
+ criterion = OSSL_STORE_SEARCH_BY_NAME;
+ if (subject != NULL) {
+ BIO_printf(bio_err, "%s: subject already given.\n",
+ prog);
+ goto end;
+ }
+ if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
+ BIO_printf(bio_err, "%s: can't parse subject argument.\n",
+ prog);
+ goto end;
+ }
+ break;
+ case OPT_CRITERION_ISSUER:
+ if (criterion != 0
+ || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+ && issuer != NULL)) {
+ BIO_printf(bio_err, "%s: criterion already given.\n",
+ prog);
+ goto end;
+ }
+ criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
+ if (issuer != NULL) {
+ BIO_printf(bio_err, "%s: issuer already given.\n",
+ prog);
+ goto end;
+ }
+ if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
+ BIO_printf(bio_err, "%s: can't parse issuer argument.\n",
+ prog);
+ goto end;
+ }
+ break;
+ case OPT_CRITERION_SERIAL:
+ if (criterion != 0
+ || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
+ && serial != NULL)) {
+ BIO_printf(bio_err, "%s: criterion already given.\n",
+ prog);
+ goto end;
+ }
+ criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
+ if (serial != NULL) {
+ BIO_printf(bio_err, "%s: serial number already given.\n",
+ prog);
+ goto end;
+ }
+ if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) {
+ BIO_printf(bio_err, "%s: can't parse serial number argument.\n",
+ prog);
+ goto end;
+ }
+ break;
+ case OPT_CRITERION_FINGERPRINT:
+ if (criterion != 0
+ || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT
+ && fingerprint != NULL)) {
+ BIO_printf(bio_err, "%s: criterion already given.\n",
+ prog);
+ goto end;
+ }
+ criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
+ if (fingerprint != NULL) {
+ BIO_printf(bio_err, "%s: fingerprint already given.\n",
+ prog);
+ goto end;
+ }
+ {
+ long tmplen = 0;
+
+ if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen))
+ == NULL) {
+ BIO_printf(bio_err,
+ "%s: can't parse fingerprint argument.\n",
+ prog);
+ goto end;
+ }
+ fingerprintlen = (size_t)tmplen;
+ }
+ break;
+ case OPT_CRITERION_ALIAS:
+ if (criterion != 0) {
+ BIO_printf(bio_err, "%s: criterion already given.\n",
+ prog);
+ goto end;
+ }
+ criterion = OSSL_STORE_SEARCH_BY_ALIAS;
+ if (alias != NULL) {
+ BIO_printf(bio_err, "%s: alias already given.\n",
+ prog);
+ goto end;
+ }
+ if ((alias = OPENSSL_strdup(opt_arg())) == NULL) {
+ BIO_printf(bio_err, "%s: can't parse alias argument.\n",
+ prog);
+ goto end;
+ }
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_unknown(), &digest))
+ goto opthelp;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (argc == 0) {
+ BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog);
+ goto opthelp;
+ }
+ if (argc > 1) {
+ BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog);
+ goto opthelp;
+ }
+
+ if (criterion != 0) {
+ switch (criterion) {
+ case OSSL_STORE_SEARCH_BY_NAME:
+ if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ break;
+ case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
+ if (issuer == NULL || serial == NULL) {
+ BIO_printf(bio_err,
+ "%s: both -issuer and -serial must be given.\n",
+ prog);
+ goto end;
+ }
+ if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial))
+ == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ break;
+ case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
+ if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest,
+ fingerprint,
+ fingerprintlen))
+ == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ break;
+ case OSSL_STORE_SEARCH_BY_ALIAS:
+ if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ break;
+ }
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+ pw_cb_data.password = passin;
+ pw_cb_data.prompt_info = argv[0];
+
+ out = bio_open_default(outfile, 'w', FORMAT_TEXT);
+ if (out == NULL)
+ goto end;
+
+ ret = process(argv[0], get_ui_method(), &pw_cb_data,
+ expected, criterion, search,
+ text, noout, recursive, 0, out, prog);
+
+ end:
+ OPENSSL_free(fingerprint);
+ OPENSSL_free(alias);
+ ASN1_INTEGER_free(serial);
+ X509_NAME_free(subject);
+ X509_NAME_free(issuer);
+ OSSL_STORE_SEARCH_free(search);
+ BIO_free_all(out);
+ OPENSSL_free(passin);
+ release_engine(e);
+ return ret;
+}
+
+static int indent_printf(int indent, BIO *bio, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+
+ ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args);
+
+ va_end(args);
+ return ret;
+}
+
+static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
+ int expected, int criterion, OSSL_STORE_SEARCH *search,
+ int text, int noout, int recursive, int indent, BIO *out,
+ const char *prog)
+{
+ OSSL_STORE_CTX *store_ctx = NULL;
+ int ret = 1, items = 0;
+
+ if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL))
+ == NULL) {
+ BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
+ ERR_print_errors(bio_err);
+ return ret;
+ }
+
+ if (expected != 0) {
+ if (!OSSL_STORE_expect(store_ctx, expected)) {
+ ERR_print_errors(bio_err);
+ goto end2;
+ }
+ }
+
+ if (criterion != 0) {
+ if (!OSSL_STORE_supports_search(store_ctx, criterion)) {
+ BIO_printf(bio_err,
+ "%s: the store scheme doesn't support the given search criteria.\n",
+ prog);
+ goto end2;
+ }
+
+ if (!OSSL_STORE_find(store_ctx, search)) {
+ ERR_print_errors(bio_err);
+ goto end2;
+ }
+ }
+
+ /* From here on, we count errors, and we'll return the count at the end */
+ ret = 0;
+
+ for (;;) {
+ OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx);
+ int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
+ const char *infostr =
+ info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
+
+ if (info == NULL) {
+ if (OSSL_STORE_eof(store_ctx))
+ break;
+
+ if (OSSL_STORE_error(store_ctx)) {
+ if (recursive)
+ ERR_clear_error();
+ else
+ ERR_print_errors(bio_err);
+ ret++;
+ continue;
+ }
+
+ BIO_printf(bio_err,
+ "ERROR: OSSL_STORE_load() returned NULL without "
+ "eof or error indications\n");
+ BIO_printf(bio_err, " This is an error in the loader\n");
+ ERR_print_errors(bio_err);
+ ret++;
+ break;
+ }
+
+ if (type == OSSL_STORE_INFO_NAME) {
+ const char *name = OSSL_STORE_INFO_get0_NAME(info);
+ const char *desc = OSSL_STORE_INFO_get0_NAME_description(info);
+ indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr,
+ name);
+ if (desc != NULL)
+ indent_printf(indent, bio_out, "%s\n", desc);
+ } else {
+ indent_printf(indent, bio_out, "%d: %s\n", items, infostr);
+ }
+
+ /*
+ * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
+ * functionality, so we must figure out how exactly to write things
+ * ourselves...
+ */
+ switch (type) {
+ case OSSL_STORE_INFO_NAME:
+ if (recursive) {
+ const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
+ ret += process(suburi, uimeth, uidata,
+ expected, criterion, search,
+ text, noout, recursive, indent + 2, out, prog);
+ }
+ break;
+ case OSSL_STORE_INFO_PARAMS:
+ if (text)
+ EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info),
+ 0, NULL);
+ if (!noout)
+ PEM_write_bio_Parameters(out,
+ OSSL_STORE_INFO_get0_PARAMS(info));
+ break;
+ case OSSL_STORE_INFO_PKEY:
+ if (text)
+ EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
+ 0, NULL);
+ if (!noout)
+ PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info),
+ NULL, NULL, 0, NULL, NULL);
+ break;
+ case OSSL_STORE_INFO_CERT:
+ if (text)
+ X509_print(out, OSSL_STORE_INFO_get0_CERT(info));
+ if (!noout)
+ PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info));
+ break;
+ case OSSL_STORE_INFO_CRL:
+ if (text)
+ X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info));
+ if (!noout)
+ PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info));
+ break;
+ default:
+ BIO_printf(bio_err, "!!! Unknown code\n");
+ ret++;
+ break;
+ }
+ items++;
+ OSSL_STORE_INFO_free(info);
+ }
+ indent_printf(indent, out, "Total found: %d\n", items);
+
+ end2:
+ if (!OSSL_STORE_close(store_ctx)) {
+ ERR_print_errors(bio_err);
+ ret++;
+ }
+
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/testdsa.h b/freebsd/crypto/openssl/apps/testdsa.h
new file mode 100644
index 00000000..3c4b459d
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/testdsa.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* used by speed.c */
+DSA *get_dsa(int);
+
+static unsigned char dsa512_priv[] = {
+ 0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c,
+ 0x9c, 0x1d, 0x7a, 0x22, 0xbd, 0xd1, 0xc2, 0xd2,
+};
+
+static unsigned char dsa512_pub[] = {
+ 0x00, 0x95, 0xa7, 0x0d, 0xec, 0x93, 0x68, 0xba, 0x5f, 0xf7, 0x5f, 0x07,
+ 0xf2, 0x3b, 0xad, 0x6b, 0x01, 0xdc, 0xbe, 0xec, 0xde, 0x04, 0x7a, 0x3a,
+ 0x27, 0xb3, 0xec, 0x49, 0xfd, 0x08, 0x43, 0x3d, 0x7e, 0xa8, 0x2c, 0x5e,
+ 0x7b, 0xbb, 0xfc, 0xf4, 0x6e, 0xeb, 0x6c, 0xb0, 0x6e, 0xf8, 0x02, 0x12,
+ 0x8c, 0x38, 0x5d, 0x83, 0x56, 0x7d, 0xee, 0x53, 0x05, 0x3e, 0x24, 0x84,
+ 0xbe, 0xba, 0x0a, 0x6b, 0xc8,
+};
+
+static unsigned char dsa512_p[] = {
+ 0x9D, 0x1B, 0x69, 0x8E, 0x26, 0xDB, 0xF2, 0x2B, 0x11, 0x70, 0x19, 0x86,
+ 0xF6, 0x19, 0xC8, 0xF8, 0x19, 0xF2, 0x18, 0x53, 0x94, 0x46, 0x06, 0xD0,
+ 0x62, 0x50, 0x33, 0x4B, 0x02, 0x3C, 0x52, 0x30, 0x03, 0x8B, 0x3B, 0xF9,
+ 0x5F, 0xD1, 0x24, 0x06, 0x4F, 0x7B, 0x4C, 0xBA, 0xAA, 0x40, 0x9B, 0xFD,
+ 0x96, 0xE4, 0x37, 0x33, 0xBB, 0x2D, 0x5A, 0xD7, 0x5A, 0x11, 0x40, 0x66,
+ 0xA2, 0x76, 0x7D, 0x31,
+};
+
+static unsigned char dsa512_q[] = {
+ 0xFB, 0x53, 0xEF, 0x50, 0xB4, 0x40, 0x92, 0x31, 0x56, 0x86, 0x53, 0x7A,
+ 0xE8, 0x8B, 0x22, 0x9A, 0x49, 0xFB, 0x71, 0x8F,
+};
+
+static unsigned char dsa512_g[] = {
+ 0x83, 0x3E, 0x88, 0xE5, 0xC5, 0x89, 0x73, 0xCE, 0x3B, 0x6C, 0x01, 0x49,
+ 0xBF, 0xB3, 0xC7, 0x9F, 0x0A, 0xEA, 0x44, 0x91, 0xE5, 0x30, 0xAA, 0xD9,
+ 0xBE, 0x5B, 0x5F, 0xB7, 0x10, 0xD7, 0x89, 0xB7, 0x8E, 0x74, 0xFB, 0xCF,
+ 0x29, 0x1E, 0xEB, 0xA8, 0x2C, 0x54, 0x51, 0xB8, 0x10, 0xDE, 0xA0, 0xCE,
+ 0x2F, 0xCC, 0x24, 0x6B, 0x90, 0x77, 0xDE, 0xA2, 0x68, 0xA6, 0x52, 0x12,
+ 0xA2, 0x03, 0x9D, 0x20,
+};
+
+static unsigned char dsa1024_priv[] = {
+ 0x7d, 0x21, 0xda, 0xbb, 0x62, 0x15, 0x47, 0x36, 0x07, 0x67, 0x12, 0xe8,
+ 0x8c, 0xaa, 0x1c, 0xcd, 0x38, 0x12, 0x61, 0x18,
+};
+
+static unsigned char dsa1024_pub[] = {
+ 0x3c, 0x4e, 0x9c, 0x2a, 0x7f, 0x16, 0xc1, 0x25, 0xeb, 0xac, 0x78, 0x63,
+ 0x90, 0x14, 0x8c, 0x8b, 0xf4, 0x68, 0x43, 0x3c, 0x2d, 0xee, 0x65, 0x50,
+ 0x7d, 0x9c, 0x8f, 0x8c, 0x8a, 0x51, 0xd6, 0x11, 0x2b, 0x99, 0xaf, 0x1e,
+ 0x90, 0x97, 0xb5, 0xd3, 0xa6, 0x20, 0x25, 0xd6, 0xfe, 0x43, 0x02, 0xd5,
+ 0x91, 0x7d, 0xa7, 0x8c, 0xdb, 0xc9, 0x85, 0xa3, 0x36, 0x48, 0xf7, 0x68,
+ 0xaa, 0x60, 0xb1, 0xf7, 0x05, 0x68, 0x3a, 0xa3, 0x3f, 0xd3, 0x19, 0x82,
+ 0xd8, 0x82, 0x7a, 0x77, 0xfb, 0xef, 0xf4, 0x15, 0x0a, 0xeb, 0x06, 0x04,
+ 0x7f, 0x53, 0x07, 0x0c, 0xbc, 0xcb, 0x2d, 0x83, 0xdb, 0x3e, 0xd1, 0x28,
+ 0xa5, 0xa1, 0x31, 0xe0, 0x67, 0xfa, 0x50, 0xde, 0x9b, 0x07, 0x83, 0x7e,
+ 0x2c, 0x0b, 0xc3, 0x13, 0x50, 0x61, 0xe5, 0xad, 0xbd, 0x36, 0xb8, 0x97,
+ 0x4e, 0x40, 0x7d, 0xe8, 0x83, 0x0d, 0xbc, 0x4b
+};
+
+static unsigned char dsa1024_p[] = {
+ 0xA7, 0x3F, 0x6E, 0x85, 0xBF, 0x41, 0x6A, 0x29, 0x7D, 0xF0, 0x9F, 0x47,
+ 0x19, 0x30, 0x90, 0x9A, 0x09, 0x1D, 0xDA, 0x6A, 0x33, 0x1E, 0xC5, 0x3D,
+ 0x86, 0x96, 0xB3, 0x15, 0xE0, 0x53, 0x2E, 0x8F, 0xE0, 0x59, 0x82, 0x73,
+ 0x90, 0x3E, 0x75, 0x31, 0x99, 0x47, 0x7A, 0x52, 0xFB, 0x85, 0xE4, 0xD9,
+ 0xA6, 0x7B, 0x38, 0x9B, 0x68, 0x8A, 0x84, 0x9B, 0x87, 0xC6, 0x1E, 0xB5,
+ 0x7E, 0x86, 0x4B, 0x53, 0x5B, 0x59, 0xCF, 0x71, 0x65, 0x19, 0x88, 0x6E,
+ 0xCE, 0x66, 0xAE, 0x6B, 0x88, 0x36, 0xFB, 0xEC, 0x28, 0xDC, 0xC2, 0xD7,
+ 0xA5, 0xBB, 0xE5, 0x2C, 0x39, 0x26, 0x4B, 0xDA, 0x9A, 0x70, 0x18, 0x95,
+ 0x37, 0x95, 0x10, 0x56, 0x23, 0xF6, 0x15, 0xED, 0xBA, 0x04, 0x5E, 0xDE,
+ 0x39, 0x4F, 0xFD, 0xB7, 0x43, 0x1F, 0xB5, 0xA4, 0x65, 0x6F, 0xCD, 0x80,
+ 0x11, 0xE4, 0x70, 0x95, 0x5B, 0x50, 0xCD, 0x49,
+};
+
+static unsigned char dsa1024_q[] = {
+ 0xF7, 0x07, 0x31, 0xED, 0xFA, 0x6C, 0x06, 0x03, 0xD5, 0x85, 0x8A, 0x1C,
+ 0xAC, 0x9C, 0x65, 0xE7, 0x50, 0x66, 0x65, 0x6F,
+};
+
+static unsigned char dsa1024_g[] = {
+ 0x4D, 0xDF, 0x4C, 0x03, 0xA6, 0x91, 0x8A, 0xF5, 0x19, 0x6F, 0x50, 0x46,
+ 0x25, 0x99, 0xE5, 0x68, 0x6F, 0x30, 0xE3, 0x69, 0xE1, 0xE5, 0xB3, 0x5D,
+ 0x98, 0xBB, 0x28, 0x86, 0x48, 0xFC, 0xDE, 0x99, 0x04, 0x3F, 0x5F, 0x88,
+ 0x0C, 0x9C, 0x73, 0x24, 0x0D, 0x20, 0x5D, 0xB9, 0x2A, 0x9A, 0x3F, 0x18,
+ 0x96, 0x27, 0xE4, 0x62, 0x87, 0xC1, 0x7B, 0x74, 0x62, 0x53, 0xFC, 0x61,
+ 0x27, 0xA8, 0x7A, 0x91, 0x09, 0x9D, 0xB6, 0xF1, 0x4D, 0x9C, 0x54, 0x0F,
+ 0x58, 0x06, 0xEE, 0x49, 0x74, 0x07, 0xCE, 0x55, 0x7E, 0x23, 0xCE, 0x16,
+ 0xF6, 0xCA, 0xDC, 0x5A, 0x61, 0x01, 0x7E, 0xC9, 0x71, 0xB5, 0x4D, 0xF6,
+ 0xDC, 0x34, 0x29, 0x87, 0x68, 0xF6, 0x5E, 0x20, 0x93, 0xB3, 0xDB, 0xF5,
+ 0xE4, 0x09, 0x6C, 0x41, 0x17, 0x95, 0x92, 0xEB, 0x01, 0xB5, 0x73, 0xA5,
+ 0x6A, 0x7E, 0xD8, 0x32, 0xED, 0x0E, 0x02, 0xB8,
+};
+
+static unsigned char dsa2048_priv[] = {
+ 0x32, 0x67, 0x92, 0xf6, 0xc4, 0xe2, 0xe2, 0xe8, 0xa0, 0x8b, 0x6b, 0x45,
+ 0x0c, 0x8a, 0x76, 0xb0, 0xee, 0xcf, 0x91, 0xa7,
+};
+
+static unsigned char dsa2048_pub[] = {
+ 0x17, 0x8f, 0xa8, 0x11, 0x84, 0x92, 0xec, 0x83, 0x47, 0xc7, 0x6a, 0xb0,
+ 0x92, 0xaf, 0x5a, 0x20, 0x37, 0xa3, 0x64, 0x79, 0xd2, 0xd0, 0x3d, 0xcd,
+ 0xe0, 0x61, 0x88, 0x88, 0x21, 0xcc, 0x74, 0x5d, 0xce, 0x4c, 0x51, 0x47,
+ 0xf0, 0xc5, 0x5c, 0x4c, 0x82, 0x7a, 0xaf, 0x72, 0xad, 0xb9, 0xe0, 0x53,
+ 0xf2, 0x78, 0xb7, 0xf0, 0xb5, 0x48, 0x7f, 0x8a, 0x3a, 0x18, 0xd1, 0x9f,
+ 0x8b, 0x7d, 0xa5, 0x47, 0xb7, 0x95, 0xab, 0x98, 0xf8, 0x7b, 0x74, 0x50,
+ 0x56, 0x8e, 0x57, 0xf0, 0xee, 0xf5, 0xb7, 0xba, 0xab, 0x85, 0x86, 0xf9,
+ 0x2b, 0xef, 0x41, 0x56, 0xa0, 0xa4, 0x9f, 0xb7, 0x38, 0x00, 0x46, 0x0a,
+ 0xa6, 0xf1, 0xfc, 0x1f, 0xd8, 0x4e, 0x85, 0x44, 0x92, 0x43, 0x21, 0x5d,
+ 0x6e, 0xcc, 0xc2, 0xcb, 0x26, 0x31, 0x0d, 0x21, 0xc4, 0xbd, 0x8d, 0x24,
+ 0xbc, 0xd9, 0x18, 0x19, 0xd7, 0xdc, 0xf1, 0xe7, 0x93, 0x50, 0x48, 0x03,
+ 0x2c, 0xae, 0x2e, 0xe7, 0x49, 0x88, 0x5f, 0x93, 0x57, 0x27, 0x99, 0x36,
+ 0xb4, 0x20, 0xab, 0xfc, 0xa7, 0x2b, 0xf2, 0xd9, 0x98, 0xd7, 0xd4, 0x34,
+ 0x9d, 0x96, 0x50, 0x58, 0x9a, 0xea, 0x54, 0xf3, 0xee, 0xf5, 0x63, 0x14,
+ 0xee, 0x85, 0x83, 0x74, 0x76, 0xe1, 0x52, 0x95, 0xc3, 0xf7, 0xeb, 0x04,
+ 0x04, 0x7b, 0xa7, 0x28, 0x1b, 0xcc, 0xea, 0x4a, 0x4e, 0x84, 0xda, 0xd8,
+ 0x9c, 0x79, 0xd8, 0x9b, 0x66, 0x89, 0x2f, 0xcf, 0xac, 0xd7, 0x79, 0xf9,
+ 0xa9, 0xd8, 0x45, 0x13, 0x78, 0xb9, 0x00, 0x14, 0xc9, 0x7e, 0x22, 0x51,
+ 0x86, 0x67, 0xb0, 0x9f, 0x26, 0x11, 0x23, 0xc8, 0x38, 0xd7, 0x70, 0x1d,
+ 0x15, 0x8e, 0x4d, 0x4f, 0x95, 0x97, 0x40, 0xa1, 0xc2, 0x7e, 0x01, 0x18,
+ 0x72, 0xf4, 0x10, 0xe6, 0x8d, 0x52, 0x16, 0x7f, 0xf2, 0xc9, 0xf8, 0x33,
+ 0x8b, 0x33, 0xb7, 0xce,
+};
+
+static unsigned char dsa2048_p[] = {
+ 0xA0, 0x25, 0xFA, 0xAD, 0xF4, 0x8E, 0xB9, 0xE5, 0x99, 0xF3, 0x5D, 0x6F,
+ 0x4F, 0x83, 0x34, 0xE2, 0x7E, 0xCF, 0x6F, 0xBF, 0x30, 0xAF, 0x6F, 0x81,
+ 0xEB, 0xF8, 0xC4, 0x13, 0xD9, 0xA0, 0x5D, 0x8B, 0x5C, 0x8E, 0xDC, 0xC2,
+ 0x1D, 0x0B, 0x41, 0x32, 0xB0, 0x1F, 0xFE, 0xEF, 0x0C, 0xC2, 0xA2, 0x7E,
+ 0x68, 0x5C, 0x28, 0x21, 0xE9, 0xF5, 0xB1, 0x58, 0x12, 0x63, 0x4C, 0x19,
+ 0x4E, 0xFF, 0x02, 0x4B, 0x92, 0xED, 0xD2, 0x07, 0x11, 0x4D, 0x8C, 0x58,
+ 0x16, 0x5C, 0x55, 0x8E, 0xAD, 0xA3, 0x67, 0x7D, 0xB9, 0x86, 0x6E, 0x0B,
+ 0xE6, 0x54, 0x6F, 0x40, 0xAE, 0x0E, 0x67, 0x4C, 0xF9, 0x12, 0x5B, 0x3C,
+ 0x08, 0x7A, 0xF7, 0xFC, 0x67, 0x86, 0x69, 0xE7, 0x0A, 0x94, 0x40, 0xBF,
+ 0x8B, 0x76, 0xFE, 0x26, 0xD1, 0xF2, 0xA1, 0x1A, 0x84, 0xA1, 0x43, 0x56,
+ 0x28, 0xBC, 0x9A, 0x5F, 0xD7, 0x3B, 0x69, 0x89, 0x8A, 0x36, 0x2C, 0x51,
+ 0xDF, 0x12, 0x77, 0x2F, 0x57, 0x7B, 0xA0, 0xAA, 0xDD, 0x7F, 0xA1, 0x62,
+ 0x3B, 0x40, 0x7B, 0x68, 0x1A, 0x8F, 0x0D, 0x38, 0xBB, 0x21, 0x5D, 0x18,
+ 0xFC, 0x0F, 0x46, 0xF7, 0xA3, 0xB0, 0x1D, 0x23, 0xC3, 0xD2, 0xC7, 0x72,
+ 0x51, 0x18, 0xDF, 0x46, 0x95, 0x79, 0xD9, 0xBD, 0xB5, 0x19, 0x02, 0x2C,
+ 0x87, 0xDC, 0xE7, 0x57, 0x82, 0x7E, 0xF1, 0x8B, 0x06, 0x3D, 0x00, 0xA5,
+ 0x7B, 0x6B, 0x26, 0x27, 0x91, 0x0F, 0x6A, 0x77, 0xE4, 0xD5, 0x04, 0xE4,
+ 0x12, 0x2C, 0x42, 0xFF, 0xD2, 0x88, 0xBB, 0xD3, 0x92, 0xA0, 0xF9, 0xC8,
+ 0x51, 0x64, 0x14, 0x5C, 0xD8, 0xF9, 0x6C, 0x47, 0x82, 0xB4, 0x1C, 0x7F,
+ 0x09, 0xB8, 0xF0, 0x25, 0x83, 0x1D, 0x3F, 0x3F, 0x05, 0xB3, 0x21, 0x0A,
+ 0x5D, 0xA7, 0xD8, 0x54, 0xC3, 0x65, 0x7D, 0xC3, 0xB0, 0x1D, 0xBF, 0xAE,
+ 0xF8, 0x68, 0xCF, 0x9B,
+};
+
+static unsigned char dsa2048_q[] = {
+ 0x97, 0xE7, 0x33, 0x4D, 0xD3, 0x94, 0x3E, 0x0B, 0xDB, 0x62, 0x74, 0xC6,
+ 0xA1, 0x08, 0xDD, 0x19, 0xA3, 0x75, 0x17, 0x1B,
+};
+
+static unsigned char dsa2048_g[] = {
+ 0x2C, 0x78, 0x16, 0x59, 0x34, 0x63, 0xF4, 0xF3, 0x92, 0xFC, 0xB5, 0xA5,
+ 0x4F, 0x13, 0xDE, 0x2F, 0x1C, 0xA4, 0x3C, 0xAE, 0xAD, 0x38, 0x3F, 0x7E,
+ 0x90, 0xBF, 0x96, 0xA6, 0xAE, 0x25, 0x90, 0x72, 0xF5, 0x8E, 0x80, 0x0C,
+ 0x39, 0x1C, 0xD9, 0xEC, 0xBA, 0x90, 0x5B, 0x3A, 0xE8, 0x58, 0x6C, 0x9E,
+ 0x30, 0x42, 0x37, 0x02, 0x31, 0x82, 0xBC, 0x6A, 0xDF, 0x6A, 0x09, 0x29,
+ 0xE3, 0xC0, 0x46, 0xD1, 0xCB, 0x85, 0xEC, 0x0C, 0x30, 0x5E, 0xEA, 0xC8,
+ 0x39, 0x8E, 0x22, 0x9F, 0x22, 0x10, 0xD2, 0x34, 0x61, 0x68, 0x37, 0x3D,
+ 0x2E, 0x4A, 0x5B, 0x9A, 0xF5, 0xC1, 0x48, 0xC6, 0xF6, 0xDC, 0x63, 0x1A,
+ 0xD3, 0x96, 0x64, 0xBA, 0x34, 0xC9, 0xD1, 0xA0, 0xD1, 0xAE, 0x6C, 0x2F,
+ 0x48, 0x17, 0x93, 0x14, 0x43, 0xED, 0xF0, 0x21, 0x30, 0x19, 0xC3, 0x1B,
+ 0x5F, 0xDE, 0xA3, 0xF0, 0x70, 0x78, 0x18, 0xE1, 0xA8, 0xE4, 0xEE, 0x2E,
+ 0x00, 0xA5, 0xE4, 0xB3, 0x17, 0xC8, 0x0C, 0x7D, 0x6E, 0x42, 0xDC, 0xB7,
+ 0x46, 0x00, 0x36, 0x4D, 0xD4, 0x46, 0xAA, 0x3D, 0x3C, 0x46, 0x89, 0x40,
+ 0xBF, 0x1D, 0x84, 0x77, 0x0A, 0x75, 0xF3, 0x87, 0x1D, 0x08, 0x4C, 0xA6,
+ 0xD1, 0xA9, 0x1C, 0x1E, 0x12, 0x1E, 0xE1, 0xC7, 0x30, 0x28, 0x76, 0xA5,
+ 0x7F, 0x6C, 0x85, 0x96, 0x2B, 0x6F, 0xDB, 0x80, 0x66, 0x26, 0xAE, 0xF5,
+ 0x93, 0xC7, 0x8E, 0xAE, 0x9A, 0xED, 0xE4, 0xCA, 0x04, 0xEA, 0x3B, 0x72,
+ 0xEF, 0xDC, 0x87, 0xED, 0x0D, 0xA5, 0x4C, 0x4A, 0xDD, 0x71, 0x22, 0x64,
+ 0x59, 0x69, 0x4E, 0x8E, 0xBF, 0x43, 0xDC, 0xAB, 0x8E, 0x66, 0xBB, 0x01,
+ 0xB6, 0xF4, 0xE7, 0xFD, 0xD2, 0xAD, 0x9F, 0x36, 0xC1, 0xA0, 0x29, 0x99,
+ 0xD1, 0x96, 0x70, 0x59, 0x06, 0x78, 0x35, 0xBD, 0x65, 0x55, 0x52, 0x9E,
+ 0xF8, 0xB2, 0xE5, 0x38,
+};
+
+typedef struct testdsa_st {
+ unsigned char *priv;
+ unsigned char *pub;
+ unsigned char *p;
+ unsigned char *g;
+ unsigned char *q;
+ int priv_l;
+ int pub_l;
+ int p_l;
+ int g_l;
+ int q_l;
+} testdsa;
+
+#define set_dsa_ptr(st, bits) \
+ do { \
+ st.priv = dsa##bits##_priv; \
+ st.pub = dsa##bits##_pub; \
+ st.p = dsa##bits##_p; \
+ st.g = dsa##bits##_g; \
+ st.q = dsa##bits##_q; \
+ st.priv_l = sizeof(dsa##bits##_priv); \
+ st.pub_l = sizeof(dsa##bits##_pub); \
+ st.p_l = sizeof(dsa##bits##_p); \
+ st.g_l = sizeof(dsa##bits##_g); \
+ st.q_l = sizeof(dsa##bits##_q); \
+ } while (0)
+
+DSA *get_dsa(int dsa_bits)
+{
+ DSA *dsa;
+ BIGNUM *priv_key, *pub_key, *p, *q, *g;
+ testdsa dsa_t;
+
+ switch (dsa_bits) {
+ case 512:
+ set_dsa_ptr(dsa_t, 512);
+ break;
+ case 1024:
+ set_dsa_ptr(dsa_t, 1024);
+ break;
+ case 2048:
+ set_dsa_ptr(dsa_t, 2048);
+ break;
+ default:
+ return NULL;
+ }
+
+ if ((dsa = DSA_new()) == NULL)
+ return NULL;
+ priv_key = BN_bin2bn(dsa_t.priv, dsa_t.priv_l, NULL);
+ pub_key = BN_bin2bn(dsa_t.pub, dsa_t.pub_l, NULL);
+ p = BN_bin2bn(dsa_t.p, dsa_t.p_l, NULL);
+ q = BN_bin2bn(dsa_t.q, dsa_t.q_l, NULL);
+ g = BN_bin2bn(dsa_t.g, dsa_t.g_l, NULL);
+ if ((priv_key == NULL) || (pub_key == NULL) || (p == NULL) || (q == NULL)
+ || (g == NULL)) {
+ goto err;
+ }
+ if (!DSA_set0_pqg(dsa, p, q, g))
+ goto err;
+
+ if (!DSA_set0_key(dsa, pub_key, priv_key))
+ goto err;
+
+ return dsa;
+ err:
+ DSA_free(dsa);
+ BN_free(priv_key);
+ BN_free(pub_key);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ return NULL;
+}
diff --git a/freebsd/crypto/openssl/apps/testrsa.h b/freebsd/crypto/openssl/apps/testrsa.h
new file mode 100644
index 00000000..1350ce54
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/testrsa.h
@@ -0,0 +1,1960 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+static unsigned char test512[] = {
+ 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+ 0xd6, 0x33, 0xb9, 0xc8, 0xfb, 0x4f, 0x3c, 0x7d, 0xc0, 0x01,
+ 0x86, 0xd0, 0xe7, 0xa0, 0x55, 0xf2, 0x95, 0x93, 0xcc, 0x4f,
+ 0xb7, 0x5b, 0x67, 0x5b, 0x94, 0x68, 0xc9, 0x34, 0x15, 0xde,
+ 0xa5, 0x2e, 0x1c, 0x33, 0xc2, 0x6e, 0xfc, 0x34, 0x5e, 0x71,
+ 0x13, 0xb7, 0xd6, 0xee, 0xd8, 0xa5, 0x65, 0x05, 0x72, 0x87,
+ 0xa8, 0xb0, 0x77, 0xfe, 0x57, 0xf5, 0xfc, 0x5f, 0x55, 0x83,
+ 0x87, 0xdd, 0x57, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x41, 0x00, 0xa7, 0xf7, 0x91, 0xc5, 0x0f, 0x84, 0x57, 0xdc,
+ 0x07, 0xf7, 0x6a, 0x7f, 0x60, 0x52, 0xb3, 0x72, 0xf1, 0x66,
+ 0x1f, 0x7d, 0x97, 0x3b, 0x9e, 0xb6, 0x0a, 0x8f, 0x8c, 0xcf,
+ 0x42, 0x23, 0x00, 0x04, 0xd4, 0x28, 0x0e, 0x1c, 0x90, 0xc4,
+ 0x11, 0x25, 0x25, 0xa5, 0x93, 0xa5, 0x2f, 0x70, 0x02, 0xdf,
+ 0x81, 0x9c, 0x49, 0x03, 0xa0, 0xf8, 0x6d, 0x54, 0x2e, 0x26,
+ 0xde, 0xaa, 0x85, 0x59, 0xa8, 0x31, 0x02, 0x21, 0x00, 0xeb,
+ 0x47, 0xd7, 0x3b, 0xf6, 0xc3, 0xdd, 0x5a, 0x46, 0xc5, 0xb9,
+ 0x2b, 0x9a, 0xa0, 0x09, 0x8f, 0xa6, 0xfb, 0xf3, 0x78, 0x7a,
+ 0x33, 0x70, 0x9d, 0x0f, 0x42, 0x6b, 0x13, 0x68, 0x24, 0xd3,
+ 0x15, 0x02, 0x21, 0x00, 0xe9, 0x10, 0xb0, 0xb3, 0x0d, 0xe2,
+ 0x82, 0x68, 0x77, 0x8a, 0x6e, 0x7c, 0xda, 0xbc, 0x3e, 0x53,
+ 0x83, 0xfb, 0xd6, 0x22, 0xe7, 0xb5, 0xae, 0x6e, 0x80, 0xda,
+ 0x00, 0x55, 0x97, 0xc1, 0xd0, 0x65, 0x02, 0x20, 0x4c, 0xf8,
+ 0x73, 0xb1, 0x6a, 0x49, 0x29, 0x61, 0x1f, 0x46, 0x10, 0x0d,
+ 0xf3, 0xc7, 0xe7, 0x58, 0xd7, 0x88, 0x15, 0x5e, 0x94, 0x9b,
+ 0xbf, 0x7b, 0xa2, 0x42, 0x58, 0x45, 0x41, 0x0c, 0xcb, 0x01,
+ 0x02, 0x20, 0x12, 0x11, 0xba, 0x31, 0x57, 0x9d, 0x3d, 0x11,
+ 0x0e, 0x5b, 0x8c, 0x2f, 0x5f, 0xe2, 0x02, 0x4f, 0x05, 0x47,
+ 0x8c, 0x15, 0x8e, 0xb3, 0x56, 0x3f, 0xb8, 0xfb, 0xad, 0xd4,
+ 0xf4, 0xfc, 0x10, 0xc5, 0x02, 0x20, 0x18, 0xa1, 0x29, 0x99,
+ 0x5b, 0xd9, 0xc8, 0xd4, 0xfc, 0x49, 0x7a, 0x2a, 0x21, 0x2c,
+ 0x49, 0xe4, 0x4f, 0xeb, 0xef, 0x51, 0xf1, 0xab, 0x6d, 0xfb,
+ 0x4b, 0x14, 0xe9, 0x4b, 0x52, 0xb5, 0x82, 0x2c,
+};
+
+static unsigned char test1024[] = {
+ 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+ 0x00, 0xdc, 0x98, 0x43, 0xe8, 0x3d, 0x43, 0x5b, 0xe4, 0x05,
+ 0xcd, 0xd0, 0xa9, 0x3e, 0xcb, 0x83, 0x75, 0xf6, 0xb5, 0xa5,
+ 0x9f, 0x6b, 0xe9, 0x34, 0x41, 0x29, 0x18, 0xfa, 0x6a, 0x55,
+ 0x4d, 0x70, 0xfc, 0xec, 0xae, 0x87, 0x38, 0x0a, 0x20, 0xa9,
+ 0xc0, 0x45, 0x77, 0x6e, 0x57, 0x60, 0x57, 0xf4, 0xed, 0x96,
+ 0x22, 0xcb, 0x8f, 0xe1, 0x33, 0x3a, 0x17, 0x1f, 0xed, 0x37,
+ 0xa5, 0x6f, 0xeb, 0xa6, 0xbc, 0x12, 0x80, 0x1d, 0x53, 0xbd,
+ 0x70, 0xeb, 0x21, 0x76, 0x3e, 0xc9, 0x2f, 0x1a, 0x45, 0x24,
+ 0x82, 0xff, 0xcd, 0x59, 0x32, 0x06, 0x2e, 0x12, 0x3b, 0x23,
+ 0x78, 0xed, 0x12, 0x3d, 0xe0, 0x8d, 0xf9, 0x67, 0x4f, 0x37,
+ 0x4e, 0x47, 0x02, 0x4c, 0x2d, 0xc0, 0x4f, 0x1f, 0xb3, 0x94,
+ 0xe1, 0x41, 0x2e, 0x2d, 0x90, 0x10, 0xfc, 0x82, 0x91, 0x8b,
+ 0x0f, 0x22, 0xd4, 0xf2, 0xfc, 0x2c, 0xab, 0x53, 0x55, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x2b, 0xcc, 0x3f,
+ 0x8f, 0x58, 0xba, 0x8b, 0x00, 0x16, 0xf6, 0xea, 0x3a, 0xf0,
+ 0x30, 0xd0, 0x05, 0x17, 0xda, 0xb0, 0xeb, 0x9a, 0x2d, 0x4f,
+ 0x26, 0xb0, 0xd6, 0x38, 0xc1, 0xeb, 0xf5, 0xd8, 0x3d, 0x1f,
+ 0x70, 0xf7, 0x7f, 0xf4, 0xe2, 0xcf, 0x51, 0x51, 0x79, 0x88,
+ 0xfa, 0xe8, 0x32, 0x0e, 0x7b, 0x2d, 0x97, 0xf2, 0xfa, 0xba,
+ 0x27, 0xc5, 0x9c, 0xd9, 0xc5, 0xeb, 0x8a, 0x79, 0x52, 0x3c,
+ 0x64, 0x34, 0x7d, 0xc2, 0xcf, 0x28, 0xc7, 0x4e, 0xd5, 0x43,
+ 0x0b, 0xd1, 0xa6, 0xca, 0x6d, 0x03, 0x2d, 0x72, 0x23, 0xbc,
+ 0x6d, 0x05, 0xfa, 0x16, 0x09, 0x2f, 0x2e, 0x5c, 0xb6, 0xee,
+ 0x74, 0xdd, 0xd2, 0x48, 0x8e, 0x36, 0x0c, 0x06, 0x3d, 0x4d,
+ 0xe5, 0x10, 0x82, 0xeb, 0x6a, 0xf3, 0x4b, 0x9f, 0xd6, 0xed,
+ 0x11, 0xb1, 0x6e, 0xec, 0xf4, 0xfe, 0x8e, 0x75, 0x94, 0x20,
+ 0x2f, 0xcb, 0xac, 0x46, 0xf1, 0x02, 0x41, 0x00, 0xf9, 0x8c,
+ 0xa3, 0x85, 0xb1, 0xdd, 0x29, 0xaf, 0x65, 0xc1, 0x33, 0xf3,
+ 0x95, 0xc5, 0x52, 0x68, 0x0b, 0xd4, 0xf1, 0xe5, 0x0e, 0x02,
+ 0x9f, 0x4f, 0xfa, 0x77, 0xdc, 0x46, 0x9e, 0xc7, 0xa6, 0xe4,
+ 0x16, 0x29, 0xda, 0xb0, 0x07, 0xcf, 0x5b, 0xa9, 0x12, 0x8a,
+ 0xdd, 0x63, 0x0a, 0xde, 0x2e, 0x8c, 0x66, 0x8b, 0x8c, 0xdc,
+ 0x19, 0xa3, 0x7e, 0xf4, 0x3b, 0xd0, 0x1a, 0x8c, 0xa4, 0xc2,
+ 0xe1, 0xd3, 0x02, 0x41, 0x00, 0xe2, 0x4c, 0x05, 0xf2, 0x04,
+ 0x86, 0x4e, 0x61, 0x43, 0xdb, 0xb0, 0xb9, 0x96, 0x86, 0x52,
+ 0x2c, 0xca, 0x8d, 0x7b, 0xab, 0x0b, 0x13, 0x0d, 0x7e, 0x38,
+ 0x5b, 0xe2, 0x2e, 0x7b, 0x0e, 0xe7, 0x19, 0x99, 0x38, 0xe7,
+ 0xf2, 0x21, 0xbd, 0x85, 0x85, 0xe3, 0xfd, 0x28, 0x77, 0x20,
+ 0x31, 0x71, 0x2c, 0xd0, 0xff, 0xfb, 0x2e, 0xaf, 0x85, 0xb4,
+ 0x86, 0xca, 0xf3, 0xbb, 0xca, 0xaa, 0x0f, 0x95, 0x37, 0x02,
+ 0x40, 0x0e, 0x41, 0x9a, 0x95, 0xe8, 0xb3, 0x59, 0xce, 0x4b,
+ 0x61, 0xde, 0x35, 0xec, 0x38, 0x79, 0x9c, 0xb8, 0x10, 0x52,
+ 0x41, 0x63, 0xab, 0x82, 0xae, 0x6f, 0x00, 0xa9, 0xf4, 0xde,
+ 0xdd, 0x49, 0x0b, 0x7e, 0xb8, 0xa5, 0x65, 0xa9, 0x0c, 0x8f,
+ 0x8f, 0xf9, 0x1f, 0x35, 0xc6, 0x92, 0xb8, 0x5e, 0xb0, 0x66,
+ 0xab, 0x52, 0x40, 0xc0, 0xb6, 0x36, 0x6a, 0x7d, 0x80, 0x46,
+ 0x04, 0x02, 0xe5, 0x9f, 0x41, 0x02, 0x41, 0x00, 0xc0, 0xad,
+ 0xcc, 0x4e, 0x21, 0xee, 0x1d, 0x24, 0x91, 0xfb, 0xa7, 0x80,
+ 0x8d, 0x9a, 0xb6, 0xb3, 0x2e, 0x8f, 0xc2, 0xe1, 0x82, 0xdf,
+ 0x69, 0x18, 0xb4, 0x71, 0xff, 0xa6, 0x65, 0xde, 0xed, 0x84,
+ 0x8d, 0x42, 0xb7, 0xb3, 0x21, 0x69, 0x56, 0x1c, 0x07, 0x60,
+ 0x51, 0x29, 0x04, 0xff, 0x34, 0x06, 0xdd, 0xb9, 0x67, 0x2c,
+ 0x7c, 0x04, 0x93, 0x0e, 0x46, 0x15, 0xbb, 0x2a, 0xb7, 0x1b,
+ 0xe7, 0x87, 0x02, 0x40, 0x78, 0xda, 0x5d, 0x07, 0x51, 0x0c,
+ 0x16, 0x7a, 0x9f, 0x29, 0x20, 0x84, 0x0d, 0x42, 0xfa, 0xd7,
+ 0x00, 0xd8, 0x77, 0x7e, 0xb0, 0xb0, 0x6b, 0xd6, 0x5b, 0x53,
+ 0xb8, 0x9b, 0x7a, 0xcd, 0xc7, 0x2b, 0xb8, 0x6a, 0x63, 0xa9,
+ 0xfb, 0x6f, 0xa4, 0x72, 0xbf, 0x4c, 0x5d, 0x00, 0x14, 0xba,
+ 0xfa, 0x59, 0x88, 0xed, 0xe4, 0xe0, 0x8c, 0xa2, 0xec, 0x14,
+ 0x7e, 0x2d, 0xe2, 0xf0, 0x46, 0x49, 0x95, 0x45,
+};
+
+static unsigned char test2048[] = {
+ 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
+ 0x01, 0x00, 0xc0, 0xc0, 0xce, 0x3e, 0x3c, 0x53, 0x67, 0x3f,
+ 0x4f, 0xc5, 0x2f, 0xa4, 0xc2, 0x5a, 0x2f, 0x58, 0xfd, 0x27,
+ 0x52, 0x6a, 0xe8, 0xcf, 0x4a, 0x73, 0x47, 0x8d, 0x25, 0x0f,
+ 0x5f, 0x03, 0x26, 0x78, 0xef, 0xf0, 0x22, 0x12, 0xd3, 0xde,
+ 0x47, 0xb2, 0x1c, 0x0b, 0x38, 0x63, 0x1a, 0x6c, 0x85, 0x7a,
+ 0x80, 0xc6, 0x8f, 0xa0, 0x41, 0xaf, 0x62, 0xc4, 0x67, 0x32,
+ 0x88, 0xf8, 0xa6, 0x9c, 0xf5, 0x23, 0x1d, 0xe4, 0xac, 0x3f,
+ 0x29, 0xf9, 0xec, 0xe1, 0x8b, 0x26, 0x03, 0x2c, 0xb2, 0xab,
+ 0xf3, 0x7d, 0xb5, 0xca, 0x49, 0xc0, 0x8f, 0x1c, 0xdf, 0x33,
+ 0x3a, 0x60, 0xda, 0x3c, 0xb0, 0x16, 0xf8, 0xa9, 0x12, 0x8f,
+ 0x64, 0xac, 0x23, 0x0c, 0x69, 0x64, 0x97, 0x5d, 0x99, 0xd4,
+ 0x09, 0x83, 0x9b, 0x61, 0xd3, 0xac, 0xf0, 0xde, 0xdd, 0x5e,
+ 0x9f, 0x44, 0x94, 0xdb, 0x3a, 0x4d, 0x97, 0xe8, 0x52, 0x29,
+ 0xf7, 0xdb, 0x94, 0x07, 0x45, 0x90, 0x78, 0x1e, 0x31, 0x0b,
+ 0x80, 0xf7, 0x57, 0xad, 0x1c, 0x79, 0xc5, 0xcb, 0x32, 0xb0,
+ 0xce, 0xcd, 0x74, 0xb3, 0xe2, 0x94, 0xc5, 0x78, 0x2f, 0x34,
+ 0x1a, 0x45, 0xf7, 0x8c, 0x52, 0xa5, 0xbc, 0x8d, 0xec, 0xd1,
+ 0x2f, 0x31, 0x3b, 0xf0, 0x49, 0x59, 0x5e, 0x88, 0x9d, 0x15,
+ 0x92, 0x35, 0x32, 0xc1, 0xe7, 0x61, 0xec, 0x50, 0x48, 0x7c,
+ 0xba, 0x05, 0xf9, 0xf8, 0xf8, 0xa7, 0x8c, 0x83, 0xe8, 0x66,
+ 0x5b, 0xeb, 0xfe, 0xd8, 0x4f, 0xdd, 0x6d, 0x36, 0xc0, 0xb2,
+ 0x90, 0x0f, 0xb8, 0x52, 0xf9, 0x04, 0x9b, 0x40, 0x2c, 0x27,
+ 0xd6, 0x36, 0x8e, 0xc2, 0x1b, 0x44, 0xf3, 0x92, 0xd5, 0x15,
+ 0x9e, 0x9a, 0xbc, 0xf3, 0x7d, 0x03, 0xd7, 0x02, 0x14, 0x20,
+ 0xe9, 0x10, 0x92, 0xfd, 0xf9, 0xfc, 0x8f, 0xe5, 0x18, 0xe1,
+ 0x95, 0xcc, 0x9e, 0x60, 0xa6, 0xfa, 0x38, 0x4d, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x00, 0xc3, 0xc3,
+ 0x0d, 0xb4, 0x27, 0x90, 0x8d, 0x4b, 0xbf, 0xb8, 0x84, 0xaa,
+ 0xd0, 0xb8, 0xc7, 0x5d, 0x99, 0xbe, 0x55, 0xf6, 0x3e, 0x7c,
+ 0x49, 0x20, 0xcb, 0x8a, 0x8e, 0x19, 0x0e, 0x66, 0x24, 0xac,
+ 0xaf, 0x03, 0x33, 0x97, 0xeb, 0x95, 0xd5, 0x3b, 0x0f, 0x40,
+ 0x56, 0x04, 0x50, 0xd1, 0xe6, 0xbe, 0x84, 0x0b, 0x25, 0xd3,
+ 0x9c, 0xe2, 0x83, 0x6c, 0xf5, 0x62, 0x5d, 0xba, 0x2b, 0x7d,
+ 0x3d, 0x7a, 0x6c, 0xe1, 0xd2, 0x0e, 0x54, 0x93, 0x80, 0x01,
+ 0x91, 0x51, 0x09, 0xe8, 0x5b, 0x8e, 0x47, 0xbd, 0x64, 0xe4,
+ 0x0e, 0x03, 0x83, 0x55, 0xcf, 0x5a, 0x37, 0xf0, 0x25, 0xb5,
+ 0x7d, 0x21, 0xd7, 0x69, 0xdf, 0x6f, 0xc2, 0xcf, 0x10, 0xc9,
+ 0x8a, 0x40, 0x9f, 0x7a, 0x70, 0xc0, 0xe8, 0xe8, 0xc0, 0xe6,
+ 0x9a, 0x15, 0x0a, 0x8d, 0x4e, 0x46, 0xcb, 0x7a, 0xdb, 0xb3,
+ 0xcb, 0x83, 0x02, 0xc4, 0xf0, 0xab, 0xeb, 0x02, 0x01, 0x0e,
+ 0x23, 0xfc, 0x1d, 0xc4, 0xbd, 0xd4, 0xaa, 0x5d, 0x31, 0x46,
+ 0x99, 0xce, 0x9e, 0xf8, 0x04, 0x75, 0x10, 0x67, 0xc4, 0x53,
+ 0x47, 0x44, 0xfa, 0xc2, 0x25, 0x73, 0x7e, 0xd0, 0x8e, 0x59,
+ 0xd1, 0xb2, 0x5a, 0xf4, 0xc7, 0x18, 0x92, 0x2f, 0x39, 0xab,
+ 0xcd, 0xa3, 0xb5, 0xc2, 0xb9, 0xc7, 0xb9, 0x1b, 0x9f, 0x48,
+ 0xfa, 0x13, 0xc6, 0x98, 0x4d, 0xca, 0x84, 0x9c, 0x06, 0xca,
+ 0xe7, 0x89, 0x01, 0x04, 0xc4, 0x6c, 0xfd, 0x29, 0x59, 0x35,
+ 0xe7, 0xf3, 0xdd, 0xce, 0x64, 0x59, 0xbf, 0x21, 0x13, 0xa9,
+ 0x9f, 0x0e, 0xc5, 0xff, 0xbd, 0x33, 0x00, 0xec, 0xac, 0x6b,
+ 0x11, 0xef, 0x51, 0x5e, 0xad, 0x07, 0x15, 0xde, 0xb8, 0x5f,
+ 0xc6, 0xb9, 0xa3, 0x22, 0x65, 0x46, 0x83, 0x14, 0xdf, 0xd0,
+ 0xf1, 0x44, 0x8a, 0xe1, 0x9c, 0x23, 0x33, 0xb4, 0x97, 0x33,
+ 0xe6, 0x6b, 0x81, 0x02, 0x81, 0x81, 0x00, 0xec, 0x12, 0xa7,
+ 0x59, 0x74, 0x6a, 0xde, 0x3e, 0xad, 0xd8, 0x36, 0x80, 0x50,
+ 0xa2, 0xd5, 0x21, 0x81, 0x07, 0xf1, 0xd0, 0x91, 0xf2, 0x6c,
+ 0x12, 0x2f, 0x9d, 0x1a, 0x26, 0xf8, 0x30, 0x65, 0xdf, 0xe8,
+ 0xc0, 0x9b, 0x6a, 0x30, 0x98, 0x82, 0x87, 0xec, 0xa2, 0x56,
+ 0x87, 0x62, 0x6f, 0xe7, 0x9f, 0xf6, 0x56, 0xe6, 0x71, 0x8f,
+ 0x49, 0x86, 0x93, 0x5a, 0x4d, 0x34, 0x58, 0xfe, 0xd9, 0x04,
+ 0x13, 0xaf, 0x79, 0xb7, 0xad, 0x11, 0xd1, 0x30, 0x9a, 0x14,
+ 0x06, 0xa0, 0xfa, 0xb7, 0x55, 0xdc, 0x6c, 0x5a, 0x4c, 0x2c,
+ 0x59, 0x56, 0xf6, 0xe8, 0x9d, 0xaf, 0x0a, 0x78, 0x99, 0x06,
+ 0x06, 0x9e, 0xe7, 0x9c, 0x51, 0x55, 0x43, 0xfc, 0x3b, 0x6c,
+ 0x0b, 0xbf, 0x2d, 0x41, 0xa7, 0xaf, 0xb7, 0xe0, 0xe8, 0x28,
+ 0x18, 0xb4, 0x13, 0xd1, 0xe6, 0x97, 0xd0, 0x9f, 0x6a, 0x80,
+ 0xca, 0xdd, 0x1a, 0x7e, 0x15, 0x02, 0x81, 0x81, 0x00, 0xd1,
+ 0x06, 0x0c, 0x1f, 0xe3, 0xd0, 0xab, 0xd6, 0xca, 0x7c, 0xbc,
+ 0x7d, 0x13, 0x35, 0xce, 0x27, 0xcd, 0xd8, 0x49, 0x51, 0x63,
+ 0x64, 0x0f, 0xca, 0x06, 0x12, 0xfc, 0x07, 0x3e, 0xaf, 0x61,
+ 0x6d, 0xe2, 0x53, 0x39, 0x27, 0xae, 0xc3, 0x11, 0x9e, 0x94,
+ 0x01, 0x4f, 0xe3, 0xf3, 0x67, 0xf9, 0x77, 0xf9, 0xe7, 0x95,
+ 0x3a, 0x6f, 0xe2, 0x20, 0x73, 0x3e, 0xa4, 0x7a, 0x28, 0xd4,
+ 0x61, 0x97, 0xf6, 0x17, 0xa0, 0x23, 0x10, 0x2b, 0xce, 0x84,
+ 0x57, 0x7e, 0x25, 0x1f, 0xf4, 0xa8, 0x54, 0xd2, 0x65, 0x94,
+ 0xcc, 0x95, 0x0a, 0xab, 0x30, 0xc1, 0x59, 0x1f, 0x61, 0x8e,
+ 0xb9, 0x6b, 0xd7, 0x4e, 0xb9, 0x83, 0x43, 0x79, 0x85, 0x11,
+ 0xbc, 0x0f, 0xae, 0x25, 0x20, 0x05, 0xbc, 0xd2, 0x48, 0xa1,
+ 0x68, 0x09, 0x84, 0xf6, 0x12, 0x9a, 0x66, 0xb9, 0x2b, 0xbb,
+ 0x76, 0x03, 0x17, 0x46, 0x4e, 0x97, 0x59, 0x02, 0x81, 0x80,
+ 0x09, 0x4c, 0xfa, 0xd6, 0xe5, 0x65, 0x48, 0x78, 0x43, 0xb5,
+ 0x1f, 0x00, 0x93, 0x2c, 0xb7, 0x24, 0xe8, 0xc6, 0x7d, 0x5a,
+ 0x70, 0x45, 0x92, 0xc8, 0x6c, 0xa3, 0xcd, 0xe1, 0xf7, 0x29,
+ 0x40, 0xfa, 0x3f, 0x5b, 0x47, 0x44, 0x39, 0xc1, 0xe8, 0x72,
+ 0x9e, 0x7a, 0x0e, 0xda, 0xaa, 0xa0, 0x2a, 0x09, 0xfd, 0x54,
+ 0x93, 0x23, 0xaa, 0x37, 0x85, 0x5b, 0xcc, 0xd4, 0xf9, 0xd8,
+ 0xff, 0xc1, 0x61, 0x0d, 0xbd, 0x7e, 0x18, 0x24, 0x73, 0x6d,
+ 0x40, 0x72, 0xf1, 0x93, 0x09, 0x48, 0x97, 0x6c, 0x84, 0x90,
+ 0xa8, 0x46, 0x14, 0x01, 0x39, 0x11, 0xe5, 0x3c, 0x41, 0x27,
+ 0x32, 0x75, 0x24, 0xed, 0xa1, 0xd9, 0x12, 0x29, 0x8a, 0x28,
+ 0x71, 0x89, 0x8d, 0xca, 0x30, 0xb0, 0x01, 0xc4, 0x2f, 0x82,
+ 0x19, 0x14, 0x4c, 0x70, 0x1c, 0xb8, 0x23, 0x2e, 0xe8, 0x90,
+ 0x49, 0x97, 0x92, 0x97, 0x6b, 0x7a, 0x9d, 0xb9, 0x02, 0x81,
+ 0x80, 0x0f, 0x0e, 0xa1, 0x76, 0xf6, 0xa1, 0x44, 0x8f, 0xaf,
+ 0x7c, 0x76, 0xd3, 0x87, 0xbb, 0xbb, 0x83, 0x10, 0x88, 0x01,
+ 0x18, 0x14, 0xd1, 0xd3, 0x75, 0x59, 0x24, 0xaa, 0xf5, 0x16,
+ 0xa5, 0xe9, 0x9d, 0xd1, 0xcc, 0xee, 0xf4, 0x15, 0xd9, 0xc5,
+ 0x7e, 0x27, 0xe9, 0x44, 0x49, 0x06, 0x72, 0xb9, 0xfc, 0xd3,
+ 0x8a, 0xc4, 0x2c, 0x36, 0x7d, 0x12, 0x9b, 0x5a, 0xaa, 0xdc,
+ 0x85, 0xee, 0x6e, 0xad, 0x54, 0xb3, 0xf4, 0xfc, 0x31, 0xa1,
+ 0x06, 0x3a, 0x70, 0x57, 0x0c, 0xf3, 0x95, 0x5b, 0x3e, 0xe8,
+ 0xfd, 0x1a, 0x4f, 0xf6, 0x78, 0x93, 0x46, 0x6a, 0xd7, 0x31,
+ 0xb4, 0x84, 0x64, 0x85, 0x09, 0x38, 0x89, 0x92, 0x94, 0x1c,
+ 0xbf, 0xe2, 0x3c, 0x2a, 0xe0, 0xff, 0x99, 0xa3, 0xf0, 0x2b,
+ 0x31, 0xc2, 0x36, 0xcd, 0x60, 0xbf, 0x9d, 0x2d, 0x74, 0x32,
+ 0xe8, 0x9c, 0x93, 0x6e, 0xbb, 0x91, 0x7b, 0xfd, 0xd9, 0x02,
+ 0x81, 0x81, 0x00, 0xa2, 0x71, 0x25, 0x38, 0xeb, 0x2a, 0xe9,
+ 0x37, 0xcd, 0xfe, 0x44, 0xce, 0x90, 0x3f, 0x52, 0x87, 0x84,
+ 0x52, 0x1b, 0xae, 0x8d, 0x22, 0x94, 0xce, 0x38, 0xe6, 0x04,
+ 0x88, 0x76, 0x85, 0x9a, 0xd3, 0x14, 0x09, 0xe5, 0x69, 0x9a,
+ 0xff, 0x58, 0x92, 0x02, 0x6a, 0x7d, 0x7c, 0x1e, 0x2c, 0xfd,
+ 0xa8, 0xca, 0x32, 0x14, 0x4f, 0x0d, 0x84, 0x0d, 0x37, 0x43,
+ 0xbf, 0xe4, 0x5d, 0x12, 0xc8, 0x24, 0x91, 0x27, 0x8d, 0x46,
+ 0xd9, 0x54, 0x53, 0xe7, 0x62, 0x71, 0xa8, 0x2b, 0x71, 0x41,
+ 0x8d, 0x75, 0xf8, 0x3a, 0xa0, 0x61, 0x29, 0x46, 0xa6, 0xe5,
+ 0x82, 0xfa, 0x3a, 0xd9, 0x08, 0xfa, 0xfc, 0x63, 0xfd, 0x6b,
+ 0x30, 0xbc, 0xf4, 0x4e, 0x9e, 0x8c, 0x25, 0x0c, 0xb6, 0x55,
+ 0xe7, 0x3c, 0xd4, 0x4e, 0x0b, 0xfd, 0x8b, 0xc3, 0x0e, 0x1d,
+ 0x9c, 0x44, 0x57, 0x8f, 0x1f, 0x86, 0xf7, 0xd5, 0x1b, 0xe4,
+ 0x95,
+};
+
+static unsigned char test3072[] = {
+ 0x30, 0x82, 0x06, 0xe3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
+ 0x81, 0x00, 0xbc, 0x3b, 0x23, 0xc0, 0x33, 0xa7, 0x8b, 0xaa,
+ 0xca, 0xa3, 0x8c, 0x94, 0xf2, 0x4c, 0x52, 0x08, 0x85, 0x80,
+ 0xfc, 0x36, 0x15, 0xfa, 0x03, 0x06, 0xb6, 0xd6, 0x3f, 0x60,
+ 0x8a, 0x89, 0x0d, 0xba, 0x1a, 0x51, 0x0b, 0x12, 0xea, 0x71,
+ 0x77, 0xf6, 0x3a, 0x30, 0x21, 0x3d, 0x24, 0xf8, 0x2e, 0xd0,
+ 0x17, 0x3a, 0x85, 0x94, 0x25, 0x42, 0x89, 0xff, 0x6a, 0x68,
+ 0xdf, 0x1f, 0x86, 0xae, 0xa5, 0xbb, 0x9a, 0x79, 0xf6, 0x69,
+ 0x94, 0xfe, 0xde, 0xfe, 0xce, 0x1b, 0x2e, 0xae, 0x1d, 0x91,
+ 0xcb, 0xb9, 0xf1, 0x2d, 0xd8, 0x00, 0x82, 0x51, 0x8e, 0xf9,
+ 0xfd, 0xac, 0xf1, 0x0e, 0x7f, 0xb7, 0x95, 0x85, 0x35, 0xf9,
+ 0xcb, 0xbe, 0x5f, 0xd3, 0x58, 0xe3, 0xa1, 0x54, 0x9e, 0x30,
+ 0xb1, 0x8d, 0x01, 0x97, 0x82, 0x06, 0x8e, 0x77, 0xfb, 0xce,
+ 0x50, 0x2f, 0xbf, 0xf1, 0xff, 0x57, 0x0a, 0x42, 0x03, 0xfd,
+ 0x0e, 0xba, 0x1e, 0xca, 0x85, 0xc1, 0x9b, 0xa5, 0x9d, 0x09,
+ 0x0e, 0xe9, 0xbb, 0xc5, 0x73, 0x47, 0x0d, 0x39, 0x3c, 0x64,
+ 0x06, 0x9a, 0x79, 0x3f, 0x50, 0x87, 0x9c, 0x18, 0x2d, 0x62,
+ 0x01, 0xfc, 0xed, 0xc1, 0x58, 0x28, 0x21, 0x94, 0x1e, 0xf9,
+ 0x2d, 0x96, 0x4f, 0xd0, 0xbc, 0xf1, 0xe0, 0x8a, 0xfa, 0x4d,
+ 0xb6, 0x78, 0x4a, 0xde, 0x17, 0x59, 0xb0, 0x22, 0xa0, 0x9a,
+ 0xd3, 0x70, 0xb6, 0xc2, 0xbe, 0xbc, 0x96, 0xca, 0x41, 0x5f,
+ 0x58, 0x4e, 0xce, 0xef, 0x64, 0x45, 0xdd, 0x3f, 0x81, 0x92,
+ 0xcc, 0x40, 0x79, 0xfc, 0x19, 0xe2, 0xbc, 0x77, 0x2f, 0x43,
+ 0xfb, 0x8e, 0xad, 0x82, 0x4a, 0x0b, 0xb1, 0xbc, 0x09, 0x8a,
+ 0x80, 0xc3, 0x0f, 0xef, 0xd2, 0x06, 0xd3, 0x4b, 0x0c, 0x7f,
+ 0xae, 0x60, 0x3f, 0x2e, 0x52, 0xb4, 0xe4, 0xc2, 0x5c, 0xa6,
+ 0x71, 0xc0, 0x13, 0x9c, 0xca, 0xa6, 0x0d, 0x13, 0xd7, 0xb7,
+ 0x14, 0x94, 0x3f, 0x0d, 0x8b, 0x06, 0x70, 0x2f, 0x15, 0x82,
+ 0x8d, 0x47, 0x45, 0xa6, 0x00, 0x8a, 0x14, 0x91, 0xde, 0x2f,
+ 0x50, 0x17, 0xe3, 0x1d, 0x34, 0x29, 0x8c, 0xe4, 0x57, 0x74,
+ 0x2a, 0x3a, 0x82, 0x65, 0x26, 0xf7, 0x8d, 0xcc, 0x1b, 0x8f,
+ 0xaf, 0xe5, 0x85, 0xe5, 0xbe, 0x85, 0xd6, 0xb7, 0x04, 0xe8,
+ 0xf5, 0xd4, 0x74, 0xe2, 0x54, 0x14, 0xdd, 0x58, 0xcf, 0x1f,
+ 0x11, 0x8a, 0x9f, 0x82, 0xa2, 0x01, 0xf9, 0xc2, 0xdf, 0x7b,
+ 0x84, 0xb1, 0xd8, 0x5b, 0x70, 0xbb, 0x24, 0xe7, 0xd0, 0x2a,
+ 0x75, 0x3d, 0x55, 0xac, 0x45, 0xe9, 0xab, 0xc6, 0x84, 0x8a,
+ 0xe7, 0x6d, 0x26, 0x12, 0x89, 0xb5, 0x67, 0xe8, 0x46, 0x9d,
+ 0x46, 0x1a, 0xfa, 0x2d, 0xc0, 0x5b, 0x60, 0x46, 0x8b, 0xb7,
+ 0x32, 0x03, 0xff, 0x75, 0xee, 0x9f, 0x3c, 0xdd, 0xb6, 0x35,
+ 0x4e, 0x82, 0xbd, 0x99, 0x73, 0x51, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0x02, 0x82, 0x01, 0x80, 0x42, 0xee, 0xa4, 0x9f, 0xcb,
+ 0xbe, 0x60, 0x23, 0xb3, 0x3a, 0xc4, 0xda, 0x91, 0xee, 0x21,
+ 0x9d, 0x76, 0x1b, 0x8f, 0x93, 0x8b, 0xed, 0x02, 0xf6, 0x78,
+ 0x3d, 0x66, 0xfb, 0xe5, 0x47, 0x26, 0xe2, 0x6e, 0x49, 0x33,
+ 0x2e, 0xde, 0xbe, 0xca, 0x71, 0x7b, 0xef, 0x71, 0x62, 0x54,
+ 0xab, 0x0b, 0xba, 0x63, 0x08, 0x24, 0x47, 0xb1, 0x98, 0x1f,
+ 0x89, 0xfb, 0x44, 0x9f, 0x52, 0x8e, 0x89, 0xbb, 0xd5, 0x21,
+ 0xf1, 0x0c, 0x76, 0x2e, 0xcd, 0x12, 0x6e, 0x78, 0xcb, 0xa1,
+ 0xa5, 0xb8, 0x4e, 0x07, 0xab, 0x6e, 0xdf, 0x66, 0x57, 0x87,
+ 0xff, 0x88, 0x5f, 0xcc, 0x9c, 0x9a, 0x7b, 0x15, 0x5f, 0x2a,
+ 0x83, 0xdb, 0xd5, 0x9f, 0x65, 0x6a, 0x9d, 0xb4, 0x95, 0xfc,
+ 0xe0, 0x22, 0x00, 0x1e, 0xa2, 0x8d, 0x56, 0x5a, 0x9e, 0x0a,
+ 0x3b, 0x10, 0x07, 0x24, 0xec, 0x55, 0xcc, 0xaf, 0x87, 0x3b,
+ 0xd6, 0x8d, 0xa4, 0x86, 0x80, 0x18, 0x42, 0xdb, 0x9d, 0x24,
+ 0xc3, 0x97, 0x3b, 0x89, 0x5a, 0x03, 0xb3, 0x0a, 0x72, 0xd1,
+ 0x78, 0xf0, 0xc8, 0x80, 0xb0, 0x9d, 0x3c, 0xae, 0x5e, 0x0a,
+ 0x5b, 0x6e, 0x87, 0xd3, 0x3d, 0x25, 0x2e, 0x03, 0x33, 0x01,
+ 0xfd, 0xb1, 0xa5, 0xd9, 0x58, 0x01, 0xb9, 0xaf, 0xf6, 0x32,
+ 0x6a, 0x38, 0xe7, 0x39, 0x63, 0x3c, 0xfc, 0x0c, 0x41, 0x90,
+ 0x28, 0x40, 0x03, 0xcd, 0xfb, 0xde, 0x80, 0x74, 0x21, 0xaa,
+ 0xae, 0x58, 0xe9, 0x97, 0x18, 0x85, 0x58, 0x3d, 0x2b, 0xd6,
+ 0x61, 0xf6, 0xe8, 0xbc, 0x6d, 0x2a, 0xf3, 0xb8, 0xea, 0x8c,
+ 0x64, 0x44, 0xc6, 0xd3, 0x9f, 0x00, 0x7b, 0xb2, 0x52, 0x18,
+ 0x11, 0x04, 0x96, 0xb7, 0x05, 0xbb, 0xc2, 0x38, 0x5b, 0xa7,
+ 0x0a, 0x84, 0xb6, 0x4f, 0x02, 0x63, 0xa4, 0x57, 0x00, 0xe3,
+ 0xde, 0xe4, 0xf2, 0xb3, 0x55, 0xd9, 0x00, 0xa9, 0xd2, 0x5c,
+ 0x69, 0x9f, 0xe5, 0x80, 0x4f, 0x23, 0x7c, 0xd9, 0xa7, 0x77,
+ 0x4a, 0xbb, 0x09, 0x6d, 0x45, 0x02, 0xcf, 0x32, 0x90, 0xfd,
+ 0x10, 0xb6, 0xb3, 0x93, 0xd9, 0x3b, 0x1d, 0x57, 0x66, 0xb5,
+ 0xb3, 0xb1, 0x6e, 0x53, 0x5f, 0x04, 0x60, 0x29, 0xcd, 0xe8,
+ 0xb8, 0xab, 0x62, 0x82, 0x33, 0x40, 0xc7, 0xf8, 0x64, 0x60,
+ 0x0e, 0xab, 0x06, 0x3e, 0xa0, 0xa3, 0x62, 0x11, 0x3f, 0x67,
+ 0x5d, 0x24, 0x9e, 0x60, 0x29, 0xdc, 0x4c, 0xd5, 0x13, 0xee,
+ 0x3d, 0xb7, 0x84, 0x93, 0x27, 0xb5, 0x6a, 0xf9, 0xf0, 0xdd,
+ 0x50, 0xac, 0x46, 0x3c, 0xe6, 0xd5, 0xec, 0xf7, 0xb7, 0x9f,
+ 0x23, 0x39, 0x9c, 0x88, 0x8c, 0x5a, 0x62, 0x3f, 0x8d, 0x4a,
+ 0xd7, 0xeb, 0x5e, 0x1e, 0x49, 0xf8, 0xa9, 0x53, 0x11, 0x75,
+ 0xd0, 0x43, 0x1e, 0xc7, 0x29, 0x22, 0x80, 0x1f, 0xc5, 0x83,
+ 0x8d, 0x20, 0x04, 0x87, 0x7f, 0x57, 0x8c, 0xf5, 0xa1, 0x02,
+ 0x81, 0xc1, 0x00, 0xf7, 0xaa, 0xf5, 0xa5, 0x00, 0xdb, 0xd6,
+ 0x11, 0xfc, 0x07, 0x6d, 0x22, 0x24, 0x2b, 0x4b, 0xc5, 0x67,
+ 0x0f, 0x37, 0xa5, 0xdb, 0x8f, 0x38, 0xe2, 0x05, 0x43, 0x9a,
+ 0x44, 0x05, 0x3f, 0xa9, 0xac, 0x4c, 0x98, 0x3c, 0x72, 0x38,
+ 0xc3, 0x89, 0x33, 0x58, 0x73, 0x51, 0xcc, 0x5d, 0x2f, 0x8f,
+ 0x6d, 0x3f, 0xa1, 0x22, 0x9e, 0xfb, 0x9a, 0xb4, 0xb8, 0x79,
+ 0x95, 0xaf, 0x83, 0xcf, 0x5a, 0xb7, 0x14, 0x14, 0x0c, 0x51,
+ 0x8a, 0x11, 0xe6, 0xd6, 0x21, 0x1e, 0x17, 0x13, 0xd3, 0x69,
+ 0x7a, 0x3a, 0xd5, 0xaf, 0x3f, 0xb8, 0x25, 0x01, 0xcb, 0x2b,
+ 0xe6, 0xfc, 0x03, 0xd8, 0xd4, 0xf7, 0x20, 0xe0, 0x21, 0xef,
+ 0x1a, 0xca, 0x61, 0xeb, 0x8e, 0x96, 0x45, 0x8e, 0x5c, 0xe6,
+ 0x81, 0x0b, 0x2d, 0x05, 0x32, 0xf9, 0x41, 0x62, 0xb4, 0x33,
+ 0x98, 0x10, 0x3a, 0xcd, 0xf0, 0x7a, 0x8b, 0x1a, 0x48, 0xd7,
+ 0x3b, 0x01, 0xf5, 0x18, 0x65, 0x8f, 0x3c, 0xc2, 0x31, 0x3b,
+ 0xd3, 0xa7, 0x17, 0x5f, 0x7c, 0x0c, 0xe7, 0x25, 0x18, 0x5a,
+ 0x08, 0xe1, 0x09, 0x89, 0x13, 0xa7, 0xc5, 0x12, 0xab, 0x88,
+ 0x30, 0xcd, 0x06, 0xf9, 0xba, 0x6f, 0xca, 0x9c, 0x8a, 0xda,
+ 0x3e, 0x53, 0x90, 0xd7, 0x16, 0x2e, 0xfc, 0xbc, 0xad, 0xd6,
+ 0x3d, 0xc0, 0x66, 0x4c, 0x02, 0x3d, 0x31, 0xfd, 0x6c, 0xdb,
+ 0x1c, 0xdf, 0x96, 0x33, 0x23, 0x02, 0x81, 0xc1, 0x00, 0xc2,
+ 0x90, 0x47, 0xc4, 0xfb, 0x59, 0xf0, 0xc5, 0x14, 0x75, 0x29,
+ 0xfa, 0x77, 0xa1, 0x8d, 0xd4, 0x90, 0xa1, 0x0d, 0x3f, 0x16,
+ 0x88, 0xe3, 0x4c, 0x8f, 0x8f, 0x18, 0x8c, 0x9c, 0x8a, 0xd5,
+ 0xa7, 0x41, 0x99, 0xf3, 0x80, 0x8e, 0xb1, 0xb8, 0x63, 0xd8,
+ 0x3f, 0x95, 0xd0, 0xd0, 0x2b, 0xf5, 0xe6, 0x93, 0xe8, 0xfe,
+ 0xd0, 0x73, 0xd5, 0xbd, 0xb4, 0xee, 0x51, 0x19, 0x6a, 0x10,
+ 0xca, 0xc8, 0xba, 0xa4, 0x4d, 0x84, 0x54, 0x38, 0x17, 0xb5,
+ 0xd0, 0xa8, 0x75, 0x22, 0xc5, 0x1b, 0x61, 0xa6, 0x51, 0x88,
+ 0x63, 0xf0, 0x4f, 0xd1, 0x88, 0xd9, 0x16, 0x49, 0x30, 0xe1,
+ 0xa8, 0x47, 0xc9, 0x30, 0x1d, 0x5c, 0x75, 0xd8, 0x89, 0xb6,
+ 0x1d, 0x45, 0xd8, 0x0f, 0x94, 0x89, 0xb3, 0xe4, 0x51, 0xfa,
+ 0x21, 0xff, 0x6f, 0xb6, 0x30, 0x6f, 0x33, 0x24, 0xbc, 0x09,
+ 0x98, 0xe9, 0x20, 0x02, 0x0b, 0xde, 0xff, 0xc5, 0x06, 0xb6,
+ 0x28, 0xa3, 0xa1, 0x07, 0xe8, 0xe1, 0xd2, 0xc2, 0xf1, 0xd1,
+ 0x23, 0x6b, 0x4c, 0x3a, 0xae, 0x85, 0xec, 0xf9, 0xff, 0xa7,
+ 0x9b, 0x25, 0xb8, 0x95, 0x1d, 0xa8, 0x14, 0x81, 0x4f, 0x79,
+ 0x4f, 0xd6, 0x39, 0x5d, 0xe6, 0x5f, 0xd2, 0x34, 0x54, 0x8b,
+ 0x1e, 0x40, 0x4c, 0x15, 0x5a, 0x45, 0xce, 0x0c, 0xb0, 0xdf,
+ 0xa1, 0x17, 0xb8, 0xb0, 0x6a, 0x82, 0xa5, 0x97, 0x92, 0x70,
+ 0xfb, 0x02, 0x81, 0xc0, 0x77, 0x46, 0x44, 0x2b, 0x04, 0xf0,
+ 0xda, 0x75, 0xaa, 0xd4, 0xc0, 0xc0, 0x32, 0x7f, 0x0f, 0x6c,
+ 0xb0, 0x27, 0x69, 0xfb, 0x5c, 0x73, 0xeb, 0x47, 0x1e, 0x95,
+ 0xe2, 0x13, 0x64, 0x1b, 0xb6, 0xd1, 0x1d, 0xca, 0x2b, 0x42,
+ 0x2f, 0x08, 0x2c, 0x69, 0x27, 0xed, 0xd1, 0xb5, 0x04, 0x23,
+ 0xc5, 0x85, 0x2d, 0xa1, 0xa2, 0x94, 0xc2, 0x43, 0x4d, 0x49,
+ 0x92, 0x74, 0x7e, 0x24, 0x92, 0x95, 0xf3, 0x99, 0x9d, 0xd6,
+ 0x18, 0xe6, 0xcf, 0x9c, 0x45, 0xff, 0x89, 0x08, 0x40, 0x2a,
+ 0x0e, 0xa0, 0x28, 0xf9, 0x83, 0xfe, 0xc1, 0xe6, 0x40, 0xa8,
+ 0xe2, 0x29, 0xc9, 0xb0, 0xe8, 0x9a, 0x17, 0xb2, 0x23, 0x7e,
+ 0xf4, 0x32, 0x08, 0xc9, 0x83, 0xb2, 0x15, 0xb8, 0xc5, 0xc9,
+ 0x03, 0xd1, 0x9d, 0xda, 0x3e, 0xa8, 0xbf, 0xd5, 0xb7, 0x7d,
+ 0x65, 0x63, 0x94, 0x5d, 0x5d, 0x94, 0xb4, 0xcf, 0x8d, 0x07,
+ 0x0b, 0x70, 0x85, 0x8e, 0xce, 0x03, 0x0b, 0x2a, 0x8d, 0xb3,
+ 0x3c, 0x46, 0xc0, 0x2f, 0xc7, 0x72, 0x6c, 0x9c, 0x5d, 0x07,
+ 0x0f, 0x45, 0x3b, 0x6b, 0x66, 0x32, 0xab, 0x17, 0x83, 0xd8,
+ 0x4c, 0x2c, 0x84, 0x71, 0x19, 0x8f, 0xaa, 0x0a, 0xff, 0xbc,
+ 0xf7, 0x42, 0x10, 0xe8, 0xae, 0x4d, 0x26, 0xaf, 0xdd, 0x06,
+ 0x33, 0x29, 0x66, 0x21, 0x5d, 0xf5, 0xae, 0x17, 0x07, 0x1f,
+ 0x87, 0x9e, 0xae, 0x27, 0x1d, 0xd5, 0x02, 0x81, 0xc0, 0x56,
+ 0x17, 0x4f, 0x9a, 0x8a, 0xf9, 0xde, 0x3e, 0xe6, 0x71, 0x7d,
+ 0x94, 0xb5, 0xb0, 0xc7, 0xb8, 0x62, 0x12, 0xd1, 0x70, 0xb4,
+ 0x00, 0xf8, 0x4a, 0xdd, 0x4f, 0x1d, 0x36, 0xc2, 0xe1, 0xef,
+ 0xee, 0x25, 0x6a, 0x00, 0xc4, 0x46, 0xdf, 0xbe, 0xce, 0x77,
+ 0x56, 0x93, 0x6d, 0x25, 0x5f, 0xfe, 0x5b, 0xfb, 0xe0, 0xe2,
+ 0x37, 0xcc, 0xb9, 0xac, 0x4a, 0xce, 0x15, 0x16, 0xa0, 0xc7,
+ 0x33, 0x63, 0xa4, 0xaa, 0xa5, 0x1e, 0x43, 0xc1, 0xda, 0x43,
+ 0xfa, 0x43, 0x40, 0x29, 0x95, 0x7c, 0x2b, 0x36, 0x53, 0xe7,
+ 0x7d, 0x09, 0x4d, 0xd8, 0x52, 0xac, 0x74, 0x5f, 0x08, 0x81,
+ 0x21, 0x5c, 0x3a, 0x5a, 0xce, 0xf3, 0x25, 0xb6, 0x1e, 0x21,
+ 0x76, 0x4c, 0x7c, 0x71, 0x50, 0x71, 0xaa, 0x27, 0x02, 0x5b,
+ 0x23, 0x06, 0x0b, 0x21, 0x5b, 0xc7, 0x28, 0xa3, 0x3d, 0x8d,
+ 0x25, 0x9b, 0x2a, 0x2d, 0x9d, 0xa1, 0x1c, 0x1d, 0xcb, 0x7d,
+ 0x78, 0xf8, 0x06, 0x7e, 0x20, 0x7f, 0x24, 0x2a, 0x5c, 0xa4,
+ 0x04, 0xff, 0x2a, 0x68, 0xe0, 0xe6, 0xa3, 0xd8, 0x6f, 0x56,
+ 0x73, 0xa1, 0x3a, 0x4e, 0xc9, 0x23, 0xa1, 0x87, 0x22, 0x6a,
+ 0x74, 0x78, 0x3f, 0x44, 0x1c, 0x77, 0x13, 0xe5, 0x51, 0xef,
+ 0x89, 0x00, 0x3c, 0x6a, 0x4a, 0x5a, 0x8e, 0xf5, 0x30, 0xa2,
+ 0x93, 0x7e, 0x92, 0x9b, 0x85, 0x55, 0xaf, 0xfe, 0x24, 0xaf,
+ 0x57, 0x02, 0x81, 0xc1, 0x00, 0xa4, 0xc2, 0x6a, 0x59, 0x45,
+ 0xea, 0x71, 0x7d, 0x4c, 0xaf, 0xaf, 0xd6, 0x55, 0x97, 0x73,
+ 0xc5, 0xa1, 0x3c, 0xf6, 0x59, 0x23, 0xb6, 0x1f, 0x5e, 0x9c,
+ 0x96, 0x0f, 0x97, 0x66, 0x82, 0x91, 0x48, 0x36, 0x70, 0x02,
+ 0x67, 0xde, 0x34, 0xa6, 0x95, 0x7b, 0x51, 0x43, 0x66, 0xa4,
+ 0x16, 0x45, 0x59, 0x12, 0xdb, 0x35, 0x19, 0x4b, 0xbf, 0x1d,
+ 0xab, 0xf3, 0x3f, 0xb4, 0xb4, 0x6f, 0x66, 0xb0, 0x67, 0xc6,
+ 0x77, 0x2c, 0x46, 0xa8, 0x03, 0x64, 0x9a, 0x13, 0x9d, 0x40,
+ 0x22, 0x56, 0x76, 0x1a, 0x7c, 0x1e, 0xe2, 0xda, 0x7f, 0x09,
+ 0xcf, 0x10, 0xe3, 0xf2, 0xf4, 0x2a, 0x3b, 0x46, 0xc7, 0x61,
+ 0x9b, 0xef, 0x4a, 0x18, 0x60, 0x8c, 0x32, 0x71, 0xb9, 0xdd,
+ 0xac, 0xa0, 0xc6, 0x8d, 0x3f, 0xab, 0xc3, 0x21, 0x2c, 0xeb,
+ 0x91, 0x8f, 0xc7, 0x43, 0x0d, 0x0c, 0x67, 0x9e, 0xab, 0xe6,
+ 0x8d, 0xb6, 0x2d, 0x41, 0xca, 0x43, 0xd8, 0xcb, 0x30, 0xfb,
+ 0x3b, 0x40, 0x0d, 0x10, 0x9b, 0xb1, 0x55, 0x93, 0x73, 0x8b,
+ 0x60, 0xef, 0xc0, 0xee, 0xc0, 0xa6, 0x7a, 0x79, 0x90, 0xfd,
+ 0x4c, 0x25, 0xd4, 0x4f, 0x67, 0xbe, 0xf7, 0x86, 0x3c, 0x5d,
+ 0x2b, 0x7d, 0x97, 0x3d, 0xa2, 0x91, 0xa5, 0x06, 0x69, 0xf6,
+ 0x7a, 0xb8, 0x77, 0xe6, 0x70, 0xa9, 0xd8, 0x86, 0x4b, 0xa6,
+ 0xcf, 0x67, 0x1d, 0x33, 0xcf, 0xfe, 0x3e
+};
+
+static unsigned char test4096[] = {
+ 0x30, 0x82, 0x09, 0x29, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02,
+ 0x01, 0x00, 0xc0, 0x71, 0xac, 0x1a, 0x13, 0x88, 0x82, 0x43,
+ 0x3b, 0x51, 0x57, 0x71, 0x8d, 0xb6, 0x2b, 0x82, 0x65, 0x21,
+ 0x53, 0x5f, 0x28, 0x29, 0x4f, 0x8d, 0x7c, 0x8a, 0xb9, 0x44,
+ 0xb3, 0x28, 0x41, 0x4f, 0xd3, 0xfa, 0x6a, 0xf8, 0xb9, 0x28,
+ 0x50, 0x39, 0x67, 0x53, 0x2c, 0x3c, 0xd7, 0xcb, 0x96, 0x41,
+ 0x40, 0x32, 0xbb, 0xeb, 0x70, 0xae, 0x1f, 0xb0, 0x65, 0xf7,
+ 0x3a, 0xd9, 0x22, 0xfd, 0x10, 0xae, 0xbd, 0x02, 0xe2, 0xdd,
+ 0xf3, 0xc2, 0x79, 0x3c, 0xc6, 0xfc, 0x75, 0xbb, 0xaf, 0x4e,
+ 0x3a, 0x36, 0xc2, 0x4f, 0xea, 0x25, 0xdf, 0x13, 0x16, 0x4b,
+ 0x20, 0xfe, 0x4b, 0x69, 0x16, 0xc4, 0x7f, 0x1a, 0x43, 0xa6,
+ 0x17, 0x1b, 0xb9, 0x0a, 0xf3, 0x09, 0x86, 0x28, 0x89, 0xcf,
+ 0x2c, 0xd0, 0xd4, 0x81, 0xaf, 0xc6, 0x6d, 0xe6, 0x21, 0x8d,
+ 0xee, 0xef, 0xea, 0xdc, 0xb7, 0xc6, 0x3b, 0x63, 0x9f, 0x0e,
+ 0xad, 0x89, 0x78, 0x23, 0x18, 0xbf, 0x70, 0x7e, 0x84, 0xe0,
+ 0x37, 0xec, 0xdb, 0x8e, 0x9c, 0x3e, 0x6a, 0x19, 0xcc, 0x99,
+ 0x72, 0xe6, 0xb5, 0x7d, 0x6d, 0xfa, 0xe5, 0xd3, 0xe4, 0x90,
+ 0xb5, 0xb2, 0xb2, 0x12, 0x70, 0x4e, 0xca, 0xf8, 0x10, 0xf8,
+ 0xa3, 0x14, 0xc2, 0x48, 0x19, 0xeb, 0x60, 0x99, 0xbb, 0x2a,
+ 0x1f, 0xb1, 0x7a, 0xb1, 0x3d, 0x24, 0xfb, 0xa0, 0x29, 0xda,
+ 0xbd, 0x1b, 0xd7, 0xa4, 0xbf, 0xef, 0x60, 0x2d, 0x22, 0xca,
+ 0x65, 0x98, 0xf1, 0xc4, 0xe1, 0xc9, 0x02, 0x6b, 0x16, 0x28,
+ 0x2f, 0xa1, 0xaa, 0x79, 0x00, 0xda, 0xdc, 0x7c, 0x43, 0xf7,
+ 0x42, 0x3c, 0xa0, 0xef, 0x68, 0xf7, 0xdf, 0xb9, 0x69, 0xfb,
+ 0x8e, 0x01, 0xed, 0x01, 0x42, 0xb5, 0x4e, 0x57, 0xa6, 0x26,
+ 0xb8, 0xd0, 0x7b, 0x56, 0x6d, 0x03, 0xc6, 0x40, 0x8c, 0x8c,
+ 0x2a, 0x55, 0xd7, 0x9c, 0x35, 0x00, 0x94, 0x93, 0xec, 0x03,
+ 0xeb, 0x22, 0xef, 0x77, 0xbb, 0x79, 0x13, 0x3f, 0x15, 0xa1,
+ 0x8f, 0xca, 0xdf, 0xfd, 0xd3, 0xb8, 0xe1, 0xd4, 0xcc, 0x09,
+ 0x3f, 0x3c, 0x2c, 0xdb, 0xd1, 0x49, 0x7f, 0x38, 0x07, 0x83,
+ 0x6d, 0xeb, 0x08, 0x66, 0xe9, 0x06, 0x44, 0x12, 0xac, 0x95,
+ 0x22, 0x90, 0x23, 0x67, 0xd4, 0x08, 0xcc, 0xf4, 0xb7, 0xdc,
+ 0xcc, 0x87, 0xd4, 0xac, 0x69, 0x35, 0x4c, 0xb5, 0x39, 0x36,
+ 0xcd, 0xa4, 0xd2, 0x95, 0xca, 0x0d, 0xc5, 0xda, 0xc2, 0xc5,
+ 0x22, 0x32, 0x28, 0x08, 0xe3, 0xd2, 0x8b, 0x38, 0x30, 0xdc,
+ 0x8c, 0x75, 0x4f, 0x6a, 0xec, 0x7a, 0xac, 0x16, 0x3e, 0xa8,
+ 0xd4, 0x6a, 0x45, 0xe1, 0xa8, 0x4f, 0x2e, 0x80, 0x34, 0xaa,
+ 0x54, 0x1b, 0x02, 0x95, 0x7d, 0x8a, 0x6d, 0xcc, 0x79, 0xca,
+ 0xf2, 0xa4, 0x2e, 0x8d, 0xfb, 0xfe, 0x15, 0x51, 0x10, 0x0e,
+ 0x4d, 0x88, 0xb1, 0xc7, 0xf4, 0x79, 0xdb, 0xf0, 0xb4, 0x56,
+ 0x44, 0x37, 0xca, 0x5a, 0xc1, 0x8c, 0x48, 0xac, 0xae, 0x48,
+ 0x80, 0x83, 0x01, 0x3f, 0xde, 0xd9, 0xd3, 0x2c, 0x51, 0x46,
+ 0xb1, 0x41, 0xb6, 0xc6, 0x91, 0x72, 0xf9, 0x83, 0x55, 0x1b,
+ 0x8c, 0xba, 0xf3, 0x73, 0xe5, 0x2c, 0x74, 0x50, 0x3a, 0xbe,
+ 0xc5, 0x2f, 0xa7, 0xb2, 0x6d, 0x8c, 0x9e, 0x13, 0x77, 0xa3,
+ 0x13, 0xcd, 0x6d, 0x8c, 0x45, 0xe1, 0xfc, 0x0b, 0xb7, 0x69,
+ 0xe9, 0x27, 0xbc, 0x65, 0xc3, 0xfa, 0x9b, 0xd0, 0xef, 0xfe,
+ 0xe8, 0x1f, 0xb3, 0x5e, 0x34, 0xf4, 0x8c, 0xea, 0xfc, 0xd3,
+ 0x81, 0xbf, 0x3d, 0x30, 0xb2, 0xb4, 0x01, 0xe8, 0x43, 0x0f,
+ 0xba, 0x02, 0x23, 0x42, 0x76, 0x82, 0x31, 0x73, 0x91, 0xed,
+ 0x07, 0x46, 0x61, 0x0d, 0x39, 0x83, 0x40, 0xce, 0x7a, 0xd4,
+ 0xdb, 0x80, 0x2c, 0x1f, 0x0d, 0xd1, 0x34, 0xd4, 0x92, 0xe3,
+ 0xd4, 0xf1, 0xc2, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+ 0x82, 0x02, 0x01, 0x00, 0x97, 0x6c, 0xda, 0x6e, 0xea, 0x4f,
+ 0xcf, 0xaf, 0xf7, 0x4c, 0xd9, 0xf1, 0x90, 0x00, 0x77, 0xdb,
+ 0xf2, 0x97, 0x76, 0x72, 0xb9, 0xb7, 0x47, 0xd1, 0x9c, 0xdd,
+ 0xcb, 0x4a, 0x33, 0x6e, 0xc9, 0x75, 0x76, 0xe6, 0xe4, 0xa5,
+ 0x31, 0x8c, 0x77, 0x13, 0xb4, 0x29, 0xcd, 0xf5, 0x52, 0x17,
+ 0xef, 0xf3, 0x08, 0x00, 0xe3, 0xbd, 0x2e, 0xbc, 0xd4, 0x52,
+ 0x88, 0xe9, 0x30, 0x75, 0x0b, 0x02, 0xf5, 0xcd, 0x89, 0x0c,
+ 0x6c, 0x57, 0x19, 0x27, 0x3d, 0x1e, 0x85, 0xb4, 0xc1, 0x2f,
+ 0x1d, 0x92, 0x00, 0x5c, 0x76, 0x29, 0x4b, 0xa4, 0xe1, 0x12,
+ 0xb3, 0xc8, 0x09, 0xfe, 0x0e, 0x78, 0x72, 0x61, 0xcb, 0x61,
+ 0x6f, 0x39, 0x91, 0x95, 0x4e, 0xd5, 0x3e, 0xc7, 0x8f, 0xb8,
+ 0xf6, 0x36, 0xfe, 0x9c, 0x93, 0x9a, 0x38, 0x25, 0x7a, 0xf4,
+ 0x4a, 0x12, 0xd4, 0xa0, 0x13, 0xbd, 0xf9, 0x1d, 0x12, 0x3e,
+ 0x21, 0x39, 0xfb, 0x72, 0xe0, 0x05, 0x3d, 0xc3, 0xe5, 0x50,
+ 0xa8, 0x5d, 0x85, 0xa3, 0xea, 0x5f, 0x1c, 0xb2, 0x3f, 0xea,
+ 0x6d, 0x03, 0x91, 0x55, 0xd8, 0x19, 0x0a, 0x21, 0x12, 0x16,
+ 0xd9, 0x12, 0xc4, 0xe6, 0x07, 0x18, 0x5b, 0x26, 0xa4, 0xae,
+ 0xed, 0x2b, 0xb7, 0xa6, 0xed, 0xf8, 0xad, 0xec, 0x77, 0xe6,
+ 0x7f, 0x4f, 0x76, 0x00, 0xc0, 0xfa, 0x15, 0x92, 0xb4, 0x2c,
+ 0x22, 0xc2, 0xeb, 0x6a, 0xad, 0x14, 0x05, 0xb2, 0xe5, 0x8a,
+ 0x9e, 0x85, 0x83, 0xcc, 0x04, 0xf1, 0x56, 0x78, 0x44, 0x5e,
+ 0xde, 0xe0, 0x60, 0x1a, 0x65, 0x79, 0x31, 0x23, 0x05, 0xbb,
+ 0x01, 0xff, 0xdd, 0x2e, 0xb7, 0xb3, 0xaa, 0x74, 0xe0, 0xa5,
+ 0x94, 0xaf, 0x4b, 0xde, 0x58, 0x0f, 0x55, 0xde, 0x33, 0xf6,
+ 0xe3, 0xd6, 0x34, 0x36, 0x57, 0xd6, 0x79, 0x91, 0x2e, 0xbe,
+ 0x3b, 0xd9, 0x4e, 0xb6, 0x9d, 0x21, 0x5c, 0xd3, 0x48, 0x14,
+ 0x7f, 0x4a, 0xc4, 0x60, 0xa9, 0x29, 0xf8, 0x53, 0x7f, 0x88,
+ 0x11, 0x2d, 0xb5, 0xc5, 0x2d, 0x6f, 0xee, 0x85, 0x0b, 0xf7,
+ 0x8d, 0x9a, 0xbe, 0xb0, 0x42, 0xf2, 0x2e, 0x71, 0xaf, 0x19,
+ 0x31, 0x6d, 0xec, 0xcd, 0x6f, 0x2b, 0x23, 0xdf, 0xb4, 0x40,
+ 0xaf, 0x2c, 0x0a, 0xc3, 0x1b, 0x7d, 0x7d, 0x03, 0x1d, 0x4b,
+ 0xf3, 0xb5, 0xe0, 0x85, 0xd8, 0xdf, 0x91, 0x6b, 0x0a, 0x69,
+ 0xf7, 0xf2, 0x69, 0x66, 0x5b, 0xf1, 0xcf, 0x46, 0x7d, 0xe9,
+ 0x70, 0xfa, 0x6d, 0x7e, 0x75, 0x4e, 0xa9, 0x77, 0xe6, 0x8c,
+ 0x02, 0xf7, 0x14, 0x4d, 0xa5, 0x41, 0x8f, 0x3f, 0xc1, 0x62,
+ 0x1e, 0x71, 0x5e, 0x38, 0xb4, 0xd6, 0xe6, 0xe1, 0x4b, 0xc2,
+ 0x2c, 0x30, 0x83, 0x81, 0x6f, 0x49, 0x2e, 0x96, 0xe6, 0xc9,
+ 0x9a, 0xf7, 0x5d, 0x09, 0xa0, 0x55, 0x02, 0xa5, 0x3a, 0x25,
+ 0x23, 0xd0, 0x92, 0xc3, 0xa3, 0xe3, 0x0e, 0x12, 0x2f, 0x4d,
+ 0xef, 0xf3, 0x55, 0x5a, 0xbe, 0xe6, 0x19, 0x86, 0x31, 0xab,
+ 0x75, 0x9a, 0xd3, 0xf0, 0x2c, 0xc5, 0x41, 0x92, 0xd9, 0x1f,
+ 0x5f, 0x11, 0x8c, 0x75, 0x1c, 0x63, 0xd0, 0x02, 0x80, 0x2c,
+ 0x68, 0xcb, 0x93, 0xfb, 0x51, 0x73, 0x49, 0xb4, 0x60, 0xda,
+ 0xe2, 0x26, 0xaf, 0xa9, 0x46, 0x12, 0xb8, 0xec, 0x50, 0xdd,
+ 0x12, 0x06, 0x5f, 0xce, 0x59, 0xe6, 0xf6, 0x1c, 0xe0, 0x54,
+ 0x10, 0xad, 0xf6, 0xcd, 0x98, 0xcc, 0x0f, 0xfb, 0xcb, 0x41,
+ 0x14, 0x9d, 0xed, 0xe4, 0xb4, 0x74, 0x5f, 0x09, 0x60, 0xc7,
+ 0x12, 0xf6, 0x7b, 0x3c, 0x8f, 0xa7, 0x20, 0xbc, 0xe4, 0xb1,
+ 0xef, 0xeb, 0xa4, 0x93, 0xc5, 0x06, 0xca, 0x9a, 0x27, 0x9d,
+ 0x87, 0xf3, 0xde, 0xca, 0xe5, 0xe7, 0xf6, 0x1c, 0x01, 0x65,
+ 0x5b, 0xfb, 0x19, 0x79, 0x6e, 0x08, 0x26, 0xc5, 0xc8, 0x28,
+ 0x0e, 0xb6, 0x3b, 0x07, 0x08, 0xc1, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0xe8, 0x1c, 0x73, 0xa6, 0xb8, 0xe0, 0x0e, 0x6d, 0x8d,
+ 0x1b, 0xb9, 0x53, 0xed, 0x58, 0x94, 0xe6, 0x1d, 0x60, 0x14,
+ 0x5c, 0x76, 0x43, 0xc4, 0x58, 0x19, 0xc4, 0x24, 0xe8, 0xbc,
+ 0x1b, 0x3b, 0x0b, 0x13, 0x24, 0x45, 0x54, 0x0e, 0xcc, 0x37,
+ 0xf0, 0xe0, 0x63, 0x7d, 0xc3, 0xf7, 0xfb, 0x81, 0x74, 0x81,
+ 0xc4, 0x0f, 0x1a, 0x21, 0x48, 0xaf, 0xce, 0xc1, 0xc4, 0x94,
+ 0x18, 0x06, 0x44, 0x8d, 0xd3, 0xd2, 0x22, 0x2d, 0x2d, 0x3e,
+ 0x5a, 0x31, 0xdc, 0x95, 0x8e, 0xf4, 0x41, 0xfc, 0x58, 0xc9,
+ 0x40, 0x92, 0x17, 0x5f, 0xe3, 0xda, 0xac, 0x9e, 0x3f, 0x1c,
+ 0x2a, 0x6b, 0x58, 0x5f, 0x48, 0x78, 0x20, 0xb1, 0xaf, 0x24,
+ 0x9b, 0x3c, 0x20, 0x8b, 0x93, 0x25, 0x9e, 0xe6, 0x6b, 0xbc,
+ 0x13, 0x42, 0x14, 0x6c, 0x36, 0x31, 0xff, 0x7a, 0xd1, 0xc1,
+ 0x1a, 0x26, 0x14, 0x7f, 0xa9, 0x76, 0xa7, 0x0c, 0xf8, 0xcc,
+ 0xed, 0x07, 0x6a, 0xd2, 0xdf, 0x62, 0xee, 0x0a, 0x7c, 0x84,
+ 0xcb, 0x49, 0x90, 0xb2, 0x03, 0x0d, 0xa2, 0x82, 0x06, 0x77,
+ 0xf1, 0xcd, 0x67, 0xf2, 0x47, 0x21, 0x02, 0x3f, 0x43, 0x21,
+ 0xf0, 0x46, 0x30, 0x62, 0x51, 0x72, 0xb1, 0xe7, 0x48, 0xc6,
+ 0x67, 0x12, 0xcd, 0x9e, 0xd6, 0x15, 0xe5, 0x21, 0xed, 0xfa,
+ 0x8f, 0x30, 0xa6, 0x41, 0xfe, 0xb6, 0xfa, 0x8f, 0x34, 0x14,
+ 0x19, 0xe8, 0x11, 0xf7, 0xa5, 0x77, 0x3e, 0xb7, 0xf9, 0x39,
+ 0x07, 0x8c, 0x67, 0x2a, 0xab, 0x7b, 0x08, 0xf8, 0xb0, 0x06,
+ 0xa8, 0xea, 0x2f, 0x8f, 0xfa, 0xcc, 0xcc, 0x40, 0xce, 0xf3,
+ 0x70, 0x4f, 0x3f, 0x7f, 0xe2, 0x0c, 0xea, 0x76, 0x4a, 0x35,
+ 0x4e, 0x47, 0xad, 0x2b, 0xa7, 0x97, 0x5d, 0x74, 0x43, 0x97,
+ 0x90, 0xd2, 0xfb, 0xd9, 0xf9, 0x96, 0x01, 0x33, 0x05, 0xed,
+ 0x7b, 0x03, 0x05, 0xad, 0xf8, 0x49, 0x03, 0x02, 0x82, 0x01,
+ 0x01, 0x00, 0xd4, 0x40, 0x17, 0x66, 0x10, 0x92, 0x95, 0xc8,
+ 0xec, 0x62, 0xa9, 0x7a, 0xcb, 0x93, 0x8e, 0xe6, 0x53, 0xd4,
+ 0x80, 0x48, 0x27, 0x4b, 0x41, 0xce, 0x61, 0xdf, 0xbf, 0x94,
+ 0xa4, 0x3d, 0x71, 0x03, 0x0b, 0xed, 0x25, 0x71, 0x98, 0xa4,
+ 0xd6, 0xd5, 0x4a, 0x57, 0xf5, 0x6c, 0x1b, 0xda, 0x21, 0x7d,
+ 0x35, 0x45, 0xb3, 0xf3, 0x6a, 0xd9, 0xd3, 0x43, 0xe8, 0x5c,
+ 0x54, 0x1c, 0x83, 0x1b, 0xb4, 0x5f, 0xf2, 0x97, 0x24, 0x2e,
+ 0xdc, 0x40, 0xde, 0x92, 0x23, 0x59, 0x8e, 0xbc, 0xd2, 0xa1,
+ 0xf2, 0xe0, 0x4c, 0xdd, 0x0b, 0xd1, 0xe7, 0xae, 0x65, 0xbc,
+ 0xb5, 0xf5, 0x5b, 0x98, 0xe9, 0xd7, 0xc2, 0xb7, 0x0e, 0x55,
+ 0x71, 0x0e, 0x3c, 0x0a, 0x24, 0x6b, 0xa6, 0xe6, 0x14, 0x61,
+ 0x11, 0xfd, 0x33, 0x42, 0x99, 0x2b, 0x84, 0x77, 0x74, 0x92,
+ 0x91, 0xf5, 0x79, 0x79, 0xcf, 0xad, 0x8e, 0x04, 0xef, 0x80,
+ 0x1e, 0x57, 0xf4, 0x14, 0xf5, 0x35, 0x09, 0x74, 0xb2, 0x13,
+ 0x71, 0x58, 0x6b, 0xea, 0x32, 0x5d, 0xf3, 0xd3, 0x76, 0x48,
+ 0x39, 0x10, 0x23, 0x84, 0x9d, 0xbe, 0x92, 0x77, 0x4a, 0xed,
+ 0x70, 0x3e, 0x1a, 0xa2, 0x6c, 0xb3, 0x81, 0x00, 0xc3, 0xc9,
+ 0xe4, 0x52, 0xc8, 0x24, 0x88, 0x0c, 0x41, 0xad, 0x87, 0x5a,
+ 0xea, 0xa3, 0x7a, 0x85, 0x1c, 0x5e, 0x31, 0x7f, 0xc3, 0x35,
+ 0xc6, 0xfa, 0x10, 0xc8, 0x75, 0x10, 0xc4, 0x96, 0x99, 0xe7,
+ 0xfe, 0x01, 0xb4, 0x74, 0xdb, 0xb4, 0x11, 0xc3, 0xc8, 0x8c,
+ 0xf6, 0xf7, 0x3b, 0x66, 0x50, 0xfc, 0xdb, 0xeb, 0xca, 0x47,
+ 0x85, 0x89, 0xe1, 0x65, 0xd9, 0x62, 0x34, 0x3c, 0x70, 0xd8,
+ 0x2e, 0xb4, 0x2f, 0x65, 0x3c, 0x4a, 0xa6, 0x2a, 0xe7, 0xc7,
+ 0xd8, 0x41, 0x8f, 0x8a, 0x43, 0xbf, 0x42, 0xf2, 0x4d, 0xbc,
+ 0xfc, 0x9e, 0x27, 0x95, 0xfb, 0x75, 0xff, 0xab, 0x02, 0x82,
+ 0x01, 0x00, 0x41, 0x2f, 0x44, 0x57, 0x6d, 0x12, 0x17, 0x5b,
+ 0x32, 0xc6, 0xb7, 0x6c, 0x57, 0x7a, 0x8a, 0x0e, 0x79, 0xef,
+ 0x72, 0xa8, 0x68, 0xda, 0x2d, 0x38, 0xe4, 0xbb, 0x8d, 0xf6,
+ 0x02, 0x65, 0xcf, 0x56, 0x13, 0xe1, 0x1a, 0xcb, 0x39, 0x80,
+ 0xa6, 0xb1, 0x32, 0x03, 0x1e, 0xdd, 0xbb, 0x35, 0xd9, 0xac,
+ 0x43, 0x89, 0x31, 0x08, 0x90, 0x92, 0x5e, 0x35, 0x3d, 0x7b,
+ 0x9c, 0x6f, 0x86, 0xcb, 0x17, 0xdd, 0x85, 0xe4, 0xed, 0x35,
+ 0x08, 0x8e, 0xc1, 0xf4, 0x05, 0xd8, 0x68, 0xc6, 0x63, 0x3c,
+ 0xf7, 0xff, 0xf7, 0x47, 0x33, 0x39, 0xc5, 0x3e, 0xb7, 0x0e,
+ 0x58, 0x35, 0x9d, 0x81, 0xea, 0xf8, 0x6a, 0x2c, 0x1c, 0x5a,
+ 0x68, 0x78, 0x64, 0x11, 0x6b, 0xc1, 0x3e, 0x4e, 0x7a, 0xbd,
+ 0x84, 0xcb, 0x0f, 0xc2, 0xb6, 0x85, 0x1d, 0xd3, 0x76, 0xc5,
+ 0x93, 0x6a, 0x69, 0x89, 0x56, 0x34, 0xdc, 0x4a, 0x9b, 0xbc,
+ 0xff, 0xa8, 0x0d, 0x6e, 0x35, 0x9c, 0x60, 0xa7, 0x23, 0x30,
+ 0xc7, 0x06, 0x64, 0x39, 0x8b, 0x94, 0x89, 0xee, 0xba, 0x7f,
+ 0x60, 0x8d, 0xfa, 0xb6, 0x97, 0x76, 0xdc, 0x51, 0x4a, 0x3c,
+ 0xeb, 0x3a, 0x14, 0x2c, 0x20, 0x60, 0x69, 0x4a, 0x86, 0xfe,
+ 0x8c, 0x21, 0x84, 0x49, 0x54, 0xb3, 0x20, 0xe1, 0x01, 0x7f,
+ 0x58, 0xdf, 0x7f, 0xb5, 0x21, 0x51, 0x8c, 0x47, 0x9f, 0x91,
+ 0xeb, 0x97, 0x3e, 0xf2, 0x54, 0xcf, 0x16, 0x46, 0xf9, 0xd9,
+ 0xb6, 0xe7, 0x64, 0xc9, 0xd0, 0x54, 0xea, 0x2f, 0xa1, 0xcf,
+ 0xa5, 0x7f, 0x28, 0x8d, 0x84, 0xec, 0xd5, 0x39, 0x03, 0x76,
+ 0x5b, 0x2d, 0x8e, 0x43, 0xf2, 0x01, 0x24, 0xc9, 0x6f, 0xc0,
+ 0xf5, 0x69, 0x6f, 0x7d, 0xb5, 0x85, 0xd2, 0x5f, 0x7f, 0x78,
+ 0x40, 0x07, 0x7f, 0x09, 0x15, 0xb5, 0x1f, 0x28, 0x65, 0x10,
+ 0xe4, 0x19, 0xa8, 0xc6, 0x9e, 0x8d, 0xdc, 0xcb, 0x02, 0x82,
+ 0x01, 0x00, 0x13, 0x01, 0xee, 0x56, 0x80, 0x93, 0x70, 0x00,
+ 0x7f, 0x52, 0xd2, 0x94, 0xa1, 0x98, 0x84, 0x4a, 0x92, 0x25,
+ 0x4c, 0x9b, 0xa9, 0x91, 0x2e, 0xc2, 0x79, 0xb7, 0x5c, 0xe3,
+ 0xc5, 0xd5, 0x8e, 0xc2, 0x54, 0x16, 0x17, 0xad, 0x55, 0x9b,
+ 0x25, 0x76, 0x12, 0x63, 0x50, 0x22, 0x2f, 0x58, 0x58, 0x79,
+ 0x6b, 0x04, 0xe3, 0xf9, 0x9f, 0x8f, 0x04, 0x41, 0x67, 0x94,
+ 0xa5, 0x1f, 0xac, 0x8a, 0x15, 0x9c, 0x26, 0x10, 0x6c, 0xf8,
+ 0x19, 0x57, 0x61, 0xd7, 0x3a, 0x7d, 0x31, 0xb0, 0x2d, 0x38,
+ 0xbd, 0x94, 0x62, 0xad, 0xc4, 0xfa, 0x36, 0x42, 0x42, 0xf0,
+ 0x24, 0x67, 0x65, 0x9d, 0x8b, 0x0b, 0x7c, 0x6f, 0x82, 0x44,
+ 0x1a, 0x8c, 0xc8, 0xc9, 0xab, 0xbb, 0x4c, 0x45, 0xfc, 0x7b,
+ 0x38, 0xee, 0x30, 0xe1, 0xfc, 0xef, 0x8d, 0xbc, 0x58, 0xdf,
+ 0x2b, 0x5d, 0x0d, 0x54, 0xe0, 0x49, 0x4d, 0x97, 0x99, 0x8f,
+ 0x22, 0xa8, 0x83, 0xbe, 0x40, 0xbb, 0x50, 0x2e, 0x78, 0x28,
+ 0x0f, 0x95, 0x78, 0x8c, 0x8f, 0x98, 0x24, 0x56, 0xc2, 0x97,
+ 0xf3, 0x2c, 0x43, 0xd2, 0x03, 0x82, 0x66, 0x81, 0x72, 0x5f,
+ 0x53, 0x16, 0xec, 0xb1, 0xb1, 0x04, 0x5e, 0x40, 0x20, 0x48,
+ 0x7b, 0x3f, 0x02, 0x97, 0x6a, 0xeb, 0x96, 0x12, 0x21, 0x35,
+ 0xfe, 0x1f, 0x47, 0xc0, 0x95, 0xea, 0xc5, 0x8a, 0x08, 0x84,
+ 0x4f, 0x5e, 0x63, 0x94, 0x60, 0x0f, 0x71, 0x5b, 0x7f, 0x4a,
+ 0xec, 0x4f, 0x60, 0xc6, 0xba, 0x4a, 0x24, 0xf1, 0x20, 0x8b,
+ 0xa7, 0x2e, 0x3a, 0xce, 0x8d, 0xe0, 0x27, 0x1d, 0xb5, 0x8e,
+ 0xb4, 0x21, 0xc5, 0xe2, 0xa6, 0x16, 0x0a, 0x51, 0x83, 0x55,
+ 0x88, 0xd1, 0x30, 0x11, 0x63, 0xd5, 0xd7, 0x8d, 0xae, 0x16,
+ 0x12, 0x82, 0xc4, 0x85, 0x00, 0x4e, 0x27, 0x83, 0xa5, 0x7c,
+ 0x90, 0x2e, 0xe5, 0xa2, 0xa3, 0xd3, 0x4c, 0x63, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x86, 0x08, 0x98, 0x98, 0xa5, 0x00, 0x05,
+ 0x39, 0x77, 0xd9, 0x66, 0xb3, 0xcf, 0xca, 0xa0, 0x71, 0xb3,
+ 0x50, 0xce, 0x3d, 0xb1, 0x93, 0x95, 0x35, 0xc4, 0xd4, 0x2e,
+ 0x90, 0xdf, 0x0f, 0xfc, 0x60, 0xc1, 0x94, 0x68, 0x61, 0x43,
+ 0xca, 0x9a, 0x23, 0x4a, 0x1e, 0x45, 0x72, 0x99, 0xb5, 0x1e,
+ 0x61, 0x8d, 0x77, 0x0f, 0xa0, 0xbb, 0xd7, 0x77, 0xb4, 0x2a,
+ 0x15, 0x11, 0x88, 0x2d, 0xb3, 0x56, 0x61, 0x5e, 0x6a, 0xed,
+ 0xa4, 0x46, 0x4a, 0x3f, 0x50, 0x11, 0xd6, 0xba, 0xb6, 0xd7,
+ 0x95, 0x65, 0x53, 0xc3, 0xa1, 0x8f, 0xe0, 0xa3, 0xf5, 0x1c,
+ 0xfd, 0xaf, 0x6e, 0x43, 0xd7, 0x17, 0xa7, 0xd3, 0x81, 0x1b,
+ 0xa4, 0xdf, 0xe0, 0x97, 0x8a, 0x46, 0x03, 0xd3, 0x46, 0x0e,
+ 0x83, 0x48, 0x4e, 0xd2, 0x02, 0xcb, 0xc0, 0xad, 0x79, 0x95,
+ 0x8c, 0x96, 0xba, 0x40, 0x34, 0x11, 0x71, 0x5e, 0xe9, 0x11,
+ 0xf9, 0xc5, 0x4a, 0x5e, 0x91, 0x9d, 0xf5, 0x92, 0x4f, 0xeb,
+ 0xc6, 0x70, 0x02, 0x2d, 0x3d, 0x04, 0xaa, 0xe9, 0x3a, 0x8e,
+ 0xd5, 0xa8, 0xad, 0xf7, 0xce, 0x0d, 0x16, 0xb2, 0xec, 0x0a,
+ 0x9c, 0xf5, 0x94, 0x39, 0xb9, 0x8a, 0xfc, 0x1e, 0xf9, 0xcc,
+ 0xf2, 0x5f, 0x21, 0x31, 0x74, 0x72, 0x6b, 0x64, 0xae, 0x35,
+ 0x61, 0x8d, 0x0d, 0xcb, 0xe7, 0xda, 0x39, 0xca, 0xf3, 0x21,
+ 0x66, 0x0b, 0x95, 0xd7, 0x0a, 0x7c, 0xca, 0xa1, 0xa9, 0x5a,
+ 0xe8, 0xac, 0xe0, 0x71, 0x54, 0xaf, 0x28, 0xcf, 0xd5, 0x70,
+ 0x89, 0xe0, 0xf3, 0x9e, 0x43, 0x6c, 0x8d, 0x7b, 0x99, 0x01,
+ 0x68, 0x4d, 0xa1, 0x45, 0x46, 0x0c, 0x43, 0xbc, 0xcc, 0x2c,
+ 0xdd, 0xc5, 0x46, 0xc8, 0x4e, 0x0e, 0xbe, 0xed, 0xb9, 0x26,
+ 0xab, 0x2e, 0xdb, 0xeb, 0x8f, 0xff, 0xdb, 0xb0, 0xc6, 0x55,
+ 0xaf, 0xf8, 0x2a, 0x91, 0x9d, 0x50, 0x44, 0x21, 0x17,
+};
+
+static unsigned char test7680[] = {
+ 0x30, 0x82, 0x11, 0x09, 0x02, 0x01, 0x00, 0x02, 0x82, 0x03,
+ 0xc1, 0x00, 0xe3, 0x27, 0x46, 0x99, 0xb5, 0x17, 0xab, 0xfa,
+ 0x65, 0x05, 0x7a, 0x06, 0x81, 0x14, 0xce, 0x43, 0x21, 0x49,
+ 0x0f, 0x08, 0xf1, 0x70, 0xb4, 0xc1, 0x10, 0xd1, 0x87, 0xf8,
+ 0x29, 0x91, 0x36, 0x66, 0x2d, 0xbe, 0x7b, 0x1d, 0xa2, 0x0b,
+ 0x20, 0x38, 0xd9, 0x8e, 0x78, 0x27, 0xcf, 0xb5, 0x45, 0x58,
+ 0x3d, 0xf4, 0xda, 0xf0, 0xdc, 0x21, 0x17, 0x52, 0xcd, 0x68,
+ 0xe2, 0x81, 0xac, 0x88, 0x61, 0x10, 0xbc, 0xb0, 0x7f, 0xe4,
+ 0xf3, 0x78, 0xb7, 0x28, 0x6c, 0x5f, 0x5c, 0xc2, 0x8d, 0x3d,
+ 0xb0, 0x87, 0x41, 0x15, 0x2e, 0x09, 0x5f, 0xea, 0x06, 0x7f,
+ 0xe9, 0x35, 0x18, 0x90, 0x50, 0xad, 0xf6, 0xb9, 0xfd, 0x33,
+ 0x02, 0x1a, 0x99, 0x9e, 0xa5, 0x7d, 0x2c, 0x3b, 0x24, 0xe7,
+ 0x31, 0x35, 0x73, 0x9a, 0xb0, 0xfe, 0x03, 0xfc, 0xc6, 0x98,
+ 0x78, 0xd9, 0x66, 0x95, 0xa5, 0x12, 0xbc, 0x1e, 0x82, 0xbc,
+ 0xf1, 0xc5, 0x31, 0xcd, 0xa6, 0xb1, 0x0c, 0x02, 0xbf, 0x7f,
+ 0xb7, 0xaf, 0x5f, 0xd6, 0xed, 0xf7, 0xc1, 0x59, 0x86, 0x3a,
+ 0x35, 0x95, 0x54, 0x21, 0x8d, 0x6a, 0xb3, 0xd1, 0x2b, 0x71,
+ 0xf5, 0xf1, 0x66, 0x00, 0xb1, 0x88, 0xee, 0x3b, 0xa4, 0x41,
+ 0x52, 0x1a, 0xf5, 0x0e, 0x32, 0xb6, 0xbf, 0x52, 0xab, 0x51,
+ 0x55, 0x91, 0x32, 0x4f, 0xaf, 0x91, 0xac, 0xf7, 0xff, 0x8e,
+ 0x3b, 0x2b, 0x61, 0xe9, 0x6d, 0x1d, 0x68, 0x80, 0x90, 0x79,
+ 0x34, 0x96, 0xca, 0x49, 0x43, 0x7c, 0x89, 0x4e, 0x5e, 0x31,
+ 0xb5, 0xce, 0x01, 0x9b, 0x09, 0xaf, 0x92, 0x06, 0x24, 0xe7,
+ 0x22, 0x35, 0xcc, 0xa2, 0x0b, 0xfb, 0x5b, 0x87, 0x65, 0x71,
+ 0xff, 0x64, 0x3e, 0xf9, 0xe8, 0x33, 0xa0, 0xc3, 0x4e, 0xb2,
+ 0x41, 0x98, 0x54, 0xeb, 0x13, 0x99, 0xfb, 0x32, 0x78, 0x7e,
+ 0xda, 0x4f, 0xd3, 0x46, 0x6a, 0xb5, 0x78, 0x81, 0x3f, 0x04,
+ 0x13, 0x5f, 0x67, 0xaf, 0x88, 0xa5, 0x9e, 0x0d, 0xc5, 0xf3,
+ 0xe7, 0x4c, 0x51, 0xf5, 0x51, 0x4a, 0xa4, 0x58, 0x64, 0xd9,
+ 0xa2, 0x32, 0x54, 0x36, 0xce, 0x38, 0xd8, 0xc2, 0x0e, 0x0d,
+ 0x60, 0x8e, 0x32, 0x7f, 0x90, 0x8a, 0xbc, 0x88, 0xbe, 0x6a,
+ 0xc0, 0x47, 0x0f, 0x02, 0x41, 0xff, 0x3b, 0x7e, 0xc5, 0xa6,
+ 0x33, 0x1d, 0x19, 0xd1, 0xd5, 0x67, 0x6c, 0xbf, 0x16, 0xb0,
+ 0x7e, 0x80, 0x10, 0xbf, 0x7f, 0xdd, 0xd0, 0xf4, 0xc3, 0x94,
+ 0x2c, 0x9a, 0x2c, 0xda, 0x69, 0x4e, 0xd6, 0x7b, 0x40, 0x4d,
+ 0x2a, 0x27, 0xcb, 0x5a, 0xe5, 0x2d, 0x3f, 0x7d, 0x51, 0x9d,
+ 0x9f, 0x70, 0xde, 0x50, 0xb1, 0xd3, 0xd2, 0x38, 0x4d, 0x1c,
+ 0xca, 0xc2, 0x1e, 0x80, 0xd0, 0x36, 0x82, 0x04, 0xe6, 0x17,
+ 0x79, 0x9f, 0x2e, 0xc9, 0xed, 0x2b, 0xd5, 0x1b, 0xfa, 0x7d,
+ 0x1a, 0x80, 0xb5, 0x0e, 0x2f, 0x05, 0xbe, 0x4a, 0x1b, 0xfe,
+ 0x0a, 0xad, 0x01, 0xde, 0x91, 0xc8, 0xf9, 0x81, 0xbe, 0xc7,
+ 0xaf, 0xe7, 0x87, 0xed, 0x9d, 0xb8, 0x6c, 0xad, 0x65, 0xed,
+ 0x5e, 0xd3, 0x67, 0x8c, 0x62, 0x3a, 0xe7, 0xfd, 0x67, 0xe0,
+ 0xbb, 0x57, 0xaf, 0x56, 0xeb, 0x4a, 0x58, 0x6e, 0xad, 0xf2,
+ 0xbe, 0xc3, 0x70, 0x29, 0xf8, 0xeb, 0x68, 0x45, 0xa0, 0xbd,
+ 0xcd, 0xa5, 0xb4, 0xd9, 0x01, 0xb7, 0x44, 0xeb, 0x97, 0xf3,
+ 0x0c, 0x56, 0xe4, 0x26, 0xd0, 0xa5, 0xb1, 0xa3, 0x49, 0x6e,
+ 0x88, 0xf2, 0x22, 0xe2, 0x7b, 0x58, 0x3a, 0xd9, 0x52, 0xa4,
+ 0xb1, 0x4c, 0x5c, 0x7c, 0xf0, 0x88, 0x7b, 0x9f, 0x06, 0xe9,
+ 0x32, 0x4e, 0xf2, 0x64, 0x83, 0x8b, 0xa2, 0xea, 0x1d, 0x25,
+ 0xf1, 0x8d, 0x16, 0x8b, 0xe0, 0xab, 0xd2, 0xe9, 0xe4, 0x6b,
+ 0x7d, 0x76, 0x98, 0x22, 0x53, 0x31, 0x6b, 0xcc, 0xf1, 0xe5,
+ 0x1d, 0xd7, 0xa5, 0xb0, 0xea, 0x6b, 0x38, 0x14, 0x0c, 0x06,
+ 0x10, 0x27, 0xd8, 0x33, 0xf3, 0x9a, 0xae, 0x94, 0xdd, 0x0b,
+ 0xb4, 0x6d, 0xe5, 0x91, 0xdd, 0xf1, 0x0f, 0x27, 0xa4, 0x94,
+ 0x55, 0xf0, 0xde, 0x07, 0x29, 0xe6, 0x3f, 0x26, 0x19, 0xa1,
+ 0xdd, 0xd1, 0x06, 0x99, 0xda, 0x54, 0x23, 0x3c, 0xf5, 0x5c,
+ 0x2e, 0x96, 0xa9, 0x21, 0x23, 0x25, 0x2e, 0x6f, 0xf1, 0xf9,
+ 0x11, 0x54, 0xe5, 0x7b, 0xb9, 0x1f, 0x11, 0xe2, 0x9e, 0x6b,
+ 0x61, 0x8b, 0xa3, 0x8b, 0xc1, 0x20, 0x9b, 0xfb, 0x51, 0xef,
+ 0xbb, 0xb9, 0xf6, 0xaf, 0x66, 0xb3, 0x2c, 0x25, 0xef, 0x76,
+ 0xcb, 0xbf, 0x7a, 0x93, 0x2f, 0xe1, 0x17, 0x56, 0xc1, 0x00,
+ 0x33, 0xb5, 0xd9, 0x91, 0x05, 0x31, 0xcc, 0x72, 0xcd, 0x4a,
+ 0x93, 0x9a, 0xe3, 0x21, 0x42, 0x9e, 0xb8, 0x4e, 0x6c, 0x27,
+ 0x93, 0xf0, 0x7f, 0x22, 0xdb, 0xe5, 0xb3, 0xa3, 0xf7, 0xe7,
+ 0x80, 0xbb, 0x91, 0xca, 0xf7, 0xe8, 0x52, 0xb8, 0x11, 0x64,
+ 0x66, 0x25, 0x94, 0xf8, 0x6f, 0x0b, 0x3b, 0xb7, 0xff, 0x80,
+ 0x9e, 0x36, 0xe9, 0x88, 0x2e, 0xab, 0x05, 0xbf, 0x99, 0x9f,
+ 0x2b, 0x4f, 0xc6, 0xb1, 0x13, 0x5b, 0x06, 0xff, 0x0a, 0x7b,
+ 0xbc, 0x7f, 0x07, 0xa0, 0x35, 0xc2, 0x2d, 0x44, 0x3e, 0xad,
+ 0x44, 0xcb, 0x47, 0x18, 0x26, 0x71, 0x7b, 0x17, 0xc9, 0x6d,
+ 0xb5, 0x4b, 0xcf, 0xdf, 0x14, 0x2c, 0x6c, 0xdf, 0x21, 0xce,
+ 0x93, 0x49, 0x34, 0x69, 0x49, 0xfd, 0x3e, 0x71, 0x5b, 0xfa,
+ 0x07, 0xc5, 0x7e, 0x5e, 0x54, 0x1a, 0x3c, 0xa6, 0x29, 0xb5,
+ 0xbf, 0x0d, 0xf1, 0xc6, 0xa4, 0x61, 0xd6, 0x17, 0x1d, 0xf0,
+ 0xa2, 0x78, 0x8f, 0xbc, 0x7e, 0x0c, 0xb4, 0xf0, 0x1e, 0x05,
+ 0xea, 0xb5, 0xad, 0x68, 0x95, 0x0b, 0x27, 0xb4, 0x29, 0x7c,
+ 0x70, 0x2a, 0x9a, 0x0a, 0x39, 0xd4, 0x76, 0xb7, 0x72, 0x30,
+ 0x5e, 0xae, 0x9c, 0x4a, 0x55, 0xc7, 0x46, 0xd7, 0x5f, 0xbe,
+ 0x10, 0x61, 0x25, 0x18, 0x7a, 0x9f, 0xd3, 0x05, 0x3d, 0x6f,
+ 0x9a, 0x1e, 0xec, 0x2b, 0x03, 0xe0, 0x49, 0x6a, 0x9c, 0xd6,
+ 0xdb, 0xc2, 0xa1, 0xe1, 0x0a, 0xbb, 0x31, 0x42, 0xc8, 0x43,
+ 0x4e, 0x7c, 0xa9, 0x7c, 0x60, 0xea, 0xbe, 0xf1, 0x8b, 0xe8,
+ 0xb2, 0x90, 0x83, 0x14, 0x21, 0xe4, 0xb3, 0x0d, 0x7c, 0x63,
+ 0x3c, 0x98, 0x55, 0xc6, 0x44, 0xa6, 0xa8, 0x1e, 0x42, 0xb7,
+ 0x89, 0xa8, 0xbd, 0xb8, 0x34, 0x3d, 0x09, 0x80, 0x99, 0x73,
+ 0x9f, 0xaf, 0x17, 0x56, 0xf2, 0x73, 0x3e, 0x1e, 0x6e, 0xe9,
+ 0x18, 0xa0, 0x5b, 0x69, 0xce, 0xfd, 0x3d, 0x77, 0x81, 0x95,
+ 0x3b, 0xf1, 0xde, 0x26, 0xe9, 0x27, 0xef, 0x92, 0x2a, 0x97,
+ 0xdc, 0x95, 0xa5, 0xa3, 0xb0, 0xfb, 0x96, 0x89, 0x4f, 0xe6,
+ 0xc1, 0x42, 0x0b, 0xfd, 0xb4, 0x6d, 0x0a, 0x9f, 0x9b, 0x31,
+ 0xd8, 0x21, 0x38, 0x8a, 0xee, 0xb6, 0x5c, 0x12, 0xa8, 0xb4,
+ 0x07, 0x79, 0x41, 0xa7, 0x7f, 0x13, 0x74, 0xad, 0x0b, 0xee,
+ 0x28, 0x52, 0xac, 0x2f, 0x4d, 0x30, 0x1c, 0xc5, 0xa6, 0xa5,
+ 0x61, 0x42, 0xbd, 0xe1, 0x4f, 0xd3, 0xec, 0x66, 0xf2, 0x63,
+ 0xf4, 0x93, 0xdb, 0x35, 0x2d, 0x3b, 0x71, 0x25, 0x09, 0xde,
+ 0xda, 0x46, 0xda, 0xe2, 0xa7, 0xa3, 0xdf, 0xcd, 0xbf, 0x58,
+ 0x05, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x03,
+ 0xc0, 0x5f, 0xd5, 0x15, 0x1b, 0x09, 0xe4, 0xa7, 0xc0, 0xa6,
+ 0xd8, 0x0d, 0xa8, 0x2a, 0xd3, 0x1d, 0x46, 0x03, 0x07, 0xf0,
+ 0x98, 0xe4, 0x4b, 0x99, 0x66, 0x8e, 0x72, 0xe7, 0xbb, 0x51,
+ 0xc6, 0x1a, 0xbe, 0x36, 0xf4, 0x52, 0xba, 0xa8, 0xbf, 0xaa,
+ 0xe3, 0x71, 0x1d, 0x83, 0x21, 0xc0, 0xa6, 0x88, 0x4f, 0xf7,
+ 0x2b, 0x93, 0x26, 0xe4, 0xa7, 0xed, 0x50, 0x18, 0xaa, 0xf4,
+ 0x4c, 0xa2, 0xfe, 0x92, 0x7c, 0xde, 0x2e, 0x54, 0x76, 0xc2,
+ 0x25, 0x1e, 0x98, 0xa6, 0x48, 0x01, 0x39, 0x6f, 0x1f, 0x24,
+ 0x97, 0x9b, 0x64, 0x95, 0x1c, 0x8d, 0x63, 0x8d, 0x44, 0x6f,
+ 0x9d, 0xdf, 0xf4, 0x1a, 0xa5, 0x9a, 0x1e, 0xd3, 0x6c, 0xae,
+ 0xa9, 0x8c, 0x3f, 0xfb, 0x2f, 0x78, 0xf6, 0xa6, 0xd6, 0x06,
+ 0xd3, 0xb7, 0x26, 0xff, 0x1e, 0xdb, 0x8d, 0xcc, 0x37, 0x4d,
+ 0x5c, 0xe2, 0xc3, 0xa5, 0x75, 0xe6, 0xf9, 0xb4, 0x4c, 0x84,
+ 0x6f, 0x9e, 0x58, 0x55, 0xc8, 0x01, 0xfa, 0x32, 0xd2, 0x6e,
+ 0x2b, 0x45, 0xf2, 0xc6, 0x48, 0xad, 0x40, 0xd8, 0xb9, 0x3c,
+ 0x1b, 0xf8, 0xf7, 0x82, 0xd3, 0x0e, 0x73, 0xe3, 0xb1, 0x5b,
+ 0x82, 0x71, 0x77, 0x3f, 0x6f, 0x36, 0x9a, 0xe0, 0xec, 0x51,
+ 0xf8, 0x5f, 0x84, 0x92, 0xee, 0xb8, 0x7e, 0xe7, 0x1a, 0x14,
+ 0x50, 0x82, 0x7a, 0x4d, 0xe6, 0xd6, 0xa3, 0x76, 0x24, 0x8a,
+ 0x5f, 0xfe, 0x19, 0xdd, 0xd7, 0xf7, 0x5b, 0xae, 0x18, 0x04,
+ 0x90, 0xcd, 0x5c, 0xe5, 0x64, 0xe8, 0x04, 0xb1, 0x06, 0xa5,
+ 0xdd, 0xf8, 0x9d, 0x71, 0x13, 0xaa, 0x36, 0x7f, 0x61, 0x27,
+ 0xf4, 0xac, 0x95, 0x7d, 0x1a, 0x99, 0x7d, 0xe0, 0xd5, 0x9c,
+ 0x5a, 0xad, 0x9a, 0xff, 0x54, 0xb0, 0xb1, 0x55, 0x45, 0x2d,
+ 0x19, 0x58, 0x52, 0x28, 0xdd, 0xe0, 0xb5, 0x65, 0x52, 0x97,
+ 0x45, 0xf0, 0x2b, 0x98, 0x1f, 0x61, 0x6c, 0x9d, 0xaa, 0x59,
+ 0x85, 0xf9, 0x97, 0x7b, 0xbd, 0xeb, 0x95, 0x81, 0xfb, 0x29,
+ 0x8c, 0xf0, 0x52, 0xdf, 0xed, 0xee, 0xb2, 0x00, 0x32, 0x35,
+ 0x14, 0xa8, 0xa4, 0xca, 0x91, 0xff, 0x18, 0xb7, 0x96, 0xfb,
+ 0x32, 0x62, 0xa9, 0xa0, 0xd0, 0x77, 0x43, 0xf5, 0x99, 0xd1,
+ 0xee, 0xe8, 0xad, 0x1a, 0x2c, 0xd4, 0xeb, 0xe1, 0xf5, 0x01,
+ 0x41, 0x78, 0xc0, 0x27, 0x19, 0x50, 0x2e, 0xba, 0x22, 0xd1,
+ 0xeb, 0xb3, 0xa5, 0x27, 0x0b, 0xec, 0xf9, 0x26, 0x7e, 0x1f,
+ 0xe7, 0x17, 0x9f, 0x39, 0xa8, 0x72, 0x22, 0x63, 0x79, 0x6a,
+ 0x9c, 0x89, 0x55, 0x9a, 0xb4, 0x61, 0x41, 0xbc, 0xaa, 0x14,
+ 0x37, 0x29, 0x03, 0xc0, 0x52, 0x4e, 0x31, 0x44, 0x8f, 0x2e,
+ 0x17, 0x81, 0x88, 0xf4, 0xce, 0xda, 0x41, 0xb8, 0xd5, 0x14,
+ 0x91, 0x8c, 0xca, 0xd2, 0x0d, 0x99, 0x06, 0x09, 0xc2, 0xb7,
+ 0xe8, 0xae, 0xfa, 0x01, 0xea, 0x99, 0x62, 0x68, 0xb6, 0xdf,
+ 0xc8, 0x27, 0xae, 0xbf, 0xb0, 0x9b, 0x5b, 0x1a, 0xa2, 0xe2,
+ 0x5a, 0x7a, 0xe5, 0x4b, 0x92, 0x1f, 0xff, 0x73, 0xae, 0x16,
+ 0x40, 0x78, 0x42, 0x28, 0xbb, 0x13, 0x5e, 0xbc, 0x71, 0x7a,
+ 0x78, 0x3e, 0xd8, 0x1b, 0xc2, 0x2c, 0xd6, 0xdc, 0xfa, 0x39,
+ 0x72, 0xf8, 0xa2, 0x2c, 0x8b, 0x1c, 0x5d, 0xab, 0xb8, 0x07,
+ 0xc7, 0xae, 0x29, 0x93, 0x68, 0xbf, 0x61, 0xe9, 0xa4, 0x37,
+ 0x83, 0x7d, 0x13, 0xc7, 0x18, 0xf0, 0x7d, 0xa4, 0x20, 0x47,
+ 0x14, 0x68, 0x95, 0x46, 0x56, 0x6d, 0xd5, 0x7b, 0xe1, 0x51,
+ 0x8f, 0x96, 0xc1, 0x7b, 0x35, 0x09, 0x7a, 0x89, 0x0e, 0xdf,
+ 0x12, 0xd5, 0xe1, 0x9c, 0x2a, 0x94, 0x95, 0x43, 0x93, 0x48,
+ 0xa6, 0x23, 0xe6, 0xd8, 0xf2, 0xb8, 0x0e, 0xba, 0x6d, 0x61,
+ 0x03, 0xaf, 0x40, 0x63, 0x2b, 0x2f, 0xee, 0x61, 0x4c, 0xc4,
+ 0x70, 0x3d, 0x78, 0xc1, 0x4f, 0x8e, 0x0b, 0x9b, 0x06, 0x35,
+ 0x6d, 0x6d, 0x83, 0x37, 0xbb, 0x39, 0x7d, 0x7f, 0x33, 0x93,
+ 0xc4, 0xeb, 0x8e, 0xfc, 0xda, 0xf0, 0x54, 0xfe, 0x1d, 0xc4,
+ 0xd3, 0x83, 0x99, 0xdf, 0x65, 0xee, 0x00, 0x7d, 0x86, 0x27,
+ 0xd4, 0x3a, 0x6b, 0xe6, 0x82, 0x8e, 0x58, 0x2d, 0x03, 0x38,
+ 0xef, 0x6c, 0x82, 0x87, 0x18, 0x3b, 0x47, 0xe7, 0xbc, 0xe1,
+ 0x58, 0x70, 0x4d, 0x46, 0x96, 0x34, 0x60, 0x96, 0x15, 0x09,
+ 0x3c, 0x84, 0x40, 0xaf, 0x80, 0x32, 0x75, 0xc7, 0x23, 0x6c,
+ 0xfb, 0x1d, 0x57, 0x73, 0x19, 0x09, 0xe8, 0x1a, 0x4c, 0x02,
+ 0x5c, 0x7e, 0x4e, 0xbe, 0x75, 0xf8, 0x73, 0xff, 0x2d, 0x54,
+ 0x19, 0x55, 0xf5, 0xf4, 0x1b, 0xc9, 0xbc, 0xc2, 0x19, 0xcb,
+ 0xb7, 0x4e, 0x6a, 0x0d, 0xff, 0xca, 0x7d, 0xd0, 0x88, 0x91,
+ 0x8b, 0x9b, 0x21, 0xa4, 0xa2, 0x43, 0x0d, 0xbc, 0x9e, 0x73,
+ 0x7d, 0x54, 0x7d, 0x95, 0xcc, 0x63, 0x5e, 0xc1, 0xb8, 0xe6,
+ 0x27, 0xff, 0x20, 0x07, 0xe8, 0x6e, 0x7e, 0xf2, 0x0f, 0x5a,
+ 0x09, 0xef, 0xe5, 0x4d, 0x80, 0x39, 0x95, 0xd5, 0xf4, 0xee,
+ 0x3b, 0xca, 0x7c, 0x73, 0xf8, 0x39, 0x5a, 0xc1, 0x1d, 0x7d,
+ 0x94, 0x72, 0x32, 0xad, 0x58, 0xe2, 0xfc, 0x71, 0x6e, 0x66,
+ 0xaa, 0xa1, 0x59, 0xd6, 0xac, 0xab, 0xbe, 0x8c, 0x53, 0x99,
+ 0xcd, 0xe8, 0x2d, 0xb5, 0xb3, 0x46, 0x58, 0x2e, 0x16, 0xd7,
+ 0x4d, 0x8b, 0x7d, 0x4a, 0xb1, 0x4c, 0x85, 0x91, 0x1b, 0x57,
+ 0x54, 0xf8, 0x14, 0x59, 0xdb, 0xc4, 0x2c, 0x9c, 0x08, 0x6d,
+ 0x3d, 0xd7, 0xf6, 0xa6, 0xe6, 0xb3, 0x2a, 0xe7, 0x29, 0x1c,
+ 0xab, 0xb4, 0xed, 0x13, 0x19, 0xf8, 0xb6, 0x60, 0x92, 0x44,
+ 0x53, 0xd4, 0xa9, 0x7e, 0xba, 0x21, 0xa2, 0xdc, 0x6e, 0xa5,
+ 0x5e, 0x53, 0x59, 0x3c, 0x52, 0x61, 0x7b, 0x5f, 0x19, 0xad,
+ 0xc8, 0x6d, 0x68, 0x8d, 0x7a, 0xc9, 0xd6, 0xef, 0xeb, 0x67,
+ 0x4f, 0xca, 0xe7, 0xf6, 0x29, 0x36, 0x97, 0xfb, 0x3e, 0x37,
+ 0x95, 0x85, 0x71, 0x70, 0xf6, 0x63, 0x86, 0x2a, 0x29, 0xd7,
+ 0x9a, 0x96, 0x76, 0xa7, 0x47, 0x98, 0x4e, 0x06, 0x31, 0xaf,
+ 0xf3, 0x4f, 0x2a, 0x65, 0x90, 0x6a, 0x4b, 0x8e, 0x43, 0x79,
+ 0xe2, 0xdd, 0xce, 0x08, 0x1c, 0x01, 0xec, 0x38, 0x41, 0xdd,
+ 0x19, 0xd8, 0xf3, 0x36, 0x03, 0x35, 0x03, 0xaf, 0x1c, 0x45,
+ 0x3c, 0xac, 0x13, 0xaa, 0x36, 0x16, 0x48, 0x77, 0xb3, 0xbe,
+ 0xa3, 0xb3, 0x9d, 0x7f, 0x20, 0xca, 0x74, 0x65, 0xac, 0x93,
+ 0xa7, 0x54, 0xad, 0xc8, 0x68, 0x0e, 0xf8, 0x44, 0x1f, 0xad,
+ 0x2c, 0xb7, 0x9a, 0x9a, 0x07, 0xe5, 0xcd, 0x87, 0xe0, 0x14,
+ 0xb5, 0xaf, 0xd3, 0xd7, 0xcf, 0x13, 0x9f, 0x3b, 0xbd, 0xfe,
+ 0x29, 0x0b, 0x72, 0xf5, 0x4c, 0x54, 0x94, 0xc7, 0x66, 0xec,
+ 0xa8, 0x41, 0x96, 0x3d, 0x17, 0xed, 0x19, 0xc0, 0x82, 0x3e,
+ 0x5f, 0x9a, 0x91, 0xfe, 0xd1, 0x2f, 0xb8, 0x94, 0xaa, 0x58,
+ 0x68, 0x95, 0x31, 0x87, 0x57, 0x9a, 0x75, 0x94, 0x4d, 0x38,
+ 0x7d, 0x56, 0x82, 0x81, 0x9c, 0xb9, 0x34, 0x2b, 0xe7, 0x40,
+ 0xd9, 0x3c, 0x77, 0x5b, 0x95, 0x51, 0x06, 0x11, 0x41, 0xe3,
+ 0x8b, 0xb7, 0x32, 0xeb, 0xe1, 0x05, 0x1b, 0x10, 0xa8, 0x0e,
+ 0xa1, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xfa, 0x38, 0x34, 0xfe,
+ 0x55, 0x87, 0x71, 0x62, 0x47, 0x00, 0x33, 0x64, 0x67, 0x70,
+ 0x79, 0x76, 0xdf, 0xfe, 0xc3, 0x28, 0x38, 0xdf, 0x90, 0xd4,
+ 0xc0, 0xee, 0x98, 0xbf, 0x9d, 0x9b, 0x85, 0xd8, 0x61, 0x65,
+ 0xa5, 0x70, 0xf5, 0xd2, 0x2c, 0xbf, 0x2f, 0xb5, 0x55, 0x79,
+ 0x92, 0x13, 0xba, 0x4d, 0x3c, 0x39, 0xbf, 0xd5, 0x31, 0x13,
+ 0x7a, 0x31, 0xf4, 0x8b, 0xce, 0xf8, 0xd0, 0xd3, 0x9b, 0xe2,
+ 0xee, 0x31, 0xdb, 0xba, 0xcc, 0x1a, 0xba, 0x1c, 0x8d, 0xee,
+ 0xea, 0xcb, 0xd3, 0x5a, 0xad, 0x87, 0xd6, 0xf9, 0x15, 0x2f,
+ 0x6e, 0x00, 0x06, 0x74, 0x25, 0x8d, 0xff, 0xc8, 0xa6, 0x11,
+ 0x1c, 0xe8, 0x16, 0x1a, 0xde, 0x53, 0x05, 0xb9, 0x53, 0x55,
+ 0x28, 0x83, 0x3d, 0xbe, 0x61, 0x0c, 0xc4, 0x98, 0x7d, 0xf6,
+ 0xec, 0x36, 0xc3, 0xe5, 0xe7, 0x1d, 0x14, 0x64, 0xcb, 0x0d,
+ 0x62, 0x5d, 0x7a, 0xcd, 0x88, 0xfc, 0x66, 0x4e, 0xf9, 0x36,
+ 0x47, 0x95, 0x18, 0x3a, 0x48, 0x2a, 0xff, 0x62, 0x8f, 0x6c,
+ 0xe2, 0xc2, 0xe9, 0xd3, 0x6a, 0x45, 0x5c, 0xf5, 0x89, 0x53,
+ 0x5c, 0xbe, 0xcf, 0xad, 0x87, 0x22, 0x9c, 0x31, 0x48, 0xdb,
+ 0xd8, 0xe4, 0xe5, 0x38, 0xae, 0xc2, 0xb0, 0xd2, 0xba, 0xb7,
+ 0x30, 0x53, 0x2d, 0xb1, 0x35, 0xf1, 0x58, 0x0f, 0x8a, 0x06,
+ 0x51, 0x76, 0xb9, 0x2c, 0x32, 0xe0, 0xd1, 0xaa, 0x82, 0x34,
+ 0x69, 0x71, 0x1c, 0x5f, 0x35, 0xa8, 0x9d, 0x11, 0xac, 0x13,
+ 0xdb, 0x7b, 0xf6, 0x93, 0xe3, 0xb9, 0xbd, 0xd9, 0xb2, 0x86,
+ 0xff, 0x61, 0x88, 0x2b, 0x72, 0x5c, 0x84, 0xe1, 0x0c, 0x72,
+ 0xab, 0x44, 0xff, 0x23, 0x13, 0xaf, 0xd1, 0x5a, 0xd3, 0xea,
+ 0x73, 0xfe, 0xd5, 0xa4, 0x7d, 0x9e, 0x4e, 0xac, 0x03, 0x93,
+ 0x72, 0x14, 0x2d, 0x96, 0x6f, 0xee, 0xb4, 0xcd, 0x4e, 0xab,
+ 0xea, 0x71, 0x93, 0x81, 0xe0, 0x3d, 0xcd, 0x61, 0x96, 0x25,
+ 0x76, 0xbd, 0xc4, 0xb5, 0xdd, 0x7c, 0xf1, 0xb9, 0xe1, 0x2c,
+ 0x58, 0x1b, 0xa4, 0x46, 0x4b, 0x12, 0x57, 0x58, 0xaa, 0x3a,
+ 0xae, 0x89, 0xa3, 0xb3, 0xcf, 0x1f, 0x8d, 0x67, 0xdf, 0x6d,
+ 0x7e, 0x8e, 0xfa, 0xc5, 0x09, 0x73, 0x46, 0x56, 0x55, 0x90,
+ 0xeb, 0x77, 0x4e, 0x16, 0x4f, 0x68, 0x7b, 0x1f, 0x61, 0x23,
+ 0xec, 0xa9, 0x71, 0x30, 0x33, 0x25, 0xc7, 0x4e, 0x26, 0x2e,
+ 0x4e, 0x2b, 0xc2, 0x64, 0x5f, 0xf5, 0x8f, 0x7a, 0x4b, 0x1c,
+ 0x06, 0xb3, 0x91, 0xf6, 0x9b, 0x51, 0xb7, 0xb0, 0x64, 0x72,
+ 0x04, 0xe5, 0xfa, 0x14, 0x2f, 0xed, 0x61, 0x29, 0x03, 0x73,
+ 0x19, 0x15, 0x6e, 0x2c, 0x8b, 0x0e, 0xec, 0x4d, 0xf1, 0xe3,
+ 0x6f, 0x58, 0x7c, 0xc9, 0x48, 0x67, 0x3f, 0x51, 0xb5, 0xb7,
+ 0x26, 0x46, 0xa7, 0x25, 0x79, 0x55, 0xfe, 0x3a, 0x44, 0xb4,
+ 0x44, 0xfc, 0xb8, 0x14, 0x34, 0x47, 0xd7, 0xa3, 0x0e, 0x76,
+ 0xe7, 0x83, 0x9a, 0x02, 0xc3, 0xcf, 0x2b, 0xd9, 0x83, 0x93,
+ 0xd5, 0xee, 0x99, 0x74, 0x45, 0x62, 0x23, 0xa6, 0x02, 0xc9,
+ 0xc0, 0x10, 0x70, 0x0a, 0x99, 0x29, 0x0c, 0x79, 0x04, 0x4c,
+ 0x77, 0x21, 0x96, 0xf0, 0xa5, 0x17, 0x22, 0xbe, 0xab, 0x9b,
+ 0xd7, 0x42, 0xd3, 0xe9, 0xc0, 0x42, 0x44, 0x7d, 0x9d, 0xc9,
+ 0x3d, 0xf9, 0x36, 0x97, 0x1b, 0x75, 0x52, 0x8f, 0xe9, 0xb9,
+ 0x8c, 0xa7, 0x64, 0x19, 0x5b, 0x5d, 0x60, 0xb4, 0x42, 0x95,
+ 0xc9, 0xdb, 0x82, 0x03, 0xc6, 0xb0, 0x28, 0x72, 0x64, 0x03,
+ 0x41, 0x4d, 0x8f, 0xc6, 0xd0, 0xcd, 0x02, 0x82, 0x01, 0xe1,
+ 0x00, 0xe8, 0x66, 0xa7, 0xf9, 0x0f, 0x5a, 0x21, 0xfc, 0x88,
+ 0x4e, 0x91, 0xd5, 0x4a, 0xf0, 0xf4, 0x32, 0xe5, 0x0d, 0xf3,
+ 0x06, 0x95, 0xd0, 0x4e, 0x47, 0x0c, 0x04, 0x66, 0x77, 0xfd,
+ 0xb8, 0x93, 0x0d, 0xff, 0x8f, 0x97, 0xa0, 0x4a, 0x36, 0x37,
+ 0xa6, 0x5e, 0x95, 0x79, 0xc8, 0xb2, 0x21, 0x98, 0x81, 0xf1,
+ 0xb8, 0xf4, 0x52, 0xaf, 0x3c, 0x8c, 0x86, 0x85, 0x55, 0x56,
+ 0xfc, 0x90, 0xe3, 0x32, 0x50, 0x7c, 0x54, 0x07, 0x9e, 0xed,
+ 0xfc, 0xd4, 0xb9, 0x5c, 0x98, 0x22, 0xfb, 0x72, 0xd7, 0x83,
+ 0xf0, 0xd1, 0x61, 0x10, 0xbd, 0x68, 0x5d, 0x72, 0xc1, 0xce,
+ 0x92, 0x43, 0x77, 0x9f, 0xb8, 0x8d, 0x8e, 0xf2, 0xe3, 0x62,
+ 0x4a, 0x93, 0x03, 0xd3, 0xd9, 0x01, 0xa8, 0x99, 0x6f, 0xa3,
+ 0x4c, 0x6d, 0x7a, 0xf2, 0x9e, 0x8e, 0x6b, 0xbc, 0xe4, 0x9d,
+ 0x8e, 0xe7, 0x25, 0x86, 0xa4, 0xa9, 0xc2, 0xef, 0xdf, 0xbb,
+ 0x6e, 0x3d, 0x4b, 0x57, 0x95, 0x81, 0x6f, 0x68, 0x3f, 0x19,
+ 0xa8, 0xff, 0x5a, 0x08, 0x7a, 0xe4, 0x4c, 0x4e, 0xb4, 0xea,
+ 0xf4, 0xc8, 0x2f, 0xef, 0x8c, 0x5e, 0xcd, 0x62, 0x1c, 0x8c,
+ 0x93, 0x60, 0x5d, 0xa3, 0x11, 0x64, 0x0b, 0xeb, 0x6d, 0x21,
+ 0xbc, 0x3a, 0x5b, 0x5c, 0x0c, 0xa7, 0x8a, 0xc6, 0xa8, 0xe1,
+ 0x48, 0x81, 0x01, 0xb5, 0x65, 0xab, 0x2e, 0xbe, 0x38, 0x94,
+ 0xf7, 0xa6, 0x33, 0xc1, 0x6e, 0x0b, 0x88, 0x38, 0xe7, 0x1b,
+ 0x04, 0x9a, 0x10, 0x2d, 0x1d, 0x3f, 0x5f, 0x5f, 0xc8, 0xef,
+ 0xcd, 0xc5, 0x16, 0xdc, 0x84, 0xc0, 0x66, 0xe0, 0xa3, 0xfc,
+ 0xfa, 0x96, 0xc7, 0xb7, 0xec, 0x4f, 0x40, 0x0a, 0xc5, 0xbe,
+ 0x6d, 0x39, 0x4a, 0x7e, 0x91, 0x4f, 0xe1, 0x03, 0xd2, 0x39,
+ 0xbc, 0x87, 0x69, 0xa1, 0xf0, 0x6d, 0x11, 0xf5, 0xb4, 0x9d,
+ 0xae, 0x76, 0x6b, 0xc6, 0xbf, 0xe4, 0x47, 0xbc, 0x4d, 0x13,
+ 0x88, 0xa8, 0x83, 0xf5, 0xae, 0x1d, 0xfb, 0x4d, 0x4c, 0x44,
+ 0x03, 0xd8, 0xa4, 0x2e, 0x4d, 0xf8, 0x5f, 0x45, 0x94, 0x58,
+ 0xd7, 0xd9, 0x4b, 0x47, 0xd8, 0xfc, 0x35, 0x05, 0xed, 0xb4,
+ 0xb6, 0xc2, 0x36, 0x2e, 0xba, 0xd2, 0x7a, 0xba, 0x69, 0x34,
+ 0xbf, 0xf1, 0xa1, 0x5e, 0x17, 0x71, 0x89, 0xd3, 0x54, 0x57,
+ 0x05, 0x2b, 0x82, 0xe3, 0x0a, 0x64, 0x5c, 0x3b, 0x8c, 0x6b,
+ 0xc7, 0x10, 0x8a, 0xb5, 0xd3, 0xd7, 0x90, 0xeb, 0xdb, 0x1d,
+ 0xa0, 0xbf, 0x6b, 0xea, 0xcd, 0x31, 0x7a, 0x8d, 0x64, 0xcc,
+ 0x58, 0xc0, 0x07, 0xa4, 0x6e, 0x14, 0x0b, 0xf3, 0xea, 0x3e,
+ 0x87, 0x9f, 0x7c, 0xb8, 0x1c, 0x22, 0x26, 0x8a, 0x7d, 0x90,
+ 0xdd, 0x57, 0x28, 0x38, 0xcc, 0x0e, 0x71, 0x92, 0x89, 0xee,
+ 0x79, 0x88, 0xbc, 0x05, 0x21, 0xda, 0x42, 0x92, 0x52, 0x66,
+ 0xac, 0x4a, 0xe5, 0xf5, 0x6e, 0x47, 0xd5, 0xba, 0x37, 0xd3,
+ 0x7c, 0x89, 0xd4, 0xd8, 0x6f, 0xde, 0x63, 0x44, 0xb5, 0x88,
+ 0xdd, 0xb1, 0x30, 0xb4, 0x6d, 0xcd, 0xbf, 0xc8, 0x34, 0x27,
+ 0x59, 0x7d, 0x79, 0xdc, 0x96, 0x5b, 0x8e, 0xc0, 0x87, 0xc0,
+ 0x4e, 0x40, 0x07, 0x13, 0x91, 0x6b, 0x3a, 0x12, 0x03, 0x64,
+ 0x70, 0xaf, 0x80, 0x24, 0x1c, 0x5c, 0xfb, 0xf5, 0xc0, 0x74,
+ 0x5e, 0xaf, 0x06, 0x18, 0x04, 0x67, 0x4a, 0xbd, 0xac, 0xd7,
+ 0xca, 0xbe, 0x4e, 0xa1, 0x19, 0x48, 0x7d, 0xa6, 0x59, 0xf6,
+ 0x1a, 0x62, 0x50, 0x53, 0x46, 0xa4, 0x5b, 0x9c, 0x5a, 0xfd,
+ 0x89, 0x9d, 0xd4, 0xde, 0xf4, 0xa7, 0x3d, 0x88, 0x73, 0xa5,
+ 0xb9, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xe7, 0x70, 0x59, 0xc3,
+ 0xed, 0xc4, 0x6b, 0xa1, 0xa5, 0x5e, 0x90, 0x2a, 0x8c, 0x6a,
+ 0xc2, 0x4e, 0xab, 0xfc, 0xee, 0xf2, 0x23, 0x38, 0xd6, 0xb3,
+ 0x93, 0x08, 0x9e, 0x0c, 0x8e, 0x71, 0x2d, 0xa9, 0xe8, 0xdc,
+ 0xa5, 0xdc, 0x07, 0xe3, 0xb1, 0x33, 0xdd, 0xa2, 0xf2, 0x3e,
+ 0x92, 0x58, 0xe0, 0xf7, 0x53, 0x7f, 0x6e, 0xea, 0x78, 0x8c,
+ 0x35, 0x78, 0x43, 0x63, 0x95, 0xbb, 0x1b, 0x1c, 0xbf, 0x91,
+ 0x75, 0x14, 0x74, 0xd3, 0x20, 0xba, 0x8f, 0xee, 0x9d, 0x71,
+ 0xa1, 0x87, 0x8a, 0x24, 0xd3, 0x61, 0x53, 0xfb, 0xec, 0x16,
+ 0x84, 0xbe, 0x4d, 0x39, 0xdd, 0x0a, 0xac, 0xce, 0x20, 0x9c,
+ 0xaf, 0x8a, 0x13, 0xf8, 0x22, 0x2f, 0xd4, 0x99, 0x88, 0x74,
+ 0xba, 0x16, 0x3a, 0x63, 0xff, 0x4c, 0x5a, 0x03, 0x5a, 0x6f,
+ 0xac, 0x29, 0x33, 0xa5, 0x50, 0xd1, 0xda, 0xed, 0x27, 0xcb,
+ 0x67, 0x72, 0x63, 0x85, 0xfc, 0xf0, 0xc8, 0x88, 0xbf, 0x85,
+ 0xef, 0x4b, 0xfe, 0xae, 0xd9, 0xd5, 0xbb, 0x86, 0xa4, 0x76,
+ 0xe8, 0x7f, 0xb4, 0xdb, 0xb1, 0xee, 0x1a, 0x7f, 0x99, 0xd7,
+ 0x9b, 0x6f, 0x7a, 0x94, 0x5c, 0xec, 0x2c, 0x60, 0x81, 0xad,
+ 0xa7, 0xbe, 0x80, 0x2e, 0x9f, 0xa6, 0xc0, 0xfb, 0x09, 0x6d,
+ 0x2b, 0xab, 0xa4, 0x15, 0xc7, 0x79, 0x46, 0x24, 0x89, 0x5c,
+ 0x32, 0xb9, 0x87, 0xa9, 0x54, 0x1e, 0x12, 0x90, 0x8e, 0x02,
+ 0x80, 0x8c, 0xf8, 0xdb, 0x2f, 0xbc, 0x98, 0x1b, 0xa2, 0x78,
+ 0x73, 0x89, 0x03, 0x97, 0xe3, 0x09, 0x08, 0x8b, 0x75, 0xcf,
+ 0xdc, 0x23, 0x90, 0x59, 0xef, 0x5b, 0x98, 0x24, 0xb8, 0xe8,
+ 0xcf, 0x75, 0xf0, 0x2f, 0xb7, 0xa3, 0xe6, 0x17, 0x06, 0xf0,
+ 0x52, 0xfe, 0x21, 0x0a, 0x16, 0x8e, 0xf8, 0xe1, 0xae, 0x25,
+ 0x11, 0x5d, 0x8c, 0x95, 0x1b, 0x4f, 0x45, 0xb8, 0xa8, 0xcd,
+ 0xe6, 0xf9, 0xca, 0xa0, 0x54, 0x93, 0x95, 0x86, 0x6f, 0xe4,
+ 0x93, 0x22, 0x0f, 0xf2, 0xcf, 0xbd, 0x23, 0xb0, 0xf4, 0x8f,
+ 0x99, 0xa7, 0x67, 0x99, 0x05, 0x13, 0x1f, 0xeb, 0x88, 0xf8,
+ 0xe2, 0x3b, 0xb9, 0x49, 0x35, 0x89, 0x4f, 0xb8, 0x06, 0x37,
+ 0x36, 0xda, 0x75, 0x25, 0x0f, 0x0a, 0xaa, 0xc2, 0x6c, 0x3e,
+ 0xb1, 0x2d, 0x16, 0xf3, 0x17, 0xdb, 0xe2, 0x16, 0x32, 0x39,
+ 0x92, 0x4b, 0x5f, 0xc0, 0x5f, 0x6e, 0xd0, 0x1c, 0x7e, 0xc0,
+ 0x51, 0xd9, 0xb3, 0xe2, 0x37, 0xc7, 0xe0, 0x40, 0x13, 0x7d,
+ 0x06, 0xcd, 0xcd, 0x72, 0xb6, 0x53, 0x2d, 0x7e, 0x60, 0x49,
+ 0xfe, 0x31, 0xe1, 0xd0, 0x0e, 0x4c, 0x98, 0x93, 0xe0, 0xf6,
+ 0xf2, 0xfa, 0x99, 0x7f, 0x65, 0xd8, 0x15, 0xc6, 0x3a, 0xb8,
+ 0x4d, 0x63, 0x21, 0x78, 0xe4, 0x19, 0x6b, 0xbd, 0xde, 0x40,
+ 0x5b, 0x8c, 0xfa, 0x49, 0x75, 0x23, 0x8f, 0x14, 0xc2, 0x3b,
+ 0xa3, 0x9b, 0xc5, 0x80, 0x1a, 0xa3, 0x60, 0xd7, 0x17, 0x27,
+ 0xf0, 0x18, 0x0f, 0xba, 0x02, 0xf7, 0x7a, 0xed, 0xa4, 0x00,
+ 0x77, 0xde, 0x4b, 0xdd, 0xf9, 0xd7, 0x3e, 0x75, 0xed, 0x1a,
+ 0x43, 0x26, 0x71, 0x1b, 0xbc, 0x72, 0xf5, 0x70, 0x72, 0x03,
+ 0x70, 0x25, 0x87, 0x81, 0x6a, 0x92, 0x2d, 0xb7, 0x02, 0xf0,
+ 0x10, 0x79, 0x65, 0x9d, 0x4e, 0x11, 0x7d, 0x5c, 0x5b, 0x37,
+ 0xaa, 0xb4, 0xfa, 0x43, 0x66, 0x48, 0x6c, 0x67, 0x64, 0x9e,
+ 0x15, 0x75, 0x36, 0xe7, 0x25, 0x55, 0x07, 0x7f, 0x74, 0x1f,
+ 0x2c, 0x28, 0x76, 0xe7, 0x9b, 0x3d, 0x91, 0x0b, 0xcd, 0x6a,
+ 0x1d, 0x5a, 0xea, 0x63, 0xd0, 0xf9, 0x02, 0x82, 0x01, 0xe0,
+ 0x3e, 0x31, 0xf2, 0xf4, 0x29, 0x92, 0xa2, 0x93, 0xd5, 0xda,
+ 0xc9, 0x16, 0x7e, 0xf6, 0xdb, 0x33, 0x9f, 0xaf, 0x4b, 0x01,
+ 0xd1, 0x28, 0x2d, 0x3a, 0xc0, 0x51, 0x91, 0x26, 0xbd, 0xa5,
+ 0x1e, 0xdd, 0xd9, 0x2e, 0x11, 0x93, 0x19, 0x29, 0x47, 0x5d,
+ 0x63, 0xe4, 0xb6, 0xf1, 0xea, 0x12, 0x29, 0xa1, 0x65, 0x12,
+ 0x6d, 0x78, 0x8f, 0x63, 0x31, 0xec, 0x72, 0x54, 0x73, 0x72,
+ 0x26, 0x48, 0x57, 0x57, 0xc8, 0xde, 0x28, 0x27, 0xf5, 0x62,
+ 0xfb, 0x7f, 0x1b, 0xf3, 0xaf, 0x31, 0x01, 0xfc, 0x01, 0x58,
+ 0x7a, 0x80, 0x72, 0x9d, 0x6e, 0x07, 0xcc, 0x45, 0x67, 0xc6,
+ 0x26, 0xfe, 0x25, 0xa5, 0x9b, 0x64, 0xcd, 0x45, 0xe3, 0x31,
+ 0x38, 0x05, 0x07, 0x36, 0x05, 0x46, 0x9c, 0xc1, 0x8e, 0xbf,
+ 0x4e, 0x71, 0x5f, 0xea, 0xe5, 0x0c, 0x9a, 0x41, 0xc8, 0x94,
+ 0xcc, 0xf1, 0x73, 0x06, 0x30, 0x54, 0x76, 0x23, 0xb7, 0x22,
+ 0x7a, 0x8e, 0xe6, 0x42, 0xa1, 0xa0, 0x32, 0x12, 0xe9, 0x08,
+ 0x1c, 0x46, 0x79, 0x0c, 0x82, 0x7a, 0x95, 0x79, 0xbf, 0x83,
+ 0x80, 0xeb, 0xab, 0x3d, 0x32, 0xc5, 0xde, 0x62, 0xeb, 0x90,
+ 0x29, 0x73, 0x05, 0xc8, 0x0a, 0xb1, 0x51, 0xf1, 0x23, 0xdd,
+ 0x1e, 0xf5, 0x02, 0x3e, 0x74, 0xbc, 0x24, 0x0c, 0x60, 0x36,
+ 0x2a, 0x28, 0x4d, 0xe6, 0x86, 0x98, 0x7c, 0xd9, 0xe1, 0xac,
+ 0x21, 0x33, 0xaa, 0xa9, 0x8b, 0xb6, 0x8a, 0x1b, 0xf7, 0x54,
+ 0x14, 0xf3, 0x0d, 0x4f, 0xcd, 0x7c, 0xf5, 0xc2, 0x6d, 0xc2,
+ 0xf0, 0xe2, 0xfc, 0x63, 0x1e, 0xa6, 0xa9, 0xa9, 0xd9, 0x73,
+ 0x2a, 0xd5, 0x0a, 0x38, 0xd8, 0xc0, 0xb7, 0xe1, 0x51, 0xe4,
+ 0x23, 0x37, 0xf7, 0x85, 0x66, 0x0e, 0x3f, 0x1a, 0x8c, 0xcf,
+ 0x12, 0xa2, 0x47, 0x6f, 0x73, 0x91, 0x21, 0xe3, 0x93, 0x6b,
+ 0x74, 0x4f, 0xc5, 0xa1, 0xe7, 0x32, 0xf7, 0x86, 0xdd, 0x1a,
+ 0x6e, 0x96, 0xda, 0x32, 0x1d, 0xdd, 0xfa, 0x42, 0xd5, 0xd4,
+ 0xfd, 0xae, 0x7a, 0xa1, 0xed, 0x3d, 0x79, 0xfe, 0x88, 0x84,
+ 0x43, 0xa7, 0xec, 0xf3, 0x7a, 0x13, 0xaa, 0xa1, 0x82, 0x02,
+ 0x83, 0x19, 0x43, 0x0a, 0x46, 0x78, 0x07, 0xd9, 0x4d, 0xff,
+ 0xac, 0x67, 0xd6, 0x29, 0x89, 0xfe, 0x2b, 0xab, 0x5f, 0x9a,
+ 0x87, 0x99, 0x80, 0xaf, 0x70, 0x4a, 0x6a, 0xb9, 0x5a, 0xc2,
+ 0xac, 0x7f, 0xa2, 0xc7, 0xad, 0xe2, 0x1f, 0xec, 0xc5, 0x12,
+ 0x17, 0x08, 0x87, 0x8f, 0x20, 0x95, 0xbe, 0xaf, 0x62, 0x2c,
+ 0xc2, 0x3f, 0x89, 0x56, 0xd8, 0x50, 0x96, 0x97, 0x72, 0xe2,
+ 0x92, 0xe1, 0x2a, 0xd8, 0x84, 0x9f, 0x31, 0xe3, 0x06, 0xd8,
+ 0xe5, 0x91, 0x63, 0x19, 0xe1, 0x27, 0xad, 0xe2, 0xf2, 0x0a,
+ 0x5e, 0x78, 0x8b, 0x1b, 0x13, 0x31, 0x4b, 0xbd, 0x77, 0xb2,
+ 0xd6, 0x5c, 0x92, 0x81, 0x50, 0x02, 0x37, 0xd2, 0xe6, 0xeb,
+ 0x66, 0x6b, 0xaa, 0xfc, 0xcd, 0x54, 0x5d, 0xb8, 0x03, 0x87,
+ 0xe8, 0xfa, 0xb2, 0xde, 0xcb, 0xf8, 0x6e, 0x58, 0xde, 0xcb,
+ 0x09, 0x54, 0x8a, 0x9f, 0x46, 0xa3, 0x7e, 0x8d, 0x15, 0xff,
+ 0x1b, 0x0d, 0x89, 0xc4, 0x1a, 0x21, 0x31, 0x5e, 0xed, 0x0b,
+ 0x67, 0x3c, 0x70, 0xed, 0x92, 0x48, 0xef, 0xec, 0xf0, 0x77,
+ 0xc2, 0x79, 0x6c, 0x06, 0x09, 0xaa, 0xab, 0xf6, 0x4c, 0xcd,
+ 0xfa, 0x7e, 0x4a, 0x88, 0xdc, 0xa8, 0x9b, 0xd3, 0x69, 0x94,
+ 0x88, 0x09, 0x1d, 0x30, 0x43, 0x9e, 0x2c, 0xcb, 0x01, 0x1d,
+ 0x4a, 0x3b, 0x04, 0xec, 0x0e, 0xb1, 0xde, 0x09, 0xad, 0x29,
+ 0x02, 0x82, 0x01, 0xe1, 0x00, 0x9f, 0x02, 0x13, 0x7a, 0xd0,
+ 0xa9, 0x8a, 0x7a, 0xa0, 0x05, 0xbb, 0x44, 0x6f, 0xaf, 0xf7,
+ 0xe3, 0xd4, 0x35, 0xef, 0x73, 0x39, 0xd5, 0xe0, 0xa2, 0x0f,
+ 0x1a, 0x25, 0xa8, 0xf7, 0xc2, 0xa5, 0xec, 0x57, 0xf8, 0x0d,
+ 0x2a, 0xb6, 0x64, 0x03, 0x8c, 0x22, 0x0f, 0xe7, 0x98, 0xa1,
+ 0x12, 0xfe, 0x24, 0xef, 0x61, 0x28, 0x9f, 0xa7, 0x22, 0x6b,
+ 0x6d, 0xab, 0x8d, 0x7d, 0x2a, 0x8b, 0xae, 0x8b, 0xfd, 0xcb,
+ 0xd5, 0x0b, 0x79, 0x1b, 0x89, 0xcb, 0x5b, 0x7a, 0x8c, 0xdc,
+ 0xe8, 0x8d, 0xdd, 0x35, 0x9f, 0x06, 0x69, 0x64, 0x12, 0xeb,
+ 0x46, 0x79, 0xdf, 0x82, 0x2c, 0x89, 0x75, 0x9e, 0x7a, 0xec,
+ 0xad, 0xe5, 0x88, 0x31, 0xfa, 0x86, 0x93, 0xca, 0xf1, 0x2d,
+ 0x9b, 0x62, 0x5a, 0xe9, 0x43, 0x09, 0xf3, 0x8c, 0xe5, 0xc7,
+ 0xc0, 0xce, 0x86, 0xe7, 0xdb, 0xc7, 0x4d, 0x27, 0xd5, 0xee,
+ 0x76, 0xce, 0x35, 0x30, 0x47, 0xef, 0x00, 0x1b, 0x69, 0x9a,
+ 0x3f, 0xa5, 0x2a, 0xc9, 0x07, 0xab, 0x99, 0xba, 0x2a, 0xe7,
+ 0xfb, 0xa9, 0x4e, 0xb9, 0xae, 0x2c, 0x50, 0xfc, 0x35, 0x49,
+ 0xe6, 0x97, 0x78, 0x3c, 0xb1, 0x59, 0xd7, 0x1d, 0x4e, 0x4e,
+ 0xea, 0xde, 0xa0, 0xd0, 0xc4, 0x1d, 0xb1, 0xd3, 0x53, 0x1e,
+ 0xf9, 0xbf, 0xb3, 0x6a, 0x17, 0xb4, 0xda, 0xcc, 0x27, 0x19,
+ 0xc6, 0x35, 0xe8, 0x28, 0xd3, 0xe3, 0x76, 0x3a, 0xdc, 0xd0,
+ 0x75, 0xc8, 0xb4, 0x6c, 0xbe, 0x84, 0x2a, 0x45, 0xd1, 0x43,
+ 0x22, 0x54, 0xd7, 0xc5, 0xd0, 0xd7, 0x73, 0x35, 0x6b, 0xa8,
+ 0xfa, 0xad, 0x60, 0xc0, 0x64, 0xc1, 0x58, 0x89, 0x09, 0x81,
+ 0x0a, 0x0b, 0xea, 0x33, 0x91, 0xb0, 0xef, 0x53, 0x50, 0x41,
+ 0xae, 0xd9, 0xee, 0xbe, 0x9e, 0xf0, 0x0b, 0xa0, 0x7c, 0xbf,
+ 0x3f, 0xc9, 0x4b, 0xe0, 0x48, 0xd8, 0x10, 0xd5, 0x2e, 0xce,
+ 0xf0, 0x7c, 0xd8, 0x05, 0xde, 0x09, 0x7e, 0x8c, 0x63, 0x4c,
+ 0xdb, 0x8b, 0x91, 0xcd, 0x7f, 0xb6, 0x6b, 0xad, 0xce, 0xb1,
+ 0x17, 0x6c, 0xf7, 0x08, 0x0d, 0x7c, 0xda, 0x4f, 0x0a, 0x07,
+ 0xd0, 0xae, 0x72, 0x3c, 0x67, 0x4a, 0x44, 0x54, 0x47, 0xce,
+ 0xe1, 0x17, 0x07, 0x12, 0xde, 0x52, 0xef, 0xef, 0x4c, 0x2b,
+ 0x42, 0x7d, 0x09, 0x80, 0x36, 0x34, 0xdc, 0x45, 0x6f, 0xb0,
+ 0x2d, 0xab, 0xa0, 0x0c, 0x58, 0xae, 0x35, 0xd3, 0x9b, 0x37,
+ 0xc1, 0x1d, 0xeb, 0xfe, 0xc3, 0x04, 0xc9, 0x1d, 0xe7, 0x3d,
+ 0x16, 0x64, 0xed, 0xf5, 0xe8, 0xdf, 0x99, 0xa4, 0xfb, 0xad,
+ 0x79, 0x88, 0xd5, 0x8c, 0x62, 0x33, 0x9e, 0x35, 0xa6, 0x7f,
+ 0x9d, 0xb6, 0x1a, 0x40, 0x6d, 0xc3, 0x89, 0x5d, 0x7b, 0xe2,
+ 0xc8, 0xd3, 0x16, 0x13, 0x07, 0x9a, 0x38, 0x22, 0x33, 0x03,
+ 0xac, 0x70, 0x3e, 0xce, 0x32, 0x56, 0x0b, 0x58, 0x56, 0xb8,
+ 0xe9, 0xd8, 0x42, 0x35, 0x6c, 0xb9, 0x02, 0xb3, 0x64, 0xeb,
+ 0xaa, 0x09, 0x3f, 0xac, 0x66, 0x08, 0xb4, 0x5f, 0x3e, 0xb4,
+ 0xec, 0x39, 0xb1, 0x99, 0xe4, 0x5d, 0x1d, 0x32, 0x14, 0xc1,
+ 0x48, 0x8f, 0x6c, 0x65, 0x87, 0x34, 0x50, 0xa4, 0xf4, 0x9b,
+ 0x5b, 0x2e, 0xb5, 0x79, 0x0d, 0x11, 0x62, 0xa4, 0x35, 0x9c,
+ 0x6f, 0x92, 0xd0, 0x68, 0x07, 0xdd, 0x69, 0x85, 0x48, 0xe3,
+ 0x5d, 0x10, 0x34, 0xaf, 0xea, 0x41, 0x72, 0x5a, 0x71, 0x00,
+ 0xf8, 0xe6, 0x47, 0x7f, 0xa0, 0x6f, 0x91, 0x96, 0x40, 0x00,
+ 0x40, 0x70, 0xfb, 0x63, 0xcf, 0xc9, 0x36, 0x04, 0x1c, 0x3b,
+ 0x11, 0x08, 0x29, 0x81, 0x9f
+};
+
+static unsigned char test15360[] = {
+ 0x30, 0x82, 0x21, 0xe8, 0x02, 0x01, 0x00, 0x02, 0x82, 0x07,
+ 0x81, 0x00, 0xad, 0x3f, 0xaa, 0xdc, 0x8c, 0x85, 0xcb, 0x60,
+ 0xd2, 0xf5, 0x30, 0xa1, 0x0f, 0x26, 0xec, 0xdf, 0xfc, 0x91,
+ 0x39, 0xbd, 0x3e, 0x8f, 0x99, 0x64, 0x1e, 0x51, 0xd2, 0x27,
+ 0x5e, 0x76, 0xcd, 0x86, 0x33, 0x07, 0xf9, 0xbd, 0x3b, 0x06,
+ 0xc3, 0x3c, 0x85, 0xcb, 0x7e, 0x91, 0x14, 0xb0, 0x0b, 0x77,
+ 0x22, 0x30, 0x71, 0xb8, 0xbb, 0x74, 0x30, 0x33, 0x35, 0x56,
+ 0x34, 0x47, 0x10, 0x8f, 0x88, 0xe2, 0x6f, 0xdc, 0x3b, 0xe9,
+ 0x58, 0x9d, 0x0c, 0xdc, 0x8f, 0x70, 0x41, 0x7a, 0x12, 0xd2,
+ 0x9a, 0x35, 0xbe, 0x0a, 0x57, 0x13, 0x0c, 0xe9, 0xbf, 0x77,
+ 0x54, 0x00, 0x74, 0xb7, 0x1a, 0x3e, 0xa7, 0xe9, 0xb6, 0xe7,
+ 0x4f, 0x1e, 0xa4, 0xc0, 0x7c, 0x4c, 0x66, 0xc5, 0xce, 0xad,
+ 0x96, 0x1b, 0xe2, 0x1a, 0xf1, 0x3d, 0x8b, 0x50, 0xcf, 0xe2,
+ 0x15, 0x21, 0x6d, 0x83, 0x95, 0x00, 0xee, 0x97, 0xc4, 0xae,
+ 0xc9, 0x38, 0x62, 0x6c, 0xb2, 0xe7, 0x7f, 0x15, 0x0a, 0xab,
+ 0x86, 0xb9, 0xd9, 0x8a, 0xf8, 0xeb, 0x88, 0x5d, 0xdc, 0x0c,
+ 0x1e, 0xc5, 0xe6, 0xa1, 0x7b, 0xbf, 0xf1, 0x02, 0xe3, 0xad,
+ 0xf8, 0xed, 0x17, 0x9f, 0x83, 0x11, 0x31, 0x3b, 0xad, 0xb4,
+ 0xf9, 0x8d, 0x1d, 0x56, 0x9b, 0xac, 0x68, 0x55, 0x0a, 0x74,
+ 0x20, 0xee, 0x57, 0xe7, 0x1c, 0x6d, 0x05, 0xa1, 0x4e, 0xa5,
+ 0x11, 0x99, 0xb4, 0x86, 0xdb, 0x58, 0xe7, 0xf6, 0xb6, 0x4f,
+ 0x92, 0x58, 0x57, 0x9b, 0x74, 0x04, 0xe5, 0xd1, 0x1d, 0x7c,
+ 0x4b, 0xb8, 0x1f, 0x5d, 0x0e, 0x93, 0xee, 0x44, 0x18, 0xb6,
+ 0x58, 0x0e, 0xa1, 0x0b, 0x8e, 0x2e, 0x99, 0x4c, 0x72, 0x91,
+ 0xfa, 0xfa, 0xe2, 0x22, 0x05, 0x5d, 0x2b, 0x2d, 0xd8, 0x60,
+ 0xd5, 0x1b, 0x08, 0x56, 0x2b, 0xb5, 0x21, 0xdb, 0x1a, 0xe6,
+ 0xa8, 0x39, 0xa2, 0xf4, 0x58, 0xcb, 0xd2, 0xf9, 0xce, 0xc0,
+ 0x1e, 0x1b, 0xf9, 0xa7, 0x37, 0xca, 0xa3, 0x77, 0x6e, 0xb1,
+ 0xaf, 0x33, 0xb5, 0x6d, 0x5f, 0x33, 0x2e, 0x1a, 0x34, 0xdb,
+ 0x42, 0xbe, 0x5f, 0xf9, 0x09, 0xb7, 0x9f, 0xd4, 0x09, 0xfb,
+ 0x87, 0x13, 0x3c, 0xe2, 0x27, 0xb8, 0xf3, 0x1d, 0x7e, 0x92,
+ 0xdd, 0x87, 0x86, 0x55, 0x69, 0x9b, 0x55, 0xcd, 0xef, 0x7a,
+ 0x71, 0x5d, 0x81, 0x3a, 0xd9, 0xf7, 0x7f, 0xde, 0xe0, 0x92,
+ 0xd9, 0x78, 0x0f, 0x1d, 0x43, 0xb1, 0x1e, 0x29, 0xc1, 0x49,
+ 0xb6, 0x5e, 0x85, 0x83, 0xd9, 0x04, 0xfd, 0x79, 0xd8, 0x47,
+ 0x03, 0x2e, 0x85, 0x19, 0xfd, 0x63, 0xe7, 0xa4, 0x8b, 0xc0,
+ 0x94, 0x0e, 0xb7, 0x54, 0x97, 0xd6, 0x44, 0x5d, 0x63, 0x12,
+ 0xff, 0xdd, 0xde, 0x2c, 0x00, 0x0e, 0xc9, 0xca, 0x7e, 0xa2,
+ 0x65, 0x25, 0xb0, 0x1d, 0xa9, 0x20, 0x4f, 0xdd, 0xea, 0x3a,
+ 0xb5, 0xe8, 0x0f, 0xf3, 0xb2, 0xb7, 0x00, 0x4a, 0xe8, 0xa4,
+ 0x83, 0x49, 0xbd, 0x78, 0xdf, 0xac, 0x2c, 0x37, 0x81, 0xb3,
+ 0xf3, 0xb7, 0x13, 0x93, 0x3e, 0xb2, 0x79, 0x55, 0xf2, 0xd8,
+ 0x9c, 0xf7, 0xf2, 0xf1, 0xd5, 0x6c, 0x9c, 0xff, 0xec, 0xf4,
+ 0xea, 0x08, 0x3c, 0x65, 0x35, 0xb7, 0x09, 0x03, 0x6d, 0x99,
+ 0x1d, 0x5b, 0x73, 0x06, 0x61, 0xb4, 0xf0, 0xc5, 0xdb, 0x3e,
+ 0xe0, 0x1d, 0xa8, 0x5b, 0x7a, 0x5b, 0x5b, 0x9c, 0x11, 0x75,
+ 0x83, 0x1d, 0xf4, 0x73, 0x27, 0xf3, 0x79, 0xf2, 0x82, 0xd6,
+ 0x28, 0x45, 0x58, 0x23, 0x6c, 0x29, 0xd3, 0x50, 0x51, 0x1b,
+ 0x38, 0xef, 0x89, 0x90, 0x84, 0xa2, 0x4c, 0x35, 0x7b, 0x30,
+ 0x5e, 0xbd, 0x1a, 0xd5, 0xdf, 0xcd, 0xcd, 0x74, 0x3f, 0x2e,
+ 0x01, 0xea, 0x33, 0x07, 0x74, 0xfb, 0x86, 0x75, 0x20, 0x0e,
+ 0x4f, 0xbf, 0x65, 0xd4, 0x15, 0x19, 0x6f, 0x8d, 0x37, 0xcd,
+ 0xb6, 0x6f, 0x50, 0x9d, 0x5e, 0x04, 0x81, 0x7d, 0xec, 0xd6,
+ 0xbb, 0x40, 0x1b, 0xe0, 0xf5, 0xd5, 0x86, 0x26, 0xc5, 0x41,
+ 0x84, 0x0e, 0x3e, 0x73, 0xb7, 0xa4, 0xbe, 0x2a, 0xfe, 0xd7,
+ 0xe4, 0x4d, 0x5c, 0x2d, 0x6a, 0x04, 0xe6, 0xdd, 0x28, 0xa0,
+ 0x75, 0x4c, 0xe0, 0x23, 0x2c, 0xad, 0xec, 0xaa, 0x72, 0xfd,
+ 0x03, 0xc0, 0x65, 0xfa, 0xc4, 0x3c, 0x25, 0x10, 0xae, 0x3f,
+ 0x09, 0x96, 0x4e, 0xff, 0xfe, 0xc7, 0xe4, 0x9e, 0xec, 0xb5,
+ 0x6e, 0xec, 0xf3, 0x7a, 0x83, 0x7a, 0x8b, 0xbb, 0x91, 0x8d,
+ 0xab, 0x3c, 0x4d, 0x7f, 0x34, 0x77, 0xbe, 0x0c, 0x87, 0xf2,
+ 0xc3, 0xd6, 0xcb, 0xcc, 0xfa, 0x1e, 0xaf, 0x21, 0x24, 0xe9,
+ 0xaa, 0x89, 0x61, 0x0c, 0x7a, 0x1c, 0x7d, 0x00, 0x87, 0x69,
+ 0x30, 0xa0, 0xb4, 0x3b, 0x96, 0x1c, 0x00, 0x14, 0x07, 0xb8,
+ 0x3f, 0x59, 0x62, 0x3a, 0x3f, 0xfb, 0x68, 0xb8, 0x81, 0x7d,
+ 0x4a, 0x9d, 0x1c, 0xa2, 0x07, 0xa3, 0xb1, 0x42, 0x7b, 0xfa,
+ 0x9b, 0xbc, 0x94, 0x30, 0x7e, 0xea, 0xe7, 0x40, 0x7e, 0xd4,
+ 0x0f, 0x33, 0x3b, 0x57, 0xda, 0x8b, 0x6d, 0x64, 0xd5, 0xe4,
+ 0x91, 0x83, 0xf0, 0x3d, 0xae, 0x8b, 0x91, 0xf0, 0xcd, 0xb1,
+ 0xa0, 0xe0, 0x0d, 0xe1, 0xbb, 0x22, 0x78, 0x1f, 0x3a, 0xe5,
+ 0x53, 0x28, 0xf0, 0x35, 0xae, 0x71, 0xe6, 0xfd, 0x63, 0xb2,
+ 0x9c, 0x3f, 0xdd, 0x95, 0x7b, 0xc4, 0xe9, 0x2f, 0xd9, 0x93,
+ 0x3a, 0x10, 0x42, 0x1c, 0x90, 0xab, 0xfb, 0xd3, 0x02, 0xe9,
+ 0x59, 0xbc, 0x53, 0x7e, 0xf3, 0xe1, 0x52, 0x15, 0xa6, 0x58,
+ 0x9e, 0xc1, 0xa6, 0x0e, 0x2e, 0x35, 0x07, 0x3a, 0xc3, 0x1f,
+ 0xaa, 0x58, 0xe7, 0xc6, 0x33, 0x6a, 0x39, 0x4b, 0x21, 0x15,
+ 0x3d, 0x92, 0x4e, 0x5e, 0xf9, 0x01, 0xd6, 0x0f, 0x28, 0x61,
+ 0x15, 0xdf, 0xed, 0x6f, 0x75, 0xc4, 0x8f, 0xcb, 0x16, 0x55,
+ 0x09, 0xc7, 0x24, 0xb2, 0x0c, 0x49, 0x25, 0x8d, 0x5e, 0xf1,
+ 0x0e, 0xe0, 0xe2, 0xc4, 0xcc, 0x1f, 0x4e, 0x60, 0x5c, 0x5e,
+ 0xc6, 0x7f, 0x68, 0x7f, 0xdb, 0x1a, 0x01, 0x67, 0x07, 0xb1,
+ 0x56, 0x93, 0xf2, 0x26, 0x81, 0xc0, 0x33, 0xb8, 0x48, 0xf9,
+ 0x2c, 0x5c, 0x18, 0x29, 0xed, 0xe0, 0x6c, 0xa0, 0xac, 0xd2,
+ 0x90, 0x4b, 0x52, 0x87, 0xbb, 0xb5, 0x05, 0xd8, 0x56, 0xc5,
+ 0xb8, 0x8f, 0x3f, 0x49, 0x52, 0x9a, 0xa2, 0xd0, 0x40, 0x80,
+ 0x5b, 0x16, 0x15, 0xbc, 0x74, 0x8e, 0x00, 0x10, 0xaf, 0xfb,
+ 0x6d, 0xba, 0xcb, 0xbc, 0xe6, 0x13, 0x75, 0xce, 0x27, 0xae,
+ 0x85, 0x57, 0x6c, 0xc0, 0x8a, 0x84, 0x6f, 0x34, 0x16, 0xd4,
+ 0x35, 0xd2, 0xcc, 0x55, 0x00, 0xc1, 0xd8, 0x28, 0x2c, 0x9c,
+ 0x84, 0x78, 0xbf, 0xf0, 0x3b, 0x0d, 0x9f, 0x81, 0xd4, 0xef,
+ 0x99, 0x77, 0x53, 0xd2, 0x8e, 0x43, 0x52, 0xf0, 0x32, 0x7e,
+ 0xba, 0xbf, 0xb6, 0x0e, 0x9d, 0x9b, 0x00, 0xd0, 0x50, 0x55,
+ 0x67, 0x5a, 0x2c, 0x8b, 0x9b, 0x29, 0xfb, 0x41, 0x74, 0x4c,
+ 0xb7, 0xd8, 0x98, 0xa2, 0xfb, 0x73, 0x07, 0x96, 0xef, 0xcd,
+ 0x47, 0x13, 0x1d, 0xe2, 0xb1, 0xac, 0xf3, 0xcf, 0x47, 0x98,
+ 0x7b, 0x6f, 0xf6, 0x32, 0x44, 0x41, 0x78, 0x09, 0x8e, 0x64,
+ 0x0c, 0xbf, 0xe2, 0x0f, 0x8c, 0x44, 0x2f, 0x4e, 0x55, 0xe0,
+ 0xc6, 0xfd, 0x05, 0x74, 0x18, 0x1a, 0xb9, 0xfa, 0xcb, 0xd3,
+ 0xfa, 0x69, 0x50, 0x63, 0xce, 0x2b, 0xef, 0x92, 0x0f, 0x11,
+ 0xd4, 0x9b, 0x53, 0x6c, 0xed, 0xc5, 0x0b, 0x7c, 0xbd, 0xa1,
+ 0x5d, 0xdf, 0xab, 0xcf, 0xaa, 0x83, 0x5e, 0xa8, 0xc5, 0xfe,
+ 0x91, 0x2b, 0x23, 0x1f, 0x39, 0x3d, 0x71, 0x74, 0xbf, 0xa2,
+ 0xf1, 0xda, 0x2f, 0x29, 0x02, 0x9b, 0xea, 0x48, 0x2c, 0xaf,
+ 0xe7, 0xa9, 0xf5, 0x68, 0xab, 0x8f, 0x18, 0xb9, 0x7b, 0x28,
+ 0xf0, 0x92, 0xfb, 0x07, 0xd7, 0xbd, 0x43, 0xcd, 0x7f, 0xfc,
+ 0xb9, 0x5f, 0x24, 0xf8, 0x48, 0x2e, 0xbe, 0x42, 0x87, 0x80,
+ 0x38, 0x78, 0x9e, 0x8c, 0x52, 0x6d, 0xfa, 0x2e, 0x46, 0x35,
+ 0x7a, 0x59, 0x88, 0xb9, 0x3e, 0xcb, 0x79, 0xb4, 0x8a, 0x9e,
+ 0xd5, 0xd0, 0x30, 0x8c, 0xb2, 0x0c, 0x9d, 0x8d, 0x2d, 0x64,
+ 0x0b, 0xf6, 0xeb, 0xf1, 0xde, 0xea, 0x74, 0xfc, 0xbc, 0x01,
+ 0x18, 0x48, 0x4e, 0x35, 0x02, 0x83, 0x01, 0xb2, 0x50, 0xa0,
+ 0x44, 0x19, 0x30, 0x00, 0x12, 0x4a, 0xa0, 0x6d, 0x6b, 0x8b,
+ 0xf1, 0xce, 0xda, 0x2e, 0x16, 0x35, 0x52, 0x26, 0xf9, 0xbe,
+ 0xb1, 0x37, 0xfc, 0x0a, 0x8b, 0x6f, 0x06, 0x11, 0x7b, 0xf7,
+ 0xa8, 0x40, 0xbd, 0x8d, 0x94, 0xa4, 0xa2, 0xe0, 0xb6, 0xdf,
+ 0x62, 0xc0, 0x6f, 0xb3, 0x5d, 0x84, 0xb9, 0xaa, 0x2f, 0xc1,
+ 0x3b, 0xcb, 0x20, 0xc6, 0x68, 0x69, 0x15, 0x74, 0xbc, 0xdb,
+ 0x43, 0x9c, 0x4a, 0xfc, 0x72, 0xc1, 0xf5, 0x87, 0x80, 0xe8,
+ 0x6c, 0xd5, 0xc1, 0x2e, 0x34, 0x5e, 0x96, 0x76, 0x08, 0x3e,
+ 0x45, 0xe4, 0xa0, 0x4a, 0x7a, 0xc1, 0x67, 0x38, 0xf2, 0x31,
+ 0x1f, 0x7b, 0x0f, 0x54, 0xbd, 0x0d, 0x1f, 0x9e, 0x8e, 0x99,
+ 0x8b, 0x58, 0xd9, 0x94, 0x87, 0xaa, 0x8b, 0x82, 0x5d, 0x5e,
+ 0xe8, 0x50, 0xf4, 0xf2, 0xc7, 0xe9, 0x85, 0x6b, 0xd2, 0xef,
+ 0x13, 0xc1, 0xed, 0x57, 0x2a, 0xc5, 0xd6, 0x5d, 0xa4, 0x3b,
+ 0x29, 0xba, 0xab, 0x1b, 0xaa, 0x21, 0x41, 0xe9, 0xdc, 0x47,
+ 0x88, 0xef, 0x0c, 0xfc, 0xb2, 0xdc, 0xf7, 0xdb, 0x55, 0x4d,
+ 0x70, 0xc7, 0xe2, 0x8a, 0x8a, 0xe1, 0xde, 0xcf, 0xe5, 0xca,
+ 0x23, 0x36, 0x29, 0xe5, 0xfc, 0x54, 0x66, 0xda, 0xe9, 0xab,
+ 0x58, 0x20, 0xb2, 0x8e, 0xb2, 0x7d, 0x5d, 0xb8, 0xc7, 0x6c,
+ 0x48, 0x53, 0x2b, 0x47, 0xe0, 0x12, 0x00, 0x0e, 0xfe, 0xa5,
+ 0x93, 0x34, 0xf9, 0x3e, 0xa6, 0x3f, 0x56, 0xaa, 0x43, 0x65,
+ 0xbb, 0x5a, 0x70, 0x3e, 0x62, 0xac, 0x3f, 0x5b, 0x90, 0x02,
+ 0x50, 0x5d, 0x05, 0xa8, 0xd5, 0x67, 0x1a, 0x62, 0xec, 0xd4,
+ 0xde, 0x29, 0x04, 0xac, 0x6d, 0x15, 0x5d, 0xa0, 0xec, 0xf2,
+ 0x57, 0x13, 0x0e, 0x17, 0x96, 0x0c, 0x32, 0x6a, 0xc5, 0xe0,
+ 0xa8, 0xff, 0x85, 0xa4, 0xa3, 0xe3, 0x0e, 0x35, 0x5d, 0xd1,
+ 0x28, 0x84, 0xaa, 0xc4, 0x84, 0xcd, 0x25, 0x63, 0x85, 0x82,
+ 0x3e, 0x12, 0x30, 0x17, 0x57, 0x45, 0xb8, 0xb4, 0x34, 0x01,
+ 0x3a, 0xa2, 0x77, 0x61, 0xc8, 0x3d, 0x1f, 0xc5, 0x0e, 0x4a,
+ 0xbb, 0xf6, 0xa0, 0x5d, 0x79, 0x4b, 0xc8, 0xf3, 0x9c, 0x87,
+ 0x05, 0x2f, 0xea, 0x25, 0x28, 0x91, 0x69, 0x77, 0x7c, 0xba,
+ 0xea, 0x4a, 0x75, 0x2e, 0x2b, 0x17, 0x83, 0x50, 0x32, 0x43,
+ 0x4f, 0xcd, 0xf1, 0x77, 0xb1, 0x22, 0x0a, 0x8b, 0x69, 0x58,
+ 0x09, 0x35, 0x07, 0x6d, 0x61, 0x4a, 0x8d, 0x18, 0x65, 0x6e,
+ 0x9b, 0x62, 0x07, 0xd0, 0x6a, 0x92, 0x39, 0x05, 0x80, 0x14,
+ 0xfa, 0x1c, 0x93, 0x84, 0x0c, 0xb5, 0x8c, 0x41, 0x91, 0x4e,
+ 0x48, 0xf0, 0xf2, 0xba, 0x1d, 0x73, 0x2f, 0x1e, 0xa1, 0x55,
+ 0xc3, 0x02, 0x8c, 0xb1, 0xf2, 0x37, 0xa6, 0x9a, 0x6b, 0xcd,
+ 0x45, 0x2e, 0x08, 0x90, 0x26, 0x63, 0x91, 0xff, 0x22, 0x5e,
+ 0xcd, 0xae, 0x9b, 0x19, 0x1e, 0x10, 0x62, 0x4e, 0x1f, 0x2d,
+ 0x81, 0x69, 0x4f, 0x41, 0xe5, 0x94, 0xff, 0x7e, 0xcc, 0x15,
+ 0x36, 0x1e, 0x29, 0x59, 0x37, 0xe7, 0x64, 0x40, 0x17, 0x1a,
+ 0x32, 0xba, 0x01, 0x26, 0x30, 0x80, 0x60, 0x07, 0x86, 0x6e,
+ 0xd4, 0xb3, 0xe2, 0x44, 0x16, 0x33, 0xf2, 0x4c, 0x84, 0x0e,
+ 0xb1, 0x4a, 0xc7, 0x92, 0xa6, 0xa3, 0x42, 0x36, 0x05, 0x3e,
+ 0x74, 0xa8, 0xb1, 0xc5, 0x63, 0x59, 0x0d, 0x1e, 0x36, 0x45,
+ 0x2b, 0x36, 0x5e, 0xca, 0xab, 0x97, 0x49, 0xd3, 0xab, 0xae,
+ 0x63, 0x0a, 0xd1, 0x03, 0x57, 0x88, 0xa4, 0xa4, 0x3c, 0xda,
+ 0x15, 0x49, 0x1a, 0x5d, 0xe6, 0x5e, 0xb9, 0x82, 0x23, 0xc0,
+ 0x83, 0x96, 0xfe, 0x38, 0x0b, 0x80, 0x0e, 0xde, 0x22, 0xeb,
+ 0x5d, 0xe4, 0x56, 0x32, 0xbe, 0xe0, 0xc0, 0x6e, 0x69, 0x63,
+ 0x27, 0x4e, 0x00, 0x58, 0x80, 0x70, 0xd9, 0xcc, 0x4e, 0xae,
+ 0x6c, 0x5e, 0x6a, 0x43, 0x81, 0xfd, 0x45, 0xb2, 0xa4, 0x6c,
+ 0xf0, 0x9c, 0x66, 0x5c, 0x7d, 0x5c, 0x78, 0x55, 0x33, 0x4b,
+ 0x3c, 0x3b, 0x1d, 0x18, 0x58, 0x79, 0x6a, 0x02, 0xec, 0xce,
+ 0x53, 0x69, 0xc0, 0x17, 0xed, 0x57, 0xaf, 0x71, 0x5b, 0x42,
+ 0x1b, 0x49, 0xd8, 0xe8, 0x96, 0x80, 0xb6, 0x48, 0x1b, 0x7c,
+ 0xf8, 0x74, 0x1c, 0xb1, 0xc4, 0x10, 0xb7, 0xf4, 0x97, 0x7e,
+ 0x6b, 0x8f, 0x54, 0xba, 0x37, 0xb9, 0x35, 0x9e, 0x7b, 0x17,
+ 0x16, 0x9b, 0x89, 0x39, 0xae, 0x4f, 0x2e, 0x18, 0x65, 0xb4,
+ 0x76, 0x20, 0x9a, 0x58, 0xe2, 0x57, 0x6e, 0x1c, 0x3f, 0x8e,
+ 0x9a, 0xbb, 0xd8, 0xfc, 0x4c, 0xd6, 0x2d, 0xc1, 0xa6, 0x46,
+ 0xac, 0x13, 0x1e, 0xa7, 0xf7, 0x1d, 0x28, 0x3a, 0xf4, 0xd6,
+ 0x48, 0xfb, 0xe5, 0xb3, 0x84, 0x94, 0x47, 0x92, 0xae, 0x9a,
+ 0x58, 0xc5, 0xac, 0x23, 0x1b, 0xb5, 0xcd, 0x96, 0xd2, 0x5e,
+ 0xb2, 0x41, 0xfc, 0x9a, 0xae, 0x19, 0xf1, 0x7b, 0x4b, 0x53,
+ 0x1b, 0xfa, 0xa5, 0x0c, 0x49, 0x6d, 0xff, 0xf4, 0x51, 0x88,
+ 0x19, 0x04, 0xd9, 0x85, 0x8e, 0xe2, 0x3a, 0x62, 0x31, 0x5c,
+ 0x6e, 0xe8, 0x4d, 0x04, 0x1d, 0xd8, 0xc2, 0x7b, 0x51, 0xe7,
+ 0x59, 0xbc, 0x85, 0x5c, 0xc4, 0xcc, 0xad, 0xcb, 0x93, 0x69,
+ 0x18, 0xe4, 0x71, 0x9e, 0x63, 0x33, 0x99, 0xb6, 0x3b, 0x23,
+ 0x11, 0x17, 0x7a, 0x3d, 0x6f, 0xb9, 0x6b, 0xf1, 0xf2, 0xa7,
+ 0x03, 0xfd, 0xf0, 0xcd, 0x5b, 0xb5, 0xda, 0x9a, 0xd9, 0x95,
+ 0x02, 0x76, 0xd8, 0x38, 0xd3, 0xbd, 0xa0, 0x4a, 0x9a, 0xab,
+ 0x70, 0xde, 0xc6, 0xf9, 0xa5, 0x19, 0x9c, 0xc4, 0xf9, 0x07,
+ 0x4d, 0xea, 0x15, 0xc2, 0x91, 0x4d, 0x54, 0xa9, 0x2c, 0xca,
+ 0xdf, 0xaa, 0xd1, 0xc4, 0xc0, 0x18, 0x77, 0x28, 0x2a, 0x2c,
+ 0xc3, 0x7c, 0x26, 0xbd, 0xd8, 0x0d, 0x51, 0xa1, 0x4d, 0xad,
+ 0x76, 0x76, 0xaa, 0xa9, 0x45, 0x82, 0x4f, 0x76, 0xfb, 0x1a,
+ 0xd3, 0x71, 0x3c, 0x55, 0xa2, 0x5c, 0xe0, 0xd6, 0xda, 0x35,
+ 0xbe, 0x25, 0x23, 0x26, 0x51, 0xc6, 0xb4, 0xf3, 0x3e, 0x2c,
+ 0x54, 0x09, 0xc7, 0x6f, 0xa5, 0x08, 0x81, 0xba, 0x75, 0xda,
+ 0xcb, 0x4d, 0x05, 0xdd, 0xca, 0x93, 0x48, 0x30, 0xe8, 0x4a,
+ 0x1f, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x07,
+ 0x80, 0x25, 0x2f, 0xbc, 0x49, 0xf8, 0xb3, 0xa3, 0x32, 0xd6,
+ 0x35, 0x20, 0xca, 0x01, 0x49, 0x96, 0xa0, 0x81, 0x42, 0xde,
+ 0xc4, 0xdb, 0x0f, 0xd1, 0x99, 0xe6, 0xd4, 0x23, 0x2a, 0xa6,
+ 0x21, 0x13, 0xfe, 0x51, 0x27, 0xce, 0x18, 0x2a, 0xfa, 0x49,
+ 0x9f, 0xcd, 0x0c, 0x1f, 0xcf, 0x9e, 0x44, 0x27, 0x41, 0xdc,
+ 0x09, 0xcf, 0xef, 0x19, 0xf5, 0x57, 0x7f, 0x36, 0x5c, 0x99,
+ 0x7e, 0x03, 0x74, 0xfb, 0xa9, 0xb6, 0xde, 0xeb, 0xd1, 0x2b,
+ 0x5f, 0x12, 0x6a, 0xa9, 0x33, 0x2c, 0x2a, 0xba, 0xad, 0x8f,
+ 0xc2, 0x27, 0x57, 0x6a, 0xd7, 0x40, 0xf7, 0x4f, 0x4c, 0x9a,
+ 0xb0, 0x3a, 0x5d, 0x2e, 0xf9, 0xf1, 0xea, 0xbd, 0x82, 0xaa,
+ 0xbd, 0xe6, 0x19, 0x16, 0xd5, 0x03, 0x5e, 0x43, 0xfd, 0x88,
+ 0x71, 0xd5, 0xb7, 0x78, 0xbe, 0x80, 0x0f, 0xc9, 0x7f, 0x3a,
+ 0x8f, 0xe1, 0x44, 0xd4, 0x0f, 0xce, 0x26, 0xaf, 0x65, 0xe0,
+ 0xf5, 0x04, 0x53, 0x56, 0x97, 0x4f, 0xf4, 0xc1, 0x44, 0x8d,
+ 0xf7, 0x88, 0x55, 0x47, 0x16, 0xaf, 0x3f, 0x8e, 0x42, 0xdf,
+ 0xbc, 0x14, 0xc3, 0xe6, 0x9f, 0x0d, 0x69, 0x54, 0x5b, 0x7c,
+ 0x49, 0xcf, 0xbf, 0x42, 0x4f, 0xc7, 0x64, 0x8a, 0xe5, 0x84,
+ 0x87, 0x20, 0x9b, 0xfd, 0x70, 0x25, 0x38, 0xd3, 0xb4, 0x97,
+ 0x78, 0xf1, 0x4f, 0x3f, 0x0f, 0xbb, 0x9c, 0xa3, 0x17, 0xd5,
+ 0x4e, 0x4b, 0xac, 0x82, 0x9a, 0x73, 0xb7, 0xc5, 0xec, 0x10,
+ 0x7a, 0x7b, 0xdb, 0x77, 0x2c, 0xb1, 0xf3, 0x8f, 0xc3, 0xa5,
+ 0x31, 0x11, 0x32, 0x55, 0x35, 0xb5, 0x77, 0xd2, 0x62, 0x19,
+ 0x46, 0x92, 0x94, 0xbb, 0x61, 0x0f, 0x30, 0x94, 0x8a, 0xf6,
+ 0xf7, 0x30, 0xe0, 0xa2, 0x8c, 0x1b, 0xff, 0x8c, 0x29, 0x44,
+ 0xb4, 0xb7, 0xb6, 0x5f, 0x4d, 0x52, 0xc6, 0x07, 0xe1, 0x28,
+ 0x8c, 0xae, 0x88, 0x8a, 0x22, 0xbd, 0xd7, 0x36, 0xe4, 0x8f,
+ 0xd1, 0xeb, 0x65, 0x54, 0x19, 0x5f, 0xba, 0xfb, 0xfc, 0x91,
+ 0xa1, 0xa4, 0xb8, 0xa4, 0x2d, 0x85, 0x20, 0xc4, 0xe5, 0xa7,
+ 0x4e, 0xdb, 0xa4, 0xc5, 0xcc, 0x2f, 0x37, 0x41, 0x29, 0x47,
+ 0x15, 0xff, 0x04, 0x80, 0x08, 0x37, 0xce, 0xc5, 0xe3, 0x5a,
+ 0x3f, 0x83, 0xbb, 0x03, 0x9e, 0xfe, 0xec, 0xe4, 0x11, 0x41,
+ 0x12, 0x13, 0xf2, 0x00, 0xe5, 0x1a, 0x02, 0x49, 0xeb, 0xdb,
+ 0x57, 0xe4, 0xce, 0xa0, 0x3f, 0xfd, 0x3c, 0x73, 0x2b, 0x92,
+ 0x44, 0x79, 0x9e, 0x12, 0x4f, 0xfa, 0xe4, 0x53, 0x62, 0xf2,
+ 0xb0, 0xe2, 0x8a, 0xf0, 0x93, 0xa8, 0x1d, 0xee, 0x8d, 0x58,
+ 0x7a, 0x4c, 0x29, 0x91, 0x29, 0xc1, 0xa4, 0xd5, 0xe6, 0x37,
+ 0x1b, 0x75, 0x5b, 0xb6, 0x6b, 0x76, 0x2e, 0xcb, 0xbd, 0xa9,
+ 0xbe, 0x4c, 0x2e, 0x21, 0xa6, 0x38, 0xde, 0x66, 0x2f, 0x51,
+ 0xea, 0x4c, 0xba, 0x3f, 0x4a, 0xfe, 0x7a, 0x15, 0xb3, 0x72,
+ 0x26, 0xba, 0xcf, 0x9e, 0x1b, 0x03, 0xa6, 0xaa, 0x65, 0x68,
+ 0xd3, 0x8c, 0x15, 0x17, 0xe9, 0x11, 0x18, 0x3c, 0xb6, 0xf8,
+ 0x02, 0x54, 0x98, 0x49, 0xfa, 0x35, 0x3c, 0xcd, 0xac, 0xc8,
+ 0x2b, 0x1a, 0x63, 0x93, 0x03, 0x05, 0xa1, 0x41, 0xbe, 0x12,
+ 0xca, 0x15, 0x47, 0x72, 0x63, 0x77, 0x26, 0xd0, 0xe7, 0x8f,
+ 0x0d, 0x6e, 0x9c, 0xac, 0x07, 0xbe, 0x03, 0x22, 0xd0, 0x39,
+ 0x63, 0x8d, 0x9b, 0xc6, 0x20, 0x81, 0xb5, 0x67, 0x15, 0xf6,
+ 0xb0, 0xe3, 0xb9, 0x3e, 0xb7, 0x3f, 0x8f, 0x46, 0xc9, 0x74,
+ 0x10, 0x1e, 0x53, 0xf1, 0xd4, 0x30, 0x4d, 0x6e, 0x72, 0xb4,
+ 0x73, 0x1c, 0xb6, 0x79, 0x82, 0x60, 0x2e, 0x2a, 0x7d, 0x82,
+ 0x95, 0xb5, 0x7c, 0x4d, 0x44, 0xcb, 0xd8, 0x8a, 0x17, 0xe8,
+ 0x50, 0x29, 0xd8, 0x3a, 0xeb, 0x29, 0xc1, 0x83, 0x0f, 0xd9,
+ 0xaf, 0xcc, 0xfa, 0xea, 0x3a, 0x47, 0x5d, 0x33, 0x1f, 0xe8,
+ 0x33, 0x5b, 0x88, 0x8e, 0xdb, 0xd5, 0x1e, 0xaf, 0x4a, 0x5f,
+ 0xc0, 0xfa, 0xf0, 0xb5, 0xa3, 0x5b, 0xda, 0x38, 0xb7, 0x38,
+ 0x5e, 0xce, 0x81, 0x44, 0xf7, 0x66, 0x62, 0x64, 0x1d, 0x04,
+ 0xf0, 0x8a, 0x4f, 0xa2, 0x80, 0x76, 0x83, 0x23, 0x89, 0x61,
+ 0x6b, 0xc3, 0xb7, 0xee, 0xb5, 0x06, 0x33, 0xad, 0x63, 0x04,
+ 0x78, 0xc9, 0xde, 0x32, 0xde, 0xcf, 0x18, 0xb9, 0xb0, 0x3b,
+ 0xee, 0x0a, 0x58, 0xea, 0xad, 0xbc, 0x1e, 0x77, 0xa0, 0x93,
+ 0xf7, 0xae, 0x9e, 0xb6, 0x31, 0x59, 0x8e, 0xb1, 0x03, 0x8f,
+ 0xbb, 0xa4, 0x25, 0x0c, 0x2e, 0xd7, 0xe2, 0x62, 0x5c, 0xf1,
+ 0x68, 0xe9, 0x76, 0xd7, 0x23, 0x14, 0x45, 0xaf, 0xcb, 0x09,
+ 0x50, 0x05, 0x3f, 0xa0, 0xf9, 0xc3, 0x9e, 0x89, 0x05, 0xa8,
+ 0x3b, 0x54, 0x55, 0x32, 0x74, 0x91, 0x46, 0xc1, 0x2c, 0x96,
+ 0x7e, 0x60, 0xad, 0xfa, 0xbb, 0xcd, 0x09, 0x7b, 0x39, 0x10,
+ 0x82, 0x8a, 0xc0, 0x5a, 0x0d, 0xab, 0xb3, 0x71, 0x45, 0xad,
+ 0x39, 0x8e, 0xec, 0x4d, 0x91, 0x8d, 0xda, 0x8d, 0xfa, 0xb0,
+ 0xad, 0x44, 0x3c, 0xc9, 0x21, 0x56, 0x22, 0xfc, 0xd3, 0xba,
+ 0xb7, 0x3c, 0xe3, 0x8d, 0xda, 0x59, 0x34, 0x42, 0xdd, 0x04,
+ 0x5b, 0x8e, 0x2b, 0xc7, 0x94, 0xd5, 0x42, 0xe0, 0x4a, 0x6f,
+ 0x35, 0x5a, 0x27, 0x82, 0xd8, 0x82, 0x40, 0xee, 0x0f, 0xa6,
+ 0xef, 0xe4, 0x70, 0xe3, 0x30, 0xb7, 0x2d, 0xd4, 0xbb, 0x27,
+ 0xb2, 0xbf, 0xad, 0x49, 0x45, 0xbc, 0xeb, 0xbe, 0xb7, 0xd8,
+ 0xe3, 0xb1, 0xf3, 0xeb, 0x41, 0x20, 0x9b, 0x21, 0x54, 0xc3,
+ 0xa8, 0xaf, 0x9f, 0x20, 0x5c, 0x15, 0x8e, 0x25, 0xbc, 0xbc,
+ 0x69, 0x91, 0xfe, 0xda, 0xad, 0xe5, 0x37, 0x7d, 0xb0, 0x51,
+ 0x14, 0xae, 0x8f, 0x35, 0x15, 0x0a, 0xd4, 0x49, 0xa7, 0xd9,
+ 0x20, 0x70, 0xa4, 0xf2, 0xf4, 0x24, 0x66, 0x52, 0xd1, 0xa5,
+ 0x22, 0xea, 0x29, 0xd9, 0xb2, 0x82, 0x8d, 0x36, 0x66, 0x75,
+ 0x6e, 0xd5, 0x8c, 0x54, 0x08, 0x21, 0xf2, 0xee, 0x78, 0xc7,
+ 0x1f, 0x9c, 0x63, 0x5d, 0x88, 0x56, 0xd1, 0xa0, 0x80, 0x33,
+ 0x60, 0x55, 0x23, 0x72, 0xd6, 0xb0, 0x1a, 0x50, 0xde, 0x25,
+ 0x70, 0xb5, 0x77, 0x42, 0xf8, 0x19, 0x18, 0x15, 0x8f, 0xfd,
+ 0x0c, 0x6a, 0x46, 0x1f, 0xbf, 0xe7, 0x60, 0x91, 0xe7, 0xbb,
+ 0x25, 0x63, 0x66, 0xff, 0x11, 0x97, 0xbb, 0xfd, 0x3a, 0x17,
+ 0x94, 0x77, 0xb4, 0xc5, 0x21, 0xba, 0x30, 0x94, 0xdd, 0xe5,
+ 0xeb, 0x1d, 0x01, 0xba, 0xf9, 0xb0, 0x30, 0xdb, 0x11, 0x93,
+ 0xb7, 0xfa, 0x79, 0xe8, 0x5e, 0xb3, 0x39, 0xf4, 0x51, 0x68,
+ 0x31, 0xce, 0xe9, 0x0e, 0x93, 0xde, 0xff, 0xec, 0x27, 0xbd,
+ 0xa6, 0x1a, 0x4c, 0xe0, 0x92, 0x5c, 0xd4, 0x07, 0xd2, 0xa1,
+ 0xdd, 0x12, 0x83, 0xd2, 0x9a, 0x79, 0xb3, 0x3c, 0xfb, 0x07,
+ 0xe3, 0x18, 0x1a, 0xa3, 0x24, 0x80, 0xb4, 0xcc, 0xf4, 0xc6,
+ 0xa5, 0x6c, 0x25, 0xd7, 0x99, 0x1a, 0x30, 0xf0, 0xa9, 0xfc,
+ 0x2e, 0x83, 0x44, 0xac, 0x64, 0x76, 0x34, 0xb0, 0xa6, 0x6f,
+ 0x20, 0x5a, 0x14, 0xf2, 0x07, 0xa7, 0x6f, 0x4d, 0xab, 0xf5,
+ 0xfc, 0x9d, 0xd6, 0x3e, 0x82, 0x48, 0x31, 0x25, 0x47, 0xc9,
+ 0x0e, 0x1d, 0xdb, 0x98, 0x91, 0x56, 0xf5, 0xfe, 0x66, 0x8d,
+ 0x48, 0xf0, 0x4c, 0x6c, 0x2c, 0x96, 0x54, 0x43, 0xec, 0x76,
+ 0xf2, 0xe1, 0x76, 0x68, 0xc8, 0xe1, 0xde, 0x0d, 0x8e, 0x6f,
+ 0xfc, 0x15, 0xd5, 0x93, 0x92, 0xfe, 0xca, 0x9b, 0x30, 0x61,
+ 0x03, 0x0b, 0xca, 0x99, 0x2f, 0xd3, 0x15, 0xe9, 0x66, 0x81,
+ 0xbd, 0x56, 0x17, 0x14, 0x4a, 0x2e, 0xf1, 0x34, 0x84, 0x55,
+ 0x9d, 0xc0, 0x2b, 0xa7, 0x4a, 0xee, 0xf1, 0x7c, 0x67, 0xc7,
+ 0xf3, 0x08, 0x1e, 0x6d, 0x6b, 0x5b, 0xcc, 0x81, 0x91, 0x5c,
+ 0x94, 0x1a, 0x80, 0xda, 0x3a, 0xce, 0x36, 0x05, 0xb0, 0x7a,
+ 0xe8, 0xd0, 0xb4, 0x57, 0x9c, 0xf9, 0xea, 0xf3, 0x26, 0x1d,
+ 0xcb, 0xf8, 0xdd, 0x65, 0xaf, 0xf7, 0xcd, 0xf7, 0xa1, 0x3d,
+ 0xfc, 0x9a, 0x3b, 0x08, 0xb9, 0xfa, 0x3c, 0x16, 0x49, 0x4a,
+ 0xf1, 0xba, 0x4d, 0x31, 0xdd, 0x5e, 0x4f, 0x3d, 0x66, 0x22,
+ 0x1b, 0x08, 0x91, 0x7d, 0xc6, 0xaf, 0x15, 0x07, 0x3c, 0xa1,
+ 0xf7, 0x07, 0xfd, 0x3e, 0x90, 0xbb, 0x6f, 0x7a, 0xe9, 0xe1,
+ 0x2f, 0xb9, 0xee, 0x91, 0x8e, 0x18, 0xcc, 0x8d, 0x1d, 0x22,
+ 0xa0, 0xa0, 0x28, 0x25, 0xfc, 0xd4, 0x94, 0xd3, 0xaa, 0xcf,
+ 0xce, 0xd0, 0x85, 0x82, 0x6f, 0x20, 0x9f, 0x55, 0x0e, 0xe5,
+ 0x72, 0x0d, 0x17, 0x3e, 0x34, 0xc7, 0x2c, 0x0a, 0x14, 0x45,
+ 0x27, 0xe2, 0xc7, 0x2f, 0x86, 0xa1, 0x55, 0x3e, 0x78, 0x03,
+ 0xe9, 0x78, 0x2e, 0xd3, 0x99, 0xee, 0xa0, 0x14, 0xf8, 0xe3,
+ 0x6c, 0xeb, 0x3f, 0x9a, 0xf3, 0x15, 0xce, 0xd5, 0x76, 0xf6,
+ 0x3a, 0x86, 0x30, 0x76, 0xf9, 0x88, 0x30, 0xf5, 0x4a, 0x50,
+ 0x58, 0x80, 0xe9, 0xd9, 0xd4, 0xb9, 0x34, 0x42, 0xa6, 0x4e,
+ 0x9c, 0x1a, 0x07, 0x16, 0x9e, 0xee, 0xe4, 0x88, 0x04, 0x8e,
+ 0xa8, 0xe7, 0xcd, 0xe8, 0x47, 0x1e, 0x54, 0x45, 0xd2, 0x65,
+ 0xd8, 0xee, 0x4b, 0xbd, 0xd0, 0x85, 0xaa, 0xfb, 0x06, 0x53,
+ 0x91, 0x7e, 0xe0, 0x59, 0x20, 0x57, 0x6a, 0xee, 0xd8, 0x9f,
+ 0x77, 0x7f, 0xd7, 0x40, 0x63, 0xbb, 0x21, 0x75, 0x76, 0x11,
+ 0x27, 0xcf, 0x05, 0xbb, 0x41, 0x30, 0x98, 0xbf, 0xdc, 0x5f,
+ 0xc6, 0xa4, 0x1e, 0x30, 0xa1, 0x53, 0xd4, 0x36, 0x7f, 0x2e,
+ 0x86, 0xd7, 0xd9, 0x95, 0x29, 0xd5, 0x46, 0x18, 0x60, 0x27,
+ 0xe4, 0x6f, 0xcb, 0xf4, 0xe2, 0xfe, 0xff, 0x3e, 0xff, 0x15,
+ 0xc6, 0xf2, 0x31, 0xf9, 0x2a, 0xc8, 0x05, 0x4e, 0x7c, 0x2e,
+ 0x92, 0xc8, 0x41, 0x4f, 0x9e, 0x23, 0x21, 0x4d, 0x74, 0xf8,
+ 0xc3, 0x44, 0x39, 0xc2, 0x69, 0x4b, 0x2e, 0x76, 0x5e, 0x44,
+ 0x12, 0x65, 0x31, 0x98, 0xbe, 0x0a, 0x10, 0x11, 0x12, 0x2c,
+ 0x67, 0x3d, 0x85, 0x2e, 0xd3, 0x97, 0x54, 0x1e, 0xb6, 0xad,
+ 0xd9, 0x45, 0x11, 0x53, 0x04, 0x7c, 0x3f, 0xf4, 0xc9, 0xac,
+ 0x82, 0x1b, 0x84, 0xf4, 0x20, 0x6b, 0xf1, 0xf5, 0x72, 0x04,
+ 0x24, 0xc1, 0xd3, 0x42, 0x43, 0x52, 0x9d, 0x2d, 0xd3, 0x89,
+ 0x8e, 0xd8, 0x28, 0xb9, 0xa2, 0xb4, 0xed, 0xbc, 0x76, 0x87,
+ 0x55, 0x67, 0x39, 0xd9, 0xb7, 0x20, 0x6a, 0xec, 0xec, 0xb8,
+ 0x14, 0x51, 0x91, 0xb9, 0x96, 0x0f, 0x7a, 0x3a, 0x12, 0xde,
+ 0x14, 0x3b, 0x83, 0xcf, 0x41, 0x5b, 0x5d, 0xff, 0x33, 0x68,
+ 0xdb, 0x53, 0x64, 0x93, 0xb1, 0xc3, 0x8a, 0x46, 0xa8, 0x44,
+ 0x9c, 0x14, 0x12, 0x6c, 0x92, 0x6f, 0xae, 0xc3, 0x45, 0xb2,
+ 0xa1, 0x67, 0x81, 0x3c, 0x22, 0x47, 0xfd, 0xa4, 0x7a, 0x79,
+ 0xa8, 0x0a, 0xfb, 0x7a, 0x91, 0x6e, 0xe9, 0x53, 0xec, 0x98,
+ 0x82, 0x57, 0xad, 0x05, 0x38, 0x55, 0xc1, 0xce, 0x3a, 0x04,
+ 0x4d, 0x12, 0x72, 0x37, 0x4a, 0x36, 0x54, 0x3f, 0x67, 0x8a,
+ 0xee, 0xd9, 0xf3, 0x80, 0xd5, 0xd7, 0xb8, 0xfc, 0x6e, 0x4f,
+ 0x60, 0x2b, 0x5a, 0xa4, 0xc5, 0x05, 0xdb, 0xe5, 0x09, 0xe3,
+ 0xeb, 0xa2, 0x51, 0x33, 0x30, 0x96, 0x46, 0x01, 0x26, 0x8f,
+ 0x38, 0xc9, 0x97, 0x32, 0x2d, 0xb4, 0x59, 0x15, 0x15, 0x38,
+ 0x66, 0x66, 0xfe, 0xcb, 0xee, 0xc1, 0xf6, 0x4e, 0xb7, 0xdf,
+ 0x7b, 0x63, 0xe6, 0x3f, 0xe0, 0x1c, 0x97, 0xed, 0x86, 0xf3,
+ 0xd2, 0xad, 0x42, 0x29, 0x20, 0x28, 0xa6, 0x59, 0x58, 0x7d,
+ 0x8f, 0x5c, 0x43, 0x07, 0xd1, 0x7e, 0x83, 0xba, 0x9c, 0x1b,
+ 0xfe, 0x17, 0x9e, 0xc8, 0x09, 0x63, 0x9a, 0x2d, 0x61, 0x33,
+ 0x51, 0x46, 0x01, 0xa8, 0xe9, 0x43, 0x1e, 0x4e, 0xfe, 0x61,
+ 0x1a, 0x28, 0x11, 0x65, 0x70, 0x43, 0x9f, 0xfc, 0x21, 0x1d,
+ 0x76, 0x7b, 0x40, 0x08, 0x18, 0xd3, 0xe8, 0xc2, 0xe3, 0x8c,
+ 0xe7, 0x27, 0xc2, 0xec, 0xb0, 0x08, 0x3e, 0x6b, 0x8f, 0x77,
+ 0x6d, 0x9e, 0xa6, 0xab, 0xce, 0x9a, 0xf8, 0x8f, 0x77, 0xb3,
+ 0xf4, 0xe8, 0x8b, 0xe7, 0xd9, 0xa1, 0x95, 0x40, 0x6b, 0xca,
+ 0x21, 0x98, 0xff, 0xdc, 0xdc, 0x96, 0xc3, 0x08, 0x81, 0x72,
+ 0x9a, 0xdd, 0xe2, 0xcf, 0x95, 0x99, 0xa6, 0xa3, 0x5e, 0x9e,
+ 0x25, 0x60, 0xa3, 0xc3, 0x39, 0xf7, 0x54, 0x6c, 0xf2, 0x75,
+ 0xa9, 0x38, 0x12, 0x38, 0x4d, 0x42, 0xe8, 0xec, 0x13, 0x25,
+ 0xa0, 0xf8, 0x04, 0xb8, 0xf6, 0x66, 0x0b, 0x56, 0xe1, 0xfb,
+ 0x26, 0x03, 0xe6, 0xa5, 0xf1, 0x4d, 0x7f, 0xa5, 0x9d, 0x58,
+ 0x71, 0xd8, 0xc7, 0x6a, 0xbe, 0xdc, 0x90, 0x89, 0xb1, 0x36,
+ 0xb4, 0xb6, 0xb4, 0xbb, 0xaf, 0x6e, 0x43, 0x10, 0xa6, 0xea,
+ 0xee, 0x12, 0xcb, 0x08, 0x2c, 0x4e, 0x66, 0xf0, 0x1f, 0xf4,
+ 0xbf, 0xd3, 0xeb, 0x63, 0x48, 0xd0, 0xbe, 0x8a, 0xed, 0x24,
+ 0xdb, 0x0f, 0x23, 0x1d, 0x2e, 0x30, 0x97, 0x0f, 0xd8, 0xc6,
+ 0x3b, 0x04, 0x2f, 0x33, 0x78, 0x20, 0x6e, 0xb1, 0x33, 0x03,
+ 0x27, 0xac, 0x0a, 0x37, 0x15, 0x31, 0xef, 0x4d, 0x43, 0xcc,
+ 0xa0, 0x49, 0x80, 0xe3, 0x8c, 0xc0, 0xf3, 0xf7, 0x2d, 0x37,
+ 0x1d, 0xd3, 0x90, 0x5f, 0xad, 0x31, 0xb5, 0x95, 0x17, 0x69,
+ 0x4b, 0xec, 0x84, 0x9d, 0x2b, 0x8d, 0xdd, 0x9b, 0x58, 0x04,
+ 0xba, 0x28, 0x0e, 0x28, 0xc1, 0x54, 0x6c, 0xb0, 0x25, 0x0c,
+ 0x4f, 0x98, 0x47, 0xf7, 0x93, 0xc2, 0xae, 0x2f, 0x6d, 0x29,
+ 0x9c, 0x3d, 0xe3, 0xb5, 0xe3, 0x28, 0x43, 0x14, 0xe6, 0x92,
+ 0x4c, 0x79, 0x90, 0x59, 0x75, 0x77, 0x56, 0x43, 0xda, 0xac,
+ 0xa9, 0x42, 0xd7, 0xca, 0x95, 0x73, 0x26, 0x54, 0x1f, 0x3a,
+ 0x8a, 0x37, 0x64, 0xd7, 0xcf, 0xe1, 0x31, 0xf7, 0x40, 0x59,
+ 0xfd, 0xff, 0xea, 0x72, 0xfd, 0xc4, 0xde, 0xe3, 0x4d, 0x8a,
+ 0xf5, 0x80, 0xc0, 0x61, 0x21, 0xbd, 0xbd, 0x8e, 0x42, 0xd5,
+ 0x4c, 0xe4, 0xf4, 0x78, 0x31, 0xca, 0xf1, 0xec, 0x7c, 0x7b,
+ 0x85, 0x6a, 0x05, 0x54, 0xbe, 0x38, 0x54, 0x2f, 0x1f, 0xda,
+ 0x9f, 0x98, 0xe2, 0x79, 0xd7, 0x42, 0xca, 0xba, 0x85, 0x21,
+ 0xe2, 0xcb, 0x2b, 0xae, 0x4a, 0x4e, 0x35, 0xfb, 0xcf, 0x3d,
+ 0xc5, 0xae, 0x27, 0x30, 0xa9, 0x45, 0xe6, 0x3b, 0x43, 0x3e,
+ 0x35, 0xe3, 0xf2, 0x0d, 0x53, 0x32, 0x2b, 0xf6, 0xe6, 0xc7,
+ 0xd5, 0x02, 0x82, 0x03, 0xc1, 0x00, 0xd4, 0x04, 0x9b, 0xef,
+ 0x5d, 0x58, 0xb0, 0xa3, 0xaa, 0xd2, 0xab, 0x53, 0x65, 0x99,
+ 0x03, 0x49, 0x48, 0x4d, 0xf5, 0xdf, 0x5d, 0x16, 0x14, 0x11,
+ 0x60, 0x45, 0x1b, 0xff, 0x4a, 0x60, 0x2b, 0x37, 0x63, 0xf6,
+ 0xa7, 0x8a, 0xa8, 0xff, 0x08, 0x97, 0x08, 0xfc, 0xbb, 0xb3,
+ 0x20, 0xa3, 0xcd, 0xd9, 0x58, 0xdb, 0x16, 0x1b, 0x88, 0x02,
+ 0x1e, 0x0f, 0x43, 0x9b, 0x16, 0x7e, 0xbe, 0xb1, 0x9c, 0x13,
+ 0x10, 0xdc, 0xa1, 0x56, 0xff, 0xa3, 0xff, 0x5e, 0x69, 0x30,
+ 0xee, 0x7e, 0x76, 0x5f, 0x84, 0x94, 0xeb, 0x8f, 0x58, 0xf8,
+ 0xcf, 0xbb, 0x99, 0x6e, 0xf0, 0xd8, 0x32, 0xf6, 0xce, 0x48,
+ 0x6f, 0x7c, 0xc8, 0x8f, 0xd3, 0x86, 0x22, 0x49, 0x9f, 0xde,
+ 0x11, 0x05, 0xa4, 0xdc, 0x92, 0xfb, 0x0f, 0xfa, 0x09, 0x4d,
+ 0x17, 0x1a, 0xe2, 0x76, 0x67, 0x40, 0xa9, 0x5b, 0x1b, 0x54,
+ 0x66, 0x48, 0xf7, 0xc3, 0x59, 0xd4, 0xcf, 0x55, 0xd0, 0x7f,
+ 0x3b, 0xb0, 0xa2, 0xd8, 0xec, 0xb7, 0x88, 0xe7, 0xb0, 0x30,
+ 0x72, 0x42, 0x65, 0xe2, 0x91, 0xa7, 0x9b, 0xf6, 0x07, 0x45,
+ 0x52, 0x51, 0xaa, 0xbe, 0x32, 0x35, 0xe4, 0x88, 0x23, 0xe7,
+ 0xcb, 0x3c, 0x1c, 0xfb, 0x0b, 0x96, 0xd5, 0xb3, 0x92, 0x86,
+ 0x79, 0x5b, 0x47, 0x93, 0xd6, 0xbd, 0xc7, 0x21, 0x17, 0xd0,
+ 0xc9, 0xc7, 0x69, 0x84, 0x80, 0x98, 0xaf, 0x2c, 0x63, 0xd1,
+ 0xef, 0x6e, 0xca, 0x84, 0x30, 0x32, 0x83, 0x2d, 0x49, 0xbb,
+ 0x1f, 0x2a, 0xfe, 0x40, 0x7c, 0x03, 0xd4, 0x45, 0xdc, 0xfe,
+ 0x94, 0xf9, 0xe4, 0x36, 0x47, 0xfa, 0x7e, 0x2e, 0x93, 0x03,
+ 0xf8, 0x15, 0xf9, 0xce, 0xc3, 0x5b, 0x76, 0x10, 0xec, 0x89,
+ 0x8c, 0xce, 0x25, 0xa5, 0x77, 0x9a, 0xc5, 0x1e, 0xdd, 0x07,
+ 0x1b, 0x5b, 0xac, 0x6f, 0xdb, 0x94, 0x85, 0xdf, 0x02, 0x22,
+ 0xd1, 0xa9, 0x01, 0x8e, 0x63, 0xa1, 0xee, 0x94, 0x9c, 0xdb,
+ 0xb4, 0x1a, 0x43, 0xe1, 0x1f, 0x4e, 0x2f, 0x68, 0x50, 0x0c,
+ 0x2f, 0x5b, 0xc5, 0x1b, 0xe1, 0x8d, 0x4b, 0xe0, 0x63, 0x8d,
+ 0x7a, 0x30, 0xbe, 0xb7, 0x2e, 0x02, 0xc6, 0x02, 0xac, 0xa8,
+ 0xb8, 0x65, 0xc6, 0x28, 0xee, 0xe4, 0xec, 0x99, 0xa1, 0x9a,
+ 0xfd, 0x1f, 0xb5, 0x85, 0x7a, 0x94, 0x16, 0xe2, 0xe7, 0x74,
+ 0x06, 0x54, 0x1b, 0xd0, 0xaf, 0x58, 0x4e, 0x50, 0x7e, 0xd6,
+ 0xe4, 0x31, 0xd2, 0x0c, 0xd7, 0x9d, 0xe2, 0x00, 0x30, 0xbe,
+ 0x26, 0x30, 0x48, 0x99, 0x98, 0x58, 0x54, 0x5a, 0xc4, 0x0a,
+ 0x6c, 0xa1, 0x06, 0xe9, 0x38, 0xe6, 0x79, 0x39, 0x00, 0x9e,
+ 0xb6, 0xe3, 0xf7, 0x01, 0xcf, 0x2f, 0x82, 0x5e, 0xc3, 0x21,
+ 0x1b, 0x79, 0x93, 0xb5, 0xe4, 0x39, 0x9d, 0x32, 0x9d, 0x72,
+ 0xa4, 0xa8, 0xc9, 0x90, 0xce, 0xaf, 0xc0, 0x00, 0xad, 0x20,
+ 0x87, 0x26, 0xc7, 0xd3, 0x5f, 0x2e, 0xf0, 0x5e, 0xf8, 0x8b,
+ 0x85, 0xa3, 0xc6, 0x66, 0xd8, 0x2f, 0x86, 0xfe, 0x7d, 0x8d,
+ 0x22, 0xa5, 0x6d, 0x68, 0x3e, 0x87, 0x6e, 0xf7, 0xf1, 0xf0,
+ 0x07, 0xc4, 0xe3, 0xf1, 0x84, 0xc4, 0x93, 0x42, 0x06, 0x20,
+ 0x80, 0x64, 0xb3, 0x52, 0x5c, 0xa5, 0xcf, 0xee, 0xfe, 0xa4,
+ 0x09, 0x41, 0xbe, 0xaa, 0x78, 0x52, 0x76, 0x3f, 0xf7, 0xe8,
+ 0xa1, 0x6b, 0x0a, 0xbc, 0x22, 0xbe, 0xdf, 0x72, 0x7b, 0xea,
+ 0x90, 0x43, 0xee, 0xc2, 0x0b, 0x26, 0xdc, 0x02, 0x26, 0xa7,
+ 0x50, 0x04, 0x7a, 0x06, 0x91, 0xae, 0x93, 0xd5, 0xd2, 0xc9,
+ 0xa1, 0xe1, 0xfc, 0xb9, 0x8c, 0x94, 0xca, 0xa8, 0x1c, 0x2c,
+ 0x57, 0x97, 0x3e, 0x50, 0xed, 0x93, 0x45, 0x7a, 0x2c, 0x59,
+ 0x7b, 0x34, 0x8f, 0xcd, 0xd6, 0x17, 0x93, 0xd8, 0xde, 0xe8,
+ 0xb0, 0x9e, 0x27, 0x15, 0xc5, 0xbb, 0xa5, 0xbb, 0xc2, 0x30,
+ 0x9b, 0xc7, 0x27, 0x02, 0x18, 0xd8, 0xdb, 0xa4, 0x84, 0x37,
+ 0x64, 0xf7, 0xf7, 0xf1, 0xc8, 0x86, 0x4c, 0x64, 0x97, 0x08,
+ 0xe9, 0x4e, 0x0e, 0xb6, 0x92, 0xe9, 0x4c, 0x7b, 0x7f, 0xe1,
+ 0xcc, 0xa0, 0x71, 0xa7, 0x34, 0x48, 0x46, 0xbb, 0x37, 0xce,
+ 0xb0, 0x4d, 0x39, 0xa8, 0x0e, 0xab, 0xf6, 0x2f, 0x7c, 0x88,
+ 0xae, 0xcf, 0x90, 0xc6, 0x01, 0xd3, 0x5b, 0x37, 0xe9, 0xb1,
+ 0x28, 0x42, 0x14, 0xbf, 0x59, 0x35, 0x04, 0xab, 0x46, 0x6e,
+ 0xa8, 0x29, 0xe2, 0x7a, 0x77, 0x0e, 0x07, 0x67, 0xe4, 0x2b,
+ 0x03, 0xd2, 0x02, 0x36, 0x16, 0xd7, 0x81, 0x5d, 0x38, 0x9c,
+ 0x68, 0x9c, 0xf5, 0x9e, 0x49, 0x7d, 0x99, 0xfd, 0xcd, 0x1d,
+ 0xd2, 0xdf, 0x3c, 0x36, 0x19, 0x85, 0xaa, 0xb1, 0x30, 0x7a,
+ 0x21, 0xb1, 0x83, 0x16, 0xcf, 0xd1, 0x75, 0xa5, 0x9d, 0xd7,
+ 0xc1, 0x60, 0xa8, 0xdb, 0x1e, 0xb9, 0x3e, 0x9c, 0x12, 0x42,
+ 0xe8, 0x47, 0x49, 0x18, 0x9f, 0x5c, 0x12, 0xd1, 0x69, 0xd5,
+ 0x7d, 0xa8, 0x3c, 0xda, 0x35, 0x8a, 0x6c, 0x63, 0xb8, 0x62,
+ 0x8a, 0x61, 0xfa, 0xf2, 0x61, 0x11, 0x1e, 0xb6, 0xf3, 0x5c,
+ 0x62, 0x9d, 0xa7, 0x62, 0x0c, 0x87, 0x93, 0xe2, 0x23, 0x6c,
+ 0x3d, 0xa9, 0x2c, 0x4b, 0xd5, 0x7f, 0xfe, 0x72, 0x27, 0x36,
+ 0x06, 0xcb, 0x65, 0x38, 0xef, 0x13, 0x57, 0x6a, 0xc9, 0xc6,
+ 0x4f, 0x51, 0xd0, 0x90, 0x06, 0xa0, 0x23, 0x65, 0x95, 0xce,
+ 0x16, 0x8f, 0x8d, 0xb2, 0xf9, 0x7f, 0x3c, 0x2c, 0x30, 0x5a,
+ 0x38, 0xf1, 0x62, 0x79, 0x4b, 0xe5, 0xd7, 0x0a, 0x3f, 0x83,
+ 0x5f, 0x46, 0x26, 0x97, 0xb7, 0x08, 0x8c, 0x5b, 0xb8, 0x02,
+ 0x28, 0xf2, 0x4d, 0xdf, 0x93, 0x97, 0xc5, 0x94, 0x4b, 0x0e,
+ 0x42, 0xc3, 0x35, 0x91, 0x6b, 0x69, 0x61, 0x76, 0x7f, 0x94,
+ 0xcf, 0x0b, 0x81, 0x33, 0xff, 0xf3, 0x0c, 0xc7, 0x01, 0x94,
+ 0x94, 0xa9, 0xed, 0xcd, 0x4b, 0xc8, 0xcb, 0x91, 0xf9, 0x7a,
+ 0x47, 0xcd, 0x79, 0x3c, 0xa6, 0xde, 0x52, 0xd2, 0x47, 0x5c,
+ 0x10, 0x62, 0xbb, 0xe5, 0x32, 0xde, 0x83, 0xcf, 0xa8, 0x52,
+ 0xb3, 0xe7, 0xf9, 0xec, 0x17, 0x34, 0xbf, 0x33, 0x5d, 0xb2,
+ 0x4e, 0x56, 0xf7, 0x29, 0xd9, 0x5c, 0x1b, 0x83, 0x01, 0xbb,
+ 0xb9, 0x2b, 0x95, 0x52, 0x08, 0xab, 0xa4, 0x51, 0x03, 0xa1,
+ 0xfb, 0x6a, 0x50, 0xcd, 0xa8, 0x9d, 0x95, 0x6f, 0x7e, 0xb1,
+ 0x80, 0x1e, 0x9d, 0x81, 0x01, 0x26, 0x41, 0x78, 0x36, 0x3c,
+ 0x8a, 0x44, 0xf4, 0x98, 0x88, 0x1c, 0x5d, 0x06, 0xd3, 0xd2,
+ 0xb2, 0x58, 0x7d, 0xa1, 0x45, 0x1b, 0xbf, 0x8c, 0xf6, 0x6a,
+ 0xfa, 0xfd, 0x08, 0x29, 0x3e, 0x91, 0x57, 0xf1, 0x3d, 0x20,
+ 0xed, 0x49, 0x6e, 0x9c, 0x46, 0xd5, 0x08, 0x8d, 0x9b, 0xf8,
+ 0xef, 0xa3, 0x3a, 0x98, 0xcb, 0xb4, 0xcb, 0x5b, 0x30, 0x25,
+ 0x20, 0xcc, 0x04, 0xa1, 0xeb, 0xeb, 0xee, 0x1b, 0x36, 0x85,
+ 0xc1, 0x93, 0x16, 0x5a, 0x31, 0xdf, 0xd6, 0x0e, 0x73, 0x9e,
+ 0x63, 0x6e, 0x96, 0x90, 0x54, 0xd2, 0xc2, 0x53, 0x69, 0x93,
+ 0xd5, 0x54, 0xca, 0xd8, 0x84, 0xf7, 0x8f, 0x9a, 0xd1, 0x80,
+ 0x0d, 0x57, 0xa8, 0x26, 0xbe, 0x45, 0x64, 0xd5, 0x2b, 0xbb,
+ 0x45, 0xb5, 0x08, 0xb9, 0x37, 0x57, 0x02, 0x82, 0x03, 0xc1,
+ 0x00, 0xd1, 0x30, 0x2e, 0xb7, 0x9b, 0xe7, 0x5d, 0x13, 0x74,
+ 0x1f, 0x52, 0xf2, 0x02, 0x18, 0xe9, 0x07, 0x87, 0x9e, 0xed,
+ 0xde, 0x83, 0x92, 0xcf, 0x73, 0x61, 0x21, 0xc4, 0x62, 0x30,
+ 0x6c, 0xa2, 0x36, 0xbd, 0xe2, 0xc5, 0x19, 0xf6, 0xdf, 0x51,
+ 0x7b, 0xca, 0xd4, 0xe4, 0x51, 0x83, 0x49, 0x27, 0xdd, 0xbd,
+ 0xb0, 0x10, 0x79, 0x39, 0xdd, 0x0e, 0x3d, 0x65, 0xad, 0x6d,
+ 0xa3, 0x95, 0x52, 0x85, 0xdb, 0x18, 0x94, 0x60, 0xaa, 0xc0,
+ 0xc8, 0x8b, 0xdb, 0xfe, 0xf9, 0xf0, 0x86, 0xf9, 0x33, 0x8a,
+ 0xd7, 0xbe, 0x8d, 0x43, 0x83, 0x4d, 0xe4, 0x17, 0x2b, 0x46,
+ 0x54, 0x44, 0x1b, 0xbe, 0x52, 0x64, 0x47, 0x02, 0x6c, 0x4a,
+ 0x64, 0xb4, 0x3f, 0x21, 0x2f, 0xbb, 0xe3, 0x72, 0x7c, 0x26,
+ 0x14, 0xdf, 0x80, 0x50, 0xd4, 0x94, 0xe9, 0xc6, 0x7d, 0x71,
+ 0xd8, 0xaf, 0xfb, 0x74, 0x36, 0x33, 0xbe, 0x58, 0x63, 0xad,
+ 0xcb, 0xdf, 0xc0, 0x73, 0x9e, 0x19, 0xb0, 0x65, 0xe1, 0xd1,
+ 0x10, 0x44, 0xf1, 0xf0, 0x08, 0xa3, 0x09, 0x25, 0xeb, 0xd5,
+ 0xcb, 0xdd, 0x98, 0xdd, 0xbc, 0x09, 0x2c, 0xef, 0xc1, 0x8d,
+ 0x43, 0x15, 0x41, 0xc2, 0xa1, 0x84, 0x37, 0x70, 0x5a, 0xd5,
+ 0xf5, 0xb2, 0x6a, 0x1f, 0xbb, 0xcc, 0x30, 0xb9, 0xd9, 0xc7,
+ 0x36, 0x21, 0xf3, 0x69, 0x3e, 0x91, 0x38, 0x4d, 0xa5, 0xc4,
+ 0xf7, 0x84, 0x90, 0x34, 0x0e, 0x47, 0x7e, 0x26, 0xf2, 0x98,
+ 0x25, 0x26, 0xda, 0xf0, 0x4e, 0x55, 0xea, 0x4d, 0x9b, 0x8a,
+ 0x4a, 0xe1, 0x1f, 0xa0, 0x07, 0x90, 0x9e, 0x59, 0x64, 0xae,
+ 0xd9, 0xd6, 0x7e, 0x72, 0xa1, 0xc4, 0xea, 0x7d, 0xbd, 0x1f,
+ 0x7d, 0x2b, 0xd9, 0x2c, 0xdc, 0x8b, 0xc0, 0xda, 0x52, 0x0c,
+ 0xd1, 0xd0, 0x56, 0xb7, 0x93, 0xc7, 0x26, 0x79, 0x71, 0xd0,
+ 0x0d, 0xae, 0xaa, 0xa7, 0xe4, 0xc1, 0x59, 0x27, 0x68, 0x97,
+ 0x9a, 0xff, 0x3d, 0x36, 0x07, 0x55, 0x77, 0x07, 0x97, 0x69,
+ 0xf3, 0x99, 0x91, 0x3f, 0x63, 0xfd, 0x70, 0x8c, 0xa1, 0xeb,
+ 0xc5, 0x21, 0xa3, 0xfe, 0x99, 0x96, 0x11, 0x37, 0xb9, 0xe6,
+ 0x93, 0xf8, 0xd0, 0xb1, 0xa3, 0x57, 0x7a, 0xa8, 0x63, 0xdd,
+ 0x09, 0x56, 0xb0, 0x3b, 0xa6, 0x59, 0xc7, 0x89, 0x54, 0x16,
+ 0xe9, 0x2d, 0x78, 0x7d, 0xaf, 0x4e, 0x0a, 0x5b, 0x62, 0x3b,
+ 0x0b, 0xcb, 0x24, 0x89, 0x4e, 0x1c, 0x3d, 0xe1, 0xbd, 0x5a,
+ 0x3e, 0xc5, 0xfd, 0x15, 0x3d, 0x08, 0x38, 0x33, 0x5e, 0x37,
+ 0x4c, 0xe3, 0xe3, 0xe9, 0xc4, 0x1d, 0x2b, 0xd4, 0x58, 0x25,
+ 0x58, 0x23, 0x8e, 0xc6, 0x83, 0x9a, 0xf3, 0x9a, 0x78, 0xe9,
+ 0xa7, 0xca, 0xd7, 0xdd, 0x89, 0x20, 0x6e, 0x02, 0xea, 0x6b,
+ 0x37, 0x74, 0xda, 0xa0, 0xc2, 0x5a, 0x2b, 0x80, 0x1c, 0x28,
+ 0x91, 0x0d, 0x50, 0x64, 0xf0, 0x12, 0xe7, 0xc4, 0x7e, 0xdd,
+ 0x28, 0x3b, 0x26, 0x9a, 0xf4, 0x39, 0x56, 0xa4, 0x72, 0x4d,
+ 0xcb, 0x67, 0x3c, 0x68, 0xb2, 0x6f, 0xf0, 0xd0, 0x15, 0x90,
+ 0xc8, 0x08, 0xbb, 0x0b, 0x08, 0x6b, 0x8a, 0xde, 0x41, 0x57,
+ 0xbc, 0x63, 0x0e, 0x00, 0x8d, 0xf8, 0xdd, 0x93, 0xce, 0x58,
+ 0x7b, 0xa8, 0xb9, 0x64, 0x26, 0x06, 0xe7, 0x71, 0x23, 0x0f,
+ 0x41, 0xf1, 0xb7, 0xae, 0x59, 0x2e, 0xd0, 0x73, 0xc5, 0xd9,
+ 0xdc, 0x0e, 0x1c, 0x02, 0x58, 0x69, 0xb3, 0x15, 0x6d, 0x96,
+ 0x2b, 0xdb, 0x7b, 0x3b, 0x6c, 0x38, 0x32, 0x6b, 0xd8, 0x08,
+ 0xb2, 0xbd, 0xa7, 0x49, 0x43, 0xeb, 0x90, 0x42, 0x70, 0xc5,
+ 0xba, 0xcd, 0x4a, 0x44, 0x8f, 0x83, 0x0d, 0x17, 0x51, 0x5a,
+ 0x95, 0xa2, 0x57, 0x9a, 0x16, 0x19, 0x91, 0xbb, 0x90, 0x5c,
+ 0x2a, 0x16, 0xe8, 0x26, 0x10, 0x3c, 0xb7, 0x10, 0x5c, 0xf8,
+ 0xc5, 0x15, 0x2b, 0x70, 0x75, 0x69, 0xba, 0x7b, 0x3d, 0x0b,
+ 0x57, 0xac, 0x39, 0x12, 0x2e, 0xd6, 0xd9, 0x13, 0x74, 0x8e,
+ 0xa8, 0x0b, 0x17, 0xe1, 0x03, 0x7a, 0xba, 0x1d, 0x07, 0x91,
+ 0x8c, 0x2a, 0x3a, 0x8d, 0xe0, 0x2a, 0x94, 0xd4, 0x16, 0x35,
+ 0x64, 0x8b, 0x92, 0x2c, 0x2f, 0xa4, 0x18, 0xfe, 0x3f, 0x02,
+ 0x19, 0x8c, 0xb9, 0xeb, 0xaf, 0x01, 0x06, 0xa8, 0x37, 0x7f,
+ 0xe2, 0x44, 0x10, 0xce, 0xeb, 0x8d, 0xd0, 0x73, 0xc4, 0x1e,
+ 0x3d, 0x2c, 0xaf, 0x77, 0xb2, 0xef, 0xe5, 0x95, 0x8b, 0xdf,
+ 0x02, 0xfc, 0x93, 0xb8, 0xa9, 0x27, 0x88, 0x1d, 0x1d, 0x82,
+ 0x9f, 0xb6, 0xe4, 0x12, 0x05, 0x79, 0xb6, 0x1c, 0x41, 0x0d,
+ 0xc1, 0x53, 0x49, 0x8f, 0x3d, 0xc9, 0xad, 0x84, 0xcb, 0x0b,
+ 0x88, 0x7e, 0xfe, 0x73, 0x59, 0x21, 0x64, 0xc5, 0x50, 0x53,
+ 0xdc, 0x98, 0xc6, 0x43, 0xb8, 0xf5, 0xc3, 0xa1, 0xf5, 0xb2,
+ 0xd8, 0x86, 0xe9, 0xae, 0x98, 0xf9, 0x3b, 0x99, 0xc0, 0xe7,
+ 0xd7, 0x4a, 0xed, 0xac, 0x89, 0x84, 0xb0, 0x8e, 0xd3, 0xab,
+ 0xec, 0x03, 0x02, 0x12, 0x4b, 0x44, 0x17, 0x4d, 0x98, 0x26,
+ 0x1e, 0x51, 0xc5, 0xbb, 0xcd, 0xdc, 0x50, 0xab, 0x83, 0x37,
+ 0x49, 0x90, 0x1e, 0x34, 0xad, 0x81, 0x22, 0x6c, 0xe4, 0xdd,
+ 0x19, 0x01, 0x09, 0x25, 0x2d, 0x9e, 0x52, 0x90, 0x72, 0xa1,
+ 0x68, 0x3d, 0x0c, 0x49, 0x99, 0x19, 0x75, 0x5a, 0xca, 0x08,
+ 0x69, 0xa1, 0xd2, 0x88, 0x8c, 0xea, 0xcf, 0x9c, 0xbc, 0x23,
+ 0xad, 0x3f, 0xb9, 0xfc, 0xb9, 0x30, 0x0d, 0xd6, 0xd9, 0x65,
+ 0x0c, 0x7e, 0x99, 0x68, 0x35, 0x26, 0x07, 0xd1, 0x55, 0xbf,
+ 0x8e, 0xde, 0xe7, 0xe7, 0x01, 0xcb, 0xca, 0x0a, 0x39, 0x2e,
+ 0xcc, 0x19, 0xec, 0x77, 0xf3, 0xab, 0xb2, 0xe6, 0x0e, 0x54,
+ 0x06, 0x01, 0x50, 0x77, 0xd3, 0x61, 0x36, 0x05, 0x90, 0xe4,
+ 0xd8, 0xc4, 0x1d, 0xf5, 0xc7, 0xfa, 0x65, 0xf0, 0x46, 0x6a,
+ 0x5f, 0xa7, 0xc3, 0x8c, 0x6f, 0x04, 0x7f, 0xcf, 0x97, 0xb9,
+ 0x68, 0x92, 0x31, 0x09, 0x02, 0x9f, 0x22, 0xc9, 0xf8, 0xe6,
+ 0x7e, 0xa8, 0x95, 0x5b, 0x6b, 0xfe, 0x9c, 0x4e, 0x63, 0x2d,
+ 0x8c, 0x1a, 0x4c, 0x8b, 0x14, 0x79, 0x08, 0xd5, 0x96, 0x76,
+ 0xd1, 0xb4, 0x2f, 0xae, 0x5d, 0x91, 0x88, 0x7c, 0xdd, 0xd2,
+ 0x06, 0x86, 0xcf, 0x0a, 0x83, 0x6f, 0xda, 0xca, 0x71, 0x7c,
+ 0xe7, 0xe5, 0x34, 0xa8, 0x9a, 0x53, 0x8d, 0xa5, 0xaa, 0x5d,
+ 0xb5, 0x17, 0x81, 0x34, 0x6f, 0xbe, 0xbb, 0xb6, 0x58, 0x22,
+ 0x90, 0x80, 0xf6, 0x9c, 0x1c, 0xb0, 0x79, 0x8f, 0x92, 0x5b,
+ 0x7d, 0x1c, 0x71, 0x5f, 0xb4, 0x87, 0x36, 0xbe, 0x81, 0x8d,
+ 0x4a, 0xfc, 0x28, 0x72, 0x81, 0xaf, 0x5f, 0xbd, 0x5f, 0x99,
+ 0xe3, 0xc9, 0x37, 0xb0, 0x6e, 0xad, 0x70, 0x96, 0xfa, 0xe3,
+ 0x99, 0xf7, 0x08, 0x14, 0x21, 0x21, 0xb7, 0x1a, 0xaa, 0xe8,
+ 0x07, 0xb6, 0xfd, 0xa3, 0x7a, 0x2d, 0x93, 0x64, 0x8f, 0x89,
+ 0x2c, 0x71, 0x49, 0x71, 0xb8, 0x45, 0xca, 0xe0, 0x7c, 0x00,
+ 0x8d, 0xbd, 0xb8, 0x1c, 0x3a, 0x94, 0xa2, 0xa7, 0x6d, 0x0a,
+ 0x2e, 0x84, 0xaf, 0xbd, 0xab, 0x05, 0x95, 0x64, 0x8b, 0x05,
+ 0xc8, 0xc9, 0x4e, 0xea, 0xb5, 0x96, 0x4a, 0x47, 0xdd, 0xf2,
+ 0xcb, 0x02, 0x82, 0x03, 0xc0, 0x59, 0xb3, 0xd9, 0x85, 0xdc,
+ 0xa8, 0xb9, 0x93, 0x85, 0xa2, 0xbc, 0x79, 0xfc, 0x72, 0x50,
+ 0xc1, 0xa0, 0xa5, 0xdb, 0x71, 0x35, 0xa1, 0x31, 0xbc, 0x68,
+ 0x4e, 0xd5, 0x19, 0x9e, 0x0e, 0x32, 0x3a, 0xad, 0x40, 0x9e,
+ 0x82, 0x3c, 0x1e, 0x2b, 0x34, 0x3b, 0xc9, 0x32, 0x61, 0x07,
+ 0x5e, 0x46, 0xa9, 0xbe, 0xbe, 0x73, 0x0c, 0x12, 0xef, 0x52,
+ 0x68, 0x82, 0xe2, 0x0b, 0x12, 0x74, 0xfc, 0x10, 0x5c, 0xc0,
+ 0xb5, 0x98, 0x4d, 0x86, 0xbb, 0x8c, 0x40, 0x15, 0xa1, 0x6e,
+ 0x46, 0x73, 0x2e, 0xd6, 0x99, 0x6b, 0x50, 0xab, 0x04, 0x1a,
+ 0x5f, 0xf4, 0xfa, 0xcb, 0x4b, 0xad, 0xc4, 0x5e, 0x62, 0xa7,
+ 0x48, 0xd4, 0x52, 0x85, 0xdc, 0x2a, 0x85, 0x9b, 0xee, 0x08,
+ 0xa5, 0xaa, 0xaa, 0xe8, 0x44, 0xf0, 0xed, 0x89, 0x21, 0xe4,
+ 0xb4, 0xab, 0x3c, 0x0d, 0x53, 0x7e, 0x53, 0xdd, 0xac, 0x47,
+ 0xda, 0x77, 0x79, 0x5f, 0x78, 0x7a, 0x80, 0x84, 0x46, 0x50,
+ 0xaa, 0xdb, 0x3b, 0x8c, 0x6b, 0xda, 0xb0, 0xac, 0x0a, 0xd3,
+ 0x4c, 0xe4, 0x6e, 0x87, 0xd1, 0xb2, 0x5a, 0xd5, 0x98, 0xae,
+ 0xcb, 0x7e, 0xc2, 0x19, 0xdc, 0x53, 0x64, 0x86, 0x4c, 0x7b,
+ 0xe0, 0x63, 0x22, 0x94, 0x34, 0xad, 0x15, 0xdc, 0xd8, 0xa8,
+ 0x5f, 0xc6, 0x58, 0xf6, 0x72, 0x34, 0xdd, 0xfb, 0x85, 0x8a,
+ 0xd9, 0xa3, 0xfb, 0x3b, 0xad, 0x5d, 0xf0, 0x1a, 0x0b, 0xa8,
+ 0x91, 0xe7, 0x7d, 0x26, 0x27, 0x38, 0xf8, 0xe0, 0x49, 0x1b,
+ 0x56, 0xc5, 0x5b, 0xe3, 0x1c, 0x7b, 0xa3, 0x53, 0x6d, 0x22,
+ 0xfa, 0xd7, 0x63, 0x5f, 0xf0, 0xcb, 0x92, 0x49, 0x01, 0x54,
+ 0xe5, 0x77, 0x5b, 0xd3, 0xab, 0xce, 0xb8, 0x3a, 0x5b, 0xb8,
+ 0x07, 0x40, 0x46, 0x51, 0xe4, 0x59, 0xa2, 0x45, 0x41, 0xcc,
+ 0x81, 0x6c, 0xe3, 0xa6, 0xb3, 0xa0, 0x30, 0x4a, 0x67, 0x10,
+ 0xed, 0xc0, 0x8a, 0xcd, 0xfc, 0xa5, 0x44, 0x9b, 0x59, 0x19,
+ 0x4a, 0x43, 0x8d, 0xec, 0x00, 0xd8, 0x6d, 0xf9, 0xf0, 0x2d,
+ 0xd9, 0x55, 0xfc, 0x05, 0xe2, 0x12, 0x48, 0x4d, 0xd6, 0x7d,
+ 0xec, 0x41, 0xc4, 0x9e, 0xe2, 0xed, 0x84, 0x14, 0x29, 0x0e,
+ 0x5b, 0x81, 0x0b, 0xb0, 0x87, 0x8a, 0xd3, 0x35, 0x5c, 0xad,
+ 0xdb, 0xcc, 0xa1, 0x3c, 0xcb, 0x8b, 0x23, 0x55, 0x69, 0xf1,
+ 0x83, 0x84, 0x81, 0x36, 0xae, 0xd5, 0xf3, 0x98, 0xb6, 0xb2,
+ 0xb5, 0xa1, 0x79, 0x6d, 0x80, 0x8f, 0x2e, 0x25, 0x71, 0x4e,
+ 0x16, 0xff, 0xa0, 0x7c, 0xa4, 0x62, 0x8c, 0x44, 0x85, 0x64,
+ 0x90, 0x7c, 0xac, 0x10, 0x36, 0xf2, 0xf2, 0xfb, 0x20, 0x2b,
+ 0xa1, 0x27, 0xd0, 0xcc, 0x27, 0xfd, 0xb0, 0xba, 0x3e, 0x37,
+ 0xb1, 0xa8, 0x9d, 0x3c, 0x82, 0x63, 0xd0, 0x16, 0x6d, 0x7a,
+ 0xdd, 0x2e, 0xea, 0xe5, 0x87, 0xd6, 0x64, 0x72, 0xdb, 0x60,
+ 0x53, 0x38, 0x18, 0x66, 0x1d, 0x25, 0xf6, 0x08, 0x92, 0x7f,
+ 0x68, 0x5b, 0x79, 0x07, 0xde, 0x93, 0xee, 0xf8, 0x8f, 0xce,
+ 0x28, 0xcf, 0xb1, 0x5b, 0x43, 0x51, 0xdf, 0xf5, 0xac, 0xe8,
+ 0x9c, 0x95, 0x14, 0x8a, 0x67, 0xe1, 0x25, 0xfe, 0x11, 0xa2,
+ 0x40, 0xf8, 0xdd, 0xcf, 0xf5, 0x17, 0x94, 0xb6, 0x88, 0x10,
+ 0xa2, 0x90, 0x58, 0xef, 0xaf, 0x73, 0xf8, 0x7c, 0x9b, 0x20,
+ 0x30, 0x79, 0xca, 0x3f, 0xa9, 0x22, 0x40, 0xfd, 0xcc, 0xb0,
+ 0x5d, 0x0d, 0x97, 0x6b, 0xc0, 0x75, 0x35, 0x33, 0xc5, 0x76,
+ 0x45, 0x6e, 0x9b, 0x78, 0xe7, 0xb4, 0x04, 0xb3, 0xba, 0x3b,
+ 0x93, 0xb1, 0xa9, 0x8f, 0xa1, 0x24, 0x5d, 0x1c, 0x0e, 0x66,
+ 0xc0, 0xc6, 0xcc, 0xd6, 0xb7, 0x88, 0x9d, 0xb8, 0x45, 0xe3,
+ 0xaa, 0xc9, 0x6c, 0xfd, 0x37, 0xdc, 0x85, 0xd5, 0x49, 0xfd,
+ 0xef, 0xeb, 0xf9, 0x7a, 0x3f, 0x7a, 0x4f, 0x86, 0x49, 0xaa,
+ 0x9f, 0x08, 0x12, 0x0b, 0x11, 0x35, 0x5c, 0xd5, 0xd3, 0xda,
+ 0x14, 0x50, 0x03, 0x2c, 0x24, 0x26, 0x0e, 0x29, 0x18, 0xcc,
+ 0x1d, 0x0a, 0x7c, 0x94, 0x8b, 0xc0, 0xa0, 0x3f, 0xea, 0xf8,
+ 0xf8, 0xa9, 0x1d, 0x65, 0x31, 0x6f, 0x3b, 0xa6, 0xd0, 0xfc,
+ 0x26, 0xb0, 0x4e, 0x3a, 0x66, 0xe7, 0x32, 0x10, 0x2e, 0x84,
+ 0x47, 0xad, 0xa9, 0x18, 0xfc, 0xa3, 0x8b, 0x74, 0x84, 0x4f,
+ 0xd4, 0x25, 0x93, 0x0f, 0xdb, 0x2e, 0xae, 0x88, 0x8e, 0x28,
+ 0xf8, 0x0f, 0xaa, 0x60, 0xd4, 0xbe, 0xad, 0x66, 0x0c, 0x0d,
+ 0x01, 0xbd, 0x8d, 0xc4, 0xfc, 0x48, 0xef, 0x78, 0x14, 0x34,
+ 0xee, 0xb3, 0xbc, 0xd4, 0xbb, 0x1f, 0x7c, 0x12, 0x5c, 0x9b,
+ 0xeb, 0x77, 0x3e, 0x2c, 0x6e, 0x31, 0x59, 0xe6, 0x78, 0xc5,
+ 0xe8, 0xa4, 0xdd, 0xf1, 0xef, 0x5d, 0x27, 0x45, 0x31, 0x13,
+ 0xd0, 0x21, 0xa1, 0x13, 0xce, 0xac, 0x7e, 0xbb, 0xfb, 0x32,
+ 0xeb, 0x76, 0x31, 0xc4, 0xba, 0xdf, 0xfb, 0x5a, 0x1b, 0xc9,
+ 0x9e, 0x74, 0xa0, 0x9e, 0x26, 0x82, 0xd5, 0x6e, 0x1d, 0xc3,
+ 0x0e, 0xd1, 0x6d, 0xdb, 0x43, 0xb3, 0x0b, 0x14, 0xcb, 0xf1,
+ 0xad, 0x62, 0x34, 0x49, 0xb8, 0xd3, 0x08, 0xca, 0x93, 0xf1,
+ 0x42, 0xb2, 0x4b, 0x23, 0x79, 0x93, 0xde, 0x18, 0x58, 0xf3,
+ 0x66, 0xfa, 0xdc, 0xab, 0xca, 0x33, 0x22, 0x2b, 0x5c, 0x8c,
+ 0x12, 0xc1, 0x7b, 0x2e, 0x52, 0x72, 0xa7, 0x78, 0x4a, 0x49,
+ 0xa1, 0x53, 0x02, 0x76, 0x2d, 0x2e, 0xf8, 0x43, 0x3c, 0xe8,
+ 0xfa, 0xb7, 0xff, 0x39, 0xed, 0x74, 0x9e, 0x11, 0x61, 0x33,
+ 0xde, 0x2a, 0x55, 0xe6, 0x4a, 0xe7, 0x97, 0xa6, 0xb2, 0xc3,
+ 0x40, 0x41, 0x52, 0x66, 0xcf, 0xbf, 0xf8, 0x8e, 0x08, 0xea,
+ 0x96, 0x4d, 0x03, 0xc9, 0xbe, 0x3c, 0x4e, 0x36, 0x8c, 0x6f,
+ 0x4d, 0x1e, 0xcd, 0x31, 0x6d, 0x53, 0xea, 0x9e, 0xf0, 0x8e,
+ 0x35, 0x97, 0x37, 0x54, 0xe9, 0x0f, 0xb8, 0x23, 0x25, 0x69,
+ 0x5b, 0xb5, 0xff, 0xc3, 0x5a, 0x2d, 0x10, 0x6a, 0xc0, 0xb8,
+ 0xee, 0x0d, 0x31, 0x5b, 0xe4, 0x69, 0x40, 0x62, 0xa7, 0x1b,
+ 0x16, 0xfa, 0xd6, 0xb8, 0xba, 0xc8, 0x6a, 0xa3, 0x29, 0xdd,
+ 0x9b, 0x4d, 0xd7, 0x96, 0xef, 0x31, 0x74, 0xac, 0x37, 0x10,
+ 0x91, 0x30, 0x0c, 0x15, 0x3f, 0x09, 0xb6, 0x7d, 0x22, 0xfb,
+ 0x8c, 0x6f, 0xc3, 0x93, 0xa3, 0x98, 0xa6, 0x23, 0xa4, 0x55,
+ 0xe0, 0x9e, 0x23, 0x06, 0xa9, 0x78, 0xe9, 0xb3, 0x88, 0xc9,
+ 0xb7, 0x83, 0x05, 0x46, 0x11, 0x3a, 0x0a, 0xb9, 0x74, 0x5b,
+ 0xa0, 0xb5, 0x06, 0x96, 0x86, 0xb6, 0xf4, 0x9d, 0x0d, 0x86,
+ 0x43, 0xa8, 0x40, 0x4b, 0x08, 0x93, 0x7c, 0xad, 0xb0, 0x50,
+ 0xb4, 0xd0, 0xe7, 0xad, 0xd0, 0x54, 0x5e, 0x15, 0xaf, 0xad,
+ 0x34, 0x12, 0x86, 0xb3, 0x29, 0x3b, 0x20, 0xc9, 0xad, 0xeb,
+ 0xc2, 0x65, 0xf3, 0x5c, 0x2d, 0xe5, 0xff, 0xfd, 0x81, 0x79,
+ 0xf5, 0x11, 0x6f, 0xf7, 0xca, 0x0c, 0x76, 0xf0, 0xd4, 0x02,
+ 0x9d, 0xb7, 0x76, 0x39, 0x6d, 0x32, 0x6a, 0xb8, 0x30, 0xa4,
+ 0x01, 0xcc, 0x10, 0xef, 0xb1, 0x0e, 0x41, 0x22, 0x82, 0x5b,
+ 0x22, 0xcb, 0x32, 0x19, 0x2e, 0xa3, 0x0a, 0xce, 0x05, 0xdd,
+ 0xe8, 0x4a, 0x58, 0x92, 0xe1, 0x02, 0x82, 0x03, 0xc0, 0x22,
+ 0x0f, 0x95, 0x5b, 0xc2, 0x1f, 0xde, 0xf0, 0xde, 0xf4, 0x86,
+ 0xbd, 0xef, 0x07, 0x7d, 0x52, 0x03, 0x8c, 0x26, 0x31, 0x17,
+ 0xfd, 0x5c, 0x97, 0xed, 0xd5, 0xe0, 0xb3, 0x18, 0x2d, 0x68,
+ 0x10, 0x3f, 0xc4, 0xdf, 0xd1, 0x05, 0x78, 0x81, 0x3d, 0x05,
+ 0xde, 0xba, 0x3a, 0x67, 0x85, 0x0e, 0xdf, 0xb5, 0x16, 0x28,
+ 0xe8, 0x84, 0x3a, 0x71, 0x2a, 0x20, 0x17, 0x28, 0x05, 0xfd,
+ 0xb7, 0x4d, 0x22, 0x4a, 0x93, 0x46, 0x56, 0x27, 0x43, 0xc0,
+ 0x3a, 0x16, 0xff, 0x3d, 0x61, 0xcc, 0xcb, 0xce, 0xac, 0xa8,
+ 0x53, 0x3a, 0x0d, 0xf4, 0x2d, 0xd2, 0x73, 0xf2, 0x64, 0xa0,
+ 0x1e, 0x60, 0x53, 0xec, 0x0d, 0xff, 0xe0, 0x00, 0x10, 0xfb,
+ 0xa4, 0x57, 0xd3, 0xfc, 0xe4, 0xe0, 0xec, 0x44, 0x0b, 0x1c,
+ 0x05, 0x39, 0xa4, 0x13, 0x87, 0x29, 0x11, 0x9d, 0xea, 0xe9,
+ 0x64, 0xa9, 0x1c, 0x76, 0x3a, 0x65, 0x0b, 0xfd, 0xed, 0x77,
+ 0x46, 0x4f, 0xcd, 0x0b, 0x63, 0xc4, 0x83, 0x0b, 0x56, 0x79,
+ 0xd3, 0x67, 0x01, 0x11, 0x02, 0xd9, 0x50, 0xd8, 0x23, 0xf4,
+ 0xb6, 0x02, 0x4c, 0xae, 0xb5, 0xc9, 0x68, 0x1b, 0x87, 0x33,
+ 0xbb, 0xdc, 0x64, 0x0e, 0x32, 0x34, 0xb2, 0x25, 0xaa, 0x76,
+ 0xdd, 0x7e, 0xc3, 0x46, 0x51, 0x1c, 0xc1, 0xd0, 0x05, 0x09,
+ 0x6c, 0x27, 0xd3, 0xcf, 0x33, 0x7a, 0xb9, 0x26, 0x24, 0x23,
+ 0x4a, 0x93, 0x9f, 0x4b, 0x96, 0xc7, 0xe2, 0xb2, 0x51, 0x42,
+ 0x4d, 0x5d, 0xd9, 0x73, 0x75, 0xce, 0x23, 0x28, 0x56, 0x5e,
+ 0xe7, 0x96, 0x58, 0x04, 0xfd, 0x33, 0x93, 0x08, 0x41, 0x62,
+ 0x02, 0x7e, 0xc9, 0xc6, 0x55, 0x64, 0x19, 0xda, 0x39, 0xb8,
+ 0x5d, 0x09, 0x47, 0xf3, 0xdd, 0x77, 0xee, 0xea, 0x35, 0x73,
+ 0x95, 0xdb, 0x18, 0x4d, 0xd1, 0xfe, 0xee, 0x40, 0x31, 0x2a,
+ 0x22, 0x91, 0x69, 0xd6, 0xed, 0x9c, 0x54, 0x14, 0x73, 0x61,
+ 0x61, 0xe7, 0x1d, 0x34, 0x96, 0x47, 0xff, 0x28, 0x7a, 0x48,
+ 0xa3, 0xf4, 0xcd, 0x64, 0x23, 0xe2, 0x52, 0x2f, 0x20, 0x8f,
+ 0x04, 0xb3, 0xdc, 0xf0, 0x29, 0x67, 0x88, 0x76, 0x79, 0xdb,
+ 0x86, 0xa7, 0x95, 0xf0, 0x15, 0x81, 0xbb, 0x98, 0xee, 0xff,
+ 0x55, 0x7c, 0xb0, 0xee, 0x67, 0x65, 0xfd, 0xf2, 0x29, 0x0f,
+ 0x85, 0x51, 0xf9, 0xac, 0x5c, 0x55, 0x5a, 0xde, 0x40, 0x62,
+ 0x58, 0x55, 0x9f, 0x09, 0x4c, 0x2e, 0x28, 0x75, 0xbc, 0x48,
+ 0xe2, 0x97, 0x85, 0xb3, 0x83, 0xeb, 0x21, 0x49, 0x21, 0xd4,
+ 0xed, 0x74, 0x4f, 0xc1, 0x6c, 0x34, 0x8c, 0x11, 0xb0, 0x93,
+ 0x41, 0x99, 0x23, 0x2e, 0xa4, 0xc1, 0x9f, 0x34, 0x74, 0x64,
+ 0xbb, 0xd7, 0x4f, 0x8f, 0x9f, 0x3a, 0x0c, 0x4f, 0x5e, 0xdd,
+ 0x41, 0x07, 0xf1, 0xfd, 0x5a, 0x9d, 0xe6, 0x77, 0xd8, 0x7e,
+ 0x71, 0x7b, 0xad, 0xf7, 0x76, 0x13, 0x71, 0x90, 0xb3, 0x0f,
+ 0x46, 0x8e, 0xee, 0x7b, 0x33, 0x97, 0x5d, 0x21, 0x3b, 0xa0,
+ 0x58, 0x9e, 0xb7, 0x87, 0x30, 0x8f, 0xc1, 0x23, 0x2c, 0xde,
+ 0xf7, 0x0d, 0xa9, 0xd6, 0x50, 0xeb, 0x35, 0x7a, 0x82, 0xab,
+ 0x22, 0x49, 0x86, 0xd4, 0x61, 0xc7, 0xc2, 0x4e, 0x77, 0xfc,
+ 0x16, 0x0b, 0xaf, 0x81, 0x6a, 0x47, 0xea, 0xac, 0x7e, 0x51,
+ 0x4c, 0x56, 0x30, 0x21, 0x46, 0x41, 0xc3, 0x92, 0x60, 0x99,
+ 0x4f, 0x88, 0x36, 0x3b, 0x27, 0xb4, 0xb2, 0x7e, 0x44, 0x2f,
+ 0xdd, 0x95, 0xe4, 0x5e, 0x16, 0x1f, 0xa7, 0x32, 0x6b, 0x60,
+ 0x24, 0x0f, 0xf2, 0xe6, 0x35, 0x3c, 0x0c, 0x3e, 0xb5, 0xd6,
+ 0xdd, 0x63, 0xe2, 0x76, 0x35, 0x38, 0x79, 0xbf, 0xa5, 0x23,
+ 0xa4, 0xdd, 0xeb, 0x01, 0x48, 0xd0, 0x60, 0x86, 0x11, 0x38,
+ 0x5f, 0x9e, 0x6b, 0x00, 0x67, 0xd2, 0x5b, 0x41, 0x0a, 0x5e,
+ 0x13, 0x0f, 0xa1, 0x9e, 0x90, 0x85, 0xa6, 0x7f, 0xe5, 0x4b,
+ 0x9e, 0x93, 0x4e, 0x5b, 0x1f, 0x47, 0x62, 0xb0, 0x23, 0xbe,
+ 0x82, 0xa9, 0xd9, 0xb6, 0x2e, 0xfd, 0xb1, 0x10, 0xca, 0xe0,
+ 0xc9, 0x5d, 0xf6, 0x85, 0x18, 0x6c, 0x9c, 0x1d, 0x1f, 0x7c,
+ 0xf6, 0x55, 0x09, 0x80, 0xcf, 0xac, 0xfe, 0x37, 0x6a, 0x4f,
+ 0x96, 0xaa, 0x40, 0x79, 0x8b, 0x4a, 0xf2, 0x96, 0x79, 0x12,
+ 0x1a, 0x26, 0x87, 0x06, 0x35, 0x4d, 0xd4, 0x3e, 0x14, 0x39,
+ 0xe5, 0x6c, 0x39, 0x0f, 0x84, 0xb3, 0x5f, 0xed, 0xf4, 0xff,
+ 0x89, 0x52, 0x05, 0x00, 0xf1, 0xd1, 0xc3, 0xcf, 0x54, 0x10,
+ 0x24, 0x7c, 0xa6, 0xb5, 0x95, 0xa8, 0x6e, 0x13, 0x3e, 0x4a,
+ 0x40, 0x6c, 0xf9, 0x63, 0x90, 0x44, 0x52, 0x07, 0x53, 0xb7,
+ 0x51, 0xd9, 0x18, 0x47, 0x2e, 0xb0, 0x4e, 0x0f, 0x09, 0x99,
+ 0x3a, 0x97, 0x26, 0x53, 0xa6, 0x02, 0x06, 0x0e, 0x93, 0xe1,
+ 0x0b, 0xc5, 0xa9, 0x14, 0xd3, 0xd6, 0x8a, 0x29, 0x75, 0xcd,
+ 0xb6, 0x7b, 0x64, 0x7c, 0xdd, 0x7e, 0xb4, 0x0a, 0x87, 0x48,
+ 0x4a, 0x1b, 0x0e, 0x74, 0x4c, 0xd3, 0x0e, 0x96, 0x0e, 0x53,
+ 0xc4, 0x3d, 0x7b, 0x1c, 0x87, 0x6a, 0x15, 0xd8, 0x77, 0xba,
+ 0xe6, 0xa0, 0x2f, 0x2c, 0x1a, 0x9d, 0xde, 0x79, 0xfd, 0xab,
+ 0x44, 0x80, 0xf0, 0x37, 0x9a, 0x3b, 0xf8, 0xde, 0x3d, 0x29,
+ 0xcb, 0x89, 0x64, 0x4b, 0x57, 0xe7, 0x6b, 0x84, 0x09, 0x27,
+ 0x17, 0x2f, 0xb2, 0xba, 0x3d, 0x09, 0xc9, 0x3c, 0x89, 0xe6,
+ 0x19, 0x73, 0x83, 0xf7, 0xc6, 0x19, 0x18, 0x96, 0xb2, 0x7d,
+ 0x1e, 0x9f, 0x70, 0x1f, 0xfc, 0x1f, 0xe2, 0xb5, 0x69, 0x1e,
+ 0xf4, 0x65, 0x91, 0xce, 0x4b, 0xdc, 0x74, 0x49, 0x21, 0x64,
+ 0x8b, 0x33, 0x50, 0xd2, 0xc1, 0x33, 0x62, 0x5b, 0xde, 0x0a,
+ 0x72, 0xbe, 0xc0, 0x05, 0x51, 0x15, 0x80, 0xed, 0x32, 0x3a,
+ 0x64, 0xa2, 0x73, 0x68, 0x5b, 0x16, 0xcf, 0x70, 0x5c, 0x98,
+ 0xe5, 0x67, 0x45, 0x60, 0x57, 0x2b, 0x47, 0x0a, 0x22, 0x73,
+ 0xc3, 0x56, 0x33, 0x3e, 0x14, 0x1d, 0x0c, 0xd1, 0x03, 0x08,
+ 0x92, 0x21, 0x2b, 0xa9, 0x6e, 0x6b, 0xf9, 0x0c, 0x1e, 0x86,
+ 0xdd, 0xb5, 0xbb, 0xa4, 0xa5, 0x82, 0x99, 0x98, 0x49, 0x36,
+ 0xec, 0x98, 0x98, 0x95, 0xac, 0xc2, 0xa0, 0x1f, 0xa5, 0x7e,
+ 0x67, 0xd1, 0xcf, 0x6a, 0xf4, 0x16, 0x08, 0x7a, 0x8d, 0x0b,
+ 0xae, 0x12, 0x51, 0xe6, 0x8e, 0xe6, 0xcd, 0xa1, 0xaa, 0x6d,
+ 0xe4, 0x54, 0xd4, 0x69, 0x1b, 0x09, 0x6a, 0xba, 0x5e, 0x0b,
+ 0x11, 0x9c, 0x83, 0xb3, 0x5c, 0x67, 0xbb, 0x2d, 0xf8, 0x66,
+ 0x1c, 0x33, 0xb8, 0x22, 0x58, 0x10, 0x96, 0xe9, 0x99, 0xaf,
+ 0x0b, 0x2a, 0xf1, 0xe0, 0xcb, 0x56, 0xfb, 0x6d, 0x04, 0x40,
+ 0xec, 0x37, 0x67, 0x1e, 0x08, 0x7a, 0x1c, 0xe9, 0xd8, 0x54,
+ 0xf7, 0xd4, 0xc7, 0x3c, 0x45, 0x23, 0x2b, 0x76, 0xd2, 0x62,
+ 0xc2, 0x53, 0xce, 0xfe, 0x02, 0xc4, 0xd9, 0xf6, 0x3c, 0xed,
+ 0x49, 0x47, 0x21, 0xf9, 0x03, 0x3a, 0xa0, 0x16, 0x3a, 0xfe,
+ 0x0c, 0x2f, 0x54, 0x7e, 0x85, 0x29, 0x7b, 0xc0, 0xaf, 0xa8,
+ 0x5d, 0x31, 0x25, 0xda, 0xa7, 0xe3, 0x92, 0x1b, 0x64, 0x01,
+ 0x1b, 0x3f, 0x6e, 0x47, 0xc5, 0x5a, 0x84, 0x52, 0x17, 0x02,
+ 0x82, 0x03, 0xc1, 0x00, 0x81, 0x99, 0x2e, 0x72, 0x41, 0x6e,
+ 0x86, 0xeb, 0x6f, 0x42, 0xd1, 0x38, 0x6e, 0xaa, 0x1a, 0xd5,
+ 0x0a, 0xad, 0x51, 0xb1, 0xce, 0xd6, 0x35, 0xbe, 0x34, 0xd8,
+ 0xc1, 0xe4, 0x5f, 0xdf, 0x2e, 0xe4, 0x90, 0xf2, 0x61, 0x21,
+ 0x46, 0xc6, 0xfe, 0xab, 0x0f, 0x6c, 0x97, 0x78, 0xcd, 0x55,
+ 0x86, 0x83, 0x61, 0x99, 0x49, 0x14, 0x86, 0xc6, 0x86, 0xf1,
+ 0x41, 0x66, 0xc9, 0x39, 0x52, 0x99, 0x49, 0x07, 0xd6, 0x9d,
+ 0xb7, 0x40, 0x34, 0x5f, 0xe7, 0x3a, 0xfa, 0x95, 0xeb, 0xa1,
+ 0x03, 0xb7, 0x52, 0x71, 0x93, 0x30, 0x0b, 0x51, 0x58, 0x82,
+ 0x07, 0x2f, 0x44, 0xa9, 0x4f, 0x9b, 0x1b, 0xf3, 0xd6, 0x21,
+ 0x3d, 0x68, 0xef, 0x3f, 0xaf, 0xc2, 0x6f, 0xa0, 0xd5, 0x2b,
+ 0xb8, 0x73, 0x84, 0x67, 0x36, 0x8b, 0xa4, 0x25, 0xe0, 0x86,
+ 0xd9, 0x14, 0x5c, 0x6c, 0xd8, 0x61, 0xe1, 0x0a, 0x6c, 0xaf,
+ 0xbb, 0x9c, 0xf6, 0x74, 0xca, 0x5a, 0x04, 0xac, 0x85, 0xc1,
+ 0x1b, 0x4d, 0xf2, 0x07, 0xb6, 0x1e, 0x97, 0x7b, 0x75, 0xdf,
+ 0x9b, 0x8a, 0x31, 0xc6, 0x90, 0xd5, 0x8d, 0x39, 0xc2, 0x54,
+ 0xf4, 0xe2, 0x83, 0x57, 0x12, 0x19, 0xf5, 0xb2, 0xd2, 0x53,
+ 0x81, 0x6d, 0xf0, 0x09, 0xc9, 0x80, 0x8b, 0x07, 0x7c, 0x59,
+ 0xcd, 0x78, 0x00, 0xd6, 0x44, 0x7f, 0xe4, 0xdb, 0x77, 0x02,
+ 0x00, 0x25, 0x79, 0x91, 0xc9, 0xde, 0xd0, 0xed, 0x3f, 0xfc,
+ 0x37, 0x36, 0xea, 0xf0, 0x56, 0x50, 0xe7, 0x38, 0xca, 0xe1,
+ 0x67, 0x12, 0x96, 0x55, 0x3e, 0xff, 0x97, 0xe5, 0xa7, 0x03,
+ 0x5b, 0x72, 0x80, 0xd6, 0xa5, 0x23, 0x39, 0x78, 0x07, 0xc8,
+ 0x83, 0x19, 0x74, 0xfb, 0x79, 0xc2, 0x9e, 0xbd, 0xf9, 0xaf,
+ 0x09, 0x0f, 0xbd, 0x3d, 0x34, 0xe8, 0x44, 0x89, 0xb1, 0xf1,
+ 0x2b, 0xa5, 0xff, 0x22, 0xc9, 0x47, 0xe2, 0x31, 0xb5, 0x6b,
+ 0x8a, 0x65, 0x5f, 0x81, 0x5f, 0x89, 0xb0, 0x03, 0x5d, 0x53,
+ 0x0e, 0xdd, 0xfb, 0xe5, 0x70, 0xaa, 0xd2, 0x37, 0x4d, 0xa1,
+ 0x7c, 0xf2, 0xe4, 0x7f, 0xf1, 0x4a, 0xaf, 0x12, 0xd1, 0x83,
+ 0xdc, 0xb2, 0x9e, 0xc1, 0x95, 0x3d, 0x04, 0x9f, 0xa3, 0xad,
+ 0xcc, 0x78, 0x14, 0x9a, 0xf9, 0x58, 0x39, 0x08, 0x15, 0xda,
+ 0x1b, 0x94, 0x50, 0x2d, 0x44, 0xc0, 0x23, 0x1c, 0x36, 0x5f,
+ 0x16, 0x08, 0xa3, 0xdf, 0x9e, 0x4f, 0xbb, 0x07, 0xcd, 0xe3,
+ 0x8c, 0xbf, 0xf1, 0xc3, 0x3e, 0x98, 0xf8, 0x49, 0x79, 0x58,
+ 0xc9, 0x0f, 0x47, 0xc0, 0xab, 0x2f, 0x21, 0x63, 0xf6, 0xe6,
+ 0xfe, 0x8a, 0xea, 0xbc, 0x32, 0x63, 0xca, 0x75, 0xf8, 0xa4,
+ 0x1b, 0x6c, 0xfe, 0x9a, 0x6e, 0x68, 0x1f, 0x48, 0x59, 0xfb,
+ 0x34, 0x43, 0x10, 0xd5, 0x0d, 0x80, 0x54, 0xcb, 0x67, 0x21,
+ 0xc7, 0x13, 0x85, 0x38, 0x0c, 0xf9, 0x40, 0x2e, 0x2e, 0x4a,
+ 0x05, 0x9e, 0x51, 0xae, 0xdd, 0xba, 0x23, 0x83, 0x66, 0x2a,
+ 0xbf, 0x7f, 0xca, 0x9c, 0x6c, 0x2d, 0x6b, 0x7d, 0x68, 0x52,
+ 0x81, 0x56, 0x2f, 0xea, 0xf9, 0xe7, 0xf1, 0x55, 0x16, 0xfc,
+ 0x29, 0xe2, 0xa5, 0x1e, 0x0a, 0x06, 0xe0, 0x85, 0x4e, 0xa6,
+ 0x5d, 0x20, 0x9d, 0x2b, 0xa2, 0xad, 0xaa, 0xd6, 0x9b, 0xd2,
+ 0x98, 0x29, 0x45, 0x5c, 0x55, 0xc0, 0x91, 0xa2, 0x65, 0xcd,
+ 0xac, 0xc6, 0x1a, 0x53, 0xa1, 0x46, 0x13, 0xf9, 0xfe, 0x1a,
+ 0xf6, 0xdf, 0xa5, 0x1a, 0x58, 0x7c, 0x81, 0x2e, 0x46, 0x46,
+ 0xf7, 0x2f, 0xd6, 0xaa, 0x21, 0xb0, 0x0e, 0x7e, 0xac, 0xb8,
+ 0xc6, 0x76, 0x62, 0x82, 0x3b, 0x0a, 0x36, 0xbe, 0x97, 0x16,
+ 0xd5, 0x79, 0x55, 0x15, 0x64, 0x2a, 0xbe, 0x19, 0x4e, 0x93,
+ 0x3b, 0x44, 0x7c, 0xe2, 0xfc, 0x18, 0x4e, 0x83, 0x37, 0xfb,
+ 0x26, 0x78, 0x6d, 0x24, 0x6b, 0x48, 0x21, 0x67, 0xde, 0xf5,
+ 0x00, 0x22, 0x9a, 0xec, 0x40, 0x16, 0x96, 0x8a, 0x3f, 0xd5,
+ 0xa6, 0x5e, 0x03, 0x84, 0xbb, 0x15, 0x4d, 0x55, 0x71, 0x00,
+ 0x90, 0xc2, 0x96, 0x25, 0x01, 0xab, 0xe6, 0x47, 0x44, 0x6f,
+ 0xf9, 0x53, 0x80, 0x2b, 0xa8, 0x83, 0xc8, 0x14, 0x77, 0x13,
+ 0x00, 0x66, 0xee, 0x7e, 0x7a, 0xa0, 0x28, 0x65, 0xf3, 0x31,
+ 0xb6, 0xac, 0xd7, 0x87, 0x84, 0x29, 0xed, 0x5b, 0xcd, 0x74,
+ 0xc0, 0x89, 0x51, 0x11, 0x9a, 0xd5, 0x7b, 0xe0, 0x9c, 0xd0,
+ 0x8d, 0x72, 0xe3, 0x77, 0xda, 0x0a, 0xc2, 0xdc, 0x6f, 0xad,
+ 0x49, 0x03, 0xfa, 0xe6, 0x7e, 0xa6, 0x24, 0x32, 0xe6, 0x8f,
+ 0xd9, 0x70, 0xfa, 0x59, 0x70, 0xa9, 0xa3, 0x08, 0x7d, 0x89,
+ 0xc4, 0x96, 0x61, 0xc2, 0xf5, 0xe5, 0xb5, 0x3b, 0x0d, 0xec,
+ 0xb8, 0x9c, 0xee, 0x09, 0x77, 0x27, 0xbd, 0x35, 0x66, 0x90,
+ 0x9e, 0x46, 0xf7, 0xbd, 0xa6, 0xc5, 0x31, 0xd4, 0x6a, 0x52,
+ 0x17, 0x5d, 0x0a, 0x0e, 0x2c, 0x34, 0x7a, 0x6a, 0x21, 0xac,
+ 0x42, 0xf0, 0x31, 0xde, 0x48, 0xe0, 0x27, 0xd0, 0x79, 0xc9,
+ 0x06, 0x94, 0x7b, 0x51, 0x4b, 0x5b, 0x02, 0x6a, 0x19, 0xba,
+ 0x71, 0x45, 0x9c, 0xdf, 0xe6, 0x30, 0x9e, 0xaa, 0xad, 0xa1,
+ 0x87, 0xf6, 0x37, 0xde, 0xa2, 0x97, 0x68, 0x20, 0x2d, 0x5a,
+ 0xdc, 0xdd, 0x91, 0x63, 0x5f, 0x79, 0xda, 0x99, 0x20, 0x3a,
+ 0x4b, 0xe5, 0x43, 0x0e, 0x12, 0x70, 0x57, 0x91, 0xfa, 0xee,
+ 0xc4, 0xb6, 0xb6, 0xb1, 0xf1, 0x06, 0xbd, 0xcf, 0x8d, 0x2a,
+ 0x05, 0xc0, 0x07, 0x23, 0x84, 0x85, 0xef, 0x9c, 0xbb, 0x6f,
+ 0x5f, 0x4a, 0x9a, 0x27, 0x9f, 0x9f, 0x32, 0x97, 0xe8, 0x24,
+ 0xb9, 0x64, 0x2c, 0x39, 0xff, 0x2f, 0x4b, 0xc4, 0x7e, 0x65,
+ 0xfe, 0xbb, 0x5c, 0xa0, 0xb2, 0x6e, 0xc4, 0xb6, 0x93, 0x2b,
+ 0x51, 0x9e, 0x2e, 0x1f, 0xd8, 0xcf, 0x60, 0xe0, 0x75, 0x15,
+ 0xf9, 0xa0, 0x67, 0x99, 0x88, 0x2b, 0x76, 0xce, 0x41, 0x42,
+ 0x10, 0x29, 0x89, 0xbf, 0xca, 0xb7, 0x61, 0x08, 0x94, 0xee,
+ 0xa0, 0xb3, 0x3a, 0x09, 0xc5, 0x6f, 0x04, 0xf9, 0x1b, 0xb5,
+ 0x64, 0x99, 0x08, 0xe4, 0xcc, 0xce, 0xdf, 0x71, 0x65, 0x8a,
+ 0x6d, 0x62, 0xde, 0x76, 0x1d, 0x6d, 0x6b, 0x78, 0x22, 0x32,
+ 0x63, 0xdd, 0x53, 0x7d, 0xec, 0xed, 0x9d, 0x82, 0xa9, 0x2c,
+ 0x5c, 0x8a, 0x17, 0xdd, 0x85, 0xf9, 0xd2, 0xac, 0x6e, 0x98,
+ 0x60, 0x2e, 0x08, 0xd4, 0x06, 0x76, 0xf4, 0x97, 0xca, 0xb1,
+ 0x72, 0x50, 0x5b, 0x83, 0xea, 0xbb, 0x39, 0x0f, 0x18, 0xb3,
+ 0xb8, 0x03, 0xee, 0x7c, 0x84, 0xa9, 0x69, 0xcd, 0x1d, 0xbd,
+ 0xe2, 0xb7, 0xce, 0xe2, 0x6f, 0x03, 0x49, 0x52, 0x67, 0xa0,
+ 0x1b, 0x23, 0x43, 0x92, 0x2c, 0x7c, 0x3b, 0x65, 0xe8, 0x61,
+ 0x99, 0xde, 0xb5, 0xf1, 0x63, 0x73, 0x92, 0x6c, 0x70, 0x8b,
+ 0x83, 0x10, 0xb4, 0x06, 0x2c, 0x99, 0x12, 0x73, 0xec, 0x87,
+ 0x92, 0x09, 0x67, 0x96, 0xd6, 0x9c, 0x9f, 0x35, 0x48, 0x48,
+ 0x3b, 0x44, 0x00, 0x73, 0x1c, 0x59, 0xeb, 0x81, 0x7b, 0xd1,
+ 0xda, 0x76, 0xcf, 0xc2, 0x4d, 0xf1, 0xa2, 0x5b, 0x2f, 0x5f,
+ 0x91, 0x29, 0x6e, 0x08, 0x37, 0xd6, 0xaa, 0xd2, 0xf8, 0x4f,
+ 0x5e, 0x00, 0x16, 0x52
+};
diff --git a/freebsd/crypto/openssl/apps/timeouts.h b/freebsd/crypto/openssl/apps/timeouts.h
new file mode 100644
index 00000000..e023b0aa
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/timeouts.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef INCLUDED_TIMEOUTS_H
+# define INCLUDED_TIMEOUTS_H
+
+/* numbers in us */
+# define DGRAM_RCV_TIMEOUT 250000
+# define DGRAM_SND_TIMEOUT 250000
+
+#endif /* ! INCLUDED_TIMEOUTS_H */
diff --git a/freebsd/crypto/openssl/apps/ts.c b/freebsd/crypto/openssl/apps/ts.c
new file mode 100644
index 00000000..3fd64d73
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/ts.c
@@ -0,0 +1,988 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_TS
+NON_EMPTY_TRANSLATION_UNIT
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include "apps.h"
+# include "progs.h"
+# include <openssl/bio.h>
+# include <openssl/err.h>
+# include <openssl/pem.h>
+# include <openssl/rand.h>
+# include <openssl/ts.h>
+# include <openssl/bn.h>
+
+/* Request nonce length, in bits (must be a multiple of 8). */
+# define NONCE_LENGTH 64
+
+/* Name of config entry that defines the OID file. */
+# define ENV_OID_FILE "oid_file"
+
+/* Is |EXACTLY_ONE| of three pointers set? */
+# define EXACTLY_ONE(a, b, c) \
+ (( a && !b && !c) || \
+ ( b && !a && !c) || \
+ ( c && !a && !b))
+
+static ASN1_OBJECT *txt2obj(const char *oid);
+static CONF *load_config_file(const char *configfile);
+
+/* Query related functions. */
+static int query_command(const char *data, const char *digest,
+ const EVP_MD *md, const char *policy, int no_nonce,
+ int cert, const char *in, const char *out, int text);
+static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
+ const char *policy, int no_nonce, int cert);
+static int create_digest(BIO *input, const char *digest,
+ const EVP_MD *md, unsigned char **md_value);
+static ASN1_INTEGER *create_nonce(int bits);
+
+/* Reply related functions. */
+static int reply_command(CONF *conf, const char *section, const char *engine,
+ const char *queryfile, const char *passin, const char *inkey,
+ const EVP_MD *md, const char *signer, const char *chain,
+ const char *policy, const char *in, int token_in,
+ const char *out, int token_out, int text);
+static TS_RESP *read_PKCS7(BIO *in_bio);
+static TS_RESP *create_response(CONF *conf, const char *section, const char *engine,
+ const char *queryfile, const char *passin,
+ const char *inkey, const EVP_MD *md, const char *signer,
+ const char *chain, const char *policy);
+static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data);
+static ASN1_INTEGER *next_serial(const char *serialfile);
+static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
+
+/* Verify related functions. */
+static int verify_command(const char *data, const char *digest, const char *queryfile,
+ const char *in, int token_in,
+ const char *CApath, const char *CAfile, const char *untrusted,
+ X509_VERIFY_PARAM *vpm);
+static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
+ const char *queryfile,
+ const char *CApath, const char *CAfile,
+ const char *untrusted,
+ X509_VERIFY_PARAM *vpm);
+static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
+ X509_VERIFY_PARAM *vpm);
+static int verify_cb(int ok, X509_STORE_CTX *ctx);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA,
+ OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT,
+ OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
+ OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
+ OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED,
+ OPT_MD, OPT_V_ENUM, OPT_R_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS ts_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"config", OPT_CONFIG, '<', "Configuration file"},
+ {"section", OPT_SECTION, 's', "Section to use within config file"},
+ {"query", OPT_QUERY, '-', "Generate a TS query"},
+ {"data", OPT_DATA, '<', "File to hash"},
+ {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"},
+ OPT_R_OPTIONS,
+ {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
+ {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
+ {"cert", OPT_CERT, '-', "Put cert request into query"},
+ {"in", OPT_IN, '<', "Input file"},
+ {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
+ {"out", OPT_OUT, '>', "Output file"},
+ {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"},
+ {"text", OPT_TEXT, '-', "Output text (not DER)"},
+ {"reply", OPT_REPLY, '-', "Generate a TS reply"},
+ {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"},
+ {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+ {"inkey", OPT_INKEY, 's', "File with private key for reply"},
+ {"signer", OPT_SIGNER, 's', "Signer certificate file"},
+ {"chain", OPT_CHAIN, '<', "File with signer CA chain"},
+ {"verify", OPT_VERIFY, '-', "Verify a TS response"},
+ {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"},
+ {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"},
+ {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"},
+ {"", OPT_MD, '-', "Any supported digest"},
+# ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+# endif
+ {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"},
+ OPT_V_OPTIONS,
+ {OPT_HELP_STR, 1, '-', "\n"},
+ {NULL}
+};
+
+/*
+ * This command is so complex, special help is needed.
+ */
+static char* opt_helplist[] = {
+ "Typical uses:",
+ "ts -query [-rand file...] [-config file] [-data file]",
+ " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]",
+ " [-in file] [-out file] [-text]",
+ " or",
+ "ts -reply [-config file] [-section tsa_section]",
+ " [-queryfile file] [-passin password]",
+ " [-signer tsa_cert.pem] [-inkey private_key.pem]",
+ " [-chain certs_file.pem] [-tspolicy oid]",
+ " [-in file] [-token_in] [-out file] [-token_out]",
+# ifndef OPENSSL_NO_ENGINE
+ " [-text] [-engine id]",
+# else
+ " [-text]",
+# endif
+ " or",
+ "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem",
+ " [-data file] [-digest hexstring]",
+ " [-queryfile file] -in file [-token_in]",
+ " [[options specific to 'ts -verify']]",
+ NULL,
+};
+
+int ts_main(int argc, char **argv)
+{
+ CONF *conf = NULL;
+ const char *CAfile = NULL, *untrusted = NULL, *prog;
+ const char *configfile = default_config_file, *engine = NULL;
+ const char *section = NULL;
+ char **helpp;
+ char *password = NULL;
+ char *data = NULL, *digest = NULL, *policy = NULL;
+ char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL;
+ char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL;
+ const EVP_MD *md = NULL;
+ OPTION_CHOICE o, mode = OPT_ERR;
+ int ret = 1, no_nonce = 0, cert = 0, text = 0;
+ int vpmtouched = 0;
+ X509_VERIFY_PARAM *vpm = NULL;
+ /* Input is ContentInfo instead of TimeStampResp. */
+ int token_in = 0;
+ /* Output is ContentInfo instead of TimeStampResp. */
+ int token_out = 0;
+
+ if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
+ goto end;
+
+ prog = opt_init(argc, argv, ts_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(ts_options);
+ for (helpp = opt_helplist; *helpp; ++helpp)
+ BIO_printf(bio_err, "%s\n", *helpp);
+ ret = 0;
+ goto end;
+ case OPT_CONFIG:
+ configfile = opt_arg();
+ break;
+ case OPT_SECTION:
+ section = opt_arg();
+ break;
+ case OPT_QUERY:
+ case OPT_REPLY:
+ case OPT_VERIFY:
+ if (mode != OPT_ERR)
+ goto opthelp;
+ mode = o;
+ break;
+ case OPT_DATA:
+ data = opt_arg();
+ break;
+ case OPT_DIGEST:
+ digest = opt_arg();
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_TSPOLICY:
+ policy = opt_arg();
+ break;
+ case OPT_NO_NONCE:
+ no_nonce = 1;
+ break;
+ case OPT_CERT:
+ cert = 1;
+ break;
+ case OPT_IN:
+ in = opt_arg();
+ break;
+ case OPT_TOKEN_IN:
+ token_in = 1;
+ break;
+ case OPT_OUT:
+ out = opt_arg();
+ break;
+ case OPT_TOKEN_OUT:
+ token_out = 1;
+ break;
+ case OPT_TEXT:
+ text = 1;
+ break;
+ case OPT_QUERYFILE:
+ queryfile = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passin = opt_arg();
+ break;
+ case OPT_INKEY:
+ inkey = opt_arg();
+ break;
+ case OPT_SIGNER:
+ signer = opt_arg();
+ break;
+ case OPT_CHAIN:
+ chain = opt_arg();
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_UNTRUSTED:
+ untrusted = opt_arg();
+ break;
+ case OPT_ENGINE:
+ engine = opt_arg();
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_unknown(), &md))
+ goto opthelp;
+ break;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ }
+ }
+ if (mode == OPT_ERR || opt_num_rest() != 0)
+ goto opthelp;
+
+ if (mode == OPT_REPLY && passin &&
+ !app_passwd(passin, NULL, &password, NULL)) {
+ BIO_printf(bio_err, "Error getting password.\n");
+ goto end;
+ }
+
+ conf = load_config_file(configfile);
+ if (configfile != default_config_file && !app_load_modules(conf))
+ goto end;
+
+ /* Check parameter consistency and execute the appropriate function. */
+ if (mode == OPT_QUERY) {
+ if (vpmtouched)
+ goto opthelp;
+ if ((data != NULL) && (digest != NULL))
+ goto opthelp;
+ ret = !query_command(data, digest, md, policy, no_nonce, cert,
+ in, out, text);
+ } else if (mode == OPT_REPLY) {
+ if (vpmtouched)
+ goto opthelp;
+ if ((in != NULL) && (queryfile != NULL))
+ goto opthelp;
+ if (in == NULL) {
+ if ((conf == NULL) || (token_in != 0))
+ goto opthelp;
+ }
+ ret = !reply_command(conf, section, engine, queryfile,
+ password, inkey, md, signer, chain, policy,
+ in, token_in, out, token_out, text);
+
+ } else if (mode == OPT_VERIFY) {
+ if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
+ goto opthelp;
+ ret = !verify_command(data, digest, queryfile, in, token_in,
+ CApath, CAfile, untrusted,
+ vpmtouched ? vpm : NULL);
+ } else {
+ goto opthelp;
+ }
+
+ end:
+ X509_VERIFY_PARAM_free(vpm);
+ NCONF_free(conf);
+ OPENSSL_free(password);
+ return ret;
+}
+
+/*
+ * Configuration file-related function definitions.
+ */
+
+static ASN1_OBJECT *txt2obj(const char *oid)
+{
+ ASN1_OBJECT *oid_obj = NULL;
+
+ if ((oid_obj = OBJ_txt2obj(oid, 0)) == NULL)
+ BIO_printf(bio_err, "cannot convert %s to OID\n", oid);
+
+ return oid_obj;
+}
+
+static CONF *load_config_file(const char *configfile)
+{
+ CONF *conf = app_load_config(configfile);
+
+ if (conf != NULL) {
+ const char *p;
+
+ BIO_printf(bio_err, "Using configuration from %s\n", configfile);
+ p = NCONF_get_string(conf, NULL, ENV_OID_FILE);
+ if (p != NULL) {
+ BIO *oid_bio = BIO_new_file(p, "r");
+ if (!oid_bio)
+ ERR_print_errors(bio_err);
+ else {
+ OBJ_create_objects(oid_bio);
+ BIO_free_all(oid_bio);
+ }
+ } else
+ ERR_clear_error();
+ if (!add_oid_section(conf))
+ ERR_print_errors(bio_err);
+ }
+ return conf;
+}
+
+/*
+ * Query-related method definitions.
+ */
+static int query_command(const char *data, const char *digest, const EVP_MD *md,
+ const char *policy, int no_nonce,
+ int cert, const char *in, const char *out, int text)
+{
+ int ret = 0;
+ TS_REQ *query = NULL;
+ BIO *in_bio = NULL;
+ BIO *data_bio = NULL;
+ BIO *out_bio = NULL;
+
+ /* Build query object. */
+ if (in != NULL) {
+ if ((in_bio = bio_open_default(in, 'r', FORMAT_ASN1)) == NULL)
+ goto end;
+ query = d2i_TS_REQ_bio(in_bio, NULL);
+ } else {
+ if (digest == NULL
+ && (data_bio = bio_open_default(data, 'r', FORMAT_ASN1)) == NULL)
+ goto end;
+ query = create_query(data_bio, digest, md, policy, no_nonce, cert);
+ }
+ if (query == NULL)
+ goto end;
+
+ if (text) {
+ if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL)
+ goto end;
+ if (!TS_REQ_print_bio(out_bio, query))
+ goto end;
+ } else {
+ if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL)
+ goto end;
+ if (!i2d_TS_REQ_bio(out_bio, query))
+ goto end;
+ }
+
+ ret = 1;
+
+ end:
+ ERR_print_errors(bio_err);
+ BIO_free_all(in_bio);
+ BIO_free_all(data_bio);
+ BIO_free_all(out_bio);
+ TS_REQ_free(query);
+ return ret;
+}
+
+static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md,
+ const char *policy, int no_nonce, int cert)
+{
+ int ret = 0;
+ TS_REQ *ts_req = NULL;
+ int len;
+ TS_MSG_IMPRINT *msg_imprint = NULL;
+ X509_ALGOR *algo = NULL;
+ unsigned char *data = NULL;
+ ASN1_OBJECT *policy_obj = NULL;
+ ASN1_INTEGER *nonce_asn1 = NULL;
+
+ if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL)
+ goto err;
+ if ((ts_req = TS_REQ_new()) == NULL)
+ goto err;
+ if (!TS_REQ_set_version(ts_req, 1))
+ goto err;
+ if ((msg_imprint = TS_MSG_IMPRINT_new()) == NULL)
+ goto err;
+ if ((algo = X509_ALGOR_new()) == NULL)
+ goto err;
+ if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL)
+ goto err;
+ if ((algo->parameter = ASN1_TYPE_new()) == NULL)
+ goto err;
+ algo->parameter->type = V_ASN1_NULL;
+ if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo))
+ goto err;
+ if ((len = create_digest(data_bio, digest, md, &data)) == 0)
+ goto err;
+ if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len))
+ goto err;
+ if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint))
+ goto err;
+ if (policy && (policy_obj = txt2obj(policy)) == NULL)
+ goto err;
+ if (policy_obj && !TS_REQ_set_policy_id(ts_req, policy_obj))
+ goto err;
+
+ /* Setting nonce if requested. */
+ if (!no_nonce && (nonce_asn1 = create_nonce(NONCE_LENGTH)) == NULL)
+ goto err;
+ if (nonce_asn1 && !TS_REQ_set_nonce(ts_req, nonce_asn1))
+ goto err;
+ if (!TS_REQ_set_cert_req(ts_req, cert))
+ goto err;
+
+ ret = 1;
+ err:
+ if (!ret) {
+ TS_REQ_free(ts_req);
+ ts_req = NULL;
+ BIO_printf(bio_err, "could not create query\n");
+ ERR_print_errors(bio_err);
+ }
+ TS_MSG_IMPRINT_free(msg_imprint);
+ X509_ALGOR_free(algo);
+ OPENSSL_free(data);
+ ASN1_OBJECT_free(policy_obj);
+ ASN1_INTEGER_free(nonce_asn1);
+ return ts_req;
+}
+
+static int create_digest(BIO *input, const char *digest, const EVP_MD *md,
+ unsigned char **md_value)
+{
+ int md_value_len;
+ int rv = 0;
+ EVP_MD_CTX *md_ctx = NULL;
+
+ md_value_len = EVP_MD_size(md);
+ if (md_value_len < 0)
+ return 0;
+
+ if (input != NULL) {
+ unsigned char buffer[4096];
+ int length;
+
+ md_ctx = EVP_MD_CTX_new();
+ if (md_ctx == NULL)
+ return 0;
+ *md_value = app_malloc(md_value_len, "digest buffer");
+ if (!EVP_DigestInit(md_ctx, md))
+ goto err;
+ while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) {
+ if (!EVP_DigestUpdate(md_ctx, buffer, length))
+ goto err;
+ }
+ if (!EVP_DigestFinal(md_ctx, *md_value, NULL))
+ goto err;
+ md_value_len = EVP_MD_size(md);
+ } else {
+ long digest_len;
+ *md_value = OPENSSL_hexstr2buf(digest, &digest_len);
+ if (!*md_value || md_value_len != digest_len) {
+ OPENSSL_free(*md_value);
+ *md_value = NULL;
+ BIO_printf(bio_err, "bad digest, %d bytes "
+ "must be specified\n", md_value_len);
+ return 0;
+ }
+ }
+ rv = md_value_len;
+ err:
+ EVP_MD_CTX_free(md_ctx);
+ return rv;
+}
+
+static ASN1_INTEGER *create_nonce(int bits)
+{
+ unsigned char buf[20];
+ ASN1_INTEGER *nonce = NULL;
+ int len = (bits - 1) / 8 + 1;
+ int i;
+
+ if (len > (int)sizeof(buf))
+ goto err;
+ if (RAND_bytes(buf, len) <= 0)
+ goto err;
+
+ /* Find the first non-zero byte and creating ASN1_INTEGER object. */
+ for (i = 0; i < len && !buf[i]; ++i)
+ continue;
+ if ((nonce = ASN1_INTEGER_new()) == NULL)
+ goto err;
+ OPENSSL_free(nonce->data);
+ nonce->length = len - i;
+ nonce->data = app_malloc(nonce->length + 1, "nonce buffer");
+ memcpy(nonce->data, buf + i, nonce->length);
+ return nonce;
+
+ err:
+ BIO_printf(bio_err, "could not create nonce\n");
+ ASN1_INTEGER_free(nonce);
+ return NULL;
+}
+
+/*
+ * Reply-related method definitions.
+ */
+
+static int reply_command(CONF *conf, const char *section, const char *engine,
+ const char *queryfile, const char *passin, const char *inkey,
+ const EVP_MD *md, const char *signer, const char *chain,
+ const char *policy, const char *in, int token_in,
+ const char *out, int token_out, int text)
+{
+ int ret = 0;
+ TS_RESP *response = NULL;
+ BIO *in_bio = NULL;
+ BIO *query_bio = NULL;
+ BIO *inkey_bio = NULL;
+ BIO *signer_bio = NULL;
+ BIO *out_bio = NULL;
+
+ if (in != NULL) {
+ if ((in_bio = BIO_new_file(in, "rb")) == NULL)
+ goto end;
+ if (token_in) {
+ response = read_PKCS7(in_bio);
+ } else {
+ response = d2i_TS_RESP_bio(in_bio, NULL);
+ }
+ } else {
+ response = create_response(conf, section, engine, queryfile,
+ passin, inkey, md, signer, chain, policy);
+ if (response != NULL)
+ BIO_printf(bio_err, "Response has been generated.\n");
+ else
+ BIO_printf(bio_err, "Response is not generated.\n");
+ }
+ if (response == NULL)
+ goto end;
+
+ /* Write response. */
+ if (text) {
+ if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL)
+ goto end;
+ if (token_out) {
+ TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
+ if (!TS_TST_INFO_print_bio(out_bio, tst_info))
+ goto end;
+ } else {
+ if (!TS_RESP_print_bio(out_bio, response))
+ goto end;
+ }
+ } else {
+ if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL)
+ goto end;
+ if (token_out) {
+ PKCS7 *token = TS_RESP_get_token(response);
+ if (!i2d_PKCS7_bio(out_bio, token))
+ goto end;
+ } else {
+ if (!i2d_TS_RESP_bio(out_bio, response))
+ goto end;
+ }
+ }
+
+ ret = 1;
+
+ end:
+ ERR_print_errors(bio_err);
+ BIO_free_all(in_bio);
+ BIO_free_all(query_bio);
+ BIO_free_all(inkey_bio);
+ BIO_free_all(signer_bio);
+ BIO_free_all(out_bio);
+ TS_RESP_free(response);
+ return ret;
+}
+
+/* Reads a PKCS7 token and adds default 'granted' status info to it. */
+static TS_RESP *read_PKCS7(BIO *in_bio)
+{
+ int ret = 0;
+ PKCS7 *token = NULL;
+ TS_TST_INFO *tst_info = NULL;
+ TS_RESP *resp = NULL;
+ TS_STATUS_INFO *si = NULL;
+
+ if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
+ goto end;
+ if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL)
+ goto end;
+ if ((resp = TS_RESP_new()) == NULL)
+ goto end;
+ if ((si = TS_STATUS_INFO_new()) == NULL)
+ goto end;
+ if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED))
+ goto end;
+ if (!TS_RESP_set_status_info(resp, si))
+ goto end;
+ TS_RESP_set_tst_info(resp, token, tst_info);
+ token = NULL; /* Ownership is lost. */
+ tst_info = NULL; /* Ownership is lost. */
+ ret = 1;
+
+ end:
+ PKCS7_free(token);
+ TS_TST_INFO_free(tst_info);
+ if (!ret) {
+ TS_RESP_free(resp);
+ resp = NULL;
+ }
+ TS_STATUS_INFO_free(si);
+ return resp;
+}
+
+static TS_RESP *create_response(CONF *conf, const char *section, const char *engine,
+ const char *queryfile, const char *passin,
+ const char *inkey, const EVP_MD *md, const char *signer,
+ const char *chain, const char *policy)
+{
+ int ret = 0;
+ TS_RESP *response = NULL;
+ BIO *query_bio = NULL;
+ TS_RESP_CTX *resp_ctx = NULL;
+
+ if ((query_bio = BIO_new_file(queryfile, "rb")) == NULL)
+ goto end;
+ if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL)
+ goto end;
+ if ((resp_ctx = TS_RESP_CTX_new()) == NULL)
+ goto end;
+ if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx))
+ goto end;
+# ifndef OPENSSL_NO_ENGINE
+ if (!TS_CONF_set_crypto_device(conf, section, engine))
+ goto end;
+# endif
+ if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_certs(conf, section, chain, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
+ goto end;
+
+ if (md) {
+ if (!TS_RESP_CTX_set_signer_digest(resp_ctx, md))
+ goto end;
+ } else if (!TS_CONF_set_signer_digest(conf, section, NULL, resp_ctx)) {
+ goto end;
+ }
+
+ if (!TS_CONF_set_ess_cert_id_digest(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_policies(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_digests(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_accuracy(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_ordering(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_tsa_name(conf, section, resp_ctx))
+ goto end;
+ if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx))
+ goto end;
+ if ((response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL)
+ goto end;
+ ret = 1;
+
+ end:
+ if (!ret) {
+ TS_RESP_free(response);
+ response = NULL;
+ }
+ TS_RESP_CTX_free(resp_ctx);
+ BIO_free_all(query_bio);
+ return response;
+}
+
+static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data)
+{
+ const char *serial_file = (const char *)data;
+ ASN1_INTEGER *serial = next_serial(serial_file);
+
+ if (serial == NULL) {
+ TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+ "Error during serial number "
+ "generation.");
+ TS_RESP_CTX_add_failure_info(ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE);
+ } else {
+ save_ts_serial(serial_file, serial);
+ }
+
+ return serial;
+}
+
+static ASN1_INTEGER *next_serial(const char *serialfile)
+{
+ int ret = 0;
+ BIO *in = NULL;
+ ASN1_INTEGER *serial = NULL;
+ BIGNUM *bn = NULL;
+
+ if ((serial = ASN1_INTEGER_new()) == NULL)
+ goto err;
+
+ if ((in = BIO_new_file(serialfile, "r")) == NULL) {
+ ERR_clear_error();
+ BIO_printf(bio_err, "Warning: could not open file %s for "
+ "reading, using serial number: 1\n", serialfile);
+ if (!ASN1_INTEGER_set(serial, 1))
+ goto err;
+ } else {
+ char buf[1024];
+ if (!a2i_ASN1_INTEGER(in, serial, buf, sizeof(buf))) {
+ BIO_printf(bio_err, "unable to load number from %s\n",
+ serialfile);
+ goto err;
+ }
+ if ((bn = ASN1_INTEGER_to_BN(serial, NULL)) == NULL)
+ goto err;
+ ASN1_INTEGER_free(serial);
+ serial = NULL;
+ if (!BN_add_word(bn, 1))
+ goto err;
+ if ((serial = BN_to_ASN1_INTEGER(bn, NULL)) == NULL)
+ goto err;
+ }
+ ret = 1;
+
+ err:
+ if (!ret) {
+ ASN1_INTEGER_free(serial);
+ serial = NULL;
+ }
+ BIO_free_all(in);
+ BN_free(bn);
+ return serial;
+}
+
+static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
+{
+ int ret = 0;
+ BIO *out = NULL;
+
+ if ((out = BIO_new_file(serialfile, "w")) == NULL)
+ goto err;
+ if (i2a_ASN1_INTEGER(out, serial) <= 0)
+ goto err;
+ if (BIO_puts(out, "\n") <= 0)
+ goto err;
+ ret = 1;
+ err:
+ if (!ret)
+ BIO_printf(bio_err, "could not save serial number to %s\n",
+ serialfile);
+ BIO_free_all(out);
+ return ret;
+}
+
+
+/*
+ * Verify-related method definitions.
+ */
+
+static int verify_command(const char *data, const char *digest, const char *queryfile,
+ const char *in, int token_in,
+ const char *CApath, const char *CAfile, const char *untrusted,
+ X509_VERIFY_PARAM *vpm)
+{
+ BIO *in_bio = NULL;
+ PKCS7 *token = NULL;
+ TS_RESP *response = NULL;
+ TS_VERIFY_CTX *verify_ctx = NULL;
+ int ret = 0;
+
+ if ((in_bio = BIO_new_file(in, "rb")) == NULL)
+ goto end;
+ if (token_in) {
+ if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
+ goto end;
+ } else {
+ if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL)
+ goto end;
+ }
+
+ if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
+ CApath, CAfile, untrusted,
+ vpm)) == NULL)
+ goto end;
+
+ ret = token_in
+ ? TS_RESP_verify_token(verify_ctx, token)
+ : TS_RESP_verify_response(verify_ctx, response);
+
+ end:
+ printf("Verification: ");
+ if (ret)
+ printf("OK\n");
+ else {
+ printf("FAILED\n");
+ ERR_print_errors(bio_err);
+ }
+
+ BIO_free_all(in_bio);
+ PKCS7_free(token);
+ TS_RESP_free(response);
+ TS_VERIFY_CTX_free(verify_ctx);
+ return ret;
+}
+
+static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest,
+ const char *queryfile,
+ const char *CApath, const char *CAfile,
+ const char *untrusted,
+ X509_VERIFY_PARAM *vpm)
+{
+ TS_VERIFY_CTX *ctx = NULL;
+ BIO *input = NULL;
+ TS_REQ *request = NULL;
+ int ret = 0;
+ int f = 0;
+
+ if (data != NULL || digest != NULL) {
+ if ((ctx = TS_VERIFY_CTX_new()) == NULL)
+ goto err;
+ f = TS_VFY_VERSION | TS_VFY_SIGNER;
+ if (data != NULL) {
+ BIO *out = NULL;
+
+ f |= TS_VFY_DATA;
+ if ((out = BIO_new_file(data, "rb")) == NULL)
+ goto err;
+ if (TS_VERIFY_CTX_set_data(ctx, out) == NULL) {
+ BIO_free_all(out);
+ goto err;
+ }
+ } else if (digest != NULL) {
+ long imprint_len;
+ unsigned char *hexstr = OPENSSL_hexstr2buf(digest, &imprint_len);
+ f |= TS_VFY_IMPRINT;
+ if (TS_VERIFY_CTX_set_imprint(ctx, hexstr, imprint_len) == NULL) {
+ BIO_printf(bio_err, "invalid digest string\n");
+ goto err;
+ }
+ }
+
+ } else if (queryfile != NULL) {
+ if ((input = BIO_new_file(queryfile, "rb")) == NULL)
+ goto err;
+ if ((request = d2i_TS_REQ_bio(input, NULL)) == NULL)
+ goto err;
+ if ((ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)) == NULL)
+ goto err;
+ } else {
+ return NULL;
+ }
+
+ /* Add the signature verification flag and arguments. */
+ TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE);
+
+ /* Initialising the X509_STORE object. */
+ if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm))
+ == NULL)
+ goto err;
+
+ /* Loading untrusted certificates. */
+ if (untrusted
+ && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL)
+ goto err;
+ ret = 1;
+
+ err:
+ if (!ret) {
+ TS_VERIFY_CTX_free(ctx);
+ ctx = NULL;
+ }
+ BIO_free_all(input);
+ TS_REQ_free(request);
+ return ctx;
+}
+
+static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
+ X509_VERIFY_PARAM *vpm)
+{
+ X509_STORE *cert_ctx = NULL;
+ X509_LOOKUP *lookup = NULL;
+ int i;
+
+ cert_ctx = X509_STORE_new();
+ X509_STORE_set_verify_cb(cert_ctx, verify_cb);
+ if (CApath != NULL) {
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
+ if (lookup == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto err;
+ }
+ i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
+ if (!i) {
+ BIO_printf(bio_err, "Error loading directory %s\n", CApath);
+ goto err;
+ }
+ }
+
+ if (CAfile != NULL) {
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+ if (lookup == NULL) {
+ BIO_printf(bio_err, "memory allocation failure\n");
+ goto err;
+ }
+ i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM);
+ if (!i) {
+ BIO_printf(bio_err, "Error loading file %s\n", CAfile);
+ goto err;
+ }
+ }
+
+ if (vpm != NULL)
+ X509_STORE_set1_param(cert_ctx, vpm);
+
+ return cert_ctx;
+
+ err:
+ X509_STORE_free(cert_ctx);
+ return NULL;
+}
+
+static int verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ return ok;
+}
+#endif /* ndef OPENSSL_NO_TS */
diff --git a/freebsd/crypto/openssl/apps/verify.c b/freebsd/crypto/openssl/apps/verify.c
new file mode 100644
index 00000000..8e7f8635
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/verify.c
@@ -0,0 +1,321 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+static int cb(int ok, X509_STORE_CTX *ctx);
+static int check(X509_STORE *ctx, const char *file,
+ STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
+ STACK_OF(X509_CRL) *crls, int show_chain);
+static int v_verbose = 0, vflags = 0;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE,
+ OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN,
+ OPT_V_ENUM, OPT_NAMEOPT,
+ OPT_VERBOSE
+} OPTION_CHOICE;
+
+const OPTIONS verify_options[] = {
+ {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
+ {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"verbose", OPT_VERBOSE, '-',
+ "Print extra information about the operations being performed."},
+ {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"},
+ {"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"},
+ {"no-CAfile", OPT_NOCAFILE, '-',
+ "Do not load the default certificates file"},
+ {"no-CApath", OPT_NOCAPATH, '-',
+ "Do not load certificates from the default certificates directory"},
+ {"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"},
+ {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"},
+ {"CRLfile", OPT_CRLFILE, '<',
+ "File containing one or more CRL's (in PEM format) to load"},
+ {"crl_download", OPT_CRL_DOWNLOAD, '-',
+ "Attempt to download CRL information for this certificate"},
+ {"show_chain", OPT_SHOW_CHAIN, '-',
+ "Display information about the certificate chain"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ OPT_V_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {NULL}
+};
+
+int verify_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
+ STACK_OF(X509_CRL) *crls = NULL;
+ X509_STORE *store = NULL;
+ X509_VERIFY_PARAM *vpm = NULL;
+ const char *prog, *CApath = NULL, *CAfile = NULL;
+ int noCApath = 0, noCAfile = 0;
+ int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1;
+ OPTION_CHOICE o;
+
+ if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
+ goto end;
+
+ prog = opt_init(argc, argv, verify_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(verify_options);
+ BIO_printf(bio_err, "Recognized usages:\n");
+ for (i = 0; i < X509_PURPOSE_get_count(); i++) {
+ X509_PURPOSE *ptmp;
+ ptmp = X509_PURPOSE_get0(i);
+ BIO_printf(bio_err, "\t%-10s\t%s\n",
+ X509_PURPOSE_get0_sname(ptmp),
+ X509_PURPOSE_get0_name(ptmp));
+ }
+
+ BIO_printf(bio_err, "Recognized verify names:\n");
+ for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) {
+ const X509_VERIFY_PARAM *vptmp;
+ vptmp = X509_VERIFY_PARAM_get0(i);
+ BIO_printf(bio_err, "\t%-10s\n",
+ X509_VERIFY_PARAM_get0_name(vptmp));
+ }
+ ret = 0;
+ goto end;
+ case OPT_V_CASES:
+ if (!opt_verify(o, vpm))
+ goto end;
+ vpmtouched++;
+ break;
+ case OPT_CAPATH:
+ CApath = opt_arg();
+ break;
+ case OPT_CAFILE:
+ CAfile = opt_arg();
+ break;
+ case OPT_NOCAPATH:
+ noCApath = 1;
+ break;
+ case OPT_NOCAFILE:
+ noCAfile = 1;
+ break;
+ case OPT_UNTRUSTED:
+ /* Zero or more times */
+ if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL,
+ "untrusted certificates"))
+ goto end;
+ break;
+ case OPT_TRUSTED:
+ /* Zero or more times */
+ noCAfile = 1;
+ noCApath = 1;
+ if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL,
+ "trusted certificates"))
+ goto end;
+ break;
+ case OPT_CRLFILE:
+ /* Zero or more times */
+ if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL,
+ "other CRLs"))
+ goto end;
+ break;
+ case OPT_CRL_DOWNLOAD:
+ crl_download = 1;
+ break;
+ case OPT_ENGINE:
+ if ((e = setup_engine(opt_arg(), 0)) == NULL) {
+ /* Failure message already displayed */
+ goto end;
+ }
+ break;
+ case OPT_SHOW_CHAIN:
+ show_chain = 1;
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto end;
+ break;
+ case OPT_VERBOSE:
+ v_verbose = 1;
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (trusted != NULL && (CAfile || CApath)) {
+ BIO_printf(bio_err,
+ "%s: Cannot use -trusted with -CAfile or -CApath\n",
+ prog);
+ goto end;
+ }
+
+ if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+ goto end;
+ X509_STORE_set_verify_cb(store, cb);
+
+ if (vpmtouched)
+ X509_STORE_set1_param(store, vpm);
+
+ ERR_clear_error();
+
+ if (crl_download)
+ store_setup_crl_download(store);
+
+ ret = 0;
+ if (argc < 1) {
+ if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1)
+ ret = -1;
+ } else {
+ for (i = 0; i < argc; i++)
+ if (check(store, argv[i], untrusted, trusted, crls,
+ show_chain) != 1)
+ ret = -1;
+ }
+
+ end:
+ X509_VERIFY_PARAM_free(vpm);
+ X509_STORE_free(store);
+ sk_X509_pop_free(untrusted, X509_free);
+ sk_X509_pop_free(trusted, X509_free);
+ sk_X509_CRL_pop_free(crls, X509_CRL_free);
+ release_engine(e);
+ return (ret < 0 ? 2 : ret);
+}
+
+static int check(X509_STORE *ctx, const char *file,
+ STACK_OF(X509) *uchain, STACK_OF(X509) *tchain,
+ STACK_OF(X509_CRL) *crls, int show_chain)
+{
+ X509 *x = NULL;
+ int i = 0, ret = 0;
+ X509_STORE_CTX *csc;
+ STACK_OF(X509) *chain = NULL;
+ int num_untrusted;
+
+ x = load_cert(file, FORMAT_PEM, "certificate file");
+ if (x == NULL)
+ goto end;
+
+ csc = X509_STORE_CTX_new();
+ if (csc == NULL) {
+ printf("error %s: X.509 store context allocation failed\n",
+ (file == NULL) ? "stdin" : file);
+ goto end;
+ }
+
+ X509_STORE_set_flags(ctx, vflags);
+ if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) {
+ X509_STORE_CTX_free(csc);
+ printf("error %s: X.509 store context initialization failed\n",
+ (file == NULL) ? "stdin" : file);
+ goto end;
+ }
+ if (tchain != NULL)
+ X509_STORE_CTX_set0_trusted_stack(csc, tchain);
+ if (crls != NULL)
+ X509_STORE_CTX_set0_crls(csc, crls);
+ i = X509_verify_cert(csc);
+ if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) {
+ printf("%s: OK\n", (file == NULL) ? "stdin" : file);
+ ret = 1;
+ if (show_chain) {
+ int j;
+
+ chain = X509_STORE_CTX_get1_chain(csc);
+ num_untrusted = X509_STORE_CTX_get_num_untrusted(csc);
+ printf("Chain:\n");
+ for (j = 0; j < sk_X509_num(chain); j++) {
+ X509 *cert = sk_X509_value(chain, j);
+ printf("depth=%d: ", j);
+ X509_NAME_print_ex_fp(stdout,
+ X509_get_subject_name(cert),
+ 0, get_nameopt());
+ if (j < num_untrusted)
+ printf(" (untrusted)");
+ printf("\n");
+ }
+ sk_X509_pop_free(chain, X509_free);
+ }
+ } else {
+ printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file);
+ }
+ X509_STORE_CTX_free(csc);
+
+ end:
+ if (i <= 0)
+ ERR_print_errors(bio_err);
+ X509_free(x);
+
+ return ret;
+}
+
+static int cb(int ok, X509_STORE_CTX *ctx)
+{
+ int cert_error = X509_STORE_CTX_get_error(ctx);
+ X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
+
+ if (!ok) {
+ if (current_cert != NULL) {
+ X509_NAME_print_ex(bio_err,
+ X509_get_subject_name(current_cert),
+ 0, get_nameopt());
+ BIO_printf(bio_err, "\n");
+ }
+ BIO_printf(bio_err, "%serror %d at %d depth lookup: %s\n",
+ X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path] " : "",
+ cert_error,
+ X509_STORE_CTX_get_error_depth(ctx),
+ X509_verify_cert_error_string(cert_error));
+ switch (cert_error) {
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ policies_print(ctx);
+ /* fall thru */
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+
+ /*
+ * since we are just checking the certificates, it is ok if they
+ * are self signed. But we should still warn the user.
+ */
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ /* Continue after extension errors too */
+ case X509_V_ERR_INVALID_CA:
+ case X509_V_ERR_INVALID_NON_CA:
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ case X509_V_ERR_INVALID_PURPOSE:
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ ok = 1;
+ }
+
+ return ok;
+
+ }
+ if (cert_error == X509_V_OK && ok == 2)
+ policies_print(ctx);
+ if (!v_verbose)
+ ERR_clear_error();
+ return ok;
+}
diff --git a/freebsd/crypto/openssl/apps/version.c b/freebsd/crypto/openssl/apps/version.c
new file mode 100644
index 00000000..82a98699
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/version.c
@@ -0,0 +1,196 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_MD2
+# include <openssl/md2.h>
+#endif
+#ifndef OPENSSL_NO_RC4
+# include <openssl/rc4.h>
+#endif
+#ifndef OPENSSL_NO_DES
+# include <openssl/des.h>
+#endif
+#ifndef OPENSSL_NO_IDEA
+# include <openssl/idea.h>
+#endif
+#ifndef OPENSSL_NO_BF
+# include <openssl/blowfish.h>
+#endif
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R
+} OPTION_CHOICE;
+
+const OPTIONS version_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"a", OPT_A, '-', "Show all data"},
+ {"b", OPT_B, '-', "Show build date"},
+ {"d", OPT_D, '-', "Show configuration directory"},
+ {"e", OPT_E, '-', "Show engines directory"},
+ {"f", OPT_F, '-', "Show compiler flags used"},
+ {"o", OPT_O, '-', "Show some internal datatype options"},
+ {"p", OPT_P, '-', "Show target build platform"},
+ {"r", OPT_R, '-', "Show random seeding options"},
+ {"v", OPT_V, '-', "Show library version"},
+ {NULL}
+};
+
+#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD)
+static void printlist(const char *prefix, const char **dev)
+{
+ printf("%s (", prefix);
+ for ( ; *dev != NULL; dev++)
+ printf(" \"%s\"", *dev);
+ printf(" )");
+}
+#endif
+
+int version_main(int argc, char **argv)
+{
+ int ret = 1, dirty = 0, seed = 0;
+ int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0;
+ int engdir = 0;
+ char *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, version_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(version_options);
+ ret = 0;
+ goto end;
+ case OPT_B:
+ dirty = date = 1;
+ break;
+ case OPT_D:
+ dirty = dir = 1;
+ break;
+ case OPT_E:
+ dirty = engdir = 1;
+ break;
+ case OPT_F:
+ dirty = cflags = 1;
+ break;
+ case OPT_O:
+ dirty = options = 1;
+ break;
+ case OPT_P:
+ dirty = platform = 1;
+ break;
+ case OPT_R:
+ dirty = seed = 1;
+ break;
+ case OPT_V:
+ dirty = version = 1;
+ break;
+ case OPT_A:
+ seed = options = cflags = version = date = platform = dir = engdir
+ = 1;
+ break;
+ }
+ }
+ if (opt_num_rest() != 0) {
+ BIO_printf(bio_err, "Extra parameters given.\n");
+ goto opthelp;
+ }
+ if (!dirty)
+ version = 1;
+
+ if (version) {
+ if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER)
+ printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
+ else
+ printf("%s (Library: %s)\n",
+ OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
+ }
+ if (date)
+ printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
+ if (platform)
+ printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
+ if (options) {
+ printf("options: ");
+ printf("%s ", BN_options());
+#ifndef OPENSSL_NO_MD2
+ printf("%s ", MD2_options());
+#endif
+#ifndef OPENSSL_NO_RC4
+ printf("%s ", RC4_options());
+#endif
+#ifndef OPENSSL_NO_DES
+ printf("%s ", DES_options());
+#endif
+#ifndef OPENSSL_NO_IDEA
+ printf("%s ", IDEA_options());
+#endif
+#ifndef OPENSSL_NO_BF
+ printf("%s ", BF_options());
+#endif
+ printf("\n");
+ }
+ if (cflags)
+ printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS));
+ if (dir)
+ printf("%s\n", OpenSSL_version(OPENSSL_DIR));
+ if (engdir)
+ printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
+ if (seed) {
+ printf("Seeding source:");
+#ifdef OPENSSL_RAND_SEED_RTDSC
+ printf(" rtdsc");
+#endif
+#ifdef OPENSSL_RAND_SEED_RDCPU
+ printf(" rdrand ( rdseed rdrand )");
+#endif
+#ifdef OPENSSL_RAND_SEED_LIBRANDOM
+ printf(" C-library-random");
+#endif
+#ifdef OPENSSL_RAND_SEED_GETRANDOM
+ printf(" getrandom-syscall");
+#endif
+#ifdef OPENSSL_RAND_SEED_DEVRANDOM
+ {
+ static const char *dev[] = { DEVRANDOM, NULL };
+ printlist(" random-device", dev);
+ }
+#endif
+#ifdef OPENSSL_RAND_SEED_EGD
+ {
+ static const char *dev[] = { DEVRANDOM_EGD, NULL };
+ printlist(" EGD", dev);
+ }
+#endif
+#ifdef OPENSSL_RAND_SEED_NONE
+ printf(" none");
+#endif
+#ifdef OPENSSL_RAND_SEED_OS
+ printf(" os-specific");
+#endif
+ printf("\n");
+ }
+ ret = 0;
+ end:
+ return ret;
+}
diff --git a/freebsd/crypto/openssl/apps/x509.c b/freebsd/crypto/openssl/apps/x509.c
new file mode 100644
index 00000000..94f0b794
--- /dev/null
+++ b/freebsd/crypto/openssl/apps/x509.c
@@ -0,0 +1,1198 @@
+#include <machine/rtems-bsd-user-space.h>
+
+/*
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+# include <openssl/dsa.h>
+#endif
+
+#undef POSTFIX
+#define POSTFIX ".srl"
+#define DEF_DAYS 30
+
+static int callb(int ok, X509_STORE_CTX *ctx);
+static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
+ const EVP_MD *digest, CONF *conf, const char *section,
+ int preserve_dates);
+static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
+ X509 *x, X509 *xca, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
+ int create, int days, int clrext, CONF *conf,
+ const char *section, ASN1_INTEGER *sno, int reqfile,
+ int preserve_dates);
+static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
+static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts);
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+ OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
+ OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
+ OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA,
+ OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY,
+ OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
+ OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
+ OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
+ OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES,
+ OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
+ OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
+ OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
+ OPT_SUBJECT_HASH_OLD,
+ OPT_ISSUER_HASH_OLD,
+ OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
+ OPT_R_ENUM, OPT_EXT
+} OPTION_CHOICE;
+
+const OPTIONS x509_options[] = {
+ {"help", OPT_HELP, '-', "Display this summary"},
+ {"inform", OPT_INFORM, 'f',
+ "Input format - default PEM (one of DER or PEM)"},
+ {"in", OPT_IN, '<', "Input file - default stdin"},
+ {"outform", OPT_OUTFORM, 'f',
+ "Output format - default PEM (one of DER or PEM)"},
+ {"out", OPT_OUT, '>', "Output file - default stdout"},
+ {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"},
+ {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
+ {"serial", OPT_SERIAL, '-', "Print serial number value"},
+ {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
+ {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
+ {"hash", OPT_HASH, '-', "Synonym for -subject_hash"},
+ {"subject", OPT_SUBJECT, '-', "Print subject DN"},
+ {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
+ {"email", OPT_EMAIL, '-', "Print email address(es)"},
+ {"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
+ {"enddate", OPT_ENDDATE, '-', "Set notAfter field"},
+ {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
+ {"dates", OPT_DATES, '-', "Both Before and After dates"},
+ {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
+ {"pubkey", OPT_PUBKEY, '-', "Output the public key"},
+ {"fingerprint", OPT_FINGERPRINT, '-',
+ "Print the certificate fingerprint"},
+ {"alias", OPT_ALIAS, '-', "Output certificate alias"},
+ {"noout", OPT_NOOUT, '-', "No output, just status"},
+ {"nocert", OPT_NOCERT, '-', "No certificate output"},
+ {"ocspid", OPT_OCSPID, '-',
+ "Print OCSP hash values for the subject name and public key"},
+ {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
+ {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"},
+ {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
+ {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"},
+ {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
+ {"addreject", OPT_ADDREJECT, 's',
+ "Reject certificate for a given purpose"},
+ {"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
+ {"days", OPT_DAYS, 'n',
+ "How long till expiry of a signed certificate - def 30 days"},
+ {"checkend", OPT_CHECKEND, 'M',
+ "Check whether the cert expires in the next arg seconds"},
+ {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"},
+ {"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"},
+ {"x509toreq", OPT_X509TOREQ, '-',
+ "Output a certification request object"},
+ {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
+ {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"},
+ {"CAkey", OPT_CAKEY, 's',
+ "The CA key, must be PEM format; if not in CAfile"},
+ {"CAcreateserial", OPT_CACREATESERIAL, '-',
+ "Create serial number file if it does not exist"},
+ {"CAserial", OPT_CASERIAL, 's', "Serial file"},
+ {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
+ {"text", OPT_TEXT, '-', "Print the certificate in text form"},
+ {"ext", OPT_EXT, 's', "Print various X509V3 extensions"},
+ {"C", OPT_C, '-', "Print out C code forms"},
+ {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
+ OPT_R_OPTIONS,
+ {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
+ {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
+ {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
+ {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
+ {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
+ {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
+ {"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"},
+ {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+ {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"},
+ {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"},
+ {"clrreject", OPT_CLRREJECT, '-',
+ "Clears all the prohibited or rejected uses of the certificate"},
+ {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"},
+ {"", OPT_MD, '-', "Any supported digest"},
+#ifndef OPENSSL_NO_MD5
+ {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
+ "Print old-style (MD5) issuer hash value"},
+ {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
+ "Print old-style (MD5) subject hash value"},
+#endif
+#ifndef OPENSSL_NO_ENGINE
+ {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+ {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"},
+ {NULL}
+};
+
+int x509_main(int argc, char **argv)
+{
+ ASN1_INTEGER *sno = NULL;
+ ASN1_OBJECT *objtmp = NULL;
+ BIO *out = NULL;
+ CONF *extconf = NULL;
+ EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
+ STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+ X509 *x = NULL, *xca = NULL;
+ X509_REQ *req = NULL, *rq = NULL;
+ X509_STORE *ctx = NULL;
+ const EVP_MD *digest = NULL;
+ char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
+ char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL;
+ char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
+ char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
+ char *prog;
+ int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
+ int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
+ int fingerprint = 0, reqfile = 0, checkend = 0;
+ int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
+ int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
+ int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
+ int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
+ int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
+ int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0;
+ int enddate = 0;
+ time_t checkoffset = 0;
+ unsigned long certflag = 0;
+ int preserve_dates = 0;
+ OPTION_CHOICE o;
+ ENGINE *e = NULL;
+#ifndef OPENSSL_NO_MD5
+ int subject_hash_old = 0, issuer_hash_old = 0;
+#endif
+
+ ctx = X509_STORE_new();
+ if (ctx == NULL)
+ goto end;
+ X509_STORE_set_verify_cb(ctx, callb);
+
+ prog = opt_init(argc, argv, x509_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(x509_options);
+ ret = 0;
+ goto end;
+ case OPT_INFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ goto opthelp;
+ break;
+ case OPT_IN:
+ infile = opt_arg();
+ break;
+ case OPT_OUTFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
+ goto opthelp;
+ break;
+ case OPT_KEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
+ goto opthelp;
+ break;
+ case OPT_CAFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
+ goto opthelp;
+ break;
+ case OPT_CAKEYFORM:
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
+ goto opthelp;
+ break;
+ case OPT_OUT:
+ outfile = opt_arg();
+ break;
+ case OPT_REQ:
+ reqfile = 1;
+ break;
+
+ case OPT_SIGOPT:
+ if (!sigopts)
+ sigopts = sk_OPENSSL_STRING_new_null();
+ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_DAYS:
+ if (preserve_dates)
+ goto opthelp;
+ days = atoi(opt_arg());
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_EXTFILE:
+ extfile = opt_arg();
+ break;
+ case OPT_R_CASES:
+ if (!opt_rand(o))
+ goto end;
+ break;
+ case OPT_EXTENSIONS:
+ extsect = opt_arg();
+ break;
+ case OPT_SIGNKEY:
+ keyfile = opt_arg();
+ sign_flag = ++num;
+ break;
+ case OPT_CA:
+ CAfile = opt_arg();
+ CA_flag = ++num;
+ break;
+ case OPT_CAKEY:
+ CAkeyfile = opt_arg();
+ break;
+ case OPT_CASERIAL:
+ CAserial = opt_arg();
+ break;
+ case OPT_SET_SERIAL:
+ if (sno != NULL) {
+ BIO_printf(bio_err, "Serial number supplied twice\n");
+ goto opthelp;
+ }
+ if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
+ goto opthelp;
+ break;
+ case OPT_FORCE_PUBKEY:
+ fkeyfile = opt_arg();
+ break;
+ case OPT_ADDTRUST:
+ if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
+ BIO_printf(bio_err,
+ "%s: Invalid trust object value %s\n",
+ prog, opt_arg());
+ goto opthelp;
+ }
+ if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
+ sk_ASN1_OBJECT_push(trust, objtmp);
+ objtmp = NULL;
+ trustout = 1;
+ break;
+ case OPT_ADDREJECT:
+ if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
+ BIO_printf(bio_err,
+ "%s: Invalid reject object value %s\n",
+ prog, opt_arg());
+ goto opthelp;
+ }
+ if (reject == NULL
+ && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
+ goto end;
+ sk_ASN1_OBJECT_push(reject, objtmp);
+ objtmp = NULL;
+ trustout = 1;
+ break;
+ case OPT_SETALIAS:
+ alias = opt_arg();
+ trustout = 1;
+ break;
+ case OPT_CERTOPT:
+ if (!set_cert_ex(&certflag, opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_NAMEOPT:
+ if (!set_nameopt(opt_arg()))
+ goto opthelp;
+ break;
+ case OPT_ENGINE:
+ e = setup_engine(opt_arg(), 0);
+ break;
+ case OPT_C:
+ C = ++num;
+ break;
+ case OPT_EMAIL:
+ email = ++num;
+ break;
+ case OPT_OCSP_URI:
+ ocsp_uri = ++num;
+ break;
+ case OPT_SERIAL:
+ serial = ++num;
+ break;
+ case OPT_NEXT_SERIAL:
+ next_serial = ++num;
+ break;
+ case OPT_MODULUS:
+ modulus = ++num;
+ break;
+ case OPT_PUBKEY:
+ pubkey = ++num;
+ break;
+ case OPT_X509TOREQ:
+ x509req = ++num;
+ break;
+ case OPT_TEXT:
+ text = ++num;
+ break;
+ case OPT_SUBJECT:
+ subject = ++num;
+ break;
+ case OPT_ISSUER:
+ issuer = ++num;
+ break;
+ case OPT_FINGERPRINT:
+ fingerprint = ++num;
+ break;
+ case OPT_HASH:
+ subject_hash = ++num;
+ break;
+ case OPT_ISSUER_HASH:
+ issuer_hash = ++num;
+ break;
+ case OPT_PURPOSE:
+ pprint = ++num;
+ break;
+ case OPT_STARTDATE:
+ startdate = ++num;
+ break;
+ case OPT_ENDDATE:
+ enddate = ++num;
+ break;
+ case OPT_NOOUT:
+ noout = ++num;
+ break;
+ case OPT_EXT:
+ ext = ++num;
+ exts = opt_arg();
+ break;
+ case OPT_NOCERT:
+ nocert = 1;
+ break;
+ case OPT_TRUSTOUT:
+ trustout = 1;
+ break;
+ case OPT_CLRTRUST:
+ clrtrust = ++num;
+ break;
+ case OPT_CLRREJECT:
+ clrreject = ++num;
+ break;
+ case OPT_ALIAS:
+ aliasout = ++num;
+ break;
+ case OPT_CACREATESERIAL:
+ CA_createserial = ++num;
+ break;
+ case OPT_CLREXT:
+ clrext = 1;
+ break;
+ case OPT_OCSPID:
+ ocspid = ++num;
+ break;
+ case OPT_BADSIG:
+ badsig = 1;
+ break;
+#ifndef OPENSSL_NO_MD5
+ case OPT_SUBJECT_HASH_OLD:
+ subject_hash_old = ++num;
+ break;
+ case OPT_ISSUER_HASH_OLD:
+ issuer_hash_old = ++num;
+ break;
+#else
+ case OPT_SUBJECT_HASH_OLD:
+ case OPT_ISSUER_HASH_OLD:
+ break;
+#endif
+ case OPT_DATES:
+ startdate = ++num;
+ enddate = ++num;
+ break;
+ case OPT_CHECKEND:
+ checkend = 1;
+ {
+ intmax_t temp = 0;
+ if (!opt_imax(opt_arg(), &temp))
+ goto opthelp;
+ checkoffset = (time_t)temp;
+ if ((intmax_t)checkoffset != temp) {
+ BIO_printf(bio_err, "%s: checkend time out of range %s\n",
+ prog, opt_arg());
+ goto opthelp;
+ }
+ }
+ break;
+ case OPT_CHECKHOST:
+ checkhost = opt_arg();
+ break;
+ case OPT_CHECKEMAIL:
+ checkemail = opt_arg();
+ break;
+ case OPT_CHECKIP:
+ checkip = opt_arg();
+ break;
+ case OPT_PRESERVE_DATES:
+ if (days != DEF_DAYS)
+ goto opthelp;
+ preserve_dates = 1;
+ break;
+ case OPT_MD:
+ if (!opt_md(opt_unknown(), &digest))
+ goto opthelp;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+ if (argc != 0) {
+ BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
+ goto opthelp;
+ }
+
+ if (!app_passwd(passinarg, NULL, &passin, NULL)) {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+
+ if (!X509_STORE_set_default_paths(ctx)) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if (fkeyfile != NULL) {
+ fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
+ if (fkey == NULL)
+ goto end;
+ }
+
+ if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
+ CAkeyfile = CAfile;
+ } else if ((CA_flag) && (CAkeyfile == NULL)) {
+ BIO_printf(bio_err,
+ "need to specify a CAkey if using the CA command\n");
+ goto end;
+ }
+
+ if (extfile != NULL) {
+ X509V3_CTX ctx2;
+ if ((extconf = app_load_config(extfile)) == NULL)
+ goto end;
+ if (extsect == NULL) {
+ extsect = NCONF_get_string(extconf, "default", "extensions");
+ if (extsect == NULL) {
+ ERR_clear_error();
+ extsect = "default";
+ }
+ }
+ X509V3_set_ctx_test(&ctx2);
+ X509V3_set_nconf(&ctx2, extconf);
+ if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
+ BIO_printf(bio_err,
+ "Error Loading extension section %s\n", extsect);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (reqfile) {
+ EVP_PKEY *pkey;
+ BIO *in;
+
+ if (!sign_flag && !CA_flag) {
+ BIO_printf(bio_err, "We need a private key to sign with\n");
+ goto end;
+ }
+ in = bio_open_default(infile, 'r', informat);
+ if (in == NULL)
+ goto end;
+ req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (req == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
+ BIO_printf(bio_err, "error unpacking public key\n");
+ goto end;
+ }
+ i = X509_REQ_verify(req, pkey);
+ if (i < 0) {
+ BIO_printf(bio_err, "Signature verification error\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (i == 0) {
+ BIO_printf(bio_err,
+ "Signature did not match the certificate request\n");
+ goto end;
+ } else {
+ BIO_printf(bio_err, "Signature ok\n");
+ }
+
+ print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
+ get_nameopt());
+
+ if ((x = X509_new()) == NULL)
+ goto end;
+
+ if (sno == NULL) {
+ sno = ASN1_INTEGER_new();
+ if (sno == NULL || !rand_serial(NULL, sno))
+ goto end;
+ if (!X509_set_serialNumber(x, sno))
+ goto end;
+ ASN1_INTEGER_free(sno);
+ sno = NULL;
+ } else if (!X509_set_serialNumber(x, sno)) {
+ goto end;
+ }
+
+ if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
+ goto end;
+ if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
+ goto end;
+ if (!set_cert_times(x, NULL, NULL, days))
+ goto end;
+
+ if (fkey != NULL) {
+ X509_set_pubkey(x, fkey);
+ } else {
+ pkey = X509_REQ_get0_pubkey(req);
+ X509_set_pubkey(x, pkey);
+ }
+ } else {
+ x = load_cert(infile, informat, "Certificate");
+ }
+
+ if (x == NULL)
+ goto end;
+ if (CA_flag) {
+ xca = load_cert(CAfile, CAformat, "CA Certificate");
+ if (xca == NULL)
+ goto end;
+ }
+
+ out = bio_open_default(outfile, 'w', outformat);
+ if (out == NULL)
+ goto end;
+
+ if (!noout || text || next_serial)
+ OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
+
+ if (alias)
+ X509_alias_set1(x, (unsigned char *)alias, -1);
+
+ if (clrtrust)
+ X509_trust_clear(x);
+ if (clrreject)
+ X509_reject_clear(x);
+
+ if (trust != NULL) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
+ objtmp = sk_ASN1_OBJECT_value(trust, i);
+ X509_add1_trust_object(x, objtmp);
+ }
+ objtmp = NULL;
+ }
+
+ if (reject != NULL) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
+ objtmp = sk_ASN1_OBJECT_value(reject, i);
+ X509_add1_reject_object(x, objtmp);
+ }
+ objtmp = NULL;
+ }
+
+ if (badsig) {
+ const ASN1_BIT_STRING *signature;
+
+ X509_get0_signature(&signature, NULL, x);
+ corrupt_signature(signature);
+ }
+
+ if (num) {
+ for (i = 1; i <= num; i++) {
+ if (issuer == i) {
+ print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
+ } else if (subject == i) {
+ print_name(out, "subject=",
+ X509_get_subject_name(x), get_nameopt());
+ } else if (serial == i) {
+ BIO_printf(out, "serial=");
+ i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
+ BIO_printf(out, "\n");
+ } else if (next_serial == i) {
+ ASN1_INTEGER *ser = X509_get_serialNumber(x);
+ BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL);
+
+ if (!bnser)
+ goto end;
+ if (!BN_add_word(bnser, 1))
+ goto end;
+ ser = BN_to_ASN1_INTEGER(bnser, NULL);
+ if (!ser)
+ goto end;
+ BN_free(bnser);
+ i2a_ASN1_INTEGER(out, ser);
+ ASN1_INTEGER_free(ser);
+ BIO_puts(out, "\n");
+ } else if ((email == i) || (ocsp_uri == i)) {
+ int j;
+ STACK_OF(OPENSSL_STRING) *emlst;
+ if (email == i)
+ emlst = X509_get1_email(x);
+ else
+ emlst = X509_get1_ocsp(x);
+ for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
+ BIO_printf(out, "%s\n",
+ sk_OPENSSL_STRING_value(emlst, j));
+ X509_email_free(emlst);
+ } else if (aliasout == i) {
+ unsigned char *alstr;
+ alstr = X509_alias_get0(x, NULL);
+ if (alstr)
+ BIO_printf(out, "%s\n", alstr);
+ else
+ BIO_puts(out, "<No Alias>\n");
+ } else if (subject_hash == i) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
+ }
+#ifndef OPENSSL_NO_MD5
+ else if (subject_hash_old == i) {
+ BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
+ }
+#endif
+ else if (issuer_hash == i) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
+ }
+#ifndef OPENSSL_NO_MD5
+ else if (issuer_hash_old == i) {
+ BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
+ }
+#endif
+ else if (pprint == i) {
+ X509_PURPOSE *ptmp;
+ int j;
+ BIO_printf(out, "Certificate purposes:\n");
+ for (j = 0; j < X509_PURPOSE_get_count(); j++) {
+ ptmp = X509_PURPOSE_get0(j);
+ purpose_print(out, x, ptmp);
+ }
+ } else if (modulus == i) {
+ EVP_PKEY *pkey;
+
+ pkey = X509_get0_pubkey(x);
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "Modulus=unavailable\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(out, "Modulus=");
+#ifndef OPENSSL_NO_RSA
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+ const BIGNUM *n;
+ RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
+ BN_print(out, n);
+ } else
+#endif
+#ifndef OPENSSL_NO_DSA
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
+ const BIGNUM *dsapub = NULL;
+ DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
+ BN_print(out, dsapub);
+ } else
+#endif
+ {
+ BIO_printf(out, "Wrong Algorithm type");
+ }
+ BIO_printf(out, "\n");
+ } else if (pubkey == i) {
+ EVP_PKEY *pkey;
+
+ pkey = X509_get0_pubkey(x);
+ if (pkey == NULL) {
+ BIO_printf(bio_err, "Error getting public key\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ PEM_write_bio_PUBKEY(out, pkey);
+ } else if (C == i) {
+ unsigned char *d;
+ char *m;
+ int len;
+
+ print_name(out, "/*\n"
+ " * Subject: ", X509_get_subject_name(x), get_nameopt());
+ print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt());
+ BIO_puts(out, " */\n");
+
+ len = i2d_X509(x, NULL);
+ m = app_malloc(len, "x509 name buffer");
+ d = (unsigned char *)m;
+ len = i2d_X509_NAME(X509_get_subject_name(x), &d);
+ print_array(out, "the_subject_name", len, (unsigned char *)m);
+ d = (unsigned char *)m;
+ len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
+ print_array(out, "the_public_key", len, (unsigned char *)m);
+ d = (unsigned char *)m;
+ len = i2d_X509(x, &d);
+ print_array(out, "the_certificate", len, (unsigned char *)m);
+ OPENSSL_free(m);
+ } else if (text == i) {
+ X509_print_ex(out, x, get_nameopt(), certflag);
+ } else if (startdate == i) {
+ BIO_puts(out, "notBefore=");
+ ASN1_TIME_print(out, X509_get0_notBefore(x));
+ BIO_puts(out, "\n");
+ } else if (enddate == i) {
+ BIO_puts(out, "notAfter=");
+ ASN1_TIME_print(out, X509_get0_notAfter(x));
+ BIO_puts(out, "\n");
+ } else if (fingerprint == i) {
+ int j;
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ const EVP_MD *fdig = digest;
+
+ if (fdig == NULL)
+ fdig = EVP_sha1();
+
+ if (!X509_digest(x, fdig, md, &n)) {
+ BIO_printf(bio_err, "out of memory\n");
+ goto end;
+ }
+ BIO_printf(out, "%s Fingerprint=",
+ OBJ_nid2sn(EVP_MD_type(fdig)));
+ for (j = 0; j < (int)n; j++) {
+ BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
+ ? '\n' : ':');
+ }
+ }
+
+ /* should be in the library */
+ else if ((sign_flag == i) && (x509req == 0)) {
+ BIO_printf(bio_err, "Getting Private key\n");
+ if (Upkey == NULL) {
+ Upkey = load_key(keyfile, keyformat, 0,
+ passin, e, "Private key");
+ if (Upkey == NULL)
+ goto end;
+ }
+
+ if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates))
+ goto end;
+ } else if (CA_flag == i) {
+ BIO_printf(bio_err, "Getting CA Private Key\n");
+ if (CAkeyfile != NULL) {
+ CApkey = load_key(CAkeyfile, CAkeyformat,
+ 0, passin, e, "CA Private Key");
+ if (CApkey == NULL)
+ goto end;
+ }
+
+ if (!x509_certify(ctx, CAfile, digest, x, xca,
+ CApkey, sigopts,
+ CAserial, CA_createserial, days, clrext,
+ extconf, extsect, sno, reqfile, preserve_dates))
+ goto end;
+ } else if (x509req == i) {
+ EVP_PKEY *pk;
+
+ BIO_printf(bio_err, "Getting request Private Key\n");
+ if (keyfile == NULL) {
+ BIO_printf(bio_err, "no request key file specified\n");
+ goto end;
+ } else {
+ pk = load_key(keyfile, keyformat, 0,
+ passin, e, "request key");
+ if (pk == NULL)
+ goto end;
+ }
+
+ BIO_printf(bio_err, "Generating certificate request\n");
+
+ rq = X509_to_X509_REQ(x, pk, digest);
+ EVP_PKEY_free(pk);
+ if (rq == NULL) {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ if (!noout) {
+ X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
+ PEM_write_bio_X509_REQ(out, rq);
+ }
+ noout = 1;
+ } else if (ocspid == i) {
+ X509_ocspid_print(out, x);
+ } else if (ext == i) {
+ print_x509v3_exts(out, x, exts);
+ }
+ }
+ }
+
+ if (checkend) {
+ time_t tcheck = time(NULL) + checkoffset;
+
+ if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
+ BIO_printf(out, "Certificate will expire\n");
+ ret = 1;
+ } else {
+ BIO_printf(out, "Certificate will not expire\n");
+ ret = 0;
+ }
+ goto end;
+ }
+
+ print_cert_checks(out, x, checkhost, checkemail, checkip);
+
+ if (noout || nocert) {
+ ret = 0;
+ goto end;
+ }
+
+ if (outformat == FORMAT_ASN1) {
+ i = i2d_X509_bio(out, x);
+ } else if (outformat == FORMAT_PEM) {
+ if (trustout)
+ i = PEM_write_bio_X509_AUX(out, x);
+ else
+ i = PEM_write_bio_X509(out, x);
+ } else {
+ BIO_printf(bio_err, "bad output format specified for outfile\n");
+ goto end;
+ }
+ if (!i) {
+ BIO_printf(bio_err, "unable to write certificate\n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ ret = 0;
+ end:
+ NCONF_free(extconf);
+ BIO_free_all(out);
+ X509_STORE_free(ctx);
+ X509_REQ_free(req);
+ X509_free(x);
+ X509_free(xca);
+ EVP_PKEY_free(Upkey);
+ EVP_PKEY_free(CApkey);
+ EVP_PKEY_free(fkey);
+ sk_OPENSSL_STRING_free(sigopts);
+ X509_REQ_free(rq);
+ ASN1_INTEGER_free(sno);
+ sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
+ sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
+ ASN1_OBJECT_free(objtmp);
+ release_engine(e);
+ OPENSSL_free(passin);
+ return ret;
+}
+
+static ASN1_INTEGER *x509_load_serial(const char *CAfile,
+ const char *serialfile, int create)
+{
+ char *buf = NULL;
+ ASN1_INTEGER *bs = NULL;
+ BIGNUM *serial = NULL;
+
+ if (serialfile == NULL) {
+ const char *p = strrchr(CAfile, '.');
+ size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile);
+
+ buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer");
+ memcpy(buf, CAfile, len);
+ memcpy(buf + len, POSTFIX, sizeof(POSTFIX));
+ serialfile = buf;
+ }
+
+ serial = load_serial(serialfile, create, NULL);
+ if (serial == NULL)
+ goto end;
+
+ if (!BN_add_word(serial, 1)) {
+ BIO_printf(bio_err, "add_word failure\n");
+ goto end;
+ }
+
+ if (!save_serial(serialfile, NULL, serial, &bs))
+ goto end;
+
+ end:
+ OPENSSL_free(buf);
+ BN_free(serial);
+ return bs;
+}
+
+static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
+ X509 *x, X509 *xca, EVP_PKEY *pkey,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ const char *serialfile, int create,
+ int days, int clrext, CONF *conf, const char *section,
+ ASN1_INTEGER *sno, int reqfile, int preserve_dates)
+{
+ int ret = 0;
+ ASN1_INTEGER *bs = NULL;
+ X509_STORE_CTX *xsc = NULL;
+ EVP_PKEY *upkey;
+
+ upkey = X509_get0_pubkey(xca);
+ if (upkey == NULL) {
+ BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
+ goto end;
+ }
+ EVP_PKEY_copy_parameters(upkey, pkey);
+
+ xsc = X509_STORE_CTX_new();
+ if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
+ BIO_printf(bio_err, "Error initialising X509 store\n");
+ goto end;
+ }
+ if (sno)
+ bs = sno;
+ else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
+ goto end;
+
+ /*
+ * NOTE: this certificate can/should be self signed, unless it was a
+ * certificate request in which case it is not.
+ */
+ X509_STORE_CTX_set_cert(xsc, x);
+ X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+ if (!reqfile && X509_verify_cert(xsc) <= 0)
+ goto end;
+
+ if (!X509_check_private_key(xca, pkey)) {
+ BIO_printf(bio_err,
+ "CA certificate and CA private key do not match\n");
+ goto end;
+ }
+
+ if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
+ goto end;
+ if (!X509_set_serialNumber(x, bs))
+ goto end;
+
+ if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+ goto end;
+
+ if (clrext) {
+ while (X509_get_ext_count(x) > 0)
+ X509_delete_ext(x, 0);
+ }
+
+ if (conf != NULL) {
+ X509V3_CTX ctx2;
+ X509_set_version(x, 2); /* version 3 certificate */
+ X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
+ X509V3_set_nconf(&ctx2, conf);
+ if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
+ goto end;
+ }
+
+ if (!do_X509_sign(x, pkey, digest, sigopts))
+ goto end;
+ ret = 1;
+ end:
+ X509_STORE_CTX_free(xsc);
+ if (!ret)
+ ERR_print_errors(bio_err);
+ if (!sno)
+ ASN1_INTEGER_free(bs);
+ return ret;
+}
+
+static int callb(int ok, X509_STORE_CTX *ctx)
+{
+ int err;
+ X509 *err_cert;
+
+ /*
+ * it is ok to use a self signed certificate This case will catch both
+ * the initial ok == 0 and the final ok == 1 calls to this function
+ */
+ err = X509_STORE_CTX_get_error(ctx);
+ if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
+ return 1;
+
+ /*
+ * BAD we should have gotten an error. Normally if everything worked
+ * X509_STORE_CTX_get_error(ctx) will still be set to
+ * DEPTH_ZERO_SELF_....
+ */
+ if (ok) {
+ BIO_printf(bio_err,
+ "error with certificate to be certified - should be self signed\n");
+ return 0;
+ } else {
+ err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
+ BIO_printf(bio_err,
+ "error with certificate - error %d at depth %d\n%s\n", err,
+ X509_STORE_CTX_get_error_depth(ctx),
+ X509_verify_cert_error_string(err));
+ return 1;
+ }
+}
+
+/* self sign */
+static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
+ const EVP_MD *digest, CONF *conf, const char *section,
+ int preserve_dates)
+{
+
+ if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
+ goto err;
+ if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+ goto err;
+ if (!X509_set_pubkey(x, pkey))
+ goto err;
+ if (clrext) {
+ while (X509_get_ext_count(x) > 0)
+ X509_delete_ext(x, 0);
+ }
+ if (conf != NULL) {
+ X509V3_CTX ctx;
+ X509_set_version(x, 2); /* version 3 certificate */
+ X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
+ X509V3_set_nconf(&ctx, conf);
+ if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
+ goto err;
+ }
+ if (!X509_sign(x, pkey, digest))
+ goto err;
+ return 1;
+ err:
+ ERR_print_errors(bio_err);
+ return 0;
+}
+
+static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
+{
+ int id, i, idret;
+ const char *pname;
+ id = X509_PURPOSE_get_id(pt);
+ pname = X509_PURPOSE_get0_name(pt);
+ for (i = 0; i < 2; i++) {
+ idret = X509_check_purpose(cert, id, i);
+ BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
+ if (idret == 1)
+ BIO_printf(bio, "Yes\n");
+ else if (idret == 0)
+ BIO_printf(bio, "No\n");
+ else
+ BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
+ }
+ return 1;
+}
+
+static int parse_ext_names(char *names, const char **result)
+{
+ char *p, *q;
+ int cnt = 0, len = 0;
+
+ p = q = names;
+ len = strlen(names);
+
+ while (q - names <= len) {
+ if (*q != ',' && *q != '\0') {
+ q++;
+ continue;
+ }
+ if (p != q) {
+ /* found */
+ if (result != NULL) {
+ result[cnt] = p;
+ *q = '\0';
+ }
+ cnt++;
+ }
+ p = ++q;
+ }
+
+ return cnt;
+}
+
+static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names)
+{
+ const STACK_OF(X509_EXTENSION) *exts = NULL;
+ STACK_OF(X509_EXTENSION) *exts2 = NULL;
+ X509_EXTENSION *ext = NULL;
+ ASN1_OBJECT *obj;
+ int i, j, ret = 0, num, nn = 0;
+ const char *sn, **names = NULL;
+ char *tmp_ext_names = NULL;
+
+ exts = X509_get0_extensions(x);
+ if ((num = sk_X509_EXTENSION_num(exts)) <= 0) {
+ BIO_printf(bio, "No extensions in certificate\n");
+ ret = 1;
+ goto end;
+ }
+
+ /* parse comma separated ext name string */
+ if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL)
+ goto end;
+ if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) {
+ BIO_printf(bio, "Invalid extension names: %s\n", ext_names);
+ goto end;
+ }
+ if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL)
+ goto end;
+ parse_ext_names(tmp_ext_names, names);
+
+ for (i = 0; i < num; i++) {
+ ext = sk_X509_EXTENSION_value(exts, i);
+
+ /* check if this ext is what we want */
+ obj = X509_EXTENSION_get_object(ext);
+ sn = OBJ_nid2sn(OBJ_obj2nid(obj));
+ if (sn == NULL || strcmp(sn, "UNDEF") == 0)
+ continue;
+
+ for (j = 0; j < nn; j++) {
+ if (strcmp(sn, names[j]) == 0) {
+ /* push the extension into a new stack */
+ if (exts2 == NULL
+ && (exts2 = sk_X509_EXTENSION_new_null()) == NULL)
+ goto end;
+ if (!sk_X509_EXTENSION_push(exts2, ext))
+ goto end;
+ }
+ }
+ }
+
+ if (!sk_X509_EXTENSION_num(exts2)) {
+ BIO_printf(bio, "No extensions matched with %s\n", ext_names);
+ ret = 1;
+ goto end;
+ }
+
+ ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0);
+ end:
+ sk_X509_EXTENSION_free(exts2);
+ OPENSSL_free(names);
+ OPENSSL_free(tmp_ext_names);
+ return ret;
+}