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