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