1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2000-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 <stdio.h>
11e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
12e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
13e1051a39Sopenharmony_ci#include <openssl/pkcs7.h>
14e1051a39Sopenharmony_ci#include <openssl/x509.h>
15e1051a39Sopenharmony_ci#include "pk7_local.h"
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci/* PKCS#7 ASN1 module */
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci/* This is the ANY DEFINED BY table for the top level PKCS#7 structure */
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ciASN1_ADB_TEMPLATE(p7default) = ASN1_EXP_OPT(PKCS7, d.other, ASN1_ANY, 0);
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ciASN1_ADB(PKCS7) = {
24e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING_NDEF, 0)),
25e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)),
26e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)),
27e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)),
28e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)),
29e1051a39Sopenharmony_ci        ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0))
30e1051a39Sopenharmony_ci} ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL);
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci/* PKCS#7 streaming support */
33e1051a39Sopenharmony_cistatic int pk7_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
34e1051a39Sopenharmony_ci                  void *exarg)
35e1051a39Sopenharmony_ci{
36e1051a39Sopenharmony_ci    ASN1_STREAM_ARG *sarg = exarg;
37e1051a39Sopenharmony_ci    PKCS7 **pp7 = (PKCS7 **)pval;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci    switch (operation) {
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci    case ASN1_OP_STREAM_PRE:
42e1051a39Sopenharmony_ci        if (PKCS7_stream(&sarg->boundary, *pp7) <= 0)
43e1051a39Sopenharmony_ci            return 0;
44e1051a39Sopenharmony_ci        /* fall thru */
45e1051a39Sopenharmony_ci    case ASN1_OP_DETACHED_PRE:
46e1051a39Sopenharmony_ci        sarg->ndef_bio = PKCS7_dataInit(*pp7, sarg->out);
47e1051a39Sopenharmony_ci        if (!sarg->ndef_bio)
48e1051a39Sopenharmony_ci            return 0;
49e1051a39Sopenharmony_ci        break;
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ci    case ASN1_OP_STREAM_POST:
52e1051a39Sopenharmony_ci    case ASN1_OP_DETACHED_POST:
53e1051a39Sopenharmony_ci        if (PKCS7_dataFinal(*pp7, sarg->ndef_bio) <= 0)
54e1051a39Sopenharmony_ci            return 0;
55e1051a39Sopenharmony_ci        break;
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_ci    }
58e1051a39Sopenharmony_ci    return 1;
59e1051a39Sopenharmony_ci}
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = {
62e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT),
63e1051a39Sopenharmony_ci        ASN1_ADB_OBJECT(PKCS7)
64e1051a39Sopenharmony_ci}ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7)
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ciPKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len)
67e1051a39Sopenharmony_ci{
68e1051a39Sopenharmony_ci    PKCS7 *ret;
69e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = NULL;
70e1051a39Sopenharmony_ci    const char *propq = NULL;
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci    if (a != NULL && *a != NULL) {
73e1051a39Sopenharmony_ci        libctx = (*a)->ctx.libctx;
74e1051a39Sopenharmony_ci        propq = (*a)->ctx.propq;
75e1051a39Sopenharmony_ci    }
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_ci    ret = (PKCS7 *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len, (PKCS7_it()),
78e1051a39Sopenharmony_ci                                    libctx, propq);
79e1051a39Sopenharmony_ci    if (ret != NULL)
80e1051a39Sopenharmony_ci        ossl_pkcs7_resolve_libctx(ret);
81e1051a39Sopenharmony_ci    return ret;
82e1051a39Sopenharmony_ci}
83e1051a39Sopenharmony_ci
84e1051a39Sopenharmony_ciint i2d_PKCS7(const PKCS7 *a, unsigned char **out)
85e1051a39Sopenharmony_ci{
86e1051a39Sopenharmony_ci    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (PKCS7_it()));\
87e1051a39Sopenharmony_ci}
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ciPKCS7 *PKCS7_new(void)
90e1051a39Sopenharmony_ci{
91e1051a39Sopenharmony_ci    return (PKCS7 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS7));
92e1051a39Sopenharmony_ci}
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ciPKCS7 *PKCS7_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
95e1051a39Sopenharmony_ci{
96e1051a39Sopenharmony_ci    PKCS7 *pkcs7 = (PKCS7 *)ASN1_item_new_ex(ASN1_ITEM_rptr(PKCS7), libctx,
97e1051a39Sopenharmony_ci                                             propq);
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    if (pkcs7 != NULL) {
100e1051a39Sopenharmony_ci        pkcs7->ctx.libctx = libctx;
101e1051a39Sopenharmony_ci        pkcs7->ctx.propq = NULL;
102e1051a39Sopenharmony_ci        if (propq != NULL) {
103e1051a39Sopenharmony_ci            pkcs7->ctx.propq = OPENSSL_strdup(propq);
104e1051a39Sopenharmony_ci            if (pkcs7->ctx.propq == NULL) {
105e1051a39Sopenharmony_ci                PKCS7_free(pkcs7);
106e1051a39Sopenharmony_ci                pkcs7 = NULL;
107e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
108e1051a39Sopenharmony_ci            }
109e1051a39Sopenharmony_ci        }
110e1051a39Sopenharmony_ci    }
111e1051a39Sopenharmony_ci    return pkcs7;
112e1051a39Sopenharmony_ci}
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_civoid PKCS7_free(PKCS7 *p7)
115e1051a39Sopenharmony_ci{
116e1051a39Sopenharmony_ci    if (p7 != NULL) {
117e1051a39Sopenharmony_ci        OPENSSL_free(p7->ctx.propq);
118e1051a39Sopenharmony_ci        ASN1_item_free((ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7));
119e1051a39Sopenharmony_ci    }
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ciIMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7)
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ciIMPLEMENT_ASN1_DUP_FUNCTION(PKCS7)
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_SIGNED) = {
127e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER),
128e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR),
129e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7),
130e1051a39Sopenharmony_ci        ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0),
131e1051a39Sopenharmony_ci        ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1),
132e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO)
133e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGNED)
134e1051a39Sopenharmony_ci
135e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED)
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci/* Minor tweak to operation: free up EVP_PKEY */
138e1051a39Sopenharmony_cistatic int si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
139e1051a39Sopenharmony_ci                 void *exarg)
140e1051a39Sopenharmony_ci{
141e1051a39Sopenharmony_ci    if (operation == ASN1_OP_FREE_POST) {
142e1051a39Sopenharmony_ci        PKCS7_SIGNER_INFO *si = (PKCS7_SIGNER_INFO *)*pval;
143e1051a39Sopenharmony_ci        EVP_PKEY_free(si->pkey);
144e1051a39Sopenharmony_ci    }
145e1051a39Sopenharmony_ci    return 1;
146e1051a39Sopenharmony_ci}
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ciASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, si_cb) = {
149e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER),
150e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL),
151e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR),
152e1051a39Sopenharmony_ci        /* NB this should be a SET OF but we use a SEQUENCE OF so the
153e1051a39Sopenharmony_ci         * original order * is retained when the structure is reencoded.
154e1051a39Sopenharmony_ci         * Since the attributes are implicitly tagged this will not affect
155e1051a39Sopenharmony_ci         * the encoding.
156e1051a39Sopenharmony_ci         */
157e1051a39Sopenharmony_ci        ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0),
158e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR),
159e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGNER_INFO, enc_digest, ASN1_OCTET_STRING),
160e1051a39Sopenharmony_ci        ASN1_IMP_SET_OF_OPT(PKCS7_SIGNER_INFO, unauth_attr, X509_ATTRIBUTE, 1)
161e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END_cb(PKCS7_SIGNER_INFO, PKCS7_SIGNER_INFO)
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ciASN1_SEQUENCE(PKCS7_ISSUER_AND_SERIAL) = {
166e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, issuer, X509_NAME),
167e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, serial, ASN1_INTEGER)
168e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(PKCS7_ISSUER_AND_SERIAL)
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_ENVELOPE) = {
173e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENVELOPE, version, ASN1_INTEGER),
174e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO),
175e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENVELOPE, enc_data, PKCS7_ENC_CONTENT)
176e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_ENVELOPE)
177e1051a39Sopenharmony_ci
178e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ci/* Minor tweak to operation: free up X509 */
181e1051a39Sopenharmony_cistatic int ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
182e1051a39Sopenharmony_ci                 void *exarg)
183e1051a39Sopenharmony_ci{
184e1051a39Sopenharmony_ci    if (operation == ASN1_OP_FREE_POST) {
185e1051a39Sopenharmony_ci        PKCS7_RECIP_INFO *ri = (PKCS7_RECIP_INFO *)*pval;
186e1051a39Sopenharmony_ci        X509_free(ri->cert);
187e1051a39Sopenharmony_ci    }
188e1051a39Sopenharmony_ci    return 1;
189e1051a39Sopenharmony_ci}
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_ciASN1_SEQUENCE_cb(PKCS7_RECIP_INFO, ri_cb) = {
192e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_RECIP_INFO, version, ASN1_INTEGER),
193e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_RECIP_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL),
194e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_RECIP_INFO, key_enc_algor, X509_ALGOR),
195e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_RECIP_INFO, enc_key, ASN1_OCTET_STRING)
196e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END_cb(PKCS7_RECIP_INFO, PKCS7_RECIP_INFO)
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_ENC_CONTENT) = {
201e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENC_CONTENT, content_type, ASN1_OBJECT),
202e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENC_CONTENT, algorithm, X509_ALGOR),
203e1051a39Sopenharmony_ci        ASN1_IMP_OPT(PKCS7_ENC_CONTENT, enc_data, ASN1_OCTET_STRING_NDEF, 0)
204e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_ENC_CONTENT)
205e1051a39Sopenharmony_ci
206e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_SIGN_ENVELOPE) = {
209e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, version, ASN1_INTEGER),
210e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO),
211e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, md_algs, X509_ALGOR),
212e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, enc_data, PKCS7_ENC_CONTENT),
213e1051a39Sopenharmony_ci        ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, cert, X509, 0),
214e1051a39Sopenharmony_ci        ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, crl, X509_CRL, 1),
215e1051a39Sopenharmony_ci        ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, signer_info, PKCS7_SIGNER_INFO)
216e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGN_ENVELOPE)
217e1051a39Sopenharmony_ci
218e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_ENCRYPT) = {
221e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENCRYPT, version, ASN1_INTEGER),
222e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_ENCRYPT, enc_data, PKCS7_ENC_CONTENT)
223e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_ENCRYPT)
224e1051a39Sopenharmony_ci
225e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ciASN1_NDEF_SEQUENCE(PKCS7_DIGEST) = {
228e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_DIGEST, version, ASN1_INTEGER),
229e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_DIGEST, md, X509_ALGOR),
230e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_DIGEST, contents, PKCS7),
231e1051a39Sopenharmony_ci        ASN1_SIMPLE(PKCS7_DIGEST, digest, ASN1_OCTET_STRING)
232e1051a39Sopenharmony_ci} ASN1_NDEF_SEQUENCE_END(PKCS7_DIGEST)
233e1051a39Sopenharmony_ci
234e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST)
235e1051a39Sopenharmony_ci
236e1051a39Sopenharmony_ci/* Specials for authenticated attributes */
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci/*
239e1051a39Sopenharmony_ci * When signing attributes we want to reorder them to match the sorted
240e1051a39Sopenharmony_ci * encoding.
241e1051a39Sopenharmony_ci */
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE(PKCS7_ATTR_SIGN) =
244e1051a39Sopenharmony_ci        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, PKCS7_ATTRIBUTES, X509_ATTRIBUTE)
245e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_SIGN)
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_ci/*
248e1051a39Sopenharmony_ci * When verifying attributes we need to use the received order. So we use
249e1051a39Sopenharmony_ci * SEQUENCE OF and tag it to SET OF
250e1051a39Sopenharmony_ci */
251e1051a39Sopenharmony_ci
252e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE(PKCS7_ATTR_VERIFY) =
253e1051a39Sopenharmony_ci        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
254e1051a39Sopenharmony_ci                                V_ASN1_SET, PKCS7_ATTRIBUTES, X509_ATTRIBUTE)
255e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_VERIFY)
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_ciIMPLEMENT_ASN1_PRINT_FUNCTION(PKCS7)
258