1/* BEGIN_HEADER */
2#include "mbedtls/bignum.h"
3#include "mbedtls/pkcs7.h"
4#include "mbedtls/x509.h"
5#include "mbedtls/x509_crt.h"
6#include "mbedtls/x509_crl.h"
7#include "x509_internal.h"
8#include "mbedtls/oid.h"
9#include "sys/types.h"
10#include "sys/stat.h"
11#include "mbedtls/rsa.h"
12#include "mbedtls/error.h"
13/* END_HEADER */
14
15/* BEGIN_DEPENDENCIES
16 * depends_on:MBEDTLS_PKCS7_C
17 * END_DEPENDENCIES
18 */
19/* BEGIN_SUITE_HELPERS */
20static int pkcs7_parse_buffer(unsigned char *pkcs7_buf, int buflen)
21{
22    int res;
23    mbedtls_pkcs7 pkcs7;
24
25    mbedtls_pkcs7_init(&pkcs7);
26    res = mbedtls_pkcs7_parse_der(&pkcs7, pkcs7_buf, buflen);
27    mbedtls_pkcs7_free(&pkcs7);
28    return res;
29}
30/* END_SUITE_HELPERS */
31
32/* BEGIN_CASE */
33void pkcs7_asn1_fail(data_t *pkcs7_buf)
34{
35    int res;
36
37    /* PKCS7 uses X509 which itself relies on PK under the hood and the latter
38     * can use PSA to store keys and perform operations so psa_crypto_init()
39     * must be called before. */
40    USE_PSA_INIT();
41
42    res = pkcs7_parse_buffer(pkcs7_buf->x, pkcs7_buf->len);
43    TEST_ASSERT(res != MBEDTLS_PKCS7_SIGNED_DATA);
44
45exit:
46    USE_PSA_DONE();
47}
48/* END_CASE */
49
50/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
51void pkcs7_parse(char *pkcs7_file, int res_expect)
52{
53    unsigned char *pkcs7_buf = NULL;
54    size_t buflen;
55    int res;
56
57    /* PKCS7 uses X509 which itself relies on PK under the hood and the latter
58     * can use PSA to store keys and perform operations so psa_crypto_init()
59     * must be called before. */
60    USE_PSA_INIT();
61
62    res = mbedtls_pk_load_file(pkcs7_file, &pkcs7_buf, &buflen);
63    TEST_EQUAL(res, 0);
64
65    res = pkcs7_parse_buffer(pkcs7_buf, buflen);
66    TEST_EQUAL(res, res_expect);
67
68exit:
69    mbedtls_free(pkcs7_buf);
70    USE_PSA_DONE();
71}
72/* END_CASE */
73
74/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C */
75void pkcs7_verify(char *pkcs7_file,
76                  char *crt_files,
77                  char *filetobesigned,
78                  int do_hash_alg,
79                  int res_expect)
80{
81    unsigned char *pkcs7_buf = NULL;
82    size_t buflen, i, k, cnt = 0, n_crts = 1;
83    unsigned char *data = NULL;
84    char **crt_files_arr = NULL;
85    unsigned char *hash = NULL;
86    struct stat st;
87    size_t datalen;
88    int res;
89    FILE *file;
90    const mbedtls_md_info_t *md_info;
91    mbedtls_pkcs7 pkcs7;
92    mbedtls_x509_crt **crts = NULL;
93
94    USE_PSA_INIT();
95
96    mbedtls_pkcs7_init(&pkcs7);
97
98    /* crt_files are space seprated list */
99    for (i = 0; i < strlen(crt_files); i++) {
100        if (crt_files[i] == ' ') {
101            n_crts++;
102        }
103    }
104
105    TEST_CALLOC(crts, n_crts);
106    TEST_CALLOC(crt_files_arr, n_crts);
107
108    for (i = 0; i < strlen(crt_files); i++) {
109        for (k = i; k < strlen(crt_files); k++) {
110            if (crt_files[k] == ' ') {
111                break;
112            }
113        }
114        TEST_CALLOC(crt_files_arr[cnt], (k-i)+1);
115        crt_files_arr[cnt][k-i] = '\0';
116        memcpy(crt_files_arr[cnt++], crt_files + i, k-i);
117        i = k;
118    }
119
120    for (i = 0; i < n_crts; i++) {
121        TEST_CALLOC(crts[i], 1);
122        mbedtls_x509_crt_init(crts[i]);
123    }
124
125    res = mbedtls_pk_load_file(pkcs7_file, &pkcs7_buf, &buflen);
126    TEST_EQUAL(res, 0);
127
128    res = mbedtls_pkcs7_parse_der(&pkcs7, pkcs7_buf, buflen);
129    TEST_EQUAL(res, MBEDTLS_PKCS7_SIGNED_DATA);
130
131    TEST_EQUAL(pkcs7.signed_data.no_of_signers, n_crts);
132
133    for (i = 0; i < n_crts; i++) {
134        res = mbedtls_x509_crt_parse_file(crts[i], crt_files_arr[i]);
135        TEST_EQUAL(res, 0);
136    }
137
138    res = stat(filetobesigned, &st);
139    TEST_EQUAL(res, 0);
140
141    file = fopen(filetobesigned, "rb");
142    TEST_ASSERT(file != NULL);
143
144    datalen = st.st_size;
145    /* Special-case for zero-length input so that data will be non-NULL */
146    TEST_CALLOC(data, datalen == 0 ? 1 : datalen);
147    buflen = fread((void *) data, sizeof(unsigned char), datalen, file);
148    TEST_EQUAL(buflen, datalen);
149
150    fclose(file);
151
152    if (do_hash_alg) {
153        md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) do_hash_alg);
154        TEST_CALLOC(hash, mbedtls_md_get_size(md_info));
155        res = mbedtls_md(md_info, data, datalen, hash);
156        TEST_EQUAL(res, 0);
157
158        for (i = 0; i < n_crts; i++) {
159            res =
160                mbedtls_pkcs7_signed_hash_verify(&pkcs7, crts[i], hash,
161                                                 mbedtls_md_get_size(md_info));
162            TEST_EQUAL(res, res_expect);
163        }
164    } else {
165        for (i = 0; i < n_crts; i++) {
166            res = mbedtls_pkcs7_signed_data_verify(&pkcs7, crts[i], data, datalen);
167            TEST_EQUAL(res, res_expect);
168        }
169    }
170
171exit:
172    for (i = 0; i < n_crts; i++) {
173        mbedtls_x509_crt_free(crts[i]);
174        mbedtls_free(crts[i]);
175        mbedtls_free(crt_files_arr[i]);
176    }
177    mbedtls_free(hash);
178    mbedtls_pkcs7_free(&pkcs7);
179    mbedtls_free(crt_files_arr);
180    mbedtls_free(crts);
181    mbedtls_free(data);
182    mbedtls_free(pkcs7_buf);
183    USE_PSA_DONE();
184}
185/* END_CASE */
186