1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
11e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
12e1051a39Sopenharmony_ci#include <openssl/pem.h>
13e1051a39Sopenharmony_ci#include <openssl/x509.h>
14e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
15e1051a39Sopenharmony_ci#include <openssl/err.h>
16e1051a39Sopenharmony_ci#include <openssl/cms.h>
17e1051a39Sopenharmony_ci#include <openssl/ess.h>
18e1051a39Sopenharmony_ci#include "internal/sizes.h"
19e1051a39Sopenharmony_ci#include "crypto/asn1.h"
20e1051a39Sopenharmony_ci#include "crypto/evp.h"
21e1051a39Sopenharmony_ci#include "crypto/ess.h"
22e1051a39Sopenharmony_ci#include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
23e1051a39Sopenharmony_ci#include "cms_local.h"
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci/* CMS SignedData Utilities */
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_cistatic CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
28e1051a39Sopenharmony_ci{
29e1051a39Sopenharmony_ci    if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
30e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
31e1051a39Sopenharmony_ci        return NULL;
32e1051a39Sopenharmony_ci    }
33e1051a39Sopenharmony_ci    return cms->d.signedData;
34e1051a39Sopenharmony_ci}
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cistatic CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
37e1051a39Sopenharmony_ci{
38e1051a39Sopenharmony_ci    if (cms->d.other == NULL) {
39e1051a39Sopenharmony_ci        cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
40e1051a39Sopenharmony_ci        if (!cms->d.signedData) {
41e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
42e1051a39Sopenharmony_ci            return NULL;
43e1051a39Sopenharmony_ci        }
44e1051a39Sopenharmony_ci        cms->d.signedData->version = 1;
45e1051a39Sopenharmony_ci        cms->d.signedData->encapContentInfo->eContentType =
46e1051a39Sopenharmony_ci            OBJ_nid2obj(NID_pkcs7_data);
47e1051a39Sopenharmony_ci        cms->d.signedData->encapContentInfo->partial = 1;
48e1051a39Sopenharmony_ci        ASN1_OBJECT_free(cms->contentType);
49e1051a39Sopenharmony_ci        cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
50e1051a39Sopenharmony_ci        return cms->d.signedData;
51e1051a39Sopenharmony_ci    }
52e1051a39Sopenharmony_ci    return cms_get0_signed(cms);
53e1051a39Sopenharmony_ci}
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci/* Just initialise SignedData e.g. for certs only structure */
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_ciint CMS_SignedData_init(CMS_ContentInfo *cms)
58e1051a39Sopenharmony_ci{
59e1051a39Sopenharmony_ci    if (cms_signed_data_init(cms))
60e1051a39Sopenharmony_ci        return 1;
61e1051a39Sopenharmony_ci    else
62e1051a39Sopenharmony_ci        return 0;
63e1051a39Sopenharmony_ci}
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci/* Check structures and fixup version numbers (if necessary) */
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_cistatic void cms_sd_set_version(CMS_SignedData *sd)
69e1051a39Sopenharmony_ci{
70e1051a39Sopenharmony_ci    int i;
71e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
72e1051a39Sopenharmony_ci    CMS_RevocationInfoChoice *rch;
73e1051a39Sopenharmony_ci    CMS_SignerInfo *si;
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
76e1051a39Sopenharmony_ci        cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
77e1051a39Sopenharmony_ci        if (cch->type == CMS_CERTCHOICE_OTHER) {
78e1051a39Sopenharmony_ci            if (sd->version < 5)
79e1051a39Sopenharmony_ci                sd->version = 5;
80e1051a39Sopenharmony_ci        } else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
81e1051a39Sopenharmony_ci            if (sd->version < 4)
82e1051a39Sopenharmony_ci                sd->version = 4;
83e1051a39Sopenharmony_ci        } else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
84e1051a39Sopenharmony_ci            if (sd->version < 3)
85e1051a39Sopenharmony_ci                sd->version = 3;
86e1051a39Sopenharmony_ci        }
87e1051a39Sopenharmony_ci    }
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
90e1051a39Sopenharmony_ci        rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
91e1051a39Sopenharmony_ci        if (rch->type == CMS_REVCHOICE_OTHER) {
92e1051a39Sopenharmony_ci            if (sd->version < 5)
93e1051a39Sopenharmony_ci                sd->version = 5;
94e1051a39Sopenharmony_ci        }
95e1051a39Sopenharmony_ci    }
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
98e1051a39Sopenharmony_ci        && (sd->version < 3))
99e1051a39Sopenharmony_ci        sd->version = 3;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
102e1051a39Sopenharmony_ci        si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
103e1051a39Sopenharmony_ci        if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
104e1051a39Sopenharmony_ci            if (si->version < 3)
105e1051a39Sopenharmony_ci                si->version = 3;
106e1051a39Sopenharmony_ci            if (sd->version < 3)
107e1051a39Sopenharmony_ci                sd->version = 3;
108e1051a39Sopenharmony_ci        } else if (si->version < 1)
109e1051a39Sopenharmony_ci            si->version = 1;
110e1051a39Sopenharmony_ci    }
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci    if (sd->version < 1)
113e1051a39Sopenharmony_ci        sd->version = 1;
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci}
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci/*
118e1051a39Sopenharmony_ci * RFC 5652 Section 11.1 Content Type
119e1051a39Sopenharmony_ci * The content-type attribute within signed-data MUST
120e1051a39Sopenharmony_ci *   1) be present if there are signed attributes
121e1051a39Sopenharmony_ci *   2) match the content type in the signed-data,
122e1051a39Sopenharmony_ci *   3) be a signed attribute.
123e1051a39Sopenharmony_ci *   4) not have more than one copy of the attribute.
124e1051a39Sopenharmony_ci *
125e1051a39Sopenharmony_ci * Note that since the CMS_SignerInfo_sign() always adds the "signing time"
126e1051a39Sopenharmony_ci * attribute, the content type attribute MUST be added also.
127e1051a39Sopenharmony_ci * Assumptions: This assumes that the attribute does not already exist.
128e1051a39Sopenharmony_ci */
129e1051a39Sopenharmony_cistatic int cms_set_si_contentType_attr(CMS_ContentInfo *cms, CMS_SignerInfo *si)
130e1051a39Sopenharmony_ci{
131e1051a39Sopenharmony_ci    ASN1_OBJECT *ctype = cms->d.signedData->encapContentInfo->eContentType;
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_ci    /* Add the contentType attribute */
134e1051a39Sopenharmony_ci    return CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
135e1051a39Sopenharmony_ci                                       V_ASN1_OBJECT, ctype, -1) > 0;
136e1051a39Sopenharmony_ci}
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci/* Copy an existing messageDigest value */
139e1051a39Sopenharmony_ci
140e1051a39Sopenharmony_cistatic int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
141e1051a39Sopenharmony_ci{
142e1051a39Sopenharmony_ci    STACK_OF(CMS_SignerInfo) *sinfos;
143e1051a39Sopenharmony_ci    CMS_SignerInfo *sitmp;
144e1051a39Sopenharmony_ci    int i;
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci    sinfos = CMS_get0_SignerInfos(cms);
147e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
148e1051a39Sopenharmony_ci        ASN1_OCTET_STRING *messageDigest;
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci        sitmp = sk_CMS_SignerInfo_value(sinfos, i);
151e1051a39Sopenharmony_ci        if (sitmp == si)
152e1051a39Sopenharmony_ci            continue;
153e1051a39Sopenharmony_ci        if (CMS_signed_get_attr_count(sitmp) < 0)
154e1051a39Sopenharmony_ci            continue;
155e1051a39Sopenharmony_ci        if (OBJ_cmp(si->digestAlgorithm->algorithm,
156e1051a39Sopenharmony_ci                    sitmp->digestAlgorithm->algorithm))
157e1051a39Sopenharmony_ci            continue;
158e1051a39Sopenharmony_ci        messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
159e1051a39Sopenharmony_ci                                                    OBJ_nid2obj
160e1051a39Sopenharmony_ci                                                    (NID_pkcs9_messageDigest),
161e1051a39Sopenharmony_ci                                                    -3, V_ASN1_OCTET_STRING);
162e1051a39Sopenharmony_ci        if (!messageDigest) {
163e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
164e1051a39Sopenharmony_ci            return 0;
165e1051a39Sopenharmony_ci        }
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci        if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
168e1051a39Sopenharmony_ci                                        V_ASN1_OCTET_STRING,
169e1051a39Sopenharmony_ci                                        messageDigest, -1))
170e1051a39Sopenharmony_ci            return 1;
171e1051a39Sopenharmony_ci        else
172e1051a39Sopenharmony_ci            return 0;
173e1051a39Sopenharmony_ci    }
174e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
175e1051a39Sopenharmony_ci    return 0;
176e1051a39Sopenharmony_ci}
177e1051a39Sopenharmony_ci
178e1051a39Sopenharmony_ciint ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
179e1051a39Sopenharmony_ci                                   int type, const CMS_CTX *ctx)
180e1051a39Sopenharmony_ci{
181e1051a39Sopenharmony_ci    switch (type) {
182e1051a39Sopenharmony_ci    case CMS_SIGNERINFO_ISSUER_SERIAL:
183e1051a39Sopenharmony_ci        if (!ossl_cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
184e1051a39Sopenharmony_ci            return 0;
185e1051a39Sopenharmony_ci        break;
186e1051a39Sopenharmony_ci
187e1051a39Sopenharmony_ci    case CMS_SIGNERINFO_KEYIDENTIFIER:
188e1051a39Sopenharmony_ci        if (!ossl_cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
189e1051a39Sopenharmony_ci            return 0;
190e1051a39Sopenharmony_ci        break;
191e1051a39Sopenharmony_ci
192e1051a39Sopenharmony_ci    default:
193e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_ID);
194e1051a39Sopenharmony_ci        return 0;
195e1051a39Sopenharmony_ci    }
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    sid->type = type;
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci    return 1;
200e1051a39Sopenharmony_ci}
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ciint ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
203e1051a39Sopenharmony_ci                                             ASN1_OCTET_STRING **keyid,
204e1051a39Sopenharmony_ci                                             X509_NAME **issuer,
205e1051a39Sopenharmony_ci                                             ASN1_INTEGER **sno)
206e1051a39Sopenharmony_ci{
207e1051a39Sopenharmony_ci    if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
208e1051a39Sopenharmony_ci        if (issuer)
209e1051a39Sopenharmony_ci            *issuer = sid->d.issuerAndSerialNumber->issuer;
210e1051a39Sopenharmony_ci        if (sno)
211e1051a39Sopenharmony_ci            *sno = sid->d.issuerAndSerialNumber->serialNumber;
212e1051a39Sopenharmony_ci    } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
213e1051a39Sopenharmony_ci        if (keyid)
214e1051a39Sopenharmony_ci            *keyid = sid->d.subjectKeyIdentifier;
215e1051a39Sopenharmony_ci    } else
216e1051a39Sopenharmony_ci        return 0;
217e1051a39Sopenharmony_ci    return 1;
218e1051a39Sopenharmony_ci}
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_ciint ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
221e1051a39Sopenharmony_ci{
222e1051a39Sopenharmony_ci    if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL)
223e1051a39Sopenharmony_ci        return ossl_cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert);
224e1051a39Sopenharmony_ci    else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
225e1051a39Sopenharmony_ci        return ossl_cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
226e1051a39Sopenharmony_ci    else
227e1051a39Sopenharmony_ci        return -1;
228e1051a39Sopenharmony_ci}
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_cistatic int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
231e1051a39Sopenharmony_ci{
232e1051a39Sopenharmony_ci    EVP_PKEY *pkey = si->pkey;
233e1051a39Sopenharmony_ci    int i;
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ci    if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC"))
236e1051a39Sopenharmony_ci        return ossl_cms_ecdsa_dsa_sign(si, cmd);
237e1051a39Sopenharmony_ci    else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
238e1051a39Sopenharmony_ci        return ossl_cms_rsa_sign(si, cmd);
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_ci    /* Something else? We'll give engines etc a chance to handle this */
241e1051a39Sopenharmony_ci    if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
242e1051a39Sopenharmony_ci        return 1;
243e1051a39Sopenharmony_ci    i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
244e1051a39Sopenharmony_ci    if (i == -2) {
245e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
246e1051a39Sopenharmony_ci        return 0;
247e1051a39Sopenharmony_ci    }
248e1051a39Sopenharmony_ci    if (i <= 0) {
249e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
250e1051a39Sopenharmony_ci        return 0;
251e1051a39Sopenharmony_ci    }
252e1051a39Sopenharmony_ci    return 1;
253e1051a39Sopenharmony_ci}
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ci/* Add SigningCertificate signed attribute to the signer info. */
256e1051a39Sopenharmony_cistatic int ossl_cms_add1_signing_cert(CMS_SignerInfo *si,
257e1051a39Sopenharmony_ci                                      const ESS_SIGNING_CERT *sc)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    ASN1_STRING *seq = NULL;
260e1051a39Sopenharmony_ci    unsigned char *p, *pp = NULL;
261e1051a39Sopenharmony_ci    int ret, len = i2d_ESS_SIGNING_CERT(sc, NULL);
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ci    if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
264e1051a39Sopenharmony_ci        return 0;
265e1051a39Sopenharmony_ci
266e1051a39Sopenharmony_ci    p = pp;
267e1051a39Sopenharmony_ci    i2d_ESS_SIGNING_CERT(sc, &p);
268e1051a39Sopenharmony_ci    if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
269e1051a39Sopenharmony_ci        ASN1_STRING_free(seq);
270e1051a39Sopenharmony_ci        OPENSSL_free(pp);
271e1051a39Sopenharmony_ci        return 0;
272e1051a39Sopenharmony_ci    }
273e1051a39Sopenharmony_ci    OPENSSL_free(pp);
274e1051a39Sopenharmony_ci    ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificate,
275e1051a39Sopenharmony_ci                                      V_ASN1_SEQUENCE, seq, -1);
276e1051a39Sopenharmony_ci    ASN1_STRING_free(seq);
277e1051a39Sopenharmony_ci    return ret;
278e1051a39Sopenharmony_ci}
279e1051a39Sopenharmony_ci
280e1051a39Sopenharmony_ci/* Add SigningCertificateV2 signed attribute to the signer info. */
281e1051a39Sopenharmony_cistatic int ossl_cms_add1_signing_cert_v2(CMS_SignerInfo *si,
282e1051a39Sopenharmony_ci                                         const ESS_SIGNING_CERT_V2 *sc)
283e1051a39Sopenharmony_ci{
284e1051a39Sopenharmony_ci    ASN1_STRING *seq = NULL;
285e1051a39Sopenharmony_ci    unsigned char *p, *pp = NULL;
286e1051a39Sopenharmony_ci    int ret, len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci    if (len <= 0 || (pp = OPENSSL_malloc(len)) == NULL)
289e1051a39Sopenharmony_ci        return 0;
290e1051a39Sopenharmony_ci
291e1051a39Sopenharmony_ci    p = pp;
292e1051a39Sopenharmony_ci    i2d_ESS_SIGNING_CERT_V2(sc, &p);
293e1051a39Sopenharmony_ci    if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
294e1051a39Sopenharmony_ci        ASN1_STRING_free(seq);
295e1051a39Sopenharmony_ci        OPENSSL_free(pp);
296e1051a39Sopenharmony_ci        return 0;
297e1051a39Sopenharmony_ci    }
298e1051a39Sopenharmony_ci    OPENSSL_free(pp);
299e1051a39Sopenharmony_ci    ret = CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificateV2,
300e1051a39Sopenharmony_ci                                      V_ASN1_SEQUENCE, seq, -1);
301e1051a39Sopenharmony_ci    ASN1_STRING_free(seq);
302e1051a39Sopenharmony_ci    return ret;
303e1051a39Sopenharmony_ci}
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ciCMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
306e1051a39Sopenharmony_ci                                X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
307e1051a39Sopenharmony_ci                                unsigned int flags)
308e1051a39Sopenharmony_ci{
309e1051a39Sopenharmony_ci    CMS_SignedData *sd;
310e1051a39Sopenharmony_ci    CMS_SignerInfo *si = NULL;
311e1051a39Sopenharmony_ci    X509_ALGOR *alg;
312e1051a39Sopenharmony_ci    int i, type;
313e1051a39Sopenharmony_ci    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci    if (!X509_check_private_key(signer, pk)) {
316e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
317e1051a39Sopenharmony_ci        return NULL;
318e1051a39Sopenharmony_ci    }
319e1051a39Sopenharmony_ci    sd = cms_signed_data_init(cms);
320e1051a39Sopenharmony_ci    if (!sd)
321e1051a39Sopenharmony_ci        goto err;
322e1051a39Sopenharmony_ci    si = M_ASN1_new_of(CMS_SignerInfo);
323e1051a39Sopenharmony_ci    if (!si)
324e1051a39Sopenharmony_ci        goto merr;
325e1051a39Sopenharmony_ci    /* Call for side-effect of computing hash and caching extensions */
326e1051a39Sopenharmony_ci    X509_check_purpose(signer, -1, -1);
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    X509_up_ref(signer);
329e1051a39Sopenharmony_ci    EVP_PKEY_up_ref(pk);
330e1051a39Sopenharmony_ci
331e1051a39Sopenharmony_ci    si->cms_ctx = ctx;
332e1051a39Sopenharmony_ci    si->pkey = pk;
333e1051a39Sopenharmony_ci    si->signer = signer;
334e1051a39Sopenharmony_ci    si->mctx = EVP_MD_CTX_new();
335e1051a39Sopenharmony_ci    si->pctx = NULL;
336e1051a39Sopenharmony_ci
337e1051a39Sopenharmony_ci    if (si->mctx == NULL) {
338e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
339e1051a39Sopenharmony_ci        goto err;
340e1051a39Sopenharmony_ci    }
341e1051a39Sopenharmony_ci
342e1051a39Sopenharmony_ci    if (flags & CMS_USE_KEYID) {
343e1051a39Sopenharmony_ci        si->version = 3;
344e1051a39Sopenharmony_ci        if (sd->version < 3)
345e1051a39Sopenharmony_ci            sd->version = 3;
346e1051a39Sopenharmony_ci        type = CMS_SIGNERINFO_KEYIDENTIFIER;
347e1051a39Sopenharmony_ci    } else {
348e1051a39Sopenharmony_ci        type = CMS_SIGNERINFO_ISSUER_SERIAL;
349e1051a39Sopenharmony_ci        si->version = 1;
350e1051a39Sopenharmony_ci    }
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci    if (!ossl_cms_set1_SignerIdentifier(si->sid, signer, type, ctx))
353e1051a39Sopenharmony_ci        goto err;
354e1051a39Sopenharmony_ci
355e1051a39Sopenharmony_ci    if (md == NULL) {
356e1051a39Sopenharmony_ci        int def_nid;
357e1051a39Sopenharmony_ci        if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
358e1051a39Sopenharmony_ci            goto err;
359e1051a39Sopenharmony_ci        md = EVP_get_digestbynid(def_nid);
360e1051a39Sopenharmony_ci        if (md == NULL) {
361e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
362e1051a39Sopenharmony_ci            goto err;
363e1051a39Sopenharmony_ci        }
364e1051a39Sopenharmony_ci    }
365e1051a39Sopenharmony_ci
366e1051a39Sopenharmony_ci    if (!md) {
367e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
368e1051a39Sopenharmony_ci        goto err;
369e1051a39Sopenharmony_ci    }
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci    if (md == NULL) {
372e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET);
373e1051a39Sopenharmony_ci        goto err;
374e1051a39Sopenharmony_ci    }
375e1051a39Sopenharmony_ci
376e1051a39Sopenharmony_ci    X509_ALGOR_set_md(si->digestAlgorithm, md);
377e1051a39Sopenharmony_ci
378e1051a39Sopenharmony_ci    /* See if digest is present in digestAlgorithms */
379e1051a39Sopenharmony_ci    for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
380e1051a39Sopenharmony_ci        const ASN1_OBJECT *aoid;
381e1051a39Sopenharmony_ci        char name[OSSL_MAX_NAME_SIZE];
382e1051a39Sopenharmony_ci
383e1051a39Sopenharmony_ci        alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
384e1051a39Sopenharmony_ci        X509_ALGOR_get0(&aoid, NULL, NULL, alg);
385e1051a39Sopenharmony_ci        OBJ_obj2txt(name, sizeof(name), aoid, 0);
386e1051a39Sopenharmony_ci        if (EVP_MD_is_a(md, name))
387e1051a39Sopenharmony_ci            break;
388e1051a39Sopenharmony_ci    }
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci    if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
391e1051a39Sopenharmony_ci        alg = X509_ALGOR_new();
392e1051a39Sopenharmony_ci        if (alg == NULL)
393e1051a39Sopenharmony_ci            goto merr;
394e1051a39Sopenharmony_ci        X509_ALGOR_set_md(alg, md);
395e1051a39Sopenharmony_ci        if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
396e1051a39Sopenharmony_ci            X509_ALGOR_free(alg);
397e1051a39Sopenharmony_ci            goto merr;
398e1051a39Sopenharmony_ci        }
399e1051a39Sopenharmony_ci    }
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ci    if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
402e1051a39Sopenharmony_ci        goto err;
403e1051a39Sopenharmony_ci    if (!(flags & CMS_NOATTR)) {
404e1051a39Sopenharmony_ci        /*
405e1051a39Sopenharmony_ci         * Initialize signed attributes structure so other attributes
406e1051a39Sopenharmony_ci         * such as signing time etc are added later even if we add none here.
407e1051a39Sopenharmony_ci         */
408e1051a39Sopenharmony_ci        if (!si->signedAttrs) {
409e1051a39Sopenharmony_ci            si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
410e1051a39Sopenharmony_ci            if (!si->signedAttrs)
411e1051a39Sopenharmony_ci                goto merr;
412e1051a39Sopenharmony_ci        }
413e1051a39Sopenharmony_ci
414e1051a39Sopenharmony_ci        if (!(flags & CMS_NOSMIMECAP)) {
415e1051a39Sopenharmony_ci            STACK_OF(X509_ALGOR) *smcap = NULL;
416e1051a39Sopenharmony_ci            i = CMS_add_standard_smimecap(&smcap);
417e1051a39Sopenharmony_ci            if (i)
418e1051a39Sopenharmony_ci                i = CMS_add_smimecap(si, smcap);
419e1051a39Sopenharmony_ci            sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
420e1051a39Sopenharmony_ci            if (!i)
421e1051a39Sopenharmony_ci                goto merr;
422e1051a39Sopenharmony_ci        }
423e1051a39Sopenharmony_ci        if (flags & CMS_CADES) {
424e1051a39Sopenharmony_ci            ESS_SIGNING_CERT *sc = NULL;
425e1051a39Sopenharmony_ci            ESS_SIGNING_CERT_V2 *sc2 = NULL;
426e1051a39Sopenharmony_ci            int add_sc;
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_ci            if (md == NULL || EVP_MD_is_a(md, SN_sha1)) {
429e1051a39Sopenharmony_ci                if ((sc = OSSL_ESS_signing_cert_new_init(signer,
430e1051a39Sopenharmony_ci                                                         NULL, 1)) == NULL)
431e1051a39Sopenharmony_ci                    goto err;
432e1051a39Sopenharmony_ci                add_sc = ossl_cms_add1_signing_cert(si, sc);
433e1051a39Sopenharmony_ci                ESS_SIGNING_CERT_free(sc);
434e1051a39Sopenharmony_ci            } else {
435e1051a39Sopenharmony_ci                if ((sc2 = OSSL_ESS_signing_cert_v2_new_init(md, signer,
436e1051a39Sopenharmony_ci                                                             NULL, 1)) == NULL)
437e1051a39Sopenharmony_ci                    goto err;
438e1051a39Sopenharmony_ci                add_sc = ossl_cms_add1_signing_cert_v2(si, sc2);
439e1051a39Sopenharmony_ci                ESS_SIGNING_CERT_V2_free(sc2);
440e1051a39Sopenharmony_ci            }
441e1051a39Sopenharmony_ci            if (!add_sc)
442e1051a39Sopenharmony_ci                goto err;
443e1051a39Sopenharmony_ci        }
444e1051a39Sopenharmony_ci        if (flags & CMS_REUSE_DIGEST) {
445e1051a39Sopenharmony_ci            if (!cms_copy_messageDigest(cms, si))
446e1051a39Sopenharmony_ci                goto err;
447e1051a39Sopenharmony_ci            if (!cms_set_si_contentType_attr(cms, si))
448e1051a39Sopenharmony_ci                goto err;
449e1051a39Sopenharmony_ci            if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
450e1051a39Sopenharmony_ci                !CMS_SignerInfo_sign(si))
451e1051a39Sopenharmony_ci                goto err;
452e1051a39Sopenharmony_ci        }
453e1051a39Sopenharmony_ci    }
454e1051a39Sopenharmony_ci
455e1051a39Sopenharmony_ci    if (!(flags & CMS_NOCERTS)) {
456e1051a39Sopenharmony_ci        /* NB ignore -1 return for duplicate cert */
457e1051a39Sopenharmony_ci        if (!CMS_add1_cert(cms, signer))
458e1051a39Sopenharmony_ci            goto merr;
459e1051a39Sopenharmony_ci    }
460e1051a39Sopenharmony_ci
461e1051a39Sopenharmony_ci    if (flags & CMS_KEY_PARAM) {
462e1051a39Sopenharmony_ci        if (flags & CMS_NOATTR) {
463e1051a39Sopenharmony_ci            si->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
464e1051a39Sopenharmony_ci                                                  si->pkey,
465e1051a39Sopenharmony_ci                                                  ossl_cms_ctx_get0_propq(ctx));
466e1051a39Sopenharmony_ci            if (si->pctx == NULL)
467e1051a39Sopenharmony_ci                goto err;
468e1051a39Sopenharmony_ci            if (EVP_PKEY_sign_init(si->pctx) <= 0)
469e1051a39Sopenharmony_ci                goto err;
470e1051a39Sopenharmony_ci            if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
471e1051a39Sopenharmony_ci                goto err;
472e1051a39Sopenharmony_ci        } else if (EVP_DigestSignInit_ex(si->mctx, &si->pctx,
473e1051a39Sopenharmony_ci                                         EVP_MD_get0_name(md),
474e1051a39Sopenharmony_ci                                         ossl_cms_ctx_get0_libctx(ctx),
475e1051a39Sopenharmony_ci                                         ossl_cms_ctx_get0_propq(ctx),
476e1051a39Sopenharmony_ci                                         pk, NULL) <= 0) {
477e1051a39Sopenharmony_ci            si->pctx = NULL;
478e1051a39Sopenharmony_ci            goto err;
479e1051a39Sopenharmony_ci        }
480e1051a39Sopenharmony_ci        else {
481e1051a39Sopenharmony_ci            EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
482e1051a39Sopenharmony_ci        }
483e1051a39Sopenharmony_ci    }
484e1051a39Sopenharmony_ci
485e1051a39Sopenharmony_ci    if (!sd->signerInfos)
486e1051a39Sopenharmony_ci        sd->signerInfos = sk_CMS_SignerInfo_new_null();
487e1051a39Sopenharmony_ci    if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
488e1051a39Sopenharmony_ci        goto merr;
489e1051a39Sopenharmony_ci
490e1051a39Sopenharmony_ci    return si;
491e1051a39Sopenharmony_ci
492e1051a39Sopenharmony_ci merr:
493e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
494e1051a39Sopenharmony_ci err:
495e1051a39Sopenharmony_ci    M_ASN1_free_of(si, CMS_SignerInfo);
496e1051a39Sopenharmony_ci    return NULL;
497e1051a39Sopenharmony_ci
498e1051a39Sopenharmony_ci}
499e1051a39Sopenharmony_ci
500e1051a39Sopenharmony_civoid ossl_cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms)
501e1051a39Sopenharmony_ci{
502e1051a39Sopenharmony_ci    int i;
503e1051a39Sopenharmony_ci    CMS_SignerInfo *si;
504e1051a39Sopenharmony_ci    STACK_OF(CMS_SignerInfo) *sinfos;
505e1051a39Sopenharmony_ci    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
506e1051a39Sopenharmony_ci
507e1051a39Sopenharmony_ci    ERR_set_mark();
508e1051a39Sopenharmony_ci    sinfos = CMS_get0_SignerInfos(cms);
509e1051a39Sopenharmony_ci    ERR_pop_to_mark(); /* removes error in case sinfos == NULL */
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
512e1051a39Sopenharmony_ci        si = sk_CMS_SignerInfo_value(sinfos, i);
513e1051a39Sopenharmony_ci        if (si != NULL)
514e1051a39Sopenharmony_ci            si->cms_ctx = ctx;
515e1051a39Sopenharmony_ci    }
516e1051a39Sopenharmony_ci}
517e1051a39Sopenharmony_ci
518e1051a39Sopenharmony_cistatic int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
519e1051a39Sopenharmony_ci{
520e1051a39Sopenharmony_ci    ASN1_TIME *tt;
521e1051a39Sopenharmony_ci    int r = 0;
522e1051a39Sopenharmony_ci
523e1051a39Sopenharmony_ci    if (t != NULL)
524e1051a39Sopenharmony_ci        tt = t;
525e1051a39Sopenharmony_ci    else
526e1051a39Sopenharmony_ci        tt = X509_gmtime_adj(NULL, 0);
527e1051a39Sopenharmony_ci
528e1051a39Sopenharmony_ci    if (tt == NULL)
529e1051a39Sopenharmony_ci        goto merr;
530e1051a39Sopenharmony_ci
531e1051a39Sopenharmony_ci    if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
532e1051a39Sopenharmony_ci                                    tt->type, tt, -1) <= 0)
533e1051a39Sopenharmony_ci        goto merr;
534e1051a39Sopenharmony_ci
535e1051a39Sopenharmony_ci    r = 1;
536e1051a39Sopenharmony_ci merr:
537e1051a39Sopenharmony_ci    if (t == NULL)
538e1051a39Sopenharmony_ci        ASN1_TIME_free(tt);
539e1051a39Sopenharmony_ci
540e1051a39Sopenharmony_ci    if (!r)
541e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
542e1051a39Sopenharmony_ci
543e1051a39Sopenharmony_ci    return r;
544e1051a39Sopenharmony_ci
545e1051a39Sopenharmony_ci}
546e1051a39Sopenharmony_ci
547e1051a39Sopenharmony_ciEVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
548e1051a39Sopenharmony_ci{
549e1051a39Sopenharmony_ci    return si->pctx;
550e1051a39Sopenharmony_ci}
551e1051a39Sopenharmony_ci
552e1051a39Sopenharmony_ciEVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
553e1051a39Sopenharmony_ci{
554e1051a39Sopenharmony_ci    return si->mctx;
555e1051a39Sopenharmony_ci}
556e1051a39Sopenharmony_ci
557e1051a39Sopenharmony_ciSTACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
558e1051a39Sopenharmony_ci{
559e1051a39Sopenharmony_ci    CMS_SignedData *sd = cms_get0_signed(cms);
560e1051a39Sopenharmony_ci
561e1051a39Sopenharmony_ci    return sd != NULL ? sd->signerInfos : NULL;
562e1051a39Sopenharmony_ci}
563e1051a39Sopenharmony_ci
564e1051a39Sopenharmony_ciSTACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
565e1051a39Sopenharmony_ci{
566e1051a39Sopenharmony_ci    STACK_OF(X509) *signers = NULL;
567e1051a39Sopenharmony_ci    STACK_OF(CMS_SignerInfo) *sinfos;
568e1051a39Sopenharmony_ci    CMS_SignerInfo *si;
569e1051a39Sopenharmony_ci    int i;
570e1051a39Sopenharmony_ci
571e1051a39Sopenharmony_ci    sinfos = CMS_get0_SignerInfos(cms);
572e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
573e1051a39Sopenharmony_ci        si = sk_CMS_SignerInfo_value(sinfos, i);
574e1051a39Sopenharmony_ci        if (si->signer != NULL) {
575e1051a39Sopenharmony_ci            if (!ossl_x509_add_cert_new(&signers, si->signer,
576e1051a39Sopenharmony_ci                                        X509_ADD_FLAG_DEFAULT)) {
577e1051a39Sopenharmony_ci                sk_X509_free(signers);
578e1051a39Sopenharmony_ci                return NULL;
579e1051a39Sopenharmony_ci            }
580e1051a39Sopenharmony_ci        }
581e1051a39Sopenharmony_ci    }
582e1051a39Sopenharmony_ci    return signers;
583e1051a39Sopenharmony_ci}
584e1051a39Sopenharmony_ci
585e1051a39Sopenharmony_civoid CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
586e1051a39Sopenharmony_ci{
587e1051a39Sopenharmony_ci    if (signer != NULL) {
588e1051a39Sopenharmony_ci        X509_up_ref(signer);
589e1051a39Sopenharmony_ci        EVP_PKEY_free(si->pkey);
590e1051a39Sopenharmony_ci        si->pkey = X509_get_pubkey(signer);
591e1051a39Sopenharmony_ci    }
592e1051a39Sopenharmony_ci    X509_free(si->signer);
593e1051a39Sopenharmony_ci    si->signer = signer;
594e1051a39Sopenharmony_ci}
595e1051a39Sopenharmony_ci
596e1051a39Sopenharmony_ciint CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
597e1051a39Sopenharmony_ci                                  ASN1_OCTET_STRING **keyid,
598e1051a39Sopenharmony_ci                                  X509_NAME **issuer, ASN1_INTEGER **sno)
599e1051a39Sopenharmony_ci{
600e1051a39Sopenharmony_ci    return ossl_cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
601e1051a39Sopenharmony_ci}
602e1051a39Sopenharmony_ci
603e1051a39Sopenharmony_ciint CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
604e1051a39Sopenharmony_ci{
605e1051a39Sopenharmony_ci    return ossl_cms_SignerIdentifier_cert_cmp(si->sid, cert);
606e1051a39Sopenharmony_ci}
607e1051a39Sopenharmony_ci
608e1051a39Sopenharmony_ciint CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
609e1051a39Sopenharmony_ci                           unsigned int flags)
610e1051a39Sopenharmony_ci{
611e1051a39Sopenharmony_ci    CMS_SignedData *sd;
612e1051a39Sopenharmony_ci    CMS_SignerInfo *si;
613e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
614e1051a39Sopenharmony_ci    STACK_OF(CMS_CertificateChoices) *certs;
615e1051a39Sopenharmony_ci    X509 *x;
616e1051a39Sopenharmony_ci    int i, j;
617e1051a39Sopenharmony_ci    int ret = 0;
618e1051a39Sopenharmony_ci
619e1051a39Sopenharmony_ci    sd = cms_get0_signed(cms);
620e1051a39Sopenharmony_ci    if (sd == NULL)
621e1051a39Sopenharmony_ci        return -1;
622e1051a39Sopenharmony_ci    certs = sd->certificates;
623e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
624e1051a39Sopenharmony_ci        si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
625e1051a39Sopenharmony_ci        if (si->signer != NULL)
626e1051a39Sopenharmony_ci            continue;
627e1051a39Sopenharmony_ci
628e1051a39Sopenharmony_ci        for (j = 0; j < sk_X509_num(scerts); j++) {
629e1051a39Sopenharmony_ci            x = sk_X509_value(scerts, j);
630e1051a39Sopenharmony_ci            if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
631e1051a39Sopenharmony_ci                CMS_SignerInfo_set1_signer_cert(si, x);
632e1051a39Sopenharmony_ci                ret++;
633e1051a39Sopenharmony_ci                break;
634e1051a39Sopenharmony_ci            }
635e1051a39Sopenharmony_ci        }
636e1051a39Sopenharmony_ci
637e1051a39Sopenharmony_ci        if (si->signer != NULL || (flags & CMS_NOINTERN))
638e1051a39Sopenharmony_ci            continue;
639e1051a39Sopenharmony_ci
640e1051a39Sopenharmony_ci        for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
641e1051a39Sopenharmony_ci            cch = sk_CMS_CertificateChoices_value(certs, j);
642e1051a39Sopenharmony_ci            if (cch->type != 0)
643e1051a39Sopenharmony_ci                continue;
644e1051a39Sopenharmony_ci            x = cch->d.certificate;
645e1051a39Sopenharmony_ci            if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
646e1051a39Sopenharmony_ci                CMS_SignerInfo_set1_signer_cert(si, x);
647e1051a39Sopenharmony_ci                ret++;
648e1051a39Sopenharmony_ci                break;
649e1051a39Sopenharmony_ci            }
650e1051a39Sopenharmony_ci        }
651e1051a39Sopenharmony_ci    }
652e1051a39Sopenharmony_ci    return ret;
653e1051a39Sopenharmony_ci}
654e1051a39Sopenharmony_ci
655e1051a39Sopenharmony_civoid CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
656e1051a39Sopenharmony_ci                              X509 **signer, X509_ALGOR **pdig,
657e1051a39Sopenharmony_ci                              X509_ALGOR **psig)
658e1051a39Sopenharmony_ci{
659e1051a39Sopenharmony_ci    if (pk != NULL)
660e1051a39Sopenharmony_ci        *pk = si->pkey;
661e1051a39Sopenharmony_ci    if (signer != NULL)
662e1051a39Sopenharmony_ci        *signer = si->signer;
663e1051a39Sopenharmony_ci    if (pdig != NULL)
664e1051a39Sopenharmony_ci        *pdig = si->digestAlgorithm;
665e1051a39Sopenharmony_ci    if (psig != NULL)
666e1051a39Sopenharmony_ci        *psig = si->signatureAlgorithm;
667e1051a39Sopenharmony_ci}
668e1051a39Sopenharmony_ci
669e1051a39Sopenharmony_ciASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
670e1051a39Sopenharmony_ci{
671e1051a39Sopenharmony_ci    return si->signature;
672e1051a39Sopenharmony_ci}
673e1051a39Sopenharmony_ci
674e1051a39Sopenharmony_cistatic int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
675e1051a39Sopenharmony_ci                                       CMS_SignerInfo *si, BIO *chain)
676e1051a39Sopenharmony_ci{
677e1051a39Sopenharmony_ci    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
678e1051a39Sopenharmony_ci    int r = 0;
679e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx = NULL;
680e1051a39Sopenharmony_ci    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
681e1051a39Sopenharmony_ci
682e1051a39Sopenharmony_ci    if (mctx == NULL) {
683e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
684e1051a39Sopenharmony_ci        return 0;
685e1051a39Sopenharmony_ci    }
686e1051a39Sopenharmony_ci
687e1051a39Sopenharmony_ci    if (si->pkey == NULL) {
688e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
689e1051a39Sopenharmony_ci        goto err;
690e1051a39Sopenharmony_ci    }
691e1051a39Sopenharmony_ci
692e1051a39Sopenharmony_ci    if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
693e1051a39Sopenharmony_ci        goto err;
694e1051a39Sopenharmony_ci    /* Set SignerInfo algorithm details if we used custom parameter */
695e1051a39Sopenharmony_ci    if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
696e1051a39Sopenharmony_ci        goto err;
697e1051a39Sopenharmony_ci
698e1051a39Sopenharmony_ci    /*
699e1051a39Sopenharmony_ci     * If any signed attributes calculate and add messageDigest attribute
700e1051a39Sopenharmony_ci     */
701e1051a39Sopenharmony_ci
702e1051a39Sopenharmony_ci    if (CMS_signed_get_attr_count(si) >= 0) {
703e1051a39Sopenharmony_ci        unsigned char md[EVP_MAX_MD_SIZE];
704e1051a39Sopenharmony_ci        unsigned int mdlen;
705e1051a39Sopenharmony_ci
706e1051a39Sopenharmony_ci        if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
707e1051a39Sopenharmony_ci            goto err;
708e1051a39Sopenharmony_ci        if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
709e1051a39Sopenharmony_ci                                         V_ASN1_OCTET_STRING, md, mdlen))
710e1051a39Sopenharmony_ci            goto err;
711e1051a39Sopenharmony_ci        /* Copy content type across */
712e1051a39Sopenharmony_ci        if (!cms_set_si_contentType_attr(cms, si))
713e1051a39Sopenharmony_ci            goto err;
714e1051a39Sopenharmony_ci
715e1051a39Sopenharmony_ci        if (!CMS_SignerInfo_sign(si))
716e1051a39Sopenharmony_ci            goto err;
717e1051a39Sopenharmony_ci    } else if (si->pctx) {
718e1051a39Sopenharmony_ci        unsigned char *sig;
719e1051a39Sopenharmony_ci        size_t siglen;
720e1051a39Sopenharmony_ci        unsigned char md[EVP_MAX_MD_SIZE];
721e1051a39Sopenharmony_ci        unsigned int mdlen;
722e1051a39Sopenharmony_ci
723e1051a39Sopenharmony_ci        pctx = si->pctx;
724e1051a39Sopenharmony_ci        si->pctx = NULL;
725e1051a39Sopenharmony_ci        if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
726e1051a39Sopenharmony_ci            goto err;
727e1051a39Sopenharmony_ci        siglen = EVP_PKEY_get_size(si->pkey);
728e1051a39Sopenharmony_ci        sig = OPENSSL_malloc(siglen);
729e1051a39Sopenharmony_ci        if (sig == NULL) {
730e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
731e1051a39Sopenharmony_ci            goto err;
732e1051a39Sopenharmony_ci        }
733e1051a39Sopenharmony_ci        if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
734e1051a39Sopenharmony_ci            OPENSSL_free(sig);
735e1051a39Sopenharmony_ci            goto err;
736e1051a39Sopenharmony_ci        }
737e1051a39Sopenharmony_ci        ASN1_STRING_set0(si->signature, sig, siglen);
738e1051a39Sopenharmony_ci    } else {
739e1051a39Sopenharmony_ci        unsigned char *sig;
740e1051a39Sopenharmony_ci        unsigned int siglen;
741e1051a39Sopenharmony_ci
742e1051a39Sopenharmony_ci        sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey));
743e1051a39Sopenharmony_ci        if (sig == NULL) {
744e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
745e1051a39Sopenharmony_ci            goto err;
746e1051a39Sopenharmony_ci        }
747e1051a39Sopenharmony_ci        if (!EVP_SignFinal_ex(mctx, sig, &siglen, si->pkey,
748e1051a39Sopenharmony_ci                              ossl_cms_ctx_get0_libctx(ctx),
749e1051a39Sopenharmony_ci                              ossl_cms_ctx_get0_propq(ctx))) {
750e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_SIGNFINAL_ERROR);
751e1051a39Sopenharmony_ci            OPENSSL_free(sig);
752e1051a39Sopenharmony_ci            goto err;
753e1051a39Sopenharmony_ci        }
754e1051a39Sopenharmony_ci        ASN1_STRING_set0(si->signature, sig, siglen);
755e1051a39Sopenharmony_ci    }
756e1051a39Sopenharmony_ci
757e1051a39Sopenharmony_ci    r = 1;
758e1051a39Sopenharmony_ci
759e1051a39Sopenharmony_ci err:
760e1051a39Sopenharmony_ci    EVP_MD_CTX_free(mctx);
761e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(pctx);
762e1051a39Sopenharmony_ci    return r;
763e1051a39Sopenharmony_ci
764e1051a39Sopenharmony_ci}
765e1051a39Sopenharmony_ci
766e1051a39Sopenharmony_ciint ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
767e1051a39Sopenharmony_ci{
768e1051a39Sopenharmony_ci    STACK_OF(CMS_SignerInfo) *sinfos;
769e1051a39Sopenharmony_ci    CMS_SignerInfo *si;
770e1051a39Sopenharmony_ci    int i;
771e1051a39Sopenharmony_ci
772e1051a39Sopenharmony_ci    sinfos = CMS_get0_SignerInfos(cms);
773e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
774e1051a39Sopenharmony_ci        si = sk_CMS_SignerInfo_value(sinfos, i);
775e1051a39Sopenharmony_ci        if (!cms_SignerInfo_content_sign(cms, si, chain))
776e1051a39Sopenharmony_ci            return 0;
777e1051a39Sopenharmony_ci    }
778e1051a39Sopenharmony_ci    cms->d.signedData->encapContentInfo->partial = 0;
779e1051a39Sopenharmony_ci    return 1;
780e1051a39Sopenharmony_ci}
781e1051a39Sopenharmony_ci
782e1051a39Sopenharmony_ciint CMS_SignerInfo_sign(CMS_SignerInfo *si)
783e1051a39Sopenharmony_ci{
784e1051a39Sopenharmony_ci    EVP_MD_CTX *mctx = si->mctx;
785e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx = NULL;
786e1051a39Sopenharmony_ci    unsigned char *abuf = NULL;
787e1051a39Sopenharmony_ci    int alen;
788e1051a39Sopenharmony_ci    size_t siglen;
789e1051a39Sopenharmony_ci    const CMS_CTX *ctx = si->cms_ctx;
790e1051a39Sopenharmony_ci    char md_name[OSSL_MAX_NAME_SIZE];
791e1051a39Sopenharmony_ci
792e1051a39Sopenharmony_ci    if (OBJ_obj2txt(md_name, sizeof(md_name),
793e1051a39Sopenharmony_ci                     si->digestAlgorithm->algorithm, 0) <= 0)
794e1051a39Sopenharmony_ci        return 0;
795e1051a39Sopenharmony_ci
796e1051a39Sopenharmony_ci    if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
797e1051a39Sopenharmony_ci        if (!cms_add1_signingTime(si, NULL))
798e1051a39Sopenharmony_ci            goto err;
799e1051a39Sopenharmony_ci    }
800e1051a39Sopenharmony_ci
801e1051a39Sopenharmony_ci    if (!ossl_cms_si_check_attributes(si))
802e1051a39Sopenharmony_ci        goto err;
803e1051a39Sopenharmony_ci
804e1051a39Sopenharmony_ci    if (si->pctx)
805e1051a39Sopenharmony_ci        pctx = si->pctx;
806e1051a39Sopenharmony_ci    else {
807e1051a39Sopenharmony_ci        EVP_MD_CTX_reset(mctx);
808e1051a39Sopenharmony_ci        if (EVP_DigestSignInit_ex(mctx, &pctx, md_name,
809e1051a39Sopenharmony_ci                                  ossl_cms_ctx_get0_libctx(ctx),
810e1051a39Sopenharmony_ci                                  ossl_cms_ctx_get0_propq(ctx), si->pkey,
811e1051a39Sopenharmony_ci                                  NULL) <= 0)
812e1051a39Sopenharmony_ci            goto err;
813e1051a39Sopenharmony_ci        EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
814e1051a39Sopenharmony_ci        si->pctx = pctx;
815e1051a39Sopenharmony_ci    }
816e1051a39Sopenharmony_ci
817e1051a39Sopenharmony_ci    alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
818e1051a39Sopenharmony_ci                         ASN1_ITEM_rptr(CMS_Attributes_Sign));
819e1051a39Sopenharmony_ci    if (!abuf)
820e1051a39Sopenharmony_ci        goto err;
821e1051a39Sopenharmony_ci    if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
822e1051a39Sopenharmony_ci        goto err;
823e1051a39Sopenharmony_ci    if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
824e1051a39Sopenharmony_ci        goto err;
825e1051a39Sopenharmony_ci    OPENSSL_free(abuf);
826e1051a39Sopenharmony_ci    abuf = OPENSSL_malloc(siglen);
827e1051a39Sopenharmony_ci    if (abuf == NULL)
828e1051a39Sopenharmony_ci        goto err;
829e1051a39Sopenharmony_ci    if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
830e1051a39Sopenharmony_ci        goto err;
831e1051a39Sopenharmony_ci
832e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(mctx);
833e1051a39Sopenharmony_ci
834e1051a39Sopenharmony_ci    ASN1_STRING_set0(si->signature, abuf, siglen);
835e1051a39Sopenharmony_ci
836e1051a39Sopenharmony_ci    return 1;
837e1051a39Sopenharmony_ci
838e1051a39Sopenharmony_ci err:
839e1051a39Sopenharmony_ci    OPENSSL_free(abuf);
840e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(mctx);
841e1051a39Sopenharmony_ci    return 0;
842e1051a39Sopenharmony_ci}
843e1051a39Sopenharmony_ci
844e1051a39Sopenharmony_ciint CMS_SignerInfo_verify(CMS_SignerInfo *si)
845e1051a39Sopenharmony_ci{
846e1051a39Sopenharmony_ci    EVP_MD_CTX *mctx = NULL;
847e1051a39Sopenharmony_ci    unsigned char *abuf = NULL;
848e1051a39Sopenharmony_ci    int alen, r = -1;
849e1051a39Sopenharmony_ci    char name[OSSL_MAX_NAME_SIZE];
850e1051a39Sopenharmony_ci    const EVP_MD *md;
851e1051a39Sopenharmony_ci    EVP_MD *fetched_md = NULL;
852e1051a39Sopenharmony_ci    const CMS_CTX *ctx = si->cms_ctx;
853e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
854e1051a39Sopenharmony_ci    const char *propq = ossl_cms_ctx_get0_propq(ctx);
855e1051a39Sopenharmony_ci
856e1051a39Sopenharmony_ci    if (si->pkey == NULL) {
857e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NO_PUBLIC_KEY);
858e1051a39Sopenharmony_ci        return -1;
859e1051a39Sopenharmony_ci    }
860e1051a39Sopenharmony_ci
861e1051a39Sopenharmony_ci    if (!ossl_cms_si_check_attributes(si))
862e1051a39Sopenharmony_ci        return -1;
863e1051a39Sopenharmony_ci
864e1051a39Sopenharmony_ci    OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0);
865e1051a39Sopenharmony_ci
866e1051a39Sopenharmony_ci    (void)ERR_set_mark();
867e1051a39Sopenharmony_ci    fetched_md = EVP_MD_fetch(libctx, name, propq);
868e1051a39Sopenharmony_ci
869e1051a39Sopenharmony_ci    if (fetched_md != NULL)
870e1051a39Sopenharmony_ci        md = fetched_md;
871e1051a39Sopenharmony_ci    else
872e1051a39Sopenharmony_ci        md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
873e1051a39Sopenharmony_ci    if (md == NULL) {
874e1051a39Sopenharmony_ci        (void)ERR_clear_last_mark();
875e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
876e1051a39Sopenharmony_ci        return -1;
877e1051a39Sopenharmony_ci    }
878e1051a39Sopenharmony_ci    (void)ERR_pop_to_mark();
879e1051a39Sopenharmony_ci
880e1051a39Sopenharmony_ci    if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
881e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
882e1051a39Sopenharmony_ci        goto err;
883e1051a39Sopenharmony_ci    }
884e1051a39Sopenharmony_ci    mctx = si->mctx;
885e1051a39Sopenharmony_ci    if (si->pctx != NULL) {
886e1051a39Sopenharmony_ci        EVP_PKEY_CTX_free(si->pctx);
887e1051a39Sopenharmony_ci        si->pctx = NULL;
888e1051a39Sopenharmony_ci    }
889e1051a39Sopenharmony_ci    if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
890e1051a39Sopenharmony_ci                                propq, si->pkey, NULL) <= 0) {
891e1051a39Sopenharmony_ci        si->pctx = NULL;
892e1051a39Sopenharmony_ci        goto err;
893e1051a39Sopenharmony_ci    }
894e1051a39Sopenharmony_ci    EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
895e1051a39Sopenharmony_ci
896e1051a39Sopenharmony_ci    if (!cms_sd_asn1_ctrl(si, 1))
897e1051a39Sopenharmony_ci        goto err;
898e1051a39Sopenharmony_ci
899e1051a39Sopenharmony_ci    alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
900e1051a39Sopenharmony_ci                         ASN1_ITEM_rptr(CMS_Attributes_Verify));
901e1051a39Sopenharmony_ci    if (abuf == NULL || alen < 0)
902e1051a39Sopenharmony_ci        goto err;
903e1051a39Sopenharmony_ci    r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
904e1051a39Sopenharmony_ci    OPENSSL_free(abuf);
905e1051a39Sopenharmony_ci    if (r <= 0) {
906e1051a39Sopenharmony_ci        r = -1;
907e1051a39Sopenharmony_ci        goto err;
908e1051a39Sopenharmony_ci    }
909e1051a39Sopenharmony_ci    r = EVP_DigestVerifyFinal(mctx,
910e1051a39Sopenharmony_ci                              si->signature->data, si->signature->length);
911e1051a39Sopenharmony_ci    if (r <= 0)
912e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
913e1051a39Sopenharmony_ci err:
914e1051a39Sopenharmony_ci    EVP_MD_free(fetched_md);
915e1051a39Sopenharmony_ci    EVP_MD_CTX_reset(mctx);
916e1051a39Sopenharmony_ci    return r;
917e1051a39Sopenharmony_ci}
918e1051a39Sopenharmony_ci
919e1051a39Sopenharmony_ci/* Create a chain of digest BIOs from a CMS ContentInfo */
920e1051a39Sopenharmony_ci
921e1051a39Sopenharmony_ciBIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms)
922e1051a39Sopenharmony_ci{
923e1051a39Sopenharmony_ci    int i;
924e1051a39Sopenharmony_ci    CMS_SignedData *sd;
925e1051a39Sopenharmony_ci    BIO *chain = NULL;
926e1051a39Sopenharmony_ci
927e1051a39Sopenharmony_ci    sd = cms_get0_signed(cms);
928e1051a39Sopenharmony_ci    if (sd == NULL)
929e1051a39Sopenharmony_ci        return NULL;
930e1051a39Sopenharmony_ci    if (cms->d.signedData->encapContentInfo->partial)
931e1051a39Sopenharmony_ci        cms_sd_set_version(sd);
932e1051a39Sopenharmony_ci    for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
933e1051a39Sopenharmony_ci        X509_ALGOR *digestAlgorithm;
934e1051a39Sopenharmony_ci        BIO *mdbio;
935e1051a39Sopenharmony_ci
936e1051a39Sopenharmony_ci        digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
937e1051a39Sopenharmony_ci        mdbio = ossl_cms_DigestAlgorithm_init_bio(digestAlgorithm,
938e1051a39Sopenharmony_ci                                                  ossl_cms_get0_cmsctx(cms));
939e1051a39Sopenharmony_ci        if (mdbio == NULL)
940e1051a39Sopenharmony_ci            goto err;
941e1051a39Sopenharmony_ci        if (chain != NULL)
942e1051a39Sopenharmony_ci            BIO_push(chain, mdbio);
943e1051a39Sopenharmony_ci        else
944e1051a39Sopenharmony_ci            chain = mdbio;
945e1051a39Sopenharmony_ci    }
946e1051a39Sopenharmony_ci    return chain;
947e1051a39Sopenharmony_ci err:
948e1051a39Sopenharmony_ci    BIO_free_all(chain);
949e1051a39Sopenharmony_ci    return NULL;
950e1051a39Sopenharmony_ci}
951e1051a39Sopenharmony_ci
952e1051a39Sopenharmony_ciint CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
953e1051a39Sopenharmony_ci{
954e1051a39Sopenharmony_ci    ASN1_OCTET_STRING *os = NULL;
955e1051a39Sopenharmony_ci    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
956e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pkctx = NULL;
957e1051a39Sopenharmony_ci    int r = -1;
958e1051a39Sopenharmony_ci    unsigned char mval[EVP_MAX_MD_SIZE];
959e1051a39Sopenharmony_ci    unsigned int mlen;
960e1051a39Sopenharmony_ci
961e1051a39Sopenharmony_ci    if (mctx == NULL) {
962e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
963e1051a39Sopenharmony_ci        goto err;
964e1051a39Sopenharmony_ci    }
965e1051a39Sopenharmony_ci    /* If we have any signed attributes look for messageDigest value */
966e1051a39Sopenharmony_ci    if (CMS_signed_get_attr_count(si) >= 0) {
967e1051a39Sopenharmony_ci        os = CMS_signed_get0_data_by_OBJ(si,
968e1051a39Sopenharmony_ci                                         OBJ_nid2obj(NID_pkcs9_messageDigest),
969e1051a39Sopenharmony_ci                                         -3, V_ASN1_OCTET_STRING);
970e1051a39Sopenharmony_ci        if (os == NULL) {
971e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
972e1051a39Sopenharmony_ci            goto err;
973e1051a39Sopenharmony_ci        }
974e1051a39Sopenharmony_ci    }
975e1051a39Sopenharmony_ci
976e1051a39Sopenharmony_ci    if (!ossl_cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
977e1051a39Sopenharmony_ci        goto err;
978e1051a39Sopenharmony_ci
979e1051a39Sopenharmony_ci    if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) {
980e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
981e1051a39Sopenharmony_ci        goto err;
982e1051a39Sopenharmony_ci    }
983e1051a39Sopenharmony_ci
984e1051a39Sopenharmony_ci    /* If messageDigest found compare it */
985e1051a39Sopenharmony_ci
986e1051a39Sopenharmony_ci    if (os != NULL) {
987e1051a39Sopenharmony_ci        if (mlen != (unsigned int)os->length) {
988e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
989e1051a39Sopenharmony_ci            goto err;
990e1051a39Sopenharmony_ci        }
991e1051a39Sopenharmony_ci
992e1051a39Sopenharmony_ci        if (memcmp(mval, os->data, mlen)) {
993e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
994e1051a39Sopenharmony_ci            r = 0;
995e1051a39Sopenharmony_ci        } else
996e1051a39Sopenharmony_ci            r = 1;
997e1051a39Sopenharmony_ci    } else {
998e1051a39Sopenharmony_ci        const EVP_MD *md = EVP_MD_CTX_get0_md(mctx);
999e1051a39Sopenharmony_ci        const CMS_CTX *ctx = si->cms_ctx;
1000e1051a39Sopenharmony_ci
1001e1051a39Sopenharmony_ci        pkctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
1002e1051a39Sopenharmony_ci                                           si->pkey,
1003e1051a39Sopenharmony_ci                                           ossl_cms_ctx_get0_propq(ctx));
1004e1051a39Sopenharmony_ci        if (pkctx == NULL)
1005e1051a39Sopenharmony_ci            goto err;
1006e1051a39Sopenharmony_ci        if (EVP_PKEY_verify_init(pkctx) <= 0)
1007e1051a39Sopenharmony_ci            goto err;
1008e1051a39Sopenharmony_ci        if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
1009e1051a39Sopenharmony_ci            goto err;
1010e1051a39Sopenharmony_ci        si->pctx = pkctx;
1011e1051a39Sopenharmony_ci        if (!cms_sd_asn1_ctrl(si, 1)) {
1012e1051a39Sopenharmony_ci            si->pctx = NULL;
1013e1051a39Sopenharmony_ci            goto err;
1014e1051a39Sopenharmony_ci        }
1015e1051a39Sopenharmony_ci        si->pctx = NULL;
1016e1051a39Sopenharmony_ci        r = EVP_PKEY_verify(pkctx, si->signature->data,
1017e1051a39Sopenharmony_ci                            si->signature->length, mval, mlen);
1018e1051a39Sopenharmony_ci        if (r <= 0) {
1019e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE);
1020e1051a39Sopenharmony_ci            r = 0;
1021e1051a39Sopenharmony_ci        }
1022e1051a39Sopenharmony_ci    }
1023e1051a39Sopenharmony_ci
1024e1051a39Sopenharmony_ci err:
1025e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(pkctx);
1026e1051a39Sopenharmony_ci    EVP_MD_CTX_free(mctx);
1027e1051a39Sopenharmony_ci    return r;
1028e1051a39Sopenharmony_ci
1029e1051a39Sopenharmony_ci}
1030e1051a39Sopenharmony_ci
1031e1051a39Sopenharmony_ciint CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
1032e1051a39Sopenharmony_ci{
1033e1051a39Sopenharmony_ci    unsigned char *smder = NULL;
1034e1051a39Sopenharmony_ci    int smderlen, r;
1035e1051a39Sopenharmony_ci
1036e1051a39Sopenharmony_ci    smderlen = i2d_X509_ALGORS(algs, &smder);
1037e1051a39Sopenharmony_ci    if (smderlen <= 0)
1038e1051a39Sopenharmony_ci        return 0;
1039e1051a39Sopenharmony_ci    r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
1040e1051a39Sopenharmony_ci                                    V_ASN1_SEQUENCE, smder, smderlen);
1041e1051a39Sopenharmony_ci    OPENSSL_free(smder);
1042e1051a39Sopenharmony_ci    return r;
1043e1051a39Sopenharmony_ci}
1044e1051a39Sopenharmony_ci
1045e1051a39Sopenharmony_ciint CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
1046e1051a39Sopenharmony_ci                            int algnid, int keysize)
1047e1051a39Sopenharmony_ci{
1048e1051a39Sopenharmony_ci    X509_ALGOR *alg = NULL;
1049e1051a39Sopenharmony_ci    ASN1_INTEGER *key = NULL;
1050e1051a39Sopenharmony_ci
1051e1051a39Sopenharmony_ci    if (keysize > 0) {
1052e1051a39Sopenharmony_ci        key = ASN1_INTEGER_new();
1053e1051a39Sopenharmony_ci        if (key == NULL || !ASN1_INTEGER_set(key, keysize))
1054e1051a39Sopenharmony_ci            goto err;
1055e1051a39Sopenharmony_ci    }
1056e1051a39Sopenharmony_ci    alg = X509_ALGOR_new();
1057e1051a39Sopenharmony_ci    if (alg == NULL)
1058e1051a39Sopenharmony_ci        goto err;
1059e1051a39Sopenharmony_ci
1060e1051a39Sopenharmony_ci    if (!X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
1061e1051a39Sopenharmony_ci                         key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key))
1062e1051a39Sopenharmony_ci        goto err;
1063e1051a39Sopenharmony_ci    key = NULL;
1064e1051a39Sopenharmony_ci    if (*algs == NULL)
1065e1051a39Sopenharmony_ci        *algs = sk_X509_ALGOR_new_null();
1066e1051a39Sopenharmony_ci    if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg))
1067e1051a39Sopenharmony_ci        goto err;
1068e1051a39Sopenharmony_ci    return 1;
1069e1051a39Sopenharmony_ci
1070e1051a39Sopenharmony_ci err:
1071e1051a39Sopenharmony_ci    ASN1_INTEGER_free(key);
1072e1051a39Sopenharmony_ci    X509_ALGOR_free(alg);
1073e1051a39Sopenharmony_ci    return 0;
1074e1051a39Sopenharmony_ci}
1075e1051a39Sopenharmony_ci
1076e1051a39Sopenharmony_ci/* Check to see if a cipher exists and if so add S/MIME capabilities */
1077e1051a39Sopenharmony_ci
1078e1051a39Sopenharmony_cistatic int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
1079e1051a39Sopenharmony_ci{
1080e1051a39Sopenharmony_ci    if (EVP_get_cipherbynid(nid))
1081e1051a39Sopenharmony_ci        return CMS_add_simple_smimecap(sk, nid, arg);
1082e1051a39Sopenharmony_ci    return 1;
1083e1051a39Sopenharmony_ci}
1084e1051a39Sopenharmony_ci
1085e1051a39Sopenharmony_cistatic int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
1086e1051a39Sopenharmony_ci{
1087e1051a39Sopenharmony_ci    if (EVP_get_digestbynid(nid))
1088e1051a39Sopenharmony_ci        return CMS_add_simple_smimecap(sk, nid, arg);
1089e1051a39Sopenharmony_ci    return 1;
1090e1051a39Sopenharmony_ci}
1091e1051a39Sopenharmony_ci
1092e1051a39Sopenharmony_ciint CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
1093e1051a39Sopenharmony_ci{
1094e1051a39Sopenharmony_ci    if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
1095e1051a39Sopenharmony_ci        || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1)
1096e1051a39Sopenharmony_ci        || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1)
1097e1051a39Sopenharmony_ci        || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
1098e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
1099e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
1100e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
1101e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
1102e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
1103e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
1104e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
1105e1051a39Sopenharmony_ci        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
1106e1051a39Sopenharmony_ci        return 0;
1107e1051a39Sopenharmony_ci    return 1;
1108e1051a39Sopenharmony_ci}
1109