1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2008-2023 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 <openssl/asn1t.h>
11e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
12e1051a39Sopenharmony_ci#include <openssl/err.h>
13e1051a39Sopenharmony_ci#include <openssl/pem.h>
14e1051a39Sopenharmony_ci#include <openssl/bio.h>
15e1051a39Sopenharmony_ci#include <openssl/asn1.h>
16e1051a39Sopenharmony_ci#include <openssl/cms.h>
17e1051a39Sopenharmony_ci#include <openssl/cms.h>
18e1051a39Sopenharmony_ci#include "internal/sizes.h"
19e1051a39Sopenharmony_ci#include "crypto/x509.h"
20e1051a39Sopenharmony_ci#include "cms_local.h"
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_cistatic STACK_OF(CMS_CertificateChoices)
23e1051a39Sopenharmony_ci**cms_get0_certificate_choices(CMS_ContentInfo *cms);
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ciIMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_ContentInfo)
26e1051a39Sopenharmony_ciIMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ciCMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
29e1051a39Sopenharmony_ci                                     const unsigned char **in, long len)
30e1051a39Sopenharmony_ci{
31e1051a39Sopenharmony_ci    CMS_ContentInfo *ci;
32e1051a39Sopenharmony_ci    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(a == NULL ? NULL : *a);
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci    ci = (CMS_ContentInfo *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len,
35e1051a39Sopenharmony_ci                                          (CMS_ContentInfo_it()),
36e1051a39Sopenharmony_ci                                          ossl_cms_ctx_get0_libctx(ctx),
37e1051a39Sopenharmony_ci                                          ossl_cms_ctx_get0_propq(ctx));
38e1051a39Sopenharmony_ci    if (ci != NULL) {
39e1051a39Sopenharmony_ci        ERR_set_mark();
40e1051a39Sopenharmony_ci        ossl_cms_resolve_libctx(ci);
41e1051a39Sopenharmony_ci        ERR_pop_to_mark();
42e1051a39Sopenharmony_ci    }
43e1051a39Sopenharmony_ci    return ci;
44e1051a39Sopenharmony_ci}
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ciint i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
47e1051a39Sopenharmony_ci{
48e1051a39Sopenharmony_ci    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
49e1051a39Sopenharmony_ci}
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ciCMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
52e1051a39Sopenharmony_ci{
53e1051a39Sopenharmony_ci    CMS_ContentInfo *ci;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci    ci = (CMS_ContentInfo *)ASN1_item_new_ex(ASN1_ITEM_rptr(CMS_ContentInfo),
56e1051a39Sopenharmony_ci                                             libctx, propq);
57e1051a39Sopenharmony_ci    if (ci != NULL) {
58e1051a39Sopenharmony_ci        ci->ctx.libctx = libctx;
59e1051a39Sopenharmony_ci        ci->ctx.propq = NULL;
60e1051a39Sopenharmony_ci        if (propq != NULL) {
61e1051a39Sopenharmony_ci            ci->ctx.propq = OPENSSL_strdup(propq);
62e1051a39Sopenharmony_ci            if (ci->ctx.propq == NULL) {
63e1051a39Sopenharmony_ci                CMS_ContentInfo_free(ci);
64e1051a39Sopenharmony_ci                ci = NULL;
65e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
66e1051a39Sopenharmony_ci            }
67e1051a39Sopenharmony_ci        }
68e1051a39Sopenharmony_ci    }
69e1051a39Sopenharmony_ci    return ci;
70e1051a39Sopenharmony_ci}
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ciconst CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms)
73e1051a39Sopenharmony_ci{
74e1051a39Sopenharmony_ci    return cms != NULL ? &cms->ctx : NULL;
75e1051a39Sopenharmony_ci}
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_ciOSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx)
78e1051a39Sopenharmony_ci{
79e1051a39Sopenharmony_ci    return ctx != NULL ? ctx->libctx : NULL;
80e1051a39Sopenharmony_ci}
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ciconst char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    return ctx != NULL ? ctx->propq : NULL;
85e1051a39Sopenharmony_ci}
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_civoid ossl_cms_resolve_libctx(CMS_ContentInfo *ci)
88e1051a39Sopenharmony_ci{
89e1051a39Sopenharmony_ci    int i;
90e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
91e1051a39Sopenharmony_ci    STACK_OF(CMS_CertificateChoices) **pcerts;
92e1051a39Sopenharmony_ci    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(ci);
93e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
94e1051a39Sopenharmony_ci    const char *propq = ossl_cms_ctx_get0_propq(ctx);
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci    ossl_cms_SignerInfos_set_cmsctx(ci);
97e1051a39Sopenharmony_ci    ossl_cms_RecipientInfos_set_cmsctx(ci);
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    pcerts = cms_get0_certificate_choices(ci);
100e1051a39Sopenharmony_ci    if (pcerts != NULL) {
101e1051a39Sopenharmony_ci        for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
102e1051a39Sopenharmony_ci            cch = sk_CMS_CertificateChoices_value(*pcerts, i);
103e1051a39Sopenharmony_ci            if (cch->type == CMS_CERTCHOICE_CERT)
104e1051a39Sopenharmony_ci                ossl_x509_set0_libctx(cch->d.certificate, libctx, propq);
105e1051a39Sopenharmony_ci        }
106e1051a39Sopenharmony_ci    }
107e1051a39Sopenharmony_ci}
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ciconst ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
110e1051a39Sopenharmony_ci{
111e1051a39Sopenharmony_ci    return cms->contentType;
112e1051a39Sopenharmony_ci}
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_ciCMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *libctx, const char *propq)
115e1051a39Sopenharmony_ci{
116e1051a39Sopenharmony_ci    CMS_ContentInfo *cms = CMS_ContentInfo_new_ex(libctx, propq);
117e1051a39Sopenharmony_ci
118e1051a39Sopenharmony_ci    if (cms != NULL) {
119e1051a39Sopenharmony_ci        cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
120e1051a39Sopenharmony_ci        /* Never detached */
121e1051a39Sopenharmony_ci        CMS_set_detached(cms, 0);
122e1051a39Sopenharmony_ci    }
123e1051a39Sopenharmony_ci    return cms;
124e1051a39Sopenharmony_ci}
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ciBIO *ossl_cms_content_bio(CMS_ContentInfo *cms)
127e1051a39Sopenharmony_ci{
128e1051a39Sopenharmony_ci    ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
129e1051a39Sopenharmony_ci
130e1051a39Sopenharmony_ci    if (pos == NULL)
131e1051a39Sopenharmony_ci        return NULL;
132e1051a39Sopenharmony_ci    /* If content detached data goes nowhere: create NULL BIO */
133e1051a39Sopenharmony_ci    if (*pos == NULL)
134e1051a39Sopenharmony_ci        return BIO_new(BIO_s_null());
135e1051a39Sopenharmony_ci    /*
136e1051a39Sopenharmony_ci     * If content not detached and created return memory BIO
137e1051a39Sopenharmony_ci     */
138e1051a39Sopenharmony_ci    if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
139e1051a39Sopenharmony_ci        return BIO_new(BIO_s_mem());
140e1051a39Sopenharmony_ci    /* Else content was read in: return read only BIO for it */
141e1051a39Sopenharmony_ci    return BIO_new_mem_buf((*pos)->data, (*pos)->length);
142e1051a39Sopenharmony_ci}
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ciBIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
145e1051a39Sopenharmony_ci{
146e1051a39Sopenharmony_ci    BIO *cmsbio, *cont;
147e1051a39Sopenharmony_ci    if (icont)
148e1051a39Sopenharmony_ci        cont = icont;
149e1051a39Sopenharmony_ci    else
150e1051a39Sopenharmony_ci        cont = ossl_cms_content_bio(cms);
151e1051a39Sopenharmony_ci    if (!cont) {
152e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
153e1051a39Sopenharmony_ci        return NULL;
154e1051a39Sopenharmony_ci    }
155e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci    case NID_pkcs7_data:
158e1051a39Sopenharmony_ci        return cont;
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
161e1051a39Sopenharmony_ci        cmsbio = ossl_cms_SignedData_init_bio(cms);
162e1051a39Sopenharmony_ci        break;
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci    case NID_pkcs7_digest:
165e1051a39Sopenharmony_ci        cmsbio = ossl_cms_DigestedData_init_bio(cms);
166e1051a39Sopenharmony_ci        break;
167e1051a39Sopenharmony_ci#ifdef ZLIB
168e1051a39Sopenharmony_ci    case NID_id_smime_ct_compressedData:
169e1051a39Sopenharmony_ci        cmsbio = ossl_cms_CompressedData_init_bio(cms);
170e1051a39Sopenharmony_ci        break;
171e1051a39Sopenharmony_ci#endif
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    case NID_pkcs7_encrypted:
174e1051a39Sopenharmony_ci        cmsbio = ossl_cms_EncryptedData_init_bio(cms);
175e1051a39Sopenharmony_ci        break;
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
178e1051a39Sopenharmony_ci        cmsbio = ossl_cms_EnvelopedData_init_bio(cms);
179e1051a39Sopenharmony_ci        break;
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
182e1051a39Sopenharmony_ci        cmsbio = ossl_cms_AuthEnvelopedData_init_bio(cms);
183e1051a39Sopenharmony_ci        break;
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci    default:
186e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
187e1051a39Sopenharmony_ci        goto err;
188e1051a39Sopenharmony_ci    }
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci    if (cmsbio)
191e1051a39Sopenharmony_ci        return BIO_push(cmsbio, cont);
192e1051a39Sopenharmony_cierr:
193e1051a39Sopenharmony_ci    if (!icont)
194e1051a39Sopenharmony_ci        BIO_free(cont);
195e1051a39Sopenharmony_ci    return NULL;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci}
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci/* unfortunately cannot constify SMIME_write_ASN1() due to this function */
200e1051a39Sopenharmony_ciint CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
201e1051a39Sopenharmony_ci{
202e1051a39Sopenharmony_ci    ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
203e1051a39Sopenharmony_ci
204e1051a39Sopenharmony_ci    if (pos == NULL)
205e1051a39Sopenharmony_ci        return 0;
206e1051a39Sopenharmony_ci    /* If embedded content find memory BIO and set content */
207e1051a39Sopenharmony_ci    if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
208e1051a39Sopenharmony_ci        BIO *mbio;
209e1051a39Sopenharmony_ci        unsigned char *cont;
210e1051a39Sopenharmony_ci        long contlen;
211e1051a39Sopenharmony_ci        mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
212e1051a39Sopenharmony_ci        if (!mbio) {
213e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
214e1051a39Sopenharmony_ci            return 0;
215e1051a39Sopenharmony_ci        }
216e1051a39Sopenharmony_ci        contlen = BIO_get_mem_data(mbio, &cont);
217e1051a39Sopenharmony_ci        /* Set bio as read only so its content can't be clobbered */
218e1051a39Sopenharmony_ci        BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
219e1051a39Sopenharmony_ci        BIO_set_mem_eof_return(mbio, 0);
220e1051a39Sopenharmony_ci        ASN1_STRING_set0(*pos, cont, contlen);
221e1051a39Sopenharmony_ci        (*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
222e1051a39Sopenharmony_ci    }
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
225e1051a39Sopenharmony_ci
226e1051a39Sopenharmony_ci    case NID_pkcs7_data:
227e1051a39Sopenharmony_ci    case NID_pkcs7_encrypted:
228e1051a39Sopenharmony_ci    case NID_id_smime_ct_compressedData:
229e1051a39Sopenharmony_ci        /* Nothing to do */
230e1051a39Sopenharmony_ci        return 1;
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
233e1051a39Sopenharmony_ci        return ossl_cms_EnvelopedData_final(cms, cmsbio);
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
236e1051a39Sopenharmony_ci        return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
239e1051a39Sopenharmony_ci        return ossl_cms_SignedData_final(cms, cmsbio);
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_ci    case NID_pkcs7_digest:
242e1051a39Sopenharmony_ci        return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
243e1051a39Sopenharmony_ci
244e1051a39Sopenharmony_ci    default:
245e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
246e1051a39Sopenharmony_ci        return 0;
247e1051a39Sopenharmony_ci    }
248e1051a39Sopenharmony_ci}
249e1051a39Sopenharmony_ci
250e1051a39Sopenharmony_ci/*
251e1051a39Sopenharmony_ci * Return an OCTET STRING pointer to content. This allows it to be accessed
252e1051a39Sopenharmony_ci * or set later.
253e1051a39Sopenharmony_ci */
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ciASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
256e1051a39Sopenharmony_ci{
257e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci    case NID_pkcs7_data:
260e1051a39Sopenharmony_ci        return &cms->d.data;
261e1051a39Sopenharmony_ci
262e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
263e1051a39Sopenharmony_ci        return &cms->d.signedData->encapContentInfo->eContent;
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
266e1051a39Sopenharmony_ci        return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
267e1051a39Sopenharmony_ci
268e1051a39Sopenharmony_ci    case NID_pkcs7_digest:
269e1051a39Sopenharmony_ci        return &cms->d.digestedData->encapContentInfo->eContent;
270e1051a39Sopenharmony_ci
271e1051a39Sopenharmony_ci    case NID_pkcs7_encrypted:
272e1051a39Sopenharmony_ci        return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
275e1051a39Sopenharmony_ci        return &cms->d.authEnvelopedData->authEncryptedContentInfo
276e1051a39Sopenharmony_ci                                        ->encryptedContent;
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ci    case NID_id_smime_ct_authData:
279e1051a39Sopenharmony_ci        return &cms->d.authenticatedData->encapContentInfo->eContent;
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ci    case NID_id_smime_ct_compressedData:
282e1051a39Sopenharmony_ci        return &cms->d.compressedData->encapContentInfo->eContent;
283e1051a39Sopenharmony_ci
284e1051a39Sopenharmony_ci    default:
285e1051a39Sopenharmony_ci        if (cms->d.other->type == V_ASN1_OCTET_STRING)
286e1051a39Sopenharmony_ci            return &cms->d.other->value.octet_string;
287e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
288e1051a39Sopenharmony_ci        return NULL;
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci    }
291e1051a39Sopenharmony_ci}
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ci/*
294e1051a39Sopenharmony_ci * Return an ASN1_OBJECT pointer to content type. This allows it to be
295e1051a39Sopenharmony_ci * accessed or set later.
296e1051a39Sopenharmony_ci */
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_cistatic ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
299e1051a39Sopenharmony_ci{
300e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
303e1051a39Sopenharmony_ci        return &cms->d.signedData->encapContentInfo->eContentType;
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
306e1051a39Sopenharmony_ci        return &cms->d.envelopedData->encryptedContentInfo->contentType;
307e1051a39Sopenharmony_ci
308e1051a39Sopenharmony_ci    case NID_pkcs7_digest:
309e1051a39Sopenharmony_ci        return &cms->d.digestedData->encapContentInfo->eContentType;
310e1051a39Sopenharmony_ci
311e1051a39Sopenharmony_ci    case NID_pkcs7_encrypted:
312e1051a39Sopenharmony_ci        return &cms->d.encryptedData->encryptedContentInfo->contentType;
313e1051a39Sopenharmony_ci
314e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
315e1051a39Sopenharmony_ci        return &cms->d.authEnvelopedData->authEncryptedContentInfo
316e1051a39Sopenharmony_ci                                        ->contentType;
317e1051a39Sopenharmony_ci    case NID_id_smime_ct_authData:
318e1051a39Sopenharmony_ci        return &cms->d.authenticatedData->encapContentInfo->eContentType;
319e1051a39Sopenharmony_ci
320e1051a39Sopenharmony_ci    case NID_id_smime_ct_compressedData:
321e1051a39Sopenharmony_ci        return &cms->d.compressedData->encapContentInfo->eContentType;
322e1051a39Sopenharmony_ci
323e1051a39Sopenharmony_ci    default:
324e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
325e1051a39Sopenharmony_ci        return NULL;
326e1051a39Sopenharmony_ci
327e1051a39Sopenharmony_ci    }
328e1051a39Sopenharmony_ci}
329e1051a39Sopenharmony_ci
330e1051a39Sopenharmony_ciconst ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
331e1051a39Sopenharmony_ci{
332e1051a39Sopenharmony_ci    ASN1_OBJECT **petype;
333e1051a39Sopenharmony_ci    petype = cms_get0_econtent_type(cms);
334e1051a39Sopenharmony_ci    if (petype)
335e1051a39Sopenharmony_ci        return *petype;
336e1051a39Sopenharmony_ci    return NULL;
337e1051a39Sopenharmony_ci}
338e1051a39Sopenharmony_ci
339e1051a39Sopenharmony_ciint CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
340e1051a39Sopenharmony_ci{
341e1051a39Sopenharmony_ci    ASN1_OBJECT **petype, *etype;
342e1051a39Sopenharmony_ci
343e1051a39Sopenharmony_ci    petype = cms_get0_econtent_type(cms);
344e1051a39Sopenharmony_ci    if (petype == NULL)
345e1051a39Sopenharmony_ci        return 0;
346e1051a39Sopenharmony_ci    if (oid == NULL)
347e1051a39Sopenharmony_ci        return 1;
348e1051a39Sopenharmony_ci    etype = OBJ_dup(oid);
349e1051a39Sopenharmony_ci    if (etype == NULL)
350e1051a39Sopenharmony_ci        return 0;
351e1051a39Sopenharmony_ci    ASN1_OBJECT_free(*petype);
352e1051a39Sopenharmony_ci    *petype = etype;
353e1051a39Sopenharmony_ci    return 1;
354e1051a39Sopenharmony_ci}
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ciint CMS_is_detached(CMS_ContentInfo *cms)
357e1051a39Sopenharmony_ci{
358e1051a39Sopenharmony_ci    ASN1_OCTET_STRING **pos;
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci    pos = CMS_get0_content(cms);
361e1051a39Sopenharmony_ci    if (pos == NULL)
362e1051a39Sopenharmony_ci        return -1;
363e1051a39Sopenharmony_ci    if (*pos != NULL)
364e1051a39Sopenharmony_ci        return 0;
365e1051a39Sopenharmony_ci    return 1;
366e1051a39Sopenharmony_ci}
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_ciint CMS_set_detached(CMS_ContentInfo *cms, int detached)
369e1051a39Sopenharmony_ci{
370e1051a39Sopenharmony_ci    ASN1_OCTET_STRING **pos;
371e1051a39Sopenharmony_ci
372e1051a39Sopenharmony_ci    pos = CMS_get0_content(cms);
373e1051a39Sopenharmony_ci    if (pos == NULL)
374e1051a39Sopenharmony_ci        return 0;
375e1051a39Sopenharmony_ci    if (detached) {
376e1051a39Sopenharmony_ci        ASN1_OCTET_STRING_free(*pos);
377e1051a39Sopenharmony_ci        *pos = NULL;
378e1051a39Sopenharmony_ci        return 1;
379e1051a39Sopenharmony_ci    }
380e1051a39Sopenharmony_ci    if (*pos == NULL)
381e1051a39Sopenharmony_ci        *pos = ASN1_OCTET_STRING_new();
382e1051a39Sopenharmony_ci    if (*pos != NULL) {
383e1051a39Sopenharmony_ci        /*
384e1051a39Sopenharmony_ci         * NB: special flag to show content is created and not read in.
385e1051a39Sopenharmony_ci         */
386e1051a39Sopenharmony_ci        (*pos)->flags |= ASN1_STRING_FLAG_CONT;
387e1051a39Sopenharmony_ci        return 1;
388e1051a39Sopenharmony_ci    }
389e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
390e1051a39Sopenharmony_ci    return 0;
391e1051a39Sopenharmony_ci}
392e1051a39Sopenharmony_ci
393e1051a39Sopenharmony_ci/* Create a digest BIO from an X509_ALGOR structure */
394e1051a39Sopenharmony_ci
395e1051a39Sopenharmony_ciBIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
396e1051a39Sopenharmony_ci                                       const CMS_CTX *ctx)
397e1051a39Sopenharmony_ci{
398e1051a39Sopenharmony_ci    BIO *mdbio = NULL;
399e1051a39Sopenharmony_ci    const ASN1_OBJECT *digestoid;
400e1051a39Sopenharmony_ci    const EVP_MD *digest = NULL;
401e1051a39Sopenharmony_ci    EVP_MD *fetched_digest = NULL;
402e1051a39Sopenharmony_ci    char alg[OSSL_MAX_NAME_SIZE];
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci    X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
405e1051a39Sopenharmony_ci    OBJ_obj2txt(alg, sizeof(alg), digestoid, 0);
406e1051a39Sopenharmony_ci
407e1051a39Sopenharmony_ci    (void)ERR_set_mark();
408e1051a39Sopenharmony_ci    fetched_digest = EVP_MD_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
409e1051a39Sopenharmony_ci                                  ossl_cms_ctx_get0_propq(ctx));
410e1051a39Sopenharmony_ci
411e1051a39Sopenharmony_ci    if (fetched_digest != NULL)
412e1051a39Sopenharmony_ci        digest = fetched_digest;
413e1051a39Sopenharmony_ci    else
414e1051a39Sopenharmony_ci        digest = EVP_get_digestbyobj(digestoid);
415e1051a39Sopenharmony_ci    if (digest == NULL) {
416e1051a39Sopenharmony_ci        (void)ERR_clear_last_mark();
417e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
418e1051a39Sopenharmony_ci        goto err;
419e1051a39Sopenharmony_ci    }
420e1051a39Sopenharmony_ci    (void)ERR_pop_to_mark();
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_ci    mdbio = BIO_new(BIO_f_md());
423e1051a39Sopenharmony_ci    if (mdbio == NULL || BIO_set_md(mdbio, digest) <= 0) {
424e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR);
425e1051a39Sopenharmony_ci        goto err;
426e1051a39Sopenharmony_ci    }
427e1051a39Sopenharmony_ci    EVP_MD_free(fetched_digest);
428e1051a39Sopenharmony_ci    return mdbio;
429e1051a39Sopenharmony_ci err:
430e1051a39Sopenharmony_ci    EVP_MD_free(fetched_digest);
431e1051a39Sopenharmony_ci    BIO_free(mdbio);
432e1051a39Sopenharmony_ci    return NULL;
433e1051a39Sopenharmony_ci}
434e1051a39Sopenharmony_ci
435e1051a39Sopenharmony_ci/* Locate a message digest content from a BIO chain based on SignerInfo */
436e1051a39Sopenharmony_ci
437e1051a39Sopenharmony_ciint ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
438e1051a39Sopenharmony_ci                                      X509_ALGOR *mdalg)
439e1051a39Sopenharmony_ci{
440e1051a39Sopenharmony_ci    int nid;
441e1051a39Sopenharmony_ci    const ASN1_OBJECT *mdoid;
442e1051a39Sopenharmony_ci    X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
443e1051a39Sopenharmony_ci    nid = OBJ_obj2nid(mdoid);
444e1051a39Sopenharmony_ci    /* Look for digest type to match signature */
445e1051a39Sopenharmony_ci    for (;;) {
446e1051a39Sopenharmony_ci        EVP_MD_CTX *mtmp;
447e1051a39Sopenharmony_ci        chain = BIO_find_type(chain, BIO_TYPE_MD);
448e1051a39Sopenharmony_ci        if (chain == NULL) {
449e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
450e1051a39Sopenharmony_ci            return 0;
451e1051a39Sopenharmony_ci        }
452e1051a39Sopenharmony_ci        BIO_get_md_ctx(chain, &mtmp);
453e1051a39Sopenharmony_ci        if (EVP_MD_CTX_get_type(mtmp) == nid
454e1051a39Sopenharmony_ci            /*
455e1051a39Sopenharmony_ci             * Workaround for broken implementations that use signature
456e1051a39Sopenharmony_ci             * algorithm OID instead of digest.
457e1051a39Sopenharmony_ci             */
458e1051a39Sopenharmony_ci            || EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mtmp)) == nid)
459e1051a39Sopenharmony_ci            return EVP_MD_CTX_copy_ex(mctx, mtmp);
460e1051a39Sopenharmony_ci        chain = BIO_next(chain);
461e1051a39Sopenharmony_ci    }
462e1051a39Sopenharmony_ci}
463e1051a39Sopenharmony_ci
464e1051a39Sopenharmony_cistatic STACK_OF(CMS_CertificateChoices)
465e1051a39Sopenharmony_ci**cms_get0_certificate_choices(CMS_ContentInfo *cms)
466e1051a39Sopenharmony_ci{
467e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
468e1051a39Sopenharmony_ci
469e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
470e1051a39Sopenharmony_ci        return &cms->d.signedData->certificates;
471e1051a39Sopenharmony_ci
472e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
473e1051a39Sopenharmony_ci        if (cms->d.envelopedData->originatorInfo == NULL)
474e1051a39Sopenharmony_ci            return NULL;
475e1051a39Sopenharmony_ci        return &cms->d.envelopedData->originatorInfo->certificates;
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
478e1051a39Sopenharmony_ci        if (cms->d.authEnvelopedData->originatorInfo == NULL)
479e1051a39Sopenharmony_ci            return NULL;
480e1051a39Sopenharmony_ci        return &cms->d.authEnvelopedData->originatorInfo->certificates;
481e1051a39Sopenharmony_ci
482e1051a39Sopenharmony_ci    default:
483e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
484e1051a39Sopenharmony_ci        return NULL;
485e1051a39Sopenharmony_ci
486e1051a39Sopenharmony_ci    }
487e1051a39Sopenharmony_ci}
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ciCMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
490e1051a39Sopenharmony_ci{
491e1051a39Sopenharmony_ci    STACK_OF(CMS_CertificateChoices) **pcerts;
492e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
493e1051a39Sopenharmony_ci
494e1051a39Sopenharmony_ci    pcerts = cms_get0_certificate_choices(cms);
495e1051a39Sopenharmony_ci    if (pcerts == NULL)
496e1051a39Sopenharmony_ci        return NULL;
497e1051a39Sopenharmony_ci    if (*pcerts == NULL)
498e1051a39Sopenharmony_ci        *pcerts = sk_CMS_CertificateChoices_new_null();
499e1051a39Sopenharmony_ci    if (*pcerts == NULL)
500e1051a39Sopenharmony_ci        return NULL;
501e1051a39Sopenharmony_ci    cch = M_ASN1_new_of(CMS_CertificateChoices);
502e1051a39Sopenharmony_ci    if (!cch)
503e1051a39Sopenharmony_ci        return NULL;
504e1051a39Sopenharmony_ci    if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
505e1051a39Sopenharmony_ci        M_ASN1_free_of(cch, CMS_CertificateChoices);
506e1051a39Sopenharmony_ci        return NULL;
507e1051a39Sopenharmony_ci    }
508e1051a39Sopenharmony_ci    return cch;
509e1051a39Sopenharmony_ci}
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ciint CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
512e1051a39Sopenharmony_ci{
513e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
514e1051a39Sopenharmony_ci    STACK_OF(CMS_CertificateChoices) **pcerts;
515e1051a39Sopenharmony_ci    int i;
516e1051a39Sopenharmony_ci
517e1051a39Sopenharmony_ci    pcerts = cms_get0_certificate_choices(cms);
518e1051a39Sopenharmony_ci    if (pcerts == NULL)
519e1051a39Sopenharmony_ci        return 0;
520e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
521e1051a39Sopenharmony_ci        cch = sk_CMS_CertificateChoices_value(*pcerts, i);
522e1051a39Sopenharmony_ci        if (cch->type == CMS_CERTCHOICE_CERT) {
523e1051a39Sopenharmony_ci            if (!X509_cmp(cch->d.certificate, cert)) {
524e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_ALREADY_PRESENT);
525e1051a39Sopenharmony_ci                return 0;
526e1051a39Sopenharmony_ci            }
527e1051a39Sopenharmony_ci        }
528e1051a39Sopenharmony_ci    }
529e1051a39Sopenharmony_ci    cch = CMS_add0_CertificateChoices(cms);
530e1051a39Sopenharmony_ci    if (!cch)
531e1051a39Sopenharmony_ci        return 0;
532e1051a39Sopenharmony_ci    cch->type = CMS_CERTCHOICE_CERT;
533e1051a39Sopenharmony_ci    cch->d.certificate = cert;
534e1051a39Sopenharmony_ci    return 1;
535e1051a39Sopenharmony_ci}
536e1051a39Sopenharmony_ci
537e1051a39Sopenharmony_ciint CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
538e1051a39Sopenharmony_ci{
539e1051a39Sopenharmony_ci    int r;
540e1051a39Sopenharmony_ci    r = CMS_add0_cert(cms, cert);
541e1051a39Sopenharmony_ci    if (r > 0)
542e1051a39Sopenharmony_ci        X509_up_ref(cert);
543e1051a39Sopenharmony_ci    return r;
544e1051a39Sopenharmony_ci}
545e1051a39Sopenharmony_ci
546e1051a39Sopenharmony_cistatic STACK_OF(CMS_RevocationInfoChoice)
547e1051a39Sopenharmony_ci**cms_get0_revocation_choices(CMS_ContentInfo *cms)
548e1051a39Sopenharmony_ci{
549e1051a39Sopenharmony_ci    switch (OBJ_obj2nid(cms->contentType)) {
550e1051a39Sopenharmony_ci
551e1051a39Sopenharmony_ci    case NID_pkcs7_signed:
552e1051a39Sopenharmony_ci        return &cms->d.signedData->crls;
553e1051a39Sopenharmony_ci
554e1051a39Sopenharmony_ci    case NID_pkcs7_enveloped:
555e1051a39Sopenharmony_ci        if (cms->d.envelopedData->originatorInfo == NULL)
556e1051a39Sopenharmony_ci            return NULL;
557e1051a39Sopenharmony_ci        return &cms->d.envelopedData->originatorInfo->crls;
558e1051a39Sopenharmony_ci
559e1051a39Sopenharmony_ci    case NID_id_smime_ct_authEnvelopedData:
560e1051a39Sopenharmony_ci        if (cms->d.authEnvelopedData->originatorInfo == NULL)
561e1051a39Sopenharmony_ci            return NULL;
562e1051a39Sopenharmony_ci        return &cms->d.authEnvelopedData->originatorInfo->crls;
563e1051a39Sopenharmony_ci
564e1051a39Sopenharmony_ci    default:
565e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
566e1051a39Sopenharmony_ci        return NULL;
567e1051a39Sopenharmony_ci
568e1051a39Sopenharmony_ci    }
569e1051a39Sopenharmony_ci}
570e1051a39Sopenharmony_ci
571e1051a39Sopenharmony_ciCMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
572e1051a39Sopenharmony_ci{
573e1051a39Sopenharmony_ci    STACK_OF(CMS_RevocationInfoChoice) **pcrls;
574e1051a39Sopenharmony_ci    CMS_RevocationInfoChoice *rch;
575e1051a39Sopenharmony_ci
576e1051a39Sopenharmony_ci    pcrls = cms_get0_revocation_choices(cms);
577e1051a39Sopenharmony_ci    if (pcrls == NULL)
578e1051a39Sopenharmony_ci        return NULL;
579e1051a39Sopenharmony_ci    if (*pcrls == NULL)
580e1051a39Sopenharmony_ci        *pcrls = sk_CMS_RevocationInfoChoice_new_null();
581e1051a39Sopenharmony_ci    if (*pcrls == NULL)
582e1051a39Sopenharmony_ci        return NULL;
583e1051a39Sopenharmony_ci    rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
584e1051a39Sopenharmony_ci    if (rch == NULL)
585e1051a39Sopenharmony_ci        return NULL;
586e1051a39Sopenharmony_ci    if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
587e1051a39Sopenharmony_ci        M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
588e1051a39Sopenharmony_ci        return NULL;
589e1051a39Sopenharmony_ci    }
590e1051a39Sopenharmony_ci    return rch;
591e1051a39Sopenharmony_ci}
592e1051a39Sopenharmony_ci
593e1051a39Sopenharmony_ciint CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
594e1051a39Sopenharmony_ci{
595e1051a39Sopenharmony_ci    CMS_RevocationInfoChoice *rch;
596e1051a39Sopenharmony_ci    rch = CMS_add0_RevocationInfoChoice(cms);
597e1051a39Sopenharmony_ci    if (!rch)
598e1051a39Sopenharmony_ci        return 0;
599e1051a39Sopenharmony_ci    rch->type = CMS_REVCHOICE_CRL;
600e1051a39Sopenharmony_ci    rch->d.crl = crl;
601e1051a39Sopenharmony_ci    return 1;
602e1051a39Sopenharmony_ci}
603e1051a39Sopenharmony_ci
604e1051a39Sopenharmony_ciint CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
605e1051a39Sopenharmony_ci{
606e1051a39Sopenharmony_ci    if (!X509_CRL_up_ref(crl))
607e1051a39Sopenharmony_ci        return 0;
608e1051a39Sopenharmony_ci    if (CMS_add0_crl(cms, crl))
609e1051a39Sopenharmony_ci        return 1;
610e1051a39Sopenharmony_ci    X509_CRL_free(crl);
611e1051a39Sopenharmony_ci    return 0;
612e1051a39Sopenharmony_ci}
613e1051a39Sopenharmony_ci
614e1051a39Sopenharmony_ciSTACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
615e1051a39Sopenharmony_ci{
616e1051a39Sopenharmony_ci    STACK_OF(X509) *certs = NULL;
617e1051a39Sopenharmony_ci    CMS_CertificateChoices *cch;
618e1051a39Sopenharmony_ci    STACK_OF(CMS_CertificateChoices) **pcerts;
619e1051a39Sopenharmony_ci    int i;
620e1051a39Sopenharmony_ci
621e1051a39Sopenharmony_ci    pcerts = cms_get0_certificate_choices(cms);
622e1051a39Sopenharmony_ci    if (pcerts == NULL)
623e1051a39Sopenharmony_ci        return NULL;
624e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
625e1051a39Sopenharmony_ci        cch = sk_CMS_CertificateChoices_value(*pcerts, i);
626e1051a39Sopenharmony_ci        if (cch->type == 0) {
627e1051a39Sopenharmony_ci            if (!ossl_x509_add_cert_new(&certs, cch->d.certificate,
628e1051a39Sopenharmony_ci                                        X509_ADD_FLAG_UP_REF)) {
629e1051a39Sopenharmony_ci                sk_X509_pop_free(certs, X509_free);
630e1051a39Sopenharmony_ci                return NULL;
631e1051a39Sopenharmony_ci            }
632e1051a39Sopenharmony_ci        }
633e1051a39Sopenharmony_ci    }
634e1051a39Sopenharmony_ci    return certs;
635e1051a39Sopenharmony_ci
636e1051a39Sopenharmony_ci}
637e1051a39Sopenharmony_ci
638e1051a39Sopenharmony_ciSTACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
639e1051a39Sopenharmony_ci{
640e1051a39Sopenharmony_ci    STACK_OF(X509_CRL) *crls = NULL;
641e1051a39Sopenharmony_ci    STACK_OF(CMS_RevocationInfoChoice) **pcrls;
642e1051a39Sopenharmony_ci    CMS_RevocationInfoChoice *rch;
643e1051a39Sopenharmony_ci    int i;
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_ci    pcrls = cms_get0_revocation_choices(cms);
646e1051a39Sopenharmony_ci    if (pcrls == NULL)
647e1051a39Sopenharmony_ci        return NULL;
648e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
649e1051a39Sopenharmony_ci        rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
650e1051a39Sopenharmony_ci        if (rch->type == 0) {
651e1051a39Sopenharmony_ci            if (!crls) {
652e1051a39Sopenharmony_ci                crls = sk_X509_CRL_new_null();
653e1051a39Sopenharmony_ci                if (!crls)
654e1051a39Sopenharmony_ci                    return NULL;
655e1051a39Sopenharmony_ci            }
656e1051a39Sopenharmony_ci            if (!sk_X509_CRL_push(crls, rch->d.crl)) {
657e1051a39Sopenharmony_ci                sk_X509_CRL_pop_free(crls, X509_CRL_free);
658e1051a39Sopenharmony_ci                return NULL;
659e1051a39Sopenharmony_ci            }
660e1051a39Sopenharmony_ci            X509_CRL_up_ref(rch->d.crl);
661e1051a39Sopenharmony_ci        }
662e1051a39Sopenharmony_ci    }
663e1051a39Sopenharmony_ci    return crls;
664e1051a39Sopenharmony_ci}
665e1051a39Sopenharmony_ci
666e1051a39Sopenharmony_ciint ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
667e1051a39Sopenharmony_ci{
668e1051a39Sopenharmony_ci    int ret;
669e1051a39Sopenharmony_ci    ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
670e1051a39Sopenharmony_ci    if (ret)
671e1051a39Sopenharmony_ci        return ret;
672e1051a39Sopenharmony_ci    return ASN1_INTEGER_cmp(ias->serialNumber, X509_get0_serialNumber(cert));
673e1051a39Sopenharmony_ci}
674e1051a39Sopenharmony_ci
675e1051a39Sopenharmony_ciint ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
676e1051a39Sopenharmony_ci{
677e1051a39Sopenharmony_ci    const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert);
678e1051a39Sopenharmony_ci
679e1051a39Sopenharmony_ci    if (cert_keyid == NULL)
680e1051a39Sopenharmony_ci        return -1;
681e1051a39Sopenharmony_ci    return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
682e1051a39Sopenharmony_ci}
683e1051a39Sopenharmony_ci
684e1051a39Sopenharmony_ciint ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
685e1051a39Sopenharmony_ci{
686e1051a39Sopenharmony_ci    CMS_IssuerAndSerialNumber *ias;
687e1051a39Sopenharmony_ci    ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber);
688e1051a39Sopenharmony_ci    if (!ias)
689e1051a39Sopenharmony_ci        goto err;
690e1051a39Sopenharmony_ci    if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
691e1051a39Sopenharmony_ci        goto err;
692e1051a39Sopenharmony_ci    if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert)))
693e1051a39Sopenharmony_ci        goto err;
694e1051a39Sopenharmony_ci    M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber);
695e1051a39Sopenharmony_ci    *pias = ias;
696e1051a39Sopenharmony_ci    return 1;
697e1051a39Sopenharmony_ci err:
698e1051a39Sopenharmony_ci    M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber);
699e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
700e1051a39Sopenharmony_ci    return 0;
701e1051a39Sopenharmony_ci}
702e1051a39Sopenharmony_ci
703e1051a39Sopenharmony_ciint ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
704e1051a39Sopenharmony_ci{
705e1051a39Sopenharmony_ci    ASN1_OCTET_STRING *keyid = NULL;
706e1051a39Sopenharmony_ci    const ASN1_OCTET_STRING *cert_keyid;
707e1051a39Sopenharmony_ci    cert_keyid = X509_get0_subject_key_id(cert);
708e1051a39Sopenharmony_ci    if (cert_keyid == NULL) {
709e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
710e1051a39Sopenharmony_ci        return 0;
711e1051a39Sopenharmony_ci    }
712e1051a39Sopenharmony_ci    keyid = ASN1_STRING_dup(cert_keyid);
713e1051a39Sopenharmony_ci    if (!keyid) {
714e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
715e1051a39Sopenharmony_ci        return 0;
716e1051a39Sopenharmony_ci    }
717e1051a39Sopenharmony_ci    ASN1_OCTET_STRING_free(*pkeyid);
718e1051a39Sopenharmony_ci    *pkeyid = keyid;
719e1051a39Sopenharmony_ci    return 1;
720e1051a39Sopenharmony_ci}
721