1 /* pkcs7.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <wolfssl/wolfcrypt/settings.h>
28
29 #ifdef HAVE_PKCS7
30
31 #include <wolfssl/wolfcrypt/pkcs7.h>
32 #include <wolfssl/wolfcrypt/error-crypt.h>
33 #include <wolfssl/wolfcrypt/logging.h>
34 #include <wolfssl/wolfcrypt/hash.h>
35 #ifndef NO_RSA
36 #include <wolfssl/wolfcrypt/rsa.h>
37 #endif
38 #ifdef HAVE_ECC
39 #include <wolfssl/wolfcrypt/ecc.h>
40 #endif
41 #ifdef HAVE_LIBZ
42 #include <wolfssl/wolfcrypt/compress.h>
43 #endif
44 #ifndef NO_PWDBASED
45 #include <wolfssl/wolfcrypt/pwdbased.h>
46 #endif
47 #ifdef NO_INLINE
48 #include <wolfssl/wolfcrypt/misc.h>
49 #else
50 #define WOLFSSL_MISC_INCLUDED
51 #include <wolfcrypt/src/misc.c>
52 #endif
53
54 /* direction for processing, encoding or decoding */
55 typedef enum {
56 WC_PKCS7_ENCODE,
57 WC_PKCS7_DECODE
58 } pkcs7Direction;
59
60 #define NO_USER_CHECK 0
61
62 /* holds information about the signers */
63 struct PKCS7SignerInfo {
64 int version;
65 byte *sid;
66 word32 sidSz;
67 };
68
69
70 #ifndef WOLFSSL_PKCS7_MAX_DECOMPRESSION
71 /* 1031 comes from "Maximum Compression Factor" in the zlib tech document,
72 * typical compression is from 2:1 to 5:1 but there is rare cases where
73 * 1030.3:1 could happen (like a file with all 0's)
74 */
75 #define WOLFSSL_PKCS7_MAX_DECOMPRESSION 1031
76 #endif
77
78 #ifndef NO_PKCS7_STREAM
79
80 #define MAX_PKCS7_STREAM_BUFFER 256
81 struct PKCS7State {
82 byte* tmpCert;
83 byte* bufferPt;
84 byte* key;
85 byte* nonce; /* stored nonce */
86 byte* aad; /* additional data for AEAD algos */
87 byte* tag; /* tag data for AEAD algos */
88 byte* content;
89 byte* buffer; /* main internal read buffer */
90
91 /* stack variables to store for when returning */
92 word32 varOne;
93 int varTwo;
94 int varThree;
95
96 word32 vers;
97 word32 idx; /* index read into current input buffer */
98 word32 maxLen; /* sanity cap on maximum amount of data to allow
99 * needed for GetSequence and other calls */
100 word32 length; /* amount of data stored */
101 word32 bufferSz; /* size of internal buffer */
102 word32 expected; /* next amount of data expected, if needed */
103 word32 totalRd; /* total amount of bytes read */
104 word32 nonceSz; /* size of nonce stored */
105 word32 aadSz; /* size of additional AEAD data */
106 word32 tagSz; /* size of tag for AEAD */
107 word32 contentSz;
108 byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */
109 #ifdef WC_PKCS7_STREAM_DEBUG
110 word32 peakUsed; /* most bytes used for struct at any one time */
111 word32 peakRead; /* most bytes used by read buffer */
112 #endif
113 byte multi:1; /* flag for if content is in multiple parts */
114 byte flagOne:1;
115 byte detached:1; /* flag to indicate detached signature is present */
116 };
117
118
119 /* creates a PKCS7State structure and returns 0 on success */
wc_PKCS7_CreateStream(PKCS7 * pkcs7)120 static int wc_PKCS7_CreateStream(PKCS7* pkcs7)
121 {
122 WOLFSSL_MSG("creating PKCS7 stream structure");
123 pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap,
124 DYNAMIC_TYPE_PKCS7);
125 if (pkcs7->stream == NULL) {
126 return MEMORY_E;
127 }
128 XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State));
129 #ifdef WC_PKCS7_STREAM_DEBUG
130 printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream);
131 #endif
132 return 0;
133 }
134
135
wc_PKCS7_ResetStream(PKCS7 * pkcs7)136 static void wc_PKCS7_ResetStream(PKCS7* pkcs7)
137 {
138 if (pkcs7 != NULL && pkcs7->stream != NULL) {
139 #ifdef WC_PKCS7_STREAM_DEBUG
140 /* collect final data point in case more was read right before reset */
141 if (pkcs7->stream->length > pkcs7->stream->peakRead) {
142 pkcs7->stream->peakRead = pkcs7->stream->length;
143 }
144 if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz +
145 pkcs7->stream->nonceSz + pkcs7->stream->tagSz >
146 pkcs7->stream->peakUsed) {
147 pkcs7->stream->peakUsed = pkcs7->stream->bufferSz +
148 pkcs7->stream->aadSz + pkcs7->stream->nonceSz +
149 pkcs7->stream->tagSz;
150 }
151
152 /* print out debugging statistics */
153 if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) {
154 printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d"
155 "\n\tPeak read buffer bytes = %d"
156 "\n\tTotal bytes read = %d"
157 "\n",
158 pkcs7->stream->peakUsed, pkcs7->stream->peakRead,
159 pkcs7->stream->totalRd);
160 }
161 printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream);
162 #endif
163
164 /* free any buffers that may be allocated */
165 XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
166 XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
167 XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
168 XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
169 XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
170 pkcs7->stream->aad = NULL;
171 pkcs7->stream->tag = NULL;
172 pkcs7->stream->nonce = NULL;
173 pkcs7->stream->buffer = NULL;
174 pkcs7->stream->key = NULL;
175
176 /* reset values, note that content and tmpCert are saved */
177 pkcs7->stream->maxLen = 0;
178 pkcs7->stream->length = 0;
179 pkcs7->stream->idx = 0;
180 pkcs7->stream->expected = 0;
181 pkcs7->stream->totalRd = 0;
182 pkcs7->stream->bufferSz = 0;
183
184 pkcs7->stream->multi = 0;
185 pkcs7->stream->flagOne = 0;
186 pkcs7->stream->detached = 0;
187 pkcs7->stream->varOne = 0;
188 pkcs7->stream->varTwo = 0;
189 pkcs7->stream->varThree = 0;
190 }
191 }
192
193
wc_PKCS7_FreeStream(PKCS7 * pkcs7)194 static void wc_PKCS7_FreeStream(PKCS7* pkcs7)
195 {
196 if (pkcs7 != NULL && pkcs7->stream != NULL) {
197 wc_PKCS7_ResetStream(pkcs7);
198
199 XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
200 XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
201 pkcs7->stream->content = NULL;
202 pkcs7->stream->tmpCert = NULL;
203
204 XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
205 pkcs7->stream = NULL;
206 }
207 }
208
209
210 /* used to increase the max size for internal buffer
211 * returns 0 on success */
wc_PKCS7_GrowStream(PKCS7 * pkcs7,word32 newSz)212 static int wc_PKCS7_GrowStream(PKCS7* pkcs7, word32 newSz)
213 {
214 byte* pt;
215 pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
216 if (pt == NULL) {
217 return MEMORY_E;
218 }
219
220 if (pkcs7->stream->buffer != NULL && pkcs7->stream->bufferSz > 0) {
221 XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz);
222 }
223
224 #ifdef WC_PKCS7_STREAM_DEBUG
225 printf("PKCS7 increasing internal stream buffer %d -> %d\n",
226 pkcs7->stream->bufferSz, newSz);
227 #endif
228 pkcs7->stream->bufferSz = newSz;
229 XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
230 pkcs7->stream->buffer = pt;
231 return 0;
232 }
233
234
235 /* pt gets set to the buffer that is holding data in the case that stream struct
236 * is used.
237 *
238 * Sets idx to be the current offset into "pt" buffer
239 * returns 0 on success
240 */
wc_PKCS7_AddDataToStream(PKCS7 * pkcs7,byte * in,word32 inSz,word32 expected,byte ** pt,word32 * idx)241 static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz,
242 word32 expected, byte** pt, word32* idx)
243 {
244 word32 rdSz = pkcs7->stream->idx;
245
246 /* If the input size minus current index into input buffer is greater than
247 * the expected size then use the input buffer. If data is already stored
248 * in stream buffer or if there is not enough input data available then use
249 * the stream buffer. */
250 if (inSz - rdSz >= expected && pkcs7->stream->length == 0) {
251 /* storing input buffer is not needed */
252 *pt = in; /* reset in case previously used internal buffer */
253 *idx = rdSz;
254 return 0;
255 }
256
257 /* is there enough stored in buffer already? */
258 if (pkcs7->stream->length >= expected) {
259 *idx = 0; /* start reading from beginning of stream buffer */
260 *pt = pkcs7->stream->buffer;
261 return 0;
262 }
263
264 /* check if all data has been read from input */
265 if (rdSz >= inSz) {
266 /* no more input to read, reset input index and request more data */
267 pkcs7->stream->idx = 0;
268 return WC_PKCS7_WANT_READ_E;
269 }
270
271 /* try to store input data into stream buffer */
272 if (inSz - rdSz > 0 && pkcs7->stream->length < expected) {
273 int len = min(inSz - rdSz, expected - pkcs7->stream->length);
274
275 /* sanity check that the input buffer is not internal buffer */
276 if (in == pkcs7->stream->buffer) {
277 return WC_PKCS7_WANT_READ_E;
278 }
279
280 /* check if internal buffer size needs to be increased */
281 if (len + pkcs7->stream->length > pkcs7->stream->bufferSz) {
282 int ret = wc_PKCS7_GrowStream(pkcs7, expected);
283 if (ret < 0) {
284 return ret;
285 }
286 }
287 XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len);
288 pkcs7->stream->length += len;
289 pkcs7->stream->idx += len;
290 pkcs7->stream->totalRd += len;
291 }
292
293 #ifdef WC_PKCS7_STREAM_DEBUG
294 /* collects memory usage for debugging */
295 if (pkcs7->stream->length > pkcs7->stream->peakRead) {
296 pkcs7->stream->peakRead = pkcs7->stream->length;
297 }
298 if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz +
299 pkcs7->stream->tagSz > pkcs7->stream->peakUsed) {
300 pkcs7->stream->peakUsed = pkcs7->stream->bufferSz +
301 pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz;
302 }
303 #endif
304
305 /* if not enough data was read in then request more */
306 if (pkcs7->stream->length < expected) {
307 pkcs7->stream->idx = 0;
308 return WC_PKCS7_WANT_READ_E;
309 }
310
311 /* adjust pointer to read from stored buffer */
312 *idx = 0;
313 *pt = pkcs7->stream->buffer;
314 return 0;
315 }
316
317
318 /* setter function for stored variables */
wc_PKCS7_StreamStoreVar(PKCS7 * pkcs7,word32 var1,int var2,int var3)319 static void wc_PKCS7_StreamStoreVar(PKCS7* pkcs7, word32 var1, int var2,
320 int var3)
321 {
322 if (pkcs7 != NULL && pkcs7->stream != NULL) {
323 pkcs7->stream->varOne = var1;
324 pkcs7->stream->varTwo = var2;
325 pkcs7->stream->varThree = var3;
326 }
327 }
328
329 /* Tries to peek at the SEQ and get the length
330 * returns 0 on success
331 */
wc_PKCS7_SetMaxStream(PKCS7 * pkcs7,byte * in,word32 defSz)332 static int wc_PKCS7_SetMaxStream(PKCS7* pkcs7, byte* in, word32 defSz)
333 {
334 /* check there is a buffer to read from */
335 if (pkcs7) {
336 int length = 0, ret;
337 word32 idx = 0, maxIdx;
338 byte* pt;
339
340 if (pkcs7->stream->length > 0) {
341 length = pkcs7->stream->length;
342 pt = pkcs7->stream->buffer;
343 }
344 else {
345 length = defSz;
346 pt = in;
347 }
348 maxIdx = (word32)length;
349
350 if (length < MAX_SEQ_SZ) {
351 WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek");
352 return 0;
353 }
354
355 if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, NO_USER_CHECK))
356 < 0) {
357 return ret;
358 }
359
360 #ifdef ASN_BER_TO_DER
361 if (length == 0 && ret == 0) {
362 idx = 0;
363 if ((ret = wc_BerToDer(pt, defSz, NULL,
364 (word32*)&length)) != LENGTH_ONLY_E) {
365 return ret;
366 }
367 }
368 #endif /* ASN_BER_TO_DER */
369 pkcs7->stream->maxLen = length + idx;
370
371 if (pkcs7->stream->maxLen == 0) {
372 pkcs7->stream->maxLen = defSz;
373 }
374 }
375
376 return 0;
377 }
378
379
380 /* getter function for stored variables */
wc_PKCS7_StreamGetVar(PKCS7 * pkcs7,word32 * var1,int * var2,int * var3)381 static void wc_PKCS7_StreamGetVar(PKCS7* pkcs7, word32* var1, int* var2,
382 int* var3)
383 {
384 if (pkcs7 != NULL && pkcs7->stream != NULL) {
385 if (var1 != NULL) *var1 = pkcs7->stream->varOne;
386 if (var2 != NULL) *var2 = pkcs7->stream->varTwo;
387 if (var3 != NULL) *var3 = pkcs7->stream->varThree;
388 }
389 }
390
391
392 /* common update of index and total read after section complete
393 * returns 0 on success */
wc_PKCS7_StreamEndCase(PKCS7 * pkcs7,word32 * tmpIdx,word32 * idx)394 static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx)
395 {
396 int ret = 0;
397
398 if (pkcs7->stream->length > 0) {
399 if (pkcs7->stream->length < *idx) {
400 WOLFSSL_MSG("PKCS7 read too much data from internal buffer");
401 ret = BUFFER_E;
402 }
403 else {
404 XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx,
405 pkcs7->stream->length - *idx);
406 pkcs7->stream->length -= *idx;
407 }
408 }
409 else {
410 pkcs7->stream->totalRd += *idx - *tmpIdx;
411 pkcs7->stream->idx = *idx; /* adjust index into input buffer */
412 *tmpIdx = *idx;
413 }
414
415 return ret;
416 }
417 #endif /* NO_PKCS7_STREAM */
418
419 #ifdef WC_PKCS7_STREAM_DEBUG
420 /* used to print out human readable state for debugging */
wc_PKCS7_GetStateName(int in)421 static const char* wc_PKCS7_GetStateName(int in)
422 {
423 switch (in) {
424 case WC_PKCS7_START: return "WC_PKCS7_START";
425
426 case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2";
427 case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3";
428 case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4";
429 case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5";
430 case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6";
431
432 /* parse info set */
433 case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START";
434 case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER";
435 case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1";
436 case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2";
437 case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END";
438
439 /* decode enveloped data */
440 case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2";
441 case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3";
442 case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4";
443 case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5";
444
445 /* decode auth enveloped */
446 case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2";
447 case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3";
448 case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4";
449 case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5";
450 case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6";
451 case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB";
452 case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND";
453 case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7";
454
455 /* decryption state types */
456 case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI";
457 case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2";
458 case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3";
459
460 case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI";
461 case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI";
462 case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI";
463 case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI";
464 case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE";
465
466 case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2";
467 case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3";
468 case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4";
469 case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5";
470 case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6";
471
472 default:
473 return "Unknown state";
474 }
475 }
476 #endif
477
478 /* Used to change the PKCS7 state. Having state change as a function allows
479 * for easier debugging */
wc_PKCS7_ChangeState(PKCS7 * pkcs7,int newState)480 static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState)
481 {
482 #ifdef WC_PKCS7_STREAM_DEBUG
483 printf("\tChanging from state [%02d] %s to [%02d] %s\n",
484 pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state),
485 newState, wc_PKCS7_GetStateName(newState));
486 #endif
487 pkcs7->state = newState;
488 }
489
490 #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \
491 MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE)
492
493
494 /* placed ASN.1 contentType OID into *output, return idx on success,
495 * 0 upon failure */
wc_SetContentType(int pkcs7TypeOID,byte * output,word32 outputSz)496 static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz)
497 {
498 /* PKCS#7 content types, RFC 2315, section 14 */
499 static const byte pkcs7[] =
500 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07 };
501 static const byte data[] =
502 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
503 static const byte signedData[] =
504 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
505 static const byte envelopedData[] =
506 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 };
507 static const byte authEnvelopedData[] =
508 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17};
509 static const byte signedAndEnveloped[] =
510 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 };
511 static const byte digestedData[] =
512 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 };
513 #ifndef NO_PKCS7_ENCRYPTED_DATA
514 static const byte encryptedData[] =
515 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 };
516 #endif
517 /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */
518 static const byte firmwarePkgData[] =
519 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x10 };
520 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
521 /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */
522 static const byte compressedData[] =
523 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x09 };
524 #endif
525
526 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
527 static const byte pwriKek[] =
528 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x03, 0x09 };
529 static const byte pbkdf2[] =
530 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C };
531 #endif
532
533 int idSz, idx = 0;
534 word32 typeSz = 0;
535 const byte* typeName = 0;
536 byte ID_Length[MAX_LENGTH_SZ];
537
538 switch (pkcs7TypeOID) {
539 case PKCS7_MSG:
540 typeSz = sizeof(pkcs7);
541 typeName = pkcs7;
542 break;
543
544 case DATA:
545 typeSz = sizeof(data);
546 typeName = data;
547 break;
548
549 case SIGNED_DATA:
550 typeSz = sizeof(signedData);
551 typeName = signedData;
552 break;
553
554 case ENVELOPED_DATA:
555 typeSz = sizeof(envelopedData);
556 typeName = envelopedData;
557 break;
558
559 case AUTH_ENVELOPED_DATA:
560 typeSz = sizeof(authEnvelopedData);
561 typeName = authEnvelopedData;
562 break;
563
564 case SIGNED_AND_ENVELOPED_DATA:
565 typeSz = sizeof(signedAndEnveloped);
566 typeName = signedAndEnveloped;
567 break;
568
569 case DIGESTED_DATA:
570 typeSz = sizeof(digestedData);
571 typeName = digestedData;
572 break;
573
574 #ifndef NO_PKCS7_ENCRYPTED_DATA
575 case ENCRYPTED_DATA:
576 typeSz = sizeof(encryptedData);
577 typeName = encryptedData;
578 break;
579 #endif
580 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
581 case COMPRESSED_DATA:
582 typeSz = sizeof(compressedData);
583 typeName = compressedData;
584 break;
585 #endif
586 case FIRMWARE_PKG_DATA:
587 typeSz = sizeof(firmwarePkgData);
588 typeName = firmwarePkgData;
589 break;
590
591 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
592 case PWRI_KEK_WRAP:
593 typeSz = sizeof(pwriKek);
594 typeName = pwriKek;
595 break;
596
597 case PBKDF2_OID:
598 typeSz = sizeof(pbkdf2);
599 typeName = pbkdf2;
600 break;
601 #endif
602
603 default:
604 WOLFSSL_MSG("Unknown PKCS#7 Type");
605 return 0;
606 };
607
608 if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) {
609 WOLFSSL_MSG("CMS content type buffer too small");
610 return BAD_FUNC_ARG;
611 }
612
613 idSz = SetLength(typeSz, ID_Length);
614 output[idx++] = ASN_OBJECT_ID;
615 XMEMCPY(output + idx, ID_Length, idSz);
616 idx += idSz;
617 XMEMCPY(output + idx, typeName, typeSz);
618 idx += typeSz;
619
620 return idx;
621 }
622
623
624 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
wc_GetContentType(const byte * input,word32 * inOutIdx,word32 * oid,word32 maxIdx)625 static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid,
626 word32 maxIdx)
627 {
628 WOLFSSL_ENTER("wc_GetContentType");
629 if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) {
630 WOLFSSL_LEAVE("wc_GetContentType", ASN_PARSE_E);
631 return ASN_PARSE_E;
632 }
633
634 return 0;
635 }
636
637
638 /* return block size for algorithm represented by oid, or <0 on error */
wc_PKCS7_GetOIDBlockSize(int oid)639 static int wc_PKCS7_GetOIDBlockSize(int oid)
640 {
641 int blockSz;
642
643 switch (oid) {
644 #ifndef NO_AES
645 #ifdef WOLFSSL_AES_128
646 #ifdef HAVE_AES_CBC
647 case AES128CBCb:
648 #endif
649 #ifdef HAVE_AESGCM
650 case AES128GCMb:
651 #endif
652 #ifdef HAVE_AESCCM
653 case AES128CCMb:
654 #endif
655 #endif
656 #ifdef WOLFSSL_AES_192
657 #ifdef HAVE_AES_CBC
658 case AES192CBCb:
659 #endif
660 #ifdef HAVE_AESGCM
661 case AES192GCMb:
662 #endif
663 #ifdef HAVE_AESCCM
664 case AES192CCMb:
665 #endif
666 #endif
667 #ifdef WOLFSSL_AES_256
668 #ifdef HAVE_AES_CBC
669 case AES256CBCb:
670 #endif
671 #ifdef HAVE_AESGCM
672 case AES256GCMb:
673 #endif
674 #ifdef HAVE_AESCCM
675 case AES256CCMb:
676 #endif
677 #endif
678 blockSz = AES_BLOCK_SIZE;
679 break;
680 #endif /* !NO_AES */
681
682 #ifndef NO_DES3
683 case DESb:
684 case DES3b:
685 blockSz = DES_BLOCK_SIZE;
686 break;
687 #endif
688 default:
689 WOLFSSL_MSG("Unsupported content cipher type");
690 return ALGO_ID_E;
691 };
692
693 return blockSz;
694 }
695
696
697 /* get key size for algorithm represented by oid, or <0 on error */
wc_PKCS7_GetOIDKeySize(int oid)698 static int wc_PKCS7_GetOIDKeySize(int oid)
699 {
700 int blockKeySz;
701
702 switch (oid) {
703 #ifndef NO_AES
704 #ifdef WOLFSSL_AES_128
705 #ifdef HAVE_AES_CBC
706 case AES128CBCb:
707 #endif
708 #ifdef HAVE_AESGCM
709 case AES128GCMb:
710 #endif
711 #ifdef HAVE_AESCCM
712 case AES128CCMb:
713 #endif
714 case AES128_WRAP:
715 blockKeySz = 16;
716 break;
717 #endif
718 #ifdef WOLFSSL_AES_192
719 #ifdef HAVE_AES_CBC
720 case AES192CBCb:
721 #endif
722 #ifdef HAVE_AESGCM
723 case AES192GCMb:
724 #endif
725 #ifdef HAVE_AESCCM
726 case AES192CCMb:
727 #endif
728 case AES192_WRAP:
729 blockKeySz = 24;
730 break;
731 #endif
732 #ifdef WOLFSSL_AES_256
733 #ifdef HAVE_AES_CBC
734 case AES256CBCb:
735 #endif
736 #ifdef HAVE_AESGCM
737 case AES256GCMb:
738 #endif
739 #ifdef HAVE_AESCCM
740 case AES256CCMb:
741 #endif
742 case AES256_WRAP:
743 blockKeySz = 32;
744 break;
745 #endif
746 #endif /* !NO_AES */
747
748 #ifndef NO_DES3
749 case DESb:
750 blockKeySz = DES_KEYLEN;
751 break;
752 case DES3b:
753 blockKeySz = DES3_KEYLEN;
754 break;
755 #endif
756 default:
757 WOLFSSL_MSG("Unsupported content cipher type");
758 return ALGO_ID_E;
759 };
760
761 return blockKeySz;
762 }
763
764
wc_PKCS7_New(void * heap,int devId)765 PKCS7* wc_PKCS7_New(void* heap, int devId)
766 {
767 PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7);
768 if (pkcs7) {
769 XMEMSET(pkcs7, 0, sizeof(PKCS7));
770 if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) {
771 pkcs7->isDynamic = 1;
772 }
773 else {
774 XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7);
775 pkcs7 = NULL;
776 }
777 }
778 return pkcs7;
779 }
780
781 /* This is to initialize a PKCS7 structure. It sets all values to 0 and can be
782 * used to set the heap hint.
783 *
784 * pkcs7 PKCS7 structure to initialize
785 * heap memory heap hint for PKCS7 structure to use
786 * devId currently not used but a place holder for async operations
787 *
788 * returns 0 on success or a negative value for failure
789 */
wc_PKCS7_Init(PKCS7 * pkcs7,void * heap,int devId)790 int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId)
791 {
792 word16 isDynamic;
793
794 WOLFSSL_ENTER("wc_PKCS7_Init");
795
796 if (pkcs7 == NULL) {
797 return BAD_FUNC_ARG;
798 }
799
800 isDynamic = pkcs7->isDynamic;
801 XMEMSET(pkcs7, 0, sizeof(PKCS7));
802 pkcs7->isDynamic = isDynamic;
803 #ifdef WOLFSSL_HEAP_TEST
804 pkcs7->heap = (void*)WOLFSSL_HEAP_TEST;
805 #else
806 pkcs7->heap = heap;
807 #endif
808 pkcs7->devId = devId;
809
810 return 0;
811 }
812
813
814 /* Certificate structure holding der pointer, size, and pointer to next
815 * Pkcs7Cert struct. Used when creating SignedData types with multiple
816 * certificates. */
817 struct Pkcs7Cert {
818 byte* der;
819 word32 derSz;
820 Pkcs7Cert* next;
821 };
822
823
824 /* Linked list of ASN.1 encoded RecipientInfos */
825 struct Pkcs7EncodedRecip {
826 byte recip[MAX_RECIP_SZ];
827 word32 recipSz;
828 int recipType;
829 int recipVersion;
830 Pkcs7EncodedRecip* next;
831 };
832
833
834 /* free all members of Pkcs7Cert linked list */
wc_PKCS7_FreeCertSet(PKCS7 * pkcs7)835 static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7)
836 {
837 Pkcs7Cert* curr = NULL;
838 Pkcs7Cert* next = NULL;
839
840 if (pkcs7 == NULL)
841 return;
842
843 curr = pkcs7->certList;
844 pkcs7->certList = NULL;
845
846 while (curr != NULL) {
847 next = curr->next;
848 curr->next = NULL;
849 XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
850 curr = next;
851 }
852
853 return;
854 }
855
856
857 /* Get total size of all recipients in recipient list.
858 *
859 * Returns total size of recipients, or negative upon error */
wc_PKCS7_GetRecipientListSize(PKCS7 * pkcs7)860 static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7)
861 {
862 int totalSz = 0;
863 Pkcs7EncodedRecip* tmp = NULL;
864
865 if (pkcs7 == NULL)
866 return BAD_FUNC_ARG;
867
868 tmp = pkcs7->recipList;
869
870 while (tmp != NULL) {
871 totalSz += tmp->recipSz;
872 tmp = tmp->next;
873 }
874
875 return totalSz;
876 }
877
878
879 /* free all members of Pkcs7EncodedRecip linked list */
wc_PKCS7_FreeEncodedRecipientSet(PKCS7 * pkcs7)880 static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7)
881 {
882 Pkcs7EncodedRecip* curr = NULL;
883 Pkcs7EncodedRecip* next = NULL;
884
885 if (pkcs7 == NULL)
886 return;
887
888 curr = pkcs7->recipList;
889 pkcs7->recipList = NULL;
890
891 while (curr != NULL) {
892 next = curr->next;
893 curr->next = NULL;
894 XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
895 curr = next;
896 }
897
898 return;
899 }
900
901
902 /* search through RecipientInfo list for specific type.
903 * return 1 if ANY recipient of type specified is present, otherwise
904 * return 0 */
wc_PKCS7_RecipientListIncludesType(PKCS7 * pkcs7,int type)905 static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type)
906 {
907 Pkcs7EncodedRecip* tmp = NULL;
908
909 if (pkcs7 == NULL)
910 return BAD_FUNC_ARG;
911
912 tmp = pkcs7->recipList;
913
914 while (tmp != NULL) {
915 if (tmp->recipType == type)
916 return 1;
917
918 tmp = tmp->next;
919 }
920
921 return 0;
922 }
923
924
925 /* searches through RecipientInfo list, returns 1 if all structure
926 * versions are set to 0, otherwise returns 0 */
wc_PKCS7_RecipientListVersionsAllZero(PKCS7 * pkcs7)927 static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7)
928 {
929 Pkcs7EncodedRecip* tmp = NULL;
930
931 if (pkcs7 == NULL)
932 return BAD_FUNC_ARG;
933
934 tmp = pkcs7->recipList;
935
936 while (tmp != NULL) {
937 if (tmp->recipVersion != 0)
938 return 0;
939
940 tmp = tmp->next;
941 }
942
943 return 1;
944 }
945
946 /* Verify RSA/ECC key is correctly formatted, used as sanity check after
947 * import of key/cert.
948 *
949 * keyOID - key OID (ex: RSAk, ECDSAk)
950 * key - key in DER
951 * keySz - size of key, octets
952 *
953 * Returns 0 on success, negative on error */
wc_PKCS7_CheckPublicKeyDer(PKCS7 * pkcs7,int keyOID,const byte * key,word32 keySz)954 static int wc_PKCS7_CheckPublicKeyDer(PKCS7* pkcs7, int keyOID,
955 const byte* key, word32 keySz)
956 {
957 int ret = 0;
958 word32 scratch = 0;
959 #ifdef WOLFSSL_SMALL_STACK
960 #ifndef NO_RSA
961 RsaKey* rsa;
962 #endif
963 #ifdef HAVE_ECC
964 ecc_key* ecc;
965 #endif
966 #else
967 #ifndef NO_RSA
968 RsaKey rsa[1];
969 #endif
970 #ifdef HAVE_ECC
971 ecc_key ecc[1];
972 #endif
973 #endif
974
975 if (pkcs7 == NULL || key == NULL || keySz == 0) {
976 return BAD_FUNC_ARG;
977 }
978
979 #ifdef WOLFSSL_SMALL_STACK
980 #ifndef NO_RSA
981 rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
982 DYNAMIC_TYPE_TMP_BUFFER);
983 if (rsa == NULL) {
984 return MEMORY_E;
985 }
986 #endif
987
988 #ifdef HAVE_ECC
989 ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
990 DYNAMIC_TYPE_TMP_BUFFER);
991 if (ecc == NULL) {
992 #ifndef NO_RSA
993 XFREE(rsa, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
994 #endif
995 return MEMORY_E;
996 }
997 #endif
998 #endif
999
1000 switch (keyOID) {
1001 #ifndef NO_RSA
1002 case RSAk:
1003 ret = wc_InitRsaKey_ex(rsa, pkcs7->heap, pkcs7->devId);
1004 if (ret != 0) {
1005 break;
1006 }
1007
1008 /* Try to decode public key as sanity check. wc_CheckRsaKey()
1009 only checks private key not public. */
1010 ret = wc_RsaPublicKeyDecode(key, &scratch, rsa, keySz);
1011 wc_FreeRsaKey(rsa);
1012
1013 break;
1014 #endif
1015 #ifdef HAVE_ECC
1016 case ECDSAk:
1017 ret = wc_ecc_init_ex(ecc, pkcs7->heap, pkcs7->devId);
1018 if (ret != 0) {
1019 break;
1020 }
1021
1022 /* Try to decode public key and check with wc_ecc_check_key() */
1023 ret = wc_EccPublicKeyDecode(key, &scratch, ecc, keySz);
1024 if (ret == 0) {
1025 ret = wc_ecc_check_key(ecc);
1026 }
1027 wc_ecc_free(ecc);
1028
1029 break;
1030 #endif
1031 }
1032
1033 #ifdef WOLFSSL_SMALL_STACK
1034 #ifndef NO_RSA
1035 XFREE(rsa, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1036 #endif
1037 #ifdef HAVE_ECC
1038 XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1039 #endif
1040 #endif
1041
1042 return ret;
1043 }
1044
1045
1046 /* Init PKCS7 struct with recipient cert, decode into DecodedCert
1047 * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
wc_PKCS7_InitWithCert(PKCS7 * pkcs7,byte * derCert,word32 derCertSz)1048 int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz)
1049 {
1050 int ret = 0;
1051 void* heap;
1052 int devId;
1053 Pkcs7Cert* cert;
1054 Pkcs7Cert* lastCert;
1055
1056 if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) {
1057 return BAD_FUNC_ARG;
1058 }
1059
1060 heap = pkcs7->heap;
1061 devId = pkcs7->devId;
1062 cert = pkcs7->certList;
1063 ret = wc_PKCS7_Init(pkcs7, heap, devId);
1064 if (ret != 0)
1065 return ret;
1066 pkcs7->certList = cert;
1067
1068 if (derCert != NULL && derCertSz > 0) {
1069 #ifdef WOLFSSL_SMALL_STACK
1070 DecodedCert* dCert;
1071
1072 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
1073 DYNAMIC_TYPE_DCERT);
1074 if (dCert == NULL)
1075 return MEMORY_E;
1076 #else
1077 DecodedCert dCert[1];
1078 #endif
1079
1080 pkcs7->singleCert = derCert;
1081 pkcs7->singleCertSz = derCertSz;
1082 pkcs7->cert[0] = derCert;
1083 pkcs7->certSz[0] = derCertSz;
1084
1085 /* create new Pkcs7Cert for recipient, freed during cleanup */
1086 cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap,
1087 DYNAMIC_TYPE_PKCS7);
1088 XMEMSET(cert, 0, sizeof(Pkcs7Cert));
1089 cert->der = derCert;
1090 cert->derSz = derCertSz;
1091 cert->next = NULL;
1092
1093 /* free existing cert list if existing */
1094 wc_PKCS7_FreeCertSet(pkcs7);
1095
1096 /* add cert to list */
1097 if (pkcs7->certList == NULL) {
1098 pkcs7->certList = cert;
1099 } else {
1100 lastCert = pkcs7->certList;
1101 while (lastCert->next != NULL) {
1102 lastCert = lastCert->next;
1103 }
1104 lastCert->next = cert;
1105 }
1106
1107 InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap);
1108 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
1109 if (ret < 0) {
1110 FreeDecodedCert(dCert);
1111 #ifdef WOLFSSL_SMALL_STACK
1112 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
1113 #endif
1114 return ret;
1115 }
1116
1117 /* verify extracted public key is valid before storing */
1118 ret = wc_PKCS7_CheckPublicKeyDer(pkcs7, dCert->keyOID,
1119 dCert->publicKey, dCert->pubKeySize);
1120 if (ret != 0) {
1121 WOLFSSL_MSG("Invalid public key, check pkcs7->cert");
1122 FreeDecodedCert(dCert);
1123 #ifdef WOLFSSL_SMALL_STACK
1124 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
1125 #endif
1126 return ret;
1127 }
1128
1129 if (dCert->pubKeySize > (MAX_RSA_INT_SZ + MAX_RSA_E_SZ) ||
1130 dCert->serialSz > MAX_SN_SZ) {
1131 WOLFSSL_MSG("Invalid size in certificate");
1132 FreeDecodedCert(dCert);
1133 #ifdef WOLFSSL_SMALL_STACK
1134 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
1135 #endif
1136 return ASN_PARSE_E;
1137 }
1138
1139 XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
1140 pkcs7->publicKeySz = dCert->pubKeySize;
1141 pkcs7->publicKeyOID = dCert->keyOID;
1142 XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
1143 pkcs7->issuer = dCert->issuerRaw;
1144 pkcs7->issuerSz = dCert->issuerRawLen;
1145 XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz);
1146 pkcs7->issuerSnSz = dCert->serialSz;
1147 XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE);
1148
1149 /* default to IssuerAndSerialNumber for SignerIdentifier */
1150 pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
1151
1152 /* free existing recipient list if existing */
1153 wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
1154
1155 FreeDecodedCert(dCert);
1156
1157 #ifdef WOLFSSL_SMALL_STACK
1158 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
1159 #endif
1160 }
1161
1162 return ret;
1163 }
1164
1165
1166 /* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate
1167 * list, to be added as part of the certificates CertificateSet. Currently
1168 * used in SignedData content type.
1169 *
1170 * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert().
1171 *
1172 * Does not represent the recipient/signer certificate, only certificates that
1173 * are part of the certificate chain used to build and verify signer
1174 * certificates.
1175 *
1176 * This API does not currently validate certificates.
1177 *
1178 * Returns 0 on success, negative upon error */
wc_PKCS7_AddCertificate(PKCS7 * pkcs7,byte * derCert,word32 derCertSz)1179 int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* derCert, word32 derCertSz)
1180 {
1181 Pkcs7Cert* cert;
1182
1183 if (pkcs7 == NULL || derCert == NULL || derCertSz == 0)
1184 return BAD_FUNC_ARG;
1185
1186 cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap,
1187 DYNAMIC_TYPE_PKCS7);
1188 if (cert == NULL)
1189 return MEMORY_E;
1190 XMEMSET(cert, 0, sizeof(Pkcs7Cert));
1191
1192 cert->der = derCert;
1193 cert->derSz = derCertSz;
1194
1195 if (pkcs7->certList == NULL) {
1196 pkcs7->certList = cert;
1197 } else {
1198 cert->next = pkcs7->certList;
1199 pkcs7->certList = cert;
1200 }
1201
1202 return 0;
1203 }
1204
1205
1206 /* free linked list of PKCS7DecodedAttrib structs */
wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib * attrib,void * heap)1207 static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap)
1208 {
1209 PKCS7DecodedAttrib* current;
1210
1211 if (attrib == NULL) {
1212 return;
1213 }
1214
1215 current = attrib;
1216 while (current != NULL) {
1217 PKCS7DecodedAttrib* next = current->next;
1218 if (current->oid != NULL) {
1219 XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7);
1220 }
1221 if (current->value != NULL) {
1222 XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7);
1223 }
1224 XFREE(current, heap, DYNAMIC_TYPE_PKCS7);
1225 current = next;
1226 }
1227
1228 (void)heap;
1229 }
1230
1231
1232 /* return 0 on success */
wc_PKCS7_SignerInfoNew(PKCS7 * pkcs7)1233 static int wc_PKCS7_SignerInfoNew(PKCS7* pkcs7)
1234 {
1235 if (pkcs7->signerInfo != NULL) {
1236 XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1237 pkcs7->signerInfo = NULL;
1238 }
1239
1240 pkcs7->signerInfo = (PKCS7SignerInfo*)XMALLOC(sizeof(PKCS7SignerInfo),
1241 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1242 if (pkcs7->signerInfo == NULL) {
1243 WOLFSSL_MSG("Unable to malloc memory for signer info");
1244 return MEMORY_E;
1245 }
1246 XMEMSET(pkcs7->signerInfo, 0, sizeof(PKCS7SignerInfo));
1247 return 0;
1248 }
1249
1250
wc_PKCS7_SignerInfoFree(PKCS7 * pkcs7)1251 static void wc_PKCS7_SignerInfoFree(PKCS7* pkcs7)
1252 {
1253 if (pkcs7->signerInfo != NULL) {
1254 if (pkcs7->signerInfo->sid != NULL) {
1255 XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1256 pkcs7->signerInfo->sid = NULL;
1257 }
1258 XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1259 pkcs7->signerInfo = NULL;
1260 }
1261 }
1262
1263
1264 /* free's any current SID and sets it to "in"
1265 * returns 0 on success
1266 */
wc_PKCS7_SignerInfoSetSID(PKCS7 * pkcs7,byte * in,int inSz)1267 static int wc_PKCS7_SignerInfoSetSID(PKCS7* pkcs7, byte* in, int inSz)
1268 {
1269 if (pkcs7 == NULL || in == NULL || inSz < 0) {
1270 return BAD_FUNC_ARG;
1271 }
1272
1273 if (pkcs7->signerInfo->sid != NULL) {
1274 XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1275 pkcs7->signerInfo->sid = NULL;
1276 }
1277 pkcs7->signerInfo->sid = (byte*)XMALLOC(inSz, pkcs7->heap,
1278 DYNAMIC_TYPE_PKCS7);
1279 if (pkcs7->signerInfo->sid == NULL) {
1280 return MEMORY_E;
1281 }
1282 XMEMCPY(pkcs7->signerInfo->sid, in, inSz);
1283 pkcs7->signerInfo->sidSz = inSz;
1284 return 0;
1285 }
1286
1287
1288 /* releases any memory allocated by a PKCS7 initializer */
wc_PKCS7_Free(PKCS7 * pkcs7)1289 void wc_PKCS7_Free(PKCS7* pkcs7)
1290 {
1291 if (pkcs7 == NULL)
1292 return;
1293
1294 #ifndef NO_PKCS7_STREAM
1295 wc_PKCS7_FreeStream(pkcs7);
1296 #endif
1297
1298 wc_PKCS7_SignerInfoFree(pkcs7);
1299 wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
1300 pkcs7->decodedAttrib = NULL;
1301 wc_PKCS7_FreeCertSet(pkcs7);
1302
1303 #ifdef ASN_BER_TO_DER
1304 if (pkcs7->der != NULL) {
1305 XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1306 pkcs7->der = NULL;
1307 }
1308 #endif
1309 if (pkcs7->contentDynamic != NULL) {
1310 XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1311 pkcs7->contentDynamic = NULL;
1312 }
1313
1314 if (pkcs7->cek != NULL) {
1315 ForceZero(pkcs7->cek, pkcs7->cekSz);
1316 XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1317 pkcs7->cek = NULL;
1318 }
1319
1320 pkcs7->contentTypeSz = 0;
1321
1322 if (pkcs7->signature) {
1323 XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE);
1324 pkcs7->signature = NULL;
1325 pkcs7->signatureSz = 0;
1326 }
1327 if (pkcs7->plainDigest) {
1328 XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
1329 pkcs7->plainDigest = NULL;
1330 pkcs7->plainDigestSz = 0;
1331 }
1332 if (pkcs7->pkcs7Digest) {
1333 XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
1334 pkcs7->pkcs7Digest = NULL;
1335 pkcs7->pkcs7DigestSz = 0;
1336 }
1337 if (pkcs7->cachedEncryptedContent != NULL) {
1338 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1339 pkcs7->cachedEncryptedContent = NULL;
1340 pkcs7->cachedEncryptedContentSz = 0;
1341 }
1342
1343 if (pkcs7->isDynamic) {
1344 pkcs7->isDynamic = 0;
1345 XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
1346 }
1347 }
1348
1349
1350 /* helper function for parsing through attributes and finding a specific one.
1351 * returns PKCS7DecodedAttrib pointer on success */
findAttrib(PKCS7 * pkcs7,const byte * oid,word32 oidSz)1352 static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz)
1353 {
1354 PKCS7DecodedAttrib* list;
1355
1356 if (pkcs7 == NULL || oid == NULL) {
1357 return NULL;
1358 }
1359
1360 /* search attributes for pkiStatus */
1361 list = pkcs7->decodedAttrib;
1362 while (list != NULL) {
1363 word32 sz = oidSz;
1364 word32 idx = 0;
1365 int length = 0;
1366 byte tag;
1367
1368 if (GetASNTag(list->oid, &idx, &tag, list->oidSz) < 0) {
1369 return NULL;
1370 }
1371 if (tag != ASN_OBJECT_ID) {
1372 WOLFSSL_MSG("Bad attribute ASN1 syntax");
1373 return NULL;
1374 }
1375
1376 if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) {
1377 WOLFSSL_MSG("Bad attribute length");
1378 return NULL;
1379 }
1380
1381 sz = (sz < (word32)length)? sz : (word32)length;
1382 if (XMEMCMP(oid, list->oid + idx, sz) == 0) {
1383 return list;
1384 }
1385 list = list->next;
1386 }
1387 return NULL;
1388 }
1389
1390
1391 /* Searches through decoded attributes and returns the value for the first one
1392 * matching the oid passed in. Note that this value includes the leading ASN1
1393 * syntax. So for a printable string of "3" this would be something like
1394 *
1395 * 0x13, 0x01, 0x33
1396 * ID SIZE "3"
1397 *
1398 * pkcs7 structure to get value from
1399 * oid OID value to search for with attributes
1400 * oidSz size of oid buffer
1401 * out buffer to hold result
1402 * outSz size of out buffer (if out is NULL this is set to needed size and
1403 LENGTH_ONLY_E is returned)
1404 *
1405 * returns size of value on success
1406 */
wc_PKCS7_GetAttributeValue(PKCS7 * pkcs7,const byte * oid,word32 oidSz,byte * out,word32 * outSz)1407 int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz,
1408 byte* out, word32* outSz)
1409 {
1410 PKCS7DecodedAttrib* attrib;
1411
1412 if (pkcs7 == NULL || oid == NULL || outSz == NULL) {
1413 return BAD_FUNC_ARG;
1414 }
1415
1416 attrib = findAttrib(pkcs7, oid, oidSz);
1417 if (attrib == NULL) {
1418 return ASN_PARSE_E;
1419 }
1420
1421 if (out == NULL) {
1422 *outSz = attrib->valueSz;
1423 return LENGTH_ONLY_E;
1424 }
1425
1426 if (*outSz < attrib->valueSz) {
1427 return BUFFER_E;
1428 }
1429
1430 XMEMCPY(out, attrib->value, attrib->valueSz);
1431 return attrib->valueSz;
1432 }
1433
1434
1435 /* build PKCS#7 data content type */
wc_PKCS7_EncodeData(PKCS7 * pkcs7,byte * output,word32 outputSz)1436 int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
1437 {
1438 static const byte oid[] =
1439 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
1440 0x07, 0x01 };
1441 byte seq[MAX_SEQ_SZ];
1442 byte octetStr[MAX_OCTET_STR_SZ];
1443 word32 seqSz;
1444 word32 octetStrSz;
1445 word32 oidSz = (word32)sizeof(oid);
1446 int idx = 0;
1447
1448 if (pkcs7 == NULL || output == NULL) {
1449 return BAD_FUNC_ARG;
1450 }
1451
1452 octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
1453 seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
1454
1455 if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
1456 return BUFFER_E;
1457
1458 XMEMCPY(output, seq, seqSz);
1459 idx += seqSz;
1460 XMEMCPY(output + idx, oid, oidSz);
1461 idx += oidSz;
1462 XMEMCPY(output + idx, octetStr, octetStrSz);
1463 idx += octetStrSz;
1464 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
1465 idx += pkcs7->contentSz;
1466
1467 return idx;
1468 }
1469
1470
1471 typedef struct EncodedAttrib {
1472 byte valueSeq[MAX_SEQ_SZ];
1473 const byte* oid;
1474 byte valueSet[MAX_SET_SZ];
1475 const byte* value;
1476 word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
1477 } EncodedAttrib;
1478
1479
1480 typedef struct ESD {
1481 wc_HashAlg hash;
1482 enum wc_HashType hashType;
1483 byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
1484 byte contentAttribsDigest[WC_MAX_DIGEST_SIZE];
1485 byte encContentDigest[MAX_ENCRYPTED_KEY_SZ];
1486
1487 byte outerSeq[MAX_SEQ_SZ];
1488 byte outerContent[MAX_EXP_SZ];
1489 byte innerSeq[MAX_SEQ_SZ];
1490 byte version[MAX_VERSION_SZ];
1491 byte digAlgoIdSet[MAX_SET_SZ];
1492 byte singleDigAlgoId[MAX_ALGO_SZ];
1493
1494 byte contentInfoSeq[MAX_SEQ_SZ];
1495 byte innerContSeq[MAX_EXP_SZ];
1496 byte innerOctets[MAX_OCTET_STR_SZ];
1497
1498 byte certsSet[MAX_SET_SZ];
1499
1500 byte signerInfoSet[MAX_SET_SZ];
1501 byte signerInfoSeq[MAX_SEQ_SZ];
1502 byte signerVersion[MAX_VERSION_SZ];
1503 /* issuerAndSerialNumber ...*/
1504 byte issuerSnSeq[MAX_SEQ_SZ];
1505 byte issuerName[MAX_SEQ_SZ];
1506 byte issuerSn[MAX_SN_SZ];
1507 /* OR subjectKeyIdentifier */
1508 byte issuerSKIDSeq[MAX_SEQ_SZ];
1509 byte issuerSKID[MAX_OCTET_STR_SZ];
1510 byte signerDigAlgoId[MAX_ALGO_SZ];
1511 byte digEncAlgoId[MAX_ALGO_SZ];
1512 byte signedAttribSet[MAX_SET_SZ];
1513 EncodedAttrib signedAttribs[7];
1514 byte signerDigest[MAX_OCTET_STR_SZ];
1515 word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
1516 word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
1517 singleDigAlgoIdSz, certsSetSz;
1518 word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
1519 issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz,
1520 issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
1521 word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
1522 signedAttribSetSz;
1523 } ESD;
1524
1525
EncodeAttributes(EncodedAttrib * ea,int eaSz,PKCS7Attrib * attribs,int attribsSz)1526 static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
1527 PKCS7Attrib* attribs, int attribsSz)
1528 {
1529 int i;
1530 int maxSz = min(eaSz, attribsSz);
1531 int allAttribsSz = 0;
1532
1533 for (i = 0; i < maxSz; i++)
1534 {
1535 int attribSz = 0;
1536
1537 ea[i].value = attribs[i].value;
1538 ea[i].valueSz = attribs[i].valueSz;
1539 attribSz += ea[i].valueSz;
1540 ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
1541 attribSz += ea[i].valueSetSz;
1542 ea[i].oid = attribs[i].oid;
1543 ea[i].oidSz = attribs[i].oidSz;
1544 attribSz += ea[i].oidSz;
1545 ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
1546 attribSz += ea[i].valueSeqSz;
1547 ea[i].totalSz = attribSz;
1548
1549 allAttribsSz += attribSz;
1550 }
1551 return allAttribsSz;
1552 }
1553
1554
1555 typedef struct FlatAttrib {
1556 byte* data;
1557 word32 dataSz;
1558 } FlatAttrib;
1559
1560 /* Returns a pointer to FlatAttrib whose members are initialized to 0.
1561 * Caller is expected to free.
1562 */
NewAttrib(void * heap)1563 static FlatAttrib* NewAttrib(void* heap)
1564 {
1565 FlatAttrib* fb = (FlatAttrib*) XMALLOC(sizeof(FlatAttrib), heap,
1566 DYNAMIC_TYPE_TMP_BUFFER);
1567 if (fb != NULL) {
1568 ForceZero(fb, sizeof(FlatAttrib));
1569 }
1570 (void)heap;
1571 return fb;
1572 }
1573
1574 /* Free FlatAttrib array and memory allocated to internal struct members */
FreeAttribArray(PKCS7 * pkcs7,FlatAttrib ** arr,int rows)1575 static void FreeAttribArray(PKCS7* pkcs7, FlatAttrib** arr, int rows)
1576 {
1577 int i;
1578
1579 if (arr) {
1580 for (i = 0; i < rows; i++) {
1581 if (arr[i]) {
1582 if (arr[i]->data) {
1583 ForceZero(arr[i]->data, arr[i]->dataSz);
1584 XFREE(arr[i]->data, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1585 }
1586 ForceZero(arr[i], sizeof(FlatAttrib));
1587 XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1588 }
1589 }
1590 ForceZero(arr, rows);
1591 XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1592 }
1593 (void)pkcs7;
1594 }
1595
1596
1597 /* Sort FlatAttrib array in ascending order */
SortAttribArray(FlatAttrib ** arr,int rows)1598 static int SortAttribArray(FlatAttrib** arr, int rows)
1599 {
1600 int i, j;
1601 word32 minSz, minIdx;
1602 FlatAttrib* a = NULL;
1603 FlatAttrib* b = NULL;
1604 FlatAttrib* tmp = NULL;
1605
1606 if (arr == NULL) {
1607 return BAD_FUNC_ARG;
1608 }
1609
1610 for (i = 0; i < rows; i++) {
1611 a = arr[i];
1612 minSz = a->dataSz;
1613 minIdx = i;
1614 for (j = i+1; j < rows; j++) {
1615 b = arr[j];
1616 if (b->dataSz < minSz) {
1617 minSz = b->dataSz;
1618 minIdx = j;
1619 }
1620 }
1621 if (minSz < a->dataSz) {
1622 /* swap array positions */
1623 tmp = arr[i];
1624 arr[i] = arr[minIdx];
1625 arr[minIdx] = tmp;
1626 }
1627 }
1628
1629 return 0;
1630 }
1631
1632
1633 /* Build up array of FlatAttrib structs from EncodedAttrib ones. FlatAttrib
1634 * holds flattened DER encoding of each attribute */
FlattenEncodedAttribs(PKCS7 * pkcs7,FlatAttrib ** derArr,int rows,EncodedAttrib * ea,int eaSz)1635 static int FlattenEncodedAttribs(PKCS7* pkcs7, FlatAttrib** derArr, int rows,
1636 EncodedAttrib* ea, int eaSz)
1637 {
1638 int i, idx, sz;
1639 byte* output = NULL;
1640 FlatAttrib* fa = NULL;
1641
1642 if (pkcs7 == NULL || derArr == NULL || ea == NULL) {
1643 WOLFSSL_MSG("Invalid arguments to FlattenEncodedAttribs");
1644 return BAD_FUNC_ARG;
1645 }
1646
1647 if (rows != eaSz) {
1648 WOLFSSL_MSG("DER array not large enough to hold attribute count");
1649 return BAD_FUNC_ARG;
1650 }
1651
1652 for (i = 0; i < eaSz; i++) {
1653 sz = ea[i].valueSeqSz + ea[i].oidSz + ea[i].valueSetSz + ea[i].valueSz;
1654
1655 output = (byte*)XMALLOC(sz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1656 if (output == NULL) {
1657 return MEMORY_E;
1658 }
1659
1660 idx = 0;
1661 XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
1662 idx += ea[i].valueSeqSz;
1663 XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
1664 idx += ea[i].oidSz;
1665 XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
1666 idx += ea[i].valueSetSz;
1667 XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
1668
1669 fa = derArr[i];
1670 fa->data = output;
1671 fa->dataSz = sz;
1672 }
1673
1674 return 0;
1675 }
1676
1677
1678 /* Sort and Flatten EncodedAttrib attributes into output buffer */
FlattenAttributes(PKCS7 * pkcs7,byte * output,EncodedAttrib * ea,int eaSz)1679 static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea,
1680 int eaSz)
1681 {
1682 int i, idx, ret;
1683 FlatAttrib** derArr = NULL;
1684 FlatAttrib* fa = NULL;
1685
1686 if (pkcs7 == NULL || output == NULL || ea == NULL) {
1687 return BAD_FUNC_ARG;
1688 }
1689
1690 /* create array of FlatAttrib struct pointers to hold DER attribs */
1691 derArr = (FlatAttrib**) XMALLOC(eaSz * sizeof(FlatAttrib*), pkcs7->heap,
1692 DYNAMIC_TYPE_TMP_BUFFER);
1693 if (derArr == NULL) {
1694 return MEMORY_E;
1695 }
1696 XMEMSET(derArr, 0, eaSz * sizeof(FlatAttrib*));
1697
1698 for (i = 0; i < eaSz; i++) {
1699 derArr[i] = NewAttrib(pkcs7->heap);
1700 if (derArr[i] == NULL) {
1701 FreeAttribArray(pkcs7, derArr, eaSz);
1702 return MEMORY_E;
1703 }
1704 ForceZero(derArr[i], sizeof(FlatAttrib));
1705 }
1706
1707 /* flatten EncodedAttrib into DER byte arrays */
1708 ret = FlattenEncodedAttribs(pkcs7, derArr, eaSz, ea, eaSz);
1709 if (ret != 0) {
1710 FreeAttribArray(pkcs7, derArr, eaSz);
1711 return ret;
1712 }
1713
1714 /* SET OF DER signed attributes must be sorted in ascending order */
1715 ret = SortAttribArray(derArr, eaSz);
1716 if (ret != 0) {
1717 FreeAttribArray(pkcs7, derArr, eaSz);
1718 return ret;
1719 }
1720
1721 /* copy sorted DER attribute arrays into output buffer */
1722 idx = 0;
1723 for (i = 0; i < eaSz; i++) {
1724 fa = derArr[i];
1725 XMEMCPY(output + idx, fa->data, fa->dataSz);
1726 idx += fa->dataSz;
1727 }
1728
1729 FreeAttribArray(pkcs7, derArr, eaSz);
1730
1731 return 0;
1732 }
1733
1734
1735 #ifndef NO_RSA
1736
1737 /* returns size of signature put into out, negative on error */
wc_PKCS7_RsaSign(PKCS7 * pkcs7,byte * in,word32 inSz,ESD * esd)1738 static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
1739 {
1740 int ret;
1741 word32 idx;
1742 #ifdef WOLFSSL_SMALL_STACK
1743 RsaKey* privKey;
1744 #else
1745 RsaKey privKey[1];
1746 #endif
1747
1748 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
1749 return BAD_FUNC_ARG;
1750 }
1751
1752 #ifdef WOLFSSL_SMALL_STACK
1753 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
1754 DYNAMIC_TYPE_TMP_BUFFER);
1755 if (privKey == NULL)
1756 return MEMORY_E;
1757 #endif
1758
1759 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
1760 if (ret == 0) {
1761 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
1762 idx = 0;
1763 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
1764 pkcs7->privateKeySz);
1765 }
1766 else if (pkcs7->devId == INVALID_DEVID) {
1767 ret = BAD_FUNC_ARG;
1768 }
1769 }
1770
1771 /* If not using old FIPS or CAVP selftest, or not using FAST,
1772 or USER RSA, able to check RSA key. */
1773 #if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(HAVE_FAST_RSA) && \
1774 !defined(HAVE_USER_RSA) && (!defined(HAVE_FIPS) || \
1775 (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) && \
1776 !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA)
1777
1778 #if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK)
1779 /* verify imported private key is a valid key before using it */
1780 if (ret == 0) {
1781 ret = wc_CheckRsaKey(privKey);
1782 if (ret != 0) {
1783 WOLFSSL_MSG("Invalid RSA private key, check pkcs7->privateKey");
1784 }
1785 }
1786 #endif
1787 #endif
1788
1789 if (ret == 0) {
1790 #ifdef WOLFSSL_ASYNC_CRYPT
1791 do {
1792 ret = wc_AsyncWait(ret, &privKey->asyncDev,
1793 WC_ASYNC_FLAG_CALL_AGAIN);
1794 if (ret >= 0)
1795 #endif
1796 {
1797 ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest,
1798 sizeof(esd->encContentDigest),
1799 privKey, pkcs7->rng);
1800 }
1801 #ifdef WOLFSSL_ASYNC_CRYPT
1802 } while (ret == WC_PENDING_E);
1803 #endif
1804 }
1805
1806 wc_FreeRsaKey(privKey);
1807 #ifdef WOLFSSL_SMALL_STACK
1808 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1809 #endif
1810
1811 return ret;
1812 }
1813
1814 #endif /* NO_RSA */
1815
1816
1817 #ifdef HAVE_ECC
1818
1819 /* returns size of signature put into out, negative on error */
wc_PKCS7_EcdsaSign(PKCS7 * pkcs7,byte * in,word32 inSz,ESD * esd)1820 static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
1821 {
1822 int ret;
1823 word32 outSz, idx;
1824 #ifdef WOLFSSL_SMALL_STACK
1825 ecc_key* privKey;
1826 #else
1827 ecc_key privKey[1];
1828 #endif
1829
1830 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
1831 return BAD_FUNC_ARG;
1832 }
1833
1834 #ifdef WOLFSSL_SMALL_STACK
1835 privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
1836 DYNAMIC_TYPE_TMP_BUFFER);
1837 if (privKey == NULL)
1838 return MEMORY_E;
1839 #endif
1840
1841 ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId);
1842 if (ret == 0) {
1843 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
1844 idx = 0;
1845 ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
1846 pkcs7->privateKeySz);
1847 }
1848 else if (pkcs7->devId == INVALID_DEVID) {
1849 ret = BAD_FUNC_ARG;
1850 }
1851 }
1852
1853 /* verify imported private key is a valid key before using it */
1854 if (ret == 0) {
1855 ret = wc_ecc_check_key(privKey);
1856 if (ret != 0) {
1857 WOLFSSL_MSG("Invalid ECC private key, check pkcs7->privateKey");
1858 }
1859 }
1860
1861 if (ret == 0) {
1862 outSz = sizeof(esd->encContentDigest);
1863 #ifdef WOLFSSL_ASYNC_CRYPT
1864 do {
1865 ret = wc_AsyncWait(ret, &privKey->asyncDev,
1866 WC_ASYNC_FLAG_CALL_AGAIN);
1867 if (ret >= 0)
1868 #endif
1869 {
1870 ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest,
1871 &outSz, pkcs7->rng, privKey);
1872 }
1873 #ifdef WOLFSSL_ASYNC_CRYPT
1874 } while (ret == WC_PENDING_E);
1875 #endif
1876 if (ret == 0)
1877 ret = (int)outSz;
1878 }
1879
1880 wc_ecc_free(privKey);
1881 #ifdef WOLFSSL_SMALL_STACK
1882 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
1883 #endif
1884
1885 return ret;
1886 }
1887
1888 #endif /* HAVE_ECC */
1889
1890
1891 /* builds up SignedData signed attributes, including default ones.
1892 *
1893 * pkcs7 - pointer to initialized PKCS7 structure
1894 * esd - pointer to initialized ESD structure, used for output
1895 *
1896 * return 0 on success, negative on error */
wc_PKCS7_BuildSignedAttributes(PKCS7 * pkcs7,ESD * esd,const byte * contentType,word32 contentTypeSz,const byte * contentTypeOid,word32 contentTypeOidSz,const byte * messageDigestOid,word32 messageDigestOidSz,const byte * signingTimeOid,word32 signingTimeOidSz,byte * signingTime,word32 signingTimeSz)1897 static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd,
1898 const byte* contentType, word32 contentTypeSz,
1899 const byte* contentTypeOid, word32 contentTypeOidSz,
1900 const byte* messageDigestOid, word32 messageDigestOidSz,
1901 const byte* signingTimeOid, word32 signingTimeOidSz,
1902 byte* signingTime, word32 signingTimeSz)
1903 {
1904 int hashSz;
1905 #ifdef NO_ASN_TIME
1906 PKCS7Attrib cannedAttribs[2];
1907 #else
1908 time_t tm;
1909 int timeSz;
1910 PKCS7Attrib cannedAttribs[3];
1911 #endif
1912 word32 idx = 0;
1913 word32 cannedAttribsCount;
1914
1915 if (pkcs7 == NULL || esd == NULL || contentType == NULL ||
1916 contentTypeOid == NULL || messageDigestOid == NULL ||
1917 signingTimeOid == NULL) {
1918 return BAD_FUNC_ARG;
1919 }
1920
1921 if (pkcs7->skipDefaultSignedAttribs == 0) {
1922 hashSz = wc_HashGetDigestSize(esd->hashType);
1923 if (hashSz < 0)
1924 return hashSz;
1925
1926 #ifndef NO_ASN_TIME
1927 if (signingTime == NULL || signingTimeSz == 0)
1928 return BAD_FUNC_ARG;
1929
1930 tm = XTIME(0);
1931 timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz);
1932 if (timeSz < 0)
1933 return timeSz;
1934 #endif
1935
1936 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
1937
1938 cannedAttribs[idx].oid = contentTypeOid;
1939 cannedAttribs[idx].oidSz = contentTypeOidSz;
1940 cannedAttribs[idx].value = contentType;
1941 cannedAttribs[idx].valueSz = contentTypeSz;
1942 idx++;
1943 #ifndef NO_ASN_TIME
1944 cannedAttribs[idx].oid = signingTimeOid;
1945 cannedAttribs[idx].oidSz = signingTimeOidSz;
1946 cannedAttribs[idx].value = signingTime;
1947 cannedAttribs[idx].valueSz = timeSz;
1948 idx++;
1949 #endif
1950 cannedAttribs[idx].oid = messageDigestOid;
1951 cannedAttribs[idx].oidSz = messageDigestOidSz;
1952 cannedAttribs[idx].value = esd->contentDigest;
1953 cannedAttribs[idx].valueSz = hashSz + 2; /* ASN.1 heading */
1954
1955 esd->signedAttribsCount += cannedAttribsCount;
1956 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3,
1957 cannedAttribs, cannedAttribsCount);
1958 } else {
1959 esd->signedAttribsCount = 0;
1960 esd->signedAttribsSz = 0;
1961 }
1962
1963 /* add custom signed attributes if set */
1964 if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) {
1965 esd->signedAttribsCount += pkcs7->signedAttribsSz;
1966 #ifdef NO_ASN_TIME
1967 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
1968 pkcs7->signedAttribs, pkcs7->signedAttribsSz);
1969 #else
1970 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4,
1971 pkcs7->signedAttribs, pkcs7->signedAttribsSz);
1972 #endif
1973 }
1974
1975 #ifdef NO_ASN_TIME
1976 (void)signingTimeOidSz;
1977 (void)signingTime;
1978 (void)signingTimeSz;
1979 #endif
1980
1981 return 0;
1982 }
1983
1984
1985 /* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or
1986 * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID.
1987 *
1988 * pkcs7 - pointer to PKCS7 structure
1989 * digEncAlgoId - [OUT] output int to store correct algo ID in
1990 * digEncAlgoType - [OUT] output for algo ID type
1991 *
1992 * return 0 on success, negative on error */
wc_PKCS7_SignedDataGetEncAlgoId(PKCS7 * pkcs7,int * digEncAlgoId,int * digEncAlgoType)1993 static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId,
1994 int* digEncAlgoType)
1995 {
1996 int algoId = 0;
1997 int algoType = 0;
1998
1999 if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL)
2000 return BAD_FUNC_ARG;
2001
2002 if (pkcs7->publicKeyOID == RSAk) {
2003
2004 algoType = oidSigType;
2005
2006 switch (pkcs7->hashOID) {
2007 #ifndef NO_SHA
2008 case SHAh:
2009 algoId = CTC_SHAwRSA;
2010 break;
2011 #endif
2012 #ifdef WOLFSSL_SHA224
2013 case SHA224h:
2014 algoId = CTC_SHA224wRSA;
2015 break;
2016 #endif
2017 #ifndef NO_SHA256
2018 case SHA256h:
2019 algoId = CTC_SHA256wRSA;
2020 break;
2021 #endif
2022 #ifdef WOLFSSL_SHA384
2023 case SHA384h:
2024 algoId = CTC_SHA384wRSA;
2025 break;
2026 #endif
2027 #ifdef WOLFSSL_SHA512
2028 case SHA512h:
2029 algoId = CTC_SHA512wRSA;
2030 break;
2031 #endif
2032 #ifdef WOLFSSL_SHA3
2033 #ifndef WOLFSSL_NOSHA3_224
2034 case SHA3_224h:
2035 algoId = CTC_SHA3_224wRSA;
2036 break;
2037 #endif
2038 #ifndef WOLFSSL_NOSHA3_256
2039 case SHA3_256h:
2040 algoId = CTC_SHA3_256wRSA;
2041 break;
2042 #endif
2043 #ifndef WOLFSSL_NOSHA3_384
2044 case SHA3_384h:
2045 algoId = CTC_SHA3_384wRSA;
2046 break;
2047 #endif
2048 #ifndef WOLFSSL_NOSHA3_512
2049 case SHA3_512h:
2050 algoId = CTC_SHA3_512wRSA;
2051 break;
2052 #endif
2053 #endif
2054 }
2055
2056 }
2057 #ifdef HAVE_ECC
2058 else if (pkcs7->publicKeyOID == ECDSAk) {
2059
2060 algoType = oidSigType;
2061
2062 switch (pkcs7->hashOID) {
2063 #ifndef NO_SHA
2064 case SHAh:
2065 algoId = CTC_SHAwECDSA;
2066 break;
2067 #endif
2068 #ifdef WOLFSSL_SHA224
2069 case SHA224h:
2070 algoId = CTC_SHA224wECDSA;
2071 break;
2072 #endif
2073 #ifndef NO_SHA256
2074 case SHA256h:
2075 algoId = CTC_SHA256wECDSA;
2076 break;
2077 #endif
2078 #ifdef WOLFSSL_SHA384
2079 case SHA384h:
2080 algoId = CTC_SHA384wECDSA;
2081 break;
2082 #endif
2083 #ifdef WOLFSSL_SHA512
2084 case SHA512h:
2085 algoId = CTC_SHA512wECDSA;
2086 break;
2087 #endif
2088 #ifdef WOLFSSL_SHA3
2089 #ifndef WOLFSSL_NOSHA3_224
2090 case SHA3_224h:
2091 algoId = CTC_SHA3_224wECDSA;
2092 break;
2093 #endif
2094 #ifndef WOLFSSL_NOSHA3_256
2095 case SHA3_256h:
2096 algoId = CTC_SHA3_256wECDSA;
2097 break;
2098 #endif
2099 #ifndef WOLFSSL_NOSHA3_384
2100 case SHA3_384h:
2101 algoId = CTC_SHA3_384wECDSA;
2102 break;
2103 #endif
2104 #ifndef WOLFSSL_NOSHA3_512
2105 case SHA3_512h:
2106 algoId = CTC_SHA3_512wECDSA;
2107 break;
2108 #endif
2109 #endif
2110 }
2111 }
2112 #endif /* HAVE_ECC */
2113
2114 if (algoId == 0) {
2115 WOLFSSL_MSG("Invalid signature algorithm type");
2116 return BAD_FUNC_ARG;
2117 }
2118
2119 *digEncAlgoId = algoId;
2120 *digEncAlgoType = algoType;
2121
2122 return 0;
2123 }
2124
2125
2126 /* build SignedData DigestInfo for use with PKCS#7/RSA
2127 *
2128 * pkcs7 - pointer to initialized PKCS7 struct
2129 * flatSignedAttribs - flattened, signed attributes
2130 * flatSignedAttrbsSz - size of flatSignedAttribs, octets
2131 * esd - pointer to initialized ESD struct
2132 * digestInfo - [OUT] output array for DigestInfo
2133 * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo
2134 *
2135 * return 0 on success, negative on error */
wc_PKCS7_BuildDigestInfo(PKCS7 * pkcs7,byte * flatSignedAttribs,word32 flatSignedAttribsSz,ESD * esd,byte * digestInfo,word32 * digestInfoSz)2136 static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs,
2137 word32 flatSignedAttribsSz, ESD* esd,
2138 byte* digestInfo, word32* digestInfoSz)
2139 {
2140 int ret, hashSz, digIdx = 0;
2141 byte digestInfoSeq[MAX_SEQ_SZ];
2142 byte digestStr[MAX_OCTET_STR_SZ];
2143 byte attribSet[MAX_SET_SZ];
2144 byte algoId[MAX_ALGO_SZ];
2145 word32 digestInfoSeqSz, digestStrSz, algoIdSz;
2146 word32 attribSetSz;
2147
2148 if (pkcs7 == NULL || esd == NULL || digestInfo == NULL ||
2149 digestInfoSz == NULL) {
2150 return BAD_FUNC_ARG;
2151 }
2152
2153 hashSz = wc_HashGetDigestSize(esd->hashType);
2154 if (hashSz < 0)
2155 return hashSz;
2156
2157 if (flatSignedAttribsSz != 0) {
2158
2159 if (flatSignedAttribs == NULL)
2160 return BAD_FUNC_ARG;
2161
2162 attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
2163
2164 ret = wc_HashInit(&esd->hash, esd->hashType);
2165 if (ret < 0)
2166 return ret;
2167
2168 ret = wc_HashUpdate(&esd->hash, esd->hashType,
2169 attribSet, attribSetSz);
2170 if (ret == 0)
2171 ret = wc_HashUpdate(&esd->hash, esd->hashType,
2172 flatSignedAttribs, flatSignedAttribsSz);
2173 if (ret == 0)
2174 ret = wc_HashFinal(&esd->hash, esd->hashType,
2175 esd->contentAttribsDigest);
2176 wc_HashFree(&esd->hash, esd->hashType);
2177
2178 if (ret < 0)
2179 return ret;
2180
2181 } else {
2182 /* when no attrs, digest is contentDigest without tag and length */
2183 XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz);
2184 }
2185
2186 /* set algoID, with NULL attributes */
2187 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
2188
2189 digestStrSz = SetOctetString(hashSz, digestStr);
2190 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
2191 digestInfoSeq);
2192
2193 if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) {
2194 return BUFFER_E;
2195 }
2196
2197 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
2198 digIdx += digestInfoSeqSz;
2199 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
2200 digIdx += algoIdSz;
2201 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
2202 digIdx += digestStrSz;
2203 XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz);
2204 digIdx += hashSz;
2205
2206 *digestInfoSz = digIdx;
2207
2208 return 0;
2209 }
2210
2211
2212 /* build SignedData signature over DigestInfo or content digest
2213 *
2214 * pkcs7 - pointer to initialized PKCS7 struct
2215 * flatSignedAttribs - flattened, signed attributes
2216 * flatSignedAttribsSz - size of flatSignedAttribs, octets
2217 * esd - pointer to initialized ESD struct
2218 *
2219 * returns length of signature on success, negative on error */
wc_PKCS7_SignedDataBuildSignature(PKCS7 * pkcs7,byte * flatSignedAttribs,word32 flatSignedAttribsSz,ESD * esd)2220 static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
2221 byte* flatSignedAttribs,
2222 word32 flatSignedAttribsSz,
2223 ESD* esd)
2224 {
2225 int ret = 0;
2226 #if defined(HAVE_ECC) || \
2227 (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA))
2228 int hashSz = 0;
2229 #endif
2230 #if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
2231 int hashOID;
2232 #endif
2233 word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ;
2234 #ifdef WOLFSSL_SMALL_STACK
2235 byte* digestInfo;
2236 #else
2237 byte digestInfo[MAX_PKCS7_DIGEST_SZ];
2238 #endif
2239
2240 if (pkcs7 == NULL || esd == NULL)
2241 return BAD_FUNC_ARG;
2242
2243 #ifdef WOLFSSL_SMALL_STACK
2244 digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap,
2245 DYNAMIC_TYPE_TMP_BUFFER);
2246 if (digestInfo == NULL) {
2247 return MEMORY_E;
2248 }
2249 #endif
2250 XMEMSET(digestInfo, 0, digestInfoSz);
2251
2252 ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs,
2253 flatSignedAttribsSz, esd, digestInfo,
2254 &digestInfoSz);
2255 if (ret < 0) {
2256 #ifdef WOLFSSL_SMALL_STACK
2257 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2258 #endif
2259 return ret;
2260 }
2261
2262 #if defined(HAVE_ECC) || \
2263 (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA))
2264 /* get digest size from hash type */
2265 hashSz = wc_HashGetDigestSize(esd->hashType);
2266 if (hashSz < 0) {
2267 #ifdef WOLFSSL_SMALL_STACK
2268 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2269 #endif
2270 return hashSz;
2271 }
2272 #endif
2273
2274 /* sign digestInfo */
2275 switch (pkcs7->publicKeyOID) {
2276
2277 #ifndef NO_RSA
2278 case RSAk:
2279 #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
2280 if (pkcs7->rsaSignRawDigestCb != NULL) {
2281 /* get hash OID */
2282 hashOID = wc_HashGetOID(esd->hashType);
2283
2284 /* user signing plain digest, build DigestInfo themselves */
2285 ret = pkcs7->rsaSignRawDigestCb(pkcs7,
2286 esd->contentAttribsDigest, hashSz,
2287 esd->encContentDigest, sizeof(esd->encContentDigest),
2288 pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId,
2289 hashOID);
2290 break;
2291 }
2292 #endif
2293 ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd);
2294 break;
2295 #endif
2296
2297 #ifdef HAVE_ECC
2298 case ECDSAk:
2299 /* CMS with ECDSA does not sign DigestInfo structure
2300 * like PKCS#7 with RSA does */
2301 ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest,
2302 hashSz, esd);
2303 break;
2304 #endif
2305
2306 default:
2307 WOLFSSL_MSG("Unsupported public key type");
2308 ret = BAD_FUNC_ARG;
2309 }
2310
2311 #ifdef WOLFSSL_SMALL_STACK
2312 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2313 #endif
2314
2315 if (ret >= 0) {
2316 esd->encContentDigestSz = (word32)ret;
2317 }
2318
2319 return ret;
2320 }
2321
2322
2323 /* build PKCS#7 signedData content type */
2324 /* To get the output size then set output = 0 and *outputSz = 0 */
PKCS7_EncodeSigned(PKCS7 * pkcs7,ESD * esd,const byte * hashBuf,word32 hashSz,byte * output,word32 * outputSz,byte * output2,word32 * output2Sz)2325 static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
2326 const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz,
2327 byte* output2, word32* output2Sz)
2328 {
2329 /* contentType OID (1.2.840.113549.1.9.3) */
2330 static const byte contentTypeOid[] =
2331 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
2332 0x09, 0x03 };
2333
2334 /* messageDigest OID (1.2.840.113549.1.9.4) */
2335 static const byte messageDigestOid[] =
2336 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
2337 0x09, 0x04 };
2338
2339 /* signingTime OID () */
2340 static const byte signingTimeOid[] =
2341 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
2342 0x09, 0x05};
2343
2344 Pkcs7Cert* certPtr = NULL;
2345 word32 certSetSz = 0;
2346
2347 word32 signerInfoSz = 0;
2348 word32 totalSz, total2Sz;
2349 int idx = 0, ret = 0;
2350 int digEncAlgoId, digEncAlgoType;
2351 byte* flatSignedAttribs = NULL;
2352 word32 flatSignedAttribsSz = 0;
2353
2354 #ifdef WOLFSSL_SMALL_STACK
2355 byte *signedDataOid = NULL;
2356 #else
2357 byte signedDataOid[MAX_OID_SZ];
2358 #endif
2359 word32 signedDataOidSz;
2360
2361 byte signingTime[MAX_TIME_STRING_SZ];
2362
2363 if (pkcs7 == NULL || pkcs7->hashOID == 0 ||
2364 outputSz == NULL || hashSz == 0 ||
2365 hashBuf == NULL) {
2366 return BAD_FUNC_ARG;
2367 }
2368
2369 #ifdef WOLFSSL_SMALL_STACK
2370 signedDataOid = (byte *)XMALLOC(MAX_OID_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2371 if (signedDataOid == NULL) {
2372 idx = MEMORY_E;
2373 goto out;
2374 }
2375
2376 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2377 if (esd == NULL) {
2378 idx = MEMORY_E;
2379 goto out;
2380 }
2381 #endif
2382
2383 XMEMSET(esd, 0, sizeof(ESD));
2384
2385 /* set content type based on contentOID, unless user has set custom one
2386 with wc_PKCS7_SetContentType() */
2387 if (pkcs7->contentTypeSz == 0) {
2388
2389 /* default to DATA content type if user has not set */
2390 if (pkcs7->contentOID == 0) {
2391 pkcs7->contentOID = DATA;
2392 }
2393
2394 ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType,
2395 sizeof(pkcs7->contentType));
2396 if (ret < 0) {
2397 idx = ret;
2398 goto out;
2399 }
2400 pkcs7->contentTypeSz = ret;
2401 }
2402
2403 /* set signedData outer content type */
2404 ret = wc_SetContentType(SIGNED_DATA, signedDataOid, MAX_OID_SZ);
2405 if (ret < 0) {
2406 idx = ret;
2407 goto out;
2408 }
2409 signedDataOidSz = ret;
2410
2411 if (pkcs7->sidType != DEGENERATE_SID) {
2412 esd->hashType = wc_OidGetHash(pkcs7->hashOID);
2413 if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) {
2414 WOLFSSL_MSG("hashSz did not match hashOID");
2415 idx = BUFFER_E;
2416 goto out;
2417 }
2418
2419 /* include hash */
2420 esd->contentDigest[0] = ASN_OCTET_STRING;
2421 esd->contentDigest[1] = (byte)hashSz;
2422 XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz);
2423 }
2424
2425 if (pkcs7->detached == 1) {
2426 /* do not include content if generating detached signature */
2427 esd->innerOctetsSz = 0;
2428 esd->innerContSeqSz = 0;
2429 esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz,
2430 esd->contentInfoSeq);
2431 } else {
2432 esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
2433 esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz +
2434 pkcs7->contentSz, esd->innerContSeq);
2435 esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz +
2436 esd->innerOctetsSz + pkcs7->contentTypeSz +
2437 esd->innerContSeqSz, esd->contentInfoSeq);
2438 }
2439
2440 /* SignerIdentifier */
2441 if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
2442 /* IssuerAndSerialNumber */
2443 esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
2444 esd->issuerSn, MAX_SN_SZ, MAX_SN_SZ);
2445 signerInfoSz += esd->issuerSnSz;
2446 esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
2447 signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
2448 esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
2449 signerInfoSz += esd->issuerSnSeqSz;
2450
2451 if (pkcs7->version == 3) {
2452 /* RFC 4108 version MUST be 3 for firmware package signer */
2453 esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0);
2454 }
2455 else {
2456 /* version MUST be 1 otherwise*/
2457 esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0);
2458 }
2459
2460 } else if (pkcs7->sidType == CMS_SKID) {
2461 /* SubjectKeyIdentifier */
2462 esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID);
2463 esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE,
2464 esd->issuerSKIDSeq);
2465 signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz +
2466 KEYID_SIZE);
2467
2468 /* version MUST be 3 */
2469 esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0);
2470 } else if (pkcs7->sidType == DEGENERATE_SID) {
2471 /* no signer info added */
2472 } else {
2473 idx = SKID_E;
2474 goto out;
2475 }
2476
2477 if (pkcs7->sidType != DEGENERATE_SID) {
2478 signerInfoSz += esd->signerVersionSz;
2479 esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId,
2480 oidHashType, 0);
2481 signerInfoSz += esd->signerDigAlgoIdSz;
2482
2483 /* set signatureAlgorithm */
2484 ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId,
2485 &digEncAlgoType);
2486 if (ret < 0) {
2487 idx = ret;
2488 goto out;
2489 }
2490 esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId,
2491 digEncAlgoType, 0);
2492 signerInfoSz += esd->digEncAlgoIdSz;
2493
2494 /* build up signed attributes, include contentType, signingTime, and
2495 messageDigest by default */
2496 ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType,
2497 pkcs7->contentTypeSz,
2498 contentTypeOid, sizeof(contentTypeOid),
2499 messageDigestOid, sizeof(messageDigestOid),
2500 signingTimeOid, sizeof(signingTimeOid),
2501 signingTime, sizeof(signingTime));
2502 if (ret < 0) {
2503 idx = ret;
2504 goto out;
2505 }
2506
2507 if (esd->signedAttribsSz > 0) {
2508 flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap,
2509 DYNAMIC_TYPE_PKCS7);
2510 if (flatSignedAttribs == NULL) {
2511 idx = MEMORY_E;
2512 goto out;
2513 }
2514
2515 flatSignedAttribsSz = esd->signedAttribsSz;
2516
2517 FlattenAttributes(pkcs7, flatSignedAttribs,
2518 esd->signedAttribs, esd->signedAttribsCount);
2519 esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
2520 esd->signedAttribSet);
2521 } else {
2522 esd->signedAttribSetSz = 0;
2523 }
2524
2525 /* Calculate the final hash and encrypt it. */
2526 ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs,
2527 flatSignedAttribsSz, esd);
2528 if (ret < 0) {
2529 idx = ret;
2530 goto out;
2531 }
2532
2533 signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
2534
2535 esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
2536 esd->signerDigest);
2537 signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
2538
2539 esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
2540 signerInfoSz += esd->signerInfoSeqSz;
2541 }
2542 esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
2543 signerInfoSz += esd->signerInfoSetSz;
2544
2545 /* certificates [0] IMPLICIT CertificateSet */
2546 /* get total certificates size */
2547 certPtr = pkcs7->certList;
2548 while (certPtr != NULL) {
2549 certSetSz += certPtr->derSz;
2550 certPtr = certPtr->next;
2551 }
2552 certPtr = NULL;
2553
2554 if (certSetSz > 0)
2555 esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet);
2556
2557 if (pkcs7->sidType != DEGENERATE_SID) {
2558 esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
2559 oidHashType, 0);
2560 }
2561 esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
2562
2563 if (pkcs7->version == 3) {
2564 /* RFC 4108 version MUST be 3 for firmware package signer */
2565 esd->versionSz = SetMyVersion(3, esd->version, 0);
2566 }
2567 else {
2568 esd->versionSz = SetMyVersion(1, esd->version, 0);
2569 }
2570
2571 totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
2572 esd->contentInfoSeqSz + pkcs7->contentTypeSz +
2573 esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz;
2574 total2Sz = esd->certsSetSz + certSetSz + signerInfoSz;
2575
2576 if (pkcs7->detached) {
2577 totalSz -= pkcs7->contentSz;
2578 }
2579
2580 esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq);
2581 totalSz += esd->innerSeqSz;
2582 esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent);
2583 totalSz += esd->outerContentSz + signedDataOidSz;
2584 esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq);
2585 totalSz += esd->outerSeqSz;
2586
2587 /* if using header/footer, we are not returning the content */
2588 if (output2 && output2Sz) {
2589 if (total2Sz > *output2Sz) {
2590 if (*outputSz == 0 && *output2Sz == 0) {
2591 *outputSz = totalSz;
2592 *output2Sz = total2Sz;
2593 idx = 0;
2594 goto out;
2595 }
2596 idx = BUFFER_E;
2597 goto out;
2598 }
2599
2600 if (!pkcs7->detached) {
2601 totalSz -= pkcs7->contentSz;
2602 }
2603 }
2604 else {
2605 /* if using single output buffer include content and footer */
2606 totalSz += total2Sz;
2607 }
2608
2609 if (totalSz > *outputSz) {
2610 if (*outputSz == 0) {
2611 *outputSz = totalSz;
2612 idx = totalSz;
2613 goto out;
2614 }
2615 idx = BUFFER_E;
2616 goto out;
2617 }
2618
2619 if (output == NULL) {
2620 idx = BUFFER_E;
2621 goto out;
2622 }
2623
2624 idx = 0;
2625 XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
2626 idx += esd->outerSeqSz;
2627 XMEMCPY(output + idx, signedDataOid, signedDataOidSz);
2628 idx += signedDataOidSz;
2629 XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz);
2630 idx += esd->outerContentSz;
2631 XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz);
2632 idx += esd->innerSeqSz;
2633 XMEMCPY(output + idx, esd->version, esd->versionSz);
2634 idx += esd->versionSz;
2635 XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz);
2636 idx += esd->digAlgoIdSetSz;
2637 XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
2638 idx += esd->singleDigAlgoIdSz;
2639 XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz);
2640 idx += esd->contentInfoSeqSz;
2641 XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz);
2642 idx += pkcs7->contentTypeSz;
2643 XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz);
2644 idx += esd->innerContSeqSz;
2645 XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz);
2646 idx += esd->innerOctetsSz;
2647
2648 /* support returning header and footer without content */
2649 if (output2 && output2Sz) {
2650 *outputSz = idx;
2651 idx = 0;
2652 }
2653 else {
2654 if (!pkcs7->detached && pkcs7->content != NULL && pkcs7->contentSz > 0) {
2655 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
2656 idx += pkcs7->contentSz;
2657 }
2658 output2 = output;
2659 }
2660
2661 /* certificates */
2662 XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz);
2663 idx += esd->certsSetSz;
2664 certPtr = pkcs7->certList;
2665 while (certPtr != NULL) {
2666 XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz);
2667 idx += certPtr->derSz;
2668 certPtr = certPtr->next;
2669 }
2670 wc_PKCS7_FreeCertSet(pkcs7);
2671
2672 XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz);
2673 idx += esd->signerInfoSetSz;
2674 XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz);
2675 idx += esd->signerInfoSeqSz;
2676 XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz);
2677 idx += esd->signerVersionSz;
2678 /* SignerIdentifier */
2679 if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
2680 /* IssuerAndSerialNumber */
2681 XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz);
2682 idx += esd->issuerSnSeqSz;
2683 XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz);
2684 idx += esd->issuerNameSz;
2685 XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz);
2686 idx += pkcs7->issuerSz;
2687 XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz);
2688 idx += esd->issuerSnSz;
2689 } else if (pkcs7->sidType == CMS_SKID) {
2690 /* SubjectKeyIdentifier */
2691 XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz);
2692 idx += esd->issuerSKIDSeqSz;
2693 XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz);
2694 idx += esd->issuerSKIDSz;
2695 XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE);
2696 idx += KEYID_SIZE;
2697 } else if (pkcs7->sidType == DEGENERATE_SID) {
2698 /* no signer infos in degenerate case */
2699 } else {
2700 idx = SKID_E;
2701 goto out;
2702 }
2703 XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
2704 idx += esd->signerDigAlgoIdSz;
2705
2706 /* SignerInfo:Attributes */
2707 if (flatSignedAttribsSz > 0) {
2708 XMEMCPY(output2 + idx, esd->signedAttribSet, esd->signedAttribSetSz);
2709 idx += esd->signedAttribSetSz;
2710 XMEMCPY(output2 + idx, flatSignedAttribs, flatSignedAttribsSz);
2711 idx += flatSignedAttribsSz;
2712 }
2713
2714 XMEMCPY(output2 + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz);
2715 idx += esd->digEncAlgoIdSz;
2716 XMEMCPY(output2 + idx, esd->signerDigest, esd->signerDigestSz);
2717 idx += esd->signerDigestSz;
2718 XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz);
2719 idx += esd->encContentDigestSz;
2720
2721 if (output2 && output2Sz) {
2722 *output2Sz = idx;
2723 idx = 0; /* success */
2724 }
2725 else {
2726 *outputSz = idx;
2727 }
2728
2729 out:
2730
2731 if (flatSignedAttribs != NULL)
2732 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
2733
2734 #ifdef WOLFSSL_SMALL_STACK
2735 if (esd)
2736 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2737 if (signedDataOid)
2738 XFREE(signedDataOid, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2739 #endif
2740
2741 return idx;
2742 }
2743
2744 /* hashBuf: The computed digest for the pkcs7->content
2745 * hashSz: The size of computed digest for the pkcs7->content based on hashOID
2746 * outputHead: The PKCS7 header that goes on top of the raw data signed.
2747 * outputFoot: The PKCS7 footer that goes at the end of the raw data signed.
2748 * pkcs7->content: Not used
2749 * pkcs7->contentSz: Must be provided as actual sign of raw data
2750 * return codes: 0=success, negative=error
2751 */
wc_PKCS7_EncodeSignedData_ex(PKCS7 * pkcs7,const byte * hashBuf,word32 hashSz,byte * outputHead,word32 * outputHeadSz,byte * outputFoot,word32 * outputFootSz)2752 int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
2753 word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot,
2754 word32* outputFootSz)
2755 {
2756 int ret;
2757 #ifdef WOLFSSL_SMALL_STACK
2758 ESD* esd;
2759 #else
2760 ESD esd[1];
2761 #endif
2762
2763 /* other args checked in wc_PKCS7_EncodeSigned_ex */
2764 if (pkcs7 == NULL || outputFoot == NULL || outputFootSz == NULL) {
2765 return BAD_FUNC_ARG;
2766 }
2767
2768 #ifdef WOLFSSL_SMALL_STACK
2769 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2770 if (esd == NULL)
2771 return MEMORY_E;
2772 #endif
2773
2774 XMEMSET(esd, 0, sizeof(ESD));
2775
2776 ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz,
2777 outputHead, outputHeadSz, outputFoot, outputFootSz);
2778
2779 #ifdef WOLFSSL_SMALL_STACK
2780 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2781 #endif
2782
2783 return ret;
2784 }
2785
2786 /* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type.
2787 * By default wolfCrypt includes the data to be signed in the SignedData
2788 * bundle. This data can be omitted in the case when a detached signature is
2789 * being created. To enable generation of detached signatures, set flag to "1",
2790 * otherwise set to "0":
2791 *
2792 * flag 1 turns on support
2793 * flag 0 turns off support
2794 *
2795 * pkcs7 - pointer to initialized PKCS7 structure
2796 * flag - turn on/off detached signature generation (1 or 0)
2797 *
2798 * Returns 0 on success, negative upon error. */
wc_PKCS7_SetDetached(PKCS7 * pkcs7,word16 flag)2799 int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag)
2800 {
2801 if (pkcs7 == NULL || (flag != 0 && flag != 1))
2802 return BAD_FUNC_ARG;
2803
2804 pkcs7->detached = flag;
2805
2806 return 0;
2807 }
2808
2809 /* By default, SignedData bundles have the following signed attributes attached:
2810 * contentType (1.2.840.113549.1.9.3)
2811 * signingTime (1.2.840.113549.1.9.5)
2812 * messageDigest (1.2.840.113549.1.9.4)
2813 *
2814 * Calling this API before wc_PKCS7_EncodeSignedData() will disable the
2815 * inclusion of those attributes.
2816 *
2817 * pkcs7 - pointer to initialized PKCS7 structure
2818 *
2819 * Returns 0 on success, negative upon error. */
wc_PKCS7_NoDefaultSignedAttribs(PKCS7 * pkcs7)2820 int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7)
2821 {
2822 if (pkcs7 == NULL)
2823 return BAD_FUNC_ARG;
2824
2825 pkcs7->skipDefaultSignedAttribs = 1;
2826
2827 return 0;
2828 }
2829
2830 /* return codes: >0: Size of signed PKCS7 output buffer, negative: error */
wc_PKCS7_EncodeSignedData(PKCS7 * pkcs7,byte * output,word32 outputSz)2831 int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
2832 {
2833 int ret;
2834 int hashSz;
2835 enum wc_HashType hashType;
2836 byte hashBuf[WC_MAX_DIGEST_SIZE];
2837 #ifdef WOLFSSL_SMALL_STACK
2838 ESD* esd;
2839 #else
2840 ESD esd[1];
2841 #endif
2842
2843 /* other args checked in wc_PKCS7_EncodeSigned_ex */
2844 if (pkcs7 == NULL || (pkcs7->contentSz > 0 && pkcs7->content == NULL)) {
2845 return BAD_FUNC_ARG;
2846 }
2847
2848 /* get hash type and size, validate hashOID */
2849 hashType = wc_OidGetHash(pkcs7->hashOID);
2850 hashSz = wc_HashGetDigestSize(hashType);
2851 if (hashSz < 0)
2852 return hashSz;
2853
2854 #ifdef WOLFSSL_SMALL_STACK
2855 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2856 if (esd == NULL)
2857 return MEMORY_E;
2858 #endif
2859
2860 XMEMSET(esd, 0, sizeof(ESD));
2861 esd->hashType = hashType;
2862
2863 /* calculate hash for content */
2864 ret = wc_HashInit(&esd->hash, esd->hashType);
2865 if (ret == 0) {
2866 ret = wc_HashUpdate(&esd->hash, esd->hashType,
2867 pkcs7->content, pkcs7->contentSz);
2868 if (ret == 0) {
2869 ret = wc_HashFinal(&esd->hash, esd->hashType, hashBuf);
2870 }
2871 wc_HashFree(&esd->hash, esd->hashType);
2872 }
2873
2874 if (ret == 0) {
2875 ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz,
2876 output, &outputSz, NULL, NULL);
2877 }
2878
2879 #ifdef WOLFSSL_SMALL_STACK
2880 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
2881 #endif
2882
2883 return ret;
2884 }
2885
2886
2887 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a
2888 * content of type FirmwarePkgData. Any recipient certificates should be
2889 * loaded into the PKCS7 structure prior to calling this function, using
2890 * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate().
2891 *
2892 * pkcs7 - pointer to initialized PKCS7 struct
2893 * privateKey - private RSA/ECC key, used for signing SignedData
2894 * privateKeySz - size of privateKey, octets
2895 * signOID - public key algorithm OID, used for sign operation
2896 * hashOID - hash algorithm OID, used for signature generation
2897 * content - content to be encapsulated, of type FirmwarePkgData
2898 * contentSz - size of content, octets
2899 * signedAttribs - optional signed attributes
2900 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs
2901 * output - output buffer for final bundle
2902 * outputSz - size of output buffer, octets
2903 *
2904 * Returns length of generated bundle on success, negative upon error. */
wc_PKCS7_EncodeSignedFPD(PKCS7 * pkcs7,byte * privateKey,word32 privateKeySz,int signOID,int hashOID,byte * content,word32 contentSz,PKCS7Attrib * signedAttribs,word32 signedAttribsSz,byte * output,word32 outputSz)2905 int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey,
2906 word32 privateKeySz, int signOID, int hashOID,
2907 byte* content, word32 contentSz,
2908 PKCS7Attrib* signedAttribs, word32 signedAttribsSz,
2909 byte* output, word32 outputSz)
2910 {
2911 int ret = 0;
2912 WC_RNG rng;
2913
2914 if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 ||
2915 content == NULL || contentSz == 0 || output == NULL || outputSz == 0)
2916 return BAD_FUNC_ARG;
2917
2918 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
2919 if (ret != 0)
2920 return ret;
2921
2922 pkcs7->rng = &rng;
2923 pkcs7->content = content;
2924 pkcs7->contentSz = contentSz;
2925 pkcs7->contentOID = FIRMWARE_PKG_DATA;
2926 pkcs7->hashOID = hashOID;
2927 pkcs7->encryptOID = signOID;
2928 pkcs7->privateKey = privateKey;
2929 pkcs7->privateKeySz = privateKeySz;
2930 pkcs7->signedAttribs = signedAttribs;
2931 pkcs7->signedAttribsSz = signedAttribsSz;
2932 pkcs7->version = 3;
2933
2934 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
2935 if (ret <= 0) {
2936 WOLFSSL_MSG("Error encoding CMS SignedData content type");
2937 }
2938
2939 pkcs7->rng = NULL;
2940 wc_FreeRng(&rng);
2941
2942 return ret;
2943 }
2944
2945 #ifndef NO_PKCS7_ENCRYPTED_DATA
2946
2947 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a
2948 * CMS EncryptedData bundle. Content of inner EncryptedData is set to that
2949 * of FirmwarePkgData. Any recipient certificates should be loaded into the
2950 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert()
2951 * and/or wc_PKCS7_AddCertificate().
2952 *
2953 * pkcs7 - pointer to initialized PKCS7 struct
2954 * encryptKey - encryption key used for encrypting EncryptedData
2955 * encryptKeySz - size of encryptKey, octets
2956 * privateKey - private RSA/ECC key, used for signing SignedData
2957 * privateKeySz - size of privateKey, octets
2958 * encryptOID - encryption algorithm OID, to be used as encryption
2959 * algorithm for EncryptedData
2960 * signOID - public key algorithm OID, to be used for sign
2961 * operation in SignedData generation
2962 * hashOID - hash algorithm OID, to be used for signature in
2963 * SignedData generation
2964 * content - content to be encapsulated
2965 * contentSz - size of content, octets
2966 * unprotectedAttribs - optional unprotected attributes, for EncryptedData
2967 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs
2968 * signedAttribs - optional signed attributes, for SignedData
2969 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs
2970 * output - output buffer for final bundle
2971 * outputSz - size of output buffer, octets
2972 *
2973 * Returns length of generated bundle on success, negative upon error. */
wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7 * pkcs7,byte * encryptKey,word32 encryptKeySz,byte * privateKey,word32 privateKeySz,int encryptOID,int signOID,int hashOID,byte * content,word32 contentSz,PKCS7Attrib * unprotectedAttribs,word32 unprotectedAttribsSz,PKCS7Attrib * signedAttribs,word32 signedAttribsSz,byte * output,word32 outputSz)2974 int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey,
2975 word32 encryptKeySz, byte* privateKey,
2976 word32 privateKeySz, int encryptOID,
2977 int signOID, int hashOID,
2978 byte* content, word32 contentSz,
2979 PKCS7Attrib* unprotectedAttribs,
2980 word32 unprotectedAttribsSz,
2981 PKCS7Attrib* signedAttribs,
2982 word32 signedAttribsSz,
2983 byte* output, word32 outputSz)
2984 {
2985 int ret = 0, encryptedSz = 0;
2986 byte* encrypted = NULL;
2987 WC_RNG rng;
2988
2989 if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 ||
2990 privateKey == NULL || privateKeySz == 0 || content == NULL ||
2991 contentSz == 0 || output == NULL || outputSz == 0) {
2992 return BAD_FUNC_ARG;
2993 }
2994
2995 /* 1: build up EncryptedData using FirmwarePkgData type, use output
2996 * buffer as tmp for storage and to get size */
2997
2998 /* set struct elements, inner content type is FirmwarePkgData */
2999 pkcs7->content = content;
3000 pkcs7->contentSz = contentSz;
3001 pkcs7->contentOID = FIRMWARE_PKG_DATA;
3002 pkcs7->encryptOID = encryptOID;
3003 pkcs7->encryptionKey = encryptKey;
3004 pkcs7->encryptionKeySz = encryptKeySz;
3005 pkcs7->unprotectedAttribs = unprotectedAttribs;
3006 pkcs7->unprotectedAttribsSz = unprotectedAttribsSz;
3007 pkcs7->version = 3;
3008
3009 encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz);
3010 if (encryptedSz < 0) {
3011 WOLFSSL_MSG("Error encoding CMS EncryptedData content type");
3012 return encryptedSz;
3013 }
3014
3015 /* save encryptedData, reset output buffer and struct */
3016 encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3017 if (encrypted == NULL) {
3018 ForceZero(output, outputSz);
3019 return MEMORY_E;
3020 }
3021
3022 XMEMCPY(encrypted, output, encryptedSz);
3023 ForceZero(output, outputSz);
3024
3025 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
3026 if (ret != 0) {
3027 ForceZero(encrypted, encryptedSz);
3028 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3029 return ret;
3030 }
3031
3032 /* 2: build up SignedData, encapsulating EncryptedData */
3033 pkcs7->rng = &rng;
3034 pkcs7->content = encrypted;
3035 pkcs7->contentSz = encryptedSz;
3036 pkcs7->contentOID = ENCRYPTED_DATA;
3037 pkcs7->hashOID = hashOID;
3038 pkcs7->encryptOID = signOID;
3039 pkcs7->privateKey = privateKey;
3040 pkcs7->privateKeySz = privateKeySz;
3041 pkcs7->signedAttribs = signedAttribs;
3042 pkcs7->signedAttribsSz = signedAttribsSz;
3043
3044 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
3045 if (ret <= 0) {
3046 WOLFSSL_MSG("Error encoding CMS SignedData content type");
3047 }
3048
3049 ForceZero(encrypted, encryptedSz);
3050 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3051 pkcs7->rng = NULL;
3052 wc_FreeRng(&rng);
3053
3054 return ret;
3055 }
3056
3057 #endif /* NO_PKCS7_ENCRYPTED_DATA */
3058
3059 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
3060 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a
3061 * CMS CompressedData bundle. Content of inner CompressedData is set to that
3062 * of FirmwarePkgData. Any recipient certificates should be loaded into the
3063 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert()
3064 * and/or wc_PKCS7_AddCertificate().
3065 *
3066 * pkcs7 - pointer to initialized PKCS7 struct
3067 * privateKey - private RSA/ECC key, used for signing SignedData
3068 * privateKeySz - size of privateKey, octets
3069 * signOID - public key algorithm OID, to be used for sign
3070 * operation in SignedData generation
3071 * hashOID - hash algorithm OID, to be used for signature in
3072 * SignedData generation
3073 * content - content to be encapsulated
3074 * contentSz - size of content, octets
3075 * signedAttribs - optional signed attributes, for SignedData
3076 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs
3077 * output - output buffer for final bundle
3078 * outputSz - size of output buffer, octets
3079 *
3080 * Returns length of generated bundle on success, negative upon error. */
wc_PKCS7_EncodeSignedCompressedFPD(PKCS7 * pkcs7,byte * privateKey,word32 privateKeySz,int signOID,int hashOID,byte * content,word32 contentSz,PKCS7Attrib * signedAttribs,word32 signedAttribsSz,byte * output,word32 outputSz)3081 int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey,
3082 word32 privateKeySz, int signOID,
3083 int hashOID, byte* content,
3084 word32 contentSz,
3085 PKCS7Attrib* signedAttribs,
3086 word32 signedAttribsSz, byte* output,
3087 word32 outputSz)
3088 {
3089 int ret = 0, compressedSz = 0;
3090 byte* compressed = NULL;
3091 WC_RNG rng;
3092
3093 if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 ||
3094 content == NULL || contentSz == 0 || output == NULL || outputSz == 0) {
3095 return BAD_FUNC_ARG;
3096 }
3097
3098 /* 1: build up CompressedData using FirmwarePkgData type, use output
3099 * buffer as tmp for storage and to get size */
3100
3101 /* set struct elements, inner content type is FirmwarePkgData */
3102 pkcs7->content = content;
3103 pkcs7->contentSz = contentSz;
3104 pkcs7->contentOID = FIRMWARE_PKG_DATA;
3105 pkcs7->version = 3;
3106
3107 compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz);
3108 if (compressedSz < 0) {
3109 WOLFSSL_MSG("Error encoding CMS CompressedData content type");
3110 return compressedSz;
3111 }
3112
3113 /* save compressedData, reset output buffer and struct */
3114 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3115 if (compressed == NULL) {
3116 ForceZero(output, outputSz);
3117 return MEMORY_E;
3118 }
3119
3120 XMEMCPY(compressed, output, compressedSz);
3121 ForceZero(output, outputSz);
3122
3123 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
3124 if (ret != 0) {
3125 ForceZero(compressed, compressedSz);
3126 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3127 return ret;
3128 }
3129
3130 /* 2: build up SignedData, encapsulating EncryptedData */
3131 pkcs7->rng = &rng;
3132 pkcs7->content = compressed;
3133 pkcs7->contentSz = compressedSz;
3134 pkcs7->contentOID = COMPRESSED_DATA;
3135 pkcs7->hashOID = hashOID;
3136 pkcs7->encryptOID = signOID;
3137 pkcs7->privateKey = privateKey;
3138 pkcs7->privateKeySz = privateKeySz;
3139 pkcs7->signedAttribs = signedAttribs;
3140 pkcs7->signedAttribsSz = signedAttribsSz;
3141
3142 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
3143 if (ret <= 0) {
3144 WOLFSSL_MSG("Error encoding CMS SignedData content type");
3145 }
3146
3147 ForceZero(compressed, compressedSz);
3148 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3149 pkcs7->rng = NULL;
3150 wc_FreeRng(&rng);
3151
3152 return ret;
3153 }
3154
3155 #ifndef NO_PKCS7_ENCRYPTED_DATA
3156
3157 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a
3158 * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData
3159 * bundle. Content of inner CompressedData is set to that of FirmwarePkgData.
3160 * Any recipient certificates should be loaded into the PKCS7 structure prior
3161 * to calling this function, using wc_PKCS7_InitWithCert() and/or
3162 * wc_PKCS7_AddCertificate().
3163 *
3164 * pkcs7 - pointer to initialized PKCS7 struct
3165 * encryptKey - encryption key used for encrypting EncryptedData
3166 * encryptKeySz - size of encryptKey, octets
3167 * privateKey - private RSA/ECC key, used for signing SignedData
3168 * privateKeySz - size of privateKey, octets
3169 * encryptOID - encryption algorithm OID, to be used as encryption
3170 * algorithm for EncryptedData
3171 * signOID - public key algorithm OID, to be used for sign
3172 * operation in SignedData generation
3173 * hashOID - hash algorithm OID, to be used for signature in
3174 * SignedData generation
3175 * content - content to be encapsulated
3176 * contentSz - size of content, octets
3177 * unprotectedAttribs - optional unprotected attributes, for EncryptedData
3178 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs
3179 * signedAttribs - optional signed attributes, for SignedData
3180 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs
3181 * output - output buffer for final bundle
3182 * outputSz - size of output buffer, octets
3183 *
3184 * Returns length of generated bundle on success, negative upon error. */
wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7 * pkcs7,byte * encryptKey,word32 encryptKeySz,byte * privateKey,word32 privateKeySz,int encryptOID,int signOID,int hashOID,byte * content,word32 contentSz,PKCS7Attrib * unprotectedAttribs,word32 unprotectedAttribsSz,PKCS7Attrib * signedAttribs,word32 signedAttribsSz,byte * output,word32 outputSz)3185 int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey,
3186 word32 encryptKeySz, byte* privateKey,
3187 word32 privateKeySz, int encryptOID,
3188 int signOID, int hashOID, byte* content,
3189 word32 contentSz,
3190 PKCS7Attrib* unprotectedAttribs,
3191 word32 unprotectedAttribsSz,
3192 PKCS7Attrib* signedAttribs,
3193 word32 signedAttribsSz,
3194 byte* output, word32 outputSz)
3195 {
3196 int ret = 0, compressedSz = 0, encryptedSz = 0;
3197 byte* compressed = NULL;
3198 byte* encrypted = NULL;
3199 WC_RNG rng;
3200
3201 if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 ||
3202 privateKey == NULL || privateKeySz == 0 || content == NULL ||
3203 contentSz == 0 || output == NULL || outputSz == 0) {
3204 return BAD_FUNC_ARG;
3205 }
3206
3207 /* 1: build up CompressedData using FirmwarePkgData type, use output
3208 * buffer as tmp for storage and to get size */
3209 pkcs7->content = content;
3210 pkcs7->contentSz = contentSz;
3211 pkcs7->contentOID = FIRMWARE_PKG_DATA;
3212 pkcs7->version = 3;
3213
3214 compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz);
3215 if (compressedSz < 0) {
3216 WOLFSSL_MSG("Error encoding CMS CompressedData content type");
3217 return compressedSz;
3218 }
3219
3220 /* save compressedData, reset output buffer and struct */
3221 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3222 if (compressed == NULL)
3223 return MEMORY_E;
3224
3225 XMEMCPY(compressed, output, compressedSz);
3226 ForceZero(output, outputSz);
3227
3228 /* 2: build up EncryptedData using CompressedData, use output
3229 * buffer as tmp for storage and to get size */
3230 pkcs7->content = compressed;
3231 pkcs7->contentSz = compressedSz;
3232 pkcs7->contentOID = COMPRESSED_DATA;
3233 pkcs7->encryptOID = encryptOID;
3234 pkcs7->encryptionKey = encryptKey;
3235 pkcs7->encryptionKeySz = encryptKeySz;
3236 pkcs7->unprotectedAttribs = unprotectedAttribs;
3237 pkcs7->unprotectedAttribsSz = unprotectedAttribsSz;
3238
3239 encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz);
3240 if (encryptedSz < 0) {
3241 WOLFSSL_MSG("Error encoding CMS EncryptedData content type");
3242 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3243 return encryptedSz;
3244 }
3245
3246 /* save encryptedData, reset output buffer and struct */
3247 encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3248 if (encrypted == NULL) {
3249 ForceZero(compressed, compressedSz);
3250 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3251 return MEMORY_E;
3252 }
3253
3254 XMEMCPY(encrypted, output, encryptedSz);
3255 ForceZero(compressed, compressedSz);
3256 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3257 ForceZero(output, outputSz);
3258
3259 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
3260 if (ret != 0) {
3261 ForceZero(encrypted, encryptedSz);
3262 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3263 return ret;
3264 }
3265
3266 /* 3: build up SignedData, encapsulating EncryptedData */
3267 pkcs7->rng = &rng;
3268 pkcs7->content = encrypted;
3269 pkcs7->contentSz = encryptedSz;
3270 pkcs7->contentOID = ENCRYPTED_DATA;
3271 pkcs7->hashOID = hashOID;
3272 pkcs7->encryptOID = signOID;
3273 pkcs7->privateKey = privateKey;
3274 pkcs7->privateKeySz = privateKeySz;
3275 pkcs7->signedAttribs = signedAttribs;
3276 pkcs7->signedAttribsSz = signedAttribsSz;
3277
3278 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
3279 if (ret <= 0) {
3280 WOLFSSL_MSG("Error encoding CMS SignedData content type");
3281 }
3282
3283 ForceZero(encrypted, encryptedSz);
3284 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
3285 pkcs7->rng = NULL;
3286 wc_FreeRng(&rng);
3287
3288 return ret;
3289 }
3290
3291 #endif /* !NO_PKCS7_ENCRYPTED_DATA */
3292 #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */
3293
3294
3295 #ifndef NO_RSA
3296
3297 #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
3298 /* register raw RSA sign digest callback */
wc_PKCS7_SetRsaSignRawDigestCb(PKCS7 * pkcs7,CallbackRsaSignRawDigest cb)3299 int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, CallbackRsaSignRawDigest cb)
3300 {
3301 if (pkcs7 == NULL || cb == NULL) {
3302 return BAD_FUNC_ARG;
3303 }
3304
3305 pkcs7->rsaSignRawDigestCb = cb;
3306
3307 return 0;
3308 }
3309 #endif
3310
3311 /* returns size of signature put into out, negative on error */
wc_PKCS7_RsaVerify(PKCS7 * pkcs7,byte * sig,int sigSz,byte * hash,word32 hashSz)3312 static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
3313 byte* hash, word32 hashSz)
3314 {
3315 int ret = 0, i;
3316 word32 scratch = 0, verified = 0;
3317 #ifdef WOLFSSL_SMALL_STACK
3318 byte* digest;
3319 RsaKey* key;
3320 DecodedCert* dCert;
3321 #else
3322 byte digest[MAX_PKCS7_DIGEST_SZ];
3323 RsaKey key[1];
3324 DecodedCert stack_dCert;
3325 DecodedCert* dCert = &stack_dCert;
3326 #endif
3327
3328 if (pkcs7 == NULL || sig == NULL || hash == NULL) {
3329 return BAD_FUNC_ARG;
3330 }
3331
3332 #ifdef WOLFSSL_SMALL_STACK
3333 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
3334 DYNAMIC_TYPE_TMP_BUFFER);
3335 if (digest == NULL)
3336 return MEMORY_E;
3337
3338 key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3339 if (key == NULL) {
3340 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3341 return MEMORY_E;
3342 }
3343
3344 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
3345 DYNAMIC_TYPE_DCERT);
3346 if (dCert == NULL) {
3347 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3348 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3349 return MEMORY_E;
3350 }
3351 #endif
3352
3353 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
3354
3355 /* loop over certs received in certificates set, try to find one
3356 * that will validate signature */
3357 for (i = 0; i < MAX_PKCS7_CERTS; i++) {
3358
3359 verified = 0;
3360 scratch = 0;
3361
3362 if (pkcs7->certSz[i] == 0)
3363 continue;
3364
3365 ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
3366 if (ret != 0) {
3367 #ifdef WOLFSSL_SMALL_STACK
3368 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3369 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3370 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
3371 #endif
3372 return ret;
3373 }
3374
3375 InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
3376 /* not verifying, only using this to extract public key */
3377 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
3378 if (ret < 0) {
3379 WOLFSSL_MSG("ASN RSA cert parse error");
3380 FreeDecodedCert(dCert);
3381 wc_FreeRsaKey(key);
3382 continue;
3383 }
3384
3385 if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key,
3386 dCert->pubKeySize) < 0) {
3387 WOLFSSL_MSG("ASN RSA key decode error");
3388 FreeDecodedCert(dCert);
3389 wc_FreeRsaKey(key);
3390 continue;
3391 }
3392
3393 #ifdef WOLFSSL_ASYNC_CRYPT
3394 do {
3395 ret = wc_AsyncWait(ret, &key->asyncDev,
3396 WC_ASYNC_FLAG_CALL_AGAIN);
3397 #endif
3398 if (ret >= 0) {
3399 ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ,
3400 key);
3401 }
3402 #ifdef WOLFSSL_ASYNC_CRYPT
3403 } while (ret == WC_PENDING_E);
3404 #endif
3405 FreeDecodedCert(dCert);
3406 wc_FreeRsaKey(key);
3407
3408 if ((ret > 0) && (hashSz == (word32)ret)) {
3409 if (XMEMCMP(digest, hash, hashSz) == 0) {
3410 /* found signer that successfully verified signature */
3411 verified = 1;
3412 break;
3413 }
3414 }
3415 }
3416
3417 if (verified == 0) {
3418 ret = SIG_VERIFY_E;
3419 }
3420
3421 #ifdef WOLFSSL_SMALL_STACK
3422 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3423 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3424 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
3425 #endif
3426
3427 return ret;
3428 }
3429
3430 #endif /* NO_RSA */
3431
3432
3433 #ifdef HAVE_ECC
3434
3435 /* returns size of signature put into out, negative on error */
wc_PKCS7_EcdsaVerify(PKCS7 * pkcs7,byte * sig,int sigSz,byte * hash,word32 hashSz)3436 static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
3437 byte* hash, word32 hashSz)
3438 {
3439 int ret = 0, i;
3440 int res = 0;
3441 int verified = 0;
3442 #ifdef WOLFSSL_SMALL_STACK
3443 byte* digest;
3444 ecc_key* key;
3445 DecodedCert* dCert;
3446 #else
3447 byte digest[MAX_PKCS7_DIGEST_SZ];
3448 ecc_key key[1];
3449 DecodedCert stack_dCert;
3450 DecodedCert* dCert = &stack_dCert;
3451 #endif
3452 word32 idx = 0;
3453
3454 if (pkcs7 == NULL || sig == NULL)
3455 return BAD_FUNC_ARG;
3456
3457 #ifdef WOLFSSL_SMALL_STACK
3458 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
3459 DYNAMIC_TYPE_TMP_BUFFER);
3460 if (digest == NULL)
3461 return MEMORY_E;
3462
3463 key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3464 if (key == NULL) {
3465 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3466 return MEMORY_E;
3467 }
3468
3469 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
3470 DYNAMIC_TYPE_DCERT);
3471 if (dCert == NULL) {
3472 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3473 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3474 return MEMORY_E;
3475 }
3476 #endif
3477
3478 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
3479
3480 /* loop over certs received in certificates set, try to find one
3481 * that will validate signature */
3482 for (i = 0; i < MAX_PKCS7_CERTS; i++) {
3483
3484 verified = 0;
3485
3486 if (pkcs7->certSz[i] == 0)
3487 continue;
3488
3489 ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId);
3490 if (ret != 0) {
3491 #ifdef WOLFSSL_SMALL_STACK
3492 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3493 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3494 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
3495 #endif
3496 return ret;
3497 }
3498
3499 InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
3500 /* not verifying, only using this to extract public key */
3501 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
3502 if (ret < 0) {
3503 WOLFSSL_MSG("ASN ECC cert parse error");
3504 FreeDecodedCert(dCert);
3505 wc_ecc_free(key);
3506 continue;
3507 }
3508
3509 if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key,
3510 pkcs7->publicKeySz) < 0) {
3511 WOLFSSL_MSG("ASN ECC key decode error");
3512 FreeDecodedCert(dCert);
3513 wc_ecc_free(key);
3514 continue;
3515 }
3516
3517 #ifdef WOLFSSL_ASYNC_CRYPT
3518 do {
3519 ret = wc_AsyncWait(ret, &key->asyncDev,
3520 WC_ASYNC_FLAG_CALL_AGAIN);
3521 #endif
3522 if (ret >= 0) {
3523 ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key);
3524 }
3525 #ifdef WOLFSSL_ASYNC_CRYPT
3526 } while (ret == WC_PENDING_E);
3527 #endif
3528
3529 FreeDecodedCert(dCert);
3530 wc_ecc_free(key);
3531
3532 if (ret == 0 && res == 1) {
3533 /* found signer that successfully verified signature */
3534 verified = 1;
3535 break;
3536 }
3537 }
3538
3539 if (verified == 0) {
3540 ret = SIG_VERIFY_E;
3541 }
3542
3543 #ifdef WOLFSSL_SMALL_STACK
3544 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3545 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3546 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
3547 #endif
3548
3549 return ret;
3550 }
3551
3552 #endif /* HAVE_ECC */
3553
3554
3555 /* build SignedData digest, both in PKCS#7 DigestInfo format and
3556 * as plain digest for CMS.
3557 *
3558 * pkcs7 - pointer to initialized PKCS7 struct
3559 * signedAttrib - signed attributes
3560 * signedAttribSz - size of signedAttrib, octets
3561 * pkcs7Digest - [OUT] PKCS#7 DigestInfo
3562 * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest
3563 * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest
3564 * plainDigestSz - [OUT] size of digest at plainDigest
3565 *
3566 * returns 0 on success, negative on error */
wc_PKCS7_BuildSignedDataDigest(PKCS7 * pkcs7,byte * signedAttrib,word32 signedAttribSz,byte * pkcs7Digest,word32 * pkcs7DigestSz,byte ** plainDigest,word32 * plainDigestSz,const byte * hashBuf,word32 hashBufSz)3567 static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib,
3568 word32 signedAttribSz, byte* pkcs7Digest,
3569 word32* pkcs7DigestSz, byte** plainDigest,
3570 word32* plainDigestSz,
3571 const byte* hashBuf, word32 hashBufSz)
3572 {
3573 int ret = 0, digIdx = 0;
3574 word32 attribSetSz = 0, hashSz = 0;
3575 byte attribSet[MAX_SET_SZ];
3576 byte digest[WC_MAX_DIGEST_SIZE];
3577 byte digestInfoSeq[MAX_SEQ_SZ];
3578 byte digestStr[MAX_OCTET_STR_SZ];
3579 byte algoId[MAX_ALGO_SZ];
3580 word32 digestInfoSeqSz, digestStrSz, algoIdSz;
3581 #ifdef WOLFSSL_SMALL_STACK
3582 byte* digestInfo;
3583 #else
3584 byte digestInfo[MAX_PKCS7_DIGEST_SZ];
3585 #endif
3586
3587 wc_HashAlg hash;
3588 enum wc_HashType hashType;
3589
3590 /* check arguments */
3591 if (pkcs7 == NULL || pkcs7Digest == NULL ||
3592 pkcs7DigestSz == NULL || plainDigest == NULL) {
3593 return BAD_FUNC_ARG;
3594 }
3595
3596 hashType = wc_OidGetHash(pkcs7->hashOID);
3597 ret = wc_HashGetDigestSize(hashType);
3598 if (ret < 0)
3599 return ret;
3600 hashSz = ret;
3601
3602 if (signedAttribSz > 0) {
3603 if (signedAttrib == NULL)
3604 return BAD_FUNC_ARG;
3605 }
3606 else {
3607 if (hashBuf && hashBufSz > 0) {
3608 if (hashSz != hashBufSz)
3609 return BAD_FUNC_ARG;
3610 }
3611 else if (pkcs7->content == NULL)
3612 return BAD_FUNC_ARG;
3613 }
3614
3615 #ifdef WOLFSSL_SMALL_STACK
3616 digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
3617 DYNAMIC_TYPE_TMP_BUFFER);
3618 if (digestInfo == NULL)
3619 return MEMORY_E;
3620 #endif
3621
3622 XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz);
3623 XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE);
3624 XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ);
3625
3626
3627 /* calculate digest */
3628 if (hashBuf && hashBufSz > 0 && signedAttribSz == 0) {
3629 XMEMCPY(digest, hashBuf, hashBufSz);
3630 }
3631 else {
3632 ret = wc_HashInit(&hash, hashType);
3633 if (ret < 0) {
3634 #ifdef WOLFSSL_SMALL_STACK
3635 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3636 #endif
3637 return ret;
3638 }
3639
3640 if (signedAttribSz > 0) {
3641 attribSetSz = SetSet(signedAttribSz, attribSet);
3642
3643 /* calculate digest */
3644 ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz);
3645 if (ret == 0)
3646 ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz);
3647 if (ret == 0)
3648 ret = wc_HashFinal(&hash, hashType, digest);
3649 } else {
3650 ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz);
3651 if (ret == 0)
3652 ret = wc_HashFinal(&hash, hashType, digest);
3653 }
3654
3655 wc_HashFree(&hash, hashType);
3656 if (ret < 0) {
3657 #ifdef WOLFSSL_SMALL_STACK
3658 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3659 #endif
3660 return ret;
3661 }
3662 }
3663
3664 /* Set algoID, with NULL attributes */
3665 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
3666
3667 digestStrSz = SetOctetString(hashSz, digestStr);
3668 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
3669 digestInfoSeq);
3670
3671 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
3672 digIdx += digestInfoSeqSz;
3673 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
3674 digIdx += algoIdSz;
3675 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
3676 digIdx += digestStrSz;
3677 XMEMCPY(digestInfo + digIdx, digest, hashSz);
3678 digIdx += hashSz;
3679
3680 XMEMCPY(pkcs7Digest, digestInfo, digIdx);
3681 *pkcs7DigestSz = digIdx;
3682
3683 /* set plain digest pointer */
3684 *plainDigest = pkcs7Digest + digIdx - hashSz;
3685 *plainDigestSz = hashSz;
3686
3687 #ifdef WOLFSSL_SMALL_STACK
3688 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3689 #endif
3690 return 0;
3691 }
3692
3693
3694 /* Verifies CMS/PKCS7 SignedData content digest matches that which is
3695 * included in the messageDigest signed attribute. Only called when
3696 * signed attributes are present, otherwise original signature verification
3697 * is done over content.
3698 *
3699 * pkcs7 - pointer to initialized PKCS7 struct
3700 * hashBuf - pointer to user-provided hash buffer, used with
3701 * wc_PKCS7_VerifySignedData_ex()
3702 * hashBufSz - size of hashBuf, octets
3703 *
3704 * return 0 on success, negative on error */
wc_PKCS7_VerifyContentMessageDigest(PKCS7 * pkcs7,const byte * hashBuf,word32 hashSz)3705 static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7,
3706 const byte* hashBuf,
3707 word32 hashSz)
3708 {
3709 int ret = 0, digestSz = 0, innerAttribSz = 0;
3710 word32 idx = 0;
3711 byte* digestBuf = NULL;
3712 #ifdef WOLFSSL_SMALL_STACK
3713 byte* digest = NULL;
3714 #else
3715 byte digest[MAX_PKCS7_DIGEST_SZ];
3716 #endif
3717 PKCS7DecodedAttrib* attrib;
3718 enum wc_HashType hashType;
3719
3720 /* messageDigest OID (1.2.840.113549.1.9.4) */
3721 const byte mdOid[] =
3722 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 };
3723
3724 if (pkcs7 == NULL)
3725 return BAD_FUNC_ARG;
3726
3727 if ((pkcs7->content == NULL || pkcs7->contentSz == 0) &&
3728 (hashBuf == NULL || hashSz == 0)) {
3729 WOLFSSL_MSG("SignedData bundle has no content or hash to verify");
3730 return BAD_FUNC_ARG;
3731 }
3732
3733 /* lookup messageDigest attribute */
3734 attrib = findAttrib(pkcs7, mdOid, sizeof(mdOid));
3735 if (attrib == NULL) {
3736 WOLFSSL_MSG("messageDigest attribute not in bundle, must be when "
3737 "signed attribs are present");
3738 return ASN_PARSE_E;
3739 }
3740
3741 /* advance past attrib->value ASN.1 header and length */
3742 if (attrib->value == NULL || attrib->valueSz == 0)
3743 return ASN_PARSE_E;
3744
3745 if (attrib->value[idx++] != ASN_OCTET_STRING)
3746 return ASN_PARSE_E;
3747
3748 if (GetLength(attrib->value, &idx, &innerAttribSz, attrib->valueSz) < 0)
3749 return ASN_PARSE_E;
3750
3751 /* get hash type and size */
3752 hashType = wc_OidGetHash(pkcs7->hashOID);
3753 if (hashType == WC_HASH_TYPE_NONE) {
3754 WOLFSSL_MSG("Error getting hash type for PKCS7 content verification");
3755 return BAD_FUNC_ARG;
3756 }
3757
3758 /* build content hash if needed, or use existing hash value */
3759 if (hashBuf == NULL) {
3760
3761 #ifdef WOLFSSL_SMALL_STACK
3762 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
3763 DYNAMIC_TYPE_TMP_BUFFER);
3764 if (digest == NULL)
3765 return MEMORY_E;
3766 #endif
3767 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
3768
3769 ret = wc_Hash(hashType, pkcs7->content, pkcs7->contentSz, digest,
3770 MAX_PKCS7_DIGEST_SZ);
3771 if (ret < 0) {
3772 WOLFSSL_MSG("Error hashing PKCS7 content for verification");
3773 #ifdef WOLFSSL_SMALL_STACK
3774 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3775 #endif
3776 return ret;
3777 }
3778
3779 digestBuf = digest;
3780 digestSz = wc_HashGetDigestSize(hashType);
3781 if (digestSz < 0) {
3782 WOLFSSL_MSG("Invalid hash type");
3783 #ifdef WOLFSSL_SMALL_STACK
3784 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3785 #endif
3786 return digestSz;
3787 }
3788 } else {
3789
3790 /* user passed in pre-computed hash */
3791 digestBuf = (byte*)hashBuf;
3792 digestSz = (int)hashSz;
3793 }
3794
3795 /* compare generated to hash in messageDigest attribute */
3796 if ((innerAttribSz != digestSz) ||
3797 (XMEMCMP(attrib->value + idx, digestBuf, (word32)digestSz) != 0)) {
3798 WOLFSSL_MSG("Content digest does not match messageDigest attrib value");
3799 #ifdef WOLFSSL_SMALL_STACK
3800 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3801 #endif
3802 return SIG_VERIFY_E;
3803 }
3804
3805 if (hashBuf == NULL) {
3806 #ifdef WOLFSSL_SMALL_STACK
3807 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3808 #endif
3809 }
3810
3811 return 0;
3812 }
3813
3814
3815 /* verifies SignedData signature, over either PKCS#7 DigestInfo or
3816 * content digest.
3817 *
3818 * pkcs7 - pointer to initialized PKCS7 struct
3819 * sig - signature to verify
3820 * sigSz - size of sig
3821 * signedAttrib - signed attributes, or null if empty
3822 * signedAttribSz - size of signedAttributes
3823 *
3824 * return 0 on success, negative on error */
wc_PKCS7_SignedDataVerifySignature(PKCS7 * pkcs7,byte * sig,word32 sigSz,byte * signedAttrib,word32 signedAttribSz,const byte * hashBuf,word32 hashSz)3825 static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig,
3826 word32 sigSz, byte* signedAttrib,
3827 word32 signedAttribSz,
3828 const byte* hashBuf, word32 hashSz)
3829 {
3830 int ret = 0;
3831 word32 plainDigestSz = 0, pkcs7DigestSz;
3832 byte* plainDigest = NULL; /* offset into pkcs7Digest */
3833 #ifdef WOLFSSL_SMALL_STACK
3834 byte* pkcs7Digest;
3835 #else
3836 byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ];
3837 #endif
3838
3839 if (pkcs7 == NULL)
3840 return BAD_FUNC_ARG;
3841
3842 /* allocate space to build hash */
3843 pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ;
3844 #ifdef WOLFSSL_SMALL_STACK
3845 pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap,
3846 DYNAMIC_TYPE_TMP_BUFFER);
3847 if (pkcs7Digest == NULL)
3848 return MEMORY_E;
3849 #endif
3850
3851 XMEMSET(pkcs7Digest, 0, pkcs7DigestSz);
3852
3853 /* verify signed attrib digest matches that of content */
3854 if (signedAttrib != NULL) {
3855 ret = wc_PKCS7_VerifyContentMessageDigest(pkcs7, hashBuf, hashSz);
3856 if (ret != 0) {
3857 #ifdef WOLFSSL_SMALL_STACK
3858 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3859 #endif
3860 return ret;
3861 }
3862 }
3863
3864 /* build hash to verify against */
3865 ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib,
3866 signedAttribSz, pkcs7Digest,
3867 &pkcs7DigestSz, &plainDigest,
3868 &plainDigestSz, hashBuf, hashSz);
3869 if (ret < 0) {
3870 #ifdef WOLFSSL_SMALL_STACK
3871 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3872 #endif
3873 return ret;
3874 }
3875
3876 /* If no certificates are available then store the signature and hash for
3877 * user to verify. Make sure that different return value than success is
3878 * returned because the signature was not verified here. */
3879 if (ret == 0) {
3880 byte haveCert = 0;
3881 int i;
3882
3883 for (i = 0; i < MAX_PKCS7_CERTS; i++) {
3884 if (pkcs7->certSz[i] == 0)
3885 continue;
3886 haveCert = 1;
3887 }
3888
3889 if (!haveCert) {
3890 WOLFSSL_MSG("No certificates in bundle to verify signature");
3891
3892 /* store signature */
3893 XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE);
3894 pkcs7->signature = NULL;
3895 pkcs7->signatureSz = 0;
3896 pkcs7->signature = (byte*)XMALLOC(sigSz, pkcs7->heap,
3897 DYNAMIC_TYPE_SIGNATURE);
3898 if (pkcs7->signature == NULL) {
3899 #ifdef WOLFSSL_SMALL_STACK
3900 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3901 #endif
3902 return MEMORY_E;
3903 }
3904 XMEMCPY(pkcs7->signature, sig, sigSz);
3905 pkcs7->signatureSz = sigSz;
3906
3907 /* store plain digest (CMS and ECC) */
3908 XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
3909 pkcs7->plainDigest = NULL;
3910 pkcs7->plainDigestSz = 0;
3911 pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap,
3912 DYNAMIC_TYPE_DIGEST);
3913 if (pkcs7->plainDigest == NULL) {
3914 #ifdef WOLFSSL_SMALL_STACK
3915 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3916 #endif
3917 return MEMORY_E;
3918 }
3919 XMEMCPY(pkcs7->plainDigest, plainDigest, plainDigestSz);
3920 pkcs7->plainDigestSz = plainDigestSz;
3921
3922 /* store pkcs7 digest (default RSA) */
3923 XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
3924 pkcs7->pkcs7Digest = NULL;
3925 pkcs7->pkcs7DigestSz = 0;
3926 pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap,
3927 DYNAMIC_TYPE_DIGEST);
3928 if (pkcs7->pkcs7Digest == NULL) {
3929 #ifdef WOLFSSL_SMALL_STACK
3930 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3931 #endif
3932 return MEMORY_E;
3933 }
3934 XMEMCPY(pkcs7->pkcs7Digest, pkcs7Digest, pkcs7DigestSz);
3935 pkcs7->pkcs7DigestSz = pkcs7DigestSz;
3936
3937 #ifdef WOLFSSL_SMALL_STACK
3938 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3939 #endif
3940 return PKCS7_SIGNEEDS_CHECK;
3941 }
3942 }
3943
3944
3945
3946 switch (pkcs7->publicKeyOID) {
3947
3948 #ifndef NO_RSA
3949 case RSAk:
3950 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest,
3951 pkcs7DigestSz);
3952 if (ret < 0) {
3953 WOLFSSL_MSG("PKCS#7 verification failed, trying CMS");
3954 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest,
3955 plainDigestSz);
3956 }
3957 break;
3958 #endif
3959
3960 #ifdef HAVE_ECC
3961 case ECDSAk:
3962 ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest,
3963 plainDigestSz);
3964 break;
3965 #endif
3966
3967 default:
3968 WOLFSSL_MSG("Unsupported public key type");
3969 ret = BAD_FUNC_ARG;
3970 }
3971
3972 #ifdef WOLFSSL_SMALL_STACK
3973 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
3974 #endif
3975 return ret;
3976 }
3977
3978
3979 /* set correct public key OID based on signature OID, stores in
3980 * pkcs7->publicKeyOID and returns same value */
wc_PKCS7_SetPublicKeyOID(PKCS7 * pkcs7,int sigOID)3981 static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID)
3982 {
3983 if (pkcs7 == NULL)
3984 return BAD_FUNC_ARG;
3985
3986 pkcs7->publicKeyOID = 0;
3987
3988 switch (sigOID) {
3989
3990 #ifndef NO_RSA
3991 /* RSA signature types */
3992 case CTC_MD2wRSA:
3993 case CTC_MD5wRSA:
3994 case CTC_SHAwRSA:
3995 case CTC_SHA224wRSA:
3996 case CTC_SHA256wRSA:
3997 case CTC_SHA384wRSA:
3998 case CTC_SHA512wRSA:
3999 case CTC_SHA3_224wRSA:
4000 case CTC_SHA3_256wRSA:
4001 case CTC_SHA3_384wRSA:
4002 case CTC_SHA3_512wRSA:
4003 pkcs7->publicKeyOID = RSAk;
4004 break;
4005
4006 /* if sigOID is already RSAk */
4007 case RSAk:
4008 pkcs7->publicKeyOID = sigOID;
4009 break;
4010 #endif
4011
4012 #ifndef NO_DSA
4013 /* DSA signature types */
4014 case CTC_SHAwDSA:
4015 pkcs7->publicKeyOID = DSAk;
4016 break;
4017
4018 /* if sigOID is already DSAk */
4019 case DSAk:
4020 pkcs7->publicKeyOID = sigOID;
4021 break;
4022 #endif
4023
4024 #ifdef HAVE_ECC
4025 /* ECDSA signature types */
4026 case CTC_SHAwECDSA:
4027 case CTC_SHA224wECDSA:
4028 case CTC_SHA256wECDSA:
4029 case CTC_SHA384wECDSA:
4030 case CTC_SHA512wECDSA:
4031 case CTC_SHA3_224wECDSA:
4032 case CTC_SHA3_256wECDSA:
4033 case CTC_SHA3_384wECDSA:
4034 case CTC_SHA3_512wECDSA:
4035 pkcs7->publicKeyOID = ECDSAk;
4036 break;
4037
4038 /* if sigOID is already ECDSAk */
4039 case ECDSAk:
4040 pkcs7->publicKeyOID = sigOID;
4041 break;
4042 #endif
4043
4044 default:
4045 WOLFSSL_MSG("Unsupported public key algorithm");
4046 return ASN_SIG_KEY_E;
4047 }
4048
4049 return pkcs7->publicKeyOID;
4050 }
4051
4052
4053 /* Parses through the attributes and adds them to the PKCS7 structure
4054 * Creates dynamic attribute structures that are free'd with calling
4055 * wc_PKCS7_Free()
4056 *
4057 * NOTE: An attribute has the ASN1 format of
4058 ** Sequence
4059 ****** Object ID
4060 ****** Set
4061 ********** {PrintableString, UTCTime, OCTET STRING ...}
4062 *
4063 * pkcs7 the PKCS7 structure to put the parsed attributes into
4064 * in buffer holding all attributes
4065 * inSz size of in buffer
4066 *
4067 * returns the number of attributes parsed on success
4068 */
wc_PKCS7_ParseAttribs(PKCS7 * pkcs7,byte * in,int inSz)4069 static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz)
4070 {
4071 int found = 0;
4072 word32 idx = 0;
4073 word32 oid;
4074
4075 if (pkcs7 == NULL || in == NULL || inSz < 0) {
4076 return BAD_FUNC_ARG;
4077 }
4078
4079 while (idx < (word32)inSz) {
4080 int length = 0;
4081 int oidIdx;
4082 PKCS7DecodedAttrib* attrib;
4083
4084 if (GetSequence(in, &idx, &length, inSz) < 0)
4085 return ASN_PARSE_E;
4086
4087 attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
4088 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4089 if (attrib == NULL) {
4090 return MEMORY_E;
4091 }
4092 XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
4093
4094 oidIdx = idx;
4095 if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz)
4096 < 0) {
4097 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4098 return ASN_PARSE_E;
4099 }
4100 attrib->oidSz = idx - oidIdx;
4101 attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
4102 DYNAMIC_TYPE_PKCS7);
4103 if (attrib->oid == NULL) {
4104 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4105 return MEMORY_E;
4106 }
4107 XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz);
4108
4109 /* Get Set that contains the printable string value */
4110 if (GetSet(in, &idx, &length, inSz) < 0) {
4111 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4112 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4113 return ASN_PARSE_E;
4114 }
4115
4116 if ((inSz - idx) < (word32)length) {
4117 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4118 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4119 return ASN_PARSE_E;
4120 }
4121
4122 attrib->valueSz = (word32)length;
4123 attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
4124 DYNAMIC_TYPE_PKCS7);
4125 if (attrib->value == NULL) {
4126 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4127 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4128 return MEMORY_E;
4129 }
4130 XMEMCPY(attrib->value, in + idx, attrib->valueSz);
4131 idx += length;
4132
4133 /* store attribute in linked list */
4134 if (pkcs7->decodedAttrib != NULL) {
4135 attrib->next = pkcs7->decodedAttrib;
4136 pkcs7->decodedAttrib = attrib;
4137 } else {
4138 pkcs7->decodedAttrib = attrib;
4139 }
4140 found++;
4141 }
4142
4143 return found;
4144 }
4145
4146
4147 /* option to turn off support for degenerate cases
4148 * flag 0 turns off support
4149 * flag 1 turns on support
4150 *
4151 * by default support for SignedData degenerate cases is on
4152 */
wc_PKCS7_AllowDegenerate(PKCS7 * pkcs7,word16 flag)4153 void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag)
4154 {
4155 if (pkcs7) {
4156 if (flag) { /* flag of 1 turns on support for degenerate */
4157 pkcs7->noDegenerate = 0;
4158 }
4159 else { /* flag of 0 turns off support */
4160 pkcs7->noDegenerate = 1;
4161 }
4162 }
4163 }
4164
4165 /* Parses through a signerInfo set. Reads buffer "in" from "idxIn" to "idxIn" +
4166 * length treating the current "idxIn" plus the length of set as max possible
4167 * index.
4168 *
4169 * In the case that signed attributes are found "signedAttrib" gets set to point
4170 * at their location in the buffer "in". Also in this case signedAttribSz gets
4171 * set to the size of the signedAttrib buffer.
4172 *
4173 * returns 0 on success
4174 */
wc_PKCS7_ParseSignerInfo(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idxIn,int degenerate,byte ** signedAttrib,int * signedAttribSz)4175 static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz,
4176 word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz)
4177 {
4178 int ret = 0;
4179 int length;
4180 int version;
4181 word32 sigOID = 0, hashOID = 0;
4182 word32 idx = *idxIn, localIdx;
4183 byte tag;
4184
4185 WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo");
4186 /* require a signer if degenerate case not allowed */
4187 if (inSz == 0 && pkcs7->noDegenerate == 1) {
4188 WOLFSSL_MSG("Set to not allow degenerate cases");
4189 return PKCS7_NO_SIGNER_E;
4190 }
4191
4192 if (inSz == 0 && degenerate == 0) {
4193 WOLFSSL_MSG("PKCS7 signers expected");
4194 return PKCS7_NO_SIGNER_E;
4195 }
4196
4197 /* not a degenerate case and there is elements in the set */
4198 if (inSz > 0 && degenerate == 0) {
4199 ret = wc_PKCS7_SignerInfoNew(pkcs7);
4200
4201 /* Get the sequence of the first signerInfo */
4202 if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
4203 ret = ASN_PARSE_E;
4204
4205 /* Get the version */
4206 if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0)
4207 ret = ASN_PARSE_E;
4208
4209 if (ret == 0) {
4210 pkcs7->signerInfo->version = version;
4211 }
4212
4213 if (ret == 0 && version == 1) {
4214 /* Get the sequence of IssuerAndSerialNumber */
4215 if (GetSequence(in, &idx, &length, inSz) < 0)
4216 ret = ASN_PARSE_E;
4217
4218 if (ret == 0) {
4219 ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length);
4220 idx += length;
4221 }
4222
4223 } else if (ret == 0 && version == 3) {
4224 /* Get the sequence of SubjectKeyIdentifier */
4225 if (idx + 1 > inSz)
4226 ret = BUFFER_E;
4227
4228 localIdx = idx;
4229 if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
4230 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
4231 idx++;
4232
4233 if (GetLength(in, &idx, &length, inSz) <= 0)
4234 ret = ASN_PARSE_E;
4235
4236 if (ret == 0 && idx + 1 > inSz)
4237 ret = BUFFER_E;
4238
4239 if (ret == 0 && GetASNTag(in, &idx, &tag, inSz) < 0)
4240 ret = ASN_PARSE_E;
4241
4242 if (ret == 0 && tag != ASN_OCTET_STRING)
4243 ret = ASN_PARSE_E;
4244
4245 if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
4246 ret = ASN_PARSE_E;
4247 }
4248 else {
4249 /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version
4250 * 3 try to get issuerAndSerial */
4251 localIdx = idx;
4252 if (GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
4253 tag == ASN_CONTEXT_SPECIFIC) {
4254 idx++;
4255 if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
4256 ret = ASN_PARSE_E;
4257 }
4258 else {
4259 if (pkcs7->version != 3) {
4260 WOLFSSL_MSG("Unexpected signer info found with version");
4261 ret = ASN_PARSE_E;
4262 }
4263
4264 if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
4265 ret = ASN_PARSE_E;
4266 }
4267 }
4268
4269 if (ret == 0) {
4270 if (length > (int)inSz - (int)idx)
4271 ret = BUFFER_E;
4272 }
4273
4274 if (ret == 0) {
4275 ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length);
4276 idx += length;
4277 }
4278
4279 } else {
4280 WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3");
4281 ret = ASN_VERSION_E;
4282 }
4283
4284 /* Get the sequence of digestAlgorithm */
4285 if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, inSz) < 0) {
4286 ret = ASN_PARSE_E;
4287 }
4288 pkcs7->hashOID = (int)hashOID;
4289
4290 /* Get the IMPLICIT[0] SET OF signedAttributes */
4291 localIdx = idx;
4292 if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
4293 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
4294 idx++;
4295
4296 if (GetLength(in, &idx, &length, inSz) < 0)
4297 ret = ASN_PARSE_E;
4298
4299 /* save pointer and length */
4300 *signedAttrib = &in[idx];
4301 *signedAttribSz = length;
4302
4303 if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, *signedAttrib,
4304 *signedAttribSz) < 0) {
4305 WOLFSSL_MSG("Error parsing signed attributes");
4306 ret = ASN_PARSE_E;
4307 }
4308
4309 idx += length;
4310 }
4311
4312 /* Get digestEncryptionAlgorithm - key type or signature type */
4313 if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidIgnoreType, inSz) < 0) {
4314 ret = ASN_PARSE_E;
4315 }
4316
4317 /* store public key type based on digestEncryptionAlgorithm */
4318 if (ret == 0) {
4319 ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID);
4320 if (ret < 0) {
4321 WOLFSSL_MSG("Failed to set public key OID from signature");
4322 }
4323 else {
4324 /* if previous return was positive then was success */
4325 ret = 0;
4326 }
4327 }
4328 }
4329
4330 /* update index on success */
4331 if (ret == 0) {
4332 *idxIn = idx;
4333 }
4334
4335 return ret;
4336 }
4337
4338
4339 /* Finds the certificates in the message and saves it. By default allows
4340 * degenerate cases which can have no signer.
4341 *
4342 * By default expects type SIGNED_DATA (SignedData) which can have any number of
4343 * elements in signerInfos collection, including zero. (RFC2315 section 9.1)
4344 * When adding support for the case of SignedAndEnvelopedData content types a
4345 * signer is required. In this case the PKCS7 flag noDegenerate could be set.
4346 */
PKCS7_VerifySignedData(PKCS7 * pkcs7,const byte * hashBuf,word32 hashSz,byte * in,word32 inSz,byte * in2,word32 in2Sz)4347 static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
4348 word32 hashSz, byte* in, word32 inSz,
4349 byte* in2, word32 in2Sz)
4350 {
4351 word32 idx, maxIdx = inSz, outerContentType, contentTypeSz = 0, totalSz = 0;
4352 int length = 0, version = 0, ret = 0;
4353 byte* content = NULL;
4354 byte* contentDynamic = NULL;
4355 byte* sig = NULL;
4356 byte* cert = NULL;
4357 byte* signedAttrib = NULL;
4358 byte* contentType = NULL;
4359 int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
4360 word32 localIdx, start;
4361 byte degenerate = 0;
4362 byte detached = 0;
4363 byte tag = 0;
4364 #ifdef ASN_BER_TO_DER
4365 byte* der;
4366 #endif
4367 int multiPart = 0, keepContent;
4368 int contentLen = 0;
4369
4370 byte* pkiMsg = in;
4371 word32 pkiMsgSz = inSz;
4372 #ifndef NO_PKCS7_STREAM
4373 word32 stateIdx = 0;
4374 #endif
4375
4376 byte* pkiMsg2 = in2;
4377 word32 pkiMsg2Sz = in2Sz;
4378
4379 if (pkcs7 == NULL)
4380 return BAD_FUNC_ARG;
4381
4382 #ifndef NO_PKCS7_STREAM
4383 /* allow for 0 size inputs with stream mode */
4384 if (pkiMsg == NULL && pkiMsgSz > 0)
4385 return BAD_FUNC_ARG;
4386
4387 #else
4388 if (pkiMsg == NULL || pkiMsgSz == 0)
4389 return BAD_FUNC_ARG;
4390 #endif
4391
4392 if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) {
4393 return BAD_FUNC_ARG;
4394 }
4395 idx = 0;
4396
4397 #ifdef ASN_BER_TO_DER
4398 if (pkcs7->derSz > 0 && pkcs7->der) {
4399 pkiMsg = in = pkcs7->der;
4400 }
4401 #endif
4402
4403 #ifndef NO_PKCS7_STREAM
4404 if (pkcs7->stream == NULL) {
4405 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
4406 return ret;
4407 }
4408 }
4409 #endif
4410
4411 switch (pkcs7->state) {
4412 case WC_PKCS7_START:
4413 #ifndef NO_PKCS7_STREAM
4414 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
4415 MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ +
4416 ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ,
4417 &pkiMsg, &idx)) != 0) {
4418 break;
4419 }
4420
4421 if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
4422 break;
4423 }
4424 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
4425 inSz;
4426 #endif
4427
4428 /* determine total message size */
4429 totalSz = pkiMsgSz;
4430 if (pkiMsg2 && pkiMsg2Sz > 0) {
4431 totalSz += pkiMsg2Sz + pkcs7->contentSz;
4432 }
4433
4434 /* Get the contentInfo sequence */
4435 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz,
4436 NO_USER_CHECK) < 0)
4437 ret = ASN_PARSE_E;
4438
4439 if (ret == 0 && length == 0 && pkiMsg[idx-1] == ASN_INDEF_LENGTH) {
4440 #ifdef ASN_BER_TO_DER
4441 word32 len = 0;
4442
4443 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
4444 if (ret != LENGTH_ONLY_E)
4445 return ret;
4446 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4447 if (pkcs7->der == NULL)
4448 return MEMORY_E;
4449 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
4450 if (ret < 0)
4451 return ret;
4452
4453 pkiMsg = in = pkcs7->der;
4454 pkiMsgSz = pkcs7->derSz = len;
4455 idx = 0;
4456 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
4457 NO_USER_CHECK) < 0)
4458 return ASN_PARSE_E;
4459
4460 #ifndef NO_PKCS7_STREAM
4461 if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
4462 break;
4463 }
4464 #endif
4465 #else
4466 ret = BER_INDEF_E;
4467 #endif
4468 }
4469
4470 /* Get the contentInfo contentType */
4471 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType,
4472 pkiMsgSz) < 0)
4473 ret = ASN_PARSE_E;
4474
4475 if (ret == 0 && outerContentType != SIGNED_DATA) {
4476 WOLFSSL_MSG("PKCS#7 input not of type SignedData");
4477 ret = PKCS7_OID_E;
4478 }
4479
4480 /* get the ContentInfo content */
4481 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, totalSz) != 0)
4482 ret = ASN_PARSE_E;
4483
4484 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
4485 ret = ASN_PARSE_E;
4486
4487 if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz,
4488 NO_USER_CHECK) < 0)
4489 ret = ASN_PARSE_E;
4490
4491 /* Get the signedData sequence */
4492 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz,
4493 NO_USER_CHECK) < 0)
4494 ret = ASN_PARSE_E;
4495
4496 /* Get the version */
4497 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
4498 ret = ASN_PARSE_E;
4499
4500
4501 /* version 1 follows RFC 2315 */
4502 /* version 3 follows RFC 4108 */
4503 if (ret == 0 && (version != 1 && version != 3)) {
4504 WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3");
4505 ret = ASN_VERSION_E;
4506 }
4507 pkcs7->version = version;
4508
4509 /* Get the set of DigestAlgorithmIdentifiers */
4510 if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
4511 ret = ASN_PARSE_E;
4512
4513 /* Skip the set. */
4514 idx += length;
4515 degenerate = (length == 0) ? 1 : 0;
4516 if (pkcs7->noDegenerate == 1 && degenerate == 1) {
4517 ret = PKCS7_NO_SIGNER_E;
4518 }
4519
4520 if (ret != 0)
4521 break;
4522
4523 #ifndef NO_PKCS7_STREAM
4524 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
4525 break;
4526 }
4527 if (pkiMsg2 && pkiMsg2Sz > 0) {
4528 pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz;
4529 }
4530 wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0);
4531 #endif
4532
4533 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2);
4534 FALL_THROUGH;
4535
4536 case WC_PKCS7_VERIFY_STAGE2:
4537 #ifndef NO_PKCS7_STREAM
4538 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
4539 MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ
4540 + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
4541 break;
4542 }
4543
4544 wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0);
4545 if (pkcs7->stream->length > 0)
4546 pkiMsgSz = pkcs7->stream->length;
4547 #ifdef ASN_BER_TO_DER
4548 else if (pkcs7->der)
4549 pkiMsgSz = pkcs7->derSz;
4550 #endif
4551 else
4552 pkiMsgSz = inSz;
4553
4554 #endif
4555 /* Get the inner ContentInfo sequence */
4556 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
4557 NO_USER_CHECK) < 0)
4558 ret = ASN_PARSE_E;
4559
4560 /* Get the inner ContentInfo contentType */
4561 if (ret == 0) {
4562 int isIndef = 0;
4563 word32 tmpIdx = idx;
4564 if (length == 0 && pkiMsg[idx-1] == ASN_INDEF_LENGTH) {
4565 isIndef = 1;
4566 }
4567 if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) == 0) {
4568 contentType = pkiMsg + tmpIdx;
4569 contentTypeSz = length + (idx - tmpIdx);
4570 idx += length;
4571 }
4572 else {
4573 ret = ASN_PARSE_E;
4574 }
4575 /* if indef, skip EOF */
4576 if (isIndef && pkiMsg[idx] == ASN_EOC && pkiMsg[idx+1] == 0) {
4577 idx += 2; /* skip EOF + zero byte */
4578 }
4579 }
4580
4581 if (ret != 0)
4582 break;
4583
4584 /* Check for content info, it could be omitted when degenerate */
4585 localIdx = idx;
4586 ret = 0;
4587 if (localIdx + 1 > pkiMsgSz) {
4588 ret = BUFFER_E;
4589 break;
4590 }
4591
4592 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0)
4593 ret = ASN_PARSE_E;
4594
4595 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
4596 ret = ASN_PARSE_E;
4597
4598 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
4599 NO_USER_CHECK) <= 0)
4600 ret = ASN_PARSE_E;
4601
4602 if (localIdx >= pkiMsgSz) {
4603 ret = BUFFER_E;
4604 }
4605
4606 /* get length of content in the case that there is multiple parts */
4607 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
4608 ret = ASN_PARSE_E;
4609
4610 if (ret == 0 && tag == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) {
4611 multiPart = 1;
4612
4613 /* Get length of all OCTET_STRINGs. */
4614 if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz,
4615 NO_USER_CHECK) < 0)
4616 ret = ASN_PARSE_E;
4617
4618 /* Check whether there is one OCTET_STRING inside. */
4619 start = localIdx;
4620 if (localIdx >= pkiMsgSz) {
4621 ret = BUFFER_E;
4622 }
4623
4624 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz)
4625 != 0)
4626 ret = ASN_PARSE_E;
4627
4628 if (ret == 0 && tag != ASN_OCTET_STRING)
4629 ret = ASN_PARSE_E;
4630
4631 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length,
4632 pkiMsgSz, NO_USER_CHECK) < 0)
4633 ret = ASN_PARSE_E;
4634
4635 if (ret == 0) {
4636 /* Use single OCTET_STRING directly, or reset length. */
4637 if (localIdx - start + length == (word32)contentLen) {
4638 multiPart = 0;
4639 } else {
4640 /* reset length to outer OCTET_STRING for bundle size
4641 * check below */
4642 length = contentLen;
4643 }
4644 localIdx = start;
4645 }
4646
4647 if (ret != 0) {
4648 /* failed ASN1 parsing during OCTET_STRING checks */
4649 break;
4650 }
4651 }
4652
4653 /* get length of content in case of single part */
4654 if (ret == 0 && !multiPart) {
4655 if (tag != ASN_OCTET_STRING)
4656 ret = ASN_PARSE_E;
4657
4658 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx,
4659 &length, pkiMsgSz, NO_USER_CHECK) < 0)
4660 ret = ASN_PARSE_E;
4661 }
4662
4663 /* update idx if successful */
4664 if (ret == 0) {
4665 /* support using header and footer without content */
4666 if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
4667 localIdx = 0;
4668
4669 } else if (pkiMsg2 == NULL && hashBuf == NULL) {
4670 /* header/footer not separate, check content length is
4671 * not larger than total bundle size */
4672 if ((localIdx + length) > pkiMsgSz) {
4673 WOLFSSL_MSG("Content length detected is larger than "
4674 "total bundle size");
4675 ret = BUFFER_E;
4676 break;
4677 }
4678 }
4679 idx = localIdx;
4680 }
4681 else {
4682
4683 /* If either pkcs7->content and pkcs7->contentSz are set
4684 * (detached signature where user has set content explicitly
4685 * into pkcs7->content/contentSz) OR pkcs7->hashBuf and
4686 * pkcs7->hashSz are set (user has pre-computed content
4687 * digest and passed in instead of content directly), try to
4688 * process as a detached signature */
4689 if (!degenerate &&
4690 ((pkcs7->content != NULL && pkcs7->contentSz != 0) ||
4691 (hashBuf != NULL && hashSz > 0)) ) {
4692 WOLFSSL_MSG("Trying to process as detached signature");
4693 detached = 1;
4694 }
4695
4696 if (!degenerate && !detached && ret != 0)
4697 break;
4698
4699 /* no content to read */
4700 length = 0;
4701 contentLen = 0;
4702
4703 pkiMsg2 = pkiMsg;
4704 pkiMsg2Sz = pkiMsgSz;
4705 }
4706
4707 #ifndef NO_PKCS7_STREAM
4708 /* save detached flag value */
4709 pkcs7->stream->detached = detached;
4710
4711 /* save contentType */
4712 pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap,
4713 DYNAMIC_TYPE_PKCS7);
4714 if (pkcs7->stream->nonce == NULL) {
4715 ret = MEMORY_E;
4716 break;
4717 }
4718 else {
4719 pkcs7->stream->nonceSz = contentTypeSz;
4720 XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz);
4721 }
4722
4723 /* content expected? */
4724 if ((ret == 0 && length > 0) &&
4725 !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) {
4726 pkcs7->stream->expected = length + ASN_TAG_SZ + MAX_LENGTH_SZ;
4727 }
4728 else {
4729 pkcs7->stream->expected = ASN_TAG_SZ + MAX_LENGTH_SZ;
4730 }
4731
4732 if (pkcs7->stream->expected > (pkcs7->stream->maxLen - idx)) {
4733 pkcs7->stream->expected = pkcs7->stream->maxLen - idx;
4734 }
4735
4736 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
4737 break;
4738 }
4739 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length);
4740
4741 /* content length is in multiple parts */
4742 if (multiPart) {
4743 pkcs7->stream->expected = contentLen + ASN_TAG_SZ;
4744 }
4745 pkcs7->stream->multi = multiPart;
4746
4747 #endif
4748 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3);
4749 FALL_THROUGH;
4750
4751 case WC_PKCS7_VERIFY_STAGE3:
4752 #ifndef NO_PKCS7_STREAM
4753 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
4754 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
4755 break;
4756 }
4757 #ifdef ASN_BER_TO_DER
4758 if (pkcs7->derSz != 0)
4759 pkiMsgSz = pkcs7->derSz;
4760 else
4761 #endif
4762 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
4763 inSz;
4764 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length);
4765
4766 if (pkcs7->stream->length > 0) {
4767 localIdx = 0;
4768 }
4769 multiPart = pkcs7->stream->multi;
4770 detached = pkcs7->stream->detached;
4771 maxIdx = idx + pkcs7->stream->expected;
4772 #endif
4773
4774 /* Break out before content because it can be optional in degenerate
4775 * cases. */
4776 if (ret != 0 && !degenerate)
4777 break;
4778
4779 /* get parts of content */
4780 if (ret == 0 && multiPart) {
4781 int i = 0;
4782 keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0);
4783
4784 if (keepContent) {
4785 /* Create a buffer to hold content of OCTET_STRINGs. */
4786 pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap,
4787 DYNAMIC_TYPE_PKCS7);
4788 if (pkcs7->contentDynamic == NULL)
4789 ret = MEMORY_E;
4790 }
4791
4792 start = localIdx;
4793 /* Use the data from each OCTET_STRING. */
4794 while (ret == 0 && localIdx < start + contentLen) {
4795 if (GetASNTag(pkiMsg, &localIdx, &tag, totalSz) < 0)
4796 ret = ASN_PARSE_E;
4797 if (ret == 0 && tag != ASN_OCTET_STRING)
4798 ret = ASN_PARSE_E;
4799
4800 if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
4801 ret = ASN_PARSE_E;
4802 if (ret == 0 && length + localIdx > start + contentLen)
4803 ret = ASN_PARSE_E;
4804
4805 if (ret == 0) {
4806 if (keepContent) {
4807 XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx,
4808 length);
4809 }
4810 i += length;
4811 localIdx += length;
4812 }
4813 }
4814 localIdx = start; /* reset for sanity check, increment later */
4815 length = i;
4816 }
4817
4818 /* Save the inner data as the content. */
4819 if (ret == 0 && length > 0) {
4820 contentSz = length;
4821
4822 /* support using header and footer without content */
4823 if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
4824 /* Content not provided, use provided pkiMsg2 footer */
4825 content = NULL;
4826 localIdx = 0;
4827 if (contentSz != (int)pkcs7->contentSz) {
4828 WOLFSSL_MSG("Data signed does not match contentSz provided");
4829 ret = BUFFER_E;
4830 }
4831 }
4832 else {
4833 if ((word32)length > pkiMsgSz - localIdx) {
4834 ret = BUFFER_E;
4835 }
4836
4837 /* Content pointer for calculating hashes later */
4838 if (ret == 0 && !multiPart) {
4839 content = &pkiMsg[localIdx];
4840 }
4841 if (ret == 0 && multiPart) {
4842 content = pkcs7->contentDynamic;
4843 }
4844
4845 if (ret == 0) {
4846 idx += length;
4847 }
4848
4849 pkiMsg2 = pkiMsg;
4850 pkiMsg2Sz = pkiMsgSz;
4851 #ifndef NO_PKCS7_STREAM
4852 pkiMsg2Sz = pkcs7->stream->maxLen;
4853 pkcs7->stream->varOne = pkiMsg2Sz;
4854 pkcs7->stream->flagOne = 1;
4855 #endif
4856 }
4857 }
4858 else {
4859 pkiMsg2 = pkiMsg;
4860 pkiMsg2Sz = pkiMsgSz;
4861 #ifndef NO_PKCS7_STREAM
4862 pkiMsg2Sz = pkcs7->stream->maxLen;
4863 pkcs7->stream->varOne = pkiMsg2Sz;
4864 pkcs7->stream->flagOne = 1;
4865 #endif
4866 }
4867
4868 /* If getting the content info failed with non degenerate then return the
4869 * error case. Otherwise with a degenerate it is ok if the content
4870 * info was omitted */
4871 if (!degenerate && !detached && (ret != 0)) {
4872 break;
4873 }
4874 else {
4875 ret = 0; /* reset ret state on degenerate case */
4876 }
4877
4878 #ifndef NO_PKCS7_STREAM
4879 /* save content */
4880 if (detached == 1) {
4881 /* if detached, use content from user in pkcs7 struct */
4882 content = pkcs7->content;
4883 contentSz = pkcs7->contentSz;
4884 }
4885
4886 if (content != NULL) {
4887 XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4888 pkcs7->stream->content = (byte*)XMALLOC(contentSz, pkcs7->heap,
4889 DYNAMIC_TYPE_PKCS7);
4890 if (pkcs7->stream->content == NULL) {
4891 ret = MEMORY_E;
4892 break;
4893 }
4894 else {
4895 XMEMCPY(pkcs7->stream->content, content, contentSz);
4896 pkcs7->stream->contentSz = contentSz;
4897 }
4898 }
4899 #endif /* !NO_PKCS7_STREAM */
4900
4901 /* Get the implicit[0] set of certificates */
4902 if (ret == 0 && idx >= pkiMsg2Sz)
4903 ret = BUFFER_E;
4904
4905 length = 0; /* set length to 0 to check if reading in any certs */
4906 localIdx = idx;
4907 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0
4908 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
4909 idx++;
4910 if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK)
4911 < 0)
4912 ret = ASN_PARSE_E;
4913 }
4914
4915 if (ret != 0) {
4916 break;
4917 }
4918 #ifndef NO_PKCS7_STREAM
4919 if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
4920 stateIdx = idx; /* case where all data was read from in2 */
4921 }
4922
4923 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
4924 break;
4925 }
4926 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
4927 if (length > 0) {
4928 pkcs7->stream->expected = length;
4929 }
4930 else {
4931 pkcs7->stream->expected = MAX_SEQ_SZ;
4932 if (pkcs7->stream->expected > (pkcs7->stream->maxLen -
4933 pkcs7->stream->totalRd) + pkcs7->stream->length) {
4934 pkcs7->stream->expected = (pkcs7->stream->maxLen -
4935 pkcs7->stream->totalRd) + pkcs7->stream->length;
4936 }
4937 }
4938 #endif
4939 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4);
4940 FALL_THROUGH;
4941
4942 case WC_PKCS7_VERIFY_STAGE4:
4943 #ifndef NO_PKCS7_STREAM
4944 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
4945 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
4946 break;
4947 }
4948
4949 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
4950 if (pkcs7->stream->flagOne) {
4951 pkiMsg2 = pkiMsg;
4952 }
4953
4954 /* restore content */
4955 content = pkcs7->stream->content;
4956 contentSz = pkcs7->stream->contentSz;
4957
4958 /* restore detached flag */
4959 detached = pkcs7->stream->detached;
4960
4961 /* store certificate if needed */
4962 if (length > 0 && in2Sz == 0) {
4963 /* free tmpCert if not NULL */
4964 XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4965 pkcs7->stream->tmpCert = (byte*)XMALLOC(length,
4966 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
4967 if ((pkiMsg2 == NULL) || (pkcs7->stream->tmpCert == NULL)) {
4968 ret = MEMORY_E;
4969 break;
4970 }
4971 XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length);
4972 pkiMsg2 = pkcs7->stream->tmpCert;
4973 pkiMsg2Sz = length;
4974 idx = 0;
4975 }
4976 #endif
4977
4978 if (length > 0) {
4979 /* At this point, idx is at the first certificate in
4980 * a set of certificates. There may be more than one,
4981 * or none, or they may be a PKCS 6 extended
4982 * certificate. We want to save the first cert if it
4983 * is X.509. */
4984
4985 word32 certIdx = idx;
4986
4987 if (length < MAX_LENGTH_SZ + ASN_TAG_SZ)
4988 ret = BUFFER_E;
4989
4990 if (ret == 0)
4991 ret = GetASNTag(pkiMsg2, &certIdx, &tag, pkiMsg2Sz);
4992
4993 if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
4994 if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0)
4995 ret = ASN_PARSE_E;
4996
4997 cert = &pkiMsg2[idx];
4998 certSz += (certIdx - idx);
4999 if (certSz > length) {
5000 ret = BUFFER_E;
5001 break;
5002 }
5003 }
5004 #ifdef ASN_BER_TO_DER
5005 der = pkcs7->der;
5006 pkcs7->der = NULL;
5007 #endif
5008 version = pkcs7->version;
5009
5010 if (ret == 0) {
5011 byte isDynamic = (byte)pkcs7->isDynamic;
5012 #ifndef NO_PKCS7_STREAM
5013 PKCS7State* stream = pkcs7->stream;
5014 pkcs7->stream = NULL;
5015 #endif
5016
5017 /* Save dynamic content before freeing PKCS7 struct */
5018 if (pkcs7->contentDynamic != NULL) {
5019 contentDynamic = (byte*)XMALLOC(contentSz,
5020 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5021 if (contentDynamic == NULL) {
5022 ret = MEMORY_E;
5023 break;
5024 }
5025 XMEMCPY(contentDynamic, pkcs7->contentDynamic,
5026 contentSz);
5027 }
5028
5029 /* Free pkcs7 resources but not the structure itself */
5030 pkcs7->isDynamic = 0;
5031 wc_PKCS7_Free(pkcs7);
5032 pkcs7->isDynamic = isDynamic;
5033 /* This will reset PKCS7 structure and then set the
5034 * certificate */
5035 ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
5036
5037 /* Restore pkcs7->contentDynamic from above, will be
5038 * freed by application with wc_PKCS7_Free() */
5039 if (contentDynamic != NULL) {
5040 pkcs7->contentDynamic = contentDynamic;
5041 contentDynamic = NULL;
5042 }
5043
5044 #ifndef NO_PKCS7_STREAM
5045 pkcs7->stream = stream;
5046 #endif
5047 }
5048 pkcs7->version = version;
5049 #ifdef ASN_BER_TO_DER
5050 pkcs7->der = der;
5051 #endif
5052 if (ret != 0)
5053 break;
5054
5055 /* iterate through any additional certificates */
5056 if (ret == 0 && MAX_PKCS7_CERTS > 0) {
5057 int sz = 0;
5058 int i;
5059
5060 pkcs7->cert[0] = cert;
5061 pkcs7->certSz[0] = certSz;
5062 certIdx = idx + certSz;
5063
5064 for (i = 1; i < MAX_PKCS7_CERTS &&
5065 certIdx + 1 < pkiMsg2Sz &&
5066 certIdx + 1 < (word32)length; i++) {
5067 localIdx = certIdx;
5068
5069 if (ret == 0 && GetASNTag(pkiMsg2, &certIdx, &tag,
5070 pkiMsg2Sz) < 0) {
5071 ret = ASN_PARSE_E;
5072 break;
5073 }
5074
5075 if (ret == 0 &&
5076 tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
5077 if (GetLength(pkiMsg2, &certIdx, &sz,
5078 pkiMsg2Sz) < 0) {
5079 ret = ASN_PARSE_E;
5080 break;
5081 }
5082
5083 pkcs7->cert[i] = &pkiMsg2[localIdx];
5084 pkcs7->certSz[i] = sz + (certIdx - localIdx);
5085 certIdx += sz;
5086 }
5087 }
5088 }
5089 }
5090 idx += length;
5091
5092 if (!detached) {
5093 /* set content and size after init of PKCS7 structure */
5094 pkcs7->content = content;
5095 pkcs7->contentSz = contentSz;
5096 }
5097 #ifndef NO_PKCS7_STREAM
5098 else {
5099 /* save content if detached and using streaming API */
5100 if (pkcs7->content != NULL) {
5101 XFREE(pkcs7->stream->content, pkcs7->heap,
5102 DYNAMIC_TYPE_PKCS7);
5103 pkcs7->stream->content = (byte*)XMALLOC(pkcs7->contentSz,
5104 pkcs7->heap,
5105 DYNAMIC_TYPE_PKCS7);
5106 if (pkcs7->stream->content == NULL) {
5107 ret = MEMORY_E;
5108 break;
5109 }
5110 else {
5111 XMEMCPY(pkcs7->stream->content, pkcs7->content,
5112 contentSz);
5113 pkcs7->stream->contentSz = pkcs7->contentSz;
5114 }
5115 }
5116 }
5117 #endif
5118
5119 if (ret != 0) {
5120 break;
5121 }
5122 #ifndef NO_PKCS7_STREAM
5123 /* factor in that recent idx was in cert buffer. If in2 buffer was
5124 * used then don't advance idx. */
5125 if (length > 0 && pkcs7->stream->flagOne &&
5126 pkcs7->stream->length == 0) {
5127 idx = stateIdx + idx;
5128 if (idx > inSz) {
5129 /* index is more than input size */
5130 ret = BUFFER_E;
5131 break;
5132 }
5133 }
5134 else {
5135 stateIdx = idx; /* didn't read any from internal buffer */
5136 }
5137
5138 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
5139 break;
5140 }
5141 if (pkcs7->stream->flagOne && pkcs7->stream->length > 0) {
5142 idx = stateIdx + idx;
5143 }
5144
5145 pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ +
5146 MAX_SET_SZ;
5147
5148 if (pkcs7->stream->expected > (pkcs7->stream->maxLen -
5149 pkcs7->stream->totalRd) + pkcs7->stream->length)
5150 pkcs7->stream->expected = (pkcs7->stream->maxLen -
5151 pkcs7->stream->totalRd) + pkcs7->stream->length;
5152
5153 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0);
5154 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
5155 #endif
5156 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5);
5157 FALL_THROUGH;
5158
5159 case WC_PKCS7_VERIFY_STAGE5:
5160 #ifndef NO_PKCS7_STREAM
5161 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
5162 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
5163 break;
5164 }
5165 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
5166 if (pkcs7->stream->flagOne) {
5167 pkiMsg2 = pkiMsg;
5168
5169 /* check if using internal stream buffer and should adjust sz */
5170 if (pkiMsg != in && pkcs7->stream->length > 0) {
5171 pkiMsg2Sz = pkcs7->stream->length;
5172 }
5173 }
5174
5175 /* restore content type */
5176 contentType = pkcs7->stream->nonce;
5177 contentTypeSz = pkcs7->stream->nonceSz;
5178
5179 maxIdx = idx + pkcs7->stream->expected;
5180 if (maxIdx > pkiMsg2Sz) {
5181 ret = BUFFER_E;
5182 break;
5183 }
5184 stateIdx = idx;
5185 #endif
5186
5187 /* set contentType and size after init of PKCS7 structure */
5188 if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType,
5189 contentTypeSz) < 0)
5190 ret = ASN_PARSE_E;
5191
5192 /* Get the implicit[1] set of crls */
5193 if (ret == 0 && idx >= maxIdx)
5194 ret = BUFFER_E;
5195
5196 localIdx = idx;
5197 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0
5198 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
5199 idx++;
5200 if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
5201 ret = ASN_PARSE_E;
5202
5203 /* Skip the set */
5204 idx += length;
5205 }
5206
5207 /* Get the set of signerInfos */
5208 if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx,
5209 NO_USER_CHECK) < 0)
5210 ret = ASN_PARSE_E;
5211
5212 if (ret != 0)
5213 break;
5214 #ifndef NO_PKCS7_STREAM
5215 if (!pkcs7->stream->flagOne) {
5216 stateIdx = idx; /* didn't read any from internal buffer */
5217 }
5218 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
5219 break;
5220 }
5221 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
5222
5223 if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
5224 if (length > 0) {
5225 pkcs7->stream->expected = length;
5226 }
5227 else {
5228 pkcs7->stream->expected = 0;
5229 }
5230 }
5231 else {
5232 /* last state expect the rest of the buffer */
5233 pkcs7->stream->expected = (pkcs7->stream->maxLen -
5234 pkcs7->stream->totalRd) + pkcs7->stream->length;
5235 }
5236
5237 #endif
5238 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6);
5239 FALL_THROUGH;
5240
5241 case WC_PKCS7_VERIFY_STAGE6:
5242 #ifndef NO_PKCS7_STREAM
5243 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
5244 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
5245 break;
5246 }
5247
5248 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
5249 if (pkcs7->stream->flagOne) {
5250 pkiMsg2 = pkiMsg;
5251
5252 /* check if using internal stream buffer and should adjust sz */
5253 if (pkiMsg != in && pkcs7->stream->length > 0) {
5254 pkiMsg2Sz = pkcs7->stream->length;
5255 }
5256 else {
5257 /* if pkiMsg2 is pkiMsg and not using an internal stream
5258 * buffer then the size is limited by inSz */
5259 pkiMsg2Sz = inSz;
5260 }
5261 }
5262
5263 /* restore content */
5264 content = pkcs7->stream->content;
5265 contentSz = pkcs7->stream->contentSz;
5266 #endif
5267
5268 ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx,
5269 degenerate, &signedAttrib, &signedAttribSz);
5270
5271 /* parse out the signature if present and verify it */
5272 if (ret == 0 && length > 0 && degenerate == 0) {
5273 WOLFSSL_MSG("Parsing signature and verifying");
5274 if (idx >= pkiMsg2Sz)
5275 ret = BUFFER_E;
5276
5277 /* Get the signature */
5278 localIdx = idx;
5279 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag,
5280 pkiMsg2Sz) == 0 && tag == ASN_OCTET_STRING) {
5281 idx++;
5282
5283 if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
5284 ret = ASN_PARSE_E;
5285
5286 /* save pointer and length */
5287 sig = &pkiMsg2[idx];
5288 sigSz = length;
5289
5290 idx += length;
5291 }
5292
5293 pkcs7->content = content;
5294 pkcs7->contentSz = contentSz;
5295
5296 if (ret == 0) {
5297 ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
5298 signedAttrib, signedAttribSz,
5299 hashBuf, hashSz);
5300 }
5301 }
5302
5303 if (ret < 0)
5304 break;
5305
5306 ret = 0; /* success */
5307 #ifndef NO_PKCS7_STREAM
5308 wc_PKCS7_ResetStream(pkcs7);
5309 #endif
5310 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
5311 break;
5312
5313 default:
5314 WOLFSSL_MSG("PKCS7 Unknown verify state");
5315 ret = BAD_FUNC_ARG;
5316 }
5317
5318 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) {
5319 #ifndef NO_PKCS7_STREAM
5320 wc_PKCS7_ResetStream(pkcs7);
5321 #endif
5322 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
5323 }
5324 return ret;
5325 }
5326
5327
5328 /* Gets a copy of the SID parsed from signerInfo. This can be called after
5329 * wc_PKCS7_VerifySignedData has been called. SID can be SKID in version 3 case
5330 * or issuerAndSerialNumber.
5331 *
5332 * return 0 on success and LENGTH_ONLY_E if just setting "outSz" for buffer
5333 * length needed.
5334 */
wc_PKCS7_GetSignerSID(PKCS7 * pkcs7,byte * out,word32 * outSz)5335 int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz)
5336 {
5337 if (outSz == NULL || pkcs7 == NULL) {
5338 return BAD_FUNC_ARG;
5339 }
5340
5341 if (pkcs7->signerInfo == NULL) {
5342 WOLFSSL_MSG("Either the bundle had no signers or"
5343 "wc_PKCS7_VerifySignedData needs called yet");
5344 return PKCS7_NO_SIGNER_E;
5345 }
5346
5347 if (pkcs7->signerInfo->sidSz == 0) {
5348 WOLFSSL_MSG("Bundle had no signer SID set");
5349 return PKCS7_NO_SIGNER_E;
5350 }
5351
5352 if (out == NULL) {
5353 *outSz = pkcs7->signerInfo->sidSz;
5354 return LENGTH_ONLY_E;
5355 }
5356
5357 if (*outSz < pkcs7->signerInfo->sidSz) {
5358 WOLFSSL_MSG("Buffer being passed in is not large enough for SKID");
5359 return BUFFER_E;
5360 }
5361 XMEMCPY(out, pkcs7->signerInfo->sid, pkcs7->signerInfo->sidSz);
5362 *outSz = pkcs7->signerInfo->sidSz;
5363 return 0;
5364 }
5365
5366
5367 /* SignedData verification function variant that allows pre-computed content
5368 * message digest and optional PKCS7/CMS bundle content header/footer to be
5369 * used for verification. Useful for large data signing.
5370 *
5371 * pkcs7 - pointer to initialized PKCS7 structure
5372 * hashBuf - message digest of content
5373 * hashSz - size of hashBuf, octets
5374 * pkiMsgHead - PKCS7/CMS header that goes on top of the raw data signed,
5375 * as output from wc_PKCS7_EncodeSignedData_ex (if also using
5376 * pkiMsgFoot). Otherwise, PKCS7/CMS bundle with
5377 * detached signature - will use hashBuf/hashSz to verify.
5378 * pkiMsgHeadSz - size of pkiMsgHead, octets
5379 * pkiMsgFoot - PKCS7/CMS footer that goes at the end of the raw data signed,
5380 * as output from wc_PKCS7_EncodeSignedData_ex. Can be NULL
5381 * if pkiMsgHead is a direct detached signature bundle to be used
5382 * with hashBuf/hashSz.
5383 * pkiMsgFootSz - size of pkiMsgFoot, octets. Should be 0 if pkiMsgFoot is NULL.
5384 *
5385 * Returns 0 on success, negative upon error.
5386 *
5387 */
wc_PKCS7_VerifySignedData_ex(PKCS7 * pkcs7,const byte * hashBuf,word32 hashSz,byte * pkiMsgHead,word32 pkiMsgHeadSz,byte * pkiMsgFoot,word32 pkiMsgFootSz)5388 int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
5389 word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot,
5390 word32 pkiMsgFootSz)
5391 {
5392 return PKCS7_VerifySignedData(pkcs7, hashBuf, hashSz,
5393 pkiMsgHead, pkiMsgHeadSz, pkiMsgFoot, pkiMsgFootSz);
5394 }
5395
wc_PKCS7_VerifySignedData(PKCS7 * pkcs7,byte * pkiMsg,word32 pkiMsgSz)5396 int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
5397 {
5398 return PKCS7_VerifySignedData(pkcs7, NULL, 0, pkiMsg, pkiMsgSz, NULL, 0);
5399 }
5400
5401
5402 /* Generate random content encryption key, store into pkcs7->cek and
5403 * pkcs7->cekSz.
5404 *
5405 * pkcs7 - pointer to initialized PKCS7 structure
5406 * len - length of key to be generated
5407 *
5408 * Returns 0 on success, negative upon error */
PKCS7_GenerateContentEncryptionKey(PKCS7 * pkcs7,word32 len)5409 static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len)
5410 {
5411 int ret;
5412 WC_RNG rng;
5413 byte* tmpKey;
5414
5415 if (pkcs7 == NULL || len == 0)
5416 return BAD_FUNC_ARG;
5417
5418 /* if key already exists, don't need to re-generate */
5419 if (pkcs7->cek != NULL && pkcs7->cekSz != 0) {
5420
5421 /* if key exists, but is different size, return error */
5422 if (pkcs7->cekSz != len) {
5423 WOLFSSL_MSG("Random content-encryption key size is inconsistent "
5424 "between CMS recipients");
5425 return WC_KEY_SIZE_E;
5426 }
5427
5428 return 0;
5429 }
5430
5431 /* allocate space for cek */
5432 tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5433 if (tmpKey == NULL)
5434 return MEMORY_E;
5435
5436 XMEMSET(tmpKey, 0, len);
5437
5438 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
5439 if (ret != 0) {
5440 XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5441 return ret;
5442 }
5443
5444 ret = wc_RNG_GenerateBlock(&rng, tmpKey, len);
5445 if (ret != 0) {
5446 wc_FreeRng(&rng);
5447 XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5448 return ret;
5449 }
5450
5451 /* store into PKCS7, memory freed during final cleanup */
5452 pkcs7->cek = tmpKey;
5453 pkcs7->cekSz = len;
5454
5455 wc_FreeRng(&rng);
5456
5457 return 0;
5458 }
5459
5460
5461 /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */
wc_PKCS7_KeyWrap(byte * cek,word32 cekSz,byte * kek,word32 kekSz,byte * out,word32 outSz,int keyWrapAlgo,int direction)5462 static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek,
5463 word32 kekSz, byte* out, word32 outSz,
5464 int keyWrapAlgo, int direction)
5465 {
5466 int ret = 0;
5467
5468 if (cek == NULL || kek == NULL || out == NULL)
5469 return BAD_FUNC_ARG;
5470
5471 switch (keyWrapAlgo) {
5472 #ifndef NO_AES
5473 #ifdef WOLFSSL_AES_128
5474 case AES128_WRAP:
5475 #endif
5476 #ifdef WOLFSSL_AES_192
5477 case AES192_WRAP:
5478 #endif
5479 #ifdef WOLFSSL_AES_256
5480 case AES256_WRAP:
5481 #endif
5482
5483 if (direction == AES_ENCRYPTION) {
5484
5485 ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
5486 out, outSz, NULL);
5487
5488 } else if (direction == AES_DECRYPTION) {
5489
5490 ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
5491 out, outSz, NULL);
5492 } else {
5493 WOLFSSL_MSG("Bad key un/wrap direction");
5494 return BAD_FUNC_ARG;
5495 }
5496
5497 if (ret <= 0)
5498 return ret;
5499 break;
5500 #endif /* NO_AES */
5501
5502 default:
5503 WOLFSSL_MSG("Unsupported key wrap algorithm");
5504 return BAD_KEYWRAP_ALG_E;
5505 };
5506
5507 (void)cekSz;
5508 (void)kekSz;
5509 (void)outSz;
5510 (void)direction;
5511 return ret;
5512 }
5513
5514
5515 #ifdef HAVE_ECC
5516
5517 /* KARI == KeyAgreeRecipientInfo (key agreement) */
5518 typedef struct WC_PKCS7_KARI {
5519 DecodedCert* decoded; /* decoded recip cert */
5520 void* heap; /* user heap, points to PKCS7->heap */
5521 int devId; /* device ID for HW based private key */
5522 ecc_key* recipKey; /* recip key (pub | priv) */
5523 ecc_key* senderKey; /* sender key (pub | priv) */
5524 byte* senderKeyExport; /* sender ephemeral key DER */
5525 byte* kek; /* key encryption key */
5526 byte* ukm; /* OPTIONAL user keying material */
5527 byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */
5528 word32 senderKeyExportSz; /* size of sender ephemeral key DER */
5529 word32 kekSz; /* size of key encryption key */
5530 word32 ukmSz; /* size of user keying material */
5531 word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */
5532 byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */
5533 byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */
5534 byte decodedInit : 1; /* indicates decoded was initialized */
5535 byte recipKeyInit : 1; /* indicates recipKey was initialized */
5536 byte senderKeyInit : 1; /* indicates senderKey was initialized */
5537 } WC_PKCS7_KARI;
5538
5539
5540 /* allocate and create new WC_PKCS7_KARI struct,
5541 * returns struct pointer on success, NULL on failure */
wc_PKCS7_KariNew(PKCS7 * pkcs7,byte direction)5542 static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction)
5543 {
5544 WC_PKCS7_KARI* kari = NULL;
5545
5546 if (pkcs7 == NULL)
5547 return NULL;
5548
5549 kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap,
5550 DYNAMIC_TYPE_PKCS7);
5551 if (kari == NULL) {
5552 WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI");
5553 return NULL;
5554 }
5555
5556 kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
5557 DYNAMIC_TYPE_PKCS7);
5558 if (kari->decoded == NULL) {
5559 WOLFSSL_MSG("Failed to allocate DecodedCert");
5560 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5561 return NULL;
5562 }
5563
5564 kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
5565 DYNAMIC_TYPE_PKCS7);
5566 if (kari->recipKey == NULL) {
5567 WOLFSSL_MSG("Failed to allocate recipient ecc_key");
5568 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5569 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5570 return NULL;
5571 }
5572
5573 kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
5574 DYNAMIC_TYPE_PKCS7);
5575 if (kari->senderKey == NULL) {
5576 WOLFSSL_MSG("Failed to allocate sender ecc_key");
5577 XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5578 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5579 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
5580 return NULL;
5581 }
5582
5583 kari->senderKeyExport = NULL;
5584 kari->senderKeyExportSz = 0;
5585 kari->kek = NULL;
5586 kari->kekSz = 0;
5587 kari->ukm = NULL;
5588 kari->ukmSz = 0;
5589 kari->ukmOwner = 0;
5590 kari->sharedInfo = NULL;
5591 kari->sharedInfoSz = 0;
5592 kari->direction = direction;
5593 kari->decodedInit = 0;
5594 kari->recipKeyInit = 0;
5595 kari->senderKeyInit = 0;
5596
5597 kari->heap = pkcs7->heap;
5598 kari->devId = pkcs7->devId;
5599
5600 return kari;
5601 }
5602
5603
5604 /* free WC_PKCS7_KARI struct, return 0 on success */
wc_PKCS7_KariFree(WC_PKCS7_KARI * kari)5605 static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari)
5606 {
5607 void* heap;
5608
5609 if (kari) {
5610 heap = kari->heap;
5611
5612 if (kari->decoded) {
5613 if (kari->decodedInit)
5614 FreeDecodedCert(kari->decoded);
5615 XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7);
5616 }
5617 if (kari->senderKey) {
5618 if (kari->senderKeyInit)
5619 wc_ecc_free(kari->senderKey);
5620 XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7);
5621 }
5622 if (kari->recipKey) {
5623 if (kari->recipKeyInit)
5624 wc_ecc_free(kari->recipKey);
5625 XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7);
5626 }
5627 if (kari->senderKeyExport) {
5628 ForceZero(kari->senderKeyExport, kari->senderKeyExportSz);
5629 XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7);
5630 kari->senderKeyExportSz = 0;
5631 }
5632 if (kari->kek) {
5633 ForceZero(kari->kek, kari->kekSz);
5634 XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7);
5635 kari->kekSz = 0;
5636 }
5637 if (kari->ukm) {
5638 if (kari->ukmOwner == 1) {
5639 XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7);
5640 }
5641 kari->ukmSz = 0;
5642 }
5643 if (kari->sharedInfo) {
5644 ForceZero(kari->sharedInfo, kari->sharedInfoSz);
5645 XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7);
5646 kari->sharedInfoSz = 0;
5647 }
5648 XFREE(kari, heap, DYNAMIC_TYPE_PKCS7);
5649 }
5650
5651 (void)heap;
5652
5653 return 0;
5654 }
5655
5656
5657 /* parse recipient cert/key, return 0 on success, negative on error
5658 * key/keySz only needed during decoding (WC_PKCS7_DECODE) */
wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI * kari,const byte * cert,word32 certSz,const byte * key,word32 keySz)5659 static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
5660 word32 certSz, const byte* key,
5661 word32 keySz)
5662 {
5663 int ret;
5664 word32 idx;
5665
5666 if (kari == NULL || kari->decoded == NULL ||
5667 cert == NULL || certSz == 0)
5668 return BAD_FUNC_ARG;
5669
5670 /* decode certificate */
5671 InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap);
5672 kari->decodedInit = 1;
5673 ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0);
5674 if (ret < 0)
5675 return ret;
5676
5677 /* only supports ECDSA for now */
5678 if (kari->decoded->keyOID != ECDSAk) {
5679 WOLFSSL_MSG("CMS KARI only supports ECDSA key types");
5680 return BAD_FUNC_ARG;
5681 }
5682
5683 /* make sure subject key id was read from cert */
5684 if (kari->decoded->extSubjKeyIdSet == 0) {
5685 WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
5686 return BAD_FUNC_ARG;
5687 }
5688
5689 ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId);
5690 if (ret != 0)
5691 return ret;
5692
5693 kari->recipKeyInit = 1;
5694
5695 /* get recip public key */
5696 if (kari->direction == WC_PKCS7_ENCODE) {
5697
5698 idx = 0;
5699 ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx,
5700 kari->recipKey, kari->decoded->pubKeySize);
5701 if (ret != 0)
5702 return ret;
5703 }
5704 /* get recip private key */
5705 else if (kari->direction == WC_PKCS7_DECODE) {
5706 if (key != NULL && keySz > 0) {
5707 idx = 0;
5708 ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz);
5709 }
5710 else if (kari->devId == INVALID_DEVID) {
5711 ret = BAD_FUNC_ARG;
5712 }
5713 if (ret != 0)
5714 return ret;
5715
5716 } else {
5717 /* bad direction */
5718 return BAD_FUNC_ARG;
5719 }
5720
5721 (void)idx;
5722
5723 return 0;
5724 }
5725
5726
5727 /* create ephemeral ECC key, places ecc_key in kari->senderKey,
5728 * DER encoded in kari->senderKeyExport. return 0 on success,
5729 * negative on error */
wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI * kari)5730 static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari)
5731 {
5732 int ret;
5733 WC_RNG rng;
5734
5735 if (kari == NULL || kari->decoded == NULL ||
5736 kari->recipKey == NULL || kari->recipKey->dp == NULL)
5737 return BAD_FUNC_ARG;
5738
5739 kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize,
5740 kari->heap, DYNAMIC_TYPE_PKCS7);
5741 if (kari->senderKeyExport == NULL)
5742 return MEMORY_E;
5743
5744 kari->senderKeyExportSz = kari->decoded->pubKeySize;
5745
5746 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
5747 if (ret != 0) {
5748 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
5749 kari->senderKeyExportSz = 0;
5750 kari->senderKeyExport = NULL;
5751 return ret;
5752 }
5753
5754 kari->senderKeyInit = 1;
5755
5756 ret = wc_InitRng_ex(&rng, kari->heap, kari->devId);
5757 if (ret != 0) {
5758 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
5759 kari->senderKeyExportSz = 0;
5760 kari->senderKeyExport = NULL;
5761 return ret;
5762 }
5763
5764 ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size,
5765 kari->senderKey, kari->recipKey->dp->id);
5766 if (ret != 0) {
5767 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
5768 kari->senderKeyExportSz = 0;
5769 kari->senderKeyExport = NULL;
5770 wc_FreeRng(&rng);
5771 return ret;
5772 }
5773
5774 wc_FreeRng(&rng);
5775
5776 /* dump generated key to X.963 DER for output in CMS bundle */
5777 PRIVATE_KEY_UNLOCK();
5778 ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport,
5779 &kari->senderKeyExportSz);
5780 PRIVATE_KEY_LOCK();
5781 if (ret != 0) {
5782 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
5783 kari->senderKeyExportSz = 0;
5784 kari->senderKeyExport = NULL;
5785 return ret;
5786 }
5787
5788 return 0;
5789 }
5790
5791
5792 /* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm,
5793 * place in kari->sharedInfo. returns 0 on success, negative on error */
wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI * kari,int keyWrapOID)5794 static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
5795 {
5796 int idx = 0;
5797 int sharedInfoSeqSz = 0;
5798 int keyInfoSz = 0;
5799 int suppPubInfoSeqSz = 0;
5800 int entityUInfoOctetSz = 0;
5801 int entityUInfoExplicitSz = 0;
5802 int kekOctetSz = 0;
5803 int sharedInfoSz = 0;
5804
5805 word32 kekBitSz = 0;
5806
5807 byte sharedInfoSeq[MAX_SEQ_SZ];
5808 byte keyInfo[MAX_ALGO_SZ];
5809 byte suppPubInfoSeq[MAX_SEQ_SZ];
5810 byte entityUInfoOctet[MAX_OCTET_STR_SZ];
5811 byte entityUInfoExplicitSeq[MAX_SEQ_SZ];
5812 byte kekOctet[MAX_OCTET_STR_SZ];
5813
5814 if (kari == NULL)
5815 return BAD_FUNC_ARG;
5816
5817 if ((kari->ukmSz > 0) && (kari->ukm == NULL))
5818 return BAD_FUNC_ARG;
5819
5820 /* kekOctet */
5821 kekOctetSz = SetOctetString(sizeof(word32), kekOctet);
5822 sharedInfoSz += (kekOctetSz + sizeof(word32));
5823
5824 /* suppPubInfo */
5825 suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2,
5826 kekOctetSz + sizeof(word32),
5827 suppPubInfoSeq);
5828 sharedInfoSz += suppPubInfoSeqSz;
5829
5830 /* optional ukm/entityInfo */
5831 if (kari->ukmSz > 0) {
5832 entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet);
5833 sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz);
5834
5835 entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz +
5836 kari->ukmSz,
5837 entityUInfoExplicitSeq);
5838 sharedInfoSz += entityUInfoExplicitSz;
5839 }
5840
5841 /* keyInfo */
5842 keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0);
5843 sharedInfoSz += keyInfoSz;
5844
5845 /* sharedInfo */
5846 sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq);
5847 sharedInfoSz += sharedInfoSeqSz;
5848
5849 kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap,
5850 DYNAMIC_TYPE_PKCS7);
5851 if (kari->sharedInfo == NULL)
5852 return MEMORY_E;
5853
5854 kari->sharedInfoSz = sharedInfoSz;
5855
5856 XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz);
5857 idx += sharedInfoSeqSz;
5858 XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz);
5859 idx += keyInfoSz;
5860 if (kari->ukmSz > 0) {
5861 XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq,
5862 entityUInfoExplicitSz);
5863 idx += entityUInfoExplicitSz;
5864 XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz);
5865 idx += entityUInfoOctetSz;
5866 XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz);
5867 idx += kari->ukmSz;
5868 }
5869 XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz);
5870 idx += suppPubInfoSeqSz;
5871 XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz);
5872 idx += kekOctetSz;
5873
5874 kekBitSz = (kari->kekSz) * 8; /* convert to bits */
5875 #ifdef LITTLE_ENDIAN_ORDER
5876 kekBitSz = ByteReverseWord32(kekBitSz); /* network byte order */
5877 #endif
5878 XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz));
5879
5880 return 0;
5881 }
5882
5883
5884 /* create key encryption key (KEK) using key wrap algorithm and key encryption
5885 * algorithm, place in kari->kek. return 0 on success, <0 on error. */
wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI * kari,WC_RNG * rng,int keyWrapOID,int keyEncOID)5886 static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, WC_RNG* rng,
5887 int keyWrapOID, int keyEncOID)
5888 {
5889 int ret;
5890 int kSz;
5891 enum wc_HashType kdfType;
5892 byte* secret;
5893 word32 secretSz;
5894
5895 if (kari == NULL || kari->recipKey == NULL ||
5896 kari->senderKey == NULL || kari->senderKey->dp == NULL)
5897 return BAD_FUNC_ARG;
5898
5899 /* get KEK size, allocate buff */
5900 kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID);
5901 if (kSz < 0)
5902 return kSz;
5903
5904 kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7);
5905 if (kari->kek == NULL)
5906 return MEMORY_E;
5907
5908 kari->kekSz = (word32)kSz;
5909
5910 /* generate ECC-CMS-SharedInfo */
5911 ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID);
5912 if (ret != 0)
5913 return ret;
5914
5915 /* generate shared secret */
5916 secretSz = kari->senderKey->dp->size;
5917 secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7);
5918 if (secret == NULL)
5919 return MEMORY_E;
5920
5921 #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
5922 (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
5923 !defined(HAVE_SELFTEST)
5924 ret = wc_ecc_set_rng(kari->senderKey, rng);
5925 if (ret != 0)
5926 return ret;
5927 ret = wc_ecc_set_rng(kari->recipKey, rng);
5928 if (ret != 0)
5929 return ret;
5930 #else
5931 (void)rng;
5932 #endif
5933
5934 if (kari->direction == WC_PKCS7_ENCODE) {
5935 PRIVATE_KEY_UNLOCK();
5936 ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey,
5937 secret, &secretSz);
5938 PRIVATE_KEY_LOCK();
5939 } else if (kari->direction == WC_PKCS7_DECODE) {
5940 PRIVATE_KEY_UNLOCK();
5941 ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey,
5942 secret, &secretSz);
5943 PRIVATE_KEY_LOCK();
5944 } else {
5945 /* bad direction */
5946 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
5947 return BAD_FUNC_ARG;
5948 }
5949
5950 if (ret != 0) {
5951 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
5952 return ret;
5953 }
5954
5955 /* run through KDF */
5956 switch (keyEncOID) {
5957
5958 #ifndef NO_SHA
5959 case dhSinglePass_stdDH_sha1kdf_scheme:
5960 kdfType = WC_HASH_TYPE_SHA;
5961 break;
5962 #endif
5963 #ifndef WOLFSSL_SHA224
5964 case dhSinglePass_stdDH_sha224kdf_scheme:
5965 kdfType = WC_HASH_TYPE_SHA224;
5966 break;
5967 #endif
5968 #ifndef NO_SHA256
5969 case dhSinglePass_stdDH_sha256kdf_scheme:
5970 kdfType = WC_HASH_TYPE_SHA256;
5971 break;
5972 #endif
5973 #ifdef WOLFSSL_SHA384
5974 case dhSinglePass_stdDH_sha384kdf_scheme:
5975 kdfType = WC_HASH_TYPE_SHA384;
5976 break;
5977 #endif
5978 #ifdef WOLFSSL_SHA512
5979 case dhSinglePass_stdDH_sha512kdf_scheme:
5980 kdfType = WC_HASH_TYPE_SHA512;
5981 break;
5982 #endif
5983 default:
5984 WOLFSSL_MSG("Unsupported key agreement algorithm");
5985 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
5986 return BAD_FUNC_ARG;
5987 };
5988
5989 ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo,
5990 kari->sharedInfoSz, kari->kek, kari->kekSz);
5991 if (ret != 0) {
5992 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
5993 return ret;
5994 }
5995
5996 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
5997
5998 return 0;
5999 }
6000
6001
6002 /* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo
6003 * to CMS/PKCS#7 EnvelopedData structure.
6004 *
6005 * Returns 0 on success, negative upon error */
wc_PKCS7_AddRecipient_KARI(PKCS7 * pkcs7,const byte * cert,word32 certSz,int keyWrapOID,int keyAgreeOID,byte * ukm,word32 ukmSz,int options)6006 int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
6007 int keyWrapOID, int keyAgreeOID, byte* ukm,
6008 word32 ukmSz, int options)
6009 {
6010 Pkcs7EncodedRecip* recip;
6011 Pkcs7EncodedRecip* lastRecip = NULL;
6012 WC_PKCS7_KARI* kari = NULL;
6013
6014 word32 idx = 0;
6015 word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
6016
6017 int ret = 0;
6018 int keySz, direction = 0;
6019 int blockKeySz = 0;
6020
6021 /* ASN.1 layout */
6022 int totalSz = 0;
6023 int kariSeqSz = 0;
6024 byte kariSeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */
6025 int verSz = 0;
6026 byte ver[MAX_VERSION_SZ];
6027
6028 int origIdOrKeySeqSz = 0;
6029 byte origIdOrKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */
6030 int origPubKeySeqSz = 0;
6031 byte origPubKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */
6032 int origAlgIdSz = 0;
6033 byte origAlgId[MAX_ALGO_SZ];
6034 int origPubKeyStrSz = 0;
6035 byte origPubKeyStr[MAX_OCTET_STR_SZ];
6036
6037 /* optional user keying material */
6038 int ukmOctetSz = 0;
6039 byte ukmOctetStr[MAX_OCTET_STR_SZ];
6040 int ukmExplicitSz = 0;
6041 byte ukmExplicitSeq[MAX_SEQ_SZ];
6042
6043 int keyEncryptAlgoIdSz = 0;
6044 byte keyEncryptAlgoId[MAX_ALGO_SZ];
6045 int keyWrapAlgSz = 0;
6046 byte keyWrapAlg[MAX_ALGO_SZ];
6047
6048 int recipEncKeysSeqSz = 0;
6049 byte recipEncKeysSeq[MAX_SEQ_SZ];
6050 int recipEncKeySeqSz = 0;
6051 byte recipEncKeySeq[MAX_SEQ_SZ];
6052 int recipKeyIdSeqSz = 0;
6053 byte recipKeyIdSeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */
6054 int subjKeyIdOctetSz = 0;
6055 byte subjKeyIdOctet[MAX_OCTET_STR_SZ];
6056 int encryptedKeyOctetSz = 0;
6057 byte encryptedKeyOctet[MAX_OCTET_STR_SZ];
6058
6059 #ifdef WOLFSSL_SMALL_STACK
6060 byte* encryptedKey;
6061
6062 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
6063 DYNAMIC_TYPE_TMP_BUFFER);
6064 if (encryptedKey == NULL) {
6065 return MEMORY_E;
6066 }
6067 #else
6068 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
6069 #endif
6070
6071 /* allocate and init memory for recipient */
6072 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
6073 DYNAMIC_TYPE_PKCS7);
6074 if (recip == NULL) {
6075 #ifdef WOLFSSL_SMALL_STACK
6076 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6077 #endif
6078 return MEMORY_E;
6079 }
6080 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
6081
6082 /* get key size for content-encryption key based on algorithm */
6083 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
6084 if (blockKeySz < 0) {
6085 #ifdef WOLFSSL_SMALL_STACK
6086 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6087 #endif
6088 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6089 return blockKeySz;
6090 }
6091
6092 /* generate random content encryption key, if needed */
6093 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
6094 if (ret < 0) {
6095 #ifdef WOLFSSL_SMALL_STACK
6096 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6097 #endif
6098 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6099 return ret;
6100 }
6101
6102 /* set direction based on keyWrapAlgo */
6103 switch (keyWrapOID) {
6104 #ifndef NO_AES
6105 #ifdef WOLFSSL_AES_128
6106 case AES128_WRAP:
6107 #endif
6108 #ifdef WOLFSSL_AES_192
6109 case AES192_WRAP:
6110 #endif
6111 #ifdef WOLFSSL_AES_256
6112 case AES256_WRAP:
6113 #endif
6114 direction = AES_ENCRYPTION;
6115 break;
6116 #endif
6117 default:
6118 WOLFSSL_MSG("Unsupported key wrap algorithm");
6119 #ifdef WOLFSSL_SMALL_STACK
6120 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6121 #endif
6122 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6123 return BAD_KEYWRAP_ALG_E;
6124 }
6125
6126 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE);
6127 if (kari == NULL) {
6128 #ifdef WOLFSSL_SMALL_STACK
6129 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6130 #endif
6131 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6132 return MEMORY_E;
6133 }
6134
6135 /* set user keying material if available */
6136 if (ukmSz > 0 && ukm != NULL) {
6137 kari->ukm = ukm;
6138 kari->ukmSz = ukmSz;
6139 kari->ukmOwner = 0;
6140 }
6141
6142 /* parse recipient cert, get public key */
6143 ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0);
6144 if (ret != 0) {
6145 wc_PKCS7_KariFree(kari);
6146 #ifdef WOLFSSL_SMALL_STACK
6147 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6148 #endif
6149 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6150 return ret;
6151 }
6152
6153 /* generate sender ephemeral ECC key */
6154 ret = wc_PKCS7_KariGenerateEphemeralKey(kari);
6155 if (ret != 0) {
6156 wc_PKCS7_KariFree(kari);
6157 #ifdef WOLFSSL_SMALL_STACK
6158 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6159 #endif
6160 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6161 return ret;
6162 }
6163
6164 /* generate KEK (key encryption key) */
6165 ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID, keyAgreeOID);
6166 if (ret != 0) {
6167 wc_PKCS7_KariFree(kari);
6168 #ifdef WOLFSSL_SMALL_STACK
6169 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6170 #endif
6171 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6172 return ret;
6173 }
6174
6175 /* encrypt CEK with KEK */
6176 keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek,
6177 kari->kekSz, encryptedKey, encryptedKeySz,
6178 keyWrapOID, direction);
6179 if (keySz <= 0) {
6180 wc_PKCS7_KariFree(kari);
6181 #ifdef WOLFSSL_SMALL_STACK
6182 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6183 #endif
6184 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6185 return keySz;
6186 }
6187 encryptedKeySz = (word32)keySz;
6188
6189 /* Start of RecipientEncryptedKeys */
6190
6191 /* EncryptedKey */
6192 encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet);
6193 totalSz += (encryptedKeyOctetSz + encryptedKeySz);
6194
6195 /* SubjectKeyIdentifier */
6196 subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet);
6197 totalSz += (subjKeyIdOctetSz + KEYID_SIZE);
6198
6199 /* RecipientKeyIdentifier IMPLICIT [0] */
6200 recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz +
6201 KEYID_SIZE, recipKeyIdSeq);
6202 totalSz += recipKeyIdSeqSz;
6203
6204 /* RecipientEncryptedKey */
6205 recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq);
6206 totalSz += recipEncKeySeqSz;
6207
6208 /* RecipientEncryptedKeys */
6209 recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq);
6210 totalSz += recipEncKeysSeqSz;
6211
6212 /* Start of optional UserKeyingMaterial */
6213
6214 if (kari->ukmSz > 0) {
6215 ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr);
6216 totalSz += (ukmOctetSz + kari->ukmSz);
6217
6218 ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz,
6219 ukmExplicitSeq);
6220 totalSz += ukmExplicitSz;
6221 }
6222
6223 /* Start of KeyEncryptionAlgorithmIdentifier */
6224
6225 /* KeyWrapAlgorithm */
6226 keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0);
6227 totalSz += keyWrapAlgSz;
6228
6229 /* KeyEncryptionAlgorithmIdentifier */
6230 keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId,
6231 oidCmsKeyAgreeType, keyWrapAlgSz);
6232 totalSz += keyEncryptAlgoIdSz;
6233
6234 /* Start of OriginatorIdentifierOrKey */
6235
6236 /* recipient ECPoint, public key */
6237 XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */
6238 origPubKeyStr[0] = ASN_BIT_STRING;
6239 origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1,
6240 origPubKeyStr + 1) + 2;
6241 totalSz += (origPubKeyStrSz + kari->senderKeyExportSz);
6242
6243 /* Originator AlgorithmIdentifier, params set to NULL for interop
6244 compatibility */
6245 origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2);
6246 origAlgId[origAlgIdSz++] = ASN_TAG_NULL;
6247 origAlgId[origAlgIdSz++] = 0;
6248 totalSz += origAlgIdSz;
6249
6250 /* outer OriginatorPublicKey IMPLICIT [1] */
6251 origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1,
6252 origAlgIdSz + origPubKeyStrSz +
6253 kari->senderKeyExportSz, origPubKeySeq);
6254 totalSz += origPubKeySeqSz;
6255
6256 /* outer OriginatorIdentifierOrKey IMPLICIT [0] */
6257 origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0,
6258 origPubKeySeqSz + origAlgIdSz +
6259 origPubKeyStrSz + kari->senderKeyExportSz,
6260 origIdOrKeySeq);
6261 totalSz += origIdOrKeySeqSz;
6262
6263 /* version, always 3 */
6264 verSz = SetMyVersion(3, ver, 0);
6265 totalSz += verSz;
6266 recip->recipVersion = 3;
6267
6268 /* outer IMPLICIT [1] kari */
6269 kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
6270 totalSz += kariSeqSz;
6271
6272 if (totalSz > MAX_RECIP_SZ) {
6273 WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small");
6274 wc_PKCS7_KariFree(kari);
6275 #ifdef WOLFSSL_SMALL_STACK
6276 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6277 #endif
6278 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6279 return BUFFER_E;
6280 }
6281
6282 XMEMCPY(recip->recip + idx, kariSeq, kariSeqSz);
6283 idx += kariSeqSz;
6284 XMEMCPY(recip->recip + idx, ver, verSz);
6285 idx += verSz;
6286
6287 XMEMCPY(recip->recip + idx, origIdOrKeySeq, origIdOrKeySeqSz);
6288 idx += origIdOrKeySeqSz;
6289 XMEMCPY(recip->recip + idx, origPubKeySeq, origPubKeySeqSz);
6290 idx += origPubKeySeqSz;
6291
6292 /* AlgorithmIdentifier with NULL parameter */
6293 XMEMCPY(recip->recip + idx, origAlgId, origAlgIdSz);
6294 idx += origAlgIdSz;
6295
6296 XMEMCPY(recip->recip + idx, origPubKeyStr, origPubKeyStrSz);
6297 idx += origPubKeyStrSz;
6298 /* ephemeral public key */
6299 XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz);
6300 idx += kari->senderKeyExportSz;
6301
6302 if (kari->ukmSz > 0) {
6303 XMEMCPY(recip->recip + idx, ukmExplicitSeq, ukmExplicitSz);
6304 idx += ukmExplicitSz;
6305 XMEMCPY(recip->recip + idx, ukmOctetStr, ukmOctetSz);
6306 idx += ukmOctetSz;
6307 XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz);
6308 idx += kari->ukmSz;
6309 }
6310
6311 XMEMCPY(recip->recip + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz);
6312 idx += keyEncryptAlgoIdSz;
6313 XMEMCPY(recip->recip + idx, keyWrapAlg, keyWrapAlgSz);
6314 idx += keyWrapAlgSz;
6315
6316 XMEMCPY(recip->recip + idx, recipEncKeysSeq, recipEncKeysSeqSz);
6317 idx += recipEncKeysSeqSz;
6318 XMEMCPY(recip->recip + idx, recipEncKeySeq, recipEncKeySeqSz);
6319 idx += recipEncKeySeqSz;
6320 XMEMCPY(recip->recip + idx, recipKeyIdSeq, recipKeyIdSeqSz);
6321 idx += recipKeyIdSeqSz;
6322 XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz);
6323 idx += subjKeyIdOctetSz;
6324 /* subject key id */
6325 XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE);
6326 idx += KEYID_SIZE;
6327 XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz);
6328 idx += encryptedKeyOctetSz;
6329 /* encrypted CEK */
6330 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
6331 idx += encryptedKeySz;
6332
6333 wc_PKCS7_KariFree(kari);
6334 #ifdef WOLFSSL_SMALL_STACK
6335 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6336 #endif
6337
6338 /* store recipient size */
6339 recip->recipSz = idx;
6340 recip->recipType = PKCS7_KARI;
6341
6342 /* add recipient to recip list */
6343 if (pkcs7->recipList == NULL) {
6344 pkcs7->recipList = recip;
6345 } else {
6346 lastRecip = pkcs7->recipList;
6347 while (lastRecip->next != NULL) {
6348 lastRecip = lastRecip->next;
6349 }
6350 lastRecip->next = recip;
6351 }
6352
6353 (void)options;
6354
6355 return idx;
6356 }
6357
6358 #endif /* HAVE_ECC */
6359
6360 #ifndef NO_RSA
6361
6362 /* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo
6363 * to CMS/PKCS#7 EnvelopedData structure.
6364 *
6365 * Returns 0 on success, negative upon error */
wc_PKCS7_AddRecipient_KTRI(PKCS7 * pkcs7,const byte * cert,word32 certSz,int options)6366 int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
6367 int options)
6368 {
6369 Pkcs7EncodedRecip* recip = NULL;
6370 Pkcs7EncodedRecip* lastRecip = NULL;
6371
6372 WC_RNG rng;
6373 word32 idx = 0;
6374 word32 encryptedKeySz = 0;
6375
6376 int ret = 0, blockKeySz;
6377 int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0;
6378 int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0;
6379 int encKeyOctetStrSz;
6380 int sidType;
6381
6382 byte ver[MAX_VERSION_SZ];
6383 byte issuerSerialSeq[MAX_SEQ_SZ];
6384 byte recipSeq[MAX_SEQ_SZ];
6385 byte issuerSeq[MAX_SEQ_SZ];
6386 byte encKeyOctetStr[MAX_OCTET_STR_SZ];
6387
6388 byte issuerSKID[MAX_LENGTH_SZ];
6389 word32 issuerSKIDSz = 0;
6390
6391 #ifdef WOLFSSL_SMALL_STACK
6392 byte* serial;
6393 byte* keyAlgArray;
6394 byte* encryptedKey;
6395 RsaKey* pubKey;
6396 DecodedCert* decoded;
6397
6398 serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6399 keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap,
6400 DYNAMIC_TYPE_TMP_BUFFER);
6401 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
6402 DYNAMIC_TYPE_TMP_BUFFER);
6403 decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
6404 DYNAMIC_TYPE_TMP_BUFFER);
6405
6406 if (decoded == NULL || serial == NULL ||
6407 encryptedKey == NULL || keyAlgArray == NULL) {
6408 if (serial)
6409 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6410 if (keyAlgArray)
6411 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6412 if (encryptedKey)
6413 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6414 if (decoded)
6415 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6416 return MEMORY_E;
6417 }
6418 #else
6419 byte serial[MAX_SN_SZ];
6420 byte keyAlgArray[MAX_ALGO_SZ];
6421 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
6422
6423 RsaKey pubKey[1];
6424 DecodedCert decoded[1];
6425 #endif
6426
6427 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
6428 XMEMSET(encryptedKey, 0, encryptedKeySz);
6429
6430 /* default to IssuerAndSerialNumber if not set */
6431 if (pkcs7->sidType != 0) {
6432 sidType = pkcs7->sidType;
6433 } else {
6434 sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
6435 }
6436
6437 /* allow options to override SubjectIdentifier type if set */
6438 if (options & CMS_SKID) {
6439 sidType = CMS_SKID;
6440 } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) {
6441 sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
6442 }
6443
6444 /* allocate recipient struct */
6445 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
6446 DYNAMIC_TYPE_PKCS7);
6447 if (recip == NULL) {
6448 #ifdef WOLFSSL_SMALL_STACK
6449 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6450 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6451 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6452 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6453 #endif
6454 return MEMORY_E;
6455 }
6456 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
6457
6458 /* get key size for content-encryption key based on algorithm */
6459 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
6460 if (blockKeySz < 0) {
6461 #ifdef WOLFSSL_SMALL_STACK
6462 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6463 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6464 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6465 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6466 #endif
6467 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6468 return blockKeySz;
6469 }
6470
6471 /* generate random content encryption key, if needed */
6472 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
6473 if (ret < 0) {
6474 #ifdef WOLFSSL_SMALL_STACK
6475 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6476 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6477 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6478 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6479 #endif
6480 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6481 return ret;
6482 }
6483
6484 InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap);
6485 ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
6486 if (ret < 0) {
6487 FreeDecodedCert(decoded);
6488 #ifdef WOLFSSL_SMALL_STACK
6489 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6490 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6491 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6492 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6493 #endif
6494 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6495 return ret;
6496 }
6497
6498 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
6499
6500 /* version, must be 0 for IssuerAndSerialNumber */
6501 verSz = SetMyVersion(0, ver, 0);
6502 recip->recipVersion = 0;
6503
6504 /* IssuerAndSerialNumber */
6505 if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
6506 WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length");
6507 FreeDecodedCert(decoded);
6508 #ifdef WOLFSSL_SMALL_STACK
6509 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6510 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6511 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6512 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6513 #endif
6514 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6515 return -1;
6516 }
6517 issuerSz = decoded->issuerRawLen;
6518 issuerSeqSz = SetSequence(issuerSz, issuerSeq);
6519
6520 if (decoded->serialSz == 0) {
6521 WOLFSSL_MSG("DecodedCert missing serial number");
6522 FreeDecodedCert(decoded);
6523 #ifdef WOLFSSL_SMALL_STACK
6524 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6525 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6526 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6527 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6528 #endif
6529 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6530 return -1;
6531 }
6532 snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial,
6533 MAX_SN_SZ, MAX_SN_SZ);
6534 if (snSz < 0) {
6535 WOLFSSL_MSG("Error setting the serial number");
6536 FreeDecodedCert(decoded);
6537 #ifdef WOLFSSL_SMALL_STACK
6538 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6539 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6540 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6541 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6542 #endif
6543 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6544 return -1;
6545 }
6546 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
6547 issuerSerialSeq);
6548 } else if (sidType == CMS_SKID) {
6549
6550 /* version, must be 2 for SubjectKeyIdentifier */
6551 verSz = SetMyVersion(2, ver, 0);
6552 recip->recipVersion = 2;
6553
6554 issuerSKIDSz = SetLength(KEYID_SIZE, issuerSKID);
6555 } else {
6556 FreeDecodedCert(decoded);
6557 #ifdef WOLFSSL_SMALL_STACK
6558 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6559 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6560 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6561 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6562 #endif
6563 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6564 return PKCS7_RECIP_E;
6565 }
6566
6567 pkcs7->publicKeyOID = decoded->keyOID;
6568
6569 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
6570 if (pkcs7->publicKeyOID != RSAk) {
6571 FreeDecodedCert(decoded);
6572 #ifdef WOLFSSL_SMALL_STACK
6573 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6574 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6575 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6576 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6577 #endif
6578 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6579 return ALGO_ID_E;
6580 }
6581
6582 keyEncAlgSz = SetAlgoID(pkcs7->publicKeyOID, keyAlgArray, oidKeyType, 0);
6583 if (keyEncAlgSz == 0) {
6584 FreeDecodedCert(decoded);
6585 #ifdef WOLFSSL_SMALL_STACK
6586 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6587 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6588 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6589 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6590 #endif
6591 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6592 return BAD_FUNC_ARG;
6593 }
6594
6595 #ifdef WOLFSSL_SMALL_STACK
6596 pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
6597 DYNAMIC_TYPE_TMP_BUFFER);
6598 if (pubKey == NULL) {
6599 FreeDecodedCert(decoded);
6600 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6601 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6602 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6603 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6604 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6605 return MEMORY_E;
6606 }
6607 #endif
6608
6609 /* EncryptedKey */
6610 ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, pkcs7->devId);
6611 if (ret != 0) {
6612 FreeDecodedCert(decoded);
6613 #ifdef WOLFSSL_SMALL_STACK
6614 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6615 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6616 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6617 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6618 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6619 #endif
6620 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6621 return ret;
6622 }
6623
6624 if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
6625 decoded->pubKeySize) < 0) {
6626 WOLFSSL_MSG("ASN RSA key decode error");
6627 wc_FreeRsaKey(pubKey);
6628 FreeDecodedCert(decoded);
6629 #ifdef WOLFSSL_SMALL_STACK
6630 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6631 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6632 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6633 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6634 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6635 #endif
6636 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6637 return PUBLIC_KEY_E;
6638 }
6639
6640 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
6641 if (ret != 0) {
6642 wc_FreeRsaKey(pubKey);
6643 FreeDecodedCert(decoded);
6644 #ifdef WOLFSSL_SMALL_STACK
6645 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6646 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6647 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6648 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6649 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6650 #endif
6651 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6652 return MEMORY_E;
6653 }
6654
6655
6656 #ifdef WOLFSSL_ASYNC_CRYPT
6657 /* Currently the call to RSA public encrypt here is blocking @TODO */
6658 do {
6659 ret = wc_AsyncWait(ret, &pubKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
6660 if (ret >= 0)
6661 #endif
6662 {
6663 ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey,
6664 encryptedKeySz, pubKey, &rng);
6665 }
6666 #ifdef WOLFSSL_ASYNC_CRYPT
6667 } while (ret == WC_PENDING_E);
6668 #endif
6669 wc_FreeRsaKey(pubKey);
6670 wc_FreeRng(&rng);
6671
6672 #ifdef WOLFSSL_SMALL_STACK
6673 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6674 #endif
6675
6676 if (ret < 0) {
6677 WOLFSSL_MSG("RSA Public Encrypt failed");
6678 FreeDecodedCert(decoded);
6679 #ifdef WOLFSSL_SMALL_STACK
6680 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6681 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6682 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6683 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6684 #endif
6685 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6686 return ret;
6687 }
6688 encryptedKeySz = ret;
6689
6690 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr);
6691
6692 /* RecipientInfo */
6693 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
6694 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
6695 issuerSz + snSz + keyEncAlgSz +
6696 encKeyOctetStrSz + encryptedKeySz, recipSeq);
6697
6698 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
6699 keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) {
6700 WOLFSSL_MSG("RecipientInfo output buffer too small");
6701 FreeDecodedCert(decoded);
6702 #ifdef WOLFSSL_SMALL_STACK
6703 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6704 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6705 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6706 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6707 #endif
6708 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6709 return BUFFER_E;
6710 }
6711
6712 } else {
6713 recipSeqSz = SetSequence(verSz + ASN_TAG_SZ + issuerSKIDSz +
6714 KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz +
6715 encryptedKeySz, recipSeq);
6716
6717 if (recipSeqSz + verSz + ASN_TAG_SZ + issuerSKIDSz + KEYID_SIZE +
6718 keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) {
6719 WOLFSSL_MSG("RecipientInfo output buffer too small");
6720 FreeDecodedCert(decoded);
6721 #ifdef WOLFSSL_SMALL_STACK
6722 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6723 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6724 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6725 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6726 #endif
6727 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
6728 return BUFFER_E;
6729 }
6730 }
6731
6732 idx = 0;
6733 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
6734 idx += recipSeqSz;
6735 XMEMCPY(recip->recip + idx, ver, verSz);
6736 idx += verSz;
6737 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
6738 XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz);
6739 idx += issuerSerialSeqSz;
6740 XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz);
6741 idx += issuerSeqSz;
6742 XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz);
6743 idx += issuerSz;
6744 XMEMCPY(recip->recip + idx, serial, snSz);
6745 idx += snSz;
6746 } else {
6747 recip->recip[idx] = ASN_CONTEXT_SPECIFIC;
6748 idx += ASN_TAG_SZ;
6749 XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz);
6750 idx += issuerSKIDSz;
6751 XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE);
6752 idx += KEYID_SIZE;
6753 }
6754 XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz);
6755 idx += keyEncAlgSz;
6756 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz);
6757 idx += encKeyOctetStrSz;
6758 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
6759 idx += encryptedKeySz;
6760
6761 FreeDecodedCert(decoded);
6762
6763 #ifdef WOLFSSL_SMALL_STACK
6764 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6765 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6766 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6767 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
6768 #endif
6769
6770 /* store recipient size */
6771 recip->recipSz = idx;
6772 recip->recipType = PKCS7_KTRI;
6773
6774 /* add recipient to recip list */
6775 if (pkcs7->recipList == NULL) {
6776 pkcs7->recipList = recip;
6777 } else {
6778 lastRecip = pkcs7->recipList;
6779 while (lastRecip->next != NULL) {
6780 lastRecip = lastRecip->next;
6781 }
6782 lastRecip->next = recip;
6783 }
6784
6785 return idx;
6786 }
6787
6788 #endif /* !NO_RSA */
6789
6790
6791 /* encrypt content using encryptOID algo */
wc_PKCS7_EncryptContent(int encryptOID,byte * key,int keySz,byte * iv,int ivSz,byte * aad,word32 aadSz,byte * authTag,word32 authTagSz,byte * in,int inSz,byte * out)6792 static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz,
6793 byte* iv, int ivSz, byte* aad, word32 aadSz,
6794 byte* authTag, word32 authTagSz, byte* in,
6795 int inSz, byte* out)
6796 {
6797 int ret;
6798 #ifndef NO_AES
6799 #ifdef WOLFSSL_SMALL_STACK
6800 Aes* aes;
6801 #else
6802 Aes aes[1];
6803 #endif
6804 #endif
6805 #ifndef NO_DES3
6806 Des des;
6807 Des3 des3;
6808 #endif
6809
6810 if (key == NULL || iv == NULL || in == NULL || out == NULL)
6811 return BAD_FUNC_ARG;
6812
6813 switch (encryptOID) {
6814 #ifndef NO_AES
6815 #ifdef HAVE_AES_CBC
6816 #ifdef WOLFSSL_AES_128
6817 case AES128CBCb:
6818 #endif
6819 #ifdef WOLFSSL_AES_192
6820 case AES192CBCb:
6821 #endif
6822 #ifdef WOLFSSL_AES_256
6823 case AES256CBCb:
6824 #endif
6825 if (
6826 #ifdef WOLFSSL_AES_128
6827 (encryptOID == AES128CBCb && keySz != 16 ) ||
6828 #endif
6829 #ifdef WOLFSSL_AES_192
6830 (encryptOID == AES192CBCb && keySz != 24 ) ||
6831 #endif
6832 #ifdef WOLFSSL_AES_256
6833 (encryptOID == AES256CBCb && keySz != 32 ) ||
6834 #endif
6835 (ivSz != AES_BLOCK_SIZE) )
6836 return BAD_FUNC_ARG;
6837
6838 #ifdef WOLFSSL_SMALL_STACK
6839 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
6840 DYNAMIC_TYPE_AES)) == NULL)
6841 return MEMORY_E;
6842 #endif
6843 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
6844 if (ret == 0) {
6845 ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
6846 if (ret == 0)
6847 ret = wc_AesCbcEncrypt(aes, out, in, inSz);
6848 wc_AesFree(aes);
6849 }
6850 #ifdef WOLFSSL_SMALL_STACK
6851 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
6852 #endif
6853 break;
6854 #endif /* HAVE_AES_CBC */
6855 #ifdef HAVE_AESGCM
6856 #ifdef WOLFSSL_AES_128
6857 case AES128GCMb:
6858 #endif
6859 #ifdef WOLFSSL_AES_192
6860 case AES192GCMb:
6861 #endif
6862 #ifdef WOLFSSL_AES_256
6863 case AES256GCMb:
6864 #endif
6865 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
6866 defined(WOLFSSL_AES_256)
6867 if (authTag == NULL)
6868 return BAD_FUNC_ARG;
6869
6870 #ifdef WOLFSSL_SMALL_STACK
6871 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
6872 DYNAMIC_TYPE_AES)) == NULL)
6873 return MEMORY_E;
6874 #endif
6875 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
6876 if (ret == 0) {
6877 ret = wc_AesGcmSetKey(aes, key, keySz);
6878 if (ret == 0)
6879 ret = wc_AesGcmEncrypt(aes, out, in, inSz, iv, ivSz,
6880 authTag, authTagSz, aad, aadSz);
6881 wc_AesFree(aes);
6882 }
6883 #ifdef WOLFSSL_SMALL_STACK
6884 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
6885 #endif
6886 break;
6887 #endif
6888 #endif /* HAVE_AESGCM */
6889 #ifdef HAVE_AESCCM
6890 #ifdef WOLFSSL_AES_128
6891 case AES128CCMb:
6892 #endif
6893 #ifdef WOLFSSL_AES_192
6894 case AES192CCMb:
6895 #endif
6896 #ifdef WOLFSSL_AES_256
6897 case AES256CCMb:
6898 #endif
6899 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
6900 defined(WOLFSSL_AES_256)
6901 if (authTag == NULL)
6902 return BAD_FUNC_ARG;
6903
6904 #ifdef WOLFSSL_SMALL_STACK
6905 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
6906 DYNAMIC_TYPE_AES)) == NULL)
6907 return MEMORY_E;
6908 #endif
6909 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
6910 if (ret == 0) {
6911 ret = wc_AesCcmSetKey(aes, key, keySz);
6912 if (ret == 0)
6913 ret = wc_AesCcmEncrypt(aes, out, in, inSz, iv, ivSz,
6914 authTag, authTagSz, aad, aadSz);
6915 wc_AesFree(aes);
6916 }
6917 #ifdef WOLFSSL_SMALL_STACK
6918 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
6919 #endif
6920 break;
6921 #endif
6922 #endif /* HAVE_AESCCM */
6923 #endif /* !NO_AES */
6924 #ifndef NO_DES3
6925 case DESb:
6926 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
6927 return BAD_FUNC_ARG;
6928
6929 ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION);
6930 if (ret == 0)
6931 ret = wc_Des_CbcEncrypt(&des, out, in, inSz);
6932
6933 break;
6934
6935 case DES3b:
6936 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
6937 return BAD_FUNC_ARG;
6938
6939 ret = wc_Des3Init(&des3, NULL, INVALID_DEVID);
6940 if (ret == 0) {
6941 ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION);
6942 if (ret == 0)
6943 ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz);
6944 wc_Des3Free(&des3);
6945 }
6946 break;
6947 #endif /* !NO_DES3 */
6948 default:
6949 WOLFSSL_MSG("Unsupported content cipher type");
6950 return ALGO_ID_E;
6951 };
6952
6953 #if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM))
6954 (void)authTag;
6955 (void)authTagSz;
6956 (void)aad;
6957 (void)aadSz;
6958 #endif
6959 return ret;
6960 }
6961
6962
6963 /* decrypt content using encryptOID algo
6964 * returns 0 on success */
wc_PKCS7_DecryptContent(PKCS7 * pkcs7,int encryptOID,byte * key,int keySz,byte * iv,int ivSz,byte * aad,word32 aadSz,byte * authTag,word32 authTagSz,byte * in,int inSz,byte * out)6965 static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key,
6966 int keySz, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag,
6967 word32 authTagSz, byte* in, int inSz, byte* out)
6968 {
6969 int ret;
6970 #ifndef NO_AES
6971 #ifdef WOLFSSL_SMALL_STACK
6972 Aes *aes;
6973 #else
6974 Aes aes[1];
6975 #endif
6976 #endif
6977 #ifndef NO_DES3
6978 Des des;
6979 Des3 des3;
6980 #endif
6981
6982 if (iv == NULL || in == NULL || out == NULL)
6983 return BAD_FUNC_ARG;
6984
6985 if (pkcs7->decryptionCb != NULL) {
6986 return pkcs7->decryptionCb(pkcs7, encryptOID, iv, ivSz,
6987 aad, aadSz, authTag, authTagSz, in,
6988 inSz, out, pkcs7->decryptionCtx);
6989 }
6990
6991 if (key == NULL)
6992 return BAD_FUNC_ARG;
6993
6994 switch (encryptOID) {
6995 #ifndef NO_AES
6996 #ifdef HAVE_AES_CBC
6997 #ifdef WOLFSSL_AES_128
6998 case AES128CBCb:
6999 #endif
7000 #ifdef WOLFSSL_AES_192
7001 case AES192CBCb:
7002 #endif
7003 #ifdef WOLFSSL_AES_256
7004 case AES256CBCb:
7005 #endif
7006 if (
7007 #ifdef WOLFSSL_AES_128
7008 (encryptOID == AES128CBCb && keySz != 16 ) ||
7009 #endif
7010 #ifdef WOLFSSL_AES_192
7011 (encryptOID == AES192CBCb && keySz != 24 ) ||
7012 #endif
7013 #ifdef WOLFSSL_AES_256
7014 (encryptOID == AES256CBCb && keySz != 32 ) ||
7015 #endif
7016 (ivSz != AES_BLOCK_SIZE) )
7017 return BAD_FUNC_ARG;
7018 #ifdef WOLFSSL_SMALL_STACK
7019 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
7020 DYNAMIC_TYPE_AES)) == NULL)
7021 return MEMORY_E;
7022 #endif
7023 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
7024 if (ret == 0) {
7025 ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION);
7026 if (ret == 0)
7027 ret = wc_AesCbcDecrypt(aes, out, in, inSz);
7028 wc_AesFree(aes);
7029 }
7030 #ifdef WOLFSSL_SMALL_STACK
7031 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
7032 #endif
7033 break;
7034 #endif /* HAVE_AES_CBC */
7035 #ifdef HAVE_AESGCM
7036 #ifdef WOLFSSL_AES_128
7037 case AES128GCMb:
7038 #endif
7039 #ifdef WOLFSSL_AES_192
7040 case AES192GCMb:
7041 #endif
7042 #ifdef WOLFSSL_AES_256
7043 case AES256GCMb:
7044 #endif
7045 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
7046 defined(WOLFSSL_AES_256)
7047 if (authTag == NULL)
7048 return BAD_FUNC_ARG;
7049
7050 #ifdef WOLFSSL_SMALL_STACK
7051 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
7052 DYNAMIC_TYPE_AES)) == NULL)
7053 return MEMORY_E;
7054 #endif
7055 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
7056 if (ret == 0) {
7057 ret = wc_AesGcmSetKey(aes, key, keySz);
7058 if (ret == 0)
7059 ret = wc_AesGcmDecrypt(aes, out, in, inSz, iv, ivSz,
7060 authTag, authTagSz, aad, aadSz);
7061 wc_AesFree(aes);
7062 }
7063 #ifdef WOLFSSL_SMALL_STACK
7064 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
7065 #endif
7066 break;
7067 #endif
7068 #endif /* HAVE_AESGCM */
7069 #ifdef HAVE_AESCCM
7070 #ifdef WOLFSSL_AES_128
7071 case AES128CCMb:
7072 #endif
7073 #ifdef WOLFSSL_AES_192
7074 case AES192CCMb:
7075 #endif
7076 #ifdef WOLFSSL_AES_256
7077 case AES256CCMb:
7078 #endif
7079 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
7080 defined(WOLFSSL_AES_256)
7081 if (authTag == NULL)
7082 return BAD_FUNC_ARG;
7083
7084 #ifdef WOLFSSL_SMALL_STACK
7085 if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
7086 DYNAMIC_TYPE_AES)) == NULL)
7087 return MEMORY_E;
7088 #endif
7089 ret = wc_AesInit(aes, NULL, INVALID_DEVID);
7090 if (ret == 0) {
7091 ret = wc_AesCcmSetKey(aes, key, keySz);
7092 if (ret == 0)
7093 ret = wc_AesCcmDecrypt(aes, out, in, inSz, iv, ivSz,
7094 authTag, authTagSz, aad, aadSz);
7095 wc_AesFree(aes);
7096 }
7097 #ifdef WOLFSSL_SMALL_STACK
7098 XFREE(aes, NULL, DYNAMIC_TYPE_AES);
7099 #endif
7100 break;
7101 #endif
7102 #endif /* HAVE_AESCCM */
7103 #endif /* !NO_AES */
7104 #ifndef NO_DES3
7105 case DESb:
7106 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
7107 return BAD_FUNC_ARG;
7108
7109 ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION);
7110 if (ret == 0)
7111 ret = wc_Des_CbcDecrypt(&des, out, in, inSz);
7112
7113 break;
7114 case DES3b:
7115 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
7116 return BAD_FUNC_ARG;
7117
7118 ret = wc_Des3Init(&des3, NULL, INVALID_DEVID);
7119 if (ret == 0) {
7120 ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION);
7121 if (ret == 0)
7122 ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz);
7123 wc_Des3Free(&des3);
7124 }
7125
7126 break;
7127 #endif /* !NO_DES3 */
7128 default:
7129 WOLFSSL_MSG("Unsupported content cipher type");
7130 return ALGO_ID_E;
7131 };
7132
7133 #if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM))
7134 (void)authTag;
7135 (void)authTagSz;
7136 (void)aad;
7137 (void)aadSz;
7138 #endif
7139
7140 return ret;
7141 }
7142
7143
7144 /* Generate random block, place in out, return 0 on success negative on error.
7145 * Used for generation of IV, nonce, etc */
wc_PKCS7_GenerateBlock(PKCS7 * pkcs7,WC_RNG * rng,byte * out,word32 outSz)7146 static int wc_PKCS7_GenerateBlock(PKCS7* pkcs7, WC_RNG* rng, byte* out,
7147 word32 outSz)
7148 {
7149 int ret;
7150 WC_RNG* rnd = NULL;
7151
7152 if (out == NULL || outSz == 0)
7153 return BAD_FUNC_ARG;
7154
7155 /* input RNG is optional, init local one if input rng is NULL */
7156 if (rng == NULL) {
7157 rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG);
7158 if (rnd == NULL)
7159 return MEMORY_E;
7160
7161 ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId);
7162 if (ret != 0) {
7163 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
7164 return ret;
7165 }
7166
7167 } else {
7168 rnd = rng;
7169 }
7170
7171 ret = wc_RNG_GenerateBlock(rnd, out, outSz);
7172
7173 if (rng == NULL) {
7174 wc_FreeRng(rnd);
7175 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
7176 }
7177
7178 return ret;
7179 }
7180
7181
7182 /* Set default SignerIdentifier type to be used. Is either
7183 * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using
7184 * IssuerAndSerialNumber unless set with this function or explicitly
7185 * overridden via options when adding RecipientInfo type.
7186 *
7187 * Using the type DEGENERATE_SID skips over signer information. In degenerate
7188 * cases there are no signers.
7189 *
7190 * pkcs7 - pointer to initialized PKCS7 structure
7191 * type - either CMS_ISSUER_AND_SERIAL_NUMBER, CMS_SKID or DEGENERATE_SID
7192 *
7193 * return 0 on success, negative upon error */
wc_PKCS7_SetSignerIdentifierType(PKCS7 * pkcs7,int type)7194 int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type)
7195 {
7196 if (pkcs7 == NULL)
7197 return BAD_FUNC_ARG;
7198
7199 if (type != CMS_ISSUER_AND_SERIAL_NUMBER &&
7200 type != CMS_SKID &&
7201 type != DEGENERATE_SID) {
7202 return BAD_FUNC_ARG;
7203 }
7204
7205 pkcs7->sidType = type;
7206
7207 return 0;
7208 }
7209
7210
7211 /* Set custom contentType, currently supported with SignedData type
7212 *
7213 * pkcs7 - pointer to initialized PKCS7 structure
7214 * contentType - pointer to array with ASN.1 encoded OID value
7215 * sz - length of contentType array, octets
7216 *
7217 * return 0 on success, negative upon error */
wc_PKCS7_SetContentType(PKCS7 * pkcs7,byte * contentType,word32 sz)7218 int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz)
7219 {
7220 if (pkcs7 == NULL || contentType == NULL || sz == 0)
7221 return BAD_FUNC_ARG;
7222
7223 if (sz > MAX_OID_SZ) {
7224 WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ");
7225 return BAD_FUNC_ARG;
7226 }
7227
7228 XMEMCPY(pkcs7->contentType, contentType, sz);
7229 pkcs7->contentTypeSz = sz;
7230
7231 return 0;
7232 }
7233
7234
7235 /* return size of padded data, padded to blockSz chunks, or negative on error */
wc_PKCS7_GetPadSize(word32 inputSz,word32 blockSz)7236 int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
7237 {
7238 int padSz;
7239
7240 if (blockSz == 0)
7241 return BAD_FUNC_ARG;
7242
7243 padSz = blockSz - (inputSz % blockSz);
7244
7245 return padSz;
7246 }
7247
7248
7249 /* pad input data to blockSz chunk, place in outSz. out must be big enough
7250 * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */
wc_PKCS7_PadData(byte * in,word32 inSz,byte * out,word32 outSz,word32 blockSz)7251 int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
7252 word32 blockSz)
7253 {
7254 int i, padSz;
7255
7256 if (in == NULL || inSz == 0 ||
7257 out == NULL || outSz == 0)
7258 return BAD_FUNC_ARG;
7259
7260 padSz = wc_PKCS7_GetPadSize(inSz, blockSz);
7261
7262 if (outSz < (inSz + padSz))
7263 return BAD_FUNC_ARG;
7264
7265 XMEMCPY(out, in, inSz);
7266
7267 for (i = 0; i < padSz; i++) {
7268 out[inSz + i] = (byte)padSz;
7269 }
7270
7271 return inSz + padSz;
7272 }
7273
7274
7275 /* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo
7276 * to CMS/PKCS#7 EnvelopedData structure.
7277 *
7278 * Return 0 on success, negative upon error */
wc_PKCS7_AddRecipient_ORI(PKCS7 * pkcs7,CallbackOriEncrypt oriEncryptCb,int options)7279 int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb,
7280 int options)
7281 {
7282 int oriTypeLenSz, blockKeySz, ret;
7283 word32 idx, recipSeqSz;
7284
7285 Pkcs7EncodedRecip* recip = NULL;
7286 Pkcs7EncodedRecip* lastRecip = NULL;
7287
7288 byte recipSeq[MAX_SEQ_SZ];
7289 byte oriTypeLen[MAX_LENGTH_SZ];
7290
7291 byte oriType[MAX_ORI_TYPE_SZ];
7292 byte oriValue[MAX_ORI_VALUE_SZ];
7293 word32 oriTypeSz = MAX_ORI_TYPE_SZ;
7294 word32 oriValueSz = MAX_ORI_VALUE_SZ;
7295
7296 if (pkcs7 == NULL || oriEncryptCb == NULL) {
7297 return BAD_FUNC_ARG;
7298 }
7299
7300 /* allocate memory for RecipientInfo, KEK, encrypted key */
7301 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip),
7302 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7303 if (recip == NULL)
7304 return MEMORY_E;
7305 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
7306
7307 /* get key size for content-encryption key based on algorithm */
7308 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
7309 if (blockKeySz < 0) {
7310 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7311 return blockKeySz;
7312 }
7313
7314 /* generate random content encryption key, if needed */
7315 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
7316 if (ret < 0) {
7317 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7318 return ret;
7319 }
7320
7321 /* call user callback to encrypt CEK and get oriType and oriValue
7322 values back */
7323 ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz,
7324 oriValue, &oriValueSz, pkcs7->oriEncryptCtx);
7325 if (ret != 0) {
7326 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7327 return ret;
7328 }
7329
7330 oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen);
7331
7332 recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz +
7333 oriValueSz, recipSeq);
7334
7335 idx = 0;
7336 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
7337 idx += recipSeqSz;
7338 /* oriType */
7339 recip->recip[idx] = ASN_OBJECT_ID;
7340 idx += 1;
7341 XMEMCPY(recip->recip + idx, oriTypeLen, oriTypeLenSz);
7342 idx += oriTypeLenSz;
7343 XMEMCPY(recip->recip + idx, oriType, oriTypeSz);
7344 idx += oriTypeSz;
7345 /* oriValue, input MUST already be ASN.1 encoded */
7346 XMEMCPY(recip->recip + idx, oriValue, oriValueSz);
7347 idx += oriValueSz;
7348
7349 /* store recipient size */
7350 recip->recipSz = idx;
7351 recip->recipType = PKCS7_ORI;
7352 recip->recipVersion = 4;
7353
7354 /* add recipient to recip list */
7355 if (pkcs7->recipList == NULL) {
7356 pkcs7->recipList = recip;
7357 } else {
7358 lastRecip = pkcs7->recipList;
7359 while (lastRecip->next != NULL) {
7360 lastRecip = lastRecip->next;
7361 }
7362 lastRecip->next = recip;
7363 }
7364
7365 (void)options;
7366
7367 return idx;
7368 }
7369
7370 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
7371
7372
wc_PKCS7_GenerateKEK_PWRI(PKCS7 * pkcs7,byte * passwd,word32 pLen,byte * salt,word32 saltSz,int kdfOID,int prfOID,int iterations,byte * out,word32 outSz)7373 static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen,
7374 byte* salt, word32 saltSz, int kdfOID,
7375 int prfOID, int iterations, byte* out,
7376 word32 outSz)
7377 {
7378 int ret;
7379
7380 if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL)
7381 return BAD_FUNC_ARG;
7382
7383 switch (kdfOID) {
7384
7385 case PBKDF2_OID:
7386
7387 ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations,
7388 outSz, prfOID);
7389 if (ret != 0) {
7390 return ret;
7391 }
7392
7393 break;
7394
7395 default:
7396 WOLFSSL_MSG("Unsupported KDF OID");
7397 return PKCS7_OID_E;
7398 }
7399
7400 return 0;
7401 }
7402
7403
7404 /* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK).
7405 *
7406 * Returns output size on success, negative upon error */
wc_PKCS7_PwriKek_KeyWrap(PKCS7 * pkcs7,const byte * kek,word32 kekSz,const byte * cek,word32 cekSz,byte * out,word32 * outSz,const byte * iv,word32 ivSz,int algID)7407 static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz,
7408 const byte* cek, word32 cekSz,
7409 byte* out, word32 *outSz,
7410 const byte* iv, word32 ivSz, int algID)
7411 {
7412 WC_RNG rng;
7413 int blockSz, outLen, ret;
7414 word32 padSz;
7415 byte* lastBlock;
7416
7417 if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL)
7418 return BAD_FUNC_ARG;
7419
7420 /* get encryption algorithm block size */
7421 blockSz = wc_PKCS7_GetOIDBlockSize(algID);
7422 if (blockSz < 0)
7423 return blockSz;
7424
7425 /* get pad bytes needed to block boundary */
7426 padSz = blockSz - ((4 + cekSz) % blockSz);
7427 outLen = 4 + cekSz + padSz;
7428
7429 /* must be at least two blocks long */
7430 if (outLen < 2 * blockSz)
7431 padSz += blockSz;
7432
7433 /* if user set out to NULL, give back required length */
7434 if (out == NULL) {
7435 *outSz = outLen;
7436 return LENGTH_ONLY_E;
7437 }
7438
7439 /* verify output buffer is large enough */
7440 if (*outSz < (word32)outLen)
7441 return BUFFER_E;
7442
7443 out[0] = cekSz;
7444 out[1] = ~cek[0];
7445 out[2] = ~cek[1];
7446 out[3] = ~cek[2];
7447 XMEMCPY(out + 4, cek, cekSz);
7448
7449 /* random padding of size padSz */
7450 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
7451 if (ret != 0)
7452 return ret;
7453
7454 ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz);
7455
7456 if (ret == 0) {
7457 /* encrypt, normal */
7458 ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv,
7459 ivSz, NULL, 0, NULL, 0, out, outLen, out);
7460 }
7461
7462 if (ret == 0) {
7463 /* encrypt again, using last ciphertext block as IV */
7464 lastBlock = out + (((outLen / blockSz) - 1) * blockSz);
7465 ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock,
7466 blockSz, NULL, 0, NULL, 0, out,
7467 outLen, out);
7468 }
7469
7470 if (ret == 0) {
7471 *outSz = outLen;
7472 } else {
7473 outLen = ret;
7474 }
7475
7476 wc_FreeRng(&rng);
7477
7478 return outLen;
7479 }
7480
7481
7482 /* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK).
7483 *
7484 * Returns cek size on success, negative upon error */
wc_PKCS7_PwriKek_KeyUnWrap(PKCS7 * pkcs7,const byte * kek,word32 kekSz,const byte * in,word32 inSz,byte * out,word32 outSz,const byte * iv,word32 ivSz,int algID)7485 static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek,
7486 word32 kekSz, const byte* in, word32 inSz,
7487 byte* out, word32 outSz, const byte* iv,
7488 word32 ivSz, int algID)
7489 {
7490 int blockSz, cekLen, ret;
7491 byte* tmpIv = NULL;
7492 byte* lastBlock = NULL;
7493 byte* outTmp = NULL;
7494
7495 if (pkcs7 == NULL || kek == NULL || in == NULL ||
7496 out == NULL || iv == NULL) {
7497 return BAD_FUNC_ARG;
7498 }
7499
7500 outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7501 if (outTmp == NULL)
7502 return MEMORY_E;
7503
7504 /* get encryption algorithm block size */
7505 blockSz = wc_PKCS7_GetOIDBlockSize(algID);
7506 if (blockSz < 0) {
7507 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7508 return blockSz;
7509 }
7510
7511 /* input needs to be blockSz multiple and at least 2 * blockSz */
7512 if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) {
7513 WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 "
7514 "times block size");
7515 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7516 return BAD_FUNC_ARG;
7517 }
7518
7519 /* use block out[n-1] as IV to decrypt block out[n] */
7520 lastBlock = (byte*)in + inSz - blockSz;
7521 tmpIv = lastBlock - blockSz;
7522
7523 /* decrypt last block */
7524 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, tmpIv,
7525 blockSz, NULL, 0, NULL, 0, lastBlock, blockSz,
7526 outTmp + inSz - blockSz);
7527
7528 if (ret == 0) {
7529 /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */
7530 lastBlock = outTmp + inSz - blockSz;
7531 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz,
7532 lastBlock, blockSz, NULL, 0, NULL, 0, (byte*)in, inSz - blockSz,
7533 outTmp);
7534 }
7535
7536 if (ret == 0) {
7537 /* decrypt using original kek and iv */
7538 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz,
7539 (byte*)iv, ivSz, NULL, 0, NULL, 0, outTmp, inSz, outTmp);
7540 }
7541
7542 if (ret != 0) {
7543 ForceZero(outTmp, inSz);
7544 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7545 return ret;
7546 }
7547
7548 cekLen = outTmp[0];
7549
7550 /* verify length */
7551 if ((word32)cekLen > inSz) {
7552 ForceZero(outTmp, inSz);
7553 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7554 return BAD_FUNC_ARG;
7555 }
7556
7557 /* verify check bytes */
7558 if ((outTmp[1] ^ outTmp[4]) != 0xFF ||
7559 (outTmp[2] ^ outTmp[5]) != 0xFF ||
7560 (outTmp[3] ^ outTmp[6]) != 0xFF) {
7561 ForceZero(outTmp, inSz);
7562 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7563 return BAD_FUNC_ARG;
7564 }
7565
7566 if (outSz < (word32)cekLen) {
7567 ForceZero(outTmp, inSz);
7568 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7569 return BUFFER_E;
7570 }
7571
7572 XMEMCPY(out, outTmp + 4, outTmp[0]);
7573 ForceZero(outTmp, inSz);
7574 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
7575
7576 return cekLen;
7577 }
7578
7579
7580 /* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo
7581 * to CMS/PKCS#7 EnvelopedData structure.
7582 *
7583 * Return 0 on success, negative upon error */
wc_PKCS7_AddRecipient_PWRI(PKCS7 * pkcs7,byte * passwd,word32 pLen,byte * salt,word32 saltSz,int kdfOID,int hashOID,int iterations,int kekEncryptOID,int options)7584 int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen,
7585 byte* salt, word32 saltSz, int kdfOID,
7586 int hashOID, int iterations, int kekEncryptOID,
7587 int options)
7588 {
7589 Pkcs7EncodedRecip* recip = NULL;
7590 Pkcs7EncodedRecip* lastRecip = NULL;
7591
7592 /* PasswordRecipientInfo */
7593 byte recipSeq[MAX_SEQ_SZ];
7594 byte ver[MAX_VERSION_SZ];
7595 word32 recipSeqSz, verSz;
7596
7597 /* KeyDerivationAlgorithmIdentifier */
7598 byte kdfAlgoIdSeq[MAX_SEQ_SZ];
7599 byte kdfAlgoId[MAX_OID_SZ];
7600 byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */
7601 byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */
7602 byte kdfIterations[MAX_VERSION_SZ];
7603 word32 kdfAlgoIdSeqSz, kdfAlgoIdSz;
7604 word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz;
7605 /* OPTIONAL: keyLength, not supported yet */
7606 /* OPTIONAL: prf AlgorithmIdentifier, not supported yet */
7607
7608 /* KeyEncryptionAlgorithmIdentifier */
7609 byte keyEncAlgoIdSeq[MAX_SEQ_SZ];
7610 byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */
7611 byte pwriEncAlgoId[MAX_ALGO_SZ];
7612 byte ivOctetString[MAX_OCTET_STR_SZ];
7613 word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz;
7614 word32 pwriEncAlgoIdSz, ivOctetStringSz;
7615
7616 /* EncryptedKey */
7617 byte encKeyOctetStr[MAX_OCTET_STR_SZ];
7618 word32 encKeyOctetStrSz;
7619
7620 byte tmpIv[MAX_CONTENT_IV_SIZE];
7621 byte* encryptedKey = NULL;
7622 byte* kek = NULL;
7623
7624 int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0;
7625 int encryptOID;
7626 word32 idx, totalSz = 0, encryptedKeySz;
7627
7628 if (pkcs7 == NULL || passwd == NULL || pLen == 0 ||
7629 salt == NULL || saltSz == 0) {
7630 return BAD_FUNC_ARG;
7631 }
7632
7633 /* allow user to use different KEK encryption algorithm than used for
7634 * main content encryption algorithm, if passed in */
7635 if (kekEncryptOID != 0) {
7636 encryptOID = kekEncryptOID;
7637 } else {
7638 encryptOID = pkcs7->encryptOID;
7639 }
7640
7641 /* get content-encryption key size, based on algorithm */
7642 cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
7643 if (cekKeySz < 0)
7644 return cekKeySz;
7645
7646 /* get KEK encryption key size, based on algorithm */
7647 if (encryptOID != pkcs7->encryptOID) {
7648 kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID);
7649 } else {
7650 kekKeySz = cekKeySz;
7651 }
7652
7653 /* get KEK encryption block size */
7654 kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID);
7655 if (kekBlockSz < 0)
7656 return kekBlockSz;
7657
7658 /* generate random CEK */
7659 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz);
7660 if (ret < 0)
7661 return ret;
7662
7663 /* generate random IV */
7664 ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz);
7665 if (ret != 0)
7666 return ret;
7667
7668 /* allocate memory for RecipientInfo, KEK, encrypted key */
7669 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip),
7670 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7671 if (recip == NULL)
7672 return MEMORY_E;
7673
7674 kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7675 if (kek == NULL) {
7676 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7677 return MEMORY_E;
7678 }
7679
7680 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ,
7681 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7682 if (encryptedKey == NULL) {
7683 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7684 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7685 return MEMORY_E;
7686 }
7687
7688 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
7689 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
7690 XMEMSET(kek, 0, kekKeySz);
7691 XMEMSET(encryptedKey, 0, encryptedKeySz);
7692
7693 /* generate KEK: expand password into KEK */
7694 ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz,
7695 kdfOID, hashOID, iterations, kek,
7696 kekKeySz);
7697 if (ret < 0) {
7698 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7699 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7700 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7701 return ret;
7702 }
7703
7704 /* generate encrypted key: encrypt CEK with KEK */
7705 ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek,
7706 pkcs7->cekSz, encryptedKey, &encryptedKeySz,
7707 tmpIv, kekBlockSz, encryptOID);
7708 if (ret < 0) {
7709 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7710 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7711 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7712 return ret;
7713 }
7714 encryptedKeySz = ret;
7715
7716 /* put together encrypted key OCTET STRING */
7717 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr);
7718 totalSz += (encKeyOctetStrSz + encryptedKeySz);
7719
7720 /* put together IV OCTET STRING */
7721 ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString);
7722 totalSz += (ivOctetStringSz + kekBlockSz);
7723
7724 /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz +
7725 blockKeySz) for IV OCTET STRING */
7726 pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId,
7727 oidBlkType, ivOctetStringSz + kekBlockSz);
7728 totalSz += pwriEncAlgoIdSz;
7729
7730 /* set KeyEncryptionAlgorithms OID */
7731 ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId));
7732 if (ret <= 0) {
7733 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7734 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7735 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7736 return ret;
7737 }
7738 keyEncAlgoIdSz = ret;
7739 totalSz += keyEncAlgoIdSz;
7740
7741 /* KeyEncryptionAlgorithm SEQ */
7742 keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz +
7743 ivOctetStringSz + kekBlockSz,
7744 keyEncAlgoIdSeq);
7745 totalSz += keyEncAlgoIdSeqSz;
7746
7747 /* set KDF salt */
7748 kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr);
7749 totalSz += (kdfSaltOctetStrSz + saltSz);
7750
7751 /* set KDF iteration count */
7752 kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0);
7753 totalSz += kdfIterationsSz;
7754
7755 /* set KDF params SEQ */
7756 kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz,
7757 kdfParamsSeq);
7758 totalSz += kdfParamsSeqSz;
7759
7760 /* set KDF algo OID */
7761 ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId));
7762 if (ret <= 0) {
7763 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7764 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7765 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7766 return ret;
7767 }
7768 kdfAlgoIdSz = ret;
7769 totalSz += kdfAlgoIdSz;
7770
7771 /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */
7772 kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz +
7773 kdfSaltOctetStrSz + saltSz + kdfIterationsSz,
7774 kdfAlgoIdSeq);
7775 totalSz += kdfAlgoIdSeqSz;
7776
7777 /* set PasswordRecipientInfo CMSVersion, MUST be 0 */
7778 verSz = SetMyVersion(0, ver, 0);
7779 totalSz += verSz;
7780 recip->recipVersion = 0;
7781
7782 /* set PasswordRecipientInfo SEQ */
7783 recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq);
7784 totalSz += recipSeqSz;
7785
7786 if (totalSz > MAX_RECIP_SZ) {
7787 WOLFSSL_MSG("CMS Recipient output buffer too small");
7788 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7789 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7790 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7791 return BUFFER_E;
7792 }
7793
7794 idx = 0;
7795 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
7796 idx += recipSeqSz;
7797 XMEMCPY(recip->recip + idx, ver, verSz);
7798 idx += verSz;
7799 XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz);
7800 idx += kdfAlgoIdSeqSz;
7801 XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz);
7802 idx += kdfAlgoIdSz;
7803 XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz);
7804 idx += kdfParamsSeqSz;
7805 XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz);
7806 idx += kdfSaltOctetStrSz;
7807 XMEMCPY(recip->recip + idx, salt, saltSz);
7808 idx += saltSz;
7809 XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz);
7810 idx += kdfIterationsSz;
7811 XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz);
7812 idx += keyEncAlgoIdSeqSz;
7813 XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz);
7814 idx += keyEncAlgoIdSz;
7815 XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz);
7816 idx += pwriEncAlgoIdSz;
7817 XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz);
7818 idx += ivOctetStringSz;
7819 XMEMCPY(recip->recip + idx, tmpIv, kekBlockSz);
7820 idx += kekBlockSz;
7821 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz);
7822 idx += encKeyOctetStrSz;
7823 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
7824 idx += encryptedKeySz;
7825
7826 ForceZero(kek, kekBlockSz);
7827 ForceZero(encryptedKey, encryptedKeySz);
7828 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7829 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7830
7831 /* store recipient size */
7832 recip->recipSz = idx;
7833 recip->recipType = PKCS7_PWRI;
7834
7835 /* add recipient to recip list */
7836 if (pkcs7->recipList == NULL) {
7837 pkcs7->recipList = recip;
7838 } else {
7839 lastRecip = pkcs7->recipList;
7840 while (lastRecip->next != NULL) {
7841 lastRecip = lastRecip->next;
7842 }
7843 lastRecip->next = recip;
7844 }
7845
7846 (void)options;
7847
7848 return idx;
7849 }
7850
7851 /* Import password and KDF settings into a PKCS7 structure. Used for setting
7852 * the password info for decryption a EnvelopedData PWRI RecipientInfo.
7853 *
7854 * Returns 0 on success, negative upon error */
wc_PKCS7_SetPassword(PKCS7 * pkcs7,byte * passwd,word32 pLen)7855 int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen)
7856 {
7857 if (pkcs7 == NULL || passwd == NULL || pLen == 0)
7858 return BAD_FUNC_ARG;
7859
7860 pkcs7->pass = passwd;
7861 pkcs7->passSz = pLen;
7862
7863 return 0;
7864 }
7865
7866 #endif /* NO_PWDBASED */
7867
7868
7869 /* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo
7870 * to CMS/PKCS#7 EnvelopedData structure.
7871 *
7872 * pkcs7 - pointer to initialized PKCS7 structure
7873 * keyWrapOID - OID sum of key wrap algorithm identifier
7874 * kek - key encryption key
7875 * kekSz - size of kek, bytes
7876 * keyID - key-encryption key identifier, pre-distributed to endpoints
7877 * keyIDSz - size of keyID, bytes
7878 * timePtr - pointer to "time_t", which is typically "long" (OPTIONAL)
7879 * otherOID - ASN.1 encoded OID of other attribute (OPTIONAL)
7880 * otherOIDSz - size of otherOID, bytes (OPTIONAL)
7881 * other - other attribute (OPTIONAL)
7882 * otherSz - size of other (OPTIONAL)
7883 *
7884 * Returns 0 on success, negative upon error */
wc_PKCS7_AddRecipient_KEKRI(PKCS7 * pkcs7,int keyWrapOID,byte * kek,word32 kekSz,byte * keyId,word32 keyIdSz,void * timePtr,byte * otherOID,word32 otherOIDSz,byte * other,word32 otherSz,int options)7885 int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek,
7886 word32 kekSz, byte* keyId, word32 keyIdSz,
7887 void* timePtr, byte* otherOID,
7888 word32 otherOIDSz, byte* other, word32 otherSz,
7889 int options)
7890 {
7891 Pkcs7EncodedRecip* recip = NULL;
7892 Pkcs7EncodedRecip* lastRecip = NULL;
7893
7894 byte recipSeq[MAX_SEQ_SZ];
7895 byte ver[MAX_VERSION_SZ];
7896 byte kekIdSeq[MAX_SEQ_SZ];
7897 byte kekIdOctetStr[MAX_OCTET_STR_SZ];
7898 byte genTime[ASN_GENERALIZED_TIME_SIZE];
7899 byte otherAttSeq[MAX_SEQ_SZ];
7900 byte encAlgoId[MAX_ALGO_SZ];
7901 byte encKeyOctetStr[MAX_OCTET_STR_SZ];
7902 #ifdef WOLFSSL_SMALL_STACK
7903 byte* encryptedKey;
7904 #else
7905 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
7906 #endif
7907
7908 int blockKeySz = 0, ret = 0, direction;
7909 word32 idx = 0;
7910 word32 totalSz = 0;
7911 word32 recipSeqSz = 0, verSz = 0;
7912 word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0;
7913 word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0;
7914 int encryptedKeySz;
7915
7916 int timeSz = 0;
7917 #ifndef NO_ASN_TIME
7918 time_t* tm = NULL;
7919 #endif
7920
7921 if (pkcs7 == NULL || kek == NULL || keyId == NULL)
7922 return BAD_FUNC_ARG;
7923
7924 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
7925 DYNAMIC_TYPE_PKCS7);
7926 if (recip == NULL)
7927 return MEMORY_E;
7928
7929 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
7930
7931 /* get key size for content-encryption key based on algorithm */
7932 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
7933 if (blockKeySz < 0) {
7934 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7935 return blockKeySz;
7936 }
7937
7938 /* generate random content encryption key, if needed */
7939 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
7940 if (ret < 0) {
7941 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7942 return ret;
7943 }
7944
7945 /* EncryptedKey */
7946 #ifdef WOLFSSL_SMALL_STACK
7947 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
7948 DYNAMIC_TYPE_PKCS7);
7949 if (encryptedKey == NULL) {
7950 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7951 return MEMORY_E;
7952 }
7953 #endif
7954 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
7955 XMEMSET(encryptedKey, 0, encryptedKeySz);
7956
7957 #ifndef NO_AES
7958 direction = AES_ENCRYPTION;
7959 #else
7960 direction = DES_ENCRYPTION;
7961 #endif
7962
7963 encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz,
7964 encryptedKey, encryptedKeySz, keyWrapOID,
7965 direction);
7966 if (encryptedKeySz < 0) {
7967 #ifdef WOLFSSL_SMALL_STACK
7968 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7969 #endif
7970 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7971 return encryptedKeySz;
7972 }
7973 /* handle a zero size encKey case as WC_KEY_SIZE_E */
7974 if (encryptedKeySz == 0 || encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) {
7975 #ifdef WOLFSSL_SMALL_STACK
7976 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7977 #endif
7978 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
7979 return WC_KEY_SIZE_E;
7980 }
7981
7982 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr);
7983 totalSz += (encKeyOctetStrSz + encryptedKeySz);
7984
7985 /* KeyEncryptionAlgorithmIdentifier */
7986 encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0);
7987 totalSz += encAlgoIdSz;
7988
7989 /* KEKIdentifier: keyIdentifier */
7990 kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr);
7991 totalSz += (kekIdOctetStrSz + keyIdSz);
7992
7993 /* KEKIdentifier: GeneralizedTime (OPTIONAL) */
7994 #ifndef NO_ASN_TIME
7995 if (timePtr != NULL) {
7996 tm = (time_t*)timePtr;
7997 timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime));
7998 if (timeSz < 0) {
7999 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8000 #ifdef WOLFSSL_SMALL_STACK
8001 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8002 #endif
8003 return timeSz;
8004 }
8005 totalSz += timeSz;
8006 }
8007 #endif
8008
8009 /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */
8010 if (other != NULL && otherSz > 0) {
8011 otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq);
8012 totalSz += otherAttSeqSz + otherOIDSz + otherSz;
8013 }
8014
8015 /* KEKIdentifier SEQ */
8016 kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + timeSz +
8017 otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq);
8018 totalSz += kekIdSeqSz;
8019
8020 /* version */
8021 verSz = SetMyVersion(4, ver, 0);
8022 totalSz += verSz;
8023 recip->recipVersion = 4;
8024
8025 /* KEKRecipientInfo SEQ */
8026 recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq);
8027 totalSz += recipSeqSz;
8028
8029 if (totalSz > MAX_RECIP_SZ) {
8030 WOLFSSL_MSG("CMS Recipient output buffer too small");
8031 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8032 #ifdef WOLFSSL_SMALL_STACK
8033 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8034 #endif
8035 return BUFFER_E;
8036 }
8037
8038 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
8039 idx += recipSeqSz;
8040 XMEMCPY(recip->recip + idx, ver, verSz);
8041 idx += verSz;
8042 XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz);
8043 idx += kekIdSeqSz;
8044 XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz);
8045 idx += kekIdOctetStrSz;
8046 XMEMCPY(recip->recip + idx, keyId, keyIdSz);
8047 idx += keyIdSz;
8048 if (timePtr != NULL) {
8049 XMEMCPY(recip->recip + idx, genTime, timeSz);
8050 idx += timeSz;
8051 }
8052 if (other != NULL && otherSz > 0) {
8053 XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz);
8054 idx += otherAttSeqSz;
8055 XMEMCPY(recip->recip + idx, otherOID, otherOIDSz);
8056 idx += otherOIDSz;
8057 XMEMCPY(recip->recip + idx, other, otherSz);
8058 idx += otherSz;
8059 }
8060 XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz);
8061 idx += encAlgoIdSz;
8062 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz);
8063 idx += encKeyOctetStrSz;
8064 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
8065 idx += encryptedKeySz;
8066
8067 #ifdef WOLFSSL_SMALL_STACK
8068 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8069 #endif
8070
8071 /* store recipient size */
8072 recip->recipSz = idx;
8073 recip->recipType = PKCS7_KEKRI;
8074
8075 /* add recipient to recip list */
8076 if (pkcs7->recipList == NULL) {
8077 pkcs7->recipList = recip;
8078 } else {
8079 lastRecip = pkcs7->recipList;
8080 while(lastRecip->next != NULL) {
8081 lastRecip = lastRecip->next;
8082 }
8083 lastRecip->next = recip;
8084 }
8085
8086 (void)options;
8087
8088 return idx;
8089 }
8090
8091
wc_PKCS7_GetCMSVersion(PKCS7 * pkcs7,int cmsContentType)8092 static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType)
8093 {
8094 int version = -1;
8095
8096 if (pkcs7 == NULL)
8097 return BAD_FUNC_ARG;
8098
8099 switch (cmsContentType) {
8100 case ENVELOPED_DATA:
8101
8102 /* NOTE: EnvelopedData does not currently support
8103 originatorInfo or unprotectedAttributes. When either of these
8104 are added, version checking below needs to be updated to match
8105 Section 6.1 of RFC 5652 */
8106
8107 /* if RecipientInfos include pwri or ori, version is 3 */
8108 if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) ||
8109 wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) {
8110 version = 3;
8111 break;
8112 }
8113
8114 /* if unprotectedAttrs is absent AND all RecipientInfo structs
8115 are version 0, version is 0 */
8116 if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) {
8117 version = 0;
8118 break;
8119 }
8120
8121 /* otherwise, version is 2 */
8122 version = 2;
8123 break;
8124
8125 default:
8126 break;
8127 }
8128
8129 return version;
8130 }
8131
8132
8133 /* build PKCS#7 envelopedData content type, return enveloped size */
wc_PKCS7_EncodeEnvelopedData(PKCS7 * pkcs7,byte * output,word32 outputSz)8134 int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
8135 {
8136 int ret, idx = 0;
8137 int totalSz, padSz, encryptedOutSz;
8138
8139 int contentInfoSeqSz = 0, outerContentTypeSz = 0, outerContentSz;
8140 byte contentInfoSeq[MAX_SEQ_SZ];
8141 byte outerContentType[MAX_ALGO_SZ];
8142 byte outerContent[MAX_SEQ_SZ];
8143
8144 int kariVersion;
8145 int envDataSeqSz, verSz;
8146 byte envDataSeq[MAX_SEQ_SZ];
8147 byte ver[MAX_VERSION_SZ];
8148
8149 WC_RNG rng;
8150 int blockSz, blockKeySz;
8151 byte* plain;
8152 byte* encryptedContent;
8153
8154 Pkcs7EncodedRecip* tmpRecip = NULL;
8155 int recipSz, recipSetSz;
8156 byte recipSet[MAX_SET_SZ];
8157
8158 int encContentOctetSz, encContentSeqSz, contentTypeSz;
8159 int contentEncAlgoSz, ivOctetStringSz;
8160 byte encContentSeq[MAX_SEQ_SZ];
8161 byte contentType[MAX_ALGO_SZ];
8162 byte contentEncAlgo[MAX_ALGO_SZ];
8163 byte tmpIv[MAX_CONTENT_IV_SIZE];
8164 byte ivOctetString[MAX_OCTET_STR_SZ];
8165 byte encContentOctet[MAX_OCTET_STR_SZ];
8166
8167 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0)
8168 return BAD_FUNC_ARG;
8169
8170 if (output == NULL || outputSz == 0)
8171 return BAD_FUNC_ARG;
8172
8173 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
8174 if (blockKeySz < 0)
8175 return blockKeySz;
8176
8177 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
8178 if (blockSz < 0)
8179 return blockSz;
8180
8181 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
8182 /* outer content type */
8183 ret = wc_SetContentType(ENVELOPED_DATA, outerContentType,
8184 sizeof(outerContentType));
8185 if (ret < 0)
8186 return ret;
8187
8188 outerContentTypeSz = ret;
8189 }
8190
8191 /* generate random content encryption key */
8192 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
8193 if (ret != 0) {
8194 return ret;
8195 }
8196
8197 /* build RecipientInfo, only if user manually set singleCert and size */
8198 if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) {
8199 switch (pkcs7->publicKeyOID) {
8200 #ifndef NO_RSA
8201 case RSAk:
8202 ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert,
8203 pkcs7->singleCertSz, 0);
8204 break;
8205 #endif
8206 #ifdef HAVE_ECC
8207 case ECDSAk:
8208 ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert,
8209 pkcs7->singleCertSz,
8210 pkcs7->keyWrapOID,
8211 pkcs7->keyAgreeOID, pkcs7->ukm,
8212 pkcs7->ukmSz, 0);
8213 break;
8214 #endif
8215
8216 default:
8217 WOLFSSL_MSG("Unsupported RecipientInfo public key type");
8218 return BAD_FUNC_ARG;
8219 };
8220
8221 if (ret < 0) {
8222 WOLFSSL_MSG("Failed to create RecipientInfo");
8223 return ret;
8224 }
8225 }
8226
8227 recipSz = wc_PKCS7_GetRecipientListSize(pkcs7);
8228 if (recipSz < 0) {
8229 return ret;
8230
8231 } else if (recipSz == 0) {
8232 WOLFSSL_MSG("You must add at least one CMS recipient");
8233 return PKCS7_RECIP_E;
8234 }
8235 recipSetSz = SetSet(recipSz, recipSet);
8236
8237 /* version, defined in Section 6.1 of RFC 5652 */
8238 kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA);
8239 if (kariVersion < 0) {
8240 WOLFSSL_MSG("Failed to set CMS EnvelopedData version");
8241 return PKCS7_RECIP_E;
8242 }
8243
8244 verSz = SetMyVersion(kariVersion, ver, 0);
8245
8246 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
8247 if (ret != 0)
8248 return ret;
8249
8250 /* generate IV for block cipher */
8251 ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz);
8252 wc_FreeRng(&rng);
8253 if (ret != 0)
8254 return ret;
8255
8256 /* EncryptedContentInfo */
8257 ret = wc_SetContentType(pkcs7->contentOID, contentType,
8258 sizeof(contentType));
8259 if (ret < 0)
8260 return ret;
8261
8262 contentTypeSz = ret;
8263
8264 /* allocate encrypted content buffer and PKCS#7 padding */
8265 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
8266 if (padSz < 0)
8267 return padSz;
8268
8269 encryptedOutSz = pkcs7->contentSz + padSz;
8270
8271 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8272 if (plain == NULL)
8273 return MEMORY_E;
8274
8275 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
8276 encryptedOutSz, blockSz);
8277 if (ret < 0) {
8278 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8279 return ret;
8280 }
8281
8282 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
8283 DYNAMIC_TYPE_PKCS7);
8284 if (encryptedContent == NULL) {
8285 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8286 return MEMORY_E;
8287 }
8288
8289 /* put together IV OCTET STRING */
8290 ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
8291
8292 /* build up our ContentEncryptionAlgorithmIdentifier sequence,
8293 * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
8294 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
8295 oidBlkType, ivOctetStringSz + blockSz);
8296
8297 if (contentEncAlgoSz == 0) {
8298 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8299 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8300 return BAD_FUNC_ARG;
8301 }
8302
8303 /* encrypt content */
8304 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek,
8305 pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain,
8306 encryptedOutSz, encryptedContent);
8307
8308 if (ret != 0) {
8309 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8310 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8311 return ret;
8312 }
8313
8314 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
8315 encContentOctet);
8316
8317 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
8318 ivOctetStringSz + blockSz +
8319 encContentOctetSz + encryptedOutSz,
8320 encContentSeq);
8321
8322 /* keep track of sizes for outer wrapper layering */
8323 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
8324 contentEncAlgoSz + ivOctetStringSz + blockSz +
8325 encContentOctetSz + encryptedOutSz;
8326
8327 /* EnvelopedData */
8328 envDataSeqSz = SetSequence(totalSz, envDataSeq);
8329 totalSz += envDataSeqSz;
8330
8331 /* outer content */
8332 outerContentSz = SetExplicit(0, totalSz, outerContent);
8333 totalSz += outerContentTypeSz;
8334 totalSz += outerContentSz;
8335
8336 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
8337 /* ContentInfo */
8338 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
8339 totalSz += contentInfoSeqSz;
8340 }
8341
8342 if (totalSz > (int)outputSz) {
8343 WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
8344 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8345 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8346 return BUFFER_E;
8347 }
8348
8349 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
8350 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
8351 idx += contentInfoSeqSz;
8352 XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
8353 idx += outerContentTypeSz;
8354 XMEMCPY(output + idx, outerContent, outerContentSz);
8355 idx += outerContentSz;
8356 }
8357 XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
8358 idx += envDataSeqSz;
8359 XMEMCPY(output + idx, ver, verSz);
8360 idx += verSz;
8361 XMEMCPY(output + idx, recipSet, recipSetSz);
8362 idx += recipSetSz;
8363 /* copy in recipients from list */
8364 tmpRecip = pkcs7->recipList;
8365 while (tmpRecip != NULL) {
8366 XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz);
8367 idx += tmpRecip->recipSz;
8368 tmpRecip = tmpRecip->next;
8369 }
8370 wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
8371 XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
8372 idx += encContentSeqSz;
8373 XMEMCPY(output + idx, contentType, contentTypeSz);
8374 idx += contentTypeSz;
8375 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
8376 idx += contentEncAlgoSz;
8377 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
8378 idx += ivOctetStringSz;
8379 XMEMCPY(output + idx, tmpIv, blockSz);
8380 idx += blockSz;
8381 XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
8382 idx += encContentOctetSz;
8383 XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
8384 idx += encryptedOutSz;
8385
8386 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8387 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
8388
8389 return idx;
8390 }
8391
8392 #ifndef NO_RSA
8393 /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */
wc_PKCS7_DecryptKtri(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)8394 static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
8395 word32* idx, byte* decryptedKey,
8396 word32* decryptedKeySz, int* recipFound)
8397 {
8398 int length, encryptedKeySz = 0, ret = 0;
8399 int keySz, version, sidType = 0;
8400 word32 encOID;
8401 word32 keyIdx;
8402 byte issuerHash[KEYID_SIZE];
8403 byte* outKey = NULL;
8404 byte* pkiMsg = in;
8405 word32 pkiMsgSz = inSz;
8406 byte tag;
8407
8408
8409 #ifndef NO_PKCS7_STREAM
8410 word32 tmpIdx = *idx;
8411 #endif
8412 #ifdef WC_RSA_BLINDING
8413 WC_RNG rng;
8414 #endif
8415
8416 #ifdef WOLFSSL_SMALL_STACK
8417 mp_int* serialNum = NULL;
8418 byte* encryptedKey = NULL;
8419 RsaKey* privKey = NULL;
8420 #else
8421 mp_int serialNum[1];
8422 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
8423 RsaKey privKey[1];
8424 #endif
8425
8426 switch (pkcs7->state) {
8427 case WC_PKCS7_DECRYPT_KTRI:
8428 #ifndef NO_PKCS7_STREAM
8429 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ,
8430 &pkiMsg, idx)) != 0) {
8431 return ret;
8432 }
8433 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
8434 #endif
8435 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0)
8436 return ASN_PARSE_E;
8437
8438 if (version == 0) {
8439 sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
8440 } else if (version == 2) {
8441 sidType = CMS_SKID;
8442 } else {
8443 return ASN_VERSION_E;
8444 }
8445
8446 #ifndef NO_PKCS7_STREAM
8447 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
8448 break;
8449 }
8450 wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version);
8451
8452 /* @TODO getting total amount left because of GetInt call later on
8453 * this could be optimized to stream better */
8454 if (pkcs7->stream->totalRd > pkcs7->stream->maxLen) {
8455 WOLFSSL_MSG("PKCS7 read more than expected");
8456 ret = BUFFER_E;
8457 break;
8458 }
8459 pkcs7->stream->expected = (pkcs7->stream->maxLen -
8460 pkcs7->stream->totalRd) + pkcs7->stream->length;
8461 #endif
8462 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2);
8463 FALL_THROUGH;
8464
8465 case WC_PKCS7_DECRYPT_KTRI_2:
8466 #ifndef NO_PKCS7_STREAM
8467
8468 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
8469 pkcs7->stream->expected, &pkiMsg, idx)) != 0) {
8470 return ret;
8471 }
8472
8473 if (in != pkiMsg) {
8474 pkiMsgSz = pkcs7->stream->length;
8475 }
8476
8477 wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version);
8478
8479 /* @TODO get expected size for next part, does not account for
8480 * GetInt call well */
8481 if (pkcs7->stream->expected == MAX_SEQ_SZ) {
8482 int sz;
8483 word32 lidx;
8484
8485 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
8486 lidx = *idx;
8487 ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz);
8488 if (ret < 0)
8489 return ret;
8490 }
8491 else {
8492 lidx = *idx + ASN_TAG_SZ;
8493 ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz);
8494 if (ret < 0)
8495 return ret;
8496 }
8497
8498 pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ +
8499 MAX_LENGTH_SZ;
8500 if (pkcs7->stream->length > 0 &&
8501 pkcs7->stream->length < pkcs7->stream->expected) {
8502 return WC_PKCS7_WANT_READ_E;
8503 }
8504 }
8505 #endif /* !NO_PKCS7_STREAM */
8506
8507 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
8508
8509 /* remove IssuerAndSerialNumber */
8510 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
8511 return ASN_PARSE_E;
8512
8513 if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
8514 return ASN_PARSE_E;
8515
8516 /* if we found correct recipient, issuer hashes will match */
8517 if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) {
8518 *recipFound = 1;
8519 }
8520
8521 #ifdef WOLFSSL_SMALL_STACK
8522 serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap,
8523 DYNAMIC_TYPE_TMP_BUFFER);
8524 if (serialNum == NULL)
8525 return MEMORY_E;
8526 #endif
8527
8528 if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) {
8529 #ifdef WOLFSSL_SMALL_STACK
8530 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8531 #endif
8532 return ASN_PARSE_E;
8533 }
8534
8535 mp_clear(serialNum);
8536
8537 #ifdef WOLFSSL_SMALL_STACK
8538 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8539 #endif
8540
8541 } else {
8542 /* parse SubjectKeyIdentifier
8543 * RFC 5652 lists SubjectKeyIdentifier as [0] followed by
8544 * simple type of octet string
8545 *
8546 * RecipientIdentifier ::= CHOICE {
8547 * issuerAndSerialNumber IssuerAndSerialNumber,
8548 * subjectKeyIdentifier [0] SubjectKeyIdentifier }
8549 *
8550 * The choice of subjectKeyIdentifier (where version was 2) is
8551 * context specific with tag number 0 within the class.
8552 */
8553
8554 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
8555 return ASN_PARSE_E;
8556
8557 /* should be context specific and tag number 0: [0] (0x80) */
8558 if (tag != ASN_CONTEXT_SPECIFIC) {
8559 return ASN_PARSE_E;
8560 }
8561
8562 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8563 return ASN_PARSE_E;
8564
8565 if (KEYID_SIZE > pkiMsgSz - (*idx))
8566 return BUFFER_E;
8567
8568 /* if we found correct recipient, SKID will match */
8569 if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId,
8570 KEYID_SIZE) == 0) {
8571 *recipFound = 1;
8572 }
8573 (*idx) += KEYID_SIZE;
8574 }
8575
8576 if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0)
8577 return ASN_PARSE_E;
8578
8579 /* key encryption algorithm must be RSA for now */
8580 if (encOID != RSAk)
8581 return ALGO_ID_E;
8582
8583 /* read encryptedKey */
8584 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
8585 return ASN_PARSE_E;
8586
8587 if (tag != ASN_OCTET_STRING)
8588 return ASN_PARSE_E;
8589
8590 if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) {
8591 return ASN_PARSE_E;
8592 }
8593 if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) {
8594 return BUFFER_E;
8595 }
8596
8597 #ifndef NO_PKCS7_STREAM
8598 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
8599 break;
8600 }
8601 wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version);
8602 pkcs7->stream->expected = encryptedKeySz;
8603 #endif
8604 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3);
8605 FALL_THROUGH;
8606
8607 case WC_PKCS7_DECRYPT_KTRI_3:
8608 #ifndef NO_PKCS7_STREAM
8609 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
8610 pkcs7->stream->expected, &pkiMsg, idx)) != 0) {
8611 return ret;
8612 }
8613 encryptedKeySz = pkcs7->stream->expected;
8614 #endif
8615
8616 #ifdef WOLFSSL_SMALL_STACK
8617 encryptedKey = (byte*)XMALLOC(encryptedKeySz, pkcs7->heap,
8618 DYNAMIC_TYPE_TMP_BUFFER);
8619 if (encryptedKey == NULL)
8620 return MEMORY_E;
8621 #endif
8622
8623 if (*recipFound == 1)
8624 XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz);
8625 *idx += encryptedKeySz;
8626
8627 /* load private key */
8628 #ifdef WOLFSSL_SMALL_STACK
8629 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
8630 DYNAMIC_TYPE_TMP_BUFFER);
8631 if (privKey == NULL) {
8632 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8633 return MEMORY_E;
8634 }
8635 #endif
8636
8637 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
8638 if (ret != 0) {
8639 #ifdef WOLFSSL_SMALL_STACK
8640 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8641 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8642 #endif
8643 return ret;
8644 }
8645
8646 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
8647 keyIdx = 0;
8648 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx,
8649 privKey, pkcs7->privateKeySz);
8650 }
8651 else if (pkcs7->devId == INVALID_DEVID) {
8652 ret = BAD_FUNC_ARG;
8653 }
8654 if (ret != 0) {
8655 WOLFSSL_MSG("Failed to decode RSA private key");
8656 wc_FreeRsaKey(privKey);
8657 #ifdef WOLFSSL_SMALL_STACK
8658 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8659 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8660 #endif
8661 return ret;
8662 }
8663
8664 /* decrypt encryptedKey */
8665 #ifdef WC_RSA_BLINDING
8666 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
8667 if (ret == 0) {
8668 ret = wc_RsaSetRNG(privKey, &rng);
8669 }
8670 #endif
8671 if (ret == 0) {
8672 #ifdef WOLFSSL_ASYNC_CRYPT
8673 /* Currently the call to RSA decrypt here is blocking @TODO */
8674 keySz = 0; /* set initial "ret" value to 0 */
8675 do {
8676 keySz = wc_AsyncWait(keySz, &privKey->asyncDev,
8677 WC_ASYNC_FLAG_CALL_AGAIN);
8678 if (keySz >= 0)
8679 #endif
8680 {
8681 keySz = wc_RsaPrivateDecryptInline(encryptedKey,
8682 encryptedKeySz, &outKey,
8683 privKey);
8684 }
8685 #ifdef WOLFSSL_ASYNC_CRYPT
8686 } while (keySz == WC_PENDING_E);
8687 #endif
8688 #ifdef WC_RSA_BLINDING
8689 wc_FreeRng(&rng);
8690 #endif
8691 } else {
8692 keySz = ret;
8693 }
8694 wc_FreeRsaKey(privKey);
8695
8696 if (keySz <= 0 || outKey == NULL) {
8697 ForceZero(encryptedKey, encryptedKeySz);
8698 #ifdef WOLFSSL_SMALL_STACK
8699 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8700 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8701 #endif
8702 return keySz;
8703 } else {
8704 *decryptedKeySz = keySz;
8705 XMEMCPY(decryptedKey, outKey, keySz);
8706 ForceZero(encryptedKey, encryptedKeySz);
8707 }
8708
8709 #ifdef WOLFSSL_SMALL_STACK
8710 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8711 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
8712 #endif
8713
8714 #ifndef NO_PKCS7_STREAM
8715 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
8716 break;
8717 }
8718 #endif
8719 ret = 0; /* success */
8720 break;
8721
8722 default:
8723 WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state");
8724 ret = BAD_FUNC_ARG;
8725 }
8726
8727 return ret;
8728 }
8729 #endif /* !NO_RSA */
8730
8731 #ifdef HAVE_ECC
8732
8733 /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */
wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx)8734 static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari,
8735 byte* pkiMsg, word32 pkiMsgSz, word32* idx)
8736 {
8737 int ret, length;
8738 word32 keyOID, oidSum = 0;
8739 int curve_id = ECC_CURVE_DEF;
8740 byte tag;
8741
8742 if (kari == NULL || pkiMsg == NULL || idx == NULL)
8743 return BAD_FUNC_ARG;
8744
8745 /* remove OriginatorIdentifierOrKey */
8746 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 &&
8747 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
8748 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8749 return ASN_PARSE_E;
8750
8751 } else {
8752 return ASN_PARSE_E;
8753 }
8754
8755 /* remove OriginatorPublicKey */
8756 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 &&
8757 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
8758 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8759 return ASN_PARSE_E;
8760
8761 } else {
8762 return ASN_PARSE_E;
8763 }
8764
8765 /* remove AlgorithmIdentifier */
8766 if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0)
8767 return ASN_PARSE_E;
8768
8769 if (keyOID != ECDSAk)
8770 return ASN_PARSE_E;
8771
8772 /* optional algorithm parameters */
8773 ret = GetObjectId(pkiMsg, idx, &oidSum, oidIgnoreType, pkiMsgSz);
8774 if (ret == 0) {
8775 /* get curve id */
8776 curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
8777 if (curve_id < 0)
8778 return ECC_CURVE_OID_E;
8779 }
8780
8781 /* remove ECPoint BIT STRING */
8782 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
8783 return ASN_PARSE_E;
8784
8785 if (tag != ASN_BIT_STRING)
8786 return ASN_PARSE_E;
8787
8788 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8789 return ASN_PARSE_E;
8790
8791 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
8792 return ASN_EXPECT_0_E;
8793
8794 if (tag != ASN_OTHER_TYPE)
8795 return ASN_EXPECT_0_E;
8796
8797 /* get sender ephemeral public ECDSA key */
8798 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
8799 if (ret != 0)
8800 return ret;
8801
8802 kari->senderKeyInit = 1;
8803
8804 /* length-1 for unused bits counter */
8805 ret = wc_ecc_import_x963_ex(pkiMsg + (*idx), length - 1, kari->senderKey,
8806 curve_id);
8807 if (ret != 0) {
8808 ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey, *idx + length - 1);
8809 if (ret != 0)
8810 return ret;
8811 }
8812 else {
8813 (*idx) += length - 1;
8814 }
8815
8816 return 0;
8817 }
8818
8819
8820 /* remove optional UserKeyingMaterial if available, return 0 on success,
8821 * < 0 on error */
wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx)8822 static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari,
8823 byte* pkiMsg, word32 pkiMsgSz, word32* idx)
8824 {
8825 int length;
8826 word32 savedIdx;
8827 byte tag;
8828
8829 if (kari == NULL || pkiMsg == NULL || idx == NULL)
8830 return BAD_FUNC_ARG;
8831
8832 savedIdx = *idx;
8833
8834 /* starts with EXPLICIT [1] */
8835 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
8836 *idx = savedIdx;
8837 return 0;
8838 }
8839 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
8840 *idx = savedIdx;
8841 return 0;
8842 }
8843
8844 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
8845 *idx = savedIdx;
8846 return 0;
8847 }
8848
8849 /* get OCTET STRING */
8850 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
8851 *idx = savedIdx;
8852 return 0;
8853 }
8854 if (tag != ASN_OCTET_STRING) {
8855 *idx = savedIdx;
8856 return 0;
8857 }
8858
8859 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
8860 *idx = savedIdx;
8861 return 0;
8862 }
8863
8864 kari->ukm = NULL;
8865 if (length > 0) {
8866 kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7);
8867 if (kari->ukm == NULL)
8868 return MEMORY_E;
8869
8870 XMEMCPY(kari->ukm, pkiMsg + (*idx), length);
8871 kari->ukmOwner = 1;
8872 }
8873
8874 (*idx) += length;
8875 kari->ukmSz = length;
8876
8877 return 0;
8878 }
8879
8880
8881 /* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success,
8882 * < 0 on error */
wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx,word32 * keyAgreeOID,word32 * keyWrapOID)8883 static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari,
8884 byte* pkiMsg, word32 pkiMsgSz, word32* idx,
8885 word32* keyAgreeOID, word32* keyWrapOID)
8886 {
8887 int length = 0;
8888 word32 localIdx;
8889
8890 if (kari == NULL || pkiMsg == NULL || idx == NULL ||
8891 keyAgreeOID == NULL || keyWrapOID == NULL)
8892 return BAD_FUNC_ARG;
8893
8894 localIdx = *idx;
8895
8896 /* remove KeyEncryptionAlgorithmIdentifier */
8897 if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
8898 return ASN_PARSE_E;
8899
8900 localIdx = *idx;
8901 if (GetAlgoId(pkiMsg, &localIdx, keyAgreeOID, oidCmsKeyAgreeType,
8902 pkiMsgSz) < 0) {
8903 return ASN_PARSE_E;
8904 }
8905
8906 if (localIdx < *idx + length) {
8907 *idx = localIdx;
8908 }
8909 /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */
8910 if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0)
8911 return ASN_PARSE_E;
8912
8913 return 0;
8914 }
8915
8916
8917 /* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error
8918 * if subject key ID matches, recipFound is set to 1 */
wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx,int * recipFound,byte * rid)8919 static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
8920 byte* pkiMsg, word32 pkiMsgSz, word32* idx,
8921 int* recipFound, byte* rid)
8922 {
8923 int length;
8924 byte tag;
8925
8926 if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL ||
8927 rid == NULL)
8928 return BAD_FUNC_ARG;
8929
8930 /* remove RecipientKeyIdentifier IMPLICIT [0] */
8931 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
8932 return ASN_PARSE_E;
8933 }
8934
8935 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
8936 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8937 return ASN_PARSE_E;
8938
8939 } else {
8940 return ASN_PARSE_E;
8941 }
8942
8943 /* remove SubjectKeyIdentifier */
8944 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
8945 return ASN_PARSE_E;
8946 }
8947
8948 if (tag != ASN_OCTET_STRING)
8949 return ASN_PARSE_E;
8950
8951 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
8952 return ASN_PARSE_E;
8953
8954 if (length != KEYID_SIZE)
8955 return ASN_PARSE_E;
8956
8957 XMEMCPY(rid, pkiMsg + (*idx), KEYID_SIZE);
8958 (*idx) += length;
8959
8960 /* subject key id should match if recipient found */
8961 if (XMEMCMP(rid, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) {
8962 *recipFound = 1;
8963 }
8964
8965 return 0;
8966 }
8967
8968
8969 /* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error
8970 * if issuer and serial number match, recipFound is set to 1 */
wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx,int * recipFound,byte * rid)8971 static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
8972 byte* pkiMsg, word32 pkiMsgSz, word32* idx,
8973 int* recipFound, byte* rid)
8974 {
8975 int length, ret;
8976 #ifdef WOLFSSL_SMALL_STACK
8977 mp_int* serial;
8978 mp_int* recipSerial;
8979 #else
8980 mp_int serial[1];
8981 mp_int recipSerial[1];
8982 #endif
8983
8984 if (rid == NULL) {
8985 return BAD_FUNC_ARG;
8986 }
8987
8988 /* remove IssuerAndSerialNumber */
8989 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
8990 return ASN_PARSE_E;
8991
8992 if (GetNameHash(pkiMsg, idx, rid, pkiMsgSz) < 0)
8993 return ASN_PARSE_E;
8994
8995 /* if we found correct recipient, issuer hashes will match */
8996 if (XMEMCMP(rid, kari->decoded->issuerHash, KEYID_SIZE) == 0) {
8997 *recipFound = 1;
8998 }
8999
9000 #ifdef WOLFSSL_SMALL_STACK
9001 serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
9002 DYNAMIC_TYPE_TMP_BUFFER);
9003 if (serial == NULL)
9004 return MEMORY_E;
9005
9006 recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
9007 DYNAMIC_TYPE_TMP_BUFFER);
9008 if (recipSerial == NULL) {
9009 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9010 return MEMORY_E;
9011 }
9012 #endif
9013
9014 if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) {
9015 #ifdef WOLFSSL_SMALL_STACK
9016 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9017 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9018 #endif
9019 return ASN_PARSE_E;
9020 }
9021
9022 ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial,
9023 kari->decoded->serialSz);
9024 if (ret != MP_OKAY) {
9025 mp_clear(serial);
9026 WOLFSSL_MSG("Failed to parse CMS recipient serial number");
9027 #ifdef WOLFSSL_SMALL_STACK
9028 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9029 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9030 #endif
9031 return ret;
9032 }
9033
9034 if (mp_cmp(recipSerial, serial) != MP_EQ) {
9035 mp_clear(serial);
9036 mp_clear(recipSerial);
9037 WOLFSSL_MSG("CMS serial number does not match recipient");
9038 #ifdef WOLFSSL_SMALL_STACK
9039 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9040 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9041 #endif
9042 return PKCS7_RECIP_E;
9043 }
9044
9045 mp_clear(serial);
9046 mp_clear(recipSerial);
9047
9048 #ifdef WOLFSSL_SMALL_STACK
9049 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9050 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
9051 #endif
9052
9053 return 0;
9054 }
9055
9056
9057 /* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */
wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI * kari,byte * pkiMsg,word32 pkiMsgSz,word32 * idx,int * recipFound,byte * encryptedKey,int * encryptedKeySz,byte * rid)9058 static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari,
9059 byte* pkiMsg, word32 pkiMsgSz, word32* idx,
9060 int* recipFound, byte* encryptedKey,
9061 int* encryptedKeySz, byte* rid)
9062 {
9063 int length;
9064 int ret = 0;
9065 byte tag;
9066 word32 localIdx;
9067
9068 if (kari == NULL || pkiMsg == NULL || idx == NULL ||
9069 recipFound == NULL || encryptedKey == NULL)
9070 return BAD_FUNC_ARG;
9071
9072 /* remove RecipientEncryptedKeys */
9073 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
9074 return ASN_PARSE_E;
9075
9076 /* remove RecipientEncryptedKeys */
9077 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
9078 return ASN_PARSE_E;
9079
9080 /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber
9081 * or [0] IMPLICIT RecipientKeyIdentifier */
9082 localIdx = *idx;
9083 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
9084 return ASN_PARSE_E;
9085
9086 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
9087 /* try to get RecipientKeyIdentifier */
9088 ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz,
9089 idx, recipFound, rid);
9090 } else {
9091 /* try to get IssuerAndSerialNumber */
9092 ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz,
9093 idx, recipFound, rid);
9094 }
9095
9096 /* if we don't have either option, malformed CMS */
9097 if (ret != 0)
9098 return ret;
9099
9100 /* remove EncryptedKey */
9101 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
9102 return ASN_PARSE_E;
9103
9104 if (tag != ASN_OCTET_STRING)
9105 return ASN_PARSE_E;
9106
9107 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
9108 return ASN_PARSE_E;
9109
9110 /* put encrypted CEK in decryptedKey buffer for now, decrypt later */
9111 if (length > *encryptedKeySz)
9112 return BUFFER_E;
9113
9114 XMEMCPY(encryptedKey, pkiMsg + (*idx), length);
9115 *encryptedKeySz = length;
9116 (*idx) += length;
9117
9118 return 0;
9119 }
9120
9121 #endif /* HAVE_ECC */
9122
9123
wc_PKCS7_SetOriEncryptCtx(PKCS7 * pkcs7,void * ctx)9124 int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx)
9125 {
9126 if (pkcs7 == NULL)
9127 return BAD_FUNC_ARG;
9128
9129 pkcs7->oriEncryptCtx = ctx;
9130
9131 return 0;
9132 }
9133
9134
wc_PKCS7_SetOriDecryptCtx(PKCS7 * pkcs7,void * ctx)9135 int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx)
9136 {
9137
9138 if (pkcs7 == NULL)
9139 return BAD_FUNC_ARG;
9140
9141 pkcs7->oriDecryptCtx = ctx;
9142
9143 return 0;
9144 }
9145
9146
wc_PKCS7_SetOriDecryptCb(PKCS7 * pkcs7,CallbackOriDecrypt cb)9147 int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb)
9148 {
9149 if (pkcs7 == NULL)
9150 return BAD_FUNC_ARG;
9151
9152 pkcs7->oriDecryptCb = cb;
9153
9154 return 0;
9155 }
9156
9157
9158 /* return 0 on success */
wc_PKCS7_SetWrapCEKCb(PKCS7 * pkcs7,CallbackWrapCEK cb)9159 int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, CallbackWrapCEK cb)
9160 {
9161 if (pkcs7 == NULL)
9162 return BAD_FUNC_ARG;
9163
9164 pkcs7->wrapCEKCb = cb;
9165
9166 return 0;
9167 }
9168
9169 /* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by:
9170 *
9171 * OtherRecipientInfo ::= SEQUENCE {
9172 * oriType OBJECT IDENTIFIER,
9173 * oriValue ANY DEFINED BY oriType }
9174 *
9175 * pkcs7 - pointer to initialized PKCS7 structure
9176 * pkiMsg - pointer to encoded CMS bundle
9177 * pkiMsgSz - size of pkiMsg, bytes
9178 * idx - [IN/OUT] pointer to index into pkiMsg
9179 * decryptedKey - [OUT] output buf for decrypted content encryption key
9180 * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key
9181 * recipFound - [OUT] 1 if recipient has been found, 0 if not
9182 *
9183 * Return 0 on success, negative upon error.
9184 */
wc_PKCS7_DecryptOri(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)9185 static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz,
9186 word32* idx, byte* decryptedKey,
9187 word32* decryptedKeySz, int* recipFound)
9188 {
9189 int ret, seqSz, oriOIDSz;
9190 word32 oriValueSz, tmpIdx;
9191 byte* oriValue;
9192 byte oriOID[MAX_OID_SZ];
9193
9194 byte* pkiMsg = in;
9195 word32 pkiMsgSz = inSz;
9196 #ifndef NO_PKCS7_STREAM
9197 word32 stateIdx = *idx;
9198 #endif
9199
9200 if (pkcs7->oriDecryptCb == NULL) {
9201 WOLFSSL_MSG("You must register an ORI Decrypt callback");
9202 return BAD_FUNC_ARG;
9203 }
9204
9205 switch (pkcs7->state) {
9206
9207 case WC_PKCS7_DECRYPT_ORI:
9208 #ifndef NO_PKCS7_STREAM
9209 /* @TODO for now just get full buffer, needs divided up */
9210 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
9211 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
9212 pkcs7->stream->length, &pkiMsg, idx)) != 0) {
9213 return ret;
9214 }
9215 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
9216 #endif
9217 /* get OtherRecipientInfo sequence length */
9218 if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0)
9219 return ASN_PARSE_E;
9220
9221 tmpIdx = *idx;
9222
9223 /* remove and store oriType OBJECT IDENTIFIER */
9224 if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0)
9225 return ASN_PARSE_E;
9226
9227 XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz);
9228 *idx += oriOIDSz;
9229
9230 /* get oriValue, increment idx */
9231 oriValue = pkiMsg + *idx;
9232 oriValueSz = seqSz - (*idx - tmpIdx);
9233 *idx += oriValueSz;
9234
9235 /* pass oriOID and oriValue to user callback, expect back
9236 decryptedKey and size */
9237 ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue,
9238 oriValueSz, decryptedKey, decryptedKeySz,
9239 pkcs7->oriDecryptCtx);
9240
9241 if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) {
9242 /* decrypt operation failed */
9243 *recipFound = 0;
9244 return PKCS7_RECIP_E;
9245 }
9246
9247 /* mark recipFound, since we only support one RecipientInfo for now */
9248 *recipFound = 1;
9249
9250 #ifndef NO_PKCS7_STREAM
9251 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) {
9252 break;
9253 }
9254 #endif
9255 ret = 0; /* success */
9256 break;
9257
9258 default:
9259 WOLFSSL_MSG("PKCS7 ORI unknown state");
9260 ret = BAD_FUNC_ARG;
9261
9262 }
9263
9264 return ret;
9265 }
9266
9267 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
9268
9269 /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success,
9270 * < 0 on error */
wc_PKCS7_DecryptPwri(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)9271 static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz,
9272 word32* idx, byte* decryptedKey,
9273 word32* decryptedKeySz, int* recipFound)
9274 {
9275 byte* salt;
9276 byte* cek;
9277 byte* kek;
9278
9279 byte tmpIv[MAX_CONTENT_IV_SIZE];
9280
9281 int ret = 0, length, saltSz, iterations, blockSz, kekKeySz;
9282 int hashOID = WC_SHA; /* default to SHA1 */
9283 word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz;
9284 byte* pkiMsg = in;
9285 word32 pkiMsgSz = inSz;
9286 byte tag;
9287 #ifndef NO_PKCS7_STREAM
9288 word32 tmpIdx = *idx;
9289 #endif
9290
9291 switch (pkcs7->state) {
9292 case WC_PKCS7_DECRYPT_PWRI:
9293 #ifndef NO_PKCS7_STREAM
9294 /*@TODO for now just get full buffer, needs divided up */
9295 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
9296 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
9297 pkcs7->stream->length, &pkiMsg, idx)) != 0) {
9298 return ret;
9299 }
9300 #ifdef ASN_BER_TO_DER
9301 /* check if pkcs7->der is being used after BER to DER */
9302 if (pkcs7->derSz > 0) {
9303 pkiMsgSz = pkcs7->derSz;
9304 }
9305 else
9306 #endif
9307 {
9308 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
9309 inSz;
9310 }
9311 #endif
9312 /* remove KeyDerivationAlgorithmIdentifier */
9313 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
9314 return ASN_PARSE_E;
9315
9316 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
9317 return ASN_PARSE_E;
9318
9319 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
9320 return ASN_PARSE_E;
9321
9322 /* get KeyDerivationAlgorithmIdentifier */
9323 if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0)
9324 return ASN_PARSE_E;
9325
9326 /* get KDF params SEQ */
9327 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
9328 return ASN_PARSE_E;
9329
9330 /* get KDF salt OCTET STRING */
9331 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
9332 return ASN_PARSE_E;
9333
9334 if (tag != ASN_OCTET_STRING)
9335 return ASN_PARSE_E;
9336
9337 if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0)
9338 return ASN_PARSE_E;
9339
9340 salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9341 if (salt == NULL)
9342 return MEMORY_E;
9343
9344 XMEMCPY(salt, pkiMsg + (*idx), saltSz);
9345 *idx += saltSz;
9346
9347 /* get KDF iterations */
9348 if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) {
9349 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9350 return ASN_PARSE_E;
9351 }
9352
9353 /* get KeyEncAlgoId SEQ */
9354 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) {
9355 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9356 return ASN_PARSE_E;
9357 }
9358
9359 /* get KeyEncAlgoId */
9360 if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) {
9361 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9362 return ASN_PARSE_E;
9363 }
9364
9365 /* get pwriEncAlgoId */
9366 if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) {
9367 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9368 return ASN_PARSE_E;
9369 }
9370
9371 blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId);
9372 if (blockSz < 0) {
9373 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9374 return blockSz;
9375 }
9376
9377 /* get content-encryption key size, based on algorithm */
9378 kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId);
9379 if (kekKeySz < 0) {
9380 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9381 return kekKeySz;
9382 }
9383
9384 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
9385 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
9386 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9387 return ASN_PARSE_E;
9388 }
9389
9390 if (tag != ASN_OCTET_STRING) {
9391 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9392 return ASN_PARSE_E;
9393 }
9394
9395 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
9396 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9397 return ASN_PARSE_E;
9398 }
9399
9400 if (length != blockSz) {
9401 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
9402 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9403 return ASN_PARSE_E;
9404 }
9405
9406 XMEMCPY(tmpIv, pkiMsg + (*idx), length);
9407 *idx += length;
9408
9409 /* get EncryptedKey */
9410 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
9411 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9412 return ASN_PARSE_E;
9413 }
9414
9415 if (tag != ASN_OCTET_STRING) {
9416 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9417 return ASN_PARSE_E;
9418 }
9419
9420 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
9421 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9422 return ASN_PARSE_E;
9423 }
9424
9425 /* allocate temporary space for decrypted key */
9426 cekSz = length;
9427 cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
9428 if (cek == NULL) {
9429 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9430 return MEMORY_E;
9431 }
9432
9433 /* generate KEK */
9434 kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9435 if (kek == NULL) {
9436 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9437 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9438 return MEMORY_E;
9439 }
9440
9441 ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz,
9442 salt, saltSz, kdfAlgoId, hashOID,
9443 iterations, kek, kekKeySz);
9444 if (ret < 0) {
9445 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9446 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9447 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9448 return ASN_PARSE_E;
9449 }
9450
9451 /* decrypt CEK with KEK */
9452 ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz,
9453 pkiMsg + (*idx), length, cek,
9454 cekSz, tmpIv, blockSz,
9455 pwriEncAlgoId);
9456 if (ret < 0) {
9457 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9458 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9459 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9460 return ret;
9461 }
9462 cekSz = ret;
9463
9464 if (*decryptedKeySz < cekSz) {
9465 WOLFSSL_MSG("Decrypted key buffer too small for CEK");
9466 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9467 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9468 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9469 return BUFFER_E;
9470 }
9471
9472 XMEMCPY(decryptedKey, cek, cekSz);
9473 *decryptedKeySz = cekSz;
9474
9475 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9476 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9477 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9478
9479 /* mark recipFound, since we only support one RecipientInfo for now */
9480 *recipFound = 1;
9481 *idx += length;
9482 #ifndef NO_PKCS7_STREAM
9483 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
9484 break;
9485 }
9486 #endif
9487 ret = 0; /* success */
9488 break;
9489
9490 default:
9491 WOLFSSL_MSG("PKCS7 PWRI unknown state");
9492 ret = BAD_FUNC_ARG;
9493 }
9494
9495 return ret;
9496 }
9497
9498 #endif /* NO_PWDBASED | NO_SHA */
9499
9500 /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success,
9501 * < 0 on error */
wc_PKCS7_DecryptKekri(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)9502 static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz,
9503 word32* idx, byte* decryptedKey,
9504 word32* decryptedKeySz, int* recipFound)
9505 {
9506 int length, keySz, dateLen, direction;
9507 byte* keyId = NULL;
9508 const byte* datePtr = NULL;
9509 byte dateFormat, tag;
9510 word32 keyIdSz, kekIdSz, keyWrapOID, localIdx;
9511
9512 int ret = 0;
9513 byte* pkiMsg = in;
9514 word32 pkiMsgSz = inSz;
9515 #ifndef NO_PKCS7_STREAM
9516 word32 tmpIdx = *idx;
9517 #endif
9518
9519 WOLFSSL_ENTER("wc_PKCS7_DecryptKekri");
9520 switch (pkcs7->state) {
9521 case WC_PKCS7_DECRYPT_KEKRI:
9522 #ifndef NO_PKCS7_STREAM
9523 /* @TODO for now just get full buffer, needs divided up */
9524 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
9525 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
9526 pkcs7->stream->length, &pkiMsg, idx)) != 0) {
9527 return ret;
9528 }
9529 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
9530 #endif
9531 /* remove KEKIdentifier */
9532 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
9533 return ASN_PARSE_E;
9534
9535 kekIdSz = length;
9536
9537 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
9538 return ASN_PARSE_E;
9539
9540 if (tag != ASN_OCTET_STRING)
9541 return ASN_PARSE_E;
9542
9543 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
9544 return ASN_PARSE_E;
9545
9546 /* save keyIdentifier and length */
9547 keyId = pkiMsg + *idx;
9548 keyIdSz = length;
9549 *idx += keyIdSz;
9550
9551 /* may have OPTIONAL GeneralizedTime */
9552 localIdx = *idx;
9553 if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag,
9554 pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) {
9555 if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat,
9556 &dateLen) != 0) {
9557 return ASN_PARSE_E;
9558 }
9559 *idx += (dateLen + 1);
9560 }
9561
9562 /* may have OPTIONAL OtherKeyAttribute */
9563 localIdx = *idx;
9564 if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag,
9565 pkiMsgSz) == 0 && tag == (ASN_SEQUENCE |
9566 ASN_CONSTRUCTED)) {
9567 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
9568 return ASN_PARSE_E;
9569
9570 /* skip it */
9571 *idx += length;
9572 }
9573
9574 /* get KeyEncryptionAlgorithmIdentifier */
9575 if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0)
9576 return ASN_PARSE_E;
9577
9578 /* get EncryptedKey */
9579 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
9580 return ASN_PARSE_E;
9581
9582 if (tag != ASN_OCTET_STRING)
9583 return ASN_PARSE_E;
9584
9585 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
9586 return ASN_PARSE_E;
9587
9588 #ifndef NO_AES
9589 direction = AES_DECRYPTION;
9590 #else
9591 direction = DES_DECRYPTION;
9592 #endif
9593
9594 /* decrypt CEK with KEK */
9595 if (pkcs7->wrapCEKCb) {
9596 keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, length, keyId,
9597 keyIdSz, NULL, 0, decryptedKey,
9598 *decryptedKeySz, keyWrapOID,
9599 (int)PKCS7_KEKRI, direction);
9600 }
9601 else {
9602 keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey,
9603 pkcs7->privateKeySz, decryptedKey, *decryptedKeySz,
9604 keyWrapOID, direction);
9605 }
9606 if (keySz <= 0)
9607 return keySz;
9608
9609 *decryptedKeySz = (word32)keySz;
9610
9611 /* mark recipFound, since we only support one RecipientInfo for now */
9612 *recipFound = 1;
9613 *idx += length;
9614
9615 #ifndef NO_PKCS7_STREAM
9616 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
9617 break;
9618 }
9619 #endif
9620 ret = 0; /* success */
9621 break;
9622
9623 default:
9624 WOLFSSL_MSG("PKCS7 KEKRI unknown state");
9625 ret = BAD_FUNC_ARG;
9626
9627 }
9628
9629 (void)keyId;
9630 return ret;
9631 }
9632
9633
9634 /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success,
9635 * < 0 on error */
wc_PKCS7_DecryptKari(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)9636 static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz,
9637 word32* idx, byte* decryptedKey,
9638 word32* decryptedKeySz, int* recipFound)
9639 {
9640 #ifdef HAVE_ECC
9641 int ret, keySz;
9642 int encryptedKeySz;
9643 int direction = 0;
9644 word32 keyAgreeOID, keyWrapOID;
9645 byte rid[KEYID_SIZE];
9646
9647 #ifdef WOLFSSL_SMALL_STACK
9648 byte* encryptedKey;
9649 #else
9650 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
9651 #endif
9652
9653 byte* pkiMsg = in;
9654 word32 pkiMsgSz = inSz;
9655 #ifndef NO_PKCS7_STREAM
9656 word32 tmpIdx = (idx) ? *idx : 0;
9657 #endif
9658
9659 WOLFSSL_ENTER("wc_PKCS7_DecryptKari");
9660 if (pkcs7 == NULL || pkiMsg == NULL ||
9661 ((pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) &&
9662 pkcs7->wrapCEKCb == NULL) ||
9663 idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) {
9664 return BAD_FUNC_ARG;
9665 }
9666
9667 switch (pkcs7->state) {
9668 case WC_PKCS7_DECRYPT_KARI: {
9669 WC_PKCS7_KARI* kari;
9670
9671 #ifndef NO_PKCS7_STREAM
9672 /* @TODO for now just get full buffer, needs divided up */
9673 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
9674 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
9675 pkcs7->stream->length, &pkiMsg, idx)) != 0) {
9676 return ret;
9677 }
9678 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
9679 #endif
9680
9681 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE);
9682 if (kari == NULL)
9683 return MEMORY_E;
9684
9685 #ifdef WOLFSSL_SMALL_STACK
9686 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
9687 DYNAMIC_TYPE_PKCS7);
9688 if (encryptedKey == NULL) {
9689 wc_PKCS7_KariFree(kari);
9690 return MEMORY_E;
9691 }
9692 #endif
9693 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
9694
9695 /* parse cert and key */
9696 if (pkcs7->singleCert != NULL) {
9697 ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert,
9698 pkcs7->singleCertSz, pkcs7->privateKey,
9699 pkcs7->privateKeySz);
9700 if (ret != 0) {
9701 wc_PKCS7_KariFree(kari);
9702 #ifdef WOLFSSL_SMALL_STACK
9703 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9704 #endif
9705 return ret;
9706 }
9707 }
9708
9709 /* remove OriginatorIdentifierOrKey */
9710 ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg,
9711 pkiMsgSz, idx);
9712 if (ret != 0) {
9713 wc_PKCS7_KariFree(kari);
9714 #ifdef WOLFSSL_SMALL_STACK
9715 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9716 #endif
9717 return ret;
9718 }
9719
9720 /* try and remove optional UserKeyingMaterial */
9721 ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx);
9722 if (ret != 0) {
9723 wc_PKCS7_KariFree(kari);
9724 #ifdef WOLFSSL_SMALL_STACK
9725 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9726 #endif
9727 return ret;
9728 }
9729
9730 /* remove KeyEncryptionAlgorithmIdentifier */
9731 ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg,
9732 pkiMsgSz, idx, &keyAgreeOID, &keyWrapOID);
9733 if (ret != 0) {
9734 wc_PKCS7_KariFree(kari);
9735 #ifdef WOLFSSL_SMALL_STACK
9736 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9737 #endif
9738 return ret;
9739 }
9740
9741 /* if user has not explicitly set keyAgreeOID, set from one in bundle */
9742 if (pkcs7->keyAgreeOID == 0)
9743 pkcs7->keyAgreeOID = keyAgreeOID;
9744
9745 /* set direction based on key wrap algorithm */
9746 switch (keyWrapOID) {
9747 #ifndef NO_AES
9748 #ifdef WOLFSSL_AES_128
9749 case AES128_WRAP:
9750 #endif
9751 #ifdef WOLFSSL_AES_192
9752 case AES192_WRAP:
9753 #endif
9754 #ifdef WOLFSSL_AES_256
9755 case AES256_WRAP:
9756 #endif
9757 direction = AES_DECRYPTION;
9758 break;
9759 #endif
9760 default:
9761 WOLFSSL_MSG("AES key wrap algorithm unsupported");
9762 if (pkcs7->wrapCEKCb) {
9763 WOLFSSL_MSG("Direction not set!");
9764 break; /* if unwrapping callback is set then do not
9765 * force restriction of supported wrap
9766 * algorithms */
9767 }
9768
9769 wc_PKCS7_KariFree(kari);
9770 #ifdef WOLFSSL_SMALL_STACK
9771 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9772 #endif
9773 return BAD_KEYWRAP_ALG_E;
9774 }
9775
9776 /* remove RecipientEncryptedKeys */
9777 ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz,
9778 idx, recipFound, encryptedKey, &encryptedKeySz, rid);
9779 if (ret != 0) {
9780 wc_PKCS7_KariFree(kari);
9781 #ifdef WOLFSSL_SMALL_STACK
9782 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9783 #endif
9784 return ret;
9785 }
9786
9787 /* decrypt CEK with KEK */
9788 if (pkcs7->wrapCEKCb) {
9789 word32 tmpKeySz = 0;
9790 byte* tmpKeyDer = NULL;
9791
9792 PRIVATE_KEY_UNLOCK();
9793 ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz);
9794 PRIVATE_KEY_LOCK();
9795 if (ret != LENGTH_ONLY_E) {
9796 return ret;
9797 }
9798
9799 /* buffer space for algorithm/curve */
9800 tmpKeySz += MAX_SEQ_SZ;
9801 tmpKeySz += 2 * MAX_ALGO_SZ;
9802
9803 /* buffer space for public key sequence */
9804 tmpKeySz += MAX_SEQ_SZ;
9805 tmpKeySz += TRAILING_ZERO;
9806
9807 tmpKeyDer = (byte*)XMALLOC(tmpKeySz, pkcs7->heap,
9808 DYNAMIC_TYPE_TMP_BUFFER);
9809 if (tmpKeyDer == NULL) {
9810 return MEMORY_E;
9811 }
9812
9813 ret = wc_EccPublicKeyToDer(kari->senderKey, tmpKeyDer,
9814 tmpKeySz, 1);
9815 if (ret < 0) {
9816 XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
9817 return ret;
9818 }
9819 tmpKeySz = (word32)ret;
9820
9821 keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz,
9822 rid, KEYID_SIZE, tmpKeyDer, tmpKeySz,
9823 decryptedKey, *decryptedKeySz,
9824 keyWrapOID, (int)PKCS7_KARI, direction);
9825 XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
9826
9827 if (keySz > 0) {
9828 /* If unwrapping was successful then consider recipient
9829 * found. Checking for NULL singleCert to confirm previous
9830 * SID check was not done */
9831 if (pkcs7->singleCert == NULL)
9832 *recipFound = 1;
9833 }
9834 }
9835 else {
9836 /* create KEK */
9837 ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID,
9838 pkcs7->keyAgreeOID);
9839 if (ret != 0) {
9840 wc_PKCS7_KariFree(kari);
9841 #ifdef WOLFSSL_SMALL_STACK
9842 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9843 #endif
9844 return ret;
9845 }
9846
9847 /* decrypt CEK with KEK */
9848 keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek,
9849 kari->kekSz, decryptedKey, *decryptedKeySz,
9850 keyWrapOID, direction);
9851 }
9852 if (keySz <= 0) {
9853 wc_PKCS7_KariFree(kari);
9854 #ifdef WOLFSSL_SMALL_STACK
9855 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9856 #endif
9857 return keySz;
9858 }
9859 *decryptedKeySz = (word32)keySz;
9860
9861 wc_PKCS7_KariFree(kari);
9862 #ifdef WOLFSSL_SMALL_STACK
9863 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
9864 #endif
9865 #ifndef NO_PKCS7_STREAM
9866 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
9867 break;
9868 }
9869 #endif
9870 ret = 0; /* success */
9871 }
9872 break;
9873
9874 default:
9875 WOLFSSL_MSG("PKCS7 kari unknown state");
9876 ret = BAD_FUNC_ARG;
9877
9878 }
9879
9880 (void)pkiMsg;
9881 (void)pkiMsgSz;
9882
9883 return ret;
9884 #else
9885 (void)in;
9886 (void)inSz;
9887 (void)pkcs7;
9888 (void)idx;
9889 (void)decryptedKey;
9890 (void)decryptedKeySz;
9891 (void)recipFound;
9892
9893 return NOT_COMPILED_IN;
9894 #endif /* HAVE_ECC */
9895 }
9896
9897
9898 /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */
wc_PKCS7_DecryptRecipientInfos(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,byte * decryptedKey,word32 * decryptedKeySz,int * recipFound)9899 static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in,
9900 word32 inSz, word32* idx, byte* decryptedKey,
9901 word32* decryptedKeySz, int* recipFound)
9902 {
9903 word32 savedIdx;
9904 int version, ret = 0, length;
9905 byte* pkiMsg = in;
9906 word32 pkiMsgSz = inSz;
9907 byte tag;
9908 #ifndef NO_PKCS7_STREAM
9909 word32 tmpIdx;
9910 #endif
9911
9912 if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL ||
9913 decryptedKey == NULL || decryptedKeySz == NULL ||
9914 recipFound == NULL) {
9915 return BAD_FUNC_ARG;
9916 }
9917
9918 WOLFSSL_ENTER("wc_PKCS7_DecryptRecipientInfos");
9919 #ifndef NO_PKCS7_STREAM
9920 tmpIdx = *idx;
9921 #endif
9922
9923 /* check if in the process of decrypting */
9924 switch (pkcs7->state) {
9925 case WC_PKCS7_DECRYPT_KTRI:
9926 case WC_PKCS7_DECRYPT_KTRI_2:
9927 case WC_PKCS7_DECRYPT_KTRI_3:
9928 #ifndef NO_RSA
9929 ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
9930 decryptedKey, decryptedKeySz, recipFound);
9931 #else
9932 return NOT_COMPILED_IN;
9933 #endif
9934 break;
9935
9936 case WC_PKCS7_DECRYPT_KARI:
9937 ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx,
9938 decryptedKey, decryptedKeySz, recipFound);
9939 break;
9940
9941 case WC_PKCS7_DECRYPT_KEKRI:
9942 ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx,
9943 decryptedKey, decryptedKeySz, recipFound);
9944 break;
9945
9946 case WC_PKCS7_DECRYPT_PWRI:
9947 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
9948 ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx,
9949 decryptedKey, decryptedKeySz, recipFound);
9950 #else
9951 return NOT_COMPILED_IN;
9952 #endif
9953 break;
9954
9955 case WC_PKCS7_DECRYPT_ORI:
9956 ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx,
9957 decryptedKey, decryptedKeySz, recipFound);
9958 break;
9959
9960 default:
9961 /* not in decrypting state */
9962 break;
9963 }
9964
9965 if (ret < 0) {
9966 return ret;
9967 }
9968
9969 savedIdx = *idx;
9970 #ifndef NO_PKCS7_STREAM
9971 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
9972 if (pkcs7->stream->length > 0)
9973 pkiMsg = pkcs7->stream->buffer;
9974 #endif
9975
9976 /* when looking for next recipient, use first sequence and version to
9977 * indicate there is another, if not, move on */
9978 while(*recipFound == 0) {
9979
9980 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
9981 * last good saved one */
9982 if (GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz, NO_USER_CHECK) > 0) {
9983
9984 #ifndef NO_RSA
9985 /* found ktri */
9986 #ifndef NO_PKCS7_STREAM
9987 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
9988 break;
9989 }
9990 #endif
9991 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI);
9992 ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
9993 decryptedKey, decryptedKeySz,
9994 recipFound);
9995 if (ret != 0)
9996 return ret;
9997 #else
9998 return NOT_COMPILED_IN;
9999 #endif
10000 }
10001 else {
10002 word32 localIdx;
10003 /* kari is IMPLICIT[1] */
10004 *idx = savedIdx;
10005 localIdx = *idx;
10006
10007 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) {
10008 /* no room for recipient info */
10009 break;
10010 }
10011
10012 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
10013 (*idx)++;
10014 if (GetLength_ex(pkiMsg, idx, &length, pkiMsgSz,
10015 NO_USER_CHECK) < 0)
10016 return ASN_PARSE_E;
10017
10018 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
10019 *idx = savedIdx;
10020 break;
10021 }
10022
10023 if (version != 3)
10024 return ASN_VERSION_E;
10025
10026 /* found kari */
10027 #ifndef NO_PKCS7_STREAM
10028 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10029 break;
10030 }
10031 #endif
10032 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI);
10033 ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx,
10034 decryptedKey, decryptedKeySz,
10035 recipFound);
10036 if (ret != 0)
10037 return ret;
10038
10039 /* kekri is IMPLICIT[2] */
10040 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) {
10041 (*idx)++;
10042
10043 if (GetLength_ex(pkiMsg, idx, &version, pkiMsgSz,
10044 NO_USER_CHECK) < 0)
10045 return ASN_PARSE_E;
10046
10047 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
10048 *idx = savedIdx;
10049 break;
10050 }
10051
10052 if (version != 4)
10053 return ASN_VERSION_E;
10054
10055 /* found kekri */
10056 #ifndef NO_PKCS7_STREAM
10057 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10058 break;
10059 }
10060 #endif
10061 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI);
10062 ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx,
10063 decryptedKey, decryptedKeySz,
10064 recipFound);
10065 if (ret != 0)
10066 return ret;
10067
10068 /* pwri is IMPLICIT[3] */
10069 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) {
10070 #if !defined(NO_PWDBASED) && !defined(NO_SHA)
10071 (*idx)++;
10072
10073 if (GetLength_ex(pkiMsg, idx, &version, pkiMsgSz,
10074 NO_USER_CHECK) < 0)
10075 return ASN_PARSE_E;
10076
10077 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
10078 *idx = savedIdx;
10079 break;
10080 }
10081
10082 if (version != 0)
10083 return ASN_VERSION_E;
10084
10085 /* found pwri */
10086 #ifndef NO_PKCS7_STREAM
10087 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10088 break;
10089 }
10090 #endif
10091 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI);
10092 ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx,
10093 decryptedKey, decryptedKeySz,
10094 recipFound);
10095 if (ret != 0)
10096 return ret;
10097 #else
10098 return NOT_COMPILED_IN;
10099 #endif
10100
10101 /* ori is IMPLICIT[4] */
10102 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 4)) {
10103 (*idx)++;
10104
10105 /* found ori */
10106 #ifndef NO_PKCS7_STREAM
10107 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10108 break;
10109 }
10110 #endif
10111 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI);
10112 ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx,
10113 decryptedKey, decryptedKeySz,
10114 recipFound);
10115 if (ret != 0)
10116 return ret;
10117
10118 } else {
10119 /* failed to find RecipientInfo, restore idx and continue */
10120 *idx = savedIdx;
10121 break;
10122 }
10123 }
10124
10125 /* update good idx */
10126 savedIdx = *idx;
10127 }
10128
10129 return ret;
10130 }
10131
10132
10133 /* Parse encoded EnvelopedData bundle up to RecipientInfo set.
10134 *
10135 * return size of RecipientInfo SET on success, negative upon error */
wc_PKCS7_ParseToRecipientInfoSet(PKCS7 * pkcs7,byte * in,word32 inSz,word32 * idx,int type)10136 static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in,
10137 word32 inSz, word32* idx,
10138 int type)
10139 {
10140 int version = 0, length, ret = 0;
10141 word32 contentType;
10142 byte* pkiMsg = in;
10143 word32 pkiMsgSz = inSz;
10144 byte tag;
10145 #ifndef NO_PKCS7_STREAM
10146 word32 tmpIdx = 0;
10147 #endif
10148
10149 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL)
10150 return BAD_FUNC_ARG;
10151
10152 if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) &&
10153 pkcs7->contentOID != FIRMWARE_PKG_DATA
10154 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
10155 && pkcs7->contentOID != COMPRESSED_DATA
10156 #endif
10157 )
10158 return BAD_FUNC_ARG;
10159
10160 #ifndef NO_PKCS7_STREAM
10161 if (pkcs7->stream == NULL) {
10162 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
10163 return ret;
10164 }
10165 }
10166 #endif
10167
10168 switch (pkcs7->state) {
10169 case WC_PKCS7_INFOSET_START:
10170 case WC_PKCS7_INFOSET_BER:
10171 case WC_PKCS7_INFOSET_STAGE1:
10172 case WC_PKCS7_INFOSET_STAGE2:
10173 case WC_PKCS7_INFOSET_END:
10174 break;
10175
10176 default:
10177 WOLFSSL_MSG("Warning, setting PKCS7 info state to start");
10178 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START);
10179 }
10180
10181 switch (pkcs7->state) {
10182 case WC_PKCS7_INFOSET_START:
10183 #ifndef NO_PKCS7_STREAM
10184 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
10185 ASN_TAG_SZ, &pkiMsg, idx)) != 0) {
10186 return ret;
10187 }
10188 if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
10189 break;
10190 }
10191 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10192 #endif
10193 /* read past ContentInfo, verify type is envelopedData */
10194 if (ret == 0 && GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz,
10195 NO_USER_CHECK) < 0)
10196 {
10197 ret = ASN_PARSE_E;
10198 }
10199
10200 if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) {
10201 #ifdef ASN_BER_TO_DER
10202 word32 len;
10203
10204 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER);
10205 FALL_THROUGH;
10206
10207 /* full buffer is needed for conversion */
10208 case WC_PKCS7_INFOSET_BER:
10209 #ifndef NO_PKCS7_STREAM
10210 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
10211 pkcs7->stream->maxLen - pkcs7->stream->length,
10212 &pkiMsg, idx)) != 0) {
10213 return ret;
10214 }
10215 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
10216 inSz;
10217 #endif
10218
10219 len = 0;
10220
10221 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
10222 if (ret != LENGTH_ONLY_E)
10223 return ret;
10224 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10225 if (pkcs7->der == NULL)
10226 return MEMORY_E;
10227 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
10228 if (ret < 0)
10229 return ret;
10230
10231 pkiMsg = in = pkcs7->der;
10232 pkiMsgSz = pkcs7->derSz = inSz = len;
10233 *idx = 0;
10234
10235 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
10236 return ASN_PARSE_E;
10237 #else
10238 return BER_INDEF_E;
10239 #endif
10240 }
10241 #ifndef NO_PKCS7_STREAM
10242 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10243 break;
10244 }
10245 #endif
10246 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1);
10247 FALL_THROUGH;
10248
10249 case WC_PKCS7_INFOSET_STAGE1:
10250 #ifndef NO_PKCS7_STREAM
10251 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ +
10252 MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) {
10253 return ret;
10254 }
10255
10256 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz;
10257 #endif
10258 if (pkcs7->contentOID != FIRMWARE_PKG_DATA ||
10259 type == AUTH_ENVELOPED_DATA) {
10260 if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType,
10261 pkiMsgSz) < 0)
10262 ret = ASN_PARSE_E;
10263
10264 if (ret == 0) {
10265 if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) {
10266 WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
10267 ret = PKCS7_OID_E;
10268 } else if (type == AUTH_ENVELOPED_DATA &&
10269 contentType != AUTH_ENVELOPED_DATA) {
10270 WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData");
10271 ret = PKCS7_OID_E;
10272 }
10273 }
10274
10275 if (ret == 0 && GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) != 0)
10276 ret = ASN_PARSE_E;
10277
10278 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
10279 | 0))
10280 ret = ASN_PARSE_E;
10281
10282 if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz,
10283 NO_USER_CHECK) < 0)
10284 ret = ASN_PARSE_E;
10285 }
10286
10287 if (ret < 0)
10288 break;
10289
10290 #ifndef NO_PKCS7_STREAM
10291 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10292 break;
10293 }
10294 #endif
10295 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2);
10296 FALL_THROUGH;
10297
10298 case WC_PKCS7_INFOSET_STAGE2:
10299 #ifndef NO_PKCS7_STREAM
10300 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
10301 MAX_VERSION_SZ, &pkiMsg, idx)) != 0) {
10302 return ret;
10303 }
10304 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10305 #endif
10306 /* remove EnvelopedData and version */
10307 if (pkcs7->contentOID != FIRMWARE_PKG_DATA ||
10308 type == AUTH_ENVELOPED_DATA) {
10309 if (ret == 0 && GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz,
10310 NO_USER_CHECK) < 0)
10311 ret = ASN_PARSE_E;
10312 }
10313
10314 if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0)
10315 ret = ASN_PARSE_E;
10316
10317 if (ret < 0)
10318 break;
10319
10320 #ifndef NO_PKCS7_STREAM
10321 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10322 break;
10323 }
10324
10325 pkcs7->stream->varOne = version;
10326 #endif
10327 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END);
10328 FALL_THROUGH;
10329
10330 case WC_PKCS7_INFOSET_END:
10331 #ifndef NO_PKCS7_STREAM
10332 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
10333 MAX_SET_SZ, &pkiMsg, idx)) != 0) {
10334 return ret;
10335 }
10336 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10337 version = pkcs7->stream->varOne;
10338 #endif
10339
10340 if (type == ENVELOPED_DATA) {
10341 /* TODO :: make this more accurate */
10342 if ((pkcs7->publicKeyOID == RSAk &&
10343 (version != 0 && version != 2))
10344 #ifdef HAVE_ECC
10345 || (pkcs7->publicKeyOID == ECDSAk &&
10346 (version != 0 && version != 2 && version != 3))
10347 #endif
10348 ) {
10349 WOLFSSL_MSG("PKCS#7 envelopedData version incorrect");
10350 ret = ASN_VERSION_E;
10351 }
10352 } else {
10353 /* AuthEnvelopedData version MUST be 0 */
10354 if (version != 0) {
10355 WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0");
10356 ret = ASN_VERSION_E;
10357 }
10358 }
10359
10360 /* remove RecipientInfo set, get length of set */
10361 if (ret == 0 && GetSet_ex(pkiMsg, idx, &length, pkiMsgSz,
10362 NO_USER_CHECK) < 0)
10363 ret = ASN_PARSE_E;
10364
10365 if (ret < 0)
10366 break;
10367
10368 #ifndef NO_PKCS7_STREAM
10369 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10370 break;
10371 }
10372 #endif
10373
10374 if (ret == 0)
10375 ret = length;
10376
10377 break;
10378
10379 default:
10380 WOLFSSL_MSG("Bad PKCS7 info set state");
10381 ret = BAD_FUNC_ARG;
10382 break;
10383 }
10384
10385 return ret;
10386 }
10387
10388
10389 /* Import secret/private key into a PKCS7 structure. Used for setting
10390 * the secret key for decryption a EnvelopedData KEKRI RecipientInfo.
10391 *
10392 * Returns 0 on success, negative upon error */
wc_PKCS7_SetKey(PKCS7 * pkcs7,byte * key,word32 keySz)10393 WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz)
10394 {
10395 if (pkcs7 == NULL || key == NULL || keySz == 0)
10396 return BAD_FUNC_ARG;
10397
10398 pkcs7->privateKey = key;
10399 pkcs7->privateKeySz = keySz;
10400
10401 return 0;
10402 }
10403
10404
10405 /* append data to encrypted content cache in PKCS7 structure
10406 * return 0 on success, negative on error */
PKCS7_CacheEncryptedContent(PKCS7 * pkcs7,byte * in,word32 inSz)10407 static int PKCS7_CacheEncryptedContent(PKCS7* pkcs7, byte* in, word32 inSz)
10408 {
10409 byte* oldCache;
10410 word32 oldCacheSz;
10411
10412 if (pkcs7 == NULL || in == NULL)
10413 return BAD_FUNC_ARG;
10414
10415 /* save pointer to old cache */
10416 oldCache = pkcs7->cachedEncryptedContent;
10417 oldCacheSz = pkcs7->cachedEncryptedContentSz;
10418
10419 /* re-allocate new buffer to fit appended data */
10420 pkcs7->cachedEncryptedContent = (byte*)XMALLOC(oldCacheSz + inSz,
10421 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10422 if (pkcs7->cachedEncryptedContent == NULL) {
10423 pkcs7->cachedEncryptedContentSz = 0;
10424 XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10425 return MEMORY_E;
10426 }
10427
10428 if (oldCache != NULL) {
10429 XMEMCPY(pkcs7->cachedEncryptedContent, oldCache, oldCacheSz);
10430 }
10431 XMEMCPY(pkcs7->cachedEncryptedContent + oldCacheSz, in, inSz);
10432 pkcs7->cachedEncryptedContentSz += inSz;
10433
10434 XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10435
10436 return 0;
10437 }
10438
10439
10440 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
wc_PKCS7_DecodeEnvelopedData(PKCS7 * pkcs7,byte * in,word32 inSz,byte * output,word32 outputSz)10441 WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
10442 word32 inSz, byte* output,
10443 word32 outputSz)
10444 {
10445 int recipFound = 0;
10446 int ret, length = 0;
10447 word32 idx = 0;
10448 #ifndef NO_PKCS7_STREAM
10449 word32 tmpIdx = 0;
10450 #endif
10451 word32 contentType = 0, encOID = 0;
10452 word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
10453
10454 int expBlockSz = 0, blockKeySz = 0;
10455 byte tmpIvBuf[MAX_CONTENT_IV_SIZE];
10456 byte* tmpIv = tmpIvBuf;
10457
10458 byte* pkiMsg = in;
10459 word32 pkiMsgSz = inSz;
10460 byte* decryptedKey = NULL;
10461 int encryptedContentTotalSz = 0;
10462 int encryptedContentSz = 0;
10463 byte padLen;
10464 byte* encryptedContent = NULL;
10465 int explicitOctet = 0;
10466 word32 localIdx;
10467 byte tag;
10468
10469 if (pkcs7 == NULL)
10470 return BAD_FUNC_ARG;
10471
10472 if (pkiMsg == NULL || pkiMsgSz == 0 ||
10473 output == NULL || outputSz == 0)
10474 return BAD_FUNC_ARG;
10475
10476 #ifndef NO_PKCS7_STREAM
10477 (void)tmpIv; /* help out static analysis */
10478 if (pkcs7->stream == NULL) {
10479 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
10480 return ret;
10481 }
10482 }
10483 #endif
10484
10485 switch (pkcs7->state) {
10486 case WC_PKCS7_START:
10487 case WC_PKCS7_INFOSET_START:
10488 case WC_PKCS7_INFOSET_BER:
10489 case WC_PKCS7_INFOSET_STAGE1:
10490 case WC_PKCS7_INFOSET_STAGE2:
10491 case WC_PKCS7_INFOSET_END:
10492 ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz,
10493 &idx, ENVELOPED_DATA);
10494 if (ret < 0) {
10495 break;
10496 }
10497
10498 #ifdef ASN_BER_TO_DER
10499 /* check if content was BER and has been converted to DER */
10500 if (pkcs7->derSz > 0)
10501 pkiMsg = in = pkcs7->der;
10502 #endif
10503
10504 decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
10505 DYNAMIC_TYPE_PKCS7);
10506 if (decryptedKey == NULL)
10507 return MEMORY_E;
10508 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2);
10509 #ifndef NO_PKCS7_STREAM
10510 tmpIdx = idx;
10511 pkcs7->stream->aad = decryptedKey;
10512 #endif
10513 FALL_THROUGH;
10514
10515 case WC_PKCS7_ENV_2:
10516 #ifndef NO_PKCS7_STREAM
10517 /* store up enough buffer for initial info set decode */
10518 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
10519 MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
10520 return ret;
10521 }
10522 #endif
10523 FALL_THROUGH;
10524
10525 case WC_PKCS7_DECRYPT_KTRI:
10526 case WC_PKCS7_DECRYPT_KTRI_2:
10527 case WC_PKCS7_DECRYPT_KTRI_3:
10528 case WC_PKCS7_DECRYPT_KARI:
10529 case WC_PKCS7_DECRYPT_KEKRI:
10530 case WC_PKCS7_DECRYPT_PWRI:
10531 case WC_PKCS7_DECRYPT_ORI:
10532 #ifndef NO_PKCS7_STREAM
10533 decryptedKey = pkcs7->stream->aad;
10534 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
10535 #endif
10536
10537 ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
10538 decryptedKey, &decryptedKeySz,
10539 &recipFound);
10540 if (ret == 0 && recipFound == 0) {
10541 WOLFSSL_MSG("No recipient found in envelopedData that matches input");
10542 ret = PKCS7_RECIP_E;
10543 }
10544
10545 if (ret != 0)
10546 break;
10547 #ifndef NO_PKCS7_STREAM
10548 tmpIdx = idx;
10549 pkcs7->stream->aadSz = decryptedKeySz;
10550 #endif
10551 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3);
10552 FALL_THROUGH;
10553
10554 case WC_PKCS7_ENV_3:
10555
10556 #ifndef NO_PKCS7_STREAM
10557 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
10558 MAX_VERSION_SZ + ASN_TAG_SZ +
10559 MAX_LENGTH_SZ, &pkiMsg, &idx))
10560 != 0) {
10561 return ret;
10562 }
10563 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10564 #else
10565 ret = 0;
10566 #endif
10567
10568 /* remove EncryptedContentInfo */
10569 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
10570 NO_USER_CHECK) < 0) {
10571 ret = ASN_PARSE_E;
10572 }
10573
10574 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
10575 pkiMsgSz) < 0) {
10576 ret = ASN_PARSE_E;
10577 }
10578
10579 if (ret == 0) {
10580 pkcs7->contentOID = contentType;
10581 }
10582
10583 if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
10584 pkiMsgSz) < 0) {
10585 ret = ASN_PARSE_E;
10586 }
10587
10588 blockKeySz = wc_PKCS7_GetOIDKeySize(encOID);
10589 if (ret == 0 && blockKeySz < 0) {
10590 ret = blockKeySz;
10591 }
10592
10593 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
10594 if (ret == 0 && expBlockSz < 0) {
10595 ret = expBlockSz;
10596 }
10597
10598 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
10599 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) != 0) {
10600 ret = ASN_PARSE_E;
10601 }
10602
10603 if (ret == 0 && tag != ASN_OCTET_STRING) {
10604 ret = ASN_PARSE_E;
10605 }
10606
10607 if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, pkiMsgSz,
10608 NO_USER_CHECK) < 0) {
10609 ret = ASN_PARSE_E;
10610 }
10611
10612 if (ret == 0 && length != expBlockSz) {
10613 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
10614 ret = ASN_PARSE_E;
10615 }
10616
10617 if (ret != 0)
10618 break;
10619 #ifndef NO_PKCS7_STREAM
10620 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
10621 break;
10622 }
10623 wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length);
10624 pkcs7->stream->contentSz = blockKeySz;
10625 pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ +
10626 ASN_TAG_SZ + ASN_TAG_SZ;
10627 #endif
10628 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4);
10629 FALL_THROUGH;
10630
10631 case WC_PKCS7_ENV_4:
10632
10633 #ifndef NO_PKCS7_STREAM
10634 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
10635 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
10636 return ret;
10637 }
10638 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10639
10640 wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length);
10641 tmpIv = pkcs7->stream->tmpIv;
10642 if (tmpIv == NULL) {
10643 /* check added to help out static analysis tool */
10644 ret = MEMORY_E;
10645 break;
10646 }
10647 #else
10648 ret = 0;
10649 #endif
10650
10651 XMEMCPY(tmpIv, &pkiMsg[idx], length);
10652 idx += length;
10653
10654 explicitOctet = 0;
10655 localIdx = idx;
10656 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
10657 tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
10658 explicitOctet = 1;
10659 }
10660
10661 /* read encryptedContent, cont[0] */
10662 if (tag != (ASN_CONTEXT_SPECIFIC | 0) &&
10663 tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
10664 ret = ASN_PARSE_E;
10665 }
10666 idx++;
10667
10668 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentTotalSz,
10669 pkiMsgSz) <= 0) {
10670 ret = ASN_PARSE_E;
10671 }
10672
10673 if (ret != 0)
10674 break;
10675
10676 #ifndef NO_PKCS7_STREAM
10677 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
10678 break;
10679 }
10680 pkcs7->stream->expected = encryptedContentTotalSz;
10681 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0);
10682 wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, explicitOctet);
10683 #endif
10684 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5);
10685 FALL_THROUGH;
10686
10687 case WC_PKCS7_ENV_5:
10688
10689 #ifndef NO_PKCS7_STREAM
10690 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
10691 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
10692 return ret;
10693 }
10694
10695 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &explicitOctet);
10696 tmpIv = pkcs7->stream->tmpIv;
10697 encryptedContentTotalSz = pkcs7->stream->expected;
10698
10699 /* restore decrypted key */
10700 decryptedKey = pkcs7->stream->aad;
10701 decryptedKeySz = pkcs7->stream->aadSz;
10702 blockKeySz = pkcs7->stream->contentSz;
10703 #else
10704 ret = 0;
10705 #endif
10706
10707 if (explicitOctet) {
10708 /* encrypted content may be fragmented into multiple
10709 * consecutive OCTET STRINGs, if so loop through
10710 * collecting and caching encrypted content bytes */
10711 localIdx = idx;
10712 while (idx < (localIdx + encryptedContentTotalSz)) {
10713
10714 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
10715 ret = ASN_PARSE_E;
10716 }
10717
10718 if (ret == 0 && (tag != ASN_OCTET_STRING)) {
10719 ret = ASN_PARSE_E;
10720 }
10721
10722 if (ret == 0 && GetLength(pkiMsg, &idx,
10723 &encryptedContentSz, pkiMsgSz) <= 0) {
10724 ret = ASN_PARSE_E;
10725 }
10726
10727 if (ret == 0) {
10728 ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx],
10729 encryptedContentSz);
10730 }
10731
10732 if (ret != 0) {
10733 break;
10734 }
10735
10736 /* advance idx past encrypted content */
10737 idx += encryptedContentSz;
10738 }
10739
10740 if (ret != 0) {
10741 break;
10742 }
10743
10744 } else {
10745 /* cache encrypted content, no OCTET STRING */
10746 ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx],
10747 encryptedContentTotalSz);
10748 if (ret != 0) {
10749 break;
10750 }
10751 idx += encryptedContentTotalSz;
10752 }
10753
10754 /* use cached content */
10755 encryptedContent = pkcs7->cachedEncryptedContent;
10756 encryptedContentSz = pkcs7->cachedEncryptedContentSz;
10757
10758 /* decrypt encryptedContent */
10759 ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey,
10760 blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0,
10761 encryptedContent, encryptedContentSz, encryptedContent);
10762 if (ret != 0) {
10763 break;
10764 }
10765
10766 padLen = encryptedContent[encryptedContentSz-1];
10767
10768 /* copy plaintext to output */
10769 if (padLen > encryptedContentSz ||
10770 (word32)(encryptedContentSz - padLen) > outputSz) {
10771 ret = BUFFER_E;
10772 break;
10773 }
10774 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
10775
10776 /* free memory, zero out keys */
10777 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
10778 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10779 if (pkcs7->cachedEncryptedContent != NULL) {
10780 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
10781 DYNAMIC_TYPE_PKCS7);
10782 pkcs7->cachedEncryptedContent = NULL;
10783 pkcs7->cachedEncryptedContentSz = 0;
10784 }
10785
10786 ret = encryptedContentSz - padLen;
10787 #ifndef NO_PKCS7_STREAM
10788 pkcs7->stream->aad = NULL;
10789 pkcs7->stream->aadSz = 0;
10790 wc_PKCS7_ResetStream(pkcs7);
10791 #endif
10792 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
10793 break;
10794
10795 default:
10796 WOLFSSL_MSG("PKCS#7 unknown decode enveloped state");
10797 ret = BAD_FUNC_ARG;
10798 }
10799
10800 #ifndef NO_PKCS7_STREAM
10801 if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) {
10802 wc_PKCS7_ResetStream(pkcs7);
10803 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
10804 if (pkcs7->cachedEncryptedContent != NULL) {
10805 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
10806 DYNAMIC_TYPE_PKCS7);
10807 pkcs7->cachedEncryptedContent = NULL;
10808 pkcs7->cachedEncryptedContentSz = 0;
10809 }
10810 }
10811 #else
10812 if (decryptedKey != NULL && ret < 0) {
10813 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
10814 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10815 }
10816 if (pkcs7->cachedEncryptedContent != NULL && ret < 0) {
10817 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10818 pkcs7->cachedEncryptedContent = NULL;
10819 pkcs7->cachedEncryptedContentSz = 0;
10820 }
10821 #endif
10822 return ret;
10823 }
10824
10825
10826 /* build PKCS#7 authEnvelopedData content type, return enveloped size */
wc_PKCS7_EncodeAuthEnvelopedData(PKCS7 * pkcs7,byte * output,word32 outputSz)10827 int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
10828 word32 outputSz)
10829 {
10830 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
10831 int ret, idx = 0;
10832 int totalSz, encryptedOutSz;
10833
10834 int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
10835 byte contentInfoSeq[MAX_SEQ_SZ];
10836 byte outerContentType[MAX_ALGO_SZ];
10837 byte outerContent[MAX_SEQ_SZ];
10838
10839 int envDataSeqSz, verSz;
10840 byte envDataSeq[MAX_SEQ_SZ];
10841 byte ver[MAX_VERSION_SZ];
10842
10843 WC_RNG rng;
10844 int blockSz, blockKeySz;
10845 byte* encryptedContent;
10846
10847 Pkcs7EncodedRecip* tmpRecip = NULL;
10848 int recipSz, recipSetSz;
10849 byte recipSet[MAX_SET_SZ];
10850
10851 int encContentOctetSz, encContentSeqSz, contentTypeSz;
10852 int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz;
10853 byte encContentSeq[MAX_SEQ_SZ];
10854 byte contentType[MAX_ALGO_SZ];
10855 byte contentEncAlgo[MAX_ALGO_SZ];
10856 byte nonceOctetString[MAX_OCTET_STR_SZ];
10857 byte encContentOctet[MAX_OCTET_STR_SZ];
10858 byte macOctetString[MAX_OCTET_STR_SZ];
10859
10860 byte authTag[AES_BLOCK_SIZE];
10861 byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */
10862 byte macInt[MAX_VERSION_SZ];
10863 word32 nonceSz = 0, macIntSz = 0;
10864
10865 /* authAttribs */
10866 byte* flatAuthAttribs = NULL;
10867 byte authAttribSet[MAX_SET_SZ];
10868 EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ];
10869 word32 authAttribsSz = 0, authAttribsCount = 0;
10870 word32 authAttribsSetSz = 0;
10871
10872 byte* aadBuffer = NULL;
10873 word32 aadBufferSz = 0;
10874 byte authAttribAadSet[MAX_SET_SZ];
10875 word32 authAttribsAadSetSz = 0;
10876
10877 /* unauthAttribs */
10878 byte* flatUnauthAttribs = NULL;
10879 byte unauthAttribSet[MAX_SET_SZ];
10880 EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ];
10881 word32 unauthAttribsSz = 0, unauthAttribsCount = 0;
10882 word32 unauthAttribsSetSz = 0;
10883
10884
10885 PKCS7Attrib contentTypeAttrib;
10886 byte contentTypeValue[MAX_OID_SZ];
10887 /* contentType OID (1.2.840.113549.1.9.3) */
10888 const byte contentTypeOid[] =
10889 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
10890 0x09, 0x03 };
10891 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0)
10892 return BAD_FUNC_ARG;
10893
10894 if (output == NULL || outputSz == 0)
10895 return BAD_FUNC_ARG;
10896
10897 switch (pkcs7->encryptOID) {
10898 #ifdef HAVE_AESGCM
10899 #ifdef WOLFSSL_AES_128
10900 case AES128GCMb:
10901 break;
10902 #endif
10903 #ifdef WOLFSSL_AES_192
10904 case AES192GCMb:
10905 break;
10906 #endif
10907 #ifdef WOLFSSL_AES_256
10908 case AES256GCMb:
10909 break;
10910 #endif
10911 #endif
10912 #ifdef HAVE_AESCCM
10913 #ifdef WOLFSSL_AES_128
10914 case AES128CCMb:
10915 break;
10916 #endif
10917 #ifdef WOLFSSL_AES_192
10918 case AES192CCMb:
10919 break;
10920 #endif
10921 #ifdef WOLFSSL_AES_256
10922 case AES256CCMb:
10923 break;
10924 #endif
10925 #endif
10926 default:
10927 WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM");
10928 return BAD_FUNC_ARG;
10929 }
10930
10931 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
10932 if (blockKeySz < 0)
10933 return blockKeySz;
10934
10935 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
10936 if (blockSz < 0)
10937 return blockSz;
10938
10939 /* outer content type */
10940 ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType,
10941 sizeof(outerContentType));
10942 if (ret < 0)
10943 return ret;
10944
10945 outerContentTypeSz = ret;
10946
10947 /* version, defined as 0 in RFC 5083 */
10948 verSz = SetMyVersion(0, ver, 0);
10949
10950 /* generate random content encryption key */
10951 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
10952 if (ret != 0) {
10953 return ret;
10954 }
10955
10956 /* build RecipientInfo, only if user manually set singleCert and size */
10957 if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) {
10958 switch (pkcs7->publicKeyOID) {
10959 #ifndef NO_RSA
10960 case RSAk:
10961 ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert,
10962 pkcs7->singleCertSz, 0);
10963 break;
10964 #endif
10965 #ifdef HAVE_ECC
10966 case ECDSAk:
10967 ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert,
10968 pkcs7->singleCertSz,
10969 pkcs7->keyWrapOID,
10970 pkcs7->keyAgreeOID, pkcs7->ukm,
10971 pkcs7->ukmSz, 0);
10972 break;
10973 #endif
10974
10975 default:
10976 WOLFSSL_MSG("Unsupported RecipientInfo public key type");
10977 return BAD_FUNC_ARG;
10978 };
10979
10980 if (ret < 0) {
10981 WOLFSSL_MSG("Failed to create RecipientInfo");
10982 return ret;
10983 }
10984 }
10985
10986 recipSz = wc_PKCS7_GetRecipientListSize(pkcs7);
10987 if (recipSz < 0) {
10988 return ret;
10989
10990 } else if (recipSz == 0) {
10991 WOLFSSL_MSG("You must add at least one CMS recipient");
10992 return PKCS7_RECIP_E;
10993 }
10994 recipSetSz = SetSet(recipSz, recipSet);
10995
10996 /* generate random nonce and IV for encryption */
10997 switch (pkcs7->encryptOID) {
10998 #ifdef HAVE_AESGCM
10999 #ifdef WOLFSSL_AES_128
11000 case AES128GCMb:
11001 FALL_THROUGH;
11002 #endif
11003 #ifdef WOLFSSL_AES_192
11004 case AES192GCMb:
11005 FALL_THROUGH;
11006 #endif
11007 #ifdef WOLFSSL_AES_256
11008 case AES256GCMb:
11009 #endif
11010 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
11011 defined(WOLFSSL_AES_256)
11012 /* GCM nonce is GCM_NONCE_MID_SZ (12) */
11013 nonceSz = GCM_NONCE_MID_SZ;
11014 break;
11015 #endif
11016 #endif /* HAVE_AESGCM */
11017 #ifdef HAVE_AESCCM
11018 #ifdef WOLFSSL_AES_128
11019 case AES128CCMb:
11020 FALL_THROUGH;
11021 #endif
11022 #ifdef WOLFSSL_AES_192
11023 case AES192CCMb:
11024 FALL_THROUGH;
11025 #endif
11026 #ifdef WOLFSSL_AES_256
11027 case AES256CCMb:
11028 #endif
11029 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
11030 defined(WOLFSSL_AES_256)
11031 /* CCM nonce is CCM_NONCE_MIN_SZ (7) */
11032 nonceSz = CCM_NONCE_MIN_SZ;
11033 break;
11034 #endif
11035 #endif /* HAVE_AESCCM */
11036 }
11037
11038 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
11039 if (ret != 0)
11040 return ret;
11041
11042 ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz);
11043 wc_FreeRng(&rng);
11044 if (ret != 0) {
11045 return ret;
11046 }
11047
11048
11049 /* authAttribs: add contentType attrib if needed */
11050 if (pkcs7->contentOID != DATA) {
11051
11052 XMEMSET(&contentTypeAttrib, 0, sizeof contentTypeAttrib);
11053
11054 /* if type is not id-data, contentType attribute MUST be added */
11055 contentTypeAttrib.oid = contentTypeOid;
11056 contentTypeAttrib.oidSz = sizeof(contentTypeOid);
11057
11058 /* try to set from contentOID first, known types */
11059 ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue,
11060 sizeof(contentTypeValue));
11061 if (ret > 0) {
11062 contentTypeAttrib.value = contentTypeValue;
11063 contentTypeAttrib.valueSz = ret;
11064
11065 /* otherwise, try to set from custom content type */
11066 } else {
11067 if (pkcs7->contentTypeSz == 0) {
11068 WOLFSSL_MSG("CMS pkcs7->contentType must be set if "
11069 "contentOID is not");
11070 return BAD_FUNC_ARG;
11071 }
11072 contentTypeAttrib.value = pkcs7->contentType;
11073 contentTypeAttrib.valueSz = pkcs7->contentTypeSz;
11074 }
11075
11076 authAttribsSz += EncodeAttributes(authAttribs, 1,
11077 &contentTypeAttrib, 1);
11078 authAttribsCount += 1;
11079 }
11080
11081 /* authAttribs: add in user authenticated attributes */
11082 if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) {
11083 authAttribsSz += EncodeAttributes(authAttribs + authAttribsCount,
11084 MAX_AUTH_ATTRIBS_SZ - authAttribsCount,
11085 pkcs7->authAttribs,
11086 pkcs7->authAttribsSz);
11087 authAttribsCount += pkcs7->authAttribsSz;
11088 }
11089
11090 /* authAttribs: flatten authAttribs */
11091 if (authAttribsSz > 0 && authAttribsCount > 0) {
11092 flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap,
11093 DYNAMIC_TYPE_PKCS7);
11094 if (flatAuthAttribs == NULL) {
11095 return MEMORY_E;
11096 }
11097
11098 FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs,
11099 authAttribsCount);
11100
11101 authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz,
11102 authAttribSet);
11103
11104 /* From RFC5083, "For the purpose of constructing the AAD, the
11105 * IMPLICIT [1] tag in the authAttrs field is not used for the
11106 * DER encoding: rather a universal SET OF tag is used. */
11107 authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet);
11108
11109 /* allocate temp buffer to hold alternate attrib encoding for aad */
11110 aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz,
11111 pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11112 if (aadBuffer == NULL) {
11113 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11114 return MEMORY_E;
11115 }
11116
11117 /* build up alternate attrib encoding for aad */
11118 aadBufferSz = 0;
11119 XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz);
11120 aadBufferSz += authAttribsAadSetSz;
11121 XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz);
11122 aadBufferSz += authAttribsSz;
11123 }
11124
11125 /* build up unauthenticated attributes (unauthAttrs) */
11126 if (pkcs7->unauthAttribsSz > 0) {
11127 unauthAttribsSz = EncodeAttributes(unauthAttribs + unauthAttribsCount,
11128 MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount,
11129 pkcs7->unauthAttribs,
11130 pkcs7->unauthAttribsSz);
11131 unauthAttribsCount = pkcs7->unauthAttribsSz;
11132
11133 flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap,
11134 DYNAMIC_TYPE_PKCS7);
11135 if (flatUnauthAttribs == NULL) {
11136 if (aadBuffer)
11137 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11138 if (flatAuthAttribs)
11139 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11140 return MEMORY_E;
11141 }
11142
11143 FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs,
11144 unauthAttribsCount);
11145 unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz,
11146 unauthAttribSet);
11147 }
11148
11149 /* allocate encrypted content buffer */
11150 encryptedOutSz = pkcs7->contentSz;
11151 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
11152 DYNAMIC_TYPE_PKCS7);
11153 if (encryptedContent == NULL) {
11154 if (aadBuffer)
11155 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11156 if (flatUnauthAttribs)
11157 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11158 if (flatAuthAttribs)
11159 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11160 return MEMORY_E;
11161 }
11162
11163 /* encrypt content */
11164 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek,
11165 pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag,
11166 sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent);
11167
11168 if (aadBuffer) {
11169 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11170 aadBuffer = NULL;
11171 }
11172
11173 if (ret != 0) {
11174 if (flatUnauthAttribs)
11175 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11176 if (flatAuthAttribs)
11177 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11178 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11179 return ret;
11180 }
11181
11182 /* EncryptedContentInfo */
11183 ret = wc_SetContentType(pkcs7->contentOID, contentType,
11184 sizeof(contentType));
11185 if (ret < 0) {
11186 if (flatUnauthAttribs)
11187 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11188 if (flatAuthAttribs)
11189 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11190 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11191 return ret;
11192 }
11193
11194 contentTypeSz = ret;
11195
11196 /* put together nonce OCTET STRING */
11197 nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString);
11198
11199 /* put together aes-ICVlen INTEGER */
11200 macIntSz = SetMyVersion(sizeof(authTag), macInt, 0);
11201
11202 /* build up our ContentEncryptionAlgorithmIdentifier sequence,
11203 * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING
11204 * and tag size */
11205 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
11206 oidBlkType, nonceOctetStringSz + nonceSz +
11207 macIntSz);
11208
11209 if (contentEncAlgoSz == 0) {
11210 if (flatUnauthAttribs)
11211 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11212 if (flatAuthAttribs)
11213 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11214 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11215 return BAD_FUNC_ARG;
11216 }
11217
11218 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
11219 encContentOctet);
11220
11221 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
11222 nonceOctetStringSz + nonceSz + macIntSz +
11223 encContentOctetSz + encryptedOutSz,
11224 encContentSeq);
11225
11226 macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString);
11227
11228 /* keep track of sizes for outer wrapper layering */
11229 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
11230 contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz +
11231 encContentOctetSz + encryptedOutSz + authAttribsSz +
11232 authAttribsSetSz + macOctetStringSz + sizeof(authTag) +
11233 unauthAttribsSz + unauthAttribsSetSz;
11234
11235 /* EnvelopedData */
11236 envDataSeqSz = SetSequence(totalSz, envDataSeq);
11237 totalSz += envDataSeqSz;
11238
11239 /* outer content */
11240 outerContentSz = SetExplicit(0, totalSz, outerContent);
11241 totalSz += outerContentTypeSz;
11242 totalSz += outerContentSz;
11243
11244 /* ContentInfo */
11245 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
11246 totalSz += contentInfoSeqSz;
11247
11248 if (totalSz > (int)outputSz) {
11249 WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
11250 if (flatUnauthAttribs)
11251 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11252 if (flatAuthAttribs)
11253 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11254 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11255 return BUFFER_E;
11256 }
11257
11258 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
11259 idx += contentInfoSeqSz;
11260 XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
11261 idx += outerContentTypeSz;
11262 XMEMCPY(output + idx, outerContent, outerContentSz);
11263 idx += outerContentSz;
11264 XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
11265 idx += envDataSeqSz;
11266 XMEMCPY(output + idx, ver, verSz);
11267 idx += verSz;
11268 XMEMCPY(output + idx, recipSet, recipSetSz);
11269 idx += recipSetSz;
11270 /* copy in recipients from list */
11271 tmpRecip = pkcs7->recipList;
11272 while (tmpRecip != NULL) {
11273 XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz);
11274 idx += tmpRecip->recipSz;
11275 tmpRecip = tmpRecip->next;
11276 }
11277 wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
11278 XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
11279 idx += encContentSeqSz;
11280 XMEMCPY(output + idx, contentType, contentTypeSz);
11281 idx += contentTypeSz;
11282 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
11283 idx += contentEncAlgoSz;
11284 XMEMCPY(output + idx, nonceOctetString, nonceOctetStringSz);
11285 idx += nonceOctetStringSz;
11286 XMEMCPY(output + idx, nonce, nonceSz);
11287 idx += nonceSz;
11288 XMEMCPY(output + idx, macInt, macIntSz);
11289 idx += macIntSz;
11290 XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
11291 idx += encContentOctetSz;
11292 XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
11293 idx += encryptedOutSz;
11294
11295 /* authenticated attributes */
11296 if (flatAuthAttribs && authAttribsSz > 0) {
11297 XMEMCPY(output + idx, authAttribSet, authAttribsSetSz);
11298 idx += authAttribsSetSz;
11299 XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz);
11300 idx += authAttribsSz;
11301 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11302 }
11303
11304 XMEMCPY(output + idx, macOctetString, macOctetStringSz);
11305 idx += macOctetStringSz;
11306 XMEMCPY(output + idx, authTag, sizeof(authTag));
11307 idx += sizeof(authTag);
11308
11309 /* unauthenticated attributes */
11310 if (unauthAttribsSz > 0) {
11311 XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz);
11312 idx += unauthAttribsSetSz;
11313 XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz);
11314 idx += unauthAttribsSz;
11315 }
11316
11317 if (flatUnauthAttribs != NULL) {
11318 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11319 }
11320
11321 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11322
11323 return idx;
11324
11325 #else
11326 WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled");
11327 (void)pkcs7;
11328 (void)output;
11329 (void)outputSz;
11330
11331 return NOT_COMPILED_IN;
11332 #endif /* HAVE_AESGCM | HAVE_AESCCM */
11333 }
11334
11335
11336 /* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */
wc_PKCS7_DecodeAuthEnvelopedData(PKCS7 * pkcs7,byte * in,word32 inSz,byte * output,word32 outputSz)11337 WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in,
11338 word32 inSz, byte* output,
11339 word32 outputSz)
11340 {
11341 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
11342 int recipFound = 0;
11343 int ret = 0, length;
11344 word32 idx = 0;
11345 #ifndef NO_PKCS7_STREAM
11346 word32 tmpIdx = 0;
11347 #endif
11348 word32 contentType = 0, encOID = 0;
11349 word32 decryptedKeySz = 0;
11350 byte* pkiMsg = in;
11351 word32 pkiMsgSz = inSz;
11352
11353 int expBlockSz = 0, blockKeySz = 0;
11354 byte authTag[AES_BLOCK_SIZE];
11355 byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */
11356 int nonceSz = 0, authTagSz = 0, macSz = 0;
11357
11358 #ifdef WOLFSSL_SMALL_STACK
11359 byte* decryptedKey = NULL;
11360 #else
11361 byte decryptedKey[MAX_ENCRYPTED_KEY_SZ];
11362 #endif
11363 int encryptedContentSz = 0;
11364 byte* encryptedContent = NULL;
11365 int explicitOctet = 0;
11366
11367 byte authAttribSetByte = 0;
11368 byte* encodedAttribs = NULL;
11369 word32 encodedAttribIdx = 0, encodedAttribSz = 0;
11370 byte* authAttrib = NULL;
11371 int authAttribSz = 0;
11372 word32 localIdx;
11373 byte tag;
11374
11375 if (pkcs7 == NULL)
11376 return BAD_FUNC_ARG;
11377
11378 if (pkiMsg == NULL || pkiMsgSz == 0 ||
11379 output == NULL || outputSz == 0)
11380 return BAD_FUNC_ARG;
11381 #ifndef NO_PKCS7_STREAM
11382 if (pkcs7->stream == NULL) {
11383 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
11384 return ret;
11385 }
11386 }
11387 #endif
11388
11389 switch (pkcs7->state) {
11390 case WC_PKCS7_START:
11391 case WC_PKCS7_INFOSET_START:
11392 case WC_PKCS7_INFOSET_STAGE1:
11393 case WC_PKCS7_INFOSET_STAGE2:
11394 case WC_PKCS7_INFOSET_END:
11395 ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz,
11396 &idx, AUTH_ENVELOPED_DATA);
11397 if (ret < 0)
11398 break;
11399
11400 #ifndef NO_PKCS7_STREAM
11401 tmpIdx = idx;
11402 #endif
11403 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2);
11404 FALL_THROUGH;
11405
11406 case WC_PKCS7_AUTHENV_2:
11407 #ifndef NO_PKCS7_STREAM
11408 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
11409 MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
11410 break;
11411 }
11412 #endif
11413 #ifdef WOLFSSL_SMALL_STACK
11414 decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
11415 DYNAMIC_TYPE_PKCS7);
11416 if (decryptedKey == NULL) {
11417 ret = MEMORY_E;
11418 break;
11419 }
11420 #ifndef NO_PKCS7_STREAM
11421 pkcs7->stream->key = decryptedKey;
11422 #endif
11423 #endif
11424 FALL_THROUGH;
11425
11426 case WC_PKCS7_DECRYPT_KTRI:
11427 case WC_PKCS7_DECRYPT_KTRI_2:
11428 case WC_PKCS7_DECRYPT_KTRI_3:
11429 case WC_PKCS7_DECRYPT_KARI:
11430 case WC_PKCS7_DECRYPT_KEKRI:
11431 case WC_PKCS7_DECRYPT_PWRI:
11432 case WC_PKCS7_DECRYPT_ORI:
11433
11434 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
11435 #ifdef WOLFSSL_SMALL_STACK
11436 #ifndef NO_PKCS7_STREAM
11437 decryptedKey = pkcs7->stream->key;
11438 #endif
11439 #endif
11440
11441 ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
11442 decryptedKey, &decryptedKeySz,
11443 &recipFound);
11444 if (ret != 0) {
11445 break;
11446 }
11447
11448 if (recipFound == 0) {
11449 WOLFSSL_MSG("No recipient found in envelopedData that matches input");
11450 ret = PKCS7_RECIP_E;
11451 break;
11452 }
11453
11454 #ifndef NO_PKCS7_STREAM
11455 tmpIdx = idx;
11456 #endif
11457 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3);
11458 FALL_THROUGH;
11459
11460 case WC_PKCS7_AUTHENV_3:
11461 #ifndef NO_PKCS7_STREAM
11462 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
11463 MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ,
11464 &pkiMsg, &idx)) != 0) {
11465 break;
11466 }
11467 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
11468 #endif
11469
11470 /* remove EncryptedContentInfo */
11471 if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
11472 ret = ASN_PARSE_E;
11473 }
11474
11475 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
11476 pkiMsgSz) < 0) {
11477 ret = ASN_PARSE_E;
11478 }
11479
11480 if (ret == 0) {
11481 pkcs7->contentOID = contentType;
11482 }
11483
11484 if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
11485 pkiMsgSz) < 0) {
11486 ret = ASN_PARSE_E;
11487 }
11488
11489 blockKeySz = wc_PKCS7_GetOIDKeySize(encOID);
11490 if (ret == 0 && blockKeySz < 0) {
11491 ret = blockKeySz;
11492 }
11493
11494 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
11495 if (ret == 0 && expBlockSz < 0) {
11496 ret = expBlockSz;
11497 }
11498
11499 /* get nonce, stored in OPTIONAL parameter of AlgoID */
11500 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
11501 ret = ASN_PARSE_E;
11502 }
11503
11504 if (ret == 0 && tag != ASN_OCTET_STRING) {
11505 ret = ASN_PARSE_E;
11506 }
11507
11508 if (ret < 0)
11509 break;
11510
11511 #ifndef NO_PKCS7_STREAM
11512 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11513 break;
11514 }
11515 wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0);
11516 #endif
11517 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4);
11518 FALL_THROUGH;
11519
11520 case WC_PKCS7_AUTHENV_4:
11521
11522 #ifndef NO_PKCS7_STREAM
11523 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
11524 MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ,
11525 &pkiMsg, &idx)) != 0) {
11526 break;
11527 }
11528 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
11529 #endif
11530 if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) {
11531 ret = ASN_PARSE_E;
11532 }
11533
11534 if (ret == 0 && nonceSz > (int)sizeof(nonce)) {
11535 WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer");
11536 ret = ASN_PARSE_E;
11537 }
11538
11539 if (ret == 0) {
11540 XMEMCPY(nonce, &pkiMsg[idx], nonceSz);
11541 idx += nonceSz;
11542 }
11543
11544 /* get mac size, also stored in OPTIONAL parameter of AlgoID */
11545 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) {
11546 ret = ASN_PARSE_E;
11547 }
11548
11549 if (ret == 0) {
11550 explicitOctet = 0;
11551 localIdx = idx;
11552 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
11553 tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
11554 explicitOctet = 1;
11555
11556 /* read encryptedContent, cont[0] */
11557 ret = GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz);
11558 }
11559
11560 if (ret == 0 &&
11561 tag != (ASN_CONTEXT_SPECIFIC | 0) &&
11562 tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
11563 ret = ASN_PARSE_E;
11564 }
11565
11566 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
11567 pkiMsgSz) <= 0) {
11568 ret = ASN_PARSE_E;
11569 }
11570
11571 if (explicitOctet) {
11572 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
11573 ret = ASN_PARSE_E;
11574 }
11575 if (ret == 0 && tag != ASN_OCTET_STRING) {
11576 ret = ASN_PARSE_E;
11577 }
11578
11579 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
11580 pkiMsgSz) <= 0) {
11581 ret = ASN_PARSE_E;
11582 }
11583 }
11584
11585 if (ret < 0)
11586 break;
11587
11588 #ifndef NO_PKCS7_STREAM
11589 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11590 break;
11591 }
11592
11593 /* store nonce for later */
11594 if (nonceSz > 0) {
11595 pkcs7->stream->nonceSz = nonceSz;
11596 pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap,
11597 DYNAMIC_TYPE_PKCS7);
11598 if (pkcs7->stream->nonce == NULL) {
11599 ret = MEMORY_E;
11600 break;
11601 }
11602 else {
11603 XMEMCPY(pkcs7->stream->nonce, nonce, nonceSz);
11604 }
11605 }
11606
11607 pkcs7->stream->expected = encryptedContentSz;
11608 wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz,
11609 encryptedContentSz);
11610 #endif
11611
11612 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5);
11613 FALL_THROUGH;
11614
11615 case WC_PKCS7_AUTHENV_5:
11616 #ifndef NO_PKCS7_STREAM
11617 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
11618 ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected,
11619 &pkiMsg, &idx)) != 0) {
11620 break;
11621 }
11622 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
11623
11624 encryptedContentSz = pkcs7->stream->expected;
11625 #endif
11626
11627 encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
11628 DYNAMIC_TYPE_PKCS7);
11629 if (ret == 0 && encryptedContent == NULL) {
11630 ret = MEMORY_E;
11631 }
11632
11633 if (ret == 0) {
11634 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
11635 idx += encryptedContentSz;
11636 }
11637 #ifndef NO_PKCS7_STREAM
11638 pkcs7->stream->bufferPt = encryptedContent;
11639 #endif
11640
11641 /* may have IMPLICIT [1] authenticatedAttributes */
11642 localIdx = idx;
11643 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
11644 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
11645 encodedAttribIdx = idx;
11646 encodedAttribs = pkiMsg + idx;
11647 idx++;
11648
11649 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
11650 ret = ASN_PARSE_E;
11651 #ifndef NO_PKCS7_STREAM
11652 pkcs7->stream->expected = length;
11653 #endif
11654 encodedAttribSz = length + (idx - encodedAttribIdx);
11655
11656 if (ret != 0)
11657 break;
11658
11659 #ifndef NO_PKCS7_STREAM
11660 if (encodedAttribSz > 0) {
11661 pkcs7->stream->aadSz = encodedAttribSz;
11662 pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz,
11663 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11664 if (pkcs7->stream->aad == NULL) {
11665 ret = MEMORY_E;
11666 break;
11667 }
11668 else {
11669 XMEMCPY(pkcs7->stream->aad, encodedAttribs,
11670 (idx - encodedAttribIdx));
11671 }
11672 }
11673
11674 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11675 break;
11676 }
11677 #endif
11678 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB);
11679 }
11680 else {
11681 #ifndef NO_PKCS7_STREAM
11682 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11683 break;
11684 }
11685 #endif
11686 goto authenv_atrbend; /* jump over attribute cases */
11687 }
11688 FALL_THROUGH;
11689
11690 case WC_PKCS7_AUTHENV_ATRB:
11691 #ifndef NO_PKCS7_STREAM
11692 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
11693 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
11694 return ret;
11695 }
11696
11697 length = pkcs7->stream->expected;
11698 encodedAttribs = pkcs7->stream->aad;
11699 #else
11700 length = 0;
11701 #endif
11702
11703 /* save pointer and length */
11704 authAttrib = &pkiMsg[idx];
11705 authAttribSz = length;
11706
11707 if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) {
11708 WOLFSSL_MSG("Error parsing authenticated attributes");
11709 ret = ASN_PARSE_E;
11710 break;
11711 }
11712
11713 idx += length;
11714
11715 #ifndef NO_PKCS7_STREAM
11716 if (encodedAttribSz > 0) {
11717 XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length),
11718 authAttrib, authAttribSz);
11719 }
11720 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11721 break;
11722 }
11723
11724 #endif
11725 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND);
11726 FALL_THROUGH;
11727
11728 case WC_PKCS7_AUTHENV_ATRBEND:
11729 authenv_atrbend:
11730 #ifndef NO_PKCS7_STREAM
11731 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
11732 ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
11733 return ret;
11734 }
11735 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
11736
11737 if (pkcs7->stream->aadSz > 0) {
11738 encodedAttribSz = pkcs7->stream->aadSz;
11739 encodedAttribs = pkcs7->stream->aad;
11740 }
11741 #endif
11742
11743
11744 /* get authTag OCTET STRING */
11745 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
11746 ret = ASN_PARSE_E;
11747 }
11748 if (ret == 0 && tag != ASN_OCTET_STRING) {
11749 ret = ASN_PARSE_E;
11750 }
11751
11752 if (ret == 0 && GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) {
11753 ret = ASN_PARSE_E;
11754 }
11755
11756 if (ret == 0 && authTagSz > (int)sizeof(authTag)) {
11757 WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer");
11758 ret = ASN_PARSE_E;
11759 }
11760
11761 if (ret == 0) {
11762 XMEMCPY(authTag, &pkiMsg[idx], authTagSz);
11763 idx += authTagSz;
11764 }
11765
11766 if (ret == 0 && authAttrib != NULL) {
11767 /* temporarily swap authAttribs byte[0] to SET OF instead of
11768 * IMPLICIT [1], for aad calculation */
11769 authAttribSetByte = encodedAttribs[0];
11770
11771 encodedAttribs[0] = ASN_SET | ASN_CONSTRUCTED;
11772 }
11773
11774 if (ret < 0)
11775 break;
11776
11777 #ifndef NO_PKCS7_STREAM
11778 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
11779 break;
11780 }
11781 pkcs7->stream->expected = (pkcs7->stream->maxLen -
11782 pkcs7->stream->totalRd) + pkcs7->stream->length;
11783
11784
11785 /* store tag for later */
11786 if (authTagSz > 0) {
11787 pkcs7->stream->tagSz = authTagSz;
11788 pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap,
11789 DYNAMIC_TYPE_PKCS7);
11790 if (pkcs7->stream->tag == NULL) {
11791 ret = MEMORY_E;
11792 break;
11793 }
11794 else {
11795 XMEMCPY(pkcs7->stream->tag, authTag, authTagSz);
11796 }
11797 }
11798
11799 #endif
11800 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6);
11801 FALL_THROUGH;
11802
11803 case WC_PKCS7_AUTHENV_6:
11804 #ifndef NO_PKCS7_STREAM
11805 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
11806 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
11807 break;
11808 }
11809
11810 /* restore all variables needed */
11811 if (pkcs7->stream->nonceSz > 0) {
11812 nonceSz = pkcs7->stream->nonceSz;
11813 if (nonceSz > GCM_NONCE_MID_SZ) {
11814 WOLFSSL_MSG("PKCS7 saved nonce is too large");
11815 ret = BUFFER_E;
11816 break;
11817 }
11818 else {
11819 XMEMCPY(nonce, pkcs7->stream->nonce, nonceSz);
11820 }
11821 }
11822
11823 if (pkcs7->stream->tagSz > 0) {
11824 authTagSz = pkcs7->stream->tagSz;
11825 if (authTagSz > AES_BLOCK_SIZE) {
11826 WOLFSSL_MSG("PKCS7 saved tag is too large");
11827 ret = BUFFER_E;
11828 break;
11829 }
11830 else {
11831 XMEMCPY(authTag, pkcs7->stream->tag, authTagSz);
11832 }
11833 }
11834
11835 if (pkcs7->stream->aadSz > 0) {
11836 encodedAttribSz = pkcs7->stream->aadSz;
11837 encodedAttribs = pkcs7->stream->aad;
11838 }
11839
11840 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz,
11841 &encryptedContentSz);
11842 encryptedContent = pkcs7->stream->bufferPt;
11843 #ifdef WOLFSSL_SMALL_STACK
11844 decryptedKey = pkcs7->stream->key;
11845 #endif
11846 #endif
11847
11848 /* decrypt encryptedContent */
11849 ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey,
11850 blockKeySz, nonce, nonceSz, encodedAttribs, encodedAttribSz,
11851 authTag, authTagSz, encryptedContent, encryptedContentSz,
11852 encryptedContent);
11853 if (ret != 0) {
11854 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11855 return ret;
11856 }
11857
11858 if (authAttrib != NULL) {
11859 /* restore authAttrib IMPLICIT [1] */
11860 encodedAttribs[0] = authAttribSetByte;
11861 }
11862
11863 /* copy plaintext to output */
11864 XMEMCPY(output, encryptedContent, encryptedContentSz);
11865
11866 /* free memory, zero out keys */
11867 ForceZero(encryptedContent, encryptedContentSz);
11868 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11869 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
11870 #ifdef WOLFSSL_SMALL_STACK
11871 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11872 decryptedKey = NULL;
11873 #ifdef WOLFSSL_SMALL_STACK
11874 #ifndef NO_PKCS7_STREAM
11875 pkcs7->stream->key = NULL;
11876 #endif
11877 #endif
11878 #endif
11879 ret = encryptedContentSz;
11880 #ifndef NO_PKCS7_STREAM
11881 wc_PKCS7_ResetStream(pkcs7);
11882 #endif
11883 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
11884 break;
11885 default:
11886 WOLFSSL_MSG("Unknown PKCS7 state");
11887 ret = BAD_FUNC_ARG;
11888 }
11889
11890 #ifdef WOLFSSL_SMALL_STACK
11891 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) {
11892 if (decryptedKey != NULL) {
11893 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
11894 }
11895 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
11896 }
11897 #endif
11898 #ifndef NO_PKCS7_STREAM
11899 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) {
11900 wc_PKCS7_ResetStream(pkcs7);
11901 }
11902 #endif
11903
11904 return ret;
11905
11906 #else
11907 WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled");
11908 (void)pkcs7;
11909 (void)in;
11910 (void)inSz;
11911 (void)output;
11912 (void)outputSz;
11913
11914 return NOT_COMPILED_IN;
11915 #endif /* HAVE_AESGCM | HAVE_AESCCM */
11916 }
11917
11918
11919 #ifndef NO_PKCS7_ENCRYPTED_DATA
11920
11921 /* build PKCS#7 encryptedData content type, return encrypted size */
wc_PKCS7_EncodeEncryptedData(PKCS7 * pkcs7,byte * output,word32 outputSz)11922 int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
11923 {
11924 int ret, idx = 0;
11925 int totalSz, padSz, encryptedOutSz;
11926
11927 int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
11928 byte contentInfoSeq[MAX_SEQ_SZ];
11929 byte outerContentType[MAX_ALGO_SZ];
11930 byte outerContent[MAX_SEQ_SZ];
11931
11932 int encDataSeqSz, verSz, blockSz;
11933 byte encDataSeq[MAX_SEQ_SZ];
11934 byte ver[MAX_VERSION_SZ];
11935
11936 byte* plain = NULL;
11937 byte* encryptedContent = NULL;
11938
11939 int encContentOctetSz, encContentSeqSz, contentTypeSz;
11940 int contentEncAlgoSz, ivOctetStringSz;
11941 byte encContentSeq[MAX_SEQ_SZ];
11942 byte contentType[MAX_OID_SZ];
11943 byte contentEncAlgo[MAX_ALGO_SZ];
11944 byte tmpIv[MAX_CONTENT_IV_SIZE];
11945 byte ivOctetString[MAX_OCTET_STR_SZ];
11946 byte encContentOctet[MAX_OCTET_STR_SZ];
11947
11948 byte attribSet[MAX_SET_SZ];
11949 EncodedAttrib* attribs = NULL;
11950 word32 attribsSz;
11951 word32 attribsCount;
11952 word32 attribsSetSz;
11953
11954 byte* flatAttribs = NULL;
11955
11956 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
11957 pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
11958 pkcs7->encryptionKeySz == 0)
11959 return BAD_FUNC_ARG;
11960
11961 if (output == NULL || outputSz == 0)
11962 return BAD_FUNC_ARG;
11963
11964 if (pkcs7->version == 3) {
11965 verSz = SetMyVersion(0, ver, 0);
11966 outerContentTypeSz = 0;
11967 }
11968 else {
11969 /* outer content type */
11970 ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType,
11971 sizeof(outerContentType));
11972 if (ret < 0)
11973 return ret;
11974
11975 outerContentTypeSz = ret;
11976
11977 /* version, 2 if unprotectedAttrs present, 0 if absent */
11978 if (pkcs7->unprotectedAttribsSz > 0) {
11979 verSz = SetMyVersion(2, ver, 0);
11980 } else {
11981 verSz = SetMyVersion(0, ver, 0);
11982 }
11983 }
11984
11985 /* EncryptedContentInfo */
11986 ret = wc_SetContentType(pkcs7->contentOID, contentType,
11987 sizeof(contentType));
11988 if (ret < 0)
11989 return ret;
11990
11991 contentTypeSz = ret;
11992
11993 /* allocate encrypted content buffer, do PKCS#7 padding */
11994 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
11995 if (blockSz < 0)
11996 return blockSz;
11997
11998 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
11999 if (padSz < 0)
12000 return padSz;
12001
12002 encryptedOutSz = pkcs7->contentSz + padSz;
12003
12004 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
12005 DYNAMIC_TYPE_PKCS7);
12006 if (plain == NULL)
12007 return MEMORY_E;
12008
12009 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
12010 encryptedOutSz, blockSz);
12011 if (ret < 0) {
12012 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12013 return ret;
12014 }
12015
12016 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
12017 DYNAMIC_TYPE_PKCS7);
12018 if (encryptedContent == NULL) {
12019 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12020 return MEMORY_E;
12021 }
12022
12023 /* put together IV OCTET STRING */
12024 ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
12025
12026 /* build up ContentEncryptionAlgorithmIdentifier sequence,
12027 adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
12028 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
12029 oidBlkType, ivOctetStringSz + blockSz);
12030 if (contentEncAlgoSz == 0) {
12031 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12032 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12033 return BAD_FUNC_ARG;
12034 }
12035
12036 /* encrypt content */
12037 WOLFSSL_MSG("Encrypting the content");
12038 ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, blockSz);
12039 if (ret != 0) {
12040 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12041 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12042 return ret;
12043 }
12044
12045 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey,
12046 pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0,
12047 plain, encryptedOutSz, encryptedContent);
12048 if (ret != 0) {
12049 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12050 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12051 return ret;
12052 }
12053
12054 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
12055 encryptedOutSz, encContentOctet);
12056
12057 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
12058 ivOctetStringSz + blockSz +
12059 encContentOctetSz + encryptedOutSz,
12060 encContentSeq);
12061
12062 /* optional UnprotectedAttributes */
12063 if (pkcs7->unprotectedAttribsSz != 0) {
12064
12065 if (pkcs7->unprotectedAttribs == NULL) {
12066 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12067 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12068 return BAD_FUNC_ARG;
12069 }
12070
12071 attribs = (EncodedAttrib*)XMALLOC(
12072 sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz,
12073 pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12074 if (attribs == NULL) {
12075 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12076 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12077 return MEMORY_E;
12078 }
12079
12080 attribsCount = pkcs7->unprotectedAttribsSz;
12081 attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz,
12082 pkcs7->unprotectedAttribs,
12083 pkcs7->unprotectedAttribsSz);
12084
12085 flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12086 if (flatAttribs == NULL) {
12087 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12088 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12089 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12090 return MEMORY_E;
12091 }
12092
12093 FlattenAttributes(pkcs7, flatAttribs, attribs, attribsCount);
12094 attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet);
12095
12096 } else {
12097 attribsSz = 0;
12098 attribsSetSz = 0;
12099 }
12100
12101 /* keep track of sizes for outer wrapper layering */
12102 totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
12103 ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz +
12104 attribsSz + attribsSetSz;
12105
12106 /* EncryptedData */
12107 encDataSeqSz = SetSequence(totalSz, encDataSeq);
12108 totalSz += encDataSeqSz;
12109
12110 if (pkcs7->version != 3) {
12111 /* outer content */
12112 outerContentSz = SetExplicit(0, totalSz, outerContent);
12113 totalSz += outerContentTypeSz;
12114 totalSz += outerContentSz;
12115 /* ContentInfo */
12116 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
12117 totalSz += contentInfoSeqSz;
12118 } else {
12119 contentInfoSeqSz = 0;
12120 outerContentSz = 0;
12121 }
12122
12123 if (totalSz > (int)outputSz) {
12124 WOLFSSL_MSG("PKCS#7 output buffer too small");
12125 if (attribs != NULL)
12126 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12127 if (flatAttribs != NULL)
12128 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12129 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12130 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12131 return BUFFER_E;
12132 }
12133
12134 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
12135 idx += contentInfoSeqSz;
12136 XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
12137 idx += outerContentTypeSz;
12138 XMEMCPY(output + idx, outerContent, outerContentSz);
12139 idx += outerContentSz;
12140 XMEMCPY(output + idx, encDataSeq, encDataSeqSz);
12141 idx += encDataSeqSz;
12142 XMEMCPY(output + idx, ver, verSz);
12143 idx += verSz;
12144 XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
12145 idx += encContentSeqSz;
12146 XMEMCPY(output + idx, contentType, contentTypeSz);
12147 idx += contentTypeSz;
12148 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
12149 idx += contentEncAlgoSz;
12150 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
12151 idx += ivOctetStringSz;
12152 XMEMCPY(output + idx, tmpIv, blockSz);
12153 idx += blockSz;
12154 XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
12155 idx += encContentOctetSz;
12156 XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
12157 idx += encryptedOutSz;
12158
12159 if (pkcs7->unprotectedAttribsSz != 0) {
12160 XMEMCPY(output + idx, attribSet, attribsSetSz);
12161 idx += attribsSetSz;
12162 XMEMCPY(output + idx, flatAttribs, attribsSz);
12163 idx += attribsSz;
12164 }
12165
12166 if (attribs != NULL)
12167 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12168 if (flatAttribs != NULL)
12169 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12170 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12171 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12172
12173 return idx;
12174 }
12175
12176
12177 /* decode and store unprotected attributes in PKCS7->decodedAttrib. Return
12178 * 0 on success, negative on error. User must call wc_PKCS7_Free(). */
wc_PKCS7_DecodeUnprotectedAttributes(PKCS7 * pkcs7,byte * pkiMsg,word32 pkiMsgSz,word32 * inOutIdx)12179 static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
12180 word32 pkiMsgSz, word32* inOutIdx)
12181 {
12182 int ret, attribLen;
12183 word32 idx;
12184 byte tag;
12185
12186 if (pkcs7 == NULL || pkiMsg == NULL ||
12187 pkiMsgSz == 0 || inOutIdx == NULL)
12188 return BAD_FUNC_ARG;
12189
12190 idx = *inOutIdx;
12191
12192 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12193 return ASN_PARSE_E;
12194
12195 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
12196 return ASN_PARSE_E;
12197
12198 if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0)
12199 return ASN_PARSE_E;
12200
12201 /* loop through attributes */
12202 if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) {
12203 return ret;
12204 }
12205
12206 *inOutIdx = idx;
12207
12208 return 0;
12209 }
12210
12211
12212 /* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
wc_PKCS7_DecodeEncryptedData(PKCS7 * pkcs7,byte * in,word32 inSz,byte * output,word32 outputSz)12213 int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz,
12214 byte* output, word32 outputSz)
12215 {
12216 int ret = 0, version, length = 0, haveAttribs = 0;
12217 word32 idx = 0;
12218
12219 #ifndef NO_PKCS7_STREAM
12220 word32 tmpIdx = 0;
12221 #endif
12222 word32 contentType = 0, encOID;
12223
12224 int expBlockSz = 0;
12225 byte tmpIvBuf[MAX_CONTENT_IV_SIZE];
12226 byte *tmpIv = tmpIvBuf;
12227
12228 int encryptedContentSz = 0;
12229 byte padLen = 0;
12230 byte* encryptedContent = NULL;
12231
12232 byte* pkiMsg = in;
12233 word32 pkiMsgSz = inSz;
12234 byte tag;
12235
12236 if (pkcs7 == NULL ||
12237 ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) &&
12238 pkcs7->decryptionCb == NULL))
12239 return BAD_FUNC_ARG;
12240
12241 if (pkiMsg == NULL || pkiMsgSz == 0 ||
12242 output == NULL || outputSz == 0)
12243 return BAD_FUNC_ARG;
12244
12245 #ifndef NO_PKCS7_STREAM
12246 (void)tmpIv; /* help out static analysis */
12247 if (pkcs7->stream == NULL) {
12248 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
12249 return ret;
12250 }
12251 }
12252 #endif
12253
12254 switch (pkcs7->state) {
12255 case WC_PKCS7_START:
12256 #ifndef NO_PKCS7_STREAM
12257 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
12258 MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) {
12259 return ret;
12260 }
12261
12262 if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
12263 return ret;
12264 }
12265 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12266 #endif
12267
12268 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
12269 NO_USER_CHECK) < 0)
12270 ret = ASN_PARSE_E;
12271
12272 if (pkcs7->version != 3) { /* ContentInfo not in firmware bundles */
12273 /* read past ContentInfo, verify type is encrypted-data */
12274 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
12275 pkiMsgSz) < 0)
12276 ret = ASN_PARSE_E;
12277
12278 if (ret == 0 && contentType != ENCRYPTED_DATA) {
12279 WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
12280 ret = PKCS7_OID_E;
12281 }
12282 }
12283 if (ret != 0) break;
12284 #ifndef NO_PKCS7_STREAM
12285 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12286 break;
12287 }
12288 #endif
12289 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2);
12290 FALL_THROUGH;
12291 /* end of stage 1 */
12292
12293 case WC_PKCS7_STAGE2:
12294 #ifndef NO_PKCS7_STREAM
12295 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12296 MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg,
12297 &idx)) != 0) {
12298 return ret;
12299 }
12300 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12301 #endif
12302 if (pkcs7->version != 3) {
12303 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12304 ret = ASN_PARSE_E;
12305 if (ret == 0 && tag !=
12306 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
12307 ret = ASN_PARSE_E;
12308
12309 if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, pkiMsgSz,
12310 NO_USER_CHECK) < 0)
12311 ret = ASN_PARSE_E;
12312
12313 /* remove EncryptedData and version */
12314 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
12315 NO_USER_CHECK) < 0)
12316 ret = ASN_PARSE_E;
12317 }
12318
12319 if (ret != 0) break;
12320 #ifndef NO_PKCS7_STREAM
12321 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12322 break;
12323 }
12324 #endif
12325 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3);
12326 FALL_THROUGH;
12327 /* end of stage 2 */
12328
12329 case WC_PKCS7_STAGE3:
12330 #ifndef NO_PKCS7_STREAM
12331 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12332 MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2,
12333 &pkiMsg, &idx)) != 0) {
12334 return ret;
12335 }
12336 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12337 #endif
12338 /* get version, check later */
12339 haveAttribs = 0;
12340 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
12341 ret = ASN_PARSE_E;
12342
12343 /* remove EncryptedContentInfo */
12344 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
12345 NO_USER_CHECK) < 0)
12346 ret = ASN_PARSE_E;
12347
12348 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
12349 pkiMsgSz) < 0)
12350 ret = ASN_PARSE_E;
12351
12352 if (ret == 0) {
12353 pkcs7->contentOID = contentType;
12354 }
12355
12356 if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
12357 pkiMsgSz)) < 0)
12358 ret = ASN_PARSE_E;
12359 if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0)
12360 ret = expBlockSz;
12361
12362 if (ret != 0) break;
12363 #ifndef NO_PKCS7_STREAM
12364 /* store expBlockSz for later */
12365 pkcs7->stream->varOne = expBlockSz;
12366 pkcs7->stream->varTwo = encOID;
12367
12368 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12369 break;
12370 }
12371
12372 /* store version for later */
12373 pkcs7->stream->vers = version;
12374 #endif
12375 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4);
12376 FALL_THROUGH;
12377 /* end of stage 3 */
12378
12379 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
12380 case WC_PKCS7_STAGE4:
12381 #ifndef NO_PKCS7_STREAM
12382 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12383 ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
12384 return ret;
12385 }
12386 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12387
12388 /* restore saved variables */
12389 expBlockSz = pkcs7->stream->varOne;
12390 #endif
12391 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12392 ret = ASN_PARSE_E;
12393 if (ret == 0 && tag != ASN_OCTET_STRING)
12394 ret = ASN_PARSE_E;
12395
12396 if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
12397 ret = ASN_PARSE_E;
12398
12399 if (ret == 0 && length != expBlockSz) {
12400 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
12401 ret = ASN_PARSE_E;
12402 }
12403
12404 if (ret != 0) break;
12405 #ifndef NO_PKCS7_STREAM
12406 /* next chunk of data expected should have the IV */
12407 pkcs7->stream->expected = length;
12408
12409 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12410 break;
12411 }
12412 #endif
12413 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5);
12414 FALL_THROUGH;
12415 /* end of stage 4 */
12416
12417 case WC_PKCS7_STAGE5:
12418 #ifndef NO_PKCS7_STREAM
12419 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12420 pkcs7->stream->expected + ASN_TAG_SZ +
12421 MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
12422 return ret;
12423 }
12424 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12425
12426 /* use IV buffer from stream structure */
12427 tmpIv = pkcs7->stream->tmpIv;
12428 length = pkcs7->stream->expected;
12429 #endif
12430 XMEMCPY(tmpIv, &pkiMsg[idx], length);
12431 idx += length;
12432 /* read encryptedContent, cont[0] */
12433 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12434 ret = ASN_PARSE_E;
12435 if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0))
12436 ret = ASN_PARSE_E;
12437
12438 if (ret == 0 && GetLength_ex(pkiMsg, &idx, &encryptedContentSz,
12439 pkiMsgSz, NO_USER_CHECK) <= 0)
12440 ret = ASN_PARSE_E;
12441
12442 if (ret < 0)
12443 break;
12444 #ifndef NO_PKCS7_STREAM
12445 /* next chunk of data should contain encrypted content */
12446 pkcs7->stream->varThree = encryptedContentSz;
12447 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
12448 break;
12449 }
12450
12451 if (pkcs7->stream->totalRd + encryptedContentSz <
12452 pkcs7->stream->maxLen) {
12453 pkcs7->stream->flagOne = 1;
12454 }
12455
12456 pkcs7->stream->expected = (pkcs7->stream->maxLen -
12457 pkcs7->stream->totalRd) + pkcs7->stream->length;
12458
12459 #endif
12460 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6);
12461 FALL_THROUGH;
12462 /* end of stage 5 */
12463
12464 case WC_PKCS7_STAGE6:
12465 #ifndef NO_PKCS7_STREAM
12466 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12467 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
12468 return ret;
12469 }
12470 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12471
12472 /* restore saved variables */
12473 expBlockSz = pkcs7->stream->varOne;
12474 encOID = pkcs7->stream->varTwo;
12475 encryptedContentSz = pkcs7->stream->varThree;
12476 version = pkcs7->stream->vers;
12477 tmpIv = pkcs7->stream->tmpIv;
12478 #else
12479 encOID = 0;
12480 #endif
12481 if (ret == 0 && (encryptedContent = (byte*)XMALLOC(
12482 encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL) {
12483 ret = MEMORY_E;
12484 break;
12485 }
12486
12487 if (ret == 0) {
12488 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
12489 idx += encryptedContentSz;
12490
12491 /* decrypt encryptedContent */
12492 ret = wc_PKCS7_DecryptContent(pkcs7, encOID,
12493 pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv,
12494 expBlockSz, NULL, 0, NULL, 0, encryptedContent,
12495 encryptedContentSz, encryptedContent);
12496 if (ret != 0) {
12497 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12498 }
12499 }
12500
12501 if (ret == 0) {
12502 padLen = encryptedContent[encryptedContentSz-1];
12503
12504 if (padLen > encryptedContentSz) {
12505 WOLFSSL_MSG("Bad padding size found");
12506 ret = BUFFER_E;
12507 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12508 break;
12509 }
12510
12511 /* copy plaintext to output */
12512 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
12513
12514 /* get implicit[1] unprotected attributes, optional */
12515 wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
12516 pkcs7->decodedAttrib = NULL;
12517 #ifndef NO_PKCS7_STREAM
12518 if (pkcs7->stream->flagOne)
12519 #else
12520 if (idx < pkiMsgSz)
12521 #endif
12522 {
12523 haveAttribs = 1;
12524
12525 ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
12526 pkiMsgSz, &idx);
12527 if (ret != 0) {
12528 ForceZero(encryptedContent, encryptedContentSz);
12529 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12530 ret = ASN_PARSE_E;
12531 }
12532 }
12533 }
12534
12535 if (ret == 0) {
12536 ForceZero(encryptedContent, encryptedContentSz);
12537 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12538
12539 /* go back and check the version now that attribs have been processed */
12540 if (pkcs7->version == 3 && version != 0) {
12541 WOLFSSL_MSG("Wrong PKCS#7 FirmwareEncryptedData version");
12542 return ASN_VERSION_E;
12543 }
12544
12545 if (pkcs7->version != 3 &&
12546 ((haveAttribs == 0 && version != 0) ||
12547 (haveAttribs == 1 && version != 2))) {
12548 WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
12549 return ASN_VERSION_E;
12550 }
12551 ret = encryptedContentSz - padLen;
12552 }
12553
12554 if (ret != 0) break;
12555 #ifndef NO_PKCS7_STREAM
12556 wc_PKCS7_ResetStream(pkcs7);
12557 #endif
12558 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
12559 break;
12560
12561 default:
12562 WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state");
12563 return BAD_STATE_E;
12564 }
12565
12566 if (ret != 0) {
12567 #ifndef NO_PKCS7_STREAM
12568 /* restart in error case */
12569 wc_PKCS7_ResetStream(pkcs7);
12570 #endif
12571 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
12572 }
12573 return ret;
12574 }
12575
12576
12577 /* Function to set callback during decryption, this overrides the default
12578 * decryption function and can be used for choosing a key at run time based
12579 * on the parsed bundle so far.
12580 * returns 0 on success
12581 */
wc_PKCS7_SetDecodeEncryptedCb(PKCS7 * pkcs7,CallbackDecryptContent decryptionCb)12582 int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7,
12583 CallbackDecryptContent decryptionCb)
12584 {
12585 if (pkcs7 != NULL) {
12586 pkcs7->decryptionCb = decryptionCb;
12587 }
12588 return 0;
12589 }
12590
12591
12592 /* Set an optional user context that gets passed to callback
12593 * returns 0 on success
12594 */
wc_PKCS7_SetDecodeEncryptedCtx(PKCS7 * pkcs7,void * ctx)12595 int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx)
12596 {
12597 if (pkcs7 != NULL) {
12598 pkcs7->decryptionCtx = ctx;
12599 }
12600 return 0;
12601 }
12602 #endif /* NO_PKCS7_ENCRYPTED_DATA */
12603
12604 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
12605
12606 /* build PKCS#7 compressedData content type, return encrypted size */
wc_PKCS7_EncodeCompressedData(PKCS7 * pkcs7,byte * output,word32 outputSz)12607 int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz)
12608 {
12609 byte contentInfoSeq[MAX_SEQ_SZ];
12610 byte contentInfoTypeOid[MAX_OID_SZ];
12611 byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */
12612 byte compressedDataSeq[MAX_SEQ_SZ];
12613 byte cmsVersion[MAX_VERSION_SZ];
12614 byte compressAlgId[MAX_ALGO_SZ];
12615 byte encapContentInfoSeq[MAX_SEQ_SZ];
12616 byte contentTypeOid[MAX_OID_SZ];
12617 byte contentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */
12618 byte contentOctetStr[MAX_OCTET_STR_SZ];
12619
12620 int ret;
12621 word32 totalSz, idx;
12622 word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz;
12623 word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz;
12624 word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz;
12625 word32 contentOctetStrSz;
12626
12627 byte* compressed;
12628 word32 compressedSz;
12629
12630 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
12631 output == NULL || outputSz == 0) {
12632 return BAD_FUNC_ARG;
12633 }
12634
12635 /* allocate space for compressed content. The libz code says the compressed
12636 * buffer should be srcSz + 0.1% + 12. */
12637 compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12);
12638 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12639 if (compressed == NULL) {
12640 WOLFSSL_MSG("Error allocating memory for CMS compressed content");
12641 return MEMORY_E;
12642 }
12643
12644 /* compress content */
12645 ret = wc_Compress(compressed, compressedSz, pkcs7->content,
12646 pkcs7->contentSz, 0);
12647 if (ret < 0) {
12648 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12649 return ret;
12650 }
12651 compressedSz = (word32)ret;
12652
12653 /* eContent OCTET STRING, working backwards */
12654 contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr);
12655 totalSz = contentOctetStrSz + compressedSz;
12656
12657 /* EXPLICIT [0] eContentType */
12658 contentSeqSz = SetExplicit(0, totalSz, contentSeq);
12659 totalSz += contentSeqSz;
12660
12661 /* eContentType OBJECT IDENTIFIER */
12662 ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid,
12663 sizeof(contentTypeOid));
12664 if (ret < 0) {
12665 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12666 return ret;
12667 }
12668
12669 contentTypeOidSz = ret;
12670 totalSz += contentTypeOidSz;
12671
12672 /* EncapsulatedContentInfo SEQUENCE */
12673 encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq);
12674 totalSz += encapContentInfoSeqSz;
12675
12676 /* compressionAlgorithm AlgorithmIdentifier */
12677 /* Only supports zlib for compression currently:
12678 * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */
12679 compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0);
12680 totalSz += compressAlgIdSz;
12681
12682 /* version */
12683 cmsVersionSz = SetMyVersion(0, cmsVersion, 0);
12684 totalSz += cmsVersionSz;
12685
12686 /* CompressedData SEQUENCE */
12687 compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq);
12688 totalSz += compressedDataSeqSz;
12689
12690 if (pkcs7->version == 3) {
12691 /* RFC 4108 section 2
12692 * When the SignedData is version 3 and eContent is compressedData then
12693 * the encoding is :
12694 * CompressedData {
12695 * version
12696 * compressionAlgorithm
12697 * encapContentInfo
12698 * }
12699 */
12700 contentInfoSeqSz = 0;
12701 contentInfoTypeOidSz = 0;
12702 contentInfoContentSeqSz = 0;
12703 }
12704 else {
12705 /* EncryptedData eContent type is encoded with:
12706 * EncryptedData {
12707 * version
12708 * EncryptedContentInfo {
12709 * contentType (i.e id-ct-compressedData)
12710 * contentEncryptionAlgorithm
12711 * octet string of CompressedData or FirmwarePkgData
12712 * }
12713 * attributes
12714 * }
12715 */
12716
12717 /* ContentInfo content EXPLICIT SEQUENCE */
12718 contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq);
12719 totalSz += contentInfoContentSeqSz;
12720
12721 ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid,
12722 sizeof(contentInfoTypeOid));
12723 if (ret < 0) {
12724 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12725 return ret;
12726 }
12727
12728 contentInfoTypeOidSz = ret;
12729 totalSz += contentInfoTypeOidSz;
12730
12731 /* ContentInfo SEQUENCE */
12732 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
12733 totalSz += contentInfoSeqSz;
12734 }
12735
12736 if (outputSz < totalSz) {
12737 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12738 return BUFFER_E;
12739 }
12740
12741 idx = 0;
12742 if (contentInfoSeqSz > 0) {
12743 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
12744 idx += contentInfoSeqSz;
12745 }
12746 if (contentInfoTypeOidSz > 0) {
12747 XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz);
12748 idx += contentInfoTypeOidSz;
12749 }
12750 if (contentInfoContentSeqSz > 0) {
12751 XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz);
12752 idx += contentInfoContentSeqSz;
12753 }
12754 XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz);
12755 idx += compressedDataSeqSz;
12756 XMEMCPY(output + idx, cmsVersion, cmsVersionSz);
12757 idx += cmsVersionSz;
12758 XMEMCPY(output + idx, compressAlgId, compressAlgIdSz);
12759 idx += compressAlgIdSz;
12760 XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz);
12761 idx += encapContentInfoSeqSz;
12762 XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz);
12763 idx += contentTypeOidSz;
12764 XMEMCPY(output + idx, contentSeq, contentSeqSz);
12765 idx += contentSeqSz;
12766 XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz);
12767 idx += contentOctetStrSz;
12768 XMEMCPY(output + idx, compressed, compressedSz);
12769 idx += compressedSz;
12770
12771 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12772
12773 return idx;
12774 }
12775
12776 /* unwrap and decompress PKCS#7/CMS compressedData object,
12777 * Handles content wrapped compressed data and raw compressed data packet
12778 * returned decoded size */
wc_PKCS7_DecodeCompressedData(PKCS7 * pkcs7,byte * pkiMsg,word32 pkiMsgSz,byte * output,word32 outputSz)12779 int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
12780 byte* output, word32 outputSz)
12781 {
12782 int length, version, ret;
12783 word32 idx = 0, algOID, contentType;
12784 byte tag;
12785
12786 byte* decompressed;
12787 word32 decompressedSz;
12788
12789 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 ||
12790 output == NULL || outputSz == 0) {
12791 return BAD_FUNC_ARG;
12792 }
12793
12794 /* unwarp content surrounding if found */
12795 {
12796 word32 localIdx = idx;
12797 int err = 0;
12798
12799 /* get ContentInfo SEQUENCE */
12800 if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
12801 err = ASN_PARSE_E;
12802
12803 if (err == 0 && pkcs7->version != 3) {
12804 /* get ContentInfo contentType */
12805 if (wc_GetContentType(pkiMsg, &localIdx, &contentType, pkiMsgSz)
12806 < 0)
12807 err = ASN_PARSE_E;
12808
12809 if (err == 0 && contentType != COMPRESSED_DATA)
12810 err = ASN_PARSE_E;
12811 }
12812
12813 /* get ContentInfo content EXPLICIT SEQUENCE */
12814 if (err == 0) {
12815 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
12816 err = ASN_PARSE_E;
12817 }
12818
12819 if (err == 0) {
12820 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
12821 err = ASN_PARSE_E;
12822 }
12823
12824 if (err == 0) {
12825 if (GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
12826 err = ASN_PARSE_E;
12827 }
12828
12829 /* successful content unwrap, update index */
12830 if (err == 0) {
12831 idx = localIdx;
12832 }
12833 }
12834
12835 /* get CompressedData SEQUENCE */
12836 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
12837 return ASN_PARSE_E;
12838
12839 /* get version */
12840 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
12841 return ASN_PARSE_E;
12842
12843 if (version != 0) {
12844 WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not");
12845 return ASN_PARSE_E;
12846 }
12847
12848 /* get CompressionAlgorithmIdentifier */
12849 if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0)
12850 return ASN_PARSE_E;
12851
12852 /* Only supports zlib for compression currently:
12853 * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */
12854 if (algOID != ZLIBc) {
12855 WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm");
12856 return ASN_PARSE_E;
12857 }
12858
12859 /* get EncapsulatedContentInfo SEQUENCE */
12860 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
12861 return ASN_PARSE_E;
12862
12863 /* get ContentType OID */
12864 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
12865 return ASN_PARSE_E;
12866
12867 pkcs7->contentOID = contentType;
12868
12869 /* get eContent EXPLICIT SEQUENCE */
12870 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12871 return ASN_PARSE_E;
12872
12873 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
12874 return ASN_PARSE_E;
12875
12876 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
12877 return ASN_PARSE_E;
12878
12879 /* get content OCTET STRING */
12880 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
12881 return ASN_PARSE_E;
12882
12883 if (tag != ASN_OCTET_STRING)
12884 return ASN_PARSE_E;
12885
12886 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
12887 return ASN_PARSE_E;
12888
12889 /* decompress content */
12890 ret = wc_DeCompressDynamic(&decompressed, WOLFSSL_PKCS7_MAX_DECOMPRESSION,
12891 DYNAMIC_TYPE_PKCS7, &pkiMsg[idx], length, 0, pkcs7->heap);
12892 if (ret < 0) {
12893 return ret;
12894 }
12895 decompressedSz = (word32)ret;
12896
12897 /* get content */
12898 if (outputSz < decompressedSz) {
12899 WOLFSSL_MSG("CMS output buffer too small to hold decompressed data");
12900 XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12901 return BUFFER_E;
12902 }
12903
12904 XMEMCPY(output, decompressed, decompressedSz);
12905 XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12906
12907 return decompressedSz;
12908 }
12909
12910 #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */
12911
12912 #else /* HAVE_PKCS7 */
12913
12914
12915 #ifdef _MSC_VER
12916 /* 4206 warning for blank file */
12917 #pragma warning(disable: 4206)
12918 #endif
12919
12920
12921 #endif /* HAVE_PKCS7 */
12922
12923