Dear Dev team, Regarding "engine" support in timestamping (ts) app, I find it has compatibility issues with the rest of OpenSSL.
That is why I took some patches that were applicable to o.9.8 version and adapted them to the current git-head. I'm not the only contributor to this patch, there are other people to give credit as well, but please find patch to apps/ts.c attached to my message. When compiled with engine support, it will enable use of "-engine" and "-keyform" command line arguments. Of no less importance is to emphasise that it adds additional "keyform" parameter to functions defined in ts.c and utilized by "-reply" function, that will *break* compatibility with any previously existing code. That is why I'm submitting this patch only as a proposal, as you have more experience on how to do it properly from the function prototype change management perspective. The patch itself has been tested with engine_pkcs11.so but requires more testing, which I plan to do (both: with engine support compiled in and without). Also find attached my testing openssl_tsa.cnf and command line invocation syntax: #!/bin/bash LD_LIBRARY_PATH=/usr/local/lib OPENSSL_CONF=openssl_tsa3.cnf /usr/local/bin/openssl ts -reply \ -keyform engine -engine pkcs11 -inkey "0:1122334455" -passin "pass:secretpassword" \ -queryfile request256.tsq -signer TSA001.crt.pem -chain ca.crt -out response.tsr \ -text -token_out Damir Dzeko Antic Manager, IT Security CISA #14116322 tel: +971 4 4347599 fax: +971 4 4405981 mobile: +971 55 3580753 Business Central Towers (BCT) Office: 2702A, P.O. Box: 503012 Dubai Media City, UAE www.recro-net.com
--- ts.c,orig 2014-08-24 10:28:57.348915511 +0400
+++ ts.c 2014-09-01 12:00:23.836618283 +0400
@@ -94,13 +94,13 @@
static ASN1_INTEGER *create_nonce(int bits);
/* Reply related functions. */
-static int reply_command(CONF *conf, char *section, char *engine,
+static int reply_command(CONF *conf, char *section, char *engine, int keyform,
char *queryfile, char *passin, char *inkey,
char *signer, char *chain, const char *policy,
char *in, int token_in, 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, char *engine,
+static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
int keyform,
char *queryfile, char *passin, char *inkey,
char *signer, char *chain, const char *policy);
static ASN1_INTEGER * MS_CALLBACK serial_cb(TS_RESP_CTX *ctx, void *data);
@@ -149,7 +149,10 @@
char *ca_path = NULL;
char *ca_file = NULL;
char *untrusted = NULL;
+#ifndef OPENSSL_NO_ENGINE
char *engine = NULL;
+ int keyform = 0;
+#endif
/* Input is ContentInfo instead of TimeStampResp. */
int token_in = 0;
/* Output is ContentInfo instead of TimeStampResp. */
@@ -285,11 +288,18 @@
if (argc-- < 1) goto usage;
untrusted = *++argv;
}
+#ifndef OPENSS_NO_ENGINE
else if (strcmp(*argv, "-engine") == 0)
{
if (argc-- < 1) goto usage;
engine = *++argv;
}
+ else if (!strcmp (*argv, "-keyform"))
+ {
+ if (argc-- < 1) goto usage;
+ keyform = str2fmt(*++argv);
+ }
+#endif
else if ((md = EVP_get_digestbyname(*argv + 1)) != NULL)
{
/* empty. */
@@ -346,8 +356,7 @@
ret = !(queryfile == NULL);
if (ret) goto usage;
}
-
- ret = !reply_command(conf, section, engine, queryfile,
+ ret = !reply_command(conf, section, engine, keyform, queryfile,
password, inkey, signer, chain, policy,
in, token_in, out, token_out, text);
break;
@@ -375,10 +384,11 @@
BIO_printf(bio_err, "or\n"
"ts -reply [-config configfile] [-section tsa_section] "
"[-queryfile request.tsq] [-passin password] "
+ "{ [-keyform engine] [-engine engine_id] } "
"[-signer tsa_cert.pem] [-inkey private_key.pem] "
"[-chain certs_file.pem] [-policy object_id] "
"[-in response.tsr] [-token_in] "
- "[-out response.tsr] [-token_out] [-text] [-engine id]\n");
+ "[-out response.tsr] [-token_out] [-text]\n");
BIO_printf(bio_err, "or\n"
"ts -verify [-data file_to_hash] [-digest digest_bytes] "
"[-queryfile request.tsq] "
@@ -671,7 +681,7 @@
* Reply-related method definitions.
*/
-static int reply_command(CONF *conf, char *section, char *engine,
+static int reply_command(CONF *conf, char *section, char *engine, int keyform,
char *queryfile, char *passin, char *inkey,
char *signer, char *chain, const char *policy,
char *in, int token_in,
@@ -703,7 +713,7 @@
}
else
{
- response = create_response(conf, section, engine, queryfile,
+ response = create_response(conf, section, engine, keyform,
queryfile,
passin, inkey, signer, chain,
policy);
if (response)
@@ -798,7 +808,7 @@
return resp;
}
-static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
+static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
int keyform,
char *queryfile, char *passin, char *inkey,
char *signer, char *chain, const char *policy)
{
@@ -806,6 +816,10 @@
TS_RESP *response = NULL;
BIO *query_bio = NULL;
TS_RESP_CTX *resp_ctx = NULL;
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *e = NULL;
+ EVP_PKEY *key_obj = NULL;
+#endif
if (!(query_bio = BIO_new_file(queryfile, "rb")))
goto end;
@@ -831,8 +845,18 @@
if (!TS_CONF_set_certs(conf, section, chain, resp_ctx)) goto end;
/* Setting TSA signer private key. */
- if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
- goto end;
+#ifndef OPENSSL_NO_ENGINE
+ if (keyform) {
+ if (!(e = setup_engine(bio_err, engine, 0))) goto end;
+ if (!(key_obj = load_key(bio_err, inkey, keyform, 0, passin, e,
"engine signing key"))) goto end;
+ if (!TS_RESP_CTX_set_signer_key(resp_ctx, key_obj)) goto end;
+ }
+ else {
+#endif
+ if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
goto end;
+#ifndef OPENSSL_NO_ENGINE
+ }
+#endif
/* Setting default policy OID. */
if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx)) goto end;
@@ -872,6 +896,9 @@
}
TS_RESP_CTX_free(resp_ctx);
BIO_free_all(query_bio);
+#ifndef OPENSSL_NO_ENGINE
+ EVP_PKEY_free(key_obj);
+#endif
return response;
}
openssl_tsa3.cnf
Description: openssl_tsa3.cnf
