1183234Ssimon/* crypto/cms/cms_sd.c */
2296341Sdelphij/*
3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4183234Ssimon * project.
5183234Ssimon */
6183234Ssimon/* ====================================================================
7183234Ssimon * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8183234Ssimon *
9183234Ssimon * Redistribution and use in source and binary forms, with or without
10183234Ssimon * modification, are permitted provided that the following conditions
11183234Ssimon * are met:
12183234Ssimon *
13183234Ssimon * 1. Redistributions of source code must retain the above copyright
14296341Sdelphij *    notice, this list of conditions and the following disclaimer.
15183234Ssimon *
16183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright
17183234Ssimon *    notice, this list of conditions and the following disclaimer in
18183234Ssimon *    the documentation and/or other materials provided with the
19183234Ssimon *    distribution.
20183234Ssimon *
21183234Ssimon * 3. All advertising materials mentioning features or use of this
22183234Ssimon *    software must display the following acknowledgment:
23183234Ssimon *    "This product includes software developed by the OpenSSL Project
24183234Ssimon *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25183234Ssimon *
26183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27183234Ssimon *    endorse or promote products derived from this software without
28183234Ssimon *    prior written permission. For written permission, please contact
29183234Ssimon *    licensing@OpenSSL.org.
30183234Ssimon *
31183234Ssimon * 5. Products derived from this software may not be called "OpenSSL"
32183234Ssimon *    nor may "OpenSSL" appear in their names without prior written
33183234Ssimon *    permission of the OpenSSL Project.
34183234Ssimon *
35183234Ssimon * 6. Redistributions of any form whatsoever must retain the following
36183234Ssimon *    acknowledgment:
37183234Ssimon *    "This product includes software developed by the OpenSSL Project
38183234Ssimon *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39183234Ssimon *
40183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43183234Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
52183234Ssimon * ====================================================================
53183234Ssimon */
54183234Ssimon
55183234Ssimon#include "cryptlib.h"
56183234Ssimon#include <openssl/asn1t.h>
57183234Ssimon#include <openssl/pem.h>
58183234Ssimon#include <openssl/x509v3.h>
59183234Ssimon#include <openssl/err.h>
60183234Ssimon#include <openssl/cms.h>
61183234Ssimon#include "cms_lcl.h"
62238405Sjkim#include "asn1_locl.h"
63183234Ssimon
64183234Ssimon/* CMS SignedData Utilities */
65183234Ssimon
66183234SsimonDECLARE_ASN1_ITEM(CMS_SignedData)
67183234Ssimon
68183234Ssimonstatic CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms)
69296341Sdelphij{
70296341Sdelphij    if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
71296341Sdelphij        CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
72296341Sdelphij        return NULL;
73296341Sdelphij    }
74296341Sdelphij    return cms->d.signedData;
75296341Sdelphij}
76183234Ssimon
77183234Ssimonstatic CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms)
78296341Sdelphij{
79296341Sdelphij    if (cms->d.other == NULL) {
80296341Sdelphij        cms->d.signedData = M_ASN1_new_of(CMS_SignedData);
81296341Sdelphij        if (!cms->d.signedData) {
82296341Sdelphij            CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE);
83296341Sdelphij            return NULL;
84296341Sdelphij        }
85296341Sdelphij        cms->d.signedData->version = 1;
86296341Sdelphij        cms->d.signedData->encapContentInfo->eContentType =
87296341Sdelphij            OBJ_nid2obj(NID_pkcs7_data);
88296341Sdelphij        cms->d.signedData->encapContentInfo->partial = 1;
89296341Sdelphij        ASN1_OBJECT_free(cms->contentType);
90296341Sdelphij        cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
91296341Sdelphij        return cms->d.signedData;
92296341Sdelphij    }
93296341Sdelphij    return cms_get0_signed(cms);
94296341Sdelphij}
95183234Ssimon
96183234Ssimon/* Just initialize SignedData e.g. for certs only structure */
97183234Ssimon
98183234Ssimonint CMS_SignedData_init(CMS_ContentInfo *cms)
99296341Sdelphij{
100296341Sdelphij    if (cms_signed_data_init(cms))
101296341Sdelphij        return 1;
102296341Sdelphij    else
103296341Sdelphij        return 0;
104296341Sdelphij}
105183234Ssimon
106183234Ssimon/* Check structures and fixup version numbers (if necessary) */
107183234Ssimon
108183234Ssimonstatic void cms_sd_set_version(CMS_SignedData *sd)
109296341Sdelphij{
110296341Sdelphij    int i;
111296341Sdelphij    CMS_CertificateChoices *cch;
112296341Sdelphij    CMS_RevocationInfoChoice *rch;
113296341Sdelphij    CMS_SignerInfo *si;
114183234Ssimon
115296341Sdelphij    for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
116296341Sdelphij        cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
117296341Sdelphij        if (cch->type == CMS_CERTCHOICE_OTHER) {
118296341Sdelphij            if (sd->version < 5)
119296341Sdelphij                sd->version = 5;
120296341Sdelphij        } else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
121296341Sdelphij            if (sd->version < 4)
122296341Sdelphij                sd->version = 4;
123296341Sdelphij        } else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
124296341Sdelphij            if (sd->version < 3)
125296341Sdelphij                sd->version = 3;
126296341Sdelphij        }
127296341Sdelphij    }
128183234Ssimon
129296341Sdelphij    for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
130296341Sdelphij        rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
131296341Sdelphij        if (rch->type == CMS_REVCHOICE_OTHER) {
132296341Sdelphij            if (sd->version < 5)
133296341Sdelphij                sd->version = 5;
134296341Sdelphij        }
135296341Sdelphij    }
136183234Ssimon
137296341Sdelphij    if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
138296341Sdelphij        && (sd->version < 3))
139296341Sdelphij        sd->version = 3;
140183234Ssimon
141296341Sdelphij    for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
142296341Sdelphij        si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
143296341Sdelphij        if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
144296341Sdelphij            if (si->version < 3)
145296341Sdelphij                si->version = 3;
146296341Sdelphij            if (sd->version < 3)
147296341Sdelphij                sd->version = 3;
148296341Sdelphij        } else if (si->version < 1)
149296341Sdelphij            si->version = 1;
150296341Sdelphij    }
151183234Ssimon
152296341Sdelphij    if (sd->version < 1)
153296341Sdelphij        sd->version = 1;
154183234Ssimon
155296341Sdelphij}
156296341Sdelphij
157183234Ssimon/* Copy an existing messageDigest value */
158183234Ssimon
159183234Ssimonstatic int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
160296341Sdelphij{
161296341Sdelphij    STACK_OF(CMS_SignerInfo) *sinfos;
162296341Sdelphij    CMS_SignerInfo *sitmp;
163296341Sdelphij    int i;
164296341Sdelphij    sinfos = CMS_get0_SignerInfos(cms);
165296341Sdelphij    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
166296341Sdelphij        ASN1_OCTET_STRING *messageDigest;
167296341Sdelphij        sitmp = sk_CMS_SignerInfo_value(sinfos, i);
168296341Sdelphij        if (sitmp == si)
169296341Sdelphij            continue;
170296341Sdelphij        if (CMS_signed_get_attr_count(sitmp) < 0)
171296341Sdelphij            continue;
172296341Sdelphij        if (OBJ_cmp(si->digestAlgorithm->algorithm,
173296341Sdelphij                    sitmp->digestAlgorithm->algorithm))
174296341Sdelphij            continue;
175296341Sdelphij        messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
176296341Sdelphij                                                    OBJ_nid2obj
177296341Sdelphij                                                    (NID_pkcs9_messageDigest),
178296341Sdelphij                                                    -3, V_ASN1_OCTET_STRING);
179296341Sdelphij        if (!messageDigest) {
180296341Sdelphij            CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST,
181296341Sdelphij                   CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
182296341Sdelphij            return 0;
183296341Sdelphij        }
184183234Ssimon
185296341Sdelphij        if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
186296341Sdelphij                                        V_ASN1_OCTET_STRING,
187296341Sdelphij                                        messageDigest, -1))
188296341Sdelphij            return 1;
189296341Sdelphij        else
190296341Sdelphij            return 0;
191296341Sdelphij    }
192296341Sdelphij    CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST);
193296341Sdelphij    return 0;
194296341Sdelphij}
195183234Ssimon
196183234Ssimonint cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
197296341Sdelphij{
198296341Sdelphij    switch (type) {
199296341Sdelphij    case CMS_SIGNERINFO_ISSUER_SERIAL:
200296341Sdelphij        sid->d.issuerAndSerialNumber =
201296341Sdelphij            M_ASN1_new_of(CMS_IssuerAndSerialNumber);
202296341Sdelphij        if (!sid->d.issuerAndSerialNumber)
203296341Sdelphij            goto merr;
204296341Sdelphij        if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer,
205296341Sdelphij                           X509_get_issuer_name(cert)))
206296341Sdelphij            goto merr;
207296341Sdelphij        if (!ASN1_STRING_copy(sid->d.issuerAndSerialNumber->serialNumber,
208296341Sdelphij                              X509_get_serialNumber(cert)))
209296341Sdelphij            goto merr;
210296341Sdelphij        break;
211183234Ssimon
212296341Sdelphij    case CMS_SIGNERINFO_KEYIDENTIFIER:
213296341Sdelphij        if (!cert->skid) {
214296341Sdelphij            CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER,
215296341Sdelphij                   CMS_R_CERTIFICATE_HAS_NO_KEYID);
216296341Sdelphij            return 0;
217296341Sdelphij        }
218296341Sdelphij        sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid);
219296341Sdelphij        if (!sid->d.subjectKeyIdentifier)
220296341Sdelphij            goto merr;
221296341Sdelphij        break;
222183234Ssimon
223296341Sdelphij    default:
224296341Sdelphij        CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID);
225296341Sdelphij        return 0;
226296341Sdelphij    }
227183234Ssimon
228296341Sdelphij    sid->type = type;
229183234Ssimon
230296341Sdelphij    return 1;
231183234Ssimon
232296341Sdelphij merr:
233296341Sdelphij    CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE);
234296341Sdelphij    return 0;
235183234Ssimon
236296341Sdelphij}
237183234Ssimon
238183234Ssimonint cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
239296341Sdelphij                                        ASN1_OCTET_STRING **keyid,
240296341Sdelphij                                        X509_NAME **issuer,
241296341Sdelphij                                        ASN1_INTEGER **sno)
242296341Sdelphij{
243296341Sdelphij    if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
244296341Sdelphij        if (issuer)
245296341Sdelphij            *issuer = sid->d.issuerAndSerialNumber->issuer;
246296341Sdelphij        if (sno)
247296341Sdelphij            *sno = sid->d.issuerAndSerialNumber->serialNumber;
248296341Sdelphij    } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
249296341Sdelphij        if (keyid)
250296341Sdelphij            *keyid = sid->d.subjectKeyIdentifier;
251296341Sdelphij    } else
252296341Sdelphij        return 0;
253296341Sdelphij    return 1;
254296341Sdelphij}
255183234Ssimon
256183234Ssimonint cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert)
257296341Sdelphij{
258296341Sdelphij    int ret;
259296341Sdelphij    if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) {
260296341Sdelphij        ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer,
261296341Sdelphij                            X509_get_issuer_name(cert));
262296341Sdelphij        if (ret)
263296341Sdelphij            return ret;
264296341Sdelphij        return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber,
265296341Sdelphij                                X509_get_serialNumber(cert));
266296341Sdelphij    } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
267296341Sdelphij        X509_check_purpose(cert, -1, -1);
268296341Sdelphij        if (!cert->skid)
269296341Sdelphij            return -1;
270296341Sdelphij        return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier, cert->skid);
271296341Sdelphij    } else
272296341Sdelphij        return -1;
273296341Sdelphij}
274183234Ssimon
275183234SsimonCMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
276296341Sdelphij                                X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
277296341Sdelphij                                unsigned int flags)
278296341Sdelphij{
279296341Sdelphij    CMS_SignedData *sd;
280296341Sdelphij    CMS_SignerInfo *si = NULL;
281296341Sdelphij    X509_ALGOR *alg;
282296341Sdelphij    int i, type;
283296341Sdelphij    if (!X509_check_private_key(signer, pk)) {
284296341Sdelphij        CMSerr(CMS_F_CMS_ADD1_SIGNER,
285296341Sdelphij               CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
286296341Sdelphij        return NULL;
287296341Sdelphij    }
288296341Sdelphij    sd = cms_signed_data_init(cms);
289296341Sdelphij    if (!sd)
290296341Sdelphij        goto err;
291296341Sdelphij    si = M_ASN1_new_of(CMS_SignerInfo);
292296341Sdelphij    if (!si)
293296341Sdelphij        goto merr;
294296341Sdelphij    X509_check_purpose(signer, -1, -1);
295183234Ssimon
296296341Sdelphij    CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
297296341Sdelphij    CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
298183234Ssimon
299296341Sdelphij    si->pkey = pk;
300296341Sdelphij    si->signer = signer;
301183234Ssimon
302296341Sdelphij    if (flags & CMS_USE_KEYID) {
303296341Sdelphij        si->version = 3;
304296341Sdelphij        if (sd->version < 3)
305296341Sdelphij            sd->version = 3;
306296341Sdelphij        type = CMS_SIGNERINFO_KEYIDENTIFIER;
307296341Sdelphij    } else {
308296341Sdelphij        type = CMS_SIGNERINFO_ISSUER_SERIAL;
309296341Sdelphij        si->version = 1;
310296341Sdelphij    }
311183234Ssimon
312296341Sdelphij    if (!cms_set1_SignerIdentifier(si->sid, signer, type))
313296341Sdelphij        goto err;
314183234Ssimon
315296341Sdelphij    if (md == NULL) {
316296341Sdelphij        int def_nid;
317296341Sdelphij        if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
318296341Sdelphij            goto err;
319296341Sdelphij        md = EVP_get_digestbynid(def_nid);
320296341Sdelphij        if (md == NULL) {
321296341Sdelphij            CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
322296341Sdelphij            goto err;
323296341Sdelphij        }
324296341Sdelphij    }
325183234Ssimon
326296341Sdelphij    if (!md) {
327296341Sdelphij        CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
328296341Sdelphij        goto err;
329296341Sdelphij    }
330183234Ssimon
331296341Sdelphij    cms_DigestAlgorithm_set(si->digestAlgorithm, md);
332183234Ssimon
333296341Sdelphij    /* See if digest is present in digestAlgorithms */
334296341Sdelphij    for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
335296341Sdelphij        ASN1_OBJECT *aoid;
336296341Sdelphij        alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
337296341Sdelphij        X509_ALGOR_get0(&aoid, NULL, NULL, alg);
338296341Sdelphij        if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
339296341Sdelphij            break;
340296341Sdelphij    }
341183234Ssimon
342296341Sdelphij    if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
343296341Sdelphij        alg = X509_ALGOR_new();
344296341Sdelphij        if (!alg)
345296341Sdelphij            goto merr;
346296341Sdelphij        cms_DigestAlgorithm_set(alg, md);
347296341Sdelphij        if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
348296341Sdelphij            X509_ALGOR_free(alg);
349296341Sdelphij            goto merr;
350296341Sdelphij        }
351296341Sdelphij    }
352183234Ssimon
353296341Sdelphij    if (pk->ameth && pk->ameth->pkey_ctrl) {
354296341Sdelphij        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, 0, si);
355296341Sdelphij        if (i == -2) {
356296341Sdelphij            CMSerr(CMS_F_CMS_ADD1_SIGNER,
357296341Sdelphij                   CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
358296341Sdelphij            goto err;
359296341Sdelphij        }
360296341Sdelphij        if (i <= 0) {
361296341Sdelphij            CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE);
362296341Sdelphij            goto err;
363296341Sdelphij        }
364296341Sdelphij    }
365183234Ssimon
366296341Sdelphij    if (!(flags & CMS_NOATTR)) {
367296341Sdelphij        /*
368296341Sdelphij         * Initialialize signed attributes strutucture so other attributes
369296341Sdelphij         * such as signing time etc are added later even if we add none here.
370296341Sdelphij         */
371296341Sdelphij        if (!si->signedAttrs) {
372296341Sdelphij            si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
373296341Sdelphij            if (!si->signedAttrs)
374296341Sdelphij                goto merr;
375296341Sdelphij        }
376183234Ssimon
377296341Sdelphij        if (!(flags & CMS_NOSMIMECAP)) {
378296341Sdelphij            STACK_OF(X509_ALGOR) *smcap = NULL;
379296341Sdelphij            i = CMS_add_standard_smimecap(&smcap);
380296341Sdelphij            if (i)
381296341Sdelphij                i = CMS_add_smimecap(si, smcap);
382296341Sdelphij            sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
383296341Sdelphij            if (!i)
384296341Sdelphij                goto merr;
385296341Sdelphij        }
386296341Sdelphij        if (flags & CMS_REUSE_DIGEST) {
387296341Sdelphij            if (!cms_copy_messageDigest(cms, si))
388296341Sdelphij                goto err;
389296341Sdelphij            if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si))
390296341Sdelphij                goto err;
391296341Sdelphij        }
392296341Sdelphij    }
393183234Ssimon
394296341Sdelphij    if (!(flags & CMS_NOCERTS)) {
395296341Sdelphij        /* NB ignore -1 return for duplicate cert */
396296341Sdelphij        if (!CMS_add1_cert(cms, signer))
397296341Sdelphij            goto merr;
398296341Sdelphij    }
399183234Ssimon
400296341Sdelphij    if (!sd->signerInfos)
401296341Sdelphij        sd->signerInfos = sk_CMS_SignerInfo_new_null();
402296341Sdelphij    if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
403296341Sdelphij        goto merr;
404183234Ssimon
405296341Sdelphij    return si;
406183234Ssimon
407296341Sdelphij merr:
408296341Sdelphij    CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
409296341Sdelphij err:
410296341Sdelphij    if (si)
411296341Sdelphij        M_ASN1_free_of(si, CMS_SignerInfo);
412296341Sdelphij    return NULL;
413183234Ssimon
414296341Sdelphij}
415183234Ssimon
416183234Ssimonstatic int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
417296341Sdelphij{
418296341Sdelphij    ASN1_TIME *tt;
419296341Sdelphij    int r = 0;
420296341Sdelphij    if (t)
421296341Sdelphij        tt = t;
422296341Sdelphij    else
423296341Sdelphij        tt = X509_gmtime_adj(NULL, 0);
424183234Ssimon
425296341Sdelphij    if (!tt)
426296341Sdelphij        goto merr;
427183234Ssimon
428296341Sdelphij    if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
429296341Sdelphij                                    tt->type, tt, -1) <= 0)
430296341Sdelphij        goto merr;
431183234Ssimon
432296341Sdelphij    r = 1;
433183234Ssimon
434296341Sdelphij merr:
435183234Ssimon
436296341Sdelphij    if (!t)
437296341Sdelphij        ASN1_TIME_free(tt);
438183234Ssimon
439296341Sdelphij    if (!r)
440296341Sdelphij        CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE);
441183234Ssimon
442296341Sdelphij    return r;
443183234Ssimon
444296341Sdelphij}
445183234Ssimon
446183234SsimonSTACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
447296341Sdelphij{
448296341Sdelphij    CMS_SignedData *sd;
449296341Sdelphij    sd = cms_get0_signed(cms);
450296341Sdelphij    if (!sd)
451296341Sdelphij        return NULL;
452296341Sdelphij    return sd->signerInfos;
453296341Sdelphij}
454183234Ssimon
455183234SsimonSTACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
456296341Sdelphij{
457296341Sdelphij    STACK_OF(X509) *signers = NULL;
458296341Sdelphij    STACK_OF(CMS_SignerInfo) *sinfos;
459296341Sdelphij    CMS_SignerInfo *si;
460296341Sdelphij    int i;
461296341Sdelphij    sinfos = CMS_get0_SignerInfos(cms);
462296341Sdelphij    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
463296341Sdelphij        si = sk_CMS_SignerInfo_value(sinfos, i);
464296341Sdelphij        if (si->signer) {
465296341Sdelphij            if (!signers) {
466296341Sdelphij                signers = sk_X509_new_null();
467296341Sdelphij                if (!signers)
468296341Sdelphij                    return NULL;
469296341Sdelphij            }
470296341Sdelphij            if (!sk_X509_push(signers, si->signer)) {
471296341Sdelphij                sk_X509_free(signers);
472296341Sdelphij                return NULL;
473296341Sdelphij            }
474296341Sdelphij        }
475296341Sdelphij    }
476296341Sdelphij    return signers;
477296341Sdelphij}
478183234Ssimon
479183234Ssimonvoid CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
480296341Sdelphij{
481296341Sdelphij    if (signer) {
482296341Sdelphij        CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
483296341Sdelphij        if (si->pkey)
484296341Sdelphij            EVP_PKEY_free(si->pkey);
485296341Sdelphij        si->pkey = X509_get_pubkey(signer);
486296341Sdelphij    }
487296341Sdelphij    if (si->signer)
488296341Sdelphij        X509_free(si->signer);
489296341Sdelphij    si->signer = signer;
490296341Sdelphij}
491183234Ssimon
492183234Ssimonint CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
493296341Sdelphij                                  ASN1_OCTET_STRING **keyid,
494296341Sdelphij                                  X509_NAME **issuer, ASN1_INTEGER **sno)
495296341Sdelphij{
496296341Sdelphij    return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno);
497296341Sdelphij}
498183234Ssimon
499183234Ssimonint CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
500296341Sdelphij{
501296341Sdelphij    return cms_SignerIdentifier_cert_cmp(si->sid, cert);
502296341Sdelphij}
503183234Ssimon
504183234Ssimonint CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
505296341Sdelphij                           unsigned int flags)
506296341Sdelphij{
507296341Sdelphij    CMS_SignedData *sd;
508296341Sdelphij    CMS_SignerInfo *si;
509296341Sdelphij    CMS_CertificateChoices *cch;
510296341Sdelphij    STACK_OF(CMS_CertificateChoices) *certs;
511296341Sdelphij    X509 *x;
512296341Sdelphij    int i, j;
513296341Sdelphij    int ret = 0;
514296341Sdelphij    sd = cms_get0_signed(cms);
515296341Sdelphij    if (!sd)
516296341Sdelphij        return -1;
517296341Sdelphij    certs = sd->certificates;
518296341Sdelphij    for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
519296341Sdelphij        si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
520296341Sdelphij        if (si->signer)
521296341Sdelphij            continue;
522183234Ssimon
523296341Sdelphij        for (j = 0; j < sk_X509_num(scerts); j++) {
524296341Sdelphij            x = sk_X509_value(scerts, j);
525296341Sdelphij            if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
526296341Sdelphij                CMS_SignerInfo_set1_signer_cert(si, x);
527296341Sdelphij                ret++;
528296341Sdelphij                break;
529296341Sdelphij            }
530296341Sdelphij        }
531183234Ssimon
532296341Sdelphij        if (si->signer || (flags & CMS_NOINTERN))
533296341Sdelphij            continue;
534183234Ssimon
535296341Sdelphij        for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
536296341Sdelphij            cch = sk_CMS_CertificateChoices_value(certs, j);
537296341Sdelphij            if (cch->type != 0)
538296341Sdelphij                continue;
539296341Sdelphij            x = cch->d.certificate;
540296341Sdelphij            if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
541296341Sdelphij                CMS_SignerInfo_set1_signer_cert(si, x);
542296341Sdelphij                ret++;
543296341Sdelphij                break;
544296341Sdelphij            }
545296341Sdelphij        }
546296341Sdelphij    }
547296341Sdelphij    return ret;
548296341Sdelphij}
549183234Ssimon
550296341Sdelphijvoid CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
551296341Sdelphij                              X509 **signer, X509_ALGOR **pdig,
552296341Sdelphij                              X509_ALGOR **psig)
553296341Sdelphij{
554296341Sdelphij    if (pk)
555296341Sdelphij        *pk = si->pkey;
556296341Sdelphij    if (signer)
557296341Sdelphij        *signer = si->signer;
558296341Sdelphij    if (pdig)
559296341Sdelphij        *pdig = si->digestAlgorithm;
560296341Sdelphij    if (psig)
561296341Sdelphij        *psig = si->signatureAlgorithm;
562296341Sdelphij}
563183234Ssimon
564183234Ssimonstatic int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
565296341Sdelphij                                       CMS_SignerInfo *si, BIO *chain)
566296341Sdelphij{
567296341Sdelphij    EVP_MD_CTX mctx;
568296341Sdelphij    int r = 0;
569296341Sdelphij    EVP_MD_CTX_init(&mctx);
570183234Ssimon
571296341Sdelphij    if (!si->pkey) {
572296341Sdelphij        CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
573296341Sdelphij        return 0;
574296341Sdelphij    }
575183234Ssimon
576296341Sdelphij    if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
577296341Sdelphij        goto err;
578183234Ssimon
579296341Sdelphij    /*
580296341Sdelphij     * If any signed attributes calculate and add messageDigest attribute
581296341Sdelphij     */
582183234Ssimon
583296341Sdelphij    if (CMS_signed_get_attr_count(si) >= 0) {
584296341Sdelphij        ASN1_OBJECT *ctype =
585296341Sdelphij            cms->d.signedData->encapContentInfo->eContentType;
586296341Sdelphij        unsigned char md[EVP_MAX_MD_SIZE];
587296341Sdelphij        unsigned int mdlen;
588296341Sdelphij        if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
589296341Sdelphij            goto err;
590296341Sdelphij        if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
591296341Sdelphij                                         V_ASN1_OCTET_STRING, md, mdlen))
592296341Sdelphij            goto err;
593296341Sdelphij        /* Copy content type across */
594296341Sdelphij        if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
595296341Sdelphij                                        V_ASN1_OBJECT, ctype, -1) <= 0)
596296341Sdelphij            goto err;
597296341Sdelphij        if (!CMS_SignerInfo_sign(si))
598296341Sdelphij            goto err;
599296341Sdelphij    } else {
600296341Sdelphij        unsigned char *sig;
601296341Sdelphij        unsigned int siglen;
602296341Sdelphij        sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
603296341Sdelphij        if (!sig) {
604296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
605296341Sdelphij            goto err;
606296341Sdelphij        }
607296341Sdelphij        if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey)) {
608296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR);
609296341Sdelphij            OPENSSL_free(sig);
610296341Sdelphij            goto err;
611296341Sdelphij        }
612296341Sdelphij        ASN1_STRING_set0(si->signature, sig, siglen);
613296341Sdelphij    }
614183234Ssimon
615296341Sdelphij    r = 1;
616183234Ssimon
617296341Sdelphij err:
618296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
619296341Sdelphij    return r;
620183234Ssimon
621296341Sdelphij}
622183234Ssimon
623183234Ssimonint cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
624296341Sdelphij{
625296341Sdelphij    STACK_OF(CMS_SignerInfo) *sinfos;
626296341Sdelphij    CMS_SignerInfo *si;
627296341Sdelphij    int i;
628296341Sdelphij    sinfos = CMS_get0_SignerInfos(cms);
629296341Sdelphij    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
630296341Sdelphij        si = sk_CMS_SignerInfo_value(sinfos, i);
631296341Sdelphij        if (!cms_SignerInfo_content_sign(cms, si, chain))
632296341Sdelphij            return 0;
633296341Sdelphij    }
634296341Sdelphij    cms->d.signedData->encapContentInfo->partial = 0;
635296341Sdelphij    return 1;
636296341Sdelphij}
637183234Ssimon
638183234Ssimonint CMS_SignerInfo_sign(CMS_SignerInfo *si)
639296341Sdelphij{
640296341Sdelphij    EVP_MD_CTX mctx;
641296341Sdelphij    EVP_PKEY_CTX *pctx;
642296341Sdelphij    unsigned char *abuf = NULL;
643296341Sdelphij    int alen;
644296341Sdelphij    size_t siglen;
645296341Sdelphij    const EVP_MD *md = NULL;
646183234Ssimon
647296341Sdelphij    md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
648296341Sdelphij    if (md == NULL)
649296341Sdelphij        return 0;
650183234Ssimon
651296341Sdelphij    EVP_MD_CTX_init(&mctx);
652183234Ssimon
653296341Sdelphij    if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
654296341Sdelphij        if (!cms_add1_signingTime(si, NULL))
655296341Sdelphij            goto err;
656296341Sdelphij    }
657183234Ssimon
658296341Sdelphij    if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
659296341Sdelphij        goto err;
660183234Ssimon
661296341Sdelphij    if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
662296341Sdelphij                          EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
663296341Sdelphij        CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
664296341Sdelphij        goto err;
665296341Sdelphij    }
666183234Ssimon
667296341Sdelphij    alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
668296341Sdelphij                         ASN1_ITEM_rptr(CMS_Attributes_Sign));
669296341Sdelphij    if (!abuf)
670296341Sdelphij        goto err;
671296341Sdelphij    if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
672296341Sdelphij        goto err;
673296341Sdelphij    if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
674296341Sdelphij        goto err;
675296341Sdelphij    OPENSSL_free(abuf);
676296341Sdelphij    abuf = OPENSSL_malloc(siglen);
677296341Sdelphij    if (!abuf)
678296341Sdelphij        goto err;
679296341Sdelphij    if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
680296341Sdelphij        goto err;
681238405Sjkim
682296341Sdelphij    if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
683296341Sdelphij                          EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
684296341Sdelphij        CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
685296341Sdelphij        goto err;
686296341Sdelphij    }
687238405Sjkim
688296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
689183234Ssimon
690296341Sdelphij    ASN1_STRING_set0(si->signature, abuf, siglen);
691183234Ssimon
692296341Sdelphij    return 1;
693183234Ssimon
694296341Sdelphij err:
695296341Sdelphij    if (abuf)
696296341Sdelphij        OPENSSL_free(abuf);
697296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
698296341Sdelphij    return 0;
699183234Ssimon
700296341Sdelphij}
701183234Ssimon
702183234Ssimonint CMS_SignerInfo_verify(CMS_SignerInfo *si)
703296341Sdelphij{
704296341Sdelphij    EVP_MD_CTX mctx;
705296341Sdelphij    EVP_PKEY_CTX *pctx;
706296341Sdelphij    unsigned char *abuf = NULL;
707296341Sdelphij    int alen, r = -1;
708296341Sdelphij    const EVP_MD *md = NULL;
709183234Ssimon
710296341Sdelphij    if (!si->pkey) {
711296341Sdelphij        CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
712296341Sdelphij        return -1;
713296341Sdelphij    }
714183234Ssimon
715296341Sdelphij    md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
716296341Sdelphij    if (md == NULL)
717296341Sdelphij        return -1;
718296341Sdelphij    EVP_MD_CTX_init(&mctx);
719296341Sdelphij    if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
720296341Sdelphij        goto err;
721183234Ssimon
722296341Sdelphij    alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
723296341Sdelphij                         ASN1_ITEM_rptr(CMS_Attributes_Verify));
724296341Sdelphij    if (!abuf)
725296341Sdelphij        goto err;
726296341Sdelphij    r = EVP_DigestVerifyUpdate(&mctx, abuf, alen);
727296341Sdelphij    OPENSSL_free(abuf);
728296341Sdelphij    if (r <= 0) {
729296341Sdelphij        r = -1;
730296341Sdelphij        goto err;
731296341Sdelphij    }
732296341Sdelphij    r = EVP_DigestVerifyFinal(&mctx,
733296341Sdelphij                              si->signature->data, si->signature->length);
734296341Sdelphij    if (r <= 0)
735296341Sdelphij        CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
736296341Sdelphij err:
737296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
738296341Sdelphij    return r;
739296341Sdelphij}
740183234Ssimon
741183234Ssimon/* Create a chain of digest BIOs from a CMS ContentInfo */
742183234Ssimon
743183234SsimonBIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
744296341Sdelphij{
745296341Sdelphij    int i;
746296341Sdelphij    CMS_SignedData *sd;
747296341Sdelphij    BIO *chain = NULL;
748296341Sdelphij    sd = cms_get0_signed(cms);
749296341Sdelphij    if (!sd)
750296341Sdelphij        return NULL;
751296341Sdelphij    if (cms->d.signedData->encapContentInfo->partial)
752296341Sdelphij        cms_sd_set_version(sd);
753296341Sdelphij    for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
754296341Sdelphij        X509_ALGOR *digestAlgorithm;
755296341Sdelphij        BIO *mdbio;
756296341Sdelphij        digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
757296341Sdelphij        mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
758296341Sdelphij        if (!mdbio)
759296341Sdelphij            goto err;
760296341Sdelphij        if (chain)
761296341Sdelphij            BIO_push(chain, mdbio);
762296341Sdelphij        else
763296341Sdelphij            chain = mdbio;
764296341Sdelphij    }
765296341Sdelphij    return chain;
766296341Sdelphij err:
767296341Sdelphij    if (chain)
768296341Sdelphij        BIO_free_all(chain);
769296341Sdelphij    return NULL;
770296341Sdelphij}
771183234Ssimon
772183234Ssimonint CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
773296341Sdelphij{
774296341Sdelphij    ASN1_OCTET_STRING *os = NULL;
775296341Sdelphij    EVP_MD_CTX mctx;
776296341Sdelphij    int r = -1;
777296341Sdelphij    EVP_MD_CTX_init(&mctx);
778296341Sdelphij    /* If we have any signed attributes look for messageDigest value */
779296341Sdelphij    if (CMS_signed_get_attr_count(si) >= 0) {
780296341Sdelphij        os = CMS_signed_get0_data_by_OBJ(si,
781296341Sdelphij                                         OBJ_nid2obj(NID_pkcs9_messageDigest),
782296341Sdelphij                                         -3, V_ASN1_OCTET_STRING);
783296341Sdelphij        if (!os) {
784296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
785296341Sdelphij                   CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
786296341Sdelphij            goto err;
787296341Sdelphij        }
788296341Sdelphij    }
789183234Ssimon
790296341Sdelphij    if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
791296341Sdelphij        goto err;
792183234Ssimon
793296341Sdelphij    /* If messageDigest found compare it */
794183234Ssimon
795296341Sdelphij    if (os) {
796296341Sdelphij        unsigned char mval[EVP_MAX_MD_SIZE];
797296341Sdelphij        unsigned int mlen;
798296341Sdelphij        if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) {
799296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
800296341Sdelphij                   CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
801296341Sdelphij            goto err;
802296341Sdelphij        }
803296341Sdelphij        if (mlen != (unsigned int)os->length) {
804296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
805296341Sdelphij                   CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
806296341Sdelphij            goto err;
807296341Sdelphij        }
808183234Ssimon
809296341Sdelphij        if (memcmp(mval, os->data, mlen)) {
810296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
811296341Sdelphij                   CMS_R_VERIFICATION_FAILURE);
812296341Sdelphij            r = 0;
813296341Sdelphij        } else
814296341Sdelphij            r = 1;
815296341Sdelphij    } else {
816296341Sdelphij        r = EVP_VerifyFinal(&mctx, si->signature->data,
817296341Sdelphij                            si->signature->length, si->pkey);
818296341Sdelphij        if (r <= 0) {
819296341Sdelphij            CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
820296341Sdelphij                   CMS_R_VERIFICATION_FAILURE);
821296341Sdelphij            r = 0;
822296341Sdelphij        }
823296341Sdelphij    }
824183234Ssimon
825296341Sdelphij err:
826296341Sdelphij    EVP_MD_CTX_cleanup(&mctx);
827296341Sdelphij    return r;
828183234Ssimon
829296341Sdelphij}
830183234Ssimon
831183234Ssimonint CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
832296341Sdelphij{
833296341Sdelphij    unsigned char *smder = NULL;
834296341Sdelphij    int smderlen, r;
835296341Sdelphij    smderlen = i2d_X509_ALGORS(algs, &smder);
836296341Sdelphij    if (smderlen <= 0)
837296341Sdelphij        return 0;
838296341Sdelphij    r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
839296341Sdelphij                                    V_ASN1_SEQUENCE, smder, smderlen);
840296341Sdelphij    OPENSSL_free(smder);
841296341Sdelphij    return r;
842296341Sdelphij}
843183234Ssimon
844183234Ssimonint CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
845296341Sdelphij                            int algnid, int keysize)
846296341Sdelphij{
847296341Sdelphij    X509_ALGOR *alg;
848296341Sdelphij    ASN1_INTEGER *key = NULL;
849296341Sdelphij    if (keysize > 0) {
850296341Sdelphij        key = ASN1_INTEGER_new();
851296341Sdelphij        if (!key || !ASN1_INTEGER_set(key, keysize))
852296341Sdelphij            return 0;
853296341Sdelphij    }
854296341Sdelphij    alg = X509_ALGOR_new();
855296341Sdelphij    if (!alg) {
856296341Sdelphij        if (key)
857296341Sdelphij            ASN1_INTEGER_free(key);
858296341Sdelphij        return 0;
859296341Sdelphij    }
860183234Ssimon
861296341Sdelphij    X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
862296341Sdelphij                    key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
863296341Sdelphij    if (!*algs)
864296341Sdelphij        *algs = sk_X509_ALGOR_new_null();
865296341Sdelphij    if (!*algs || !sk_X509_ALGOR_push(*algs, alg)) {
866296341Sdelphij        X509_ALGOR_free(alg);
867296341Sdelphij        return 0;
868296341Sdelphij    }
869296341Sdelphij    return 1;
870296341Sdelphij}
871296341Sdelphij
872183234Ssimon/* Check to see if a cipher exists and if so add S/MIME capabilities */
873183234Ssimon
874183234Ssimonstatic int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
875296341Sdelphij{
876296341Sdelphij    if (EVP_get_cipherbynid(nid))
877296341Sdelphij        return CMS_add_simple_smimecap(sk, nid, arg);
878296341Sdelphij    return 1;
879296341Sdelphij}
880238405Sjkim
881183234Ssimonstatic int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
882296341Sdelphij{
883296341Sdelphij    if (EVP_get_digestbynid(nid))
884296341Sdelphij        return CMS_add_simple_smimecap(sk, nid, arg);
885296341Sdelphij    return 1;
886296341Sdelphij}
887238405Sjkim
888183234Ssimonint CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
889296341Sdelphij{
890296341Sdelphij    if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
891296341Sdelphij        || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
892296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
893296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
894296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
895296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
896296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128)
897296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64)
898296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1)
899296341Sdelphij        || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
900296341Sdelphij        return 0;
901296341Sdelphij    return 1;
902296341Sdelphij}
903