-static int TS_RESP_sign(TS_RESP_CTX *ctx)
- {
- int ret = 0;
- PKCS7 *p7 = NULL;
- PKCS7_SIGNER_INFO *si;
- STACK_OF(X509) *certs; /* Certificates to include in sc. */
- ESS_SIGNING_CERT *sc = NULL;
- ASN1_OBJECT *oid;
- BIO *p7bio = NULL;
- int i;
-
- /* Check if signcert and pkey match. */
- if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) {
- TSerr(TS_F_TS_RESP_SIGN,
- TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
- goto err;
- }
-
- /* Create a new PKCS7 signed object. */
- if (!(p7 = PKCS7_new())) {
- TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!PKCS7_set_type(p7, NID_pkcs7_signed)) goto err;
-
- /* Force SignedData version to be 3 instead of the default 1. */
- if (!ASN1_INTEGER_set(p7->d.sign->version, 3)) goto err;
-
- /* Add signer certificate and optional certificate chain. */
- if (TS_REQ_get_cert_req(ctx->request))
- {
- PKCS7_add_certificate(p7, ctx->signer_cert);
- if (ctx->certs)
- {
- for(i = 0; i < sk_X509_num(ctx->certs); ++i)
- {
- X509 *cert = sk_X509_value(ctx->certs, i);
- PKCS7_add_certificate(p7, cert);
- }
- }
- }
-
- /* Add a new signer info. */
- if (!(si = PKCS7_add_signature(p7, ctx->signer_cert,
- ctx->signer_key, EVP_sha1())))
- {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNATURE_ERROR);
- goto err;
- }
-
- /* Add content type signed attribute to the signer info. */
- oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
- if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
- V_ASN1_OBJECT, oid))
- {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
- goto err;
- }
-
- /* Create the ESS SigningCertificate attribute which contains
- the signer certificate id and optionally the certificate chain. */
- certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL;
- if (!(sc = ESS_SIGNING_CERT_new_init(ctx->signer_cert, certs)))
- goto err;
-
- /* Add SigningCertificate signed attribute to the signer info. */
- if (!ESS_add_signing_cert(si, sc))
- {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR);
- goto err;
- }
-
- /* Add a new empty NID_id_smime_ct_TSTInfo encapsulated content. */
- if (!TS_TST_INFO_content_new(p7)) goto err;
-
- /* Add the DER encoded tst_info to the PKCS7 structure. */
- if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
- TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Convert tst_info to DER. */
- if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info))
- {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
- goto err;
- }
-
- /* Create the signature and add it to the signer info. */
- if (!PKCS7_dataFinal(p7, p7bio))
- {
- TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
- goto err;
- }
-
- /* Set new PKCS7 and TST_INFO objects. */
- TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info);
- p7 = NULL; /* Ownership is lost. */
- ctx->tst_info = NULL; /* Ownership is lost. */
-
- ret = 1;
- err:
- if (!ret)
- TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
- "Error during signature "
- "generation.");
- BIO_free_all(p7bio);
- ESS_SIGNING_CERT_free(sc);
- PKCS7_free(p7);
- return ret;
- }
-
-static ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert,
- STACK_OF(X509) *certs)
- {
- ESS_CERT_ID *cid;
- ESS_SIGNING_CERT *sc = NULL;
- int i;
-
- /* Creating the ESS_CERT_ID stack. */
- if (!(sc = ESS_SIGNING_CERT_new())) goto err;
- if (!sc->cert_ids && !(sc->cert_ids = sk_ESS_CERT_ID_new_null()))
- goto err;
-
- /* Adding the signing certificate id. */
- if (!(cid = ESS_CERT_ID_new_init(signcert, 0))
- || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
- goto err;
- /* Adding the certificate chain ids. */
- for (i = 0; i < sk_X509_num(certs); ++i)
- {
- X509 *cert = sk_X509_value(certs, i);
- if (!(cid = ESS_CERT_ID_new_init(cert, 1))
- || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
- goto err;
- }
-
- return sc;
-err:
- ESS_SIGNING_CERT_free(sc);
- TSerr(TS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
-static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
- {
- ESS_CERT_ID *cid = NULL;
- GENERAL_NAME *name = NULL;
-
- /* Recompute SHA1 hash of certificate if necessary (side effect). */
- X509_check_purpose(cert, -1, 0);
-
- if (!(cid = ESS_CERT_ID_new())) goto err;
- if (!ASN1_OCTET_STRING_set(cid->hash, cert->sha1_hash,
- sizeof(cert->sha1_hash)))
- goto err;
-
- /* Setting the issuer/serial if requested. */
- if (issuer_needed)
- {
- /* Creating issuer/serial structure. */
- if (!cid->issuer_serial
- && !(cid->issuer_serial = ESS_ISSUER_SERIAL_new()))
- goto err;
- /* Creating general name from the certificate issuer. */
- if (!(name = GENERAL_NAME_new())) goto err;
- name->type = GEN_DIRNAME;
- if (!(name->d.dirn = X509_NAME_dup(cert->cert_info->issuer)))
- goto err;
- if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
- goto err;
- name = NULL; /* Ownership is lost. */
- /* Setting the serial number. */
- ASN1_INTEGER_free(cid->issuer_serial->serial);
- if (!(cid->issuer_serial->serial =
- ASN1_INTEGER_dup(cert->cert_info->serialNumber)))
- goto err;
- }
-
- return cid;
-err:
- GENERAL_NAME_free(name);
- ESS_CERT_ID_free(cid);
- TSerr(TS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
-static int TS_TST_INFO_content_new(PKCS7 *p7)
- {
- PKCS7 *ret = NULL;
- ASN1_OCTET_STRING *octet_string = NULL;
-
- /* Create new encapsulated NID_id_smime_ct_TSTInfo content. */
- if (!(ret = PKCS7_new())) goto err;
- if (!(ret->d.other = ASN1_TYPE_new())) goto err;
- ret->type = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
- if (!(octet_string = ASN1_OCTET_STRING_new())) goto err;
- ASN1_TYPE_set(ret->d.other, V_ASN1_OCTET_STRING, octet_string);
- octet_string = NULL;
-
- /* Add encapsulated content to signed PKCS7 structure. */
- if (!PKCS7_set_content(p7, ret)) goto err;
-
- return 1;
+static int ts_RESP_sign(TS_RESP_CTX *ctx)
+{
+ int ret = 0;
+ 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;
+ int i;
+
+ if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) {
+ TSerr(TS_F_TS_RESP_SIGN, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+ goto err;
+ }
+
+ if ((p7 = PKCS7_new()) == NULL) {
+ TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!PKCS7_set_type(p7, NID_pkcs7_signed))
+ goto err;
+ if (!ASN1_INTEGER_set(p7->d.sign->version, 3))
+ goto err;
+
+ if (ctx->request->cert_req) {
+ PKCS7_add_certificate(p7, ctx->signer_cert);
+ if (ctx->certs) {
+ for (i = 0; i < sk_X509_num(ctx->certs); ++i) {
+ X509 *cert = sk_X509_value(ctx->certs, i);
+ PKCS7_add_certificate(p7, cert);
+ }
+ }
+ }
+
+ if ((si = PKCS7_add_signature(p7, ctx->signer_cert,
+ ctx->signer_key, ctx->signer_md)) == NULL) {
+ TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNATURE_ERROR);
+ goto err;
+ }
+
+ oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
+ if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
+ V_ASN1_OBJECT, oid)) {
+ TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
+ goto err;
+ }
+
+ certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL;
+ if (ctx->ess_cert_id_digest == NULL
+ || ctx->ess_cert_id_digest == EVP_sha1()) {
+ if ((sc = ESS_SIGNING_CERT_new_init(ctx->signer_cert, certs, 0)) == NULL)
+ goto err;
+
+ if (!ESS_SIGNING_CERT_add(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, 0);
+ if (sc2 == NULL)
+ goto err;
+
+ if (!ESS_SIGNING_CERT_V2_add(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))
+ goto err;
+ if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
+ TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info)) {
+ TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
+ goto err;
+ }
+ if (!PKCS7_dataFinal(p7, p7bio)) {
+ TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
+ goto err;
+ }
+ TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info);
+ p7 = NULL; /* Ownership is lost. */
+ ctx->tst_info = NULL; /* Ownership is lost. */
+
+ ret = 1;