Skip to content

Commit 19338aa

Browse files
committed
PKCS7: decoder full stack support
Signed-off-by: Stephan Mueller <smueller@chronox.de>
1 parent 8812eb2 commit 19338aa

File tree

11 files changed

+113
-59
lines changed

11 files changed

+113
-59
lines changed

TODO

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
- ARMv8: enable ARMv8 intrinsics in the kernel (SHAKE2x and by extension SLH-DSA)
1717

18-
- PKCS7 parser: eliminate the malloc for X509 cert data structures and signer info data structures (this is, however, a challenge as we have an unknown amount of them)
19-
2018
- lc_x509_helper: remove duplication between asn1/tests/asn1_test_helper.c and apps/src/lc_x509_generator_file_helper.c
2119

2220
- RISCV64: update internal/src/cpufeatures_riscv_auxv.c once kernels report ZBB correctly

apps/src/lc_pkcs7_generator.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,41 +164,41 @@ static int pkcs7_gen_file(struct pkcs7_generator_opts *opts,
164164
static int pkcs7_enc_dump(struct pkcs7_generator_opts *opts,
165165
const uint8_t *pkcs7_data, size_t pkcs7_datalen)
166166
{
167-
struct lc_pkcs7_message ppkcs7 = { 0 };
167+
LC_PKCS7_MSG_ON_STACK(ppkcs7, 1, 4);
168168
int ret;
169169

170170
if (!opts->print_pkcs7 && !opts->checker)
171171
return 0;
172172

173-
CKINT(lc_pkcs7_message_parse(&ppkcs7, pkcs7_data, pkcs7_datalen));
173+
CKINT(lc_pkcs7_message_parse(ppkcs7, pkcs7_data, pkcs7_datalen));
174174

175175
if (opts->data) {
176-
CKINT(lc_pkcs7_set_data(&ppkcs7, opts->data, opts->datalen, 0));
176+
CKINT(lc_pkcs7_set_data(ppkcs7, opts->data, opts->datalen, 0));
177177
}
178178

179179
CKINT_LOG(lc_pkcs7_verify(
180-
&ppkcs7,
180+
ppkcs7,
181181
opts->use_trust_store ? &opts->trust_store : NULL,
182182
opts->verify_rules_set ? &opts->verify_rules : NULL),
183183
"Verification of PKCS#7 message failed\n");
184184

185185
if (opts->checker)
186-
CKINT(apply_checks_pkcs7(&ppkcs7, &opts->checker_opts));
186+
CKINT(apply_checks_pkcs7(ppkcs7, &opts->checker_opts));
187187

188188
if (opts->print_pkcs7) {
189-
CKINT(print_pkcs7_data(&ppkcs7));
189+
CKINT(print_pkcs7_data(ppkcs7));
190190
}
191191

192192
out:
193-
lc_pkcs7_message_clear(&ppkcs7);
193+
lc_pkcs7_message_clear(ppkcs7);
194194
return ret;
195195
}
196196

197197
static int pkcs7_dump_file(struct pkcs7_generator_opts *opts)
198198
{
199-
struct lc_pkcs7_message ppkcs7 = { 0 };
200199
uint8_t *pkcs7_data = NULL;
201200
size_t pkcs7_datalen = 0;
201+
LC_PKCS7_MSG_ON_STACK(ppkcs7, 1, 4);
202202
int ret;
203203

204204
if (!opts->pkcs7_msg && !opts->checker)
@@ -207,13 +207,13 @@ static int pkcs7_dump_file(struct pkcs7_generator_opts *opts)
207207
CKINT_LOG(get_data(opts->pkcs7_msg, &pkcs7_data, &pkcs7_datalen),
208208
"Loading of file %s failed\n", opts->pkcs7_msg);
209209

210-
CKINT_LOG(lc_pkcs7_message_parse(&ppkcs7, pkcs7_data, pkcs7_datalen),
210+
CKINT_LOG(lc_pkcs7_message_parse(ppkcs7, pkcs7_data, pkcs7_datalen),
211211
"Parsing of input file %s failed\n", opts->pkcs7_msg);
212212

213213
if (opts->data) {
214-
CKINT(lc_pkcs7_set_data(&ppkcs7, opts->data, opts->datalen, 0));
214+
CKINT(lc_pkcs7_set_data(ppkcs7, opts->data, opts->datalen, 0));
215215
CKINT_LOG(lc_pkcs7_verify(
216-
&ppkcs7,
216+
ppkcs7,
217217
opts->use_trust_store ? &opts->trust_store :
218218
NULL,
219219
opts->verify_rules_set ? &opts->verify_rules :
@@ -222,13 +222,13 @@ static int pkcs7_dump_file(struct pkcs7_generator_opts *opts)
222222
}
223223

224224
if (opts->checker)
225-
CKINT(apply_checks_pkcs7(&ppkcs7, &opts->checker_opts));
225+
CKINT(apply_checks_pkcs7(ppkcs7, &opts->checker_opts));
226226

227227
if (opts->print_pkcs7)
228-
CKINT(print_pkcs7_data(&ppkcs7));
228+
CKINT(print_pkcs7_data(ppkcs7));
229229

230230
out:
231-
lc_pkcs7_message_clear(&ppkcs7);
231+
lc_pkcs7_message_clear(ppkcs7);
232232
release_data(pkcs7_data, pkcs7_datalen);
233233
return ret;
234234
}
@@ -549,7 +549,7 @@ int main(int argc, char *argv[])
549549
struct pkcs7_generator_opts parsed_opts = { 0 };
550550
struct x509_checker_options *checker_opts = &parsed_opts.checker_opts;
551551
struct lc_verify_rules *verify_rules = &parsed_opts.verify_rules;
552-
LC_PKCS7_MSG_ON_STACK(pkcs7_msg, 2);
552+
LC_PKCS7_MSG_ON_STACK(pkcs7_msg, 1, 4);
553553
int ret = 0, opt_index = 0;
554554

555555
static const char *opts_short = "ho:i:";

apps/src/lc_x509_generator_print.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ int print_x509_cert(const struct lc_x509_certificate *x509)
271271
int print_pkcs7_data(const struct lc_pkcs7_message *pkcs7_msg)
272272
{
273273
struct lc_x509_certificate *cert = pkcs7_msg->certs;
274-
struct lc_pkcs7_signed_info *sinfos = pkcs7_msg->list_head_signed_infos;
274+
struct lc_pkcs7_signed_info *sinfos = pkcs7_msg->list_head_sinfo;
275275
const char *hash_name;
276276
int ret = 0;
277277

asn1/api/lc_pkcs7_common.h

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,32 @@ struct lc_pkcs7_message {
8787
/*
8888
* Signed information
8989
*/
90-
struct lc_pkcs7_signed_info *curr_signed_infos;
91-
struct lc_pkcs7_signed_info *list_head_signed_infos;
92-
struct lc_pkcs7_signed_info **list_tail_signed_infos;
90+
struct lc_pkcs7_signed_info *curr_sinfo;
91+
struct lc_pkcs7_signed_info *list_head_sinfo;
92+
struct lc_pkcs7_signed_info **list_tail_sinfo;
93+
uint8_t avail_preallocated_sinfo;
94+
uint8_t consumed_preallocated_sinfo;
95+
struct lc_pkcs7_signed_info *preallocated_sinfo;
96+
9397
uint8_t version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */
9498

9599
/* Content Data (or NULL) */
96100
enum OID data_type; /* Type of Data */
97101
size_t data_len; /* Length of Data */
98102
const uint8_t *data; /* Content Data (or 0) */
99103

100-
uint8_t avail_preallocated_sinfo;
101-
uint8_t consumed_preallocated_sinfo;
102-
struct lc_pkcs7_signed_info *preallocated_sinfo;
104+
uint8_t avail_preallocated_x509;
105+
uint8_t consumed_preallocated_x509;
106+
struct lc_x509_certificate *preallocated_x509;
103107

104108
unsigned int have_authattrs : 1; /* T if have authattrs */
105109
unsigned int embed_data : 1; /* Embed data into message */
106110
};
107111

108-
#define LC_PKCS7_MSG_SIZE(num_sinfo) \
112+
#define LC_PKCS7_MSG_SIZE(num_sinfo, num_x509) \
109113
sizeof(struct lc_pkcs7_message) + \
110-
num_sinfo * sizeof(struct lc_pkcs7_signed_info)
114+
num_sinfo * sizeof(struct lc_pkcs7_signed_info) + \
115+
num_x509 * sizeof(struct lc_x509_certificate)
111116

112117
/// \endcond
113118

@@ -117,22 +122,39 @@ struct lc_pkcs7_message {
117122
* @brief Allocate memory for struct lc_pkcs7_message holding given number of
118123
* preallocated sinfo members
119124
*
125+
* This allocation allows the PKCS7 parsing to avoid allocate memory and keep
126+
* all operations on stack. In case more signers than \p num_sinfo or more
127+
* X.509 certificates than \p num_x509 are parsed from the PKCS7 message,
128+
* then first all pre-allocated structures are used and then new ones are
129+
* allocated.
130+
*
131+
* When not using this macro, which is perfectly legal, an simply allocating
132+
* \p struct lc_pkcs7_message on stack, then for all parsed signers and
133+
* X.509 certificates, a new memory entry is allocated.
134+
*
120135
* @param [in] name Name of stack variable
121136
* @param [in] num_sinfo Number of preallocated sinfo members (must be less than
122137
* 256)
138+
* @param [in] num_x509 Number of preallocated X.509 certificate structures
139+
* (must be less than 256)
123140
*/
124-
#define LC_PKCS7_MSG_ON_STACK(name, num_sinfo) \
141+
#define LC_PKCS7_MSG_ON_STACK(name, num_sinfo, num_x509) \
125142
_Pragma("GCC diagnostic push") _Pragma( \
126143
"GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
127144
_Pragma("GCC diagnostic ignored \"-Wcast-align\"") \
128-
LC_ALIGNED_BUFFER(name##_ctx_buf, LC_PKCS7_MSG_SIZE(num_sinfo),\
129-
8); \
145+
LC_ALIGNED_BUFFER(name##_ctx_buf, \
146+
LC_PKCS7_MSG_SIZE(num_sinfo, num_x509), 8); \
130147
struct lc_pkcs7_message *name = \
131148
(struct lc_pkcs7_message *)name##_ctx_buf; \
132149
(name)->avail_preallocated_sinfo = num_sinfo; \
133150
(name)->preallocated_sinfo = \
134151
(struct lc_pkcs7_signed_info *)((uint8_t *)(name) + \
135152
sizeof(struct lc_pkcs7_message)); \
153+
(name)->avail_preallocated_x509 = num_x509; \
154+
(name)->preallocated_x509 = \
155+
(struct lc_x509_certificate *)((uint8_t *)(name) + \
156+
sizeof(struct lc_pkcs7_message) + \
157+
num_sinfo * sizeof(struct lc_pkcs7_signed_info)); \
136158
_Pragma("GCC diagnostic pop")
137159

138160
#ifdef __cplusplus

asn1/api/lc_x509_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ struct lc_x509_certificate {
303303
unsigned int
304304
unsupported_sig : 1; /* T if signature uses unsupported crypto */
305305
unsigned int blacklisted : 1;
306+
unsigned int preallocated : 1;
306307
};
307308

308309
/// \endcond

asn1/src/pkcs7_generator.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,13 +1050,13 @@ static inline int pkcs7_initialize_ctx(struct pkcs7_generate_context *ctx,
10501050
int ret = 0;
10511051

10521052
CKNULL(pkcs7->certs, -EINVAL);
1053-
CKNULL(pkcs7->list_head_signed_infos, -EINVAL);
1053+
CKNULL(pkcs7->list_head_sinfo, -EINVAL);
10541054

10551055
ctx->pkcs7 = pkcs7;
10561056
ctx->current_x509 = pkcs7->certs;
1057-
ctx->current_sinfo = pkcs7->list_head_signed_infos;
1057+
ctx->current_sinfo = pkcs7->list_head_sinfo;
10581058

1059-
for (sinfo = pkcs7->list_head_signed_infos; sinfo;
1059+
for (sinfo = pkcs7->list_head_sinfo; sinfo;
10601060
sinfo = sinfo->next) {
10611061
const struct lc_hash *hash;
10621062

asn1/src/pkcs7_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ int pkcs7_sinfo_get(struct lc_pkcs7_signed_info **sinfo,
5959
struct lc_pkcs7_message *pkcs7);
6060
void pkcs7_sinfo_free(struct lc_pkcs7_message *pkcs7);
6161

62+
int pkcs7_x509_get(struct lc_x509_certificate **x509,
63+
struct lc_pkcs7_message *pkcs7);
64+
void pkcs7_x509_free(struct lc_x509_certificate *x509);
65+
6266
#ifdef __cplusplus
6367
}
6468
#endif

asn1/src/pkcs7_memory.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ void pkcs7_sinfo_free(struct lc_pkcs7_message *pkcs7)
2626
struct lc_pkcs7_signed_info *sinfo;
2727
uint8_t idx = 0;
2828

29-
while (pkcs7->list_head_signed_infos) {
30-
sinfo = pkcs7->list_head_signed_infos;
31-
pkcs7->list_head_signed_infos = sinfo->next;
29+
while (pkcs7->list_head_sinfo) {
30+
sinfo = pkcs7->list_head_sinfo;
31+
pkcs7->list_head_sinfo = sinfo->next;
3232
public_key_signature_clear(&sinfo->sig);
3333
if (idx < pkcs7->consumed_preallocated_sinfo) {
3434
idx++;
@@ -37,8 +37,8 @@ void pkcs7_sinfo_free(struct lc_pkcs7_message *pkcs7)
3737
}
3838
}
3939

40-
if (pkcs7->curr_signed_infos) {
41-
sinfo = pkcs7->curr_signed_infos;
40+
if (pkcs7->curr_sinfo) {
41+
sinfo = pkcs7->curr_sinfo;
4242
public_key_signature_clear(&sinfo->sig);
4343

4444
if (idx >= pkcs7->consumed_preallocated_sinfo)
@@ -48,14 +48,14 @@ void pkcs7_sinfo_free(struct lc_pkcs7_message *pkcs7)
4848

4949
int pkcs7_sinfo_add(struct lc_pkcs7_message *pkcs7)
5050
{
51-
if (!pkcs7->list_head_signed_infos) {
52-
pkcs7->list_head_signed_infos = pkcs7->curr_signed_infos;
51+
if (!pkcs7->list_head_sinfo) {
52+
pkcs7->list_head_sinfo = pkcs7->curr_sinfo;
5353
} else {
54-
*pkcs7->list_tail_signed_infos = pkcs7->curr_signed_infos;
54+
*pkcs7->list_tail_sinfo = pkcs7->curr_sinfo;
5555
}
5656

57-
pkcs7->list_tail_signed_infos = &pkcs7->curr_signed_infos->next;
58-
pkcs7->curr_signed_infos = NULL;
57+
pkcs7->list_tail_sinfo = &pkcs7->curr_sinfo->next;
58+
pkcs7->curr_sinfo = NULL;
5959

6060
return 0;
6161
}
@@ -67,20 +67,55 @@ int pkcs7_sinfo_get(struct lc_pkcs7_signed_info **sinfo,
6767

6868
CKNULL(sinfo, -EINVAL);
6969

70-
if (!pkcs7->curr_signed_infos) {
70+
if (!pkcs7->curr_sinfo) {
7171
if (pkcs7->consumed_preallocated_sinfo <
7272
pkcs7->avail_preallocated_sinfo) {
73-
pkcs7->curr_signed_infos = pkcs7->preallocated_sinfo;
73+
pkcs7->curr_sinfo = pkcs7->preallocated_sinfo;
7474
pkcs7->consumed_preallocated_sinfo++;
7575
pkcs7->preallocated_sinfo++;
7676
} else {
7777
CKINT(lc_alloc_aligned(
78-
(void **)&pkcs7->curr_signed_infos, 8,
78+
(void **)&pkcs7->curr_sinfo, 8,
7979
sizeof(struct lc_pkcs7_signed_info)));
8080
}
8181
}
8282

83-
*sinfo = pkcs7->curr_signed_infos;
83+
*sinfo = pkcs7->curr_sinfo;
84+
85+
out:
86+
return ret;
87+
}
88+
89+
void pkcs7_x509_free(struct lc_x509_certificate *x509)
90+
{
91+
if (x509->preallocated) {
92+
lc_x509_cert_clear(x509);
93+
} else {
94+
lc_x509_cert_clear(x509);
95+
lc_free(x509);
96+
}
97+
}
98+
99+
int pkcs7_x509_get(struct lc_x509_certificate **x509,
100+
struct lc_pkcs7_message *pkcs7)
101+
{
102+
struct lc_x509_certificate *tmp_x509;
103+
int ret = 0;
104+
105+
CKNULL(x509, -EINVAL);
106+
107+
if (pkcs7->consumed_preallocated_x509 <
108+
pkcs7->avail_preallocated_x509) {
109+
tmp_x509 = pkcs7->preallocated_x509;
110+
pkcs7->consumed_preallocated_x509++;
111+
pkcs7->preallocated_x509++;
112+
tmp_x509->preallocated = 1;
113+
} else {
114+
CKINT(lc_alloc_aligned((void **)&tmp_x509, 8,
115+
sizeof(struct lc_x509_certificate)));
116+
}
117+
118+
*x509 = tmp_x509;
84119

85120
out:
86121
return ret;

asn1/src/pkcs7_parser.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static int pkcs7_check_authattrs(struct lc_pkcs7_message *msg)
9494
struct lc_pkcs7_signed_info *sinfo;
9595
unsigned int want = 0;
9696

97-
sinfo = msg->list_head_signed_infos;
97+
sinfo = msg->list_head_sinfo;
9898
if (!sinfo)
9999
goto inconsistent;
100100

@@ -376,6 +376,7 @@ int pkcs7_extract_cert(void *context, size_t hdrlen, unsigned char tag,
376376
const uint8_t *value, size_t vlen)
377377
{
378378
struct pkcs7_parse_context *ctx = context;
379+
struct lc_pkcs7_message *pkcs7 = ctx->msg;
379380
struct lc_x509_certificate *x509;
380381
struct lc_asymmetric_key_id *id;
381382
int ret;
@@ -397,8 +398,7 @@ int pkcs7_extract_cert(void *context, size_t hdrlen, unsigned char tag,
397398
if (((uint8_t *)value)[1] == 0x80)
398399
vlen += 2; /* Indefinite length - there should be an EOC */
399400

400-
CKINT(lc_alloc_aligned((void **)&x509, 8,
401-
sizeof(struct lc_x509_certificate)));
401+
CKINT(pkcs7_x509_get(&x509, pkcs7));
402402

403403
CKINT(lc_x509_cert_decode(x509, value, vlen));
404404

@@ -781,8 +781,7 @@ LC_INTERFACE_FUNCTION(void, lc_pkcs7_message_clear,
781781
while (pkcs7->certs) {
782782
cert = pkcs7->certs;
783783
pkcs7->certs = cert->next;
784-
lc_x509_cert_clear(cert);
785-
lc_free(cert);
784+
pkcs7_x509_free(cert);
786785
}
787786
while (pkcs7->crl) {
788787
cert = pkcs7->crl;
@@ -805,10 +804,7 @@ LC_INTERFACE_FUNCTION(int, lc_pkcs7_message_parse,
805804
CKNULL(pkcs7, -EINVAL);
806805
CKNULL(data, -EINVAL);
807806

808-
lc_memset_secure(pkcs7, 0, sizeof(struct lc_pkcs7_message));
809-
810807
ctx.msg = pkcs7;
811-
812808
ctx.data = data;
813809
ctx.ppcerts = &ctx.certs;
814810

@@ -822,8 +818,7 @@ LC_INTERFACE_FUNCTION(int, lc_pkcs7_message_parse,
822818
struct lc_x509_certificate *cert = ctx.certs;
823819

824820
ctx.certs = cert->next;
825-
lc_x509_cert_clear(cert);
826-
lc_free(cert);
821+
pkcs7_x509_free(cert);
827822
}
828823

829824
if (ret)

0 commit comments

Comments
 (0)