From f0ef20bf386b5c37ba5a4ce5c1de9a819bbeffb2 Mon Sep 17 00:00:00 2001 From: Marek Klein Date: Tue, 1 Mar 2016 16:32:10 +0000 Subject: [PATCH] Added support for ESSCertIDv2 Reviewed-by: Rich Salz Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/771) --- apps/openssl-vms.cnf | 2 + apps/openssl.cnf | 2 + apps/ts.c | 2 + crypto/objects/obj_dat.h | 15 ++-- crypto/objects/obj_mac.num | 1 + crypto/objects/objects.txt | 1 + crypto/ts/ts_asn1.c | 17 ++++ crypto/ts/ts_conf.c | 25 ++++++ crypto/ts/ts_err.c | 8 +- crypto/ts/ts_lcl.h | 28 ++++++ crypto/ts/ts_rsp_sign.c | 174 ++++++++++++++++++++++++++++++++++--- crypto/ts/ts_rsp_verify.c | 99 +++++++++++++++++---- doc/man1/ts.pod | 8 +- include/openssl/obj_mac.h | 4 + include/openssl/ts.h | 27 ++++++ test/CAtsa.cnf | 2 + util/indent.pro | 3 + util/libcrypto.num | 12 +++ 18 files changed, 396 insertions(+), 34 deletions(-) diff --git a/apps/openssl-vms.cnf b/apps/openssl-vms.cnf index 0092a650cb..a3ca393018 100644 --- a/apps/openssl-vms.cnf +++ b/apps/openssl-vms.cnf @@ -344,3 +344,5 @@ tsa_name = yes # Must the TSA name be included in the reply? # (optional, default: no) ess_cert_id_chain = no # Must the ESS cert id chain be included? # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) diff --git a/apps/openssl.cnf b/apps/openssl.cnf index b3e7444e5f..32ee9e9fbb 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -344,3 +344,5 @@ tsa_name = yes # Must the TSA name be included in the reply? # (optional, default: no) ess_cert_id_chain = no # Must the ESS cert id chain be included? # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) diff --git a/apps/ts.c b/apps/ts.c index 0db6b509f8..e816c32a1f 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -709,6 +709,8 @@ static TS_RESP *create_response(CONF *conf, const char *section, const char *eng 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)) diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 93843e16c2..d1942c0fa4 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -10,7 +10,7 @@ */ /* Serialized OID's */ -static const unsigned char so[6900] = { +static const unsigned char so[6911] = { 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ @@ -976,9 +976,10 @@ static const unsigned char so[6900] = { 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0D, /* [ 6872] OBJ_aria_256_cfb128 */ 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0E, /* [ 6881] OBJ_aria_256_ofb128 */ 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0F, /* [ 6890] OBJ_aria_256_ctr */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1E, /* [ 6899] OBJ_id_smime_aa_signingCertificateV2 */ }; -#define NUM_NID 1086 +#define NUM_NID 1087 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -2066,9 +2067,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"ARIA-128-CFB8", "aria-128-cfb8", NID_aria_128_cfb8}, {"ARIA-192-CFB8", "aria-192-cfb8", NID_aria_192_cfb8}, {"ARIA-256-CFB8", "aria-256-cfb8", NID_aria_256_cfb8}, + {"id-smime-aa-signingCertificateV2", "id-smime-aa-signingCertificateV2", NID_id_smime_aa_signingCertificateV2, 11, &so[6899]}, }; -#define NUM_SN 1077 +#define NUM_SN 1078 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -2712,6 +2714,7 @@ static const unsigned int sn_objs[NUM_SN] = { 213, /* "id-smime-aa-securityLabel" */ 239, /* "id-smime-aa-signatureType" */ 223, /* "id-smime-aa-signingCertificate" */ + 1086, /* "id-smime-aa-signingCertificateV2" */ 224, /* "id-smime-aa-smimeEncryptCerts" */ 225, /* "id-smime-aa-timeStampToken" */ 192, /* "id-smime-alg" */ @@ -3149,7 +3152,7 @@ static const unsigned int sn_objs[NUM_SN] = { 160, /* "x509Crl" */ }; -#define NUM_LN 1077 +#define NUM_LN 1078 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ @@ -3786,6 +3789,7 @@ static const unsigned int ln_objs[NUM_LN] = { 213, /* "id-smime-aa-securityLabel" */ 239, /* "id-smime-aa-signatureType" */ 223, /* "id-smime-aa-signingCertificate" */ + 1086, /* "id-smime-aa-signingCertificateV2" */ 224, /* "id-smime-aa-smimeEncryptCerts" */ 225, /* "id-smime-aa-timeStampToken" */ 192, /* "id-smime-alg" */ @@ -4230,7 +4234,7 @@ static const unsigned int ln_objs[NUM_LN] = { 125, /* "zlib compression" */ }; -#define NUM_OBJ 971 +#define NUM_OBJ 972 static const unsigned int obj_objs[NUM_OBJ] = { 0, /* OBJ_undef 0 */ 181, /* OBJ_iso 1 */ @@ -5173,6 +5177,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 238, /* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */ 239, /* OBJ_id_smime_aa_signatureType 1 2 840 113549 1 9 16 2 28 */ 240, /* OBJ_id_smime_aa_dvcs_dvc 1 2 840 113549 1 9 16 2 29 */ + 1086, /* OBJ_id_smime_aa_signingCertificateV2 1 2 840 113549 1 9 16 2 30 */ 241, /* OBJ_id_smime_alg_ESDHwith3DES 1 2 840 113549 1 9 16 3 1 */ 242, /* OBJ_id_smime_alg_ESDHwithRC2 1 2 840 113549 1 9 16 3 2 */ 243, /* OBJ_id_smime_alg_3DESwrap 1 2 840 113549 1 9 16 3 3 */ diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 270e7e51a6..ca8dcdb7e7 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1083,3 +1083,4 @@ aria_256_cfb1 1082 aria_128_cfb8 1083 aria_192_cfb8 1084 aria_256_cfb8 1085 +id_smime_aa_signingCertificateV2 1086 diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 442b39caa3..f19c5ce286 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -294,6 +294,7 @@ id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp id-smime-aa 28 : id-smime-aa-signatureType id-smime-aa 29 : id-smime-aa-dvcs-dvc +id-smime-aa 30 : id-smime-aa-signingCertificateV2 # S/MIME Algorithm Identifiers # obsolete diff --git a/crypto/ts/ts_asn1.c b/crypto/ts/ts_asn1.c index e60675ab72..8707207082 100644 --- a/crypto/ts/ts_asn1.c +++ b/crypto/ts/ts_asn1.c @@ -225,6 +225,23 @@ ASN1_SEQUENCE(ESS_SIGNING_CERT) = { IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT) IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT) +ASN1_SEQUENCE(ESS_CERT_ID_V2) = { + ASN1_OPT(ESS_CERT_ID_V2, hash_alg, X509_ALGOR), + ASN1_SIMPLE(ESS_CERT_ID_V2, hash, ASN1_OCTET_STRING), + ASN1_OPT(ESS_CERT_ID_V2, issuer_serial, ESS_ISSUER_SERIAL) +} static_ASN1_SEQUENCE_END(ESS_CERT_ID_V2) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID_V2) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2) + +ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = { + ASN1_SEQUENCE_OF(ESS_SIGNING_CERT_V2, cert_ids, ESS_CERT_ID_V2), + ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT_V2, policy_info, POLICYINFO) +} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT_V2) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT_V2) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2) + /* Getting encapsulated TS_TST_INFO object from PKCS7. */ TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token) { diff --git a/crypto/ts/ts_conf.c b/crypto/ts/ts_conf.c index f5f3934dfd..625089a59b 100644 --- a/crypto/ts/ts_conf.c +++ b/crypto/ts/ts_conf.c @@ -37,6 +37,7 @@ #define ENV_CLOCK_PRECISION_DIGITS "clock_precision_digits" #define ENV_VALUE_YES "yes" #define ENV_VALUE_NO "no" +#define ENV_ESS_CERT_ID_ALG "ess_cert_id_alg" /* Function definitions for certificate and key loading. */ @@ -466,3 +467,27 @@ int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, return ts_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN, TS_ESS_CERT_ID_CHAIN, ctx); } + +int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, + TS_RESP_CTX *ctx) +{ + int ret = 0; + const EVP_MD *cert_md = NULL; + const char *md = NCONF_get_string(conf, section, ENV_ESS_CERT_ID_ALG); + + if (md == NULL) + md = "sha1"; + + cert_md = EVP_get_digestbyname(md); + if (cert_md == NULL) { + ts_CONF_invalid(section, ENV_ESS_CERT_ID_ALG); + goto err; + } + + if (!TS_RESP_CTX_set_ess_cert_id_digest(ctx, cert_md)) + goto err; + + ret = 1; +err: + return ret; +} diff --git a/crypto/ts/ts_err.c b/crypto/ts/ts_err.c index a6d73a174b..5aed0461b9 100644 --- a/crypto/ts/ts_err.c +++ b/crypto/ts/ts_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -22,8 +22,12 @@ static ERR_STRING_DATA TS_str_functs[] = { {ERR_FUNC(TS_F_DEF_SERIAL_CB), "def_serial_cb"}, {ERR_FUNC(TS_F_DEF_TIME_CB), "def_time_cb"}, {ERR_FUNC(TS_F_ESS_ADD_SIGNING_CERT), "ESS_add_signing_cert"}, + {ERR_FUNC(TS_F_ESS_ADD_SIGNING_CERT_V2), "ess_add_signing_cert_v2"}, {ERR_FUNC(TS_F_ESS_CERT_ID_NEW_INIT), "ess_CERT_ID_new_init"}, + {ERR_FUNC(TS_F_ESS_CERT_ID_V2_NEW_INIT), "ess_cert_id_new_init"}, {ERR_FUNC(TS_F_ESS_SIGNING_CERT_NEW_INIT), "ess_SIGNING_CERT_new_init"}, + {ERR_FUNC(TS_F_ESS_SIGNING_CERT_V2_NEW_INIT), + "ess_signing_cert_V2_new_init"}, {ERR_FUNC(TS_F_INT_TS_RESP_VERIFY_TOKEN), "int_ts_RESP_verify_token"}, {ERR_FUNC(TS_F_PKCS7_TO_TS_TST_INFO), "PKCS7_to_TS_TST_INFO"}, {ERR_FUNC(TS_F_TS_ACCURACY_SET_MICROS), "TS_ACCURACY_set_micros"}, @@ -92,6 +96,8 @@ static ERR_STRING_DATA TS_str_reasons[] = { {ERR_REASON(TS_R_DETACHED_CONTENT), "detached content"}, {ERR_REASON(TS_R_ESS_ADD_SIGNING_CERT_ERROR), "ess add signing cert error"}, + {ERR_REASON(TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR), + "ess add signing cert v2 error"}, {ERR_REASON(TS_R_ESS_SIGNING_CERTIFICATE_ERROR), "ess signing certificate error"}, {ERR_REASON(TS_R_INVALID_NULL_POINTER), "invalid null pointer"}, diff --git a/crypto/ts/ts_lcl.h b/crypto/ts/ts_lcl.h index d0c3cf816e..771784fef7 100644 --- a/crypto/ts/ts_lcl.h +++ b/crypto/ts/ts_lcl.h @@ -131,11 +131,39 @@ struct ESS_signing_cert { STACK_OF(POLICYINFO) *policy_info; }; +/*- + * ESSCertIDv2 ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier + * DEFAULT {algorithm id-sha256}, + * certHash Hash, + * issuerSerial IssuerSerial OPTIONAL + * } + */ + +struct ESS_cert_id_v2_st { + X509_ALGOR *hash_alg; /* Default: SHA-256 */ + ASN1_OCTET_STRING *hash; + ESS_ISSUER_SERIAL *issuer_serial; +}; + +/*- + * SigningCertificateV2 ::= SEQUENCE { + * certs SEQUENCE OF ESSCertIDv2, + * policies SEQUENCE OF PolicyInformation OPTIONAL + * } + */ + +struct ESS_signing_cert_v2_st { + STACK_OF(ESS_CERT_ID_V2) *cert_ids; + STACK_OF(POLICYINFO) *policy_info; +}; + struct TS_resp_ctx { X509 *signer_cert; EVP_PKEY *signer_key; const EVP_MD *signer_md; + const EVP_MD *ess_cert_id_digest; STACK_OF(X509) *certs; /* Certs to include in signed data. */ STACK_OF(ASN1_OBJECT) *policies; /* Acceptable policies. */ ASN1_OBJECT *default_policy; /* It may appear in policies, too. */ diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c index aea7b922a3..76011ada59 100644 --- a/crypto/ts/ts_rsp_sign.c +++ b/crypto/ts/ts_rsp_sign.c @@ -35,7 +35,16 @@ static ESS_SIGNING_CERT *ess_SIGNING_CERT_new_init(X509 *signcert, STACK_OF(X509) *certs); static ESS_CERT_ID *ess_CERT_ID_new_init(X509 *cert, int issuer_needed); static int ts_TST_INFO_content_new(PKCS7 *p7); -static int ESS_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc); +static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc); + +static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg, + X509 *signcert, + STACK_OF(X509) + *certs); +static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg, + X509 *cert, int issuer_needed); +static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si, + ESS_SIGNING_CERT_V2 *sc); static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *, long, long, @@ -628,6 +637,7 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx) PKCS7 *p7 = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(X509) *certs; /* Certificates to include in sc. */ + ESS_SIGNING_CERT_V2 *sc2 = NULL; ESS_SIGNING_CERT *sc = NULL; ASN1_OBJECT *oid; BIO *p7bio = NULL; @@ -671,11 +681,24 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx) } certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL; - if ((sc = ess_SIGNING_CERT_new_init(ctx->signer_cert, certs)) == NULL) - goto err; - if (!ESS_add_signing_cert(si, sc)) { - TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR); - goto err; + if (ctx->ess_cert_id_digest == EVP_sha1()) { + if ((sc = ess_SIGNING_CERT_new_init(ctx->signer_cert, certs)) == NULL) + goto err; + + if (!ess_add_signing_cert(si, sc)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR); + goto err; + } + } else { + sc2 = ess_signing_cert_v2_new_init(ctx->ess_cert_id_digest, + ctx->signer_cert, certs); + if (sc2 == NULL) + goto err; + + if (!ess_add_signing_cert_v2(si, sc2)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR); + goto err; + } } if (!ts_TST_INFO_content_new(p7)) @@ -703,6 +726,7 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx) "Error during signature " "generation."); BIO_free_all(p7bio); + ESS_SIGNING_CERT_V2_free(sc2); ESS_SIGNING_CERT_free(sc); PKCS7_free(p7); return ret; @@ -806,7 +830,7 @@ static int ts_TST_INFO_content_new(PKCS7 *p7) return 0; } -static int ESS_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc) +static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc) { ASN1_STRING *seq = NULL; unsigned char *p, *pp = NULL; @@ -835,9 +859,133 @@ static int ESS_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc) return 0; } -static ASN1_GENERALIZEDTIME -*TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *asn1_time, - long sec, long usec, unsigned precision) +static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg, + X509 *signcert, + STACK_OF(X509) *certs) +{ + ESS_CERT_ID_V2 *cid = NULL; + ESS_SIGNING_CERT_V2 *sc = NULL; + int i; + + if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) + goto err; + if ((cid = ess_cert_id_v2_new_init(hash_alg, signcert, 0)) == NULL) + goto err; + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + goto err; + cid = NULL; + + for (i = 0; i < sk_X509_num(certs); ++i) { + X509 *cert = sk_X509_value(certs, i); + + if ((cid = ess_cert_id_v2_new_init(hash_alg, cert, 1)) == NULL) + goto err; + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + goto err; + cid = NULL; + } + + return sc; + err: + ESS_SIGNING_CERT_V2_free(sc); + ESS_CERT_ID_V2_free(cid); + TSerr(TS_F_ESS_SIGNING_CERT_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg, + X509 *cert, int issuer_needed) +{ + ESS_CERT_ID_V2 *cid = NULL; + GENERAL_NAME *name = NULL; + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = sizeof(hash); + X509_ALGOR *alg = NULL; + + memset(hash, 0, sizeof(hash)); + + if ((cid = ESS_CERT_ID_V2_new()) == NULL) + goto err; + + if (hash_alg != EVP_sha256()) { + alg = X509_ALGOR_new(); + if (alg == NULL) + goto err; + X509_ALGOR_set_md(alg, hash_alg); + if (alg->algorithm == NULL) + goto err; + cid->hash_alg = alg; + alg = NULL; + } else { + cid->hash_alg = NULL; + } + + if (!X509_digest(cert, hash_alg, hash, &hash_len)) + goto err; + + if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) + goto err; + + if (issuer_needed) { + if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) + goto err; + if ((name = GENERAL_NAME_new()) == NULL) + goto err; + name->type = GEN_DIRNAME; + if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) + goto err; + if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) + goto err; + name = NULL; /* Ownership is lost. */ + ASN1_INTEGER_free(cid->issuer_serial->serial); + cid->issuer_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (cid->issuer_serial->serial == NULL) + goto err; + } + + return cid; + err: + X509_ALGOR_free(alg); + GENERAL_NAME_free(name); + ESS_CERT_ID_V2_free(cid); + TSerr(TS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si, + ESS_SIGNING_CERT_V2 *sc) +{ + ASN1_STRING *seq = NULL; + unsigned char *p, *pp = NULL; + int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL); + + if ((pp = OPENSSL_malloc(len)) == NULL) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE); + goto err; + } + + p = pp; + i2d_ESS_SIGNING_CERT_V2(sc, &p); + if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE); + goto err; + } + + OPENSSL_free(pp); + pp = NULL; + return PKCS7_add_signed_attribute(si, + NID_id_smime_aa_signingCertificateV2, + V_ASN1_SEQUENCE, seq); + err: + ASN1_STRING_free(seq); + OPENSSL_free(pp); + return 0; +} + +static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision( + ASN1_GENERALIZEDTIME *asn1_time, long sec, long usec, + unsigned precision) { time_t time_sec = (time_t)sec; struct tm *tm = NULL; @@ -902,3 +1050,9 @@ static ASN1_GENERALIZEDTIME TSerr(TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, TS_R_COULD_NOT_SET_TIME); return NULL; } + +int TS_RESP_CTX_set_ess_cert_id_digest(TS_RESP_CTX *ctx, const EVP_MD *md) +{ + ctx->ess_cert_id_digest = md; + return 1; +} diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 66f5be6f69..9deda81b07 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -37,6 +37,8 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info); static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer); static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name); +static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert); +static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si); /* * This must be large enough to hold all values in ts_status_text (with @@ -201,34 +203,57 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, { ESS_SIGNING_CERT *ss = ess_get_signing_cert(si); STACK_OF(ESS_CERT_ID) *cert_ids = NULL; + ESS_SIGNING_CERT_V2 *ssv2 = ess_get_signing_cert_v2(si); + STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = NULL; X509 *cert; int i = 0; int ret = 0; - if (!ss) - goto err; - cert_ids = ss->cert_ids; - cert = sk_X509_value(chain, 0); - if (ts_find_cert(cert_ids, cert) != 0) - goto err; + if (ss != NULL) { + cert_ids = ss->cert_ids; + cert = sk_X509_value(chain, 0); + if (ts_find_cert(cert_ids, cert) != 0) + goto err; - /* - * 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) { - for (i = 1; i < sk_X509_num(chain); ++i) { - cert = sk_X509_value(chain, i); - if (ts_find_cert(cert_ids, cert) < 0) - goto err; + /* + * 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) { + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ts_find_cert(cert_ids, cert) < 0) + goto err; + } } + } else if (ssv2 != NULL) { + cert_ids_v2 = ssv2->cert_ids; + cert = sk_X509_value(chain, 0); + if (ts_find_cert_v2(cert_ids_v2, cert) != 0) + goto err; + + /* + * Check the other certificates of the chain if there are more than one + * certificate ids in cert_ids. + */ + if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) { + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ts_find_cert_v2(cert_ids_v2, cert) < 0) + goto err; + } + } + } else { + goto err; } + ret = 1; err: if (!ret) TSerr(TS_F_TS_CHECK_SIGNING_CERTS, TS_R_ESS_SIGNING_CERTIFICATE_ERROR); ESS_SIGNING_CERT_free(ss); + ESS_SIGNING_CERT_V2_free(ssv2); return ret; } @@ -243,6 +268,18 @@ static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si) return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); } +static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si) +{ + ASN1_TYPE *attr; + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); + if (attr == NULL) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); +} + /* Returns < 0 if certificate is not found, certificate index otherwise. */ static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) { @@ -272,6 +309,38 @@ static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) return -1; } +/* Returns < 0 if certificate is not found, certificate index otherwise. */ +static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert) +{ + int i; + unsigned char cert_digest[EVP_MAX_MD_SIZE]; + unsigned int len; + + /* Look for cert in the cert_ids vector. */ + for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) { + ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i); + const EVP_MD *md; + + if (cid->hash_alg != NULL) + md = EVP_get_digestbyobj(cid->hash_alg->algorithm); + else + md = EVP_sha256(); + + X509_digest(cert, md, cert_digest, &len); + if (cid->hash->length != (int)len) + return -1; + + if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) { + ESS_ISSUER_SERIAL *is = cid->issuer_serial; + + if (is == NULL || !ts_issuer_serial_cmp(is, cert)) + return i; + } + } + + return -1; +} + static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert) { GENERAL_NAME *issuer; diff --git a/doc/man1/ts.pod b/doc/man1/ts.pod index 2ec9837075..d469b23196 100644 --- a/doc/man1/ts.pod +++ b/doc/man1/ts.pod @@ -503,6 +503,11 @@ be included in the SigningCertificate signed attribute. If this variable is set to no, only the signing certificate identifier is included. Default is no. (Optional) +=item B + +This option specifies the hash function to be used to calculate the TSA's +public key certificate identifier. Default is sha1. (Optional) + =back =head1 EXAMPLES @@ -605,9 +610,6 @@ You could also look at the 'test' directory for more examples. =for comment foreign manuals: procmail(1), perl(1) -If you find any bugs or you have suggestions please write to -Zoltan Glozik . Known issues: - =over 2 =item * diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index d9c45dee01..3762e514cb 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -932,6 +932,10 @@ #define NID_id_smime_aa_dvcs_dvc 240 #define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L +#define SN_id_smime_aa_signingCertificateV2 "id-smime-aa-signingCertificateV2" +#define NID_id_smime_aa_signingCertificateV2 1086 +#define OBJ_id_smime_aa_signingCertificateV2 OBJ_id_smime_aa,30L + #define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" #define NID_id_smime_alg_ESDHwith3DES 241 #define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L diff --git a/include/openssl/ts.h b/include/openssl/ts.h index a5659825fb..ce8341038d 100644 --- a/include/openssl/ts.h +++ b/include/openssl/ts.h @@ -61,6 +61,11 @@ typedef struct ESS_signing_cert ESS_SIGNING_CERT; DEFINE_STACK_OF(ESS_CERT_ID) +typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2; +typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2; + +DEFINE_STACK_OF(ESS_CERT_ID_V2) + typedef struct TS_resp_st TS_RESP; TS_REQ *TS_REQ_new(void); @@ -156,6 +161,21 @@ ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, const unsigned char **pp, long length); ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a); +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new(void); +void ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a); +int i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **pp); +ESS_CERT_ID_V2 *d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a, + const unsigned char **pp, long length); +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *a); + +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new(void); +void ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a); +int i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a, unsigned char **pp); +ESS_SIGNING_CERT_V2 *d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a, + const unsigned char **pp, + long length); +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *a); + int TS_REQ_set_version(TS_REQ *a, long version); long TS_REQ_get_version(const TS_REQ *a); @@ -316,6 +336,7 @@ int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key); int TS_RESP_CTX_set_signer_digest(TS_RESP_CTX *ctx, const EVP_MD *signer_digest); +int TS_RESP_CTX_set_ess_cert_id_digest(TS_RESP_CTX *ctx, const EVP_MD *md); /* This parameter must be set. */ int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy); @@ -528,6 +549,8 @@ int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx); int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx); int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, + TS_RESP_CTX *ctx); /* -------------------------------------------------- */ /* BEGIN ERROR CODES */ @@ -544,8 +567,11 @@ int ERR_load_TS_strings(void); # define TS_F_DEF_SERIAL_CB 110 # define TS_F_DEF_TIME_CB 111 # define TS_F_ESS_ADD_SIGNING_CERT 112 +# define TS_F_ESS_ADD_SIGNING_CERT_V2 147 # define TS_F_ESS_CERT_ID_NEW_INIT 113 +# define TS_F_ESS_CERT_ID_V2_NEW_INIT 156 # define TS_F_ESS_SIGNING_CERT_NEW_INIT 114 +# define TS_F_ESS_SIGNING_CERT_V2_NEW_INIT 157 # define TS_F_INT_TS_RESP_VERIFY_TOKEN 149 # define TS_F_PKCS7_TO_TS_TST_INFO 148 # define TS_F_TS_ACCURACY_SET_MICROS 115 @@ -606,6 +632,7 @@ int ERR_load_TS_strings(void); # define TS_R_COULD_NOT_SET_TIME 115 # define TS_R_DETACHED_CONTENT 134 # define TS_R_ESS_ADD_SIGNING_CERT_ERROR 116 +# define TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR 139 # define TS_R_ESS_SIGNING_CERTIFICATE_ERROR 101 # define TS_R_INVALID_NULL_POINTER 102 # define TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE 117 diff --git a/test/CAtsa.cnf b/test/CAtsa.cnf index ab2f84aa0f..d1642879be 100644 --- a/test/CAtsa.cnf +++ b/test/CAtsa.cnf @@ -144,6 +144,8 @@ tsa_name = yes # Must the TSA name be included in the reply? # (optional, default: no) ess_cert_id_chain = yes # Must the ESS cert id chain be included? # (optional, default: no) +ess_cert_id_alg = sha256 # algorithm to compute certificate + # identifier (optional, default: sha1) [ tsa_config2 ] diff --git a/util/indent.pro b/util/indent.pro index 81590e141e..c147f97854 100644 --- a/util/indent.pro +++ b/util/indent.pro @@ -223,8 +223,10 @@ -T ERR_STATE -T ERR_STRING_DATA -T ESS_CERT_ID +-T ESS_CERT_ID_V2 -T ESS_ISSUER_SERIAL -T ESS_SIGNING_CERT +-T ESS_SIGNING_CERT_V2 -T EVP_AES_HMAC_SHA1 -T EVP_AES_HMAC_SHA256 -T EVP_CIPHER @@ -525,6 +527,7 @@ -T STACK_OF_ENGINE_ -T STACK_OF_ENGINE_CLEANUP_ITEM_ -T STACK_OF_ESS_CERT_ID_ +-T STACK_OF_ESS_CERT_ID_V2_ -T STACK_OF_EVP_PBE_CTL_ -T STACK_OF_EVP_PKEY_ASN1_METHOD_ -T STACK_OF_EVP_PKEY_METHOD_ diff --git a/util/libcrypto.num b/util/libcrypto.num index b136a73500..2e820426e9 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4276,3 +4276,15 @@ X509_CRL_print_ex 4218 1_1_1 EXIST::FUNCTION: X509_SIG_INFO_get 4219 1_1_1 EXIST::FUNCTION: X509_get_signature_info 4220 1_1_1 EXIST::FUNCTION: X509_SIG_INFO_set 4221 1_1_1 EXIST::FUNCTION: +ESS_CERT_ID_V2_free 4222 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_new 4223 1_1_1 EXIST::FUNCTION:TS +d2i_ESS_SIGNING_CERT_V2 4224 1_1_1 EXIST::FUNCTION:TS +i2d_ESS_CERT_ID_V2 4225 1_1_1 EXIST::FUNCTION:TS +ESS_CERT_ID_V2_dup 4226 1_1_1 EXIST::FUNCTION:TS +TS_RESP_CTX_set_ess_cert_id_digest 4227 1_1_1 EXIST::FUNCTION:TS +d2i_ESS_CERT_ID_V2 4228 1_1_1 EXIST::FUNCTION:TS +i2d_ESS_SIGNING_CERT_V2 4229 1_1_1 EXIST::FUNCTION:TS +TS_CONF_set_ess_cert_id_digest 4230 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_free 4231 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_dup 4232 1_1_1 EXIST::FUNCTION:TS +ESS_CERT_ID_V2_new 4233 1_1_1 EXIST::FUNCTION:TS -- 2.25.1