I updated the patch (now in unified form) to keep backwards compatibility.
Best regards,
Martin
2010/12/29 Stephen Henson via RT <[email protected]>:
>> [[email protected] - Mon Dec 27 14:59:59 2010]:
>>
>> The attached patch contains:
>>
>> - an additional method for creating a timestamp directly from a
>> TS_REQ. The existing method taking a BIO was renamed. In cases where
>> the reference to TS_REQ is still available, this avoids the
>> unnecessary DER-encoding and later -decoding.
>
> We are very reluctant to rename/delete functions as this will break some
> applications. It is only ever done on major releases (meaning they can't
> be backported to 1.0.x) and then usually for functions that are only
> intended to be used internally. So really we need new functions names
> keeping the existing ones: it's unfortunate that the BIO related
> functions don't follow the convention of having "bio" in their name but
> we're stuck with it now.
>
> Also please use unified diff format for patches.
>
> Steve.
> --
> Dr Stephen N. Henson. OpenSSL project core developer.
> Commercial tech support now available see: http://www.openssl.org
>
>
Index: crypto/ts/ts.h
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ts/ts.h,v
retrieving revision 1.6
diff -u -r1.6 ts.h
--- crypto/ts/ts.h 12 Nov 2008 03:58:06 -0000 1.6
+++ crypto/ts/ts.h 29 Dec 2010 17:33:07 -0000
@@ -604,6 +604,7 @@
* In case of errors it sets the status info properly.
* Returns NULL only in case of memory allocation/fatal error.
*/
+TS_RESP *TS_RESP_create_response_req(TS_RESP_CTX *ctx, TS_REQ *req);
TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio);
/*
@@ -611,8 +612,11 @@
* they are defined in ts/ts_resp_verify.c.
*/
-int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
- X509_STORE *store, X509 **signer_out);
+int TS_RESP_verify_signature_flags(PKCS7 *token, STACK_OF(X509) *certs,
+ X509_STORE *store, X509 **signer_out,
+ unsigned flags);
+#define TS_RESP_verify_signature(p7, certs, store, s_out) \
+ TS_RESP_verify_signature_flags(p7, certs, store, s_out, 0)
/* Context structure for the generic verify method. */
@@ -635,6 +639,8 @@
#define TS_VFY_SIGNER (1u << 6)
/* Verify if the TSA name field equals to the user provided name. */
#define TS_VFY_TSA_NAME (1u << 7)
+/* Verify and validate the signer certificate chain */
+#define TS_VFY_CHAIN (1u << 8)
/* You can use the following convenience constants. */
#define TS_VFY_ALL_IMPRINT (TS_VFY_SIGNATURE \
@@ -643,14 +649,16 @@
| TS_VFY_IMPRINT \
| TS_VFY_NONCE \
| TS_VFY_SIGNER \
- | TS_VFY_TSA_NAME)
+ | TS_VFY_TSA_NAME \
+ | TS_VFY_CHAIN)
#define TS_VFY_ALL_DATA (TS_VFY_SIGNATURE \
| TS_VFY_VERSION \
| TS_VFY_POLICY \
| TS_VFY_DATA \
| TS_VFY_NONCE \
| TS_VFY_SIGNER \
- | TS_VFY_TSA_NAME)
+ | TS_VFY_TSA_NAME \
+ | TS_VFY_CHAIN)
typedef struct TS_verify_ctx
{
Index: crypto/ts/ts_rsp_sign.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ts/ts_rsp_sign.c,v
retrieving revision 1.6
diff -u -r1.6 ts_rsp_sign.c
--- crypto/ts/ts_rsp_sign.c 19 Mar 2006 21:09:48 -0000 1.6
+++ crypto/ts/ts_rsp_sign.c 29 Dec 2010 17:33:08 -0000
@@ -80,6 +80,8 @@
ASN1_OBJECT *policy);
static int TS_RESP_process_extensions(TS_RESP_CTX *ctx);
static int TS_RESP_sign(TS_RESP_CTX *ctx);
+static int int_TS_RESP_create_response(TS_RESP_CTX *ctx, TS_REQ *req);
+static TS_RESP *TS_RESP_finalize(int result, TS_RESP_CTX *ctx);
static ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert,
STACK_OF(X509) *certs);
@@ -414,24 +416,35 @@
return 1;
}
-/* Main entry method of the response generation. */
-TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
+static TS_RESP *TS_RESP_finalize(int result, TS_RESP_CTX *ctx)
{
- ASN1_OBJECT *policy;
TS_RESP *response;
- int result = 0;
-
- TS_RESP_CTX_init(ctx);
-
- /* Creating the response object. */
- if (!(ctx->response = TS_RESP_new()))
+ if (!result)
{
- TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE);
- goto end;
+ TSerr(TS_F_TS_RESP_CREATE_RESPONSE, TS_R_RESPONSE_SETUP_ERROR);
+ if (ctx->response != NULL)
+ {
+ if (TS_RESP_CTX_set_status_info_cond(ctx,
+ TS_STATUS_REJECTION, "Error during response "
+ "generation.") == 0)
+ {
+ TS_RESP_free(ctx->response);
+ ctx->response = NULL;
+ }
+ }
}
+ response = ctx->response;
+ ctx->response = NULL; /* Ownership will be returned to caller. */
+ TS_RESP_CTX_cleanup(ctx);
+ return response;
+ }
- /* Parsing DER request. */
- if (!(ctx->request = d2i_TS_REQ_bio(req_bio, NULL)))
+static int int_TS_RESP_create_response(TS_RESP_CTX *ctx, TS_REQ *req)
+ {
+ ASN1_OBJECT *policy;
+ int result = 0;
+
+ if (!(ctx->request = req))
{
TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
"Bad request format or "
@@ -463,24 +476,52 @@
/* Everything was successful. */
result = 1;
end:
- if (!result)
+ return result;
+ }
+
+/* Main entry method of the response generation. */
+TS_RESP *TS_RESP_create_response_req(TS_RESP_CTX *ctx, TS_REQ *req)
+ {
+ int result = 0;
+ TS_RESP_CTX_init(ctx);
+
+ /* Creating the response object. */
+ if (!(ctx->response = TS_RESP_new()))
{
- TSerr(TS_F_TS_RESP_CREATE_RESPONSE, TS_R_RESPONSE_SETUP_ERROR);
- if (ctx->response != NULL)
- {
- if (TS_RESP_CTX_set_status_info_cond(ctx,
- TS_STATUS_REJECTION, "Error during response "
- "generation.") == 0)
- {
- TS_RESP_free(ctx->response);
- ctx->response = NULL;
- }
- }
+ TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE);
+ goto end;
}
- response = ctx->response;
- ctx->response = NULL; /* Ownership will be returned to caller. */
- TS_RESP_CTX_cleanup(ctx);
- return response;
+ result = int_TS_RESP_create_response(ctx, req);
+end:
+ ctx->request = NULL; /* Ownership returned to caller. */
+ return TS_RESP_finalize (result, ctx);
+ }
+
+TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
+ {
+ int result = 0;
+ TS_REQ *req;
+ TS_RESP_CTX_init(ctx);
+
+ /* Creating the response object. */
+ if (!(ctx->response = TS_RESP_new()))
+ {
+ TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ /* Parsing DER request. */
+ if (!(req = d2i_TS_REQ_bio(req_bio, NULL)))
+ {
+ TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+ "Bad request format or "
+ "system error.");
+ TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT);
+ goto end;
+ }
+
+ result = int_TS_RESP_create_response(ctx, req);
+end:
+ return TS_RESP_finalize (result, ctx);
}
/* Initializes the variable part of the context. */
Index: crypto/ts/ts_rsp_verify.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ts/ts_rsp_verify.c,v
retrieving revision 1.6
diff -u -r1.6 ts_rsp_verify.c
--- crypto/ts/ts_rsp_verify.c 23 Sep 2009 23:43:48 -0000 1.6
+++ crypto/ts/ts_rsp_verify.c 29 Dec 2010 17:33:08 -0000
@@ -66,7 +66,8 @@
static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
X509 *signer, STACK_OF(X509) **chain);
-static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain);
+static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain,
+ int validate_chain);
static ESS_SIGNING_CERT *ESS_get_signing_cert(PKCS7_SIGNER_INFO *si);
static int TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509_CINF *cinfo);
@@ -137,8 +138,9 @@
* - Verify the signature value.
* - Returns the signer certificate in 'signer', if 'signer' is not NULL.
*/
-int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
- X509_STORE *store, X509 **signer_out)
+int TS_RESP_verify_signature_flags(PKCS7 *token, STACK_OF(X509) *certs,
+ X509_STORE *store, X509 **signer_out,
+ unsigned flags)
{
STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL;
PKCS7_SIGNER_INFO *si;
@@ -186,12 +188,34 @@
if (!signers || sk_X509_num(signers) != 1) goto err;
signer = sk_X509_value(signers, 0);
- /* Now verify the certificate. */
- if (!TS_verify_cert(store, certs, signer, &chain)) goto err;
+ /* Now verify the certificate if requested. */
+ if ((flags & TS_VFY_CHAIN)
+ && !TS_verify_cert(store, certs, signer, &chain))
+ {
+ goto err;
+ }
+ else
+ {
+ /* simply check if the signer certificate has extended
+ key usage timeStamping */
+ if (!X509_check_purpose(signer,
+ X509_PURPOSE_TIMESTAMP_SIGN,
+ 0))
+ {
+ goto err;
+ }
+ if (!(chain = sk_X509_new_null()))
+ {
+ goto err;
+ }
+ sk_X509_push(chain, signer);
+ CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
+ }
/* Check if the signer certificate is consistent with the
ESS extension. */
- if (!TS_check_signing_certs(si, chain)) goto err;
+ if (!TS_check_signing_certs(si, chain, (flags & TS_VFY_CHAIN)))
+ goto err;
/* Creating the message digest. */
p7bio = PKCS7_dataInit(token, NULL);
@@ -259,7 +283,8 @@
return ret;
}
-static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain)
+static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain,
+ int validate_chain)
{
ESS_SIGNING_CERT *ss = ESS_get_signing_cert(si);
STACK_OF(ESS_CERT_ID) *cert_ids = NULL;
@@ -275,7 +300,7 @@
/* Check the other certificates of the chain if there are more
than one certificate ids in cert_ids. */
- if (sk_ESS_CERT_ID_num(cert_ids) > 1)
+ if (validate_chain && sk_ESS_CERT_ID_num(cert_ids) > 1)
{
/* All the certificates of the chain must be in cert_ids. */
for (i = 1; i < sk_X509_num(chain); ++i)
@@ -417,8 +442,8 @@
/* Verify the signature. */
if ((ctx->flags & TS_VFY_SIGNATURE)
- && !TS_RESP_verify_signature(token, ctx->certs, ctx->store,
- &signer))
+ && !TS_RESP_verify_signature_flags(token, ctx->certs, ctx->store,
+ &signer, ctx->flags))
goto err;
/* Check version number of response. */