1/*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *    http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef MBEDTLS_PKCS7_H
17#define MBEDTLS_PKCS7_H
18#include <stdbool.h>
19#include <stdint.h>
20#include <mbedtls/asn1.h>
21#include <mbedtls/x509.h>
22#include <mbedtls/x509_crt.h>
23#include <mbedtls/x509_crl.h>
24#include <mbedtls/pem.h>
25#include <mbedtls/oid.h>
26
27#ifdef __cplusplus
28#if __cplusplus
29extern "C" {
30#endif
31#endif
32
33/*
34 * if the pkcs7 format is pem, add this define in this header file
35 * or in build env
36 * #define PARSE_PEM_FORMAT_SIGNED_DATA 1
37 */
38#define MAX_SIGNER_NAME_LEN 512
39
40typedef enum {
41    PKCS7_SUCC = 0,
42    PKCS7_PARSING_ERROR,
43    PKCS7_INVALID_PARAM,
44    PKCS7_INVALID_VALUE,
45    PKCS7_INVALID_CONTENT_TYPE_OR_NO_CONTENT,
46    PKCS7_CERTIFICATE_NOT_FOUND,
47    PKCS7_INVALID_VERSION,
48    PKCS7_INVALID_DIGEST_ALG,
49    PKCS7_INVALID_SIGNING_ALG,
50    PKCS7_MEMORY_EXHAUST,
51    PKCS7_ROOT_CA_NOT_VALID,
52    PKCS7_BUILD_CERT_PATH_FAIL,
53    PKCS7_HAS_NO_AUTH_ATTR_IN_SIGNER,
54    PKCS7_HAS_NO_SIGNER_INFO,
55    PKCS7_HAS_NO_SIGNER_CRT,
56    PKCS7_IS_REVOKED,
57    PKCS7_VERIFY_FAIL,
58} PKCS7_RetCode;
59
60typedef struct {
61    char issuer[MAX_SIGNER_NAME_LEN];
62    char subject[MAX_SIGNER_NAME_LEN];
63    int32_t depth;
64} SignerResovledInfo;
65
66typedef struct {
67    SignerResovledInfo *signers;
68    int32_t nrOfSigners;
69} SignersResovedInfo;
70
71/*
72 * The structure bellow used the mbedtls open source structure which definition is kernel-like style,
73 * We do not redefine it to Camel style
74 *
75 * the PKCS7 signer's cert path header
76 * depth is the signer's cert path depth
77 * crt is the certs list header, the lower ca cert is at front
78 */
79typedef struct {
80    int32_t depth;
81    mbedtls_x509_crt *crt;
82} SignerCertPath;
83
84/*
85 * PKCS7 signer info structure, as defined in PKCS7
86 * rootCert is not defined in PKCS7, this is the signer's root cert preinstall in system
87 * certPath is for cert chain verify
88 * next is point to the next signer info, as PKCS7 definination, maybe there are multi signer
89 */
90typedef struct tagSignerInfo {
91    int32_t version;
92    mbedtls_x509_buf serial;
93    mbedtls_x509_name issuer;
94    mbedtls_x509_crt *rootCert;
95    mbedtls_x509_buf issuerRaw;
96    mbedtls_x509_buf digestAlgId;
97    mbedtls_x509_buf authAttr;
98    mbedtls_x509_buf authAttrRaw;
99    mbedtls_x509_buf digestEncAlgId;
100    mbedtls_x509_buf signature;
101    mbedtls_x509_buf unAuthAttr;
102    SignerCertPath certPath;
103    struct tagSignerInfo *next;
104} SignerInfo;
105
106/*
107 * PKCS7 signed data content info
108 */
109typedef struct tagContent {
110    mbedtls_asn1_buf oid;
111    mbedtls_asn1_buf data;
112} Content;
113
114/*
115 * PKCS7 signed data digest algorithm identifiers
116 */
117typedef struct tagDigestAlgId {
118    mbedtls_asn1_buf algBuf;
119    struct tagDigestAlgId *next;
120} DigestAlgId;
121
122/*
123 * PKCS7 signed-data structure
124 */
125typedef struct {
126    int32_t version;
127    DigestAlgId digestAlgIds;
128    Content content;
129    mbedtls_x509_crt *certs;
130    mbedtls_x509_crl crl;
131    SignerInfo signers;
132} SignedData;
133
134/*
135 * PKCS7 signed data total structure header
136 * contentTypeOid must be the pkcs7 signed-data oid 1.2.840.113549.1.7.2
137 */
138typedef struct {
139    mbedtls_asn1_buf contentTypeOid;
140    SignedData signedData;
141#ifdef PARSE_PEM_FORMAT_SIGNED_DATA
142    mbedtls_pem_context pem;
143#endif
144} Pkcs7;
145
146/*******************************************************************************
147 * Function    : PKCS7_ParseSignedData
148 * Description : parse the pkcs7 signed data, store the resolved data to pkcs7
149 * Input       : buf     - pkcs7 signed data
150 *               bufLen  - pkcs7 signed data length
151 * Output      : pkcs7   - resolved pkcs7 data, caller provide this arg, malloc
152 *                         from heap memory or use stack memory, if malloced
153 *                         from heap memory, caller must freed the memory after
154 *                         called PKCS7_FreeRes
155 * Return      : 0 on success, others on fail
156 * Note        : need to call PKCS7_FreeRes to free the resource when success
157 *               parse and use, no need to call PKCS7_FreeRes when parse failed
158 *******************************************************************************/
159int32_t PKCS7_ParseSignedData(const unsigned char *buf, size_t bufLen, Pkcs7 *pkcs7);
160
161/*******************************************************************************
162 * Function    : PKCS7_VerifyCertsChain
163 * Description : Verify all signer's cert chain
164 * Input       : pkcs7 -- the pkcs7 signed data header.
165 * Return      : 0 on success, others on fail
166 *******************************************************************************/
167int32_t PKCS7_VerifyCertsChain(const Pkcs7 *pkcs7);
168
169/*******************************************************************************
170 * Function    : PKCS7_FreeRes
171 * Description : free the resource of resolved pkcs7 data
172 * Input       : pkcs7   - resolved pkcs7 data
173 * Return      : 0 on success, others on fail
174 * Note        : need to call PKCS7_FreeRes to free the resource when success
175 *               parse and use, no need to call PKCS7_FreeRes when parse failed
176 *******************************************************************************/
177void PKCS7_FreeRes(Pkcs7 *pkcs7);
178
179/*******************************************************************************
180 * Function    : PKCS7_CalcDigest
181 * Description : is a callback defined by upper layer user, calculate the
182 *               digest for final verify the signed data signature.
183 * Input       : pkcs7   - pkcs7 signed data header
184 *               signer  - pkcs7 signer info
185 *               algType - digest algorithm type, defined in mbedtls, exp:
186 *                         MBEDTLS_MD_SHA256/MBEDTLS_MD_SHA512
187 * Output      : hash    - the calcuated digest hash
188 *               hashLen - the length of calculated digest hash
189 * Return      : 0 on success, others on fail
190 *******************************************************************************/
191typedef int32_t (*PKCS7_CalcDigest)(const Pkcs7 *pkcs7, const SignerInfo *signer,
192    mbedtls_md_type_t algType, unsigned char *hash, size_t *hashLen);
193
194/*******************************************************************************
195 * Function    : PKCS7_GetContentData
196 * Description : get the content data of PKCS#7 signed-data content
197 * Input       : pkcs7   - pkcs7 signed data header
198 * Output      : data    - pointer to the content data
199 *                         user need not to free this var
200 *               dataLen - the content data length
201 * Return      : 0 on success, others on fail
202 *******************************************************************************/
203int32_t PKCS7_GetContentData(const Pkcs7 *pkcs7, unsigned char **data, size_t *dataLen);
204
205/*******************************************************************************
206 * Function    : PKCS7_GetDigestInSignerAuthAttr
207 * Description : get the digest which stored in signer's auth attribute.
208 * Input       : signer  - pkcs7 signer info
209 * Output      : dig     - pointer to the digest stored in signer's auth attribute
210 *                         user need not to free this var
211 *               digLen  - digest length
212 * Return      : 0 on success, others on fail
213 *******************************************************************************/
214int32_t PKCS7_GetDigestInSignerAuthAttr(const SignerInfo *signer, unsigned char **dig, size_t *digLen);
215
216/*******************************************************************************
217 * Function    : PKCS7_GetSignerAuthAttr
218 * Description : get the signer's auth attribute content, which maybe signed by
219 *               signer, so upper layer can call this to get to-be-signed data,
220 *               then calculate digest of it for signature verification
221 * Input       : signer  - pkcs7 signer info
222 * Output      : data    - pointer to signer's auth attribute start location
223 *                         user need not to free this var
224 *               dataLen - signer auth attribute data length
225 * Return      : 0 on success, others on fail
226 *******************************************************************************/
227int32_t PKCS7_GetSignerAuthAttr(const SignerInfo *signer, unsigned char **data, size_t *dataLen);
228
229/*******************************************************************************
230 * Function    : PKCS7_VerifySignerSignature
231 * Description : Verify all of signer's signature
232 * Input       : pkcs7   - pkcs7 signed data header
233 *               calcDigest - callback function for upper layer user to calculate
234 *                            the digest of signature
235 * Output      : NA
236 * Return      : 0 on success, others on fail
237 *******************************************************************************/
238int32_t PKCS7_VerifySignerSignature(const Pkcs7 *pkcs7, PKCS7_CalcDigest calcDigest);
239
240/*******************************************************************************
241 * Function    : PKCS7_GetAllSignersResolvedInfo
242 * Description : Get all signer's associate info, now including subject/issuer/
243 *               cert depth, used it for trustlist match.
244 * Input       : pkcs7   - pkcs7 signed data header
245 * Output      : the structure of associate signer's info
246 * Return      : non-NULL on success, and user need to call
247 *               PKCS7_FreeAllSignersResolvedInfo to free resource
248 *******************************************************************************/
249SignersResovedInfo *PKCS7_GetAllSignersResolvedInfo(const Pkcs7 *pkcs7);
250
251/*******************************************************************************
252 * Function    : PKCS7_FreeAllSignersResolvedInfo
253 * Description : Free the signer associate info.
254 * Input       : sri    - signer associate info
255 * Output      : NA
256 * Return      : void
257 *******************************************************************************/
258void PKCS7_FreeAllSignersResolvedInfo(SignersResovedInfo *sri);
259
260/*******************************************************************************
261 * Function    : PKCS7_EnableDebugMode
262 * Description : Enable or disable debug mode, so it can install the app that
263 *               signed by the test cert's private key.
264 * Input       : mode    - true:enable, false:disable
265 * Output      : NA
266 * Return      : 0 on success, others on error
267 *******************************************************************************/
268int32_t PKCS7_EnableDebugMode(bool mode);
269
270#ifdef __cplusplus
271#if __cplusplus
272}
273#endif
274#endif
275#endif // MBEDTLS_PKCS7_H
276