Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
pkcs7.c
00001 /* pkcs7.c 00002 * 00003 * Copyright (C) 2006-2020 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifdef HAVE_PKCS7 00030 00031 #include <wolfssl/wolfcrypt/pkcs7.h > 00032 #include <wolfssl/wolfcrypt/error-crypt.h > 00033 #include <wolfssl/wolfcrypt/logging.h > 00034 #include <wolfssl/wolfcrypt/hash.h > 00035 #ifndef NO_RSA 00036 #include <wolfssl/wolfcrypt/rsa.h > 00037 #endif 00038 #ifdef HAVE_ECC 00039 #include <wolfssl/wolfcrypt/ecc.h > 00040 #endif 00041 #ifdef HAVE_LIBZ 00042 #include <wolfssl/wolfcrypt/compress.h > 00043 #endif 00044 #ifndef NO_PWDBASED 00045 #include <wolfssl/wolfcrypt/pwdbased.h > 00046 #endif 00047 #ifdef NO_INLINE 00048 #include <wolfssl/wolfcrypt/misc.h> 00049 #else 00050 #define WOLFSSL_MISC_INCLUDED 00051 #include <wolfcrypt/src/misc.c> 00052 #endif 00053 00054 /* direction for processing, encoding or decoding */ 00055 typedef enum { 00056 WC_PKCS7_ENCODE, 00057 WC_PKCS7_DECODE 00058 } pkcs7Direction; 00059 00060 #define NO_USER_CHECK 0 00061 00062 /* holds information about the signers */ 00063 struct PKCS7SignerInfo { 00064 int version; 00065 byte *sid; 00066 word32 sidSz; 00067 }; 00068 00069 00070 #ifndef NO_PKCS7_STREAM 00071 00072 #define MAX_PKCS7_STREAM_BUFFER 256 00073 struct PKCS7State { 00074 byte* tmpCert; 00075 byte* bufferPt; 00076 byte* key; 00077 byte* nonce; /* stored nonce */ 00078 byte* aad; /* additional data for AEAD algos */ 00079 byte* tag; /* tag data for AEAD algos */ 00080 byte* content; 00081 byte* buffer; /* main internal read buffer */ 00082 00083 /* stack variables to store for when returning */ 00084 word32 varOne; 00085 int varTwo; 00086 int varThree; 00087 00088 word32 vers; 00089 word32 idx; /* index read into current input buffer */ 00090 word32 maxLen; /* sanity cap on maximum amount of data to allow 00091 * needed for GetSequence and other calls */ 00092 word32 length; /* amount of data stored */ 00093 word32 bufferSz; /* size of internal buffer */ 00094 word32 expected; /* next amount of data expected, if needed */ 00095 word32 totalRd; /* total amount of bytes read */ 00096 word32 nonceSz; /* size of nonce stored */ 00097 word32 aadSz; /* size of additional AEAD data */ 00098 word32 tagSz; /* size of tag for AEAD */ 00099 word32 contentSz; 00100 byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ 00101 #ifdef WC_PKCS7_STREAM_DEBUG 00102 word32 peakUsed; /* most bytes used for struct at any one time */ 00103 word32 peakRead; /* most bytes used by read buffer */ 00104 #endif 00105 byte multi:1; /* flag for if content is in multiple parts */ 00106 byte flagOne:1; 00107 byte detached:1; /* flag to indicate detached signature is present */ 00108 }; 00109 00110 00111 enum PKCS7_MaxLen { 00112 PKCS7_DEFAULT_PEEK = 0, 00113 PKCS7_SEQ_PEEK 00114 }; 00115 00116 /* creates a PKCS7State structure and returns 0 on success */ 00117 static int wc_PKCS7_CreateStream(PKCS7* pkcs7) 00118 { 00119 WOLFSSL_MSG("creating PKCS7 stream structure"); 00120 pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap, 00121 DYNAMIC_TYPE_PKCS7); 00122 if (pkcs7->stream == NULL) { 00123 return MEMORY_E; 00124 } 00125 XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); 00126 #ifdef WC_PKCS7_STREAM_DEBUG 00127 printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream); 00128 #endif 00129 return 0; 00130 } 00131 00132 00133 static void wc_PKCS7_ResetStream(PKCS7* pkcs7) 00134 { 00135 if (pkcs7 != NULL && pkcs7->stream != NULL) { 00136 #ifdef WC_PKCS7_STREAM_DEBUG 00137 /* collect final data point in case more was read right before reset */ 00138 if (pkcs7->stream->length > pkcs7->stream->peakRead) { 00139 pkcs7->stream->peakRead = pkcs7->stream->length; 00140 } 00141 if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + 00142 pkcs7->stream->nonceSz + pkcs7->stream->tagSz > 00143 pkcs7->stream->peakUsed) { 00144 pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + 00145 pkcs7->stream->aadSz + pkcs7->stream->nonceSz + 00146 pkcs7->stream->tagSz; 00147 } 00148 00149 /* print out debugging statistics */ 00150 if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) { 00151 printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d" 00152 "\n\tPeak read buffer bytes = %d" 00153 "\n\tTotal bytes read = %d" 00154 "\n", 00155 pkcs7->stream->peakUsed, pkcs7->stream->peakRead, 00156 pkcs7->stream->totalRd); 00157 } 00158 printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream); 00159 #endif 00160 00161 /* free any buffers that may be allocated */ 00162 XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00163 XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00164 XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00165 XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00166 XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00167 pkcs7->stream->aad = NULL; 00168 pkcs7->stream->tag = NULL; 00169 pkcs7->stream->nonce = NULL; 00170 pkcs7->stream->buffer = NULL; 00171 pkcs7->stream->key = NULL; 00172 00173 /* reset values, note that content and tmpCert are saved */ 00174 pkcs7->stream->maxLen = 0; 00175 pkcs7->stream->length = 0; 00176 pkcs7->stream->idx = 0; 00177 pkcs7->stream->expected = 0; 00178 pkcs7->stream->totalRd = 0; 00179 pkcs7->stream->bufferSz = 0; 00180 00181 pkcs7->stream->multi = 0; 00182 pkcs7->stream->flagOne = 0; 00183 pkcs7->stream->detached = 0; 00184 pkcs7->stream->varOne = 0; 00185 pkcs7->stream->varTwo = 0; 00186 pkcs7->stream->varThree = 0; 00187 } 00188 } 00189 00190 00191 static void wc_PKCS7_FreeStream(PKCS7* pkcs7) 00192 { 00193 if (pkcs7 != NULL && pkcs7->stream != NULL) { 00194 wc_PKCS7_ResetStream(pkcs7); 00195 00196 XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00197 XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00198 pkcs7->stream->content = NULL; 00199 pkcs7->stream->tmpCert = NULL; 00200 00201 XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00202 pkcs7->stream = NULL; 00203 } 00204 } 00205 00206 00207 /* used to increase the max size for internal buffer 00208 * returns 0 on success */ 00209 static int wc_PKCS7_GrowStream(PKCS7* pkcs7, word32 newSz) 00210 { 00211 byte* pt; 00212 00213 pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00214 if (pt == NULL) { 00215 return MEMORY_E; 00216 } 00217 XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz); 00218 00219 #ifdef WC_PKCS7_STREAM_DEBUG 00220 printf("PKCS7 increasing internal stream buffer %d -> %d\n", 00221 pkcs7->stream->bufferSz, newSz); 00222 #endif 00223 pkcs7->stream->bufferSz = newSz; 00224 XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00225 pkcs7->stream->buffer = pt; 00226 return 0; 00227 } 00228 00229 00230 /* pt gets set to the buffer that is holding data in the case that stream struct 00231 * is used. 00232 * 00233 * Sets idx to be the current offset into "pt" buffer 00234 * returns 0 on success 00235 */ 00236 static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, 00237 word32 expected, byte** pt, word32* idx) 00238 { 00239 word32 rdSz = pkcs7->stream->idx; 00240 00241 /* If the input size minus current index into input buffer is greater than 00242 * the expected size then use the input buffer. If data is already stored 00243 * in stream buffer or if there is not enough input data available then use 00244 * the stream buffer. */ 00245 if (inSz - rdSz >= expected && pkcs7->stream->length == 0) { 00246 /* storing input buffer is not needed */ 00247 *pt = in; /* reset in case previously used internal buffer */ 00248 *idx = rdSz; 00249 return 0; 00250 } 00251 00252 /* is there enough stored in buffer already? */ 00253 if (pkcs7->stream->length >= expected) { 00254 *idx = 0; /* start reading from beginning of stream buffer */ 00255 *pt = pkcs7->stream->buffer; 00256 return 0; 00257 } 00258 00259 /* check if all data has been read from input */ 00260 if (rdSz >= inSz) { 00261 /* no more input to read, reset input index and request more data */ 00262 pkcs7->stream->idx = 0; 00263 return WC_PKCS7_WANT_READ_E; 00264 } 00265 00266 /* try to store input data into stream buffer */ 00267 if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { 00268 int len = min(inSz - rdSz, expected - pkcs7->stream->length); 00269 00270 /* sanity check that the input buffer is not internal buffer */ 00271 if (in == pkcs7->stream->buffer) { 00272 return WC_PKCS7_WANT_READ_E; 00273 } 00274 00275 /* check if internal buffer size needs to be increased */ 00276 if (len + pkcs7->stream->length > pkcs7->stream->bufferSz) { 00277 int ret = wc_PKCS7_GrowStream(pkcs7, expected); 00278 if (ret < 0) { 00279 return ret; 00280 } 00281 } 00282 XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); 00283 pkcs7->stream->length += len; 00284 pkcs7->stream->idx += len; 00285 pkcs7->stream->totalRd += len; 00286 } 00287 00288 #ifdef WC_PKCS7_STREAM_DEBUG 00289 /* collects memory usage for debugging */ 00290 if (pkcs7->stream->length > pkcs7->stream->peakRead) { 00291 pkcs7->stream->peakRead = pkcs7->stream->length; 00292 } 00293 if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + 00294 pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { 00295 pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + 00296 pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; 00297 } 00298 #endif 00299 00300 /* if not enough data was read in then request more */ 00301 if (pkcs7->stream->length < expected) { 00302 pkcs7->stream->idx = 0; 00303 return WC_PKCS7_WANT_READ_E; 00304 } 00305 00306 /* adjust pointer to read from stored buffer */ 00307 *idx = 0; 00308 *pt = pkcs7->stream->buffer; 00309 return 0; 00310 } 00311 00312 00313 /* Does two things 00314 * 1) Tries to get the length from current buffer and set it as max length 00315 * 2) Retrieves the set max length 00316 * 00317 * if no flag value is set then the stored max length is returned. 00318 * returns length found on success and defSz if no stored data is found 00319 */ 00320 static long wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, 00321 word32 defSz) 00322 { 00323 /* check there is a buffer to read from */ 00324 if (pkcs7) { 00325 int length = 0, ret; 00326 word32 idx = 0, maxIdx; 00327 byte* pt; 00328 00329 if (flag != PKCS7_DEFAULT_PEEK) { 00330 if (pkcs7->stream->length > 0) { 00331 length = pkcs7->stream->length; 00332 pt = pkcs7->stream->buffer; 00333 } 00334 else { 00335 length = defSz; 00336 pt = in; 00337 } 00338 maxIdx = (word32)length; 00339 00340 if (length < MAX_SEQ_SZ) { 00341 WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); 00342 return 0; 00343 } 00344 if (flag == PKCS7_SEQ_PEEK) { 00345 if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, 00346 NO_USER_CHECK)) < 0) { 00347 return ret; 00348 } 00349 00350 #ifdef ASN_BER_TO_DER 00351 if (length == 0 && ret == 0) { 00352 idx = 0; 00353 if ((ret = wc_BerToDer(pt, defSz, NULL, 00354 (word32*)&length)) != LENGTH_ONLY_E) { 00355 return ret; 00356 } 00357 } 00358 #endif /* ASN_BER_TO_DER */ 00359 pkcs7->stream->maxLen = length + idx; 00360 } 00361 } 00362 00363 if (pkcs7->stream->maxLen == 0) { 00364 pkcs7->stream->maxLen = defSz; 00365 } 00366 00367 return pkcs7->stream->maxLen; 00368 } 00369 00370 return defSz; 00371 } 00372 00373 00374 /* setter function for stored variables */ 00375 static void wc_PKCS7_StreamStoreVar(PKCS7* pkcs7, word32 var1, int var2, 00376 int var3) 00377 { 00378 if (pkcs7 != NULL && pkcs7->stream != NULL) { 00379 pkcs7->stream->varOne = var1; 00380 pkcs7->stream->varTwo = var2; 00381 pkcs7->stream->varThree = var3; 00382 } 00383 } 00384 00385 /* getter function for stored variables */ 00386 static void wc_PKCS7_StreamGetVar(PKCS7* pkcs7, word32* var1, int* var2, 00387 int* var3) 00388 { 00389 if (pkcs7 != NULL && pkcs7->stream != NULL) { 00390 if (var1 != NULL) *var1 = pkcs7->stream->varOne; 00391 if (var2 != NULL) *var2 = pkcs7->stream->varTwo; 00392 if (var3 != NULL) *var3 = pkcs7->stream->varThree; 00393 } 00394 } 00395 00396 00397 /* common update of index and total read after section complete 00398 * returns 0 on success */ 00399 static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) 00400 { 00401 int ret = 0; 00402 00403 if (pkcs7->stream->length > 0) { 00404 if (pkcs7->stream->length < *idx) { 00405 WOLFSSL_MSG("PKCS7 read too much data from internal buffer"); 00406 ret = BUFFER_E; 00407 } 00408 else { 00409 XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx, 00410 pkcs7->stream->length - *idx); 00411 pkcs7->stream->length -= *idx; 00412 } 00413 } 00414 else { 00415 pkcs7->stream->totalRd += *idx - *tmpIdx; 00416 pkcs7->stream->idx = *idx; /* adjust index into input buffer */ 00417 *tmpIdx = *idx; 00418 } 00419 00420 return ret; 00421 } 00422 #endif /* NO_PKCS7_STREAM */ 00423 00424 #ifdef WC_PKCS7_STREAM_DEBUG 00425 /* used to print out human readable state for debugging */ 00426 static const char* wc_PKCS7_GetStateName(int in) 00427 { 00428 switch (in) { 00429 case WC_PKCS7_START: return "WC_PKCS7_START"; 00430 00431 case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2"; 00432 case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3"; 00433 case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4"; 00434 case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5"; 00435 case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6"; 00436 00437 /* parse info set */ 00438 case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; 00439 case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; 00440 case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1"; 00441 case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; 00442 case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; 00443 00444 /* decode enveloped data */ 00445 case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2"; 00446 case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3"; 00447 case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4"; 00448 case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5"; 00449 00450 /* decode auth enveloped */ 00451 case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; 00452 case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; 00453 case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4"; 00454 case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5"; 00455 case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6"; 00456 case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB"; 00457 case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND"; 00458 case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7"; 00459 00460 /* decryption state types */ 00461 case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; 00462 case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2"; 00463 case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3"; 00464 00465 case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; 00466 case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI"; 00467 case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; 00468 case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; 00469 case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; 00470 00471 case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2"; 00472 case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3"; 00473 case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4"; 00474 case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5"; 00475 case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6"; 00476 00477 default: 00478 return "Unknown state"; 00479 } 00480 } 00481 #endif 00482 00483 /* Used to change the PKCS7 state. Having state change as a function allows 00484 * for easier debugging */ 00485 static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState) 00486 { 00487 #ifdef WC_PKCS7_STREAM_DEBUG 00488 printf("\tChanging from state [%02d] %s to [%02d] %s\n", 00489 pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state), 00490 newState, wc_PKCS7_GetStateName(newState)); 00491 #endif 00492 pkcs7->state = newState; 00493 } 00494 00495 #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ 00496 MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) 00497 00498 00499 /* placed ASN.1 contentType OID into *output, return idx on success, 00500 * 0 upon failure */ 00501 static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) 00502 { 00503 /* PKCS#7 content types, RFC 2315, section 14 */ 00504 const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00505 0x0D, 0x01, 0x07 }; 00506 const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00507 0x0D, 0x01, 0x07, 0x01 }; 00508 const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00509 0x0D, 0x01, 0x07, 0x02}; 00510 const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00511 0x0D, 0x01, 0x07, 0x03 }; 00512 const byte authEnvelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00513 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17}; 00514 const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00515 0x0D, 0x01, 0x07, 0x04 }; 00516 const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00517 0x0D, 0x01, 0x07, 0x05 }; 00518 #ifndef NO_PKCS7_ENCRYPTED_DATA 00519 const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00520 0x0D, 0x01, 0x07, 0x06 }; 00521 #endif 00522 /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */ 00523 const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 00524 0x01, 0x09, 0x10, 0x01, 0x10 }; 00525 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) 00526 /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */ 00527 const byte compressedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 00528 0x01, 0x09, 0x10, 0x01, 0x09 }; 00529 #endif 00530 00531 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 00532 const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 00533 0x01, 0x09, 0x10, 0x03, 0x09 }; 00534 const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 00535 0x01, 0x05, 0x0C }; 00536 #endif 00537 00538 int idSz, idx = 0; 00539 word32 typeSz = 0; 00540 const byte* typeName = 0; 00541 byte ID_Length[MAX_LENGTH_SZ]; 00542 00543 switch (pkcs7TypeOID) { 00544 case PKCS7_MSG: 00545 typeSz = sizeof(pkcs7); 00546 typeName = pkcs7; 00547 break; 00548 00549 case DATA: 00550 typeSz = sizeof(data); 00551 typeName = data; 00552 break; 00553 00554 case SIGNED_DATA: 00555 typeSz = sizeof(signedData); 00556 typeName = signedData; 00557 break; 00558 00559 case ENVELOPED_DATA: 00560 typeSz = sizeof(envelopedData); 00561 typeName = envelopedData; 00562 break; 00563 00564 case AUTH_ENVELOPED_DATA: 00565 typeSz = sizeof(authEnvelopedData); 00566 typeName = authEnvelopedData; 00567 break; 00568 00569 case SIGNED_AND_ENVELOPED_DATA: 00570 typeSz = sizeof(signedAndEnveloped); 00571 typeName = signedAndEnveloped; 00572 break; 00573 00574 case DIGESTED_DATA: 00575 typeSz = sizeof(digestedData); 00576 typeName = digestedData; 00577 break; 00578 00579 #ifndef NO_PKCS7_ENCRYPTED_DATA 00580 case ENCRYPTED_DATA: 00581 typeSz = sizeof(encryptedData); 00582 typeName = encryptedData; 00583 break; 00584 #endif 00585 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) 00586 case COMPRESSED_DATA: 00587 typeSz = sizeof(compressedData); 00588 typeName = compressedData; 00589 break; 00590 #endif 00591 case FIRMWARE_PKG_DATA: 00592 typeSz = sizeof(firmwarePkgData); 00593 typeName = firmwarePkgData; 00594 break; 00595 00596 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 00597 case PWRI_KEK_WRAP: 00598 typeSz = sizeof(pwriKek); 00599 typeName = pwriKek; 00600 break; 00601 00602 case PBKDF2_OID: 00603 typeSz = sizeof(pbkdf2); 00604 typeName = pbkdf2; 00605 break; 00606 #endif 00607 00608 default: 00609 WOLFSSL_MSG("Unknown PKCS#7 Type"); 00610 return 0; 00611 }; 00612 00613 if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) { 00614 WOLFSSL_MSG("CMS content type buffer too small"); 00615 return BAD_FUNC_ARG; 00616 } 00617 00618 idSz = SetLength(typeSz, ID_Length); 00619 output[idx++] = ASN_OBJECT_ID; 00620 XMEMCPY(output + idx, ID_Length, idSz); 00621 idx += idSz; 00622 XMEMCPY(output + idx, typeName, typeSz); 00623 idx += typeSz; 00624 00625 return idx; 00626 } 00627 00628 00629 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */ 00630 static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, 00631 word32 maxIdx) 00632 { 00633 WOLFSSL_ENTER("wc_GetContentType"); 00634 if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) 00635 return ASN_PARSE_E; 00636 00637 return 0; 00638 } 00639 00640 00641 /* return block size for algorithm represented by oid, or <0 on error */ 00642 static int wc_PKCS7_GetOIDBlockSize(int oid) 00643 { 00644 int blockSz; 00645 00646 switch (oid) { 00647 #ifndef NO_AES 00648 #ifdef WOLFSSL_AES_128 00649 case AES128CBCb: 00650 case AES128GCMb: 00651 case AES128CCMb: 00652 #endif 00653 #ifdef WOLFSSL_AES_192 00654 case AES192CBCb: 00655 case AES192GCMb: 00656 case AES192CCMb: 00657 #endif 00658 #ifdef WOLFSSL_AES_256 00659 case AES256CBCb: 00660 case AES256GCMb: 00661 case AES256CCMb: 00662 #endif 00663 blockSz = AES_BLOCK_SIZE; 00664 break; 00665 #endif 00666 #ifndef NO_DES3 00667 case DESb: 00668 case DES3b: 00669 blockSz = DES_BLOCK_SIZE; 00670 break; 00671 #endif 00672 default: 00673 WOLFSSL_MSG("Unsupported content cipher type"); 00674 return ALGO_ID_E; 00675 }; 00676 00677 return blockSz; 00678 } 00679 00680 00681 /* get key size for algorithm represented by oid, or <0 on error */ 00682 static int wc_PKCS7_GetOIDKeySize(int oid) 00683 { 00684 int blockKeySz; 00685 00686 switch (oid) { 00687 #ifndef NO_AES 00688 #ifdef WOLFSSL_AES_128 00689 case AES128CBCb: 00690 case AES128GCMb: 00691 case AES128CCMb: 00692 case AES128_WRAP: 00693 blockKeySz = 16; 00694 break; 00695 #endif 00696 #ifdef WOLFSSL_AES_192 00697 case AES192CBCb: 00698 case AES192GCMb: 00699 case AES192CCMb: 00700 case AES192_WRAP: 00701 blockKeySz = 24; 00702 break; 00703 #endif 00704 #ifdef WOLFSSL_AES_256 00705 case AES256CBCb: 00706 case AES256GCMb: 00707 case AES256CCMb: 00708 case AES256_WRAP: 00709 blockKeySz = 32; 00710 break; 00711 #endif 00712 #endif 00713 #ifndef NO_DES3 00714 case DESb: 00715 blockKeySz = DES_KEYLEN; 00716 break; 00717 00718 case DES3b: 00719 blockKeySz = DES3_KEYLEN; 00720 break; 00721 #endif 00722 default: 00723 WOLFSSL_MSG("Unsupported content cipher type"); 00724 return ALGO_ID_E; 00725 }; 00726 00727 return blockKeySz; 00728 } 00729 00730 00731 PKCS7* wc_PKCS7_New(void* heap, int devId) 00732 { 00733 PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7); 00734 if (pkcs7) { 00735 XMEMSET(pkcs7, 0, sizeof(PKCS7)); 00736 if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) { 00737 pkcs7->isDynamic = 1; 00738 } 00739 else { 00740 XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7); 00741 pkcs7 = NULL; 00742 } 00743 } 00744 return pkcs7; 00745 } 00746 00747 /* This is to initialize a PKCS7 structure. It sets all values to 0 and can be 00748 * used to set the heap hint. 00749 * 00750 * pkcs7 PKCS7 structure to initialize 00751 * heap memory heap hint for PKCS7 structure to use 00752 * devId currently not used but a place holder for async operations 00753 * 00754 * returns 0 on success or a negative value for failure 00755 */ 00756 int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) 00757 { 00758 word16 isDynamic; 00759 00760 WOLFSSL_ENTER("wc_PKCS7_Init"); 00761 00762 if (pkcs7 == NULL) { 00763 return BAD_FUNC_ARG; 00764 } 00765 00766 isDynamic = pkcs7->isDynamic; 00767 XMEMSET(pkcs7, 0, sizeof(PKCS7)); 00768 pkcs7->isDynamic = isDynamic; 00769 #ifdef WOLFSSL_HEAP_TEST 00770 pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; 00771 #else 00772 pkcs7->heap = heap; 00773 #endif 00774 pkcs7->devId = devId; 00775 00776 return 0; 00777 } 00778 00779 00780 /* Certificate structure holding der pointer, size, and pointer to next 00781 * Pkcs7Cert struct. Used when creating SignedData types with multiple 00782 * certificates. */ 00783 struct Pkcs7Cert { 00784 byte* der; 00785 word32 derSz; 00786 Pkcs7Cert* next; 00787 }; 00788 00789 00790 /* Linked list of ASN.1 encoded RecipientInfos */ 00791 struct Pkcs7EncodedRecip { 00792 byte recip[MAX_RECIP_SZ]; 00793 word32 recipSz; 00794 int recipType; 00795 int recipVersion; 00796 Pkcs7EncodedRecip* next; 00797 }; 00798 00799 00800 /* free all members of Pkcs7Cert linked list */ 00801 static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) 00802 { 00803 Pkcs7Cert* curr = NULL; 00804 Pkcs7Cert* next = NULL; 00805 00806 if (pkcs7 == NULL) 00807 return; 00808 00809 curr = pkcs7->certList; 00810 pkcs7->certList = NULL; 00811 00812 while (curr != NULL) { 00813 next = curr->next; 00814 curr->next = NULL; 00815 XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00816 curr = next; 00817 } 00818 00819 return; 00820 } 00821 00822 00823 /* Get total size of all recipients in recipient list. 00824 * 00825 * Returns total size of recipients, or negative upon error */ 00826 static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) 00827 { 00828 int totalSz = 0; 00829 Pkcs7EncodedRecip* tmp = NULL; 00830 00831 if (pkcs7 == NULL) 00832 return BAD_FUNC_ARG; 00833 00834 tmp = pkcs7->recipList; 00835 00836 while (tmp != NULL) { 00837 totalSz += tmp->recipSz; 00838 tmp = tmp->next; 00839 } 00840 00841 return totalSz; 00842 } 00843 00844 00845 /* free all members of Pkcs7EncodedRecip linked list */ 00846 static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7) 00847 { 00848 Pkcs7EncodedRecip* curr = NULL; 00849 Pkcs7EncodedRecip* next = NULL; 00850 00851 if (pkcs7 == NULL) 00852 return; 00853 00854 curr = pkcs7->recipList; 00855 pkcs7->recipList = NULL; 00856 00857 while (curr != NULL) { 00858 next = curr->next; 00859 curr->next = NULL; 00860 XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00861 curr = next; 00862 } 00863 00864 return; 00865 } 00866 00867 00868 /* search through RecipientInfo list for specific type. 00869 * return 1 if ANY recipient of type specified is present, otherwise 00870 * return 0 */ 00871 static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type) 00872 { 00873 Pkcs7EncodedRecip* tmp = NULL; 00874 00875 if (pkcs7 == NULL) 00876 return BAD_FUNC_ARG; 00877 00878 tmp = pkcs7->recipList; 00879 00880 while (tmp != NULL) { 00881 if (tmp->recipType == type) 00882 return 1; 00883 00884 tmp = tmp->next; 00885 } 00886 00887 return 0; 00888 } 00889 00890 00891 /* searches through RecipientInfo list, returns 1 if all structure 00892 * versions are set to 0, otherwise returns 0 */ 00893 static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7) 00894 { 00895 Pkcs7EncodedRecip* tmp = NULL; 00896 00897 if (pkcs7 == NULL) 00898 return BAD_FUNC_ARG; 00899 00900 tmp = pkcs7->recipList; 00901 00902 while (tmp != NULL) { 00903 if (tmp->recipVersion != 0) 00904 return 0; 00905 00906 tmp = tmp->next; 00907 } 00908 00909 return 1; 00910 } 00911 00912 00913 /* Init PKCS7 struct with recipient cert, decode into DecodedCert 00914 * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ 00915 int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) 00916 { 00917 int ret = 0; 00918 void* heap; 00919 int devId; 00920 Pkcs7Cert* cert; 00921 Pkcs7Cert* lastCert; 00922 00923 if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) { 00924 return BAD_FUNC_ARG; 00925 } 00926 00927 heap = pkcs7->heap; 00928 devId = pkcs7->devId; 00929 cert = pkcs7->certList; 00930 ret = wc_PKCS7_Init(pkcs7, heap, devId); 00931 if (ret != 0) 00932 return ret; 00933 pkcs7->certList = cert; 00934 00935 if (derCert != NULL && derCertSz > 0) { 00936 #ifdef WOLFSSL_SMALL_STACK 00937 DecodedCert* dCert; 00938 00939 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 00940 DYNAMIC_TYPE_DCERT); 00941 if (dCert == NULL) 00942 return MEMORY_E; 00943 #else 00944 DecodedCert dCert[1]; 00945 #endif 00946 00947 pkcs7->singleCert = derCert; 00948 pkcs7->singleCertSz = derCertSz; 00949 pkcs7->cert[0] = derCert; 00950 pkcs7->certSz[0] = derCertSz; 00951 00952 /* create new Pkcs7Cert for recipient, freed during cleanup */ 00953 cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, 00954 DYNAMIC_TYPE_PKCS7); 00955 XMEMSET(cert, 0, sizeof(Pkcs7Cert)); 00956 cert->der = derCert; 00957 cert->derSz = derCertSz; 00958 cert->next = NULL; 00959 00960 /* free existing cert list if existing */ 00961 wc_PKCS7_FreeCertSet(pkcs7); 00962 00963 /* add cert to list */ 00964 if (pkcs7->certList == NULL) { 00965 pkcs7->certList = cert; 00966 } else { 00967 lastCert = pkcs7->certList; 00968 while (lastCert->next != NULL) { 00969 lastCert = lastCert->next; 00970 } 00971 lastCert->next = cert; 00972 } 00973 00974 InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap); 00975 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); 00976 if (ret < 0) { 00977 FreeDecodedCert(dCert); 00978 #ifdef WOLFSSL_SMALL_STACK 00979 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 00980 #endif 00981 return ret; 00982 } 00983 00984 XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); 00985 pkcs7->publicKeySz = dCert->pubKeySize; 00986 pkcs7->publicKeyOID = dCert->keyOID; 00987 XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE); 00988 pkcs7->issuer = dCert->issuerRaw; 00989 pkcs7->issuerSz = dCert->issuerRawLen; 00990 XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); 00991 pkcs7->issuerSnSz = dCert->serialSz; 00992 XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); 00993 00994 /* default to IssuerAndSerialNumber for SignerIdentifier */ 00995 pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER; 00996 00997 /* free existing recipient list if existing */ 00998 wc_PKCS7_FreeEncodedRecipientSet(pkcs7); 00999 01000 FreeDecodedCert(dCert); 01001 01002 #ifdef WOLFSSL_SMALL_STACK 01003 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 01004 #endif 01005 } 01006 01007 return ret; 01008 } 01009 01010 01011 /* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate 01012 * list, to be added as part of the certificates CertificateSet. Currently 01013 * used in SignedData content type. 01014 * 01015 * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert(). 01016 * 01017 * Does not represent the recipient/signer certificate, only certificates that 01018 * are part of the certificate chain used to build and verify signer 01019 * certificates. 01020 * 01021 * This API does not currently validate certificates. 01022 * 01023 * Returns 0 on success, negative upon error */ 01024 int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* derCert, word32 derCertSz) 01025 { 01026 Pkcs7Cert* cert; 01027 01028 if (pkcs7 == NULL || derCert == NULL || derCertSz == 0) 01029 return BAD_FUNC_ARG; 01030 01031 cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, 01032 DYNAMIC_TYPE_PKCS7); 01033 if (cert == NULL) 01034 return MEMORY_E; 01035 01036 cert->der = derCert; 01037 cert->derSz = derCertSz; 01038 01039 if (pkcs7->certList == NULL) { 01040 pkcs7->certList = cert; 01041 } else { 01042 cert->next = pkcs7->certList; 01043 pkcs7->certList = cert; 01044 } 01045 01046 return 0; 01047 } 01048 01049 01050 /* free linked list of PKCS7DecodedAttrib structs */ 01051 static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) 01052 { 01053 PKCS7DecodedAttrib* current; 01054 01055 if (attrib == NULL) { 01056 return; 01057 } 01058 01059 current = attrib; 01060 while (current != NULL) { 01061 PKCS7DecodedAttrib* next = current->next; 01062 if (current->oid != NULL) { 01063 XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7); 01064 } 01065 if (current->value != NULL) { 01066 XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7); 01067 } 01068 XFREE(current, heap, DYNAMIC_TYPE_PKCS7); 01069 current = next; 01070 } 01071 01072 (void)heap; 01073 } 01074 01075 01076 /* return 0 on success */ 01077 static int wc_PKCS7_SignerInfoNew(PKCS7* pkcs7) 01078 { 01079 if (pkcs7->signerInfo != NULL) { 01080 XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01081 pkcs7->signerInfo = NULL; 01082 } 01083 01084 pkcs7->signerInfo = (PKCS7SignerInfo*)XMALLOC(sizeof(PKCS7SignerInfo), 01085 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01086 if (pkcs7->signerInfo == NULL) { 01087 WOLFSSL_MSG("Unable to malloc memory for signer info"); 01088 return MEMORY_E; 01089 } 01090 XMEMSET(pkcs7->signerInfo, 0, sizeof(PKCS7SignerInfo)); 01091 return 0; 01092 } 01093 01094 01095 static void wc_PKCS7_SignerInfoFree(PKCS7* pkcs7) 01096 { 01097 if (pkcs7->signerInfo != NULL) { 01098 if (pkcs7->signerInfo->sid != NULL) { 01099 XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01100 pkcs7->signerInfo->sid = NULL; 01101 } 01102 XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01103 pkcs7->signerInfo = NULL; 01104 } 01105 } 01106 01107 01108 /* free's any current SID and sets it to "in" 01109 * returns 0 on success 01110 */ 01111 static int wc_PKCS7_SignerInfoSetSID(PKCS7* pkcs7, byte* in, int inSz) 01112 { 01113 if (pkcs7 == NULL || in == NULL || inSz < 0) { 01114 return BAD_FUNC_ARG; 01115 } 01116 01117 if (pkcs7->signerInfo->sid != NULL) { 01118 XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01119 pkcs7->signerInfo->sid = NULL; 01120 } 01121 pkcs7->signerInfo->sid = (byte*)XMALLOC(inSz, pkcs7->heap, 01122 DYNAMIC_TYPE_PKCS7); 01123 if (pkcs7->signerInfo->sid == NULL) { 01124 return MEMORY_E; 01125 } 01126 XMEMCPY(pkcs7->signerInfo->sid, in, inSz); 01127 pkcs7->signerInfo->sidSz = inSz; 01128 return 0; 01129 } 01130 01131 01132 /* releases any memory allocated by a PKCS7 initializer */ 01133 void wc_PKCS7_Free(PKCS7* pkcs7) 01134 { 01135 if (pkcs7 == NULL) 01136 return; 01137 01138 #ifndef NO_PKCS7_STREAM 01139 wc_PKCS7_FreeStream(pkcs7); 01140 #endif 01141 01142 wc_PKCS7_SignerInfoFree(pkcs7); 01143 wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); 01144 wc_PKCS7_FreeCertSet(pkcs7); 01145 01146 #ifdef ASN_BER_TO_DER 01147 if (pkcs7->der != NULL) 01148 XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01149 #endif 01150 if (pkcs7->contentDynamic != NULL) 01151 XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01152 01153 if (pkcs7->cek != NULL) { 01154 ForceZero(pkcs7->cek, pkcs7->cekSz); 01155 XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01156 } 01157 01158 pkcs7->contentTypeSz = 0; 01159 01160 if (pkcs7->signature) { 01161 XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE); 01162 pkcs7->signature = NULL; 01163 pkcs7->signatureSz = 0; 01164 } 01165 if (pkcs7->plainDigest) { 01166 XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); 01167 pkcs7->plainDigest = NULL; 01168 pkcs7->plainDigestSz = 0; 01169 } 01170 if (pkcs7->pkcs7Digest) { 01171 XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); 01172 pkcs7->pkcs7Digest = NULL; 01173 pkcs7->pkcs7DigestSz = 0; 01174 } 01175 if (pkcs7->cachedEncryptedContent != NULL) { 01176 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01177 pkcs7->cachedEncryptedContent = NULL; 01178 pkcs7->cachedEncryptedContentSz = 0; 01179 } 01180 01181 if (pkcs7->isDynamic) { 01182 pkcs7->isDynamic = 0; 01183 XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01184 } 01185 } 01186 01187 01188 /* helper function for parsing through attributes and finding a specific one. 01189 * returns PKCS7DecodedAttrib pointer on success */ 01190 static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz) 01191 { 01192 PKCS7DecodedAttrib* list; 01193 01194 if (pkcs7 == NULL || oid == NULL) { 01195 return NULL; 01196 } 01197 01198 /* search attributes for pkiStatus */ 01199 list = pkcs7->decodedAttrib; 01200 while (list != NULL) { 01201 word32 sz = oidSz; 01202 word32 idx = 0; 01203 int length = 0; 01204 byte tag; 01205 01206 if (GetASNTag(list->oid, &idx, &tag, list->oidSz) < 0) { 01207 return NULL; 01208 } 01209 if (tag != ASN_OBJECT_ID) { 01210 WOLFSSL_MSG("Bad attribute ASN1 syntax"); 01211 return NULL; 01212 } 01213 01214 if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) { 01215 WOLFSSL_MSG("Bad attribute length"); 01216 return NULL; 01217 } 01218 01219 sz = (sz < (word32)length)? sz : (word32)length; 01220 if (XMEMCMP(oid, list->oid + idx, sz) == 0) { 01221 return list; 01222 } 01223 list = list->next; 01224 } 01225 return NULL; 01226 } 01227 01228 01229 /* Searches through decoded attributes and returns the value for the first one 01230 * matching the oid passed in. Note that this value includes the leading ASN1 01231 * syntax. So for a printable string of "3" this would be something like 01232 * 01233 * 0x13, 0x01, 0x33 01234 * ID SIZE "3" 01235 * 01236 * pkcs7 structure to get value from 01237 * oid OID value to search for with attributes 01238 * oidSz size of oid buffer 01239 * out buffer to hold result 01240 * outSz size of out buffer (if out is NULL this is set to needed size and 01241 LENGTH_ONLY_E is returned) 01242 * 01243 * returns size of value on success 01244 */ 01245 int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz, 01246 byte* out, word32* outSz) 01247 { 01248 PKCS7DecodedAttrib* attrib; 01249 01250 if (pkcs7 == NULL || oid == NULL || outSz == NULL) { 01251 return BAD_FUNC_ARG; 01252 } 01253 01254 attrib = findAttrib(pkcs7, oid, oidSz); 01255 if (attrib == NULL) { 01256 return ASN_PARSE_E; 01257 } 01258 01259 if (out == NULL) { 01260 *outSz = attrib->valueSz; 01261 return LENGTH_ONLY_E; 01262 } 01263 01264 if (*outSz < attrib->valueSz) { 01265 return BUFFER_E; 01266 } 01267 01268 XMEMCPY(out, attrib->value, attrib->valueSz); 01269 return attrib->valueSz; 01270 } 01271 01272 01273 /* build PKCS#7 data content type */ 01274 int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz) 01275 { 01276 static const byte oid[] = 01277 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 01278 0x07, 0x01 }; 01279 byte seq[MAX_SEQ_SZ]; 01280 byte octetStr[MAX_OCTET_STR_SZ]; 01281 word32 seqSz; 01282 word32 octetStrSz; 01283 word32 oidSz = (word32)sizeof(oid); 01284 int idx = 0; 01285 01286 if (pkcs7 == NULL || output == NULL) { 01287 return BAD_FUNC_ARG; 01288 } 01289 01290 octetStrSz = SetOctetString(pkcs7->contentSz, octetStr); 01291 seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq); 01292 01293 if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz) 01294 return BUFFER_E; 01295 01296 XMEMCPY(output, seq, seqSz); 01297 idx += seqSz; 01298 XMEMCPY(output + idx, oid, oidSz); 01299 idx += oidSz; 01300 XMEMCPY(output + idx, octetStr, octetStrSz); 01301 idx += octetStrSz; 01302 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 01303 idx += pkcs7->contentSz; 01304 01305 return idx; 01306 } 01307 01308 01309 typedef struct EncodedAttrib { 01310 byte valueSeq[MAX_SEQ_SZ]; 01311 const byte* oid; 01312 byte valueSet[MAX_SET_SZ]; 01313 const byte* value; 01314 word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz; 01315 } EncodedAttrib; 01316 01317 01318 typedef struct ESD { 01319 wc_HashAlg hash; 01320 enum wc_HashType hashType; 01321 byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ 01322 byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; 01323 byte encContentDigest[MAX_ENCRYPTED_KEY_SZ]; 01324 01325 byte outerSeq[MAX_SEQ_SZ]; 01326 byte outerContent[MAX_EXP_SZ]; 01327 byte innerSeq[MAX_SEQ_SZ]; 01328 byte version[MAX_VERSION_SZ]; 01329 byte digAlgoIdSet[MAX_SET_SZ]; 01330 byte singleDigAlgoId[MAX_ALGO_SZ]; 01331 01332 byte contentInfoSeq[MAX_SEQ_SZ]; 01333 byte innerContSeq[MAX_EXP_SZ]; 01334 byte innerOctets[MAX_OCTET_STR_SZ]; 01335 01336 byte certsSet[MAX_SET_SZ]; 01337 01338 byte signerInfoSet[MAX_SET_SZ]; 01339 byte signerInfoSeq[MAX_SEQ_SZ]; 01340 byte signerVersion[MAX_VERSION_SZ]; 01341 /* issuerAndSerialNumber ...*/ 01342 byte issuerSnSeq[MAX_SEQ_SZ]; 01343 byte issuerName[MAX_SEQ_SZ]; 01344 byte issuerSn[MAX_SN_SZ]; 01345 /* OR subjectKeyIdentifier */ 01346 byte issuerSKIDSeq[MAX_SEQ_SZ]; 01347 byte issuerSKID[MAX_OCTET_STR_SZ]; 01348 byte signerDigAlgoId[MAX_ALGO_SZ]; 01349 byte digEncAlgoId[MAX_ALGO_SZ]; 01350 byte signedAttribSet[MAX_SET_SZ]; 01351 EncodedAttrib signedAttribs[7]; 01352 byte signerDigest[MAX_OCTET_STR_SZ]; 01353 word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; 01354 word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, 01355 singleDigAlgoIdSz, certsSetSz; 01356 word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, 01357 issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz, 01358 issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; 01359 word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, 01360 signedAttribSetSz; 01361 } ESD; 01362 01363 01364 static int EncodeAttributes(EncodedAttrib* ea, int eaSz, 01365 PKCS7Attrib* attribs, int attribsSz) 01366 { 01367 int i; 01368 int maxSz = min(eaSz, attribsSz); 01369 int allAttribsSz = 0; 01370 01371 for (i = 0; i < maxSz; i++) 01372 { 01373 int attribSz = 0; 01374 01375 ea[i].value = attribs[i].value; 01376 ea[i].valueSz = attribs[i].valueSz; 01377 attribSz += ea[i].valueSz; 01378 ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet); 01379 attribSz += ea[i].valueSetSz; 01380 ea[i].oid = attribs[i].oid; 01381 ea[i].oidSz = attribs[i].oidSz; 01382 attribSz += ea[i].oidSz; 01383 ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq); 01384 attribSz += ea[i].valueSeqSz; 01385 ea[i].totalSz = attribSz; 01386 01387 allAttribsSz += attribSz; 01388 } 01389 return allAttribsSz; 01390 } 01391 01392 01393 typedef struct FlatAttrib { 01394 byte* data; 01395 word32 dataSz; 01396 } FlatAttrib; 01397 01398 /* Returns a pointer to FlatAttrib whose members are initialized to 0. 01399 * Caller is expected to free. 01400 */ 01401 static FlatAttrib* NewAttrib(void* heap) 01402 { 01403 FlatAttrib* fb = (FlatAttrib*) XMALLOC(sizeof(FlatAttrib), heap, 01404 DYNAMIC_TYPE_TMP_BUFFER); 01405 if (fb != NULL) { 01406 ForceZero(fb, sizeof(FlatAttrib)); 01407 } 01408 (void)heap; 01409 return fb; 01410 } 01411 01412 /* Free FlatAttrib array and memory allocated to internal struct members */ 01413 static void FreeAttribArray(PKCS7* pkcs7, FlatAttrib** arr, int rows) 01414 { 01415 int i; 01416 01417 if (arr) { 01418 for (i = 0; i < rows; i++) { 01419 if (arr[i]) { 01420 if (arr[i]->data) { 01421 ForceZero(arr[i]->data, arr[i]->dataSz); 01422 XFREE(arr[i]->data, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01423 } 01424 ForceZero(arr[i], sizeof(FlatAttrib)); 01425 XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01426 } 01427 } 01428 ForceZero(arr, rows); 01429 XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01430 } 01431 (void)pkcs7; 01432 } 01433 01434 01435 /* Sort FlatAttrib array in ascending order */ 01436 static int SortAttribArray(FlatAttrib** arr, int rows) 01437 { 01438 int i, j; 01439 word32 minSz, minIdx; 01440 FlatAttrib* a = NULL; 01441 FlatAttrib* b = NULL; 01442 FlatAttrib* tmp = NULL; 01443 01444 if (arr == NULL) { 01445 return BAD_FUNC_ARG; 01446 } 01447 01448 for (i = 0; i < rows; i++) { 01449 a = arr[i]; 01450 minSz = a->dataSz; 01451 minIdx = i; 01452 for (j = i+1; j < rows; j++) { 01453 b = arr[j]; 01454 if (b->dataSz < minSz) { 01455 minSz = b->dataSz; 01456 minIdx = j; 01457 } 01458 } 01459 if (minSz < a->dataSz) { 01460 /* swap array positions */ 01461 tmp = arr[i]; 01462 arr[i] = arr[minIdx]; 01463 arr[minIdx] = tmp; 01464 } 01465 } 01466 01467 return 0; 01468 } 01469 01470 01471 /* Build up array of FlatAttrib structs from EncodedAttrib ones. FlatAttrib 01472 * holds flattened DER encoding of each attribute */ 01473 static int FlattenEncodedAttribs(PKCS7* pkcs7, FlatAttrib** derArr, int rows, 01474 EncodedAttrib* ea, int eaSz) 01475 { 01476 int i, idx, sz; 01477 byte* output = NULL; 01478 FlatAttrib* fa = NULL; 01479 01480 if (pkcs7 == NULL || derArr == NULL || ea == NULL) { 01481 WOLFSSL_MSG("Invalid arguments to FlattenEncodedAttribs"); 01482 return BAD_FUNC_ARG; 01483 } 01484 01485 if (rows != eaSz) { 01486 WOLFSSL_MSG("DER array not large enough to hold attribute count"); 01487 return BAD_FUNC_ARG; 01488 } 01489 01490 for (i = 0; i < eaSz; i++) { 01491 sz = ea[i].valueSeqSz + ea[i].oidSz + ea[i].valueSetSz + ea[i].valueSz; 01492 01493 output = (byte*)XMALLOC(sz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01494 if (output == NULL) { 01495 return MEMORY_E; 01496 } 01497 01498 idx = 0; 01499 XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz); 01500 idx += ea[i].valueSeqSz; 01501 XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz); 01502 idx += ea[i].oidSz; 01503 XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz); 01504 idx += ea[i].valueSetSz; 01505 XMEMCPY(output + idx, ea[i].value, ea[i].valueSz); 01506 01507 fa = derArr[i]; 01508 fa->data = output; 01509 fa->dataSz = sz; 01510 } 01511 01512 return 0; 01513 } 01514 01515 01516 /* Sort and Flatten EncodedAttrib attributes into output buffer */ 01517 static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea, 01518 int eaSz) 01519 { 01520 int i, idx, ret; 01521 FlatAttrib** derArr = NULL; 01522 FlatAttrib* fa = NULL; 01523 01524 if (pkcs7 == NULL || output == NULL || ea == NULL) { 01525 return BAD_FUNC_ARG; 01526 } 01527 01528 /* create array of FlatAttrib struct pointers to hold DER attribs */ 01529 derArr = (FlatAttrib**) XMALLOC(eaSz * sizeof(FlatAttrib*), pkcs7->heap, 01530 DYNAMIC_TYPE_TMP_BUFFER); 01531 if (derArr == NULL) { 01532 return MEMORY_E; 01533 } 01534 XMEMSET(derArr, 0, eaSz * sizeof(FlatAttrib*)); 01535 01536 for (i = 0; i < eaSz; i++) { 01537 derArr[i] = NewAttrib(pkcs7->heap); 01538 if (derArr[i] == NULL) { 01539 FreeAttribArray(pkcs7, derArr, eaSz); 01540 return MEMORY_E; 01541 } 01542 ForceZero(derArr[i], sizeof(FlatAttrib)); 01543 } 01544 01545 /* flatten EncodedAttrib into DER byte arrays */ 01546 ret = FlattenEncodedAttribs(pkcs7, derArr, eaSz, ea, eaSz); 01547 if (ret != 0) { 01548 FreeAttribArray(pkcs7, derArr, eaSz); 01549 return ret; 01550 } 01551 01552 /* SET OF DER signed attributes must be sorted in ascending order */ 01553 ret = SortAttribArray(derArr, eaSz); 01554 if (ret != 0) { 01555 FreeAttribArray(pkcs7, derArr, eaSz); 01556 return ret; 01557 } 01558 01559 /* copy sorted DER attribute arrays into output buffer */ 01560 idx = 0; 01561 for (i = 0; i < eaSz; i++) { 01562 fa = derArr[i]; 01563 XMEMCPY(output + idx, fa->data, fa->dataSz); 01564 idx += fa->dataSz; 01565 } 01566 01567 FreeAttribArray(pkcs7, derArr, eaSz); 01568 01569 return 0; 01570 } 01571 01572 01573 #ifndef NO_RSA 01574 01575 /* returns size of signature put into out, negative on error */ 01576 static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) 01577 { 01578 int ret; 01579 word32 idx; 01580 #ifdef WOLFSSL_SMALL_STACK 01581 RsaKey* privKey; 01582 #else 01583 RsaKey privKey[1]; 01584 #endif 01585 01586 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { 01587 return BAD_FUNC_ARG; 01588 } 01589 01590 #ifdef WOLFSSL_SMALL_STACK 01591 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, 01592 DYNAMIC_TYPE_TMP_BUFFER); 01593 if (privKey == NULL) 01594 return MEMORY_E; 01595 #endif 01596 01597 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); 01598 if (ret == 0) { 01599 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 01600 idx = 0; 01601 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, 01602 pkcs7->privateKeySz); 01603 } 01604 else if (pkcs7->devId == INVALID_DEVID) { 01605 ret = BAD_FUNC_ARG; 01606 } 01607 } 01608 if (ret == 0) { 01609 #ifdef WOLFSSL_ASYNC_CRYPT 01610 do { 01611 ret = wc_AsyncWait(ret, &privKey->asyncDev, 01612 WC_ASYNC_FLAG_CALL_AGAIN); 01613 if (ret >= 0) 01614 #endif 01615 { 01616 ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, 01617 sizeof(esd->encContentDigest), 01618 privKey, pkcs7->rng); 01619 } 01620 #ifdef WOLFSSL_ASYNC_CRYPT 01621 } while (ret == WC_PENDING_E); 01622 #endif 01623 } 01624 01625 wc_FreeRsaKey(privKey); 01626 #ifdef WOLFSSL_SMALL_STACK 01627 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01628 #endif 01629 01630 return ret; 01631 } 01632 01633 #endif /* NO_RSA */ 01634 01635 01636 #ifdef HAVE_ECC 01637 01638 /* returns size of signature put into out, negative on error */ 01639 static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) 01640 { 01641 int ret; 01642 word32 outSz, idx; 01643 #ifdef WOLFSSL_SMALL_STACK 01644 ecc_key* privKey; 01645 #else 01646 ecc_key privKey[1]; 01647 #endif 01648 01649 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { 01650 return BAD_FUNC_ARG; 01651 } 01652 01653 #ifdef WOLFSSL_SMALL_STACK 01654 privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 01655 DYNAMIC_TYPE_TMP_BUFFER); 01656 if (privKey == NULL) 01657 return MEMORY_E; 01658 #endif 01659 01660 ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); 01661 if (ret == 0) { 01662 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 01663 idx = 0; 01664 ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, 01665 pkcs7->privateKeySz); 01666 } 01667 else if (pkcs7->devId == INVALID_DEVID) { 01668 ret = BAD_FUNC_ARG; 01669 } 01670 } 01671 if (ret == 0) { 01672 outSz = sizeof(esd->encContentDigest); 01673 #ifdef WOLFSSL_ASYNC_CRYPT 01674 do { 01675 ret = wc_AsyncWait(ret, &privKey->asyncDev, 01676 WC_ASYNC_FLAG_CALL_AGAIN); 01677 if (ret >= 0) 01678 #endif 01679 { 01680 ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, 01681 &outSz, pkcs7->rng, privKey); 01682 } 01683 #ifdef WOLFSSL_ASYNC_CRYPT 01684 } while (ret == WC_PENDING_E); 01685 #endif 01686 if (ret == 0) 01687 ret = (int)outSz; 01688 } 01689 01690 wc_ecc_free(privKey); 01691 #ifdef WOLFSSL_SMALL_STACK 01692 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01693 #endif 01694 01695 return ret; 01696 } 01697 01698 #endif /* HAVE_ECC */ 01699 01700 01701 /* builds up SignedData signed attributes, including default ones. 01702 * 01703 * pkcs7 - pointer to initialized PKCS7 structure 01704 * esd - pointer to initialized ESD structure, used for output 01705 * 01706 * return 0 on success, negative on error */ 01707 static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, 01708 const byte* contentType, word32 contentTypeSz, 01709 const byte* contentTypeOid, word32 contentTypeOidSz, 01710 const byte* messageDigestOid, word32 messageDigestOidSz, 01711 const byte* signingTimeOid, word32 signingTimeOidSz, 01712 byte* signingTime, word32 signingTimeSz) 01713 { 01714 int hashSz; 01715 #ifdef NO_ASN_TIME 01716 PKCS7Attrib cannedAttribs[2]; 01717 #else 01718 time_t tm; 01719 int timeSz; 01720 PKCS7Attrib cannedAttribs[3]; 01721 #endif 01722 word32 idx = 0; 01723 word32 cannedAttribsCount; 01724 01725 if (pkcs7 == NULL || esd == NULL || contentType == NULL || 01726 contentTypeOid == NULL || messageDigestOid == NULL || 01727 signingTimeOid == NULL) { 01728 return BAD_FUNC_ARG; 01729 } 01730 01731 if (pkcs7->skipDefaultSignedAttribs == 0) { 01732 hashSz = wc_HashGetDigestSize(esd->hashType); 01733 if (hashSz < 0) 01734 return hashSz; 01735 01736 #ifndef NO_ASN_TIME 01737 if (signingTime == NULL || signingTimeSz == 0) 01738 return BAD_FUNC_ARG; 01739 01740 tm = XTIME(0); 01741 timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz); 01742 if (timeSz < 0) 01743 return timeSz; 01744 #endif 01745 01746 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); 01747 01748 cannedAttribs[idx].oid = contentTypeOid; 01749 cannedAttribs[idx].oidSz = contentTypeOidSz; 01750 cannedAttribs[idx].value = contentType; 01751 cannedAttribs[idx].valueSz = contentTypeSz; 01752 idx++; 01753 #ifndef NO_ASN_TIME 01754 cannedAttribs[idx].oid = signingTimeOid; 01755 cannedAttribs[idx].oidSz = signingTimeOidSz; 01756 cannedAttribs[idx].value = signingTime; 01757 cannedAttribs[idx].valueSz = timeSz; 01758 idx++; 01759 #endif 01760 cannedAttribs[idx].oid = messageDigestOid; 01761 cannedAttribs[idx].oidSz = messageDigestOidSz; 01762 cannedAttribs[idx].value = esd->contentDigest; 01763 cannedAttribs[idx].valueSz = hashSz + 2; /* ASN.1 heading */ 01764 01765 esd->signedAttribsCount += cannedAttribsCount; 01766 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3, 01767 cannedAttribs, cannedAttribsCount); 01768 } else { 01769 esd->signedAttribsCount = 0; 01770 esd->signedAttribsSz = 0; 01771 } 01772 01773 /* add custom signed attributes if set */ 01774 if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) { 01775 esd->signedAttribsCount += pkcs7->signedAttribsSz; 01776 #ifdef NO_ASN_TIME 01777 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, 01778 pkcs7->signedAttribs, pkcs7->signedAttribsSz); 01779 #else 01780 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4, 01781 pkcs7->signedAttribs, pkcs7->signedAttribsSz); 01782 #endif 01783 } 01784 01785 #ifdef NO_ASN_TIME 01786 (void)signingTimeOidSz; 01787 (void)signingTime; 01788 (void)signingTimeSz; 01789 #endif 01790 01791 return 0; 01792 } 01793 01794 01795 /* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or 01796 * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID. 01797 * 01798 * pkcs7 - pointer to PKCS7 structure 01799 * digEncAlgoId - [OUT] output int to store correct algo ID in 01800 * digEncAlgoType - [OUT] output for algo ID type 01801 * 01802 * return 0 on success, negative on error */ 01803 static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, 01804 int* digEncAlgoType) 01805 { 01806 int algoId = 0; 01807 int algoType = 0; 01808 01809 if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) 01810 return BAD_FUNC_ARG; 01811 01812 if (pkcs7->publicKeyOID == RSAk) { 01813 01814 algoType = oidSigType; 01815 01816 switch (pkcs7->hashOID) { 01817 #ifndef NO_SHA 01818 case SHAh: 01819 algoId = CTC_SHAwRSA; 01820 break; 01821 #endif 01822 #ifdef WOLFSSL_SHA224 01823 case SHA224h: 01824 algoId = CTC_SHA224wRSA; 01825 break; 01826 #endif 01827 #ifndef NO_SHA256 01828 case SHA256h: 01829 algoId = CTC_SHA256wRSA; 01830 break; 01831 #endif 01832 #ifdef WOLFSSL_SHA384 01833 case SHA384h: 01834 algoId = CTC_SHA384wRSA; 01835 break; 01836 #endif 01837 #ifdef WOLFSSL_SHA512 01838 case SHA512h: 01839 algoId = CTC_SHA512wRSA; 01840 break; 01841 #endif 01842 } 01843 01844 } 01845 #ifdef HAVE_ECC 01846 else if (pkcs7->publicKeyOID == ECDSAk) { 01847 01848 algoType = oidSigType; 01849 01850 switch (pkcs7->hashOID) { 01851 #ifndef NO_SHA 01852 case SHAh: 01853 algoId = CTC_SHAwECDSA; 01854 break; 01855 #endif 01856 #ifdef WOLFSSL_SHA224 01857 case SHA224h: 01858 algoId = CTC_SHA224wECDSA; 01859 break; 01860 #endif 01861 #ifndef NO_SHA256 01862 case SHA256h: 01863 algoId = CTC_SHA256wECDSA; 01864 break; 01865 #endif 01866 #ifdef WOLFSSL_SHA384 01867 case SHA384h: 01868 algoId = CTC_SHA384wECDSA; 01869 break; 01870 #endif 01871 #ifdef WOLFSSL_SHA512 01872 case SHA512h: 01873 algoId = CTC_SHA512wECDSA; 01874 break; 01875 #endif 01876 } 01877 } 01878 #endif /* HAVE_ECC */ 01879 01880 if (algoId == 0) { 01881 WOLFSSL_MSG("Invalid signature algorithm type"); 01882 return BAD_FUNC_ARG; 01883 } 01884 01885 *digEncAlgoId = algoId; 01886 *digEncAlgoType = algoType; 01887 01888 return 0; 01889 } 01890 01891 01892 /* build SignedData DigestInfo for use with PKCS#7/RSA 01893 * 01894 * pkcs7 - pointer to initialized PKCS7 struct 01895 * flatSignedAttribs - flattened, signed attributes 01896 * flatSignedAttrbsSz - size of flatSignedAttribs, octets 01897 * esd - pointer to initialized ESD struct 01898 * digestInfo - [OUT] output array for DigestInfo 01899 * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo 01900 * 01901 * return 0 on success, negative on error */ 01902 static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, 01903 word32 flatSignedAttribsSz, ESD* esd, 01904 byte* digestInfo, word32* digestInfoSz) 01905 { 01906 int ret, hashSz, digIdx = 0; 01907 byte digestInfoSeq[MAX_SEQ_SZ]; 01908 byte digestStr[MAX_OCTET_STR_SZ]; 01909 byte attribSet[MAX_SET_SZ]; 01910 byte algoId[MAX_ALGO_SZ]; 01911 word32 digestInfoSeqSz, digestStrSz, algoIdSz; 01912 word32 attribSetSz; 01913 01914 if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || 01915 digestInfoSz == NULL) { 01916 return BAD_FUNC_ARG; 01917 } 01918 01919 hashSz = wc_HashGetDigestSize(esd->hashType); 01920 if (hashSz < 0) 01921 return hashSz; 01922 01923 if (flatSignedAttribsSz != 0) { 01924 01925 if (flatSignedAttribs == NULL) 01926 return BAD_FUNC_ARG; 01927 01928 attribSetSz = SetSet(flatSignedAttribsSz, attribSet); 01929 01930 ret = wc_HashInit(&esd->hash, esd->hashType); 01931 if (ret < 0) 01932 return ret; 01933 01934 ret = wc_HashUpdate(&esd->hash, esd->hashType, 01935 attribSet, attribSetSz); 01936 if (ret == 0) 01937 ret = wc_HashUpdate(&esd->hash, esd->hashType, 01938 flatSignedAttribs, flatSignedAttribsSz); 01939 if (ret == 0) 01940 ret = wc_HashFinal(&esd->hash, esd->hashType, 01941 esd->contentAttribsDigest); 01942 wc_HashFree(&esd->hash, esd->hashType); 01943 01944 if (ret < 0) 01945 return ret; 01946 01947 } else { 01948 /* when no attrs, digest is contentDigest without tag and length */ 01949 XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); 01950 } 01951 01952 /* set algoID, with NULL attributes */ 01953 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); 01954 01955 digestStrSz = SetOctetString(hashSz, digestStr); 01956 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, 01957 digestInfoSeq); 01958 01959 if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { 01960 return BUFFER_E; 01961 } 01962 01963 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); 01964 digIdx += digestInfoSeqSz; 01965 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); 01966 digIdx += algoIdSz; 01967 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); 01968 digIdx += digestStrSz; 01969 XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); 01970 digIdx += hashSz; 01971 01972 *digestInfoSz = digIdx; 01973 01974 return 0; 01975 } 01976 01977 01978 /* build SignedData signature over DigestInfo or content digest 01979 * 01980 * pkcs7 - pointer to initialized PKCS7 struct 01981 * flatSignedAttribs - flattened, signed attributes 01982 * flatSignedAttribsSz - size of flatSignedAttribs, octets 01983 * esd - pointer to initialized ESD struct 01984 * 01985 * returns length of signature on success, negative on error */ 01986 static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, 01987 byte* flatSignedAttribs, 01988 word32 flatSignedAttribsSz, 01989 ESD* esd) 01990 { 01991 int ret = 0; 01992 #if defined(HAVE_ECC) || \ 01993 (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) 01994 int hashSz = 0; 01995 #endif 01996 #if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) 01997 int hashOID; 01998 #endif 01999 word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; 02000 #ifdef WOLFSSL_SMALL_STACK 02001 byte* digestInfo; 02002 #else 02003 byte digestInfo[MAX_PKCS7_DIGEST_SZ]; 02004 #endif 02005 02006 if (pkcs7 == NULL || esd == NULL) 02007 return BAD_FUNC_ARG; 02008 02009 #ifdef WOLFSSL_SMALL_STACK 02010 digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap, 02011 DYNAMIC_TYPE_TMP_BUFFER); 02012 if (digestInfo == NULL) { 02013 return MEMORY_E; 02014 } 02015 #endif 02016 XMEMSET(digestInfo, 0, digestInfoSz); 02017 02018 ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, 02019 flatSignedAttribsSz, esd, digestInfo, 02020 &digestInfoSz); 02021 if (ret < 0) { 02022 #ifdef WOLFSSL_SMALL_STACK 02023 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02024 #endif 02025 return ret; 02026 } 02027 02028 #if defined(HAVE_ECC) || \ 02029 (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) 02030 /* get digest size from hash type */ 02031 hashSz = wc_HashGetDigestSize(esd->hashType); 02032 if (hashSz < 0) { 02033 #ifdef WOLFSSL_SMALL_STACK 02034 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02035 #endif 02036 return hashSz; 02037 } 02038 #endif 02039 02040 /* sign digestInfo */ 02041 switch (pkcs7->publicKeyOID) { 02042 02043 #ifndef NO_RSA 02044 case RSAk: 02045 #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK 02046 if (pkcs7->rsaSignRawDigestCb != NULL) { 02047 /* get hash OID */ 02048 hashOID = wc_HashGetOID(esd->hashType); 02049 02050 /* user signing plain digest, build DigestInfo themselves */ 02051 ret = pkcs7->rsaSignRawDigestCb(pkcs7, 02052 esd->contentAttribsDigest, hashSz, 02053 esd->encContentDigest, sizeof(esd->encContentDigest), 02054 pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId, 02055 hashOID); 02056 break; 02057 } 02058 #endif 02059 ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); 02060 break; 02061 #endif 02062 02063 #ifdef HAVE_ECC 02064 case ECDSAk: 02065 /* CMS with ECDSA does not sign DigestInfo structure 02066 * like PKCS#7 with RSA does */ 02067 ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, 02068 hashSz, esd); 02069 break; 02070 #endif 02071 02072 default: 02073 WOLFSSL_MSG("Unsupported public key type"); 02074 ret = BAD_FUNC_ARG; 02075 } 02076 02077 #ifdef WOLFSSL_SMALL_STACK 02078 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02079 #endif 02080 02081 if (ret >= 0) { 02082 esd->encContentDigestSz = (word32)ret; 02083 } 02084 02085 return ret; 02086 } 02087 02088 02089 /* build PKCS#7 signedData content type */ 02090 static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, 02091 const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, 02092 byte* output2, word32* output2Sz) 02093 { 02094 /* contentType OID (1.2.840.113549.1.9.3) */ 02095 const byte contentTypeOid[] = 02096 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 02097 0x09, 0x03 }; 02098 02099 /* messageDigest OID (1.2.840.113549.1.9.4) */ 02100 const byte messageDigestOid[] = 02101 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 02102 0x09, 0x04 }; 02103 02104 /* signingTime OID () */ 02105 byte signingTimeOid[] = 02106 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 02107 0x09, 0x05}; 02108 02109 Pkcs7Cert* certPtr = NULL; 02110 word32 certSetSz = 0; 02111 02112 word32 signerInfoSz = 0; 02113 word32 totalSz, total2Sz; 02114 int idx = 0, ret = 0; 02115 int digEncAlgoId, digEncAlgoType; 02116 byte* flatSignedAttribs = NULL; 02117 word32 flatSignedAttribsSz = 0; 02118 02119 byte signedDataOid[MAX_OID_SZ]; 02120 word32 signedDataOidSz; 02121 02122 byte signingTime[MAX_TIME_STRING_SZ]; 02123 02124 if (pkcs7 == NULL || pkcs7->contentSz == 0 || 02125 pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || 02126 output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 || 02127 hashBuf == NULL) { 02128 return BAD_FUNC_ARG; 02129 } 02130 02131 /* verify the hash size matches */ 02132 #ifdef WOLFSSL_SMALL_STACK 02133 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02134 if (esd == NULL) 02135 return MEMORY_E; 02136 #endif 02137 02138 XMEMSET(esd, 0, sizeof(ESD)); 02139 02140 /* set content type based on contentOID, unless user has set custom one 02141 with wc_PKCS7_SetContentType() */ 02142 if (pkcs7->contentTypeSz == 0) { 02143 02144 /* default to DATA content type if user has not set */ 02145 if (pkcs7->contentOID == 0) { 02146 pkcs7->contentOID = DATA; 02147 } 02148 02149 ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType, 02150 sizeof(pkcs7->contentType)); 02151 if (ret < 0) { 02152 #ifdef WOLFSSL_SMALL_STACK 02153 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02154 #endif 02155 return ret; 02156 } 02157 pkcs7->contentTypeSz = ret; 02158 } 02159 02160 /* set signedData outer content type */ 02161 ret = wc_SetContentType(SIGNED_DATA, signedDataOid, sizeof(signedDataOid)); 02162 if (ret < 0) { 02163 #ifdef WOLFSSL_SMALL_STACK 02164 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02165 #endif 02166 return ret; 02167 } 02168 signedDataOidSz = ret; 02169 02170 if (pkcs7->sidType != DEGENERATE_SID) { 02171 esd->hashType = wc_OidGetHash(pkcs7->hashOID); 02172 if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { 02173 WOLFSSL_MSG("hashSz did not match hashOID"); 02174 #ifdef WOLFSSL_SMALL_STACK 02175 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02176 #endif 02177 return BUFFER_E; 02178 } 02179 02180 /* include hash */ 02181 esd->contentDigest[0] = ASN_OCTET_STRING; 02182 esd->contentDigest[1] = (byte)hashSz; 02183 XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz); 02184 } 02185 02186 if (pkcs7->detached == 1) { 02187 /* do not include content if generating detached signature */ 02188 esd->innerOctetsSz = 0; 02189 esd->innerContSeqSz = 0; 02190 esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz, 02191 esd->contentInfoSeq); 02192 } else { 02193 esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); 02194 esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + 02195 pkcs7->contentSz, esd->innerContSeq); 02196 esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + 02197 esd->innerOctetsSz + pkcs7->contentTypeSz + 02198 esd->innerContSeqSz, esd->contentInfoSeq); 02199 } 02200 02201 /* SignerIdentifier */ 02202 if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 02203 /* IssuerAndSerialNumber */ 02204 esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, 02205 esd->issuerSn, MAX_SN_SZ, MAX_SN_SZ); 02206 signerInfoSz += esd->issuerSnSz; 02207 esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); 02208 signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; 02209 esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); 02210 signerInfoSz += esd->issuerSnSeqSz; 02211 02212 if (pkcs7->version == 3) { 02213 /* RFC 4108 version MUST be 3 for firmware package signer */ 02214 esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); 02215 } 02216 else { 02217 /* version MUST be 1 otherwise*/ 02218 esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); 02219 } 02220 02221 } else if (pkcs7->sidType == CMS_SKID) { 02222 /* SubjectKeyIdentifier */ 02223 esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID); 02224 esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE, 02225 esd->issuerSKIDSeq); 02226 signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + 02227 KEYID_SIZE); 02228 02229 /* version MUST be 3 */ 02230 esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); 02231 } else if (pkcs7->sidType == DEGENERATE_SID) { 02232 /* no signer info added */ 02233 } else { 02234 #ifdef WOLFSSL_SMALL_STACK 02235 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02236 #endif 02237 return SKID_E; 02238 } 02239 02240 if (pkcs7->sidType != DEGENERATE_SID) { 02241 signerInfoSz += esd->signerVersionSz; 02242 esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, 02243 oidHashType, 0); 02244 signerInfoSz += esd->signerDigAlgoIdSz; 02245 02246 /* set signatureAlgorithm */ 02247 ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, 02248 &digEncAlgoType); 02249 if (ret < 0) { 02250 #ifdef WOLFSSL_SMALL_STACK 02251 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02252 #endif 02253 return ret; 02254 } 02255 esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, 02256 digEncAlgoType, 0); 02257 signerInfoSz += esd->digEncAlgoIdSz; 02258 02259 /* build up signed attributes, include contentType, signingTime, and 02260 messageDigest by default */ 02261 ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, 02262 pkcs7->contentTypeSz, 02263 contentTypeOid, sizeof(contentTypeOid), 02264 messageDigestOid, sizeof(messageDigestOid), 02265 signingTimeOid, sizeof(signingTimeOid), 02266 signingTime, sizeof(signingTime)); 02267 if (ret < 0) { 02268 #ifdef WOLFSSL_SMALL_STACK 02269 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02270 #endif 02271 return ret; 02272 } 02273 02274 if (esd->signedAttribsSz > 0) { 02275 flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, 02276 DYNAMIC_TYPE_PKCS7); 02277 flatSignedAttribsSz = esd->signedAttribsSz; 02278 if (flatSignedAttribs == NULL) { 02279 #ifdef WOLFSSL_SMALL_STACK 02280 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02281 #endif 02282 return MEMORY_E; 02283 } 02284 02285 FlattenAttributes(pkcs7, flatSignedAttribs, 02286 esd->signedAttribs, esd->signedAttribsCount); 02287 esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, 02288 esd->signedAttribSet); 02289 } else { 02290 esd->signedAttribSetSz = 0; 02291 } 02292 02293 /* Calculate the final hash and encrypt it. */ 02294 ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, 02295 flatSignedAttribsSz, esd); 02296 if (ret < 0) { 02297 if (pkcs7->signedAttribsSz != 0) 02298 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02299 #ifdef WOLFSSL_SMALL_STACK 02300 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02301 #endif 02302 return ret; 02303 } 02304 02305 signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; 02306 02307 esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, 02308 esd->signerDigest); 02309 signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; 02310 02311 esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); 02312 signerInfoSz += esd->signerInfoSeqSz; 02313 } 02314 esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); 02315 signerInfoSz += esd->signerInfoSetSz; 02316 02317 /* certificates [0] IMPLICIT CertificateSet */ 02318 /* get total certificates size */ 02319 certPtr = pkcs7->certList; 02320 while (certPtr != NULL) { 02321 certSetSz += certPtr->derSz; 02322 certPtr = certPtr->next; 02323 } 02324 certPtr = NULL; 02325 02326 if (certSetSz > 0) 02327 esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet); 02328 02329 if (pkcs7->sidType != DEGENERATE_SID) { 02330 esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, 02331 oidHashType, 0); 02332 } 02333 esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); 02334 02335 if (pkcs7->version == 3) { 02336 /* RFC 4108 version MUST be 3 for firmware package signer */ 02337 esd->versionSz = SetMyVersion(3, esd->version, 0); 02338 } 02339 else { 02340 esd->versionSz = SetMyVersion(1, esd->version, 0); 02341 } 02342 02343 totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + 02344 esd->contentInfoSeqSz + pkcs7->contentTypeSz + 02345 esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz; 02346 total2Sz = esd->certsSetSz + certSetSz + signerInfoSz; 02347 02348 if (pkcs7->detached) { 02349 totalSz -= pkcs7->contentSz; 02350 } 02351 02352 esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq); 02353 totalSz += esd->innerSeqSz; 02354 esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent); 02355 totalSz += esd->outerContentSz + signedDataOidSz; 02356 esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq); 02357 totalSz += esd->outerSeqSz; 02358 02359 /* if using header/footer, we are not returning the content */ 02360 if (output2 && output2Sz) { 02361 if (total2Sz > *output2Sz) { 02362 if (pkcs7->signedAttribsSz != 0) 02363 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02364 #ifdef WOLFSSL_SMALL_STACK 02365 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02366 #endif 02367 return BUFFER_E; 02368 } 02369 02370 if (!pkcs7->detached) { 02371 totalSz -= pkcs7->contentSz; 02372 } 02373 } 02374 else { 02375 /* if using single output buffer include content and footer */ 02376 totalSz += total2Sz; 02377 } 02378 02379 if (totalSz > *outputSz) { 02380 if (pkcs7->signedAttribsSz != 0) 02381 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02382 #ifdef WOLFSSL_SMALL_STACK 02383 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02384 #endif 02385 return BUFFER_E; 02386 } 02387 02388 idx = 0; 02389 XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); 02390 idx += esd->outerSeqSz; 02391 XMEMCPY(output + idx, signedDataOid, signedDataOidSz); 02392 idx += signedDataOidSz; 02393 XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); 02394 idx += esd->outerContentSz; 02395 XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); 02396 idx += esd->innerSeqSz; 02397 XMEMCPY(output + idx, esd->version, esd->versionSz); 02398 idx += esd->versionSz; 02399 XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); 02400 idx += esd->digAlgoIdSetSz; 02401 XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); 02402 idx += esd->singleDigAlgoIdSz; 02403 XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); 02404 idx += esd->contentInfoSeqSz; 02405 XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz); 02406 idx += pkcs7->contentTypeSz; 02407 XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); 02408 idx += esd->innerContSeqSz; 02409 XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); 02410 idx += esd->innerOctetsSz; 02411 02412 /* support returning header and footer without content */ 02413 if (output2 && output2Sz) { 02414 *outputSz = idx; 02415 idx = 0; 02416 } 02417 else { 02418 if (!pkcs7->detached) { 02419 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 02420 idx += pkcs7->contentSz; 02421 } 02422 output2 = output; 02423 } 02424 02425 /* certificates */ 02426 XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz); 02427 idx += esd->certsSetSz; 02428 certPtr = pkcs7->certList; 02429 while (certPtr != NULL) { 02430 XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz); 02431 idx += certPtr->derSz; 02432 certPtr = certPtr->next; 02433 } 02434 wc_PKCS7_FreeCertSet(pkcs7); 02435 02436 XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); 02437 idx += esd->signerInfoSetSz; 02438 XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); 02439 idx += esd->signerInfoSeqSz; 02440 XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); 02441 idx += esd->signerVersionSz; 02442 /* SignerIdentifier */ 02443 if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 02444 /* IssuerAndSerialNumber */ 02445 XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); 02446 idx += esd->issuerSnSeqSz; 02447 XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); 02448 idx += esd->issuerNameSz; 02449 XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); 02450 idx += pkcs7->issuerSz; 02451 XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); 02452 idx += esd->issuerSnSz; 02453 } else if (pkcs7->sidType == CMS_SKID) { 02454 /* SubjectKeyIdentifier */ 02455 XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); 02456 idx += esd->issuerSKIDSeqSz; 02457 XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz); 02458 idx += esd->issuerSKIDSz; 02459 XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); 02460 idx += KEYID_SIZE; 02461 } else if (pkcs7->sidType == DEGENERATE_SID) { 02462 /* no signer infos in degenerate case */ 02463 } else { 02464 #ifdef WOLFSSL_SMALL_STACK 02465 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02466 #endif 02467 return SKID_E; 02468 } 02469 XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); 02470 idx += esd->signerDigAlgoIdSz; 02471 02472 /* SignerInfo:Attributes */ 02473 if (flatSignedAttribsSz > 0) { 02474 XMEMCPY(output2 + idx, esd->signedAttribSet, esd->signedAttribSetSz); 02475 idx += esd->signedAttribSetSz; 02476 XMEMCPY(output2 + idx, flatSignedAttribs, flatSignedAttribsSz); 02477 idx += flatSignedAttribsSz; 02478 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02479 } 02480 02481 XMEMCPY(output2 + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); 02482 idx += esd->digEncAlgoIdSz; 02483 XMEMCPY(output2 + idx, esd->signerDigest, esd->signerDigestSz); 02484 idx += esd->signerDigestSz; 02485 XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz); 02486 idx += esd->encContentDigestSz; 02487 02488 if (output2 && output2Sz) { 02489 *output2Sz = idx; 02490 idx = 0; /* success */ 02491 } 02492 else { 02493 *outputSz = idx; 02494 } 02495 02496 #ifdef WOLFSSL_SMALL_STACK 02497 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02498 #endif 02499 return idx; 02500 } 02501 02502 /* hashBuf: The computed digest for the pkcs7->content 02503 * hashSz: The size of computed digest for the pkcs7->content based on hashOID 02504 * outputHead: The PKCS7 header that goes on top of the raw data signed. 02505 * outputFoot: The PKCS7 footer that goes at the end of the raw data signed. 02506 * pkcs7->content: Not used 02507 * pkcs7->contentSz: Must be provided as actual sign of raw data 02508 * return codes: 0=success, negative=error 02509 */ 02510 int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, 02511 word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot, 02512 word32* outputFootSz) 02513 { 02514 int ret; 02515 #ifdef WOLFSSL_SMALL_STACK 02516 ESD* esd; 02517 #else 02518 ESD esd[1]; 02519 #endif 02520 02521 /* other args checked in wc_PKCS7_EncodeSigned_ex */ 02522 if (pkcs7 == NULL || outputFoot == NULL || outputFootSz == NULL) { 02523 return BAD_FUNC_ARG; 02524 } 02525 02526 #ifdef WOLFSSL_SMALL_STACK 02527 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02528 if (esd == NULL) 02529 return MEMORY_E; 02530 #endif 02531 02532 XMEMSET(esd, 0, sizeof(ESD)); 02533 02534 ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, 02535 outputHead, outputHeadSz, outputFoot, outputFootSz); 02536 02537 #ifdef WOLFSSL_SMALL_STACK 02538 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02539 #endif 02540 02541 return ret; 02542 } 02543 02544 /* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type. 02545 * By default wolfCrypt includes the data to be signed in the SignedData 02546 * bundle. This data can be omitted in the case when a detached signature is 02547 * being created. To enable generation of detached signatures, set flag to "1", 02548 * otherwise set to "0": 02549 * 02550 * flag 1 turns on support 02551 * flag 0 turns off support 02552 * 02553 * pkcs7 - pointer to initialized PKCS7 structure 02554 * flag - turn on/off detached signature generation (1 or 0) 02555 * 02556 * Returns 0 on success, negative upon error. */ 02557 int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag) 02558 { 02559 if (pkcs7 == NULL || (flag != 0 && flag != 1)) 02560 return BAD_FUNC_ARG; 02561 02562 pkcs7->detached = flag; 02563 02564 return 0; 02565 } 02566 02567 /* By default, SignedData bundles have the following signed attributes attached: 02568 * contentType (1.2.840.113549.1.9.3) 02569 * signgingTime (1.2.840.113549.1.9.5) 02570 * messageDigest (1.2.840.113549.1.9.4) 02571 * 02572 * Calling this API before wc_PKCS7_EncodeSignedData() will disable the 02573 * inclusion of those attributes. 02574 * 02575 * pkcs7 - pointer to initialized PKCS7 structure 02576 * 02577 * Returns 0 on success, negative upon error. */ 02578 int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7) 02579 { 02580 if (pkcs7 == NULL) 02581 return BAD_FUNC_ARG; 02582 02583 pkcs7->skipDefaultSignedAttribs = 1; 02584 02585 return 0; 02586 } 02587 02588 /* return codes: >0: Size of signed PKCS7 output buffer, negative: error */ 02589 int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) 02590 { 02591 int ret; 02592 int hashSz; 02593 enum wc_HashType hashType; 02594 byte hashBuf[WC_MAX_DIGEST_SIZE]; 02595 #ifdef WOLFSSL_SMALL_STACK 02596 ESD* esd; 02597 #else 02598 ESD esd[1]; 02599 #endif 02600 02601 /* other args checked in wc_PKCS7_EncodeSigned_ex */ 02602 if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->content == NULL) { 02603 return BAD_FUNC_ARG; 02604 } 02605 02606 /* get hash type and size, validate hashOID */ 02607 hashType = wc_OidGetHash(pkcs7->hashOID); 02608 hashSz = wc_HashGetDigestSize(hashType); 02609 if (hashSz < 0) 02610 return hashSz; 02611 02612 #ifdef WOLFSSL_SMALL_STACK 02613 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02614 if (esd == NULL) 02615 return MEMORY_E; 02616 #endif 02617 02618 XMEMSET(esd, 0, sizeof(ESD)); 02619 esd->hashType = hashType; 02620 02621 /* calculate hash for content */ 02622 ret = wc_HashInit(&esd->hash, esd->hashType); 02623 if (ret == 0) { 02624 ret = wc_HashUpdate(&esd->hash, esd->hashType, 02625 pkcs7->content, pkcs7->contentSz); 02626 if (ret == 0) { 02627 ret = wc_HashFinal(&esd->hash, esd->hashType, hashBuf); 02628 } 02629 wc_HashFree(&esd->hash, esd->hashType); 02630 } 02631 02632 if (ret == 0) { 02633 ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, 02634 output, &outputSz, NULL, NULL); 02635 } 02636 02637 #ifdef WOLFSSL_SMALL_STACK 02638 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 02639 #endif 02640 02641 return ret; 02642 } 02643 02644 02645 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a 02646 * content of type FirmwarePkgData. Any recipient certificates should be 02647 * loaded into the PKCS7 structure prior to calling this function, using 02648 * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate(). 02649 * 02650 * pkcs7 - pointer to initialized PKCS7 struct 02651 * privateKey - private RSA/ECC key, used for signing SignedData 02652 * privateKeySz - size of privateKey, octets 02653 * signOID - public key algorithm OID, used for sign operation 02654 * hashOID - hash algorithm OID, used for signature generation 02655 * content - content to be encapsulated, of type FirmwarePkgData 02656 * contentSz - size of content, octets 02657 * signedAttribs - optional signed attributes 02658 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs 02659 * output - output buffer for final bundle 02660 * outputSz - size of output buffer, octets 02661 * 02662 * Returns length of generated bundle on success, negative upon error. */ 02663 int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, 02664 word32 privateKeySz, int signOID, int hashOID, 02665 byte* content, word32 contentSz, 02666 PKCS7Attrib* signedAttribs, word32 signedAttribsSz, 02667 byte* output, word32 outputSz) 02668 { 02669 int ret = 0; 02670 WC_RNG rng; 02671 02672 if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || 02673 content == NULL || contentSz == 0 || output == NULL || outputSz == 0) 02674 return BAD_FUNC_ARG; 02675 02676 ret = wc_InitRng(&rng); 02677 if (ret != 0) 02678 return ret; 02679 02680 pkcs7->rng = &rng; 02681 pkcs7->content = content; 02682 pkcs7->contentSz = contentSz; 02683 pkcs7->contentOID = FIRMWARE_PKG_DATA; 02684 pkcs7->hashOID = hashOID; 02685 pkcs7->encryptOID = signOID; 02686 pkcs7->privateKey = privateKey; 02687 pkcs7->privateKeySz = privateKeySz; 02688 pkcs7->signedAttribs = signedAttribs; 02689 pkcs7->signedAttribsSz = signedAttribsSz; 02690 pkcs7->version = 3; 02691 02692 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); 02693 if (ret <= 0) { 02694 WOLFSSL_MSG("Error encoding CMS SignedData content type"); 02695 } 02696 02697 pkcs7->rng = NULL; 02698 wc_FreeRng(&rng); 02699 02700 return ret; 02701 } 02702 02703 #ifndef NO_PKCS7_ENCRYPTED_DATA 02704 02705 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a 02706 * CMS EncryptedData bundle. Content of inner EncryptedData is set to that 02707 * of FirmwarePkgData. Any recipient certificates should be loaded into the 02708 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() 02709 * and/or wc_PKCS7_AddCertificate(). 02710 * 02711 * pkcs7 - pointer to initialized PKCS7 struct 02712 * encryptKey - encryption key used for encrypting EncryptedData 02713 * encryptKeySz - size of encryptKey, octets 02714 * privateKey - private RSA/ECC key, used for signing SignedData 02715 * privateKeySz - size of privateKey, octets 02716 * encryptOID - encryption algorithm OID, to be used as encryption 02717 * algorithm for EncryptedData 02718 * signOID - public key algorithm OID, to be used for sign 02719 * operation in SignedData generation 02720 * hashOID - hash algorithm OID, to be used for signature in 02721 * SignedData generation 02722 * content - content to be encapsulated 02723 * contentSz - size of content, octets 02724 * unprotectedAttribs - optional unprotected attributes, for EncryptedData 02725 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs 02726 * signedAttribs - optional signed attributes, for SignedData 02727 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs 02728 * output - output buffer for final bundle 02729 * outputSz - size of output buffer, octets 02730 * 02731 * Returns length of generated bundle on success, negative upon error. */ 02732 int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, 02733 word32 encryptKeySz, byte* privateKey, 02734 word32 privateKeySz, int encryptOID, 02735 int signOID, int hashOID, 02736 byte* content, word32 contentSz, 02737 PKCS7Attrib* unprotectedAttribs, 02738 word32 unprotectedAttribsSz, 02739 PKCS7Attrib* signedAttribs, 02740 word32 signedAttribsSz, 02741 byte* output, word32 outputSz) 02742 { 02743 int ret = 0, encryptedSz = 0; 02744 byte* encrypted = NULL; 02745 WC_RNG rng; 02746 02747 if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || 02748 privateKey == NULL || privateKeySz == 0 || content == NULL || 02749 contentSz == 0 || output == NULL || outputSz == 0) { 02750 return BAD_FUNC_ARG; 02751 } 02752 02753 /* 1: build up EncryptedData using FirmwarePkgData type, use output 02754 * buffer as tmp for storage and to get size */ 02755 02756 /* set struct elements, inner content type is FirmwarePkgData */ 02757 pkcs7->content = content; 02758 pkcs7->contentSz = contentSz; 02759 pkcs7->contentOID = FIRMWARE_PKG_DATA; 02760 pkcs7->encryptOID = encryptOID; 02761 pkcs7->encryptionKey = encryptKey; 02762 pkcs7->encryptionKeySz = encryptKeySz; 02763 pkcs7->unprotectedAttribs = unprotectedAttribs; 02764 pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; 02765 pkcs7->version = 3; 02766 02767 encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); 02768 if (encryptedSz < 0) { 02769 WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); 02770 return encryptedSz; 02771 } 02772 02773 /* save encryptedData, reset output buffer and struct */ 02774 encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02775 if (encrypted == NULL) { 02776 ForceZero(output, outputSz); 02777 return MEMORY_E; 02778 } 02779 02780 XMEMCPY(encrypted, output, encryptedSz); 02781 ForceZero(output, outputSz); 02782 02783 ret = wc_InitRng(&rng); 02784 if (ret != 0) { 02785 ForceZero(encrypted, encryptedSz); 02786 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02787 return ret; 02788 } 02789 02790 /* 2: build up SignedData, encapsulating EncryptedData */ 02791 pkcs7->rng = &rng; 02792 pkcs7->content = encrypted; 02793 pkcs7->contentSz = encryptedSz; 02794 pkcs7->contentOID = ENCRYPTED_DATA; 02795 pkcs7->hashOID = hashOID; 02796 pkcs7->encryptOID = signOID; 02797 pkcs7->privateKey = privateKey; 02798 pkcs7->privateKeySz = privateKeySz; 02799 pkcs7->signedAttribs = signedAttribs; 02800 pkcs7->signedAttribsSz = signedAttribsSz; 02801 02802 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); 02803 if (ret <= 0) { 02804 WOLFSSL_MSG("Error encoding CMS SignedData content type"); 02805 } 02806 02807 ForceZero(encrypted, encryptedSz); 02808 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02809 pkcs7->rng = NULL; 02810 wc_FreeRng(&rng); 02811 02812 return ret; 02813 } 02814 02815 #endif /* NO_PKCS7_ENCRYPTED_DATA */ 02816 02817 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) 02818 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a 02819 * CMS CompressedData bundle. Content of inner CompressedData is set to that 02820 * of FirmwarePkgData. Any recipient certificates should be loaded into the 02821 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() 02822 * and/or wc_PKCS7_AddCertificate(). 02823 * 02824 * pkcs7 - pointer to initialized PKCS7 struct 02825 * privateKey - private RSA/ECC key, used for signing SignedData 02826 * privateKeySz - size of privateKey, octets 02827 * signOID - public key algorithm OID, to be used for sign 02828 * operation in SignedData generation 02829 * hashOID - hash algorithm OID, to be used for signature in 02830 * SignedData generation 02831 * content - content to be encapsulated 02832 * contentSz - size of content, octets 02833 * signedAttribs - optional signed attributes, for SignedData 02834 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs 02835 * output - output buffer for final bundle 02836 * outputSz - size of output buffer, octets 02837 * 02838 * Returns length of generated bundle on success, negative upon error. */ 02839 int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, 02840 word32 privateKeySz, int signOID, 02841 int hashOID, byte* content, 02842 word32 contentSz, 02843 PKCS7Attrib* signedAttribs, 02844 word32 signedAttribsSz, byte* output, 02845 word32 outputSz) 02846 { 02847 int ret = 0, compressedSz = 0; 02848 byte* compressed = NULL; 02849 WC_RNG rng; 02850 02851 if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || 02852 content == NULL || contentSz == 0 || output == NULL || outputSz == 0) { 02853 return BAD_FUNC_ARG; 02854 } 02855 02856 /* 1: build up CompressedData using FirmwarePkgData type, use output 02857 * buffer as tmp for storage and to get size */ 02858 02859 /* set struct elements, inner content type is FirmwarePkgData */ 02860 pkcs7->content = content; 02861 pkcs7->contentSz = contentSz; 02862 pkcs7->contentOID = FIRMWARE_PKG_DATA; 02863 pkcs7->version = 3; 02864 02865 compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); 02866 if (compressedSz < 0) { 02867 WOLFSSL_MSG("Error encoding CMS CompressedData content type"); 02868 return compressedSz; 02869 } 02870 02871 /* save compressedData, reset output buffer and struct */ 02872 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02873 if (compressed == NULL) { 02874 ForceZero(output, outputSz); 02875 return MEMORY_E; 02876 } 02877 02878 XMEMCPY(compressed, output, compressedSz); 02879 ForceZero(output, outputSz); 02880 02881 ret = wc_InitRng(&rng); 02882 if (ret != 0) { 02883 ForceZero(compressed, compressedSz); 02884 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02885 return ret; 02886 } 02887 02888 /* 2: build up SignedData, encapsulating EncryptedData */ 02889 pkcs7->rng = &rng; 02890 pkcs7->content = compressed; 02891 pkcs7->contentSz = compressedSz; 02892 pkcs7->contentOID = COMPRESSED_DATA; 02893 pkcs7->hashOID = hashOID; 02894 pkcs7->encryptOID = signOID; 02895 pkcs7->privateKey = privateKey; 02896 pkcs7->privateKeySz = privateKeySz; 02897 pkcs7->signedAttribs = signedAttribs; 02898 pkcs7->signedAttribsSz = signedAttribsSz; 02899 02900 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); 02901 if (ret <= 0) { 02902 WOLFSSL_MSG("Error encoding CMS SignedData content type"); 02903 } 02904 02905 ForceZero(compressed, compressedSz); 02906 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02907 pkcs7->rng = NULL; 02908 wc_FreeRng(&rng); 02909 02910 return ret; 02911 } 02912 02913 #ifndef NO_PKCS7_ENCRYPTED_DATA 02914 02915 /* Single-shot API to generate a CMS SignedData bundle that encapsulates a 02916 * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData 02917 * bundle. Content of inner CompressedData is set to that of FirmwarePkgData. 02918 * Any recipient certificates should be loaded into the PKCS7 structure prior 02919 * to calling this function, using wc_PKCS7_InitWithCert() and/or 02920 * wc_PKCS7_AddCertificate(). 02921 * 02922 * pkcs7 - pointer to initialized PKCS7 struct 02923 * encryptKey - encryption key used for encrypting EncryptedData 02924 * encryptKeySz - size of encryptKey, octets 02925 * privateKey - private RSA/ECC key, used for signing SignedData 02926 * privateKeySz - size of privateKey, octets 02927 * encryptOID - encryption algorithm OID, to be used as encryption 02928 * algorithm for EncryptedData 02929 * signOID - public key algorithm OID, to be used for sign 02930 * operation in SignedData generation 02931 * hashOID - hash algorithm OID, to be used for signature in 02932 * SignedData generation 02933 * content - content to be encapsulated 02934 * contentSz - size of content, octets 02935 * unprotectedAttribs - optional unprotected attributes, for EncryptedData 02936 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs 02937 * signedAttribs - optional signed attributes, for SignedData 02938 * signedAttribsSz - number of PKCS7Attrib members in signedAttribs 02939 * output - output buffer for final bundle 02940 * outputSz - size of output buffer, octets 02941 * 02942 * Returns length of generated bundle on success, negative upon error. */ 02943 int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey, 02944 word32 encryptKeySz, byte* privateKey, 02945 word32 privateKeySz, int encryptOID, 02946 int signOID, int hashOID, byte* content, 02947 word32 contentSz, 02948 PKCS7Attrib* unprotectedAttribs, 02949 word32 unprotectedAttribsSz, 02950 PKCS7Attrib* signedAttribs, 02951 word32 signedAttribsSz, 02952 byte* output, word32 outputSz) 02953 { 02954 int ret = 0, compressedSz = 0, encryptedSz = 0; 02955 byte* compressed = NULL; 02956 byte* encrypted = NULL; 02957 WC_RNG rng; 02958 02959 if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || 02960 privateKey == NULL || privateKeySz == 0 || content == NULL || 02961 contentSz == 0 || output == NULL || outputSz == 0) { 02962 return BAD_FUNC_ARG; 02963 } 02964 02965 /* 1: build up CompressedData using FirmwarePkgData type, use output 02966 * buffer as tmp for storage and to get size */ 02967 pkcs7->content = content; 02968 pkcs7->contentSz = contentSz; 02969 pkcs7->contentOID = FIRMWARE_PKG_DATA; 02970 pkcs7->version = 3; 02971 02972 compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); 02973 if (compressedSz < 0) { 02974 WOLFSSL_MSG("Error encoding CMS CompressedData content type"); 02975 return compressedSz; 02976 } 02977 02978 /* save compressedData, reset output buffer and struct */ 02979 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02980 if (compressed == NULL) 02981 return MEMORY_E; 02982 02983 XMEMCPY(compressed, output, compressedSz); 02984 ForceZero(output, outputSz); 02985 02986 /* 2: build up EncryptedData using CompressedData, use output 02987 * buffer as tmp for storage and to get size */ 02988 pkcs7->content = compressed; 02989 pkcs7->contentSz = compressedSz; 02990 pkcs7->contentOID = COMPRESSED_DATA; 02991 pkcs7->encryptOID = encryptOID; 02992 pkcs7->encryptionKey = encryptKey; 02993 pkcs7->encryptionKeySz = encryptKeySz; 02994 pkcs7->unprotectedAttribs = unprotectedAttribs; 02995 pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; 02996 02997 encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); 02998 if (encryptedSz < 0) { 02999 WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); 03000 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03001 return encryptedSz; 03002 } 03003 03004 /* save encryptedData, reset output buffer and struct */ 03005 encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03006 if (encrypted == NULL) { 03007 ForceZero(compressed, compressedSz); 03008 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03009 return MEMORY_E; 03010 } 03011 03012 XMEMCPY(encrypted, output, encryptedSz); 03013 ForceZero(compressed, compressedSz); 03014 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03015 ForceZero(output, outputSz); 03016 03017 ret = wc_InitRng(&rng); 03018 if (ret != 0) { 03019 ForceZero(encrypted, encryptedSz); 03020 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03021 return ret; 03022 } 03023 03024 /* 3: build up SignedData, encapsulating EncryptedData */ 03025 pkcs7->rng = &rng; 03026 pkcs7->content = encrypted; 03027 pkcs7->contentSz = encryptedSz; 03028 pkcs7->contentOID = ENCRYPTED_DATA; 03029 pkcs7->hashOID = hashOID; 03030 pkcs7->encryptOID = signOID; 03031 pkcs7->privateKey = privateKey; 03032 pkcs7->privateKeySz = privateKeySz; 03033 pkcs7->signedAttribs = signedAttribs; 03034 pkcs7->signedAttribsSz = signedAttribsSz; 03035 03036 ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); 03037 if (ret <= 0) { 03038 WOLFSSL_MSG("Error encoding CMS SignedData content type"); 03039 } 03040 03041 ForceZero(encrypted, encryptedSz); 03042 XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03043 pkcs7->rng = NULL; 03044 wc_FreeRng(&rng); 03045 03046 return ret; 03047 } 03048 03049 #endif /* !NO_PKCS7_ENCRYPTED_DATA */ 03050 #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ 03051 03052 03053 #ifndef NO_RSA 03054 03055 #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK 03056 /* register raw RSA sign digest callback */ 03057 int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, CallbackRsaSignRawDigest cb) 03058 { 03059 if (pkcs7 == NULL || cb == NULL) { 03060 return BAD_FUNC_ARG; 03061 } 03062 03063 pkcs7->rsaSignRawDigestCb = cb; 03064 03065 return 0; 03066 } 03067 #endif 03068 03069 /* returns size of signature put into out, negative on error */ 03070 static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, 03071 byte* hash, word32 hashSz) 03072 { 03073 int ret = 0, i; 03074 word32 scratch = 0, verified = 0; 03075 #ifdef WOLFSSL_SMALL_STACK 03076 byte* digest; 03077 RsaKey* key; 03078 DecodedCert* dCert; 03079 #else 03080 byte digest[MAX_PKCS7_DIGEST_SZ]; 03081 RsaKey key[1]; 03082 DecodedCert stack_dCert; 03083 DecodedCert* dCert = &stack_dCert; 03084 #endif 03085 03086 if (pkcs7 == NULL || sig == NULL || hash == NULL) { 03087 return BAD_FUNC_ARG; 03088 } 03089 03090 #ifdef WOLFSSL_SMALL_STACK 03091 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 03092 DYNAMIC_TYPE_TMP_BUFFER); 03093 if (digest == NULL) 03094 return MEMORY_E; 03095 03096 key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03097 if (key == NULL) { 03098 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03099 return MEMORY_E; 03100 } 03101 03102 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 03103 DYNAMIC_TYPE_DCERT); 03104 if (dCert == NULL) { 03105 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03106 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03107 return MEMORY_E; 03108 } 03109 #endif 03110 03111 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); 03112 03113 /* loop over certs received in certificates set, try to find one 03114 * that will validate signature */ 03115 for (i = 0; i < MAX_PKCS7_CERTS; i++) { 03116 03117 verified = 0; 03118 scratch = 0; 03119 03120 if (pkcs7->certSz[i] == 0) 03121 continue; 03122 03123 ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); 03124 if (ret != 0) { 03125 #ifdef WOLFSSL_SMALL_STACK 03126 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03127 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03128 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 03129 #endif 03130 return ret; 03131 } 03132 03133 InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); 03134 /* not verifying, only using this to extract public key */ 03135 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); 03136 if (ret < 0) { 03137 WOLFSSL_MSG("ASN RSA cert parse error"); 03138 FreeDecodedCert(dCert); 03139 wc_FreeRsaKey(key); 03140 continue; 03141 } 03142 03143 if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key, 03144 dCert->pubKeySize) < 0) { 03145 WOLFSSL_MSG("ASN RSA key decode error"); 03146 FreeDecodedCert(dCert); 03147 wc_FreeRsaKey(key); 03148 continue; 03149 } 03150 03151 #ifdef WOLFSSL_ASYNC_CRYPT 03152 do { 03153 ret = wc_AsyncWait(ret, &key->asyncDev, 03154 WC_ASYNC_FLAG_CALL_AGAIN); 03155 #endif 03156 if (ret >= 0) { 03157 ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, 03158 key); 03159 } 03160 #ifdef WOLFSSL_ASYNC_CRYPT 03161 } while (ret == WC_PENDING_E); 03162 #endif 03163 FreeDecodedCert(dCert); 03164 wc_FreeRsaKey(key); 03165 03166 if ((ret > 0) && (hashSz == (word32)ret)) { 03167 if (XMEMCMP(digest, hash, hashSz) == 0) { 03168 /* found signer that successfully verified signature */ 03169 verified = 1; 03170 break; 03171 } 03172 } 03173 } 03174 03175 if (verified == 0) { 03176 ret = SIG_VERIFY_E; 03177 } 03178 03179 #ifdef WOLFSSL_SMALL_STACK 03180 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03181 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03182 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 03183 #endif 03184 03185 return ret; 03186 } 03187 03188 #endif /* NO_RSA */ 03189 03190 03191 #ifdef HAVE_ECC 03192 03193 /* returns size of signature put into out, negative on error */ 03194 static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, 03195 byte* hash, word32 hashSz) 03196 { 03197 int ret = 0, i; 03198 int res = 0; 03199 int verified = 0; 03200 #ifdef WOLFSSL_SMALL_STACK 03201 byte* digest; 03202 ecc_key* key; 03203 DecodedCert* dCert; 03204 #else 03205 byte digest[MAX_PKCS7_DIGEST_SZ]; 03206 ecc_key key[1]; 03207 DecodedCert stack_dCert; 03208 DecodedCert* dCert = &stack_dCert; 03209 #endif 03210 word32 idx = 0; 03211 03212 if (pkcs7 == NULL || sig == NULL) 03213 return BAD_FUNC_ARG; 03214 03215 #ifdef WOLFSSL_SMALL_STACK 03216 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 03217 DYNAMIC_TYPE_TMP_BUFFER); 03218 if (digest == NULL) 03219 return MEMORY_E; 03220 03221 key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03222 if (key == NULL) { 03223 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03224 return MEMORY_E; 03225 } 03226 03227 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 03228 DYNAMIC_TYPE_DCERT); 03229 if (dCert == NULL) { 03230 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03231 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03232 return MEMORY_E; 03233 } 03234 #endif 03235 03236 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); 03237 03238 /* loop over certs received in certificates set, try to find one 03239 * that will validate signature */ 03240 for (i = 0; i < MAX_PKCS7_CERTS; i++) { 03241 03242 verified = 0; 03243 03244 if (pkcs7->certSz[i] == 0) 03245 continue; 03246 03247 ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); 03248 if (ret != 0) { 03249 #ifdef WOLFSSL_SMALL_STACK 03250 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03251 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03252 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 03253 #endif 03254 return ret; 03255 } 03256 03257 InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); 03258 /* not verifying, only using this to extract public key */ 03259 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); 03260 if (ret < 0) { 03261 WOLFSSL_MSG("ASN ECC cert parse error"); 03262 FreeDecodedCert(dCert); 03263 wc_ecc_free(key); 03264 continue; 03265 } 03266 03267 if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, 03268 pkcs7->publicKeySz) < 0) { 03269 WOLFSSL_MSG("ASN ECC key decode error"); 03270 FreeDecodedCert(dCert); 03271 wc_ecc_free(key); 03272 continue; 03273 } 03274 03275 #ifdef WOLFSSL_ASYNC_CRYPT 03276 do { 03277 ret = wc_AsyncWait(ret, &key->asyncDev, 03278 WC_ASYNC_FLAG_CALL_AGAIN); 03279 #endif 03280 if (ret >= 0) { 03281 ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); 03282 } 03283 #ifdef WOLFSSL_ASYNC_CRYPT 03284 } while (ret == WC_PENDING_E); 03285 #endif 03286 03287 FreeDecodedCert(dCert); 03288 wc_ecc_free(key); 03289 03290 if (ret == 0 && res == 1) { 03291 /* found signer that successfully verified signature */ 03292 verified = 1; 03293 break; 03294 } 03295 } 03296 03297 if (verified == 0) { 03298 ret = SIG_VERIFY_E; 03299 } 03300 03301 #ifdef WOLFSSL_SMALL_STACK 03302 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03303 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03304 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 03305 #endif 03306 03307 return ret; 03308 } 03309 03310 #endif /* HAVE_ECC */ 03311 03312 03313 /* build SignedData digest, both in PKCS#7 DigestInfo format and 03314 * as plain digest for CMS. 03315 * 03316 * pkcs7 - pointer to initialized PKCS7 struct 03317 * signedAttrib - signed attributes 03318 * signedAttribSz - size of signedAttrib, octets 03319 * pkcs7Digest - [OUT] PKCS#7 DigestInfo 03320 * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest 03321 * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest 03322 * plainDigestSz - [OUT] size of digest at plainDigest 03323 * 03324 * returns 0 on success, negative on error */ 03325 static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, 03326 word32 signedAttribSz, byte* pkcs7Digest, 03327 word32* pkcs7DigestSz, byte** plainDigest, 03328 word32* plainDigestSz, 03329 const byte* hashBuf, word32 hashBufSz) 03330 { 03331 int ret = 0, digIdx = 0; 03332 word32 attribSetSz = 0, hashSz = 0; 03333 byte attribSet[MAX_SET_SZ]; 03334 byte digest[WC_MAX_DIGEST_SIZE]; 03335 byte digestInfoSeq[MAX_SEQ_SZ]; 03336 byte digestStr[MAX_OCTET_STR_SZ]; 03337 byte algoId[MAX_ALGO_SZ]; 03338 word32 digestInfoSeqSz, digestStrSz, algoIdSz; 03339 #ifdef WOLFSSL_SMALL_STACK 03340 byte* digestInfo; 03341 #else 03342 byte digestInfo[MAX_PKCS7_DIGEST_SZ]; 03343 #endif 03344 03345 wc_HashAlg hash; 03346 enum wc_HashType hashType; 03347 03348 /* check arguments */ 03349 if (pkcs7 == NULL || pkcs7Digest == NULL || 03350 pkcs7DigestSz == NULL || plainDigest == NULL) { 03351 return BAD_FUNC_ARG; 03352 } 03353 03354 hashType = wc_OidGetHash(pkcs7->hashOID); 03355 ret = wc_HashGetDigestSize(hashType); 03356 if (ret < 0) 03357 return ret; 03358 hashSz = ret; 03359 03360 if (signedAttribSz > 0) { 03361 if (signedAttrib == NULL) 03362 return BAD_FUNC_ARG; 03363 } 03364 else { 03365 if (hashBuf && hashBufSz > 0) { 03366 if (hashSz != hashBufSz) 03367 return BAD_FUNC_ARG; 03368 } 03369 else if (pkcs7->content == NULL) 03370 return BAD_FUNC_ARG; 03371 } 03372 03373 #ifdef WOLFSSL_SMALL_STACK 03374 digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 03375 DYNAMIC_TYPE_TMP_BUFFER); 03376 if (digestInfo == NULL) 03377 return MEMORY_E; 03378 #endif 03379 03380 XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); 03381 XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); 03382 XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); 03383 03384 03385 /* calculate digest */ 03386 if (hashBuf && hashBufSz > 0 && signedAttribSz == 0) { 03387 XMEMCPY(digest, hashBuf, hashBufSz); 03388 } 03389 else { 03390 ret = wc_HashInit(&hash, hashType); 03391 if (ret < 0) { 03392 #ifdef WOLFSSL_SMALL_STACK 03393 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03394 #endif 03395 return ret; 03396 } 03397 03398 if (signedAttribSz > 0) { 03399 attribSetSz = SetSet(signedAttribSz, attribSet); 03400 03401 /* calculate digest */ 03402 ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); 03403 if (ret == 0) 03404 ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); 03405 if (ret == 0) 03406 ret = wc_HashFinal(&hash, hashType, digest); 03407 } else { 03408 ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); 03409 if (ret == 0) 03410 ret = wc_HashFinal(&hash, hashType, digest); 03411 } 03412 03413 wc_HashFree(&hash, hashType); 03414 if (ret < 0) { 03415 #ifdef WOLFSSL_SMALL_STACK 03416 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03417 #endif 03418 return ret; 03419 } 03420 } 03421 03422 /* Set algoID, with NULL attributes */ 03423 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); 03424 03425 digestStrSz = SetOctetString(hashSz, digestStr); 03426 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, 03427 digestInfoSeq); 03428 03429 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); 03430 digIdx += digestInfoSeqSz; 03431 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); 03432 digIdx += algoIdSz; 03433 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); 03434 digIdx += digestStrSz; 03435 XMEMCPY(digestInfo + digIdx, digest, hashSz); 03436 digIdx += hashSz; 03437 03438 XMEMCPY(pkcs7Digest, digestInfo, digIdx); 03439 *pkcs7DigestSz = digIdx; 03440 03441 /* set plain digest pointer */ 03442 *plainDigest = pkcs7Digest + digIdx - hashSz; 03443 *plainDigestSz = hashSz; 03444 03445 #ifdef WOLFSSL_SMALL_STACK 03446 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03447 #endif 03448 return 0; 03449 } 03450 03451 03452 /* Verifies CMS/PKCS7 SignedData content digest matches that which is 03453 * included in the messageDigest signed attribute. Only called when 03454 * signed attributes are present, otherwise original signature verification 03455 * is done over content. 03456 * 03457 * pkcs7 - pointer to initialized PKCS7 struct 03458 * hashBuf - pointer to user-provided hash buffer, used with 03459 * wc_PKCS7_VerifySignedData_ex() 03460 * hashBufSz - size of hashBuf, octets 03461 * 03462 * return 0 on success, negative on error */ 03463 static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7, 03464 const byte* hashBuf, 03465 word32 hashSz) 03466 { 03467 int ret = 0, digestSz = 0, innerAttribSz = 0; 03468 word32 idx = 0; 03469 byte* digestBuf = NULL; 03470 #ifdef WOLFSSL_SMALL_STACK 03471 byte* digest = NULL; 03472 #else 03473 byte digest[MAX_PKCS7_DIGEST_SZ]; 03474 #endif 03475 PKCS7DecodedAttrib* attrib; 03476 enum wc_HashType hashType; 03477 03478 /* messageDigest OID (1.2.840.113549.1.9.4) */ 03479 const byte mdOid[] = 03480 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; 03481 03482 if (pkcs7 == NULL) 03483 return BAD_FUNC_ARG; 03484 03485 if ((pkcs7->content == NULL || pkcs7->contentSz == 0) && 03486 (hashBuf == NULL || hashSz == 0)) { 03487 WOLFSSL_MSG("SignedData bundle has no content or hash to verify"); 03488 return BAD_FUNC_ARG; 03489 } 03490 03491 /* lookup messageDigest attribute */ 03492 attrib = findAttrib(pkcs7, mdOid, sizeof(mdOid)); 03493 if (attrib == NULL) { 03494 WOLFSSL_MSG("messageDigest attribute not in bundle, must be when " 03495 "signed attribs are present"); 03496 return ASN_PARSE_E; 03497 } 03498 03499 /* advance past attrib->value ASN.1 header and length */ 03500 if (attrib->value == NULL || attrib->valueSz == 0) 03501 return ASN_PARSE_E; 03502 03503 if (attrib->value[idx++] != ASN_OCTET_STRING) 03504 return ASN_PARSE_E; 03505 03506 if (GetLength(attrib->value, &idx, &innerAttribSz, attrib->valueSz) < 0) 03507 return ASN_PARSE_E; 03508 03509 /* get hash type and size */ 03510 hashType = wc_OidGetHash(pkcs7->hashOID); 03511 if (hashType == WC_HASH_TYPE_NONE) { 03512 WOLFSSL_MSG("Error getting hash type for PKCS7 content verification"); 03513 return BAD_FUNC_ARG; 03514 } 03515 03516 /* build content hash if needed, or use existing hash value */ 03517 if (hashBuf == NULL) { 03518 03519 #ifdef WOLFSSL_SMALL_STACK 03520 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 03521 DYNAMIC_TYPE_TMP_BUFFER); 03522 if (digest == NULL) 03523 return MEMORY_E; 03524 #endif 03525 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); 03526 03527 ret = wc_Hash(hashType, pkcs7->content, pkcs7->contentSz, digest, 03528 MAX_PKCS7_DIGEST_SZ); 03529 if (ret < 0) { 03530 WOLFSSL_MSG("Error hashing PKCS7 content for verification"); 03531 #ifdef WOLFSSL_SMALL_STACK 03532 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03533 #endif 03534 return ret; 03535 } 03536 03537 digestBuf = digest; 03538 digestSz = wc_HashGetDigestSize(hashType); 03539 if (digestSz < 0) { 03540 WOLFSSL_MSG("Invalid hash type"); 03541 #ifdef WOLFSSL_SMALL_STACK 03542 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03543 #endif 03544 return digestSz; 03545 } 03546 } else { 03547 03548 /* user passed in pre-computed hash */ 03549 digestBuf = (byte*)hashBuf; 03550 digestSz = (int)hashSz; 03551 } 03552 03553 /* compare generated to hash in messageDigest attribute */ 03554 if ((innerAttribSz != digestSz) || 03555 (XMEMCMP(attrib->value + idx, digestBuf, (word32)digestSz) != 0)) { 03556 WOLFSSL_MSG("Content digest does not match messageDigest attrib value"); 03557 #ifdef WOLFSSL_SMALL_STACK 03558 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03559 #endif 03560 return SIG_VERIFY_E; 03561 } 03562 03563 if (hashBuf == NULL) { 03564 #ifdef WOLFSSL_SMALL_STACK 03565 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03566 #endif 03567 } 03568 03569 return 0; 03570 } 03571 03572 03573 /* verifies SignedData signature, over either PKCS#7 DigestInfo or 03574 * content digest. 03575 * 03576 * pkcs7 - pointer to initialized PKCS7 struct 03577 * sig - signature to verify 03578 * sigSz - size of sig 03579 * signedAttrib - signed attributes, or null if empty 03580 * signedAttribSz - size of signedAttributes 03581 * 03582 * return 0 on success, negative on error */ 03583 static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, 03584 word32 sigSz, byte* signedAttrib, 03585 word32 signedAttribSz, 03586 const byte* hashBuf, word32 hashSz) 03587 { 03588 int ret = 0; 03589 word32 plainDigestSz = 0, pkcs7DigestSz; 03590 byte* plainDigest = NULL; /* offset into pkcs7Digest */ 03591 #ifdef WOLFSSL_SMALL_STACK 03592 byte* pkcs7Digest; 03593 #else 03594 byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; 03595 #endif 03596 03597 if (pkcs7 == NULL) 03598 return BAD_FUNC_ARG; 03599 03600 /* allocate space to build hash */ 03601 pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; 03602 #ifdef WOLFSSL_SMALL_STACK 03603 pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, 03604 DYNAMIC_TYPE_TMP_BUFFER); 03605 if (pkcs7Digest == NULL) 03606 return MEMORY_E; 03607 #endif 03608 03609 XMEMSET(pkcs7Digest, 0, pkcs7DigestSz); 03610 03611 /* verify signed attrib digest matches that of content */ 03612 if (signedAttrib != NULL) { 03613 ret = wc_PKCS7_VerifyContentMessageDigest(pkcs7, hashBuf, hashSz); 03614 if (ret != 0) { 03615 #ifdef WOLFSSL_SMALL_STACK 03616 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03617 #endif 03618 return ret; 03619 } 03620 } 03621 03622 /* build hash to verify against */ 03623 ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, 03624 signedAttribSz, pkcs7Digest, 03625 &pkcs7DigestSz, &plainDigest, 03626 &plainDigestSz, hashBuf, hashSz); 03627 if (ret < 0) { 03628 #ifdef WOLFSSL_SMALL_STACK 03629 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03630 #endif 03631 return ret; 03632 } 03633 03634 /* If no certificates are available then store the signature and hash for 03635 * user to verify. Make sure that different return value than success is 03636 * returned because the signature was not verified here. */ 03637 if (ret == 0) { 03638 byte haveCert = 0; 03639 int i; 03640 03641 for (i = 0; i < MAX_PKCS7_CERTS; i++) { 03642 if (pkcs7->certSz[i] == 0) 03643 continue; 03644 haveCert = 1; 03645 } 03646 03647 if (!haveCert) { 03648 WOLFSSL_MSG("No certificates in bundle to verify signature"); 03649 03650 /* store signature */ 03651 XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE); 03652 pkcs7->signature = NULL; 03653 pkcs7->signatureSz = 0; 03654 pkcs7->signature = (byte*)XMALLOC(sigSz, pkcs7->heap, 03655 DYNAMIC_TYPE_SIGNATURE); 03656 if (pkcs7->signature == NULL) { 03657 #ifdef WOLFSSL_SMALL_STACK 03658 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03659 #endif 03660 return MEMORY_E; 03661 } 03662 XMEMCPY(pkcs7->signature, sig, sigSz); 03663 pkcs7->signatureSz = sigSz; 03664 03665 /* store plain digest (CMS and ECC) */ 03666 XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); 03667 pkcs7->plainDigest = NULL; 03668 pkcs7->plainDigestSz = 0; 03669 pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap, 03670 DYNAMIC_TYPE_DIGEST); 03671 if (pkcs7->plainDigest == NULL) { 03672 #ifdef WOLFSSL_SMALL_STACK 03673 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03674 #endif 03675 return MEMORY_E; 03676 } 03677 XMEMCPY(pkcs7->plainDigest, plainDigest, plainDigestSz); 03678 pkcs7->plainDigestSz = plainDigestSz; 03679 03680 /* store pkcs7 digest (default RSA) */ 03681 XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); 03682 pkcs7->pkcs7Digest = NULL; 03683 pkcs7->pkcs7DigestSz = 0; 03684 pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, 03685 DYNAMIC_TYPE_DIGEST); 03686 if (pkcs7->pkcs7Digest == NULL) { 03687 #ifdef WOLFSSL_SMALL_STACK 03688 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03689 #endif 03690 return MEMORY_E; 03691 } 03692 XMEMCPY(pkcs7->pkcs7Digest, pkcs7Digest, pkcs7DigestSz); 03693 pkcs7->pkcs7DigestSz = pkcs7DigestSz; 03694 03695 #ifdef WOLFSSL_SMALL_STACK 03696 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03697 #endif 03698 return PKCS7_SIGNEEDS_CHECK; 03699 } 03700 } 03701 03702 03703 03704 switch (pkcs7->publicKeyOID) { 03705 03706 #ifndef NO_RSA 03707 case RSAk: 03708 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, 03709 pkcs7DigestSz); 03710 if (ret < 0) { 03711 WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); 03712 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, 03713 plainDigestSz); 03714 } 03715 break; 03716 #endif 03717 03718 #ifdef HAVE_ECC 03719 case ECDSAk: 03720 ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, 03721 plainDigestSz); 03722 break; 03723 #endif 03724 03725 default: 03726 WOLFSSL_MSG("Unsupported public key type"); 03727 ret = BAD_FUNC_ARG; 03728 } 03729 03730 #ifdef WOLFSSL_SMALL_STACK 03731 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03732 #endif 03733 return ret; 03734 } 03735 03736 03737 /* set correct public key OID based on signature OID, stores in 03738 * pkcs7->publicKeyOID and returns same value */ 03739 static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) 03740 { 03741 if (pkcs7 == NULL) 03742 return BAD_FUNC_ARG; 03743 03744 pkcs7->publicKeyOID = 0; 03745 03746 switch (sigOID) { 03747 03748 #ifndef NO_RSA 03749 /* RSA signature types */ 03750 case CTC_MD2wRSA: 03751 case CTC_MD5wRSA: 03752 case CTC_SHAwRSA: 03753 case CTC_SHA224wRSA: 03754 case CTC_SHA256wRSA: 03755 case CTC_SHA384wRSA: 03756 case CTC_SHA512wRSA: 03757 pkcs7->publicKeyOID = RSAk; 03758 break; 03759 03760 /* if sigOID is already RSAk */ 03761 case RSAk: 03762 pkcs7->publicKeyOID = sigOID; 03763 break; 03764 #endif 03765 03766 #ifndef NO_DSA 03767 /* DSA signature types */ 03768 case CTC_SHAwDSA: 03769 pkcs7->publicKeyOID = DSAk; 03770 break; 03771 03772 /* if sigOID is already DSAk */ 03773 case DSAk: 03774 pkcs7->publicKeyOID = sigOID; 03775 break; 03776 #endif 03777 03778 #ifdef HAVE_ECC 03779 /* ECDSA signature types */ 03780 case CTC_SHAwECDSA: 03781 case CTC_SHA224wECDSA: 03782 case CTC_SHA256wECDSA: 03783 case CTC_SHA384wECDSA: 03784 case CTC_SHA512wECDSA: 03785 pkcs7->publicKeyOID = ECDSAk; 03786 break; 03787 03788 /* if sigOID is already ECDSAk */ 03789 case ECDSAk: 03790 pkcs7->publicKeyOID = sigOID; 03791 break; 03792 #endif 03793 03794 default: 03795 WOLFSSL_MSG("Unsupported public key algorithm"); 03796 return ASN_SIG_KEY_E; 03797 } 03798 03799 return pkcs7->publicKeyOID; 03800 } 03801 03802 03803 /* Parses through the attributes and adds them to the PKCS7 structure 03804 * Creates dynamic attribute structures that are free'd with calling 03805 * wc_PKCS7_Free() 03806 * 03807 * NOTE: An attribute has the ASN1 format of 03808 ** Sequence 03809 ****** Object ID 03810 ****** Set 03811 ********** {PritnableString, UTCTime, OCTET STRING ...} 03812 * 03813 * pkcs7 the PKCS7 structure to put the parsed attributes into 03814 * in buffer holding all attributes 03815 * inSz size of in buffer 03816 * 03817 * returns the number of attributes parsed on success 03818 */ 03819 static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) 03820 { 03821 int found = 0; 03822 word32 idx = 0; 03823 word32 oid; 03824 03825 if (pkcs7 == NULL || in == NULL || inSz < 0) { 03826 return BAD_FUNC_ARG; 03827 } 03828 03829 while (idx < (word32)inSz) { 03830 int length = 0; 03831 int oidIdx; 03832 PKCS7DecodedAttrib* attrib; 03833 03834 if (GetSequence(in, &idx, &length, inSz) < 0) 03835 return ASN_PARSE_E; 03836 03837 attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), 03838 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03839 if (attrib == NULL) { 03840 return MEMORY_E; 03841 } 03842 XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib)); 03843 03844 oidIdx = idx; 03845 if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz) 03846 < 0) { 03847 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03848 return ASN_PARSE_E; 03849 } 03850 attrib->oidSz = idx - oidIdx; 03851 attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap, 03852 DYNAMIC_TYPE_PKCS7); 03853 if (attrib->oid == NULL) { 03854 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03855 return MEMORY_E; 03856 } 03857 XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz); 03858 03859 /* Get Set that contains the printable string value */ 03860 if (GetSet(in, &idx, &length, inSz) < 0) { 03861 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03862 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03863 return ASN_PARSE_E; 03864 } 03865 03866 if ((inSz - idx) < (word32)length) { 03867 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03868 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03869 return ASN_PARSE_E; 03870 } 03871 03872 attrib->valueSz = (word32)length; 03873 attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap, 03874 DYNAMIC_TYPE_PKCS7); 03875 if (attrib->value == NULL) { 03876 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03877 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03878 return MEMORY_E; 03879 } 03880 XMEMCPY(attrib->value, in + idx, attrib->valueSz); 03881 idx += length; 03882 03883 /* store attribute in linked list */ 03884 if (pkcs7->decodedAttrib != NULL) { 03885 attrib->next = pkcs7->decodedAttrib; 03886 pkcs7->decodedAttrib = attrib; 03887 } else { 03888 pkcs7->decodedAttrib = attrib; 03889 } 03890 found++; 03891 } 03892 03893 return found; 03894 } 03895 03896 03897 /* option to turn off support for degenerate cases 03898 * flag 0 turns off support 03899 * flag 1 turns on support 03900 * 03901 * by default support for SignedData degenerate cases is on 03902 */ 03903 void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag) 03904 { 03905 if (pkcs7) { 03906 if (flag) { /* flag of 1 turns on support for degenerate */ 03907 pkcs7->noDegenerate = 0; 03908 } 03909 else { /* flag of 0 turns off support */ 03910 pkcs7->noDegenerate = 1; 03911 } 03912 } 03913 } 03914 03915 /* Parses through a signerInfo set. Reads buffer "in" from "idxIn" to "idxIn" + 03916 * length treating the current "idxIn" plus the length of set as max possible 03917 * index. 03918 * 03919 * In the case that signed attributes are found "signedAttrib" gets set to point 03920 * at their location in the buffer "in". Also in this case signedAttribSz gets 03921 * set to the size of the signedAttrib buffer. 03922 * 03923 * returns 0 on success 03924 */ 03925 static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, 03926 word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz) 03927 { 03928 int ret = 0; 03929 int length; 03930 int version; 03931 word32 sigOID = 0, hashOID = 0; 03932 word32 idx = *idxIn, localIdx; 03933 byte tag; 03934 03935 WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo"); 03936 /* require a signer if degenerate case not allowed */ 03937 if (inSz == 0 && pkcs7->noDegenerate == 1) { 03938 WOLFSSL_MSG("Set to not allow degenerate cases"); 03939 return PKCS7_NO_SIGNER_E; 03940 } 03941 03942 if (inSz == 0 && degenerate == 0) { 03943 WOLFSSL_MSG("PKCS7 signers expected"); 03944 return PKCS7_NO_SIGNER_E; 03945 } 03946 03947 /* not a degenerate case and there is elements in the set */ 03948 if (inSz > 0 && degenerate == 0) { 03949 ret = wc_PKCS7_SignerInfoNew(pkcs7); 03950 03951 /* Get the sequence of the first signerInfo */ 03952 if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) 03953 ret = ASN_PARSE_E; 03954 03955 /* Get the version */ 03956 if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0) 03957 ret = ASN_PARSE_E; 03958 03959 if (ret == 0) { 03960 pkcs7->signerInfo->version = version; 03961 } 03962 03963 if (ret == 0 && version == 1) { 03964 /* Get the sequence of IssuerAndSerialNumber */ 03965 if (GetSequence(in, &idx, &length, inSz) < 0) 03966 ret = ASN_PARSE_E; 03967 03968 if (ret == 0) { 03969 ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); 03970 idx += length; 03971 } 03972 03973 } else if (ret == 0 && version == 3) { 03974 /* Get the sequence of SubjectKeyIdentifier */ 03975 if (idx + 1 > inSz) 03976 ret = BUFFER_E; 03977 03978 localIdx = idx; 03979 if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && 03980 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 03981 idx++; 03982 03983 if (GetLength(in, &idx, &length, inSz) <= 0) 03984 ret = ASN_PARSE_E; 03985 03986 if (ret == 0 && idx + 1 > inSz) 03987 ret = BUFFER_E; 03988 03989 if (ret == 0 && GetASNTag(in, &idx, &tag, inSz) < 0) 03990 ret = ASN_PARSE_E; 03991 03992 if (ret == 0 && tag != ASN_OCTET_STRING) 03993 ret = ASN_PARSE_E; 03994 03995 if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) 03996 ret = ASN_PARSE_E; 03997 } 03998 else { 03999 /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version 04000 * 3 try to get issuerAndSerial */ 04001 localIdx = idx; 04002 if (GetASNTag(in, &localIdx, &tag, inSz) == 0 && 04003 tag == ASN_CONTEXT_SPECIFIC) { 04004 idx++; 04005 if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) 04006 ret = ASN_PARSE_E; 04007 } 04008 else { 04009 if (pkcs7->version != 3) { 04010 WOLFSSL_MSG("Unexpected signer info found with version"); 04011 ret = ASN_PARSE_E; 04012 } 04013 04014 if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) 04015 ret = ASN_PARSE_E; 04016 } 04017 } 04018 04019 if (ret == 0) { 04020 ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); 04021 idx += length; 04022 } 04023 04024 } else { 04025 WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); 04026 ret = ASN_VERSION_E; 04027 } 04028 04029 /* Get the sequence of digestAlgorithm */ 04030 if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, inSz) < 0) { 04031 ret = ASN_PARSE_E; 04032 } 04033 pkcs7->hashOID = (int)hashOID; 04034 04035 /* Get the IMPLICIT[0] SET OF signedAttributes */ 04036 localIdx = idx; 04037 if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && 04038 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 04039 idx++; 04040 04041 if (GetLength(in, &idx, &length, inSz) < 0) 04042 ret = ASN_PARSE_E; 04043 04044 /* save pointer and length */ 04045 *signedAttrib = &in[idx]; 04046 *signedAttribSz = length; 04047 04048 if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, *signedAttrib, 04049 *signedAttribSz) < 0) { 04050 WOLFSSL_MSG("Error parsing signed attributes"); 04051 ret = ASN_PARSE_E; 04052 } 04053 04054 idx += length; 04055 } 04056 04057 /* Get digestEncryptionAlgorithm */ 04058 if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidSigType, inSz) < 0) { 04059 ret = ASN_PARSE_E; 04060 } 04061 04062 /* store public key type based on digestEncryptionAlgorithm */ 04063 if (ret == 0) { 04064 ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); 04065 if (ret < 0) { 04066 WOLFSSL_MSG("Failed to set public key OID from signature"); 04067 } 04068 else { 04069 /* if previous return was positive then was success */ 04070 ret = 0; 04071 } 04072 } 04073 } 04074 04075 /* update index on success */ 04076 if (ret == 0) { 04077 *idxIn = idx; 04078 } 04079 04080 return ret; 04081 } 04082 04083 04084 /* Finds the certificates in the message and saves it. By default allows 04085 * degenerate cases which can have no signer. 04086 * 04087 * By default expects type SIGNED_DATA (SignedData) which can have any number of 04088 * elements in signerInfos collection, including zero. (RFC2315 section 9.1) 04089 * When adding support for the case of SignedAndEnvelopedData content types a 04090 * signer is required. In this case the PKCS7 flag noDegenerate could be set. 04091 */ 04092 static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, 04093 word32 hashSz, byte* in, word32 inSz, 04094 byte* in2, word32 in2Sz) 04095 { 04096 word32 idx, maxIdx = inSz, outerContentType, contentTypeSz = 0, totalSz = 0; 04097 int length = 0, version = 0, ret = 0; 04098 byte* content = NULL; 04099 byte* contentDynamic = NULL; 04100 byte* sig = NULL; 04101 byte* cert = NULL; 04102 byte* signedAttrib = NULL; 04103 byte* contentType = NULL; 04104 int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; 04105 word32 localIdx, start; 04106 byte degenerate = 0; 04107 byte detached = 0; 04108 byte tag = 0; 04109 #ifdef ASN_BER_TO_DER 04110 byte* der; 04111 #endif 04112 int multiPart = 0, keepContent; 04113 int contentLen = 0; 04114 04115 byte* pkiMsg = in; 04116 word32 pkiMsgSz = inSz; 04117 #ifndef NO_PKCS7_STREAM 04118 word32 stateIdx = 0; 04119 long rc; 04120 #endif 04121 04122 byte* pkiMsg2 = in2; 04123 word32 pkiMsg2Sz = in2Sz; 04124 04125 if (pkcs7 == NULL) 04126 return BAD_FUNC_ARG; 04127 04128 #ifndef NO_PKCS7_STREAM 04129 /* allow for 0 size inputs with stream mode */ 04130 if (pkiMsg == NULL && pkiMsgSz > 0) 04131 return BAD_FUNC_ARG; 04132 04133 #else 04134 if (pkiMsg == NULL || pkiMsgSz == 0) 04135 return BAD_FUNC_ARG; 04136 #endif 04137 04138 if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) { 04139 return BAD_FUNC_ARG; 04140 } 04141 idx = 0; 04142 04143 #ifdef ASN_BER_TO_DER 04144 if (pkcs7->derSz > 0 && pkcs7->der) { 04145 pkiMsg = in = pkcs7->der; 04146 } 04147 #endif 04148 04149 #ifndef NO_PKCS7_STREAM 04150 if (pkcs7->stream == NULL) { 04151 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { 04152 return ret; 04153 } 04154 } 04155 #endif 04156 04157 switch (pkcs7->state) { 04158 case WC_PKCS7_START: 04159 #ifndef NO_PKCS7_STREAM 04160 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + 04161 MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + 04162 ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ, 04163 &pkiMsg, &idx)) != 0) { 04164 break; 04165 } 04166 04167 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); 04168 if (rc < 0) { 04169 ret = (int)rc; 04170 break; 04171 } 04172 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; 04173 #endif 04174 04175 /* determine total message size */ 04176 totalSz = pkiMsgSz; 04177 if (pkiMsg2 && pkiMsg2Sz > 0) { 04178 totalSz += pkiMsg2Sz + pkcs7->contentSz; 04179 } 04180 04181 /* Get the contentInfo sequence */ 04182 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, 04183 NO_USER_CHECK) < 0) 04184 ret = ASN_PARSE_E; 04185 04186 if (ret == 0 && length == 0 && pkiMsg[idx-1] == 0x80) { 04187 #ifdef ASN_BER_TO_DER 04188 word32 len = 0; 04189 04190 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); 04191 if (ret != LENGTH_ONLY_E) 04192 return ret; 04193 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04194 if (pkcs7->der == NULL) 04195 return MEMORY_E; 04196 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); 04197 if (ret < 0) 04198 return ret; 04199 04200 pkiMsg = in = pkcs7->der; 04201 pkiMsgSz = pkcs7->derSz = len; 04202 idx = 0; 04203 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, 04204 NO_USER_CHECK) < 0) 04205 return ASN_PARSE_E; 04206 04207 #ifndef NO_PKCS7_STREAM 04208 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, 04209 pkiMsg, pkiMsgSz); 04210 if (rc < 0) { 04211 ret = (int)rc; 04212 break; 04213 } 04214 #endif 04215 #else 04216 ret = BER_INDEF_E; 04217 #endif 04218 } 04219 04220 /* Get the contentInfo contentType */ 04221 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType, 04222 pkiMsgSz) < 0) 04223 ret = ASN_PARSE_E; 04224 04225 if (ret == 0 && outerContentType != SIGNED_DATA) { 04226 WOLFSSL_MSG("PKCS#7 input not of type SignedData"); 04227 ret = PKCS7_OID_E; 04228 } 04229 04230 /* get the ContentInfo content */ 04231 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, totalSz) != 0) 04232 ret = ASN_PARSE_E; 04233 04234 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 04235 ret = ASN_PARSE_E; 04236 04237 if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz, 04238 NO_USER_CHECK) < 0) 04239 ret = ASN_PARSE_E; 04240 04241 /* Get the signedData sequence */ 04242 if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, 04243 NO_USER_CHECK) < 0) 04244 ret = ASN_PARSE_E; 04245 04246 /* Get the version */ 04247 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 04248 ret = ASN_PARSE_E; 04249 04250 04251 /* version 1 follows RFC 2315 */ 04252 /* version 3 follows RFC 4108 */ 04253 if (ret == 0 && (version != 1 && version != 3)) { 04254 WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3"); 04255 ret = ASN_VERSION_E; 04256 } 04257 pkcs7->version = version; 04258 04259 /* Get the set of DigestAlgorithmIdentifiers */ 04260 if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04261 ret = ASN_PARSE_E; 04262 04263 /* Skip the set. */ 04264 idx += length; 04265 degenerate = (length == 0)? 1 : 0; 04266 if (pkcs7->noDegenerate == 1 && degenerate == 1) { 04267 ret = PKCS7_NO_SIGNER_E; 04268 } 04269 04270 if (ret != 0) 04271 break; 04272 04273 #ifndef NO_PKCS7_STREAM 04274 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { 04275 break; 04276 } 04277 if (pkiMsg2 && pkiMsg2Sz > 0) { 04278 pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz; 04279 } 04280 wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0); 04281 #endif 04282 04283 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2); 04284 FALL_THROUGH; 04285 04286 case WC_PKCS7_VERIFY_STAGE2: 04287 #ifndef NO_PKCS7_STREAM 04288 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, 04289 MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ 04290 + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { 04291 break; 04292 } 04293 04294 wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); 04295 if (pkcs7->stream->length > 0) 04296 pkiMsgSz = pkcs7->stream->length; 04297 #ifdef ASN_BER_TO_DER 04298 else if (pkcs7->der) 04299 pkiMsgSz = pkcs7->derSz; 04300 #endif 04301 else 04302 pkiMsgSz = inSz; 04303 04304 #endif 04305 /* Get the inner ContentInfo sequence */ 04306 if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, 04307 NO_USER_CHECK) < 0) 04308 ret = ASN_PARSE_E; 04309 04310 /* Get the inner ContentInfo contentType */ 04311 if (ret == 0) { 04312 word32 tmpIdx = idx; 04313 04314 if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) 04315 ret = ASN_PARSE_E; 04316 04317 contentType = pkiMsg + tmpIdx; 04318 contentTypeSz = length + (idx - tmpIdx); 04319 04320 idx += length; 04321 } 04322 04323 if (ret != 0) 04324 break; 04325 04326 /* Check for content info, it could be omitted when degenerate */ 04327 localIdx = idx; 04328 ret = 0; 04329 if (localIdx + 1 > pkiMsgSz) { 04330 ret = BUFFER_E; 04331 break; 04332 } 04333 04334 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) 04335 ret = ASN_PARSE_E; 04336 04337 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 04338 ret = ASN_PARSE_E; 04339 04340 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, 04341 NO_USER_CHECK) <= 0) 04342 ret = ASN_PARSE_E; 04343 04344 if (localIdx >= pkiMsgSz) { 04345 ret = BUFFER_E; 04346 } 04347 04348 /* get length of content in the case that there is multiple parts */ 04349 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) 04350 ret = ASN_PARSE_E; 04351 04352 if (ret == 0 && tag == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { 04353 multiPart = 1; 04354 04355 /* Get length of all OCTET_STRINGs. */ 04356 if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz, 04357 NO_USER_CHECK) < 0) 04358 ret = ASN_PARSE_E; 04359 04360 /* Check whether there is one OCTET_STRING inside. */ 04361 start = localIdx; 04362 if (localIdx >= pkiMsgSz) { 04363 ret = BUFFER_E; 04364 } 04365 04366 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) 04367 != 0) 04368 ret = ASN_PARSE_E; 04369 04370 if (ret == 0 && tag != ASN_OCTET_STRING) 04371 ret = ASN_PARSE_E; 04372 04373 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, 04374 NO_USER_CHECK) < 0) 04375 ret = ASN_PARSE_E; 04376 04377 if (ret == 0) { 04378 /* Use single OCTET_STRING directly. */ 04379 if (localIdx - start + length == (word32)contentLen) 04380 multiPart = 0; 04381 localIdx = start; 04382 } 04383 } 04384 04385 /* get length of content in case of single part */ 04386 if (ret == 0 && !multiPart) { 04387 if (tag != ASN_OCTET_STRING) 04388 ret = ASN_PARSE_E; 04389 04390 if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, 04391 &length, pkiMsgSz, NO_USER_CHECK) < 0) 04392 ret = ASN_PARSE_E; 04393 } 04394 04395 /* update idx if successful */ 04396 if (ret == 0) { 04397 /* support using header and footer without content */ 04398 if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { 04399 localIdx = 0; 04400 } 04401 idx = localIdx; 04402 } 04403 else { 04404 04405 /* if pkcs7->content and pkcs7->contentSz are set, try to 04406 process as a detached signature */ 04407 if (!degenerate && 04408 (pkcs7->content != NULL && pkcs7->contentSz != 0)) { 04409 detached = 1; 04410 } 04411 04412 if (!degenerate && !detached && ret != 0) 04413 break; 04414 04415 length = 0; /* no content to read */ 04416 pkiMsg2 = pkiMsg; 04417 pkiMsg2Sz = pkiMsgSz; 04418 } 04419 04420 #ifndef NO_PKCS7_STREAM 04421 /* save detached flag value */ 04422 pkcs7->stream->detached = detached; 04423 04424 /* save contentType */ 04425 pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap, 04426 DYNAMIC_TYPE_PKCS7); 04427 if (pkcs7->stream->nonce == NULL) { 04428 ret = MEMORY_E; 04429 break; 04430 } 04431 else { 04432 pkcs7->stream->nonceSz = contentTypeSz; 04433 XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz); 04434 } 04435 04436 /* content expected? */ 04437 if ((ret == 0 && length > 0) && 04438 !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { 04439 pkcs7->stream->expected = length + ASN_TAG_SZ + MAX_LENGTH_SZ; 04440 } 04441 else { 04442 pkcs7->stream->expected = ASN_TAG_SZ + MAX_LENGTH_SZ; 04443 } 04444 04445 if (pkcs7->stream->expected > (pkcs7->stream->maxLen - idx)) { 04446 pkcs7->stream->expected = pkcs7->stream->maxLen - idx; 04447 } 04448 04449 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { 04450 break; 04451 } 04452 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); 04453 04454 /* content length is in multiple parts */ 04455 if (multiPart) { 04456 pkcs7->stream->expected = contentLen + ASN_TAG_SZ; 04457 } 04458 pkcs7->stream->multi = multiPart; 04459 04460 #endif 04461 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3); 04462 FALL_THROUGH; 04463 04464 case WC_PKCS7_VERIFY_STAGE3: 04465 #ifndef NO_PKCS7_STREAM 04466 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, 04467 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 04468 break; 04469 } 04470 04471 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 04472 pkiMsg, pkiMsgSz); 04473 if (rc < 0) { 04474 ret = (int)rc; 04475 break; 04476 } 04477 #ifdef ASN_BER_TO_DER 04478 if (pkcs7->derSz != 0) 04479 pkiMsgSz = pkcs7->derSz; 04480 else 04481 #endif 04482 pkiMsgSz = (word32)rc; 04483 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); 04484 04485 if (pkcs7->stream->length > 0) { 04486 localIdx = 0; 04487 } 04488 multiPart = pkcs7->stream->multi; 04489 detached = pkcs7->stream->detached; 04490 maxIdx = idx + pkcs7->stream->expected; 04491 #endif 04492 04493 /* Break out before content because it can be optional in degenerate 04494 * cases. */ 04495 if (ret != 0 && !degenerate) 04496 break; 04497 04498 /* get parts of content */ 04499 if (ret == 0 && multiPart) { 04500 int i = 0; 04501 keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0); 04502 04503 if (keepContent) { 04504 /* Create a buffer to hold content of OCTET_STRINGs. */ 04505 pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap, 04506 DYNAMIC_TYPE_PKCS7); 04507 if (pkcs7->contentDynamic == NULL) 04508 ret = MEMORY_E; 04509 } 04510 04511 start = localIdx; 04512 /* Use the data from each OCTET_STRING. */ 04513 while (ret == 0 && localIdx < start + contentLen) { 04514 if (GetASNTag(pkiMsg, &localIdx, &tag, totalSz) < 0) 04515 ret = ASN_PARSE_E; 04516 if (ret == 0 && tag != ASN_OCTET_STRING) 04517 ret = ASN_PARSE_E; 04518 04519 if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) 04520 ret = ASN_PARSE_E; 04521 if (ret == 0 && length + localIdx > start + contentLen) 04522 ret = ASN_PARSE_E; 04523 04524 if (ret == 0) { 04525 if (keepContent) { 04526 XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx, 04527 length); 04528 } 04529 i += length; 04530 localIdx += length; 04531 } 04532 } 04533 localIdx = start; /* reset for sanity check, increment later */ 04534 length = i; 04535 } 04536 04537 /* Save the inner data as the content. */ 04538 if (ret == 0 && length > 0) { 04539 contentSz = length; 04540 04541 /* support using header and footer without content */ 04542 if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { 04543 /* Content not provided, use provided pkiMsg2 footer */ 04544 content = NULL; 04545 localIdx = 0; 04546 if (contentSz != (int)pkcs7->contentSz) { 04547 WOLFSSL_MSG("Data signed does not match contentSz provided"); 04548 ret = BUFFER_E; 04549 } 04550 } 04551 else { 04552 if ((word32)length > pkiMsgSz - localIdx) { 04553 ret = BUFFER_E; 04554 } 04555 04556 /* Content pointer for calculating hashes later */ 04557 if (ret == 0 && !multiPart) { 04558 content = &pkiMsg[localIdx]; 04559 } 04560 if (ret == 0 && multiPart) { 04561 content = pkcs7->contentDynamic; 04562 } 04563 04564 if (ret == 0) { 04565 idx += length; 04566 04567 pkiMsg2 = pkiMsg; 04568 pkiMsg2Sz = pkiMsgSz; 04569 #ifndef NO_PKCS7_STREAM 04570 pkcs7->stream->varOne = pkiMsg2Sz; 04571 pkcs7->stream->flagOne = 1; 04572 #endif 04573 } 04574 } 04575 } 04576 else { 04577 pkiMsg2 = pkiMsg; 04578 pkiMsg2Sz = pkiMsgSz; 04579 #ifndef NO_PKCS7_STREAM 04580 pkcs7->stream->varOne = pkiMsg2Sz; 04581 pkcs7->stream->flagOne = 1; 04582 #endif 04583 } 04584 04585 /* If getting the content info failed with non degenerate then return the 04586 * error case. Otherwise with a degenerate it is ok if the content 04587 * info was omitted */ 04588 if (!degenerate && !detached && (ret != 0)) { 04589 break; 04590 } 04591 else { 04592 ret = 0; /* reset ret state on degenerate case */ 04593 } 04594 04595 #ifndef NO_PKCS7_STREAM 04596 /* save content */ 04597 if (detached == 1) { 04598 /* if detached, use content from user in pkcs7 struct */ 04599 content = pkcs7->content; 04600 contentSz = pkcs7->contentSz; 04601 } 04602 04603 if (content != NULL) { 04604 XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04605 pkcs7->stream->content = (byte*)XMALLOC(contentSz, pkcs7->heap, 04606 DYNAMIC_TYPE_PKCS7); 04607 if (pkcs7->stream->content == NULL) { 04608 ret = MEMORY_E; 04609 break; 04610 } 04611 else { 04612 XMEMCPY(pkcs7->stream->content, content, contentSz); 04613 pkcs7->stream->contentSz = contentSz; 04614 } 04615 } 04616 #endif /* !NO_PKCS7_STREAM */ 04617 04618 /* Get the implicit[0] set of certificates */ 04619 if (ret == 0 && idx >= pkiMsg2Sz) 04620 ret = BUFFER_E; 04621 04622 length = 0; /* set length to 0 to check if reading in any certs */ 04623 localIdx = idx; 04624 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 04625 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 04626 idx++; 04627 if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK) 04628 < 0) 04629 ret = ASN_PARSE_E; 04630 } 04631 04632 if (ret != 0) { 04633 break; 04634 } 04635 #ifndef NO_PKCS7_STREAM 04636 if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { 04637 stateIdx = idx; /* case where all data was read from in2 */ 04638 } 04639 04640 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { 04641 break; 04642 } 04643 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); 04644 if (length > 0) { 04645 pkcs7->stream->expected = length; 04646 } 04647 else { 04648 pkcs7->stream->expected = MAX_SEQ_SZ; 04649 if (pkcs7->stream->expected > (pkcs7->stream->maxLen - 04650 pkcs7->stream->totalRd) + pkcs7->stream->length) { 04651 pkcs7->stream->expected = (pkcs7->stream->maxLen - 04652 pkcs7->stream->totalRd) + pkcs7->stream->length; 04653 } 04654 } 04655 #endif 04656 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4); 04657 FALL_THROUGH; 04658 04659 case WC_PKCS7_VERIFY_STAGE4: 04660 #ifndef NO_PKCS7_STREAM 04661 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, 04662 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 04663 break; 04664 } 04665 04666 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); 04667 if (pkcs7->stream->flagOne) { 04668 pkiMsg2 = pkiMsg; 04669 } 04670 04671 /* restore content */ 04672 content = pkcs7->stream->content; 04673 contentSz = pkcs7->stream->contentSz; 04674 04675 /* restore detached flag */ 04676 detached = pkcs7->stream->detached; 04677 04678 /* store certificate if needed */ 04679 if (length > 0 && in2Sz == 0) { 04680 /* free tmpCert if not NULL */ 04681 XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04682 pkcs7->stream->tmpCert = (byte*)XMALLOC(length, 04683 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04684 if ((pkiMsg2 == NULL) || (pkcs7->stream->tmpCert == NULL)) { 04685 ret = MEMORY_E; 04686 break; 04687 } 04688 XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); 04689 pkiMsg2 = pkcs7->stream->tmpCert; 04690 pkiMsg2Sz = length; 04691 idx = 0; 04692 } 04693 #endif 04694 04695 if (length > 0) { 04696 /* At this point, idx is at the first certificate in 04697 * a set of certificates. There may be more than one, 04698 * or none, or they may be a PKCS 6 extended 04699 * certificate. We want to save the first cert if it 04700 * is X.509. */ 04701 04702 word32 certIdx = idx; 04703 04704 if (length < MAX_LENGTH_SZ + ASN_TAG_SZ) 04705 ret = BUFFER_E; 04706 04707 if (ret == 0) 04708 ret = GetASNTag(pkiMsg2, &certIdx, &tag, pkiMsg2Sz); 04709 04710 if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 04711 if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) 04712 ret = ASN_PARSE_E; 04713 04714 cert = &pkiMsg2[idx]; 04715 certSz += (certIdx - idx); 04716 if (certSz > length) { 04717 ret = BUFFER_E; 04718 break; 04719 } 04720 } 04721 #ifdef ASN_BER_TO_DER 04722 der = pkcs7->der; 04723 #endif 04724 contentDynamic = pkcs7->contentDynamic; 04725 version = pkcs7->version; 04726 04727 04728 if (ret == 0) { 04729 #ifndef NO_PKCS7_STREAM 04730 PKCS7State* stream = pkcs7->stream; 04731 #endif 04732 /* This will reset PKCS7 structure and then set the 04733 * certificate */ 04734 ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); 04735 #ifndef NO_PKCS7_STREAM 04736 pkcs7->stream = stream; 04737 #endif 04738 } 04739 pkcs7->contentDynamic = contentDynamic; 04740 pkcs7->version = version; 04741 #ifdef ASN_BER_TO_DER 04742 pkcs7->der = der; 04743 #endif 04744 if (ret != 0) 04745 break; 04746 04747 /* iterate through any additional certificates */ 04748 if (ret == 0 && MAX_PKCS7_CERTS > 0) { 04749 int sz = 0; 04750 int i; 04751 04752 pkcs7->cert[0] = cert; 04753 pkcs7->certSz[0] = certSz; 04754 certIdx = idx + certSz; 04755 04756 for (i = 1; i < MAX_PKCS7_CERTS && 04757 certIdx + 1 < pkiMsg2Sz && 04758 certIdx + 1 < (word32)length; i++) { 04759 localIdx = certIdx; 04760 04761 if (ret == 0 && GetASNTag(pkiMsg2, &certIdx, &tag, 04762 pkiMsg2Sz) < 0) { 04763 ret = ASN_PARSE_E; 04764 break; 04765 } 04766 04767 if (ret == 0 && 04768 tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 04769 if (GetLength(pkiMsg2, &certIdx, &sz, 04770 pkiMsg2Sz) < 0) { 04771 ret = ASN_PARSE_E; 04772 break; 04773 } 04774 04775 pkcs7->cert[i] = &pkiMsg2[localIdx]; 04776 pkcs7->certSz[i] = sz + (certIdx - localIdx); 04777 certIdx += sz; 04778 } 04779 } 04780 } 04781 } 04782 idx += length; 04783 04784 if (!detached) { 04785 /* set content and size after init of PKCS7 structure */ 04786 pkcs7->content = content; 04787 pkcs7->contentSz = contentSz; 04788 } 04789 #ifndef NO_PKCS7_STREAM 04790 else { 04791 /* save content if detached and using streaming API */ 04792 if (pkcs7->content != NULL) { 04793 XFREE(pkcs7->stream->content, pkcs7->heap, 04794 DYNAMIC_TYPE_PKCS7); 04795 pkcs7->stream->content = (byte*)XMALLOC(pkcs7->contentSz, 04796 pkcs7->heap, 04797 DYNAMIC_TYPE_PKCS7); 04798 if (pkcs7->stream->content == NULL) { 04799 ret = MEMORY_E; 04800 break; 04801 } 04802 else { 04803 XMEMCPY(pkcs7->stream->content, pkcs7->content, 04804 contentSz); 04805 pkcs7->stream->contentSz = pkcs7->contentSz; 04806 } 04807 } 04808 } 04809 #endif 04810 04811 if (ret != 0) { 04812 break; 04813 } 04814 #ifndef NO_PKCS7_STREAM 04815 /* factor in that recent idx was in cert buffer. If in2 buffer was 04816 * used then don't advance idx. */ 04817 if (length > 0 && pkcs7->stream->flagOne && 04818 pkcs7->stream->length == 0) { 04819 idx = stateIdx + idx; 04820 if (idx > inSz) { 04821 /* index is more than input size */ 04822 ret = BUFFER_E; 04823 break; 04824 } 04825 } 04826 else { 04827 stateIdx = idx; /* didn't read any from internal buffer */ 04828 } 04829 04830 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { 04831 break; 04832 } 04833 if (pkcs7->stream->flagOne && pkcs7->stream->length > 0) { 04834 idx = stateIdx + idx; 04835 } 04836 04837 pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + 04838 MAX_SET_SZ; 04839 04840 if (pkcs7->stream->expected > (pkcs7->stream->maxLen - 04841 pkcs7->stream->totalRd) + pkcs7->stream->length) 04842 pkcs7->stream->expected = (pkcs7->stream->maxLen - 04843 pkcs7->stream->totalRd) + pkcs7->stream->length; 04844 04845 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0); 04846 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); 04847 #endif 04848 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); 04849 FALL_THROUGH; 04850 04851 case WC_PKCS7_VERIFY_STAGE5: 04852 #ifndef NO_PKCS7_STREAM 04853 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, 04854 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 04855 break; 04856 } 04857 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); 04858 if (pkcs7->stream->flagOne) { 04859 pkiMsg2 = pkiMsg; 04860 } 04861 04862 /* restore content type */ 04863 contentType = pkcs7->stream->nonce; 04864 contentTypeSz = pkcs7->stream->nonceSz; 04865 04866 maxIdx = idx + pkcs7->stream->expected; 04867 if (maxIdx > pkiMsg2Sz) { 04868 ret = BUFFER_E; 04869 break; 04870 } 04871 stateIdx = idx; 04872 #endif 04873 04874 /* set contentType and size after init of PKCS7 structure */ 04875 if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType, 04876 contentTypeSz) < 0) 04877 ret = ASN_PARSE_E; 04878 04879 /* Get the implicit[1] set of crls */ 04880 if (ret == 0 && idx >= maxIdx) 04881 ret = BUFFER_E; 04882 04883 localIdx = idx; 04884 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 04885 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 04886 idx++; 04887 if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) 04888 ret = ASN_PARSE_E; 04889 04890 /* Skip the set */ 04891 idx += length; 04892 } 04893 04894 /* Get the set of signerInfos */ 04895 if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx, 04896 NO_USER_CHECK) < 0) 04897 ret = ASN_PARSE_E; 04898 04899 if (ret != 0) 04900 break; 04901 #ifndef NO_PKCS7_STREAM 04902 if (!pkcs7->stream->flagOne) { 04903 stateIdx = idx; /* didn't read any from internal buffer */ 04904 } 04905 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { 04906 break; 04907 } 04908 wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); 04909 04910 if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { 04911 if (length > 0) { 04912 pkcs7->stream->expected = length; 04913 } 04914 else { 04915 pkcs7->stream->expected = 0; 04916 } 04917 } 04918 else { 04919 /* last state expect the reset of the buffer */ 04920 pkcs7->stream->expected = (pkcs7->stream->maxLen - 04921 pkcs7->stream->totalRd) + pkcs7->stream->length; 04922 } 04923 04924 #endif 04925 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); 04926 FALL_THROUGH; 04927 04928 case WC_PKCS7_VERIFY_STAGE6: 04929 #ifndef NO_PKCS7_STREAM 04930 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, 04931 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 04932 break; 04933 } 04934 04935 wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); 04936 if (pkcs7->stream->flagOne) { 04937 pkiMsg2 = pkiMsg; 04938 } 04939 04940 /* restore content */ 04941 content = pkcs7->stream->content; 04942 contentSz = pkcs7->stream->contentSz; 04943 #endif 04944 04945 ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx, 04946 degenerate, &signedAttrib, &signedAttribSz); 04947 04948 /* parse out the signature if present and verify it */ 04949 if (ret == 0 && length > 0 && degenerate == 0) { 04950 WOLFSSL_MSG("Parsing signature and verifying"); 04951 if (idx >= pkiMsg2Sz) 04952 ret = BUFFER_E; 04953 04954 /* Get the signature */ 04955 localIdx = idx; 04956 if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, 04957 pkiMsg2Sz) == 0 && tag == ASN_OCTET_STRING) { 04958 idx++; 04959 04960 if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) 04961 ret = ASN_PARSE_E; 04962 04963 /* save pointer and length */ 04964 sig = &pkiMsg2[idx]; 04965 sigSz = length; 04966 04967 idx += length; 04968 } 04969 04970 pkcs7->content = content; 04971 pkcs7->contentSz = contentSz; 04972 04973 if (ret == 0) { 04974 ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, 04975 signedAttrib, signedAttribSz, 04976 hashBuf, hashSz); 04977 } 04978 } 04979 04980 if (ret < 0) 04981 break; 04982 04983 ret = 0; /* success */ 04984 #ifndef NO_PKCS7_STREAM 04985 wc_PKCS7_ResetStream(pkcs7); 04986 #endif 04987 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 04988 break; 04989 04990 default: 04991 WOLFSSL_MSG("PKCS7 Unknown verify state"); 04992 ret = BAD_FUNC_ARG; 04993 } 04994 04995 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { 04996 #ifndef NO_PKCS7_STREAM 04997 wc_PKCS7_ResetStream(pkcs7); 04998 #endif 04999 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 05000 } 05001 return ret; 05002 } 05003 05004 05005 /* Gets a copy of the SID parsed from signerInfo. This can be called after 05006 * wc_PKCS7_VerifySignedData has been called. SID can be SKID in version 3 case 05007 * or issuerAndSerialNumber. 05008 * 05009 * return 0 on success and LENGTH_ONLY_E if just setting "outSz" for buffer 05010 * length needed. 05011 */ 05012 int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz) 05013 { 05014 if (outSz == NULL || pkcs7 == NULL) { 05015 return BAD_FUNC_ARG; 05016 } 05017 05018 if (pkcs7->signerInfo == NULL) { 05019 WOLFSSL_MSG("Either the bundle had no signers or" 05020 "wc_PKCS7_VerifySignedData needs called yet"); 05021 return PKCS7_NO_SIGNER_E; 05022 } 05023 05024 if (pkcs7->signerInfo->sidSz == 0) { 05025 WOLFSSL_MSG("Bundle had no signer SID set"); 05026 return PKCS7_NO_SIGNER_E; 05027 } 05028 05029 if (out == NULL) { 05030 *outSz = pkcs7->signerInfo->sidSz; 05031 return LENGTH_ONLY_E; 05032 } 05033 05034 if (*outSz < pkcs7->signerInfo->sidSz) { 05035 WOLFSSL_MSG("Buffer being passed in is not large enough for SKID"); 05036 return BUFFER_E; 05037 } 05038 XMEMCPY(out, pkcs7->signerInfo->sid, pkcs7->signerInfo->sidSz); 05039 *outSz = pkcs7->signerInfo->sidSz; 05040 return 0; 05041 } 05042 05043 05044 /* variant that allows computed data hash and header/foot, 05045 * which is useful for large data signing */ 05046 int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, 05047 word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, 05048 word32 pkiMsgFootSz) 05049 { 05050 return PKCS7_VerifySignedData(pkcs7, hashBuf, hashSz, 05051 pkiMsgHead, pkiMsgHeadSz, pkiMsgFoot, pkiMsgFootSz); 05052 } 05053 05054 int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) 05055 { 05056 return PKCS7_VerifySignedData(pkcs7, NULL, 0, pkiMsg, pkiMsgSz, NULL, 0); 05057 } 05058 05059 05060 /* Generate random content encryption key, store into pkcs7->cek and 05061 * pkcs7->cekSz. 05062 * 05063 * pkcs7 - pointer to initialized PKCS7 structure 05064 * len - length of key to be generated 05065 * 05066 * Returns 0 on success, negative upon error */ 05067 static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) 05068 { 05069 int ret; 05070 WC_RNG rng; 05071 byte* tmpKey; 05072 05073 if (pkcs7 == NULL || len == 0) 05074 return BAD_FUNC_ARG; 05075 05076 /* if key already exists, don't need to re-generate */ 05077 if (pkcs7->cek != NULL && pkcs7->cekSz != 0) { 05078 05079 /* if key exists, but is different size, return error */ 05080 if (pkcs7->cekSz != len) { 05081 WOLFSSL_MSG("Random content-encryption key size is inconsistent " 05082 "between CMS recipients"); 05083 return WC_KEY_SIZE_E; 05084 } 05085 05086 return 0; 05087 } 05088 05089 /* allocate space for cek */ 05090 tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05091 if (tmpKey == NULL) 05092 return MEMORY_E; 05093 05094 XMEMSET(tmpKey, 0, len); 05095 05096 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 05097 if (ret != 0) { 05098 XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05099 return ret; 05100 } 05101 05102 ret = wc_RNG_GenerateBlock(&rng, tmpKey, len); 05103 if (ret != 0) { 05104 wc_FreeRng(&rng); 05105 XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05106 return ret; 05107 } 05108 05109 /* store into PKCS7, memory freed during final cleanup */ 05110 pkcs7->cek = tmpKey; 05111 pkcs7->cekSz = len; 05112 05113 wc_FreeRng(&rng); 05114 05115 return 0; 05116 } 05117 05118 05119 /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ 05120 static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, 05121 word32 kekSz, byte* out, word32 outSz, 05122 int keyWrapAlgo, int direction) 05123 { 05124 int ret = 0; 05125 05126 if (cek == NULL || kek == NULL || out == NULL) 05127 return BAD_FUNC_ARG; 05128 05129 switch (keyWrapAlgo) { 05130 #ifndef NO_AES 05131 #ifdef WOLFSSL_AES_128 05132 case AES128_WRAP: 05133 #endif 05134 #ifdef WOLFSSL_AES_192 05135 case AES192_WRAP: 05136 #endif 05137 #ifdef WOLFSSL_AES_256 05138 case AES256_WRAP: 05139 #endif 05140 05141 if (direction == AES_ENCRYPTION) { 05142 05143 ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz, 05144 out, outSz, NULL); 05145 05146 } else if (direction == AES_DECRYPTION) { 05147 05148 ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz, 05149 out, outSz, NULL); 05150 } else { 05151 WOLFSSL_MSG("Bad key un/wrap direction"); 05152 return BAD_FUNC_ARG; 05153 } 05154 05155 if (ret <= 0) 05156 return ret; 05157 break; 05158 #endif /* NO_AES */ 05159 05160 default: 05161 WOLFSSL_MSG("Unsupported key wrap algorithm"); 05162 return BAD_KEYWRAP_ALG_E; 05163 }; 05164 05165 (void)cekSz; 05166 (void)kekSz; 05167 (void)outSz; 05168 (void)direction; 05169 return ret; 05170 } 05171 05172 05173 #ifdef HAVE_ECC 05174 05175 /* KARI == KeyAgreeRecipientInfo (key agreement) */ 05176 typedef struct WC_PKCS7_KARI { 05177 DecodedCert* decoded; /* decoded recip cert */ 05178 void* heap; /* user heap, points to PKCS7->heap */ 05179 int devId; /* device ID for HW based private key */ 05180 ecc_key* recipKey; /* recip key (pub | priv) */ 05181 ecc_key* senderKey; /* sender key (pub | priv) */ 05182 byte* senderKeyExport; /* sender ephemeral key DER */ 05183 byte* kek; /* key encryption key */ 05184 byte* ukm; /* OPTIONAL user keying material */ 05185 byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ 05186 word32 senderKeyExportSz; /* size of sender ephemeral key DER */ 05187 word32 kekSz; /* size of key encryption key */ 05188 word32 ukmSz; /* size of user keying material */ 05189 word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ 05190 byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ 05191 byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ 05192 byte decodedInit : 1; /* indicates decoded was initialized */ 05193 byte recipKeyInit : 1; /* indicates recipKey was initialized */ 05194 byte senderKeyInit : 1; /* indicates senderKey was initialized */ 05195 } WC_PKCS7_KARI; 05196 05197 05198 /* allocate and create new WC_PKCS7_KARI struct, 05199 * returns struct pointer on success, NULL on failure */ 05200 static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) 05201 { 05202 WC_PKCS7_KARI* kari = NULL; 05203 05204 if (pkcs7 == NULL) 05205 return NULL; 05206 05207 kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap, 05208 DYNAMIC_TYPE_PKCS7); 05209 if (kari == NULL) { 05210 WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI"); 05211 return NULL; 05212 } 05213 05214 kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 05215 DYNAMIC_TYPE_PKCS7); 05216 if (kari->decoded == NULL) { 05217 WOLFSSL_MSG("Failed to allocate DecodedCert"); 05218 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05219 return NULL; 05220 } 05221 05222 kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 05223 DYNAMIC_TYPE_PKCS7); 05224 if (kari->recipKey == NULL) { 05225 WOLFSSL_MSG("Failed to allocate recipient ecc_key"); 05226 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05227 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05228 return NULL; 05229 } 05230 05231 kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 05232 DYNAMIC_TYPE_PKCS7); 05233 if (kari->senderKey == NULL) { 05234 WOLFSSL_MSG("Failed to allocate sender ecc_key"); 05235 XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05236 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05237 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05238 return NULL; 05239 } 05240 05241 kari->senderKeyExport = NULL; 05242 kari->senderKeyExportSz = 0; 05243 kari->kek = NULL; 05244 kari->kekSz = 0; 05245 kari->ukm = NULL; 05246 kari->ukmSz = 0; 05247 kari->ukmOwner = 0; 05248 kari->sharedInfo = NULL; 05249 kari->sharedInfoSz = 0; 05250 kari->direction = direction; 05251 kari->decodedInit = 0; 05252 kari->recipKeyInit = 0; 05253 kari->senderKeyInit = 0; 05254 05255 kari->heap = pkcs7->heap; 05256 kari->devId = pkcs7->devId; 05257 05258 return kari; 05259 } 05260 05261 05262 /* free WC_PKCS7_KARI struct, return 0 on success */ 05263 static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) 05264 { 05265 void* heap; 05266 05267 if (kari) { 05268 heap = kari->heap; 05269 05270 if (kari->decoded) { 05271 if (kari->decodedInit) 05272 FreeDecodedCert(kari->decoded); 05273 XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); 05274 } 05275 if (kari->senderKey) { 05276 if (kari->senderKeyInit) 05277 wc_ecc_free(kari->senderKey); 05278 XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7); 05279 } 05280 if (kari->recipKey) { 05281 if (kari->recipKeyInit) 05282 wc_ecc_free(kari->recipKey); 05283 XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); 05284 } 05285 if (kari->senderKeyExport) { 05286 ForceZero(kari->senderKeyExport, kari->senderKeyExportSz); 05287 XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7); 05288 kari->senderKeyExportSz = 0; 05289 } 05290 if (kari->kek) { 05291 ForceZero(kari->kek, kari->kekSz); 05292 XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7); 05293 kari->kekSz = 0; 05294 } 05295 if (kari->ukm) { 05296 if (kari->ukmOwner == 1) { 05297 XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7); 05298 } 05299 kari->ukmSz = 0; 05300 } 05301 if (kari->sharedInfo) { 05302 ForceZero(kari->sharedInfo, kari->sharedInfoSz); 05303 XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7); 05304 kari->sharedInfoSz = 0; 05305 } 05306 XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); 05307 } 05308 05309 (void)heap; 05310 05311 return 0; 05312 } 05313 05314 05315 /* parse recipient cert/key, return 0 on success, negative on error 05316 * key/keySz only needed during decoding (WC_PKCS7_DECODE) */ 05317 static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, 05318 word32 certSz, const byte* key, 05319 word32 keySz) 05320 { 05321 int ret; 05322 word32 idx; 05323 05324 if (kari == NULL || kari->decoded == NULL || 05325 cert == NULL || certSz == 0) 05326 return BAD_FUNC_ARG; 05327 05328 /* decode certificate */ 05329 InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap); 05330 kari->decodedInit = 1; 05331 ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0); 05332 if (ret < 0) 05333 return ret; 05334 05335 /* only supports ECDSA for now */ 05336 if (kari->decoded->keyOID != ECDSAk) { 05337 WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); 05338 return BAD_FUNC_ARG; 05339 } 05340 05341 /* make sure subject key id was read from cert */ 05342 if (kari->decoded->extSubjKeyIdSet == 0) { 05343 WOLFSSL_MSG("Failed to read subject key ID from recipient cert"); 05344 return BAD_FUNC_ARG; 05345 } 05346 05347 ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId); 05348 if (ret != 0) 05349 return ret; 05350 05351 kari->recipKeyInit = 1; 05352 05353 /* get recip public key */ 05354 if (kari->direction == WC_PKCS7_ENCODE) { 05355 05356 idx = 0; 05357 ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx, 05358 kari->recipKey, kari->decoded->pubKeySize); 05359 if (ret != 0) 05360 return ret; 05361 } 05362 /* get recip private key */ 05363 else if (kari->direction == WC_PKCS7_DECODE) { 05364 if (key != NULL && keySz > 0) { 05365 idx = 0; 05366 ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); 05367 } 05368 else if (kari->devId == INVALID_DEVID) { 05369 ret = BAD_FUNC_ARG; 05370 } 05371 if (ret != 0) 05372 return ret; 05373 05374 } else { 05375 /* bad direction */ 05376 return BAD_FUNC_ARG; 05377 } 05378 05379 (void)idx; 05380 05381 return 0; 05382 } 05383 05384 05385 /* create ephemeral ECC key, places ecc_key in kari->senderKey, 05386 * DER encoded in kari->senderKeyExport. return 0 on success, 05387 * negative on error */ 05388 static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari) 05389 { 05390 int ret; 05391 WC_RNG rng; 05392 05393 if (kari == NULL || kari->decoded == NULL || 05394 kari->recipKey == NULL || kari->recipKey->dp == NULL) 05395 return BAD_FUNC_ARG; 05396 05397 kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize, 05398 kari->heap, DYNAMIC_TYPE_PKCS7); 05399 if (kari->senderKeyExport == NULL) 05400 return MEMORY_E; 05401 05402 kari->senderKeyExportSz = kari->decoded->pubKeySize; 05403 05404 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); 05405 if (ret != 0) { 05406 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); 05407 return ret; 05408 } 05409 05410 kari->senderKeyInit = 1; 05411 05412 ret = wc_InitRng_ex(&rng, kari->heap, kari->devId); 05413 if (ret != 0) { 05414 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); 05415 return ret; 05416 } 05417 05418 ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size, 05419 kari->senderKey, kari->recipKey->dp->id); 05420 if (ret != 0) { 05421 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); 05422 wc_FreeRng(&rng); 05423 return ret; 05424 } 05425 05426 wc_FreeRng(&rng); 05427 05428 /* dump generated key to X.963 DER for output in CMS bundle */ 05429 ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport, 05430 &kari->senderKeyExportSz); 05431 if (ret != 0) { 05432 XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); 05433 return ret; 05434 } 05435 05436 return 0; 05437 } 05438 05439 05440 /* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm, 05441 * place in kari->sharedInfo. returns 0 on success, negative on error */ 05442 static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) 05443 { 05444 int idx = 0; 05445 int sharedInfoSeqSz = 0; 05446 int keyInfoSz = 0; 05447 int suppPubInfoSeqSz = 0; 05448 int entityUInfoOctetSz = 0; 05449 int entityUInfoExplicitSz = 0; 05450 int kekOctetSz = 0; 05451 int sharedInfoSz = 0; 05452 05453 word32 kekBitSz = 0; 05454 05455 byte sharedInfoSeq[MAX_SEQ_SZ]; 05456 byte keyInfo[MAX_ALGO_SZ]; 05457 byte suppPubInfoSeq[MAX_SEQ_SZ]; 05458 byte entityUInfoOctet[MAX_OCTET_STR_SZ]; 05459 byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; 05460 byte kekOctet[MAX_OCTET_STR_SZ]; 05461 05462 if (kari == NULL) 05463 return BAD_FUNC_ARG; 05464 05465 if ((kari->ukmSz > 0) && (kari->ukm == NULL)) 05466 return BAD_FUNC_ARG; 05467 05468 /* kekOctet */ 05469 kekOctetSz = SetOctetString(sizeof(word32), kekOctet); 05470 sharedInfoSz += (kekOctetSz + sizeof(word32)); 05471 05472 /* suppPubInfo */ 05473 suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2, 05474 kekOctetSz + sizeof(word32), 05475 suppPubInfoSeq); 05476 sharedInfoSz += suppPubInfoSeqSz; 05477 05478 /* optional ukm/entityInfo */ 05479 if (kari->ukmSz > 0) { 05480 entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); 05481 sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); 05482 05483 entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + 05484 kari->ukmSz, 05485 entityUInfoExplicitSeq); 05486 sharedInfoSz += entityUInfoExplicitSz; 05487 } 05488 05489 /* keyInfo */ 05490 keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); 05491 sharedInfoSz += keyInfoSz; 05492 05493 /* sharedInfo */ 05494 sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq); 05495 sharedInfoSz += sharedInfoSeqSz; 05496 05497 kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap, 05498 DYNAMIC_TYPE_PKCS7); 05499 if (kari->sharedInfo == NULL) 05500 return MEMORY_E; 05501 05502 kari->sharedInfoSz = sharedInfoSz; 05503 05504 XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz); 05505 idx += sharedInfoSeqSz; 05506 XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); 05507 idx += keyInfoSz; 05508 if (kari->ukmSz > 0) { 05509 XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, 05510 entityUInfoExplicitSz); 05511 idx += entityUInfoExplicitSz; 05512 XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); 05513 idx += entityUInfoOctetSz; 05514 XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); 05515 idx += kari->ukmSz; 05516 } 05517 XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz); 05518 idx += suppPubInfoSeqSz; 05519 XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz); 05520 idx += kekOctetSz; 05521 05522 kekBitSz = (kari->kekSz) * 8; /* convert to bits */ 05523 #ifdef LITTLE_ENDIAN_ORDER 05524 kekBitSz = ByteReverseWord32(kekBitSz); /* network byte order */ 05525 #endif 05526 XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz)); 05527 05528 return 0; 05529 } 05530 05531 05532 /* create key encryption key (KEK) using key wrap algorithm and key encryption 05533 * algorithm, place in kari->kek. return 0 on success, <0 on error. */ 05534 static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, 05535 int keyWrapOID, int keyEncOID) 05536 { 05537 int ret; 05538 int kSz; 05539 enum wc_HashType kdfType; 05540 byte* secret; 05541 word32 secretSz; 05542 05543 if (kari == NULL || kari->recipKey == NULL || 05544 kari->senderKey == NULL || kari->senderKey->dp == NULL) 05545 return BAD_FUNC_ARG; 05546 05547 /* get KEK size, allocate buff */ 05548 kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID); 05549 if (kSz < 0) 05550 return kSz; 05551 05552 kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7); 05553 if (kari->kek == NULL) 05554 return MEMORY_E; 05555 05556 kari->kekSz = (word32)kSz; 05557 05558 /* generate ECC-CMS-SharedInfo */ 05559 ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID); 05560 if (ret != 0) 05561 return ret; 05562 05563 /* generate shared secret */ 05564 secretSz = kari->senderKey->dp->size; 05565 secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7); 05566 if (secret == NULL) 05567 return MEMORY_E; 05568 05569 if (kari->direction == WC_PKCS7_ENCODE) { 05570 05571 ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey, 05572 secret, &secretSz); 05573 05574 } else if (kari->direction == WC_PKCS7_DECODE) { 05575 05576 ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey, 05577 secret, &secretSz); 05578 05579 } else { 05580 /* bad direction */ 05581 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 05582 return BAD_FUNC_ARG; 05583 } 05584 05585 if (ret != 0) { 05586 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 05587 return ret; 05588 } 05589 05590 /* run through KDF */ 05591 switch (keyEncOID) { 05592 05593 #ifndef NO_SHA 05594 case dhSinglePass_stdDH_sha1kdf_scheme: 05595 kdfType = WC_HASH_TYPE_SHA; 05596 break; 05597 #endif 05598 #ifndef WOLFSSL_SHA224 05599 case dhSinglePass_stdDH_sha224kdf_scheme: 05600 kdfType = WC_HASH_TYPE_SHA224; 05601 break; 05602 #endif 05603 #ifndef NO_SHA256 05604 case dhSinglePass_stdDH_sha256kdf_scheme: 05605 kdfType = WC_HASH_TYPE_SHA256; 05606 break; 05607 #endif 05608 #ifdef WOLFSSL_SHA384 05609 case dhSinglePass_stdDH_sha384kdf_scheme: 05610 kdfType = WC_HASH_TYPE_SHA384; 05611 break; 05612 #endif 05613 #ifdef WOLFSSL_SHA512 05614 case dhSinglePass_stdDH_sha512kdf_scheme: 05615 kdfType = WC_HASH_TYPE_SHA512; 05616 break; 05617 #endif 05618 default: 05619 WOLFSSL_MSG("Unsupported key agreement algorithm"); 05620 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 05621 return BAD_FUNC_ARG; 05622 }; 05623 05624 ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo, 05625 kari->sharedInfoSz, kari->kek, kari->kekSz); 05626 if (ret != 0) { 05627 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 05628 return ret; 05629 } 05630 05631 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 05632 05633 return 0; 05634 } 05635 05636 05637 /* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo 05638 * to CMS/PKCS#7 EnvelopedData structure. 05639 * 05640 * Returns 0 on success, negative upon error */ 05641 int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, 05642 int keyWrapOID, int keyAgreeOID, byte* ukm, 05643 word32 ukmSz, int options) 05644 { 05645 Pkcs7EncodedRecip* recip; 05646 Pkcs7EncodedRecip* lastRecip = NULL; 05647 WC_PKCS7_KARI* kari = NULL; 05648 05649 word32 idx = 0; 05650 word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 05651 05652 int ret = 0; 05653 int keySz, direction = 0; 05654 int blockKeySz = 0; 05655 05656 /* ASN.1 layout */ 05657 int totalSz = 0; 05658 int kariSeqSz = 0; 05659 byte kariSeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ 05660 int verSz = 0; 05661 byte ver[MAX_VERSION_SZ]; 05662 05663 int origIdOrKeySeqSz = 0; 05664 byte origIdOrKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ 05665 int origPubKeySeqSz = 0; 05666 byte origPubKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ 05667 int origAlgIdSz = 0; 05668 byte origAlgId[MAX_ALGO_SZ]; 05669 int origPubKeyStrSz = 0; 05670 byte origPubKeyStr[MAX_OCTET_STR_SZ]; 05671 05672 /* optional user keying material */ 05673 int ukmOctetSz = 0; 05674 byte ukmOctetStr[MAX_OCTET_STR_SZ]; 05675 int ukmExplicitSz = 0; 05676 byte ukmExplicitSeq[MAX_SEQ_SZ]; 05677 05678 int keyEncryptAlgoIdSz = 0; 05679 byte keyEncryptAlgoId[MAX_ALGO_SZ]; 05680 int keyWrapAlgSz = 0; 05681 byte keyWrapAlg[MAX_ALGO_SZ]; 05682 05683 int recipEncKeysSeqSz = 0; 05684 byte recipEncKeysSeq[MAX_SEQ_SZ]; 05685 int recipEncKeySeqSz = 0; 05686 byte recipEncKeySeq[MAX_SEQ_SZ]; 05687 int recipKeyIdSeqSz = 0; 05688 byte recipKeyIdSeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ 05689 int subjKeyIdOctetSz = 0; 05690 byte subjKeyIdOctet[MAX_OCTET_STR_SZ]; 05691 int encryptedKeyOctetSz = 0; 05692 byte encryptedKeyOctet[MAX_OCTET_STR_SZ]; 05693 05694 #ifdef WOLFSSL_SMALL_STACK 05695 byte* encryptedKey; 05696 05697 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 05698 DYNAMIC_TYPE_TMP_BUFFER); 05699 if (encryptedKey == NULL) { 05700 return MEMORY_E; 05701 } 05702 #else 05703 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 05704 #endif 05705 05706 /* allocate and init memory for recipient */ 05707 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, 05708 DYNAMIC_TYPE_PKCS7); 05709 if (recip == NULL) { 05710 #ifdef WOLFSSL_SMALL_STACK 05711 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05712 #endif 05713 return MEMORY_E; 05714 } 05715 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); 05716 05717 /* get key size for content-encryption key based on algorithm */ 05718 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 05719 if (blockKeySz < 0) { 05720 #ifdef WOLFSSL_SMALL_STACK 05721 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05722 #endif 05723 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05724 return blockKeySz; 05725 } 05726 05727 /* generate random content encryption key, if needed */ 05728 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 05729 if (ret < 0) { 05730 #ifdef WOLFSSL_SMALL_STACK 05731 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05732 #endif 05733 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05734 return ret; 05735 } 05736 05737 /* set direction based on keyWrapAlgo */ 05738 switch (keyWrapOID) { 05739 #ifndef NO_AES 05740 #ifdef WOLFSSL_AES_128 05741 case AES128_WRAP: 05742 #endif 05743 #ifdef WOLFSSL_AES_192 05744 case AES192_WRAP: 05745 #endif 05746 #ifdef WOLFSSL_AES_256 05747 case AES256_WRAP: 05748 #endif 05749 direction = AES_ENCRYPTION; 05750 break; 05751 #endif 05752 default: 05753 WOLFSSL_MSG("Unsupported key wrap algorithm"); 05754 #ifdef WOLFSSL_SMALL_STACK 05755 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05756 #endif 05757 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05758 return BAD_KEYWRAP_ALG_E; 05759 } 05760 05761 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE); 05762 if (kari == NULL) { 05763 #ifdef WOLFSSL_SMALL_STACK 05764 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05765 #endif 05766 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05767 return MEMORY_E; 05768 } 05769 05770 /* set user keying material if available */ 05771 if (ukmSz > 0 && ukm != NULL) { 05772 kari->ukm = ukm; 05773 kari->ukmSz = ukmSz; 05774 kari->ukmOwner = 0; 05775 } 05776 05777 /* parse recipient cert, get public key */ 05778 ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0); 05779 if (ret != 0) { 05780 wc_PKCS7_KariFree(kari); 05781 #ifdef WOLFSSL_SMALL_STACK 05782 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05783 #endif 05784 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05785 return ret; 05786 } 05787 05788 /* generate sender ephemeral ECC key */ 05789 ret = wc_PKCS7_KariGenerateEphemeralKey(kari); 05790 if (ret != 0) { 05791 wc_PKCS7_KariFree(kari); 05792 #ifdef WOLFSSL_SMALL_STACK 05793 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05794 #endif 05795 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05796 return ret; 05797 } 05798 05799 /* generate KEK (key encryption key) */ 05800 ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, keyAgreeOID); 05801 if (ret != 0) { 05802 wc_PKCS7_KariFree(kari); 05803 #ifdef WOLFSSL_SMALL_STACK 05804 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05805 #endif 05806 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05807 return ret; 05808 } 05809 05810 /* encrypt CEK with KEK */ 05811 keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek, 05812 kari->kekSz, encryptedKey, encryptedKeySz, 05813 keyWrapOID, direction); 05814 if (keySz <= 0) { 05815 wc_PKCS7_KariFree(kari); 05816 #ifdef WOLFSSL_SMALL_STACK 05817 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05818 #endif 05819 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05820 return keySz; 05821 } 05822 encryptedKeySz = (word32)keySz; 05823 05824 /* Start of RecipientEncryptedKeys */ 05825 05826 /* EncryptedKey */ 05827 encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet); 05828 totalSz += (encryptedKeyOctetSz + encryptedKeySz); 05829 05830 /* SubjectKeyIdentifier */ 05831 subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet); 05832 totalSz += (subjKeyIdOctetSz + KEYID_SIZE); 05833 05834 /* RecipientKeyIdentifier IMPLICIT [0] */ 05835 recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz + 05836 KEYID_SIZE, recipKeyIdSeq); 05837 totalSz += recipKeyIdSeqSz; 05838 05839 /* RecipientEncryptedKey */ 05840 recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq); 05841 totalSz += recipEncKeySeqSz; 05842 05843 /* RecipientEncryptedKeys */ 05844 recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq); 05845 totalSz += recipEncKeysSeqSz; 05846 05847 /* Start of optional UserKeyingMaterial */ 05848 05849 if (kari->ukmSz > 0) { 05850 ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr); 05851 totalSz += (ukmOctetSz + kari->ukmSz); 05852 05853 ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz, 05854 ukmExplicitSeq); 05855 totalSz += ukmExplicitSz; 05856 } 05857 05858 /* Start of KeyEncryptionAlgorithmIdentifier */ 05859 05860 /* KeyWrapAlgorithm */ 05861 keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); 05862 totalSz += keyWrapAlgSz; 05863 05864 /* KeyEncryptionAlgorithmIdentifier */ 05865 keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId, 05866 oidCmsKeyAgreeType, keyWrapAlgSz); 05867 totalSz += keyEncryptAlgoIdSz; 05868 05869 /* Start of OriginatorIdentifierOrKey */ 05870 05871 /* recipient ECPoint, public key */ 05872 XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */ 05873 origPubKeyStr[0] = ASN_BIT_STRING; 05874 origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1, 05875 origPubKeyStr + 1) + 2; 05876 totalSz += (origPubKeyStrSz + kari->senderKeyExportSz); 05877 05878 /* Originator AlgorithmIdentifier, params set to NULL for interop 05879 compatibility */ 05880 origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2); 05881 origAlgId[origAlgIdSz++] = ASN_TAG_NULL; 05882 origAlgId[origAlgIdSz++] = 0; 05883 totalSz += origAlgIdSz; 05884 05885 /* outer OriginatorPublicKey IMPLICIT [1] */ 05886 origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1, 05887 origAlgIdSz + origPubKeyStrSz + 05888 kari->senderKeyExportSz, origPubKeySeq); 05889 totalSz += origPubKeySeqSz; 05890 05891 /* outer OriginatorIdentiferOrKey IMPLICIT [0] */ 05892 origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0, 05893 origPubKeySeqSz + origAlgIdSz + 05894 origPubKeyStrSz + kari->senderKeyExportSz, 05895 origIdOrKeySeq); 05896 totalSz += origIdOrKeySeqSz; 05897 05898 /* version, always 3 */ 05899 verSz = SetMyVersion(3, ver, 0); 05900 totalSz += verSz; 05901 recip->recipVersion = 3; 05902 05903 /* outer IMPLICIT [1] kari */ 05904 kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); 05905 totalSz += kariSeqSz; 05906 05907 if (totalSz > MAX_RECIP_SZ) { 05908 WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small"); 05909 wc_PKCS7_KariFree(kari); 05910 #ifdef WOLFSSL_SMALL_STACK 05911 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05912 #endif 05913 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05914 return BUFFER_E; 05915 } 05916 05917 XMEMCPY(recip->recip + idx, kariSeq, kariSeqSz); 05918 idx += kariSeqSz; 05919 XMEMCPY(recip->recip + idx, ver, verSz); 05920 idx += verSz; 05921 05922 XMEMCPY(recip->recip + idx, origIdOrKeySeq, origIdOrKeySeqSz); 05923 idx += origIdOrKeySeqSz; 05924 XMEMCPY(recip->recip + idx, origPubKeySeq, origPubKeySeqSz); 05925 idx += origPubKeySeqSz; 05926 05927 /* AlgorithmIdentifier with NULL parameter */ 05928 XMEMCPY(recip->recip + idx, origAlgId, origAlgIdSz); 05929 idx += origAlgIdSz; 05930 05931 XMEMCPY(recip->recip + idx, origPubKeyStr, origPubKeyStrSz); 05932 idx += origPubKeyStrSz; 05933 /* ephemeral public key */ 05934 XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz); 05935 idx += kari->senderKeyExportSz; 05936 05937 if (kari->ukmSz > 0) { 05938 XMEMCPY(recip->recip + idx, ukmExplicitSeq, ukmExplicitSz); 05939 idx += ukmExplicitSz; 05940 XMEMCPY(recip->recip + idx, ukmOctetStr, ukmOctetSz); 05941 idx += ukmOctetSz; 05942 XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz); 05943 idx += kari->ukmSz; 05944 } 05945 05946 XMEMCPY(recip->recip + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); 05947 idx += keyEncryptAlgoIdSz; 05948 XMEMCPY(recip->recip + idx, keyWrapAlg, keyWrapAlgSz); 05949 idx += keyWrapAlgSz; 05950 05951 XMEMCPY(recip->recip + idx, recipEncKeysSeq, recipEncKeysSeqSz); 05952 idx += recipEncKeysSeqSz; 05953 XMEMCPY(recip->recip + idx, recipEncKeySeq, recipEncKeySeqSz); 05954 idx += recipEncKeySeqSz; 05955 XMEMCPY(recip->recip + idx, recipKeyIdSeq, recipKeyIdSeqSz); 05956 idx += recipKeyIdSeqSz; 05957 XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz); 05958 idx += subjKeyIdOctetSz; 05959 /* subject key id */ 05960 XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); 05961 idx += KEYID_SIZE; 05962 XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz); 05963 idx += encryptedKeyOctetSz; 05964 /* encrypted CEK */ 05965 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); 05966 idx += encryptedKeySz; 05967 05968 wc_PKCS7_KariFree(kari); 05969 #ifdef WOLFSSL_SMALL_STACK 05970 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 05971 #endif 05972 05973 /* store recipient size */ 05974 recip->recipSz = idx; 05975 recip->recipType = PKCS7_KARI; 05976 05977 /* add recipient to recip list */ 05978 if (pkcs7->recipList == NULL) { 05979 pkcs7->recipList = recip; 05980 } else { 05981 lastRecip = pkcs7->recipList; 05982 while (lastRecip->next != NULL) { 05983 lastRecip = lastRecip->next; 05984 } 05985 lastRecip->next = recip; 05986 } 05987 05988 (void)options; 05989 05990 return idx; 05991 } 05992 05993 #endif /* HAVE_ECC */ 05994 05995 #ifndef NO_RSA 05996 05997 /* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo 05998 * to CMS/PKCS#7 EnvelopedData structure. 05999 * 06000 * Returns 0 on success, negative upon error */ 06001 int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, 06002 int options) 06003 { 06004 Pkcs7EncodedRecip* recip = NULL; 06005 Pkcs7EncodedRecip* lastRecip = NULL; 06006 06007 WC_RNG rng; 06008 word32 idx = 0; 06009 word32 encryptedKeySz = 0; 06010 06011 int ret = 0, blockKeySz; 06012 int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0; 06013 int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0; 06014 int encKeyOctetStrSz; 06015 int sidType; 06016 06017 byte ver[MAX_VERSION_SZ]; 06018 byte issuerSerialSeq[MAX_SEQ_SZ]; 06019 byte recipSeq[MAX_SEQ_SZ]; 06020 byte issuerSeq[MAX_SEQ_SZ]; 06021 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 06022 06023 byte issuerSKIDSeq[MAX_SEQ_SZ]; 06024 byte issuerSKID[MAX_OCTET_STR_SZ]; 06025 word32 issuerSKIDSeqSz = 0, issuerSKIDSz = 0; 06026 06027 #ifdef WOLFSSL_SMALL_STACK 06028 byte* serial; 06029 byte* keyAlgArray; 06030 byte* encryptedKey; 06031 RsaKey* pubKey; 06032 DecodedCert* decoded; 06033 06034 serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06035 keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, 06036 DYNAMIC_TYPE_TMP_BUFFER); 06037 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 06038 DYNAMIC_TYPE_TMP_BUFFER); 06039 decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 06040 DYNAMIC_TYPE_TMP_BUFFER); 06041 06042 if (decoded == NULL || serial == NULL || 06043 encryptedKey == NULL || keyAlgArray == NULL) { 06044 if (serial) 06045 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06046 if (keyAlgArray) 06047 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06048 if (encryptedKey) 06049 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06050 if (decoded) 06051 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06052 return MEMORY_E; 06053 } 06054 #else 06055 byte serial[MAX_SN_SZ]; 06056 byte keyAlgArray[MAX_ALGO_SZ]; 06057 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 06058 06059 RsaKey pubKey[1]; 06060 DecodedCert decoded[1]; 06061 #endif 06062 06063 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 06064 XMEMSET(encryptedKey, 0, encryptedKeySz); 06065 06066 /* default to IssuerAndSerialNumber if not set */ 06067 if (pkcs7->sidType != 0) { 06068 sidType = pkcs7->sidType; 06069 } else { 06070 sidType = CMS_ISSUER_AND_SERIAL_NUMBER; 06071 } 06072 06073 /* allow options to override SubjectIdentifier type if set */ 06074 if (options & CMS_SKID) { 06075 sidType = CMS_SKID; 06076 } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) { 06077 sidType = CMS_ISSUER_AND_SERIAL_NUMBER; 06078 } 06079 06080 /* allocate recipient struct */ 06081 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, 06082 DYNAMIC_TYPE_PKCS7); 06083 if (recip == NULL) { 06084 #ifdef WOLFSSL_SMALL_STACK 06085 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06086 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06087 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06088 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06089 #endif 06090 return MEMORY_E; 06091 } 06092 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); 06093 06094 /* get key size for content-encryption key based on algorithm */ 06095 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 06096 if (blockKeySz < 0) { 06097 #ifdef WOLFSSL_SMALL_STACK 06098 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06099 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06100 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06101 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06102 #endif 06103 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06104 return blockKeySz; 06105 } 06106 06107 /* generate random content encryption key, if needed */ 06108 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 06109 if (ret < 0) { 06110 #ifdef WOLFSSL_SMALL_STACK 06111 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06112 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06113 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06114 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06115 #endif 06116 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06117 return ret; 06118 } 06119 06120 InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap); 06121 ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); 06122 if (ret < 0) { 06123 FreeDecodedCert(decoded); 06124 #ifdef WOLFSSL_SMALL_STACK 06125 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06126 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06127 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06128 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06129 #endif 06130 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06131 return ret; 06132 } 06133 06134 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 06135 06136 /* version, must be 0 for IssuerAndSerialNumber */ 06137 verSz = SetMyVersion(0, ver, 0); 06138 recip->recipVersion = 0; 06139 06140 /* IssuerAndSerialNumber */ 06141 if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { 06142 WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); 06143 FreeDecodedCert(decoded); 06144 #ifdef WOLFSSL_SMALL_STACK 06145 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06146 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06147 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06148 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06149 #endif 06150 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06151 return -1; 06152 } 06153 issuerSz = decoded->issuerRawLen; 06154 issuerSeqSz = SetSequence(issuerSz, issuerSeq); 06155 06156 if (decoded->serialSz == 0) { 06157 WOLFSSL_MSG("DecodedCert missing serial number"); 06158 FreeDecodedCert(decoded); 06159 #ifdef WOLFSSL_SMALL_STACK 06160 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06161 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06162 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06163 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06164 #endif 06165 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06166 return -1; 06167 } 06168 snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, 06169 MAX_SN_SZ, MAX_SN_SZ); 06170 06171 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, 06172 issuerSerialSeq); 06173 06174 } else if (sidType == CMS_SKID) { 06175 06176 /* version, must be 2 for SubjectKeyIdentifier */ 06177 verSz = SetMyVersion(2, ver, 0); 06178 recip->recipVersion = 2; 06179 06180 issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID); 06181 issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE, 06182 issuerSKIDSeq); 06183 } else { 06184 FreeDecodedCert(decoded); 06185 #ifdef WOLFSSL_SMALL_STACK 06186 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06187 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06188 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06189 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06190 #endif 06191 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06192 return PKCS7_RECIP_E; 06193 } 06194 06195 pkcs7->publicKeyOID = decoded->keyOID; 06196 06197 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ 06198 if (pkcs7->publicKeyOID != RSAk) { 06199 FreeDecodedCert(decoded); 06200 #ifdef WOLFSSL_SMALL_STACK 06201 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06202 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06203 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06204 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06205 #endif 06206 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06207 return ALGO_ID_E; 06208 } 06209 06210 keyEncAlgSz = SetAlgoID(pkcs7->publicKeyOID, keyAlgArray, oidKeyType, 0); 06211 if (keyEncAlgSz == 0) { 06212 FreeDecodedCert(decoded); 06213 #ifdef WOLFSSL_SMALL_STACK 06214 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06215 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06216 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06217 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06218 #endif 06219 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06220 return BAD_FUNC_ARG; 06221 } 06222 06223 #ifdef WOLFSSL_SMALL_STACK 06224 pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, 06225 DYNAMIC_TYPE_TMP_BUFFER); 06226 if (pubKey == NULL) { 06227 FreeDecodedCert(decoded); 06228 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06229 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06230 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06231 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06232 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06233 return MEMORY_E; 06234 } 06235 #endif 06236 06237 /* EncryptedKey */ 06238 ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, INVALID_DEVID); 06239 if (ret != 0) { 06240 FreeDecodedCert(decoded); 06241 #ifdef WOLFSSL_SMALL_STACK 06242 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06243 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06244 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06245 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06246 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06247 #endif 06248 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06249 return ret; 06250 } 06251 06252 if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey, 06253 decoded->pubKeySize) < 0) { 06254 WOLFSSL_MSG("ASN RSA key decode error"); 06255 wc_FreeRsaKey(pubKey); 06256 FreeDecodedCert(decoded); 06257 #ifdef WOLFSSL_SMALL_STACK 06258 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06259 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06260 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06261 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06262 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06263 #endif 06264 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06265 return PUBLIC_KEY_E; 06266 } 06267 06268 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 06269 if (ret != 0) { 06270 wc_FreeRsaKey(pubKey); 06271 FreeDecodedCert(decoded); 06272 #ifdef WOLFSSL_SMALL_STACK 06273 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06274 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06275 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06276 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06277 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06278 #endif 06279 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06280 return MEMORY_E; 06281 } 06282 06283 06284 ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey, 06285 encryptedKeySz, pubKey, &rng); 06286 wc_FreeRsaKey(pubKey); 06287 wc_FreeRng(&rng); 06288 06289 #ifdef WOLFSSL_SMALL_STACK 06290 XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06291 #endif 06292 06293 if (ret < 0) { 06294 WOLFSSL_MSG("RSA Public Encrypt failed"); 06295 FreeDecodedCert(decoded); 06296 #ifdef WOLFSSL_SMALL_STACK 06297 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06298 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06299 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06300 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06301 #endif 06302 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06303 return ret; 06304 } 06305 encryptedKeySz = ret; 06306 06307 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); 06308 06309 /* RecipientInfo */ 06310 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 06311 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + 06312 issuerSz + snSz + keyEncAlgSz + 06313 encKeyOctetStrSz + encryptedKeySz, recipSeq); 06314 06315 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + 06316 keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { 06317 WOLFSSL_MSG("RecipientInfo output buffer too small"); 06318 FreeDecodedCert(decoded); 06319 #ifdef WOLFSSL_SMALL_STACK 06320 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06321 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06322 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06323 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06324 #endif 06325 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06326 return BUFFER_E; 06327 } 06328 06329 } else { 06330 recipSeqSz = SetSequence(verSz + issuerSKIDSeqSz + issuerSKIDSz + 06331 KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz + 06332 encryptedKeySz, recipSeq); 06333 06334 if (recipSeqSz + verSz + issuerSKIDSeqSz + issuerSKIDSz + KEYID_SIZE + 06335 keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { 06336 WOLFSSL_MSG("RecipientInfo output buffer too small"); 06337 FreeDecodedCert(decoded); 06338 #ifdef WOLFSSL_SMALL_STACK 06339 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06340 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06341 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06342 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06343 #endif 06344 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06345 return BUFFER_E; 06346 } 06347 } 06348 06349 idx = 0; 06350 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); 06351 idx += recipSeqSz; 06352 XMEMCPY(recip->recip + idx, ver, verSz); 06353 idx += verSz; 06354 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 06355 XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); 06356 idx += issuerSerialSeqSz; 06357 XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); 06358 idx += issuerSeqSz; 06359 XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); 06360 idx += issuerSz; 06361 XMEMCPY(recip->recip + idx, serial, snSz); 06362 idx += snSz; 06363 } else { 06364 XMEMCPY(recip->recip + idx, issuerSKIDSeq, issuerSKIDSeqSz); 06365 idx += issuerSKIDSeqSz; 06366 XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz); 06367 idx += issuerSKIDSz; 06368 XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); 06369 idx += KEYID_SIZE; 06370 } 06371 XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz); 06372 idx += keyEncAlgSz; 06373 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); 06374 idx += encKeyOctetStrSz; 06375 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); 06376 idx += encryptedKeySz; 06377 06378 FreeDecodedCert(decoded); 06379 06380 #ifdef WOLFSSL_SMALL_STACK 06381 XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06382 XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06383 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06384 XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 06385 #endif 06386 06387 /* store recipient size */ 06388 recip->recipSz = idx; 06389 recip->recipType = PKCS7_KTRI; 06390 06391 /* add recipient to recip list */ 06392 if (pkcs7->recipList == NULL) { 06393 pkcs7->recipList = recip; 06394 } else { 06395 lastRecip = pkcs7->recipList; 06396 while (lastRecip->next != NULL) { 06397 lastRecip = lastRecip->next; 06398 } 06399 lastRecip->next = recip; 06400 } 06401 06402 return idx; 06403 } 06404 06405 #endif /* !NO_RSA */ 06406 06407 06408 /* encrypt content using encryptOID algo */ 06409 static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, 06410 byte* iv, int ivSz, byte* aad, word32 aadSz, 06411 byte* authTag, word32 authTagSz, byte* in, 06412 int inSz, byte* out) 06413 { 06414 int ret; 06415 #ifndef NO_AES 06416 Aes aes; 06417 #endif 06418 #ifndef NO_DES3 06419 Des des; 06420 Des3 des3; 06421 #endif 06422 06423 if (key == NULL || iv == NULL || in == NULL || out == NULL) 06424 return BAD_FUNC_ARG; 06425 06426 switch (encryptOID) { 06427 #ifndef NO_AES 06428 #ifdef WOLFSSL_AES_128 06429 case AES128CBCb: 06430 #endif 06431 #ifdef WOLFSSL_AES_192 06432 case AES192CBCb: 06433 #endif 06434 #ifdef WOLFSSL_AES_256 06435 case AES256CBCb: 06436 #endif 06437 if ( 06438 #ifdef WOLFSSL_AES_128 06439 (encryptOID == AES128CBCb && keySz != 16 ) || 06440 #endif 06441 #ifdef WOLFSSL_AES_192 06442 (encryptOID == AES192CBCb && keySz != 24 ) || 06443 #endif 06444 #ifdef WOLFSSL_AES_256 06445 (encryptOID == AES256CBCb && keySz != 32 ) || 06446 #endif 06447 (ivSz != AES_BLOCK_SIZE) ) 06448 return BAD_FUNC_ARG; 06449 06450 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06451 if (ret == 0) { 06452 ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION); 06453 if (ret == 0) 06454 ret = wc_AesCbcEncrypt(&aes, out, in, inSz); 06455 wc_AesFree(&aes); 06456 } 06457 break; 06458 #ifdef HAVE_AESGCM 06459 #ifdef WOLFSSL_AES_128 06460 case AES128GCMb: 06461 #endif 06462 #ifdef WOLFSSL_AES_192 06463 case AES192GCMb: 06464 #endif 06465 #ifdef WOLFSSL_AES_256 06466 case AES256GCMb: 06467 #endif 06468 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 06469 defined(WOLFSSL_AES_256) 06470 if (authTag == NULL) 06471 return BAD_FUNC_ARG; 06472 06473 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06474 if (ret == 0) { 06475 ret = wc_AesGcmSetKey(&aes, key, keySz); 06476 if (ret == 0) 06477 ret = wc_AesGcmEncrypt(&aes, out, in, inSz, iv, ivSz, 06478 authTag, authTagSz, aad, aadSz); 06479 wc_AesFree(&aes); 06480 } 06481 break; 06482 #endif 06483 #endif /* HAVE_AESGCM */ 06484 #ifdef HAVE_AESCCM 06485 #ifdef WOLFSSL_AES_128 06486 case AES128CCMb: 06487 #endif 06488 #ifdef WOLFSSL_AES_192 06489 case AES192CCMb: 06490 #endif 06491 #ifdef WOLFSSL_AES_256 06492 case AES256CCMb: 06493 #endif 06494 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 06495 defined(WOLFSSL_AES_256) 06496 if (authTag == NULL) 06497 return BAD_FUNC_ARG; 06498 06499 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06500 if (ret == 0) { 06501 ret = wc_AesCcmSetKey(&aes, key, keySz); 06502 if (ret == 0) 06503 ret = wc_AesCcmEncrypt(&aes, out, in, inSz, iv, ivSz, 06504 authTag, authTagSz, aad, aadSz); 06505 wc_AesFree(&aes); 06506 } 06507 break; 06508 #endif 06509 #endif /* HAVE_AESCCM */ 06510 #endif /* NO_AES */ 06511 #ifndef NO_DES3 06512 case DESb: 06513 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) 06514 return BAD_FUNC_ARG; 06515 06516 ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); 06517 if (ret == 0) 06518 ret = wc_Des_CbcEncrypt(&des, out, in, inSz); 06519 06520 break; 06521 06522 case DES3b: 06523 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) 06524 return BAD_FUNC_ARG; 06525 06526 ret = wc_Des3Init(&des3, NULL, INVALID_DEVID); 06527 if (ret == 0) { 06528 ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION); 06529 if (ret == 0) 06530 ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz); 06531 wc_Des3Free(&des3); 06532 } 06533 break; 06534 #endif 06535 default: 06536 WOLFSSL_MSG("Unsupported content cipher type"); 06537 return ALGO_ID_E; 06538 }; 06539 06540 #if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) 06541 (void)authTag; 06542 (void)authTagSz; 06543 (void)aad; 06544 (void)aadSz; 06545 #endif 06546 return ret; 06547 } 06548 06549 06550 /* decrypt content using encryptOID algo 06551 * returns 0 on success */ 06552 static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, 06553 int keySz, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, 06554 word32 authTagSz, byte* in, int inSz, byte* out) 06555 { 06556 int ret; 06557 #ifndef NO_AES 06558 Aes aes; 06559 #endif 06560 #ifndef NO_DES3 06561 Des des; 06562 Des3 des3; 06563 #endif 06564 06565 if (iv == NULL || in == NULL || out == NULL) 06566 return BAD_FUNC_ARG; 06567 06568 if (pkcs7->decryptionCb != NULL) { 06569 return pkcs7->decryptionCb(pkcs7, encryptOID, iv, ivSz, 06570 aad, aadSz, authTag, authTagSz, in, 06571 inSz, out, pkcs7->decryptionCtx); 06572 } 06573 06574 if (key == NULL) 06575 return BAD_FUNC_ARG; 06576 06577 switch (encryptOID) { 06578 #ifndef NO_AES 06579 #ifdef WOLFSSL_AES_128 06580 case AES128CBCb: 06581 #endif 06582 #ifdef WOLFSSL_AES_192 06583 case AES192CBCb: 06584 #endif 06585 #ifdef WOLFSSL_AES_256 06586 case AES256CBCb: 06587 #endif 06588 if ( 06589 #ifdef WOLFSSL_AES_128 06590 (encryptOID == AES128CBCb && keySz != 16 ) || 06591 #endif 06592 #ifdef WOLFSSL_AES_192 06593 (encryptOID == AES192CBCb && keySz != 24 ) || 06594 #endif 06595 #ifdef WOLFSSL_AES_256 06596 (encryptOID == AES256CBCb && keySz != 32 ) || 06597 #endif 06598 (ivSz != AES_BLOCK_SIZE) ) 06599 return BAD_FUNC_ARG; 06600 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06601 if (ret == 0) { 06602 ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION); 06603 if (ret == 0) 06604 ret = wc_AesCbcDecrypt(&aes, out, in, inSz); 06605 wc_AesFree(&aes); 06606 } 06607 break; 06608 #ifdef HAVE_AESGCM 06609 #ifdef WOLFSSL_AES_128 06610 case AES128GCMb: 06611 #endif 06612 #ifdef WOLFSSL_AES_192 06613 case AES192GCMb: 06614 #endif 06615 #ifdef WOLFSSL_AES_256 06616 case AES256GCMb: 06617 #endif 06618 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 06619 defined(WOLFSSL_AES_256) 06620 if (authTag == NULL) 06621 return BAD_FUNC_ARG; 06622 06623 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06624 if (ret == 0) { 06625 ret = wc_AesGcmSetKey(&aes, key, keySz); 06626 if (ret == 0) 06627 ret = wc_AesGcmDecrypt(&aes, out, in, inSz, iv, ivSz, 06628 authTag, authTagSz, aad, aadSz); 06629 wc_AesFree(&aes); 06630 } 06631 break; 06632 #endif 06633 #endif /* HAVE_AESGCM */ 06634 #ifdef HAVE_AESCCM 06635 #ifdef WOLFSSL_AES_128 06636 case AES128CCMb: 06637 #endif 06638 #ifdef WOLFSSL_AES_192 06639 case AES192CCMb: 06640 #endif 06641 #ifdef WOLFSSL_AES_256 06642 case AES256CCMb: 06643 #endif 06644 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 06645 defined(WOLFSSL_AES_256) 06646 if (authTag == NULL) 06647 return BAD_FUNC_ARG; 06648 06649 ret = wc_AesInit(&aes, NULL, INVALID_DEVID); 06650 if (ret == 0) { 06651 ret = wc_AesCcmSetKey(&aes, key, keySz); 06652 if (ret == 0) 06653 ret = wc_AesCcmDecrypt(&aes, out, in, inSz, iv, ivSz, 06654 authTag, authTagSz, aad, aadSz); 06655 wc_AesFree(&aes); 06656 } 06657 break; 06658 #endif 06659 #endif /* HAVE_AESCCM */ 06660 #endif /* NO_AES */ 06661 #ifndef NO_DES3 06662 case DESb: 06663 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) 06664 return BAD_FUNC_ARG; 06665 06666 ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION); 06667 if (ret == 0) 06668 ret = wc_Des_CbcDecrypt(&des, out, in, inSz); 06669 06670 break; 06671 case DES3b: 06672 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) 06673 return BAD_FUNC_ARG; 06674 06675 ret = wc_Des3Init(&des3, NULL, INVALID_DEVID); 06676 if (ret == 0) { 06677 ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION); 06678 if (ret == 0) 06679 ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz); 06680 wc_Des3Free(&des3); 06681 } 06682 06683 break; 06684 #endif 06685 default: 06686 WOLFSSL_MSG("Unsupported content cipher type"); 06687 return ALGO_ID_E; 06688 }; 06689 06690 #if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) 06691 (void)authTag; 06692 (void)authTagSz; 06693 (void)aad; 06694 (void)aadSz; 06695 #endif 06696 06697 return ret; 06698 } 06699 06700 06701 /* Generate random block, place in out, return 0 on success negative on error. 06702 * Used for generation of IV, nonce, etc */ 06703 static int wc_PKCS7_GenerateBlock(PKCS7* pkcs7, WC_RNG* rng, byte* out, 06704 word32 outSz) 06705 { 06706 int ret; 06707 WC_RNG* rnd = NULL; 06708 06709 if (out == NULL || outSz == 0) 06710 return BAD_FUNC_ARG; 06711 06712 /* input RNG is optional, init local one if input rng is NULL */ 06713 if (rng == NULL) { 06714 rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG); 06715 if (rnd == NULL) 06716 return MEMORY_E; 06717 06718 ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId); 06719 if (ret != 0) { 06720 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); 06721 return ret; 06722 } 06723 06724 } else { 06725 rnd = rng; 06726 } 06727 06728 ret = wc_RNG_GenerateBlock(rnd, out, outSz); 06729 06730 if (rng == NULL) { 06731 wc_FreeRng(rnd); 06732 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); 06733 } 06734 06735 return ret; 06736 } 06737 06738 06739 /* Set default SignerIdentifier type to be used. Is either 06740 * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using 06741 * IssuerAndSerialNumber unless set with this function or explicitly 06742 * overridden via options when adding RecipientInfo type. 06743 * 06744 * Using the type DEGENERATE_SID skips over signer information. In degenerate 06745 * cases there are no signers. 06746 * 06747 * pkcs7 - pointer to initialized PKCS7 structure 06748 * type - either CMS_ISSUER_AND_SERIAL_NUMBER, CMS_SKID or DEGENERATE_SID 06749 * 06750 * return 0 on success, negative upon error */ 06751 int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) 06752 { 06753 if (pkcs7 == NULL) 06754 return BAD_FUNC_ARG; 06755 06756 if (type != CMS_ISSUER_AND_SERIAL_NUMBER && 06757 type != CMS_SKID && 06758 type != DEGENERATE_SID) { 06759 return BAD_FUNC_ARG; 06760 } 06761 06762 pkcs7->sidType = type; 06763 06764 return 0; 06765 } 06766 06767 06768 /* Set custom contentType, currently supported with SignedData type 06769 * 06770 * pkcs7 - pointer to initialized PKCS7 structure 06771 * contentType - pointer to array with ASN.1 encoded OID value 06772 * sz - length of contentType array, octets 06773 * 06774 * return 0 on success, negative upon error */ 06775 int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz) 06776 { 06777 if (pkcs7 == NULL || contentType == NULL || sz == 0) 06778 return BAD_FUNC_ARG; 06779 06780 if (sz > MAX_OID_SZ) { 06781 WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ"); 06782 return BAD_FUNC_ARG; 06783 } 06784 06785 XMEMCPY(pkcs7->contentType, contentType, sz); 06786 pkcs7->contentTypeSz = sz; 06787 06788 return 0; 06789 } 06790 06791 06792 /* return size of padded data, padded to blockSz chunks, or negative on error */ 06793 int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) 06794 { 06795 int padSz; 06796 06797 if (blockSz == 0) 06798 return BAD_FUNC_ARG; 06799 06800 padSz = blockSz - (inputSz % blockSz); 06801 06802 return padSz; 06803 } 06804 06805 06806 /* pad input data to blockSz chunk, place in outSz. out must be big enough 06807 * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */ 06808 int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, 06809 word32 blockSz) 06810 { 06811 int i, padSz; 06812 06813 if (in == NULL || inSz == 0 || 06814 out == NULL || outSz == 0) 06815 return BAD_FUNC_ARG; 06816 06817 padSz = wc_PKCS7_GetPadSize(inSz, blockSz); 06818 06819 if (outSz < (inSz + padSz)) 06820 return BAD_FUNC_ARG; 06821 06822 XMEMCPY(out, in, inSz); 06823 06824 for (i = 0; i < padSz; i++) { 06825 out[inSz + i] = (byte)padSz; 06826 } 06827 06828 return inSz + padSz; 06829 } 06830 06831 06832 /* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo 06833 * to CMS/PKCS#7 EnvelopedData structure. 06834 * 06835 * Return 0 on success, negative upon error */ 06836 int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, 06837 int options) 06838 { 06839 int oriTypeLenSz, blockKeySz, ret; 06840 word32 idx, recipSeqSz; 06841 06842 Pkcs7EncodedRecip* recip = NULL; 06843 Pkcs7EncodedRecip* lastRecip = NULL; 06844 06845 byte recipSeq[MAX_SEQ_SZ]; 06846 byte oriTypeLen[MAX_LENGTH_SZ]; 06847 06848 byte oriType[MAX_ORI_TYPE_SZ]; 06849 byte oriValue[MAX_ORI_VALUE_SZ]; 06850 word32 oriTypeSz = MAX_ORI_TYPE_SZ; 06851 word32 oriValueSz = MAX_ORI_VALUE_SZ; 06852 06853 if (pkcs7 == NULL || oriEncryptCb == NULL) { 06854 return BAD_FUNC_ARG; 06855 } 06856 06857 /* allocate memory for RecipientInfo, KEK, encrypted key */ 06858 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), 06859 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06860 if (recip == NULL) 06861 return MEMORY_E; 06862 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); 06863 06864 /* get key size for content-encryption key based on algorithm */ 06865 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 06866 if (blockKeySz < 0) { 06867 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06868 return blockKeySz; 06869 } 06870 06871 /* generate random content encryption key, if needed */ 06872 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 06873 if (ret < 0) { 06874 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06875 return ret; 06876 } 06877 06878 /* call user callback to encrypt CEK and get oriType and oriValue 06879 values back */ 06880 ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz, 06881 oriValue, &oriValueSz, pkcs7->oriEncryptCtx); 06882 if (ret != 0) { 06883 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 06884 return ret; 06885 } 06886 06887 oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen); 06888 06889 recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz + 06890 oriValueSz, recipSeq); 06891 06892 idx = 0; 06893 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); 06894 idx += recipSeqSz; 06895 /* oriType */ 06896 recip->recip[idx] = ASN_OBJECT_ID; 06897 idx += 1; 06898 XMEMCPY(recip->recip + idx, oriTypeLen, oriTypeLenSz); 06899 idx += oriTypeLenSz; 06900 XMEMCPY(recip->recip + idx, oriType, oriTypeSz); 06901 idx += oriTypeSz; 06902 /* oriValue, input MUST already be ASN.1 encoded */ 06903 XMEMCPY(recip->recip + idx, oriValue, oriValueSz); 06904 idx += oriValueSz; 06905 06906 /* store recipient size */ 06907 recip->recipSz = idx; 06908 recip->recipType = PKCS7_ORI; 06909 recip->recipVersion = 4; 06910 06911 /* add recipient to recip list */ 06912 if (pkcs7->recipList == NULL) { 06913 pkcs7->recipList = recip; 06914 } else { 06915 lastRecip = pkcs7->recipList; 06916 while (lastRecip->next != NULL) { 06917 lastRecip = lastRecip->next; 06918 } 06919 lastRecip->next = recip; 06920 } 06921 06922 (void)options; 06923 06924 return idx; 06925 } 06926 06927 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 06928 06929 06930 static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, 06931 byte* salt, word32 saltSz, int kdfOID, 06932 int prfOID, int iterations, byte* out, 06933 word32 outSz) 06934 { 06935 int ret; 06936 06937 if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL) 06938 return BAD_FUNC_ARG; 06939 06940 switch (kdfOID) { 06941 06942 case PBKDF2_OID: 06943 06944 ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, 06945 outSz, prfOID); 06946 if (ret != 0) { 06947 return ret; 06948 } 06949 06950 break; 06951 06952 default: 06953 WOLFSSL_MSG("Unsupported KDF OID"); 06954 return PKCS7_OID_E; 06955 } 06956 06957 return 0; 06958 } 06959 06960 06961 /* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK). 06962 * 06963 * Returns output size on success, negative upon error */ 06964 static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, 06965 const byte* cek, word32 cekSz, 06966 byte* out, word32 *outSz, 06967 const byte* iv, word32 ivSz, int algID) 06968 { 06969 WC_RNG rng; 06970 int blockSz, outLen, ret; 06971 word32 padSz; 06972 byte* lastBlock; 06973 06974 if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL) 06975 return BAD_FUNC_ARG; 06976 06977 /* get encryption algorithm block size */ 06978 blockSz = wc_PKCS7_GetOIDBlockSize(algID); 06979 if (blockSz < 0) 06980 return blockSz; 06981 06982 /* get pad bytes needed to block boundary */ 06983 padSz = blockSz - ((4 + cekSz) % blockSz); 06984 outLen = 4 + cekSz + padSz; 06985 06986 /* must be at least two blocks long */ 06987 if (outLen < 2 * blockSz) 06988 padSz += blockSz; 06989 06990 /* if user set out to NULL, give back required length */ 06991 if (out == NULL) { 06992 *outSz = outLen; 06993 return LENGTH_ONLY_E; 06994 } 06995 06996 /* verify output buffer is large enough */ 06997 if (*outSz < (word32)outLen) 06998 return BUFFER_E; 06999 07000 out[0] = cekSz; 07001 out[1] = ~cek[0]; 07002 out[2] = ~cek[1]; 07003 out[3] = ~cek[2]; 07004 XMEMCPY(out + 4, cek, cekSz); 07005 07006 /* random padding of size padSz */ 07007 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 07008 if (ret != 0) 07009 return ret; 07010 07011 ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz); 07012 07013 if (ret == 0) { 07014 /* encrypt, normal */ 07015 ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, 07016 ivSz, NULL, 0, NULL, 0, out, outLen, out); 07017 } 07018 07019 if (ret == 0) { 07020 /* encrypt again, using last ciphertext block as IV */ 07021 lastBlock = out + (((outLen / blockSz) - 1) * blockSz); 07022 ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, 07023 blockSz, NULL, 0, NULL, 0, out, 07024 outLen, out); 07025 } 07026 07027 if (ret == 0) { 07028 *outSz = outLen; 07029 } else { 07030 outLen = ret; 07031 } 07032 07033 wc_FreeRng(&rng); 07034 07035 return outLen; 07036 } 07037 07038 07039 /* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK). 07040 * 07041 * Returns cek size on success, negative upon error */ 07042 static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, 07043 word32 kekSz, const byte* in, word32 inSz, 07044 byte* out, word32 outSz, const byte* iv, 07045 word32 ivSz, int algID) 07046 { 07047 int blockSz, cekLen, ret; 07048 byte* tmpIv = NULL; 07049 byte* lastBlock = NULL; 07050 byte* outTmp = NULL; 07051 07052 if (pkcs7 == NULL || kek == NULL || in == NULL || 07053 out == NULL || iv == NULL) { 07054 return BAD_FUNC_ARG; 07055 } 07056 07057 outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07058 if (outTmp == NULL) 07059 return MEMORY_E; 07060 07061 /* get encryption algorithm block size */ 07062 blockSz = wc_PKCS7_GetOIDBlockSize(algID); 07063 if (blockSz < 0) { 07064 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07065 return blockSz; 07066 } 07067 07068 /* input needs to be blockSz multiple and at least 2 * blockSz */ 07069 if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) { 07070 WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 " 07071 "times block size"); 07072 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07073 return BAD_FUNC_ARG; 07074 } 07075 07076 /* use block out[n-1] as IV to decrypt block out[n] */ 07077 lastBlock = (byte*)in + inSz - blockSz; 07078 tmpIv = lastBlock - blockSz; 07079 07080 /* decrypt last block */ 07081 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, tmpIv, 07082 blockSz, NULL, 0, NULL, 0, lastBlock, blockSz, 07083 outTmp + inSz - blockSz); 07084 07085 if (ret == 0) { 07086 /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ 07087 lastBlock = outTmp + inSz - blockSz; 07088 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, 07089 lastBlock, blockSz, NULL, 0, NULL, 0, (byte*)in, inSz - blockSz, 07090 outTmp); 07091 } 07092 07093 if (ret == 0) { 07094 /* decrypt using original kek and iv */ 07095 ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, 07096 (byte*)iv, ivSz, NULL, 0, NULL, 0, outTmp, inSz, outTmp); 07097 } 07098 07099 if (ret != 0) { 07100 ForceZero(outTmp, inSz); 07101 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07102 return ret; 07103 } 07104 07105 cekLen = outTmp[0]; 07106 07107 /* verify length */ 07108 if ((word32)cekLen > inSz) { 07109 ForceZero(outTmp, inSz); 07110 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07111 return BAD_FUNC_ARG; 07112 } 07113 07114 /* verify check bytes */ 07115 if ((outTmp[1] ^ outTmp[4]) != 0xFF || 07116 (outTmp[2] ^ outTmp[5]) != 0xFF || 07117 (outTmp[3] ^ outTmp[6]) != 0xFF) { 07118 ForceZero(outTmp, inSz); 07119 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07120 return BAD_FUNC_ARG; 07121 } 07122 07123 if (outSz < (word32)cekLen) { 07124 ForceZero(outTmp, inSz); 07125 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07126 return BUFFER_E; 07127 } 07128 07129 XMEMCPY(out, outTmp + 4, outTmp[0]); 07130 ForceZero(outTmp, inSz); 07131 XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07132 07133 return cekLen; 07134 } 07135 07136 07137 /* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo 07138 * to CMS/PKCS#7 EnvelopedData structure. 07139 * 07140 * Return 0 on success, negative upon error */ 07141 int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, 07142 byte* salt, word32 saltSz, int kdfOID, 07143 int hashOID, int iterations, int kekEncryptOID, 07144 int options) 07145 { 07146 Pkcs7EncodedRecip* recip = NULL; 07147 Pkcs7EncodedRecip* lastRecip = NULL; 07148 07149 /* PasswordRecipientInfo */ 07150 byte recipSeq[MAX_SEQ_SZ]; 07151 byte ver[MAX_VERSION_SZ]; 07152 word32 recipSeqSz, verSz; 07153 07154 /* KeyDerivationAlgorithmIdentifier */ 07155 byte kdfAlgoIdSeq[MAX_SEQ_SZ]; 07156 byte kdfAlgoId[MAX_OID_SZ]; 07157 byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */ 07158 byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */ 07159 byte kdfIterations[MAX_VERSION_SZ]; 07160 word32 kdfAlgoIdSeqSz, kdfAlgoIdSz; 07161 word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz; 07162 /* OPTIONAL: keyLength, not supported yet */ 07163 /* OPTIONAL: prf AlgorithIdentifier, not supported yet */ 07164 07165 /* KeyEncryptionAlgorithmIdentifier */ 07166 byte keyEncAlgoIdSeq[MAX_SEQ_SZ]; 07167 byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */ 07168 byte pwriEncAlgoId[MAX_ALGO_SZ]; 07169 byte ivOctetString[MAX_OCTET_STR_SZ]; 07170 word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz; 07171 word32 pwriEncAlgoIdSz, ivOctetStringSz; 07172 07173 /* EncryptedKey */ 07174 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 07175 word32 encKeyOctetStrSz; 07176 07177 byte tmpIv[MAX_CONTENT_IV_SIZE]; 07178 byte* encryptedKey = NULL; 07179 byte* kek = NULL; 07180 07181 int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0; 07182 int encryptOID; 07183 word32 idx, totalSz = 0, encryptedKeySz; 07184 07185 if (pkcs7 == NULL || passwd == NULL || pLen == 0 || 07186 salt == NULL || saltSz == 0) { 07187 return BAD_FUNC_ARG; 07188 } 07189 07190 /* allow user to use different KEK encryption algorithm than used for 07191 * main content encryption algorithm, if passed in */ 07192 if (kekEncryptOID != 0) { 07193 encryptOID = kekEncryptOID; 07194 } else { 07195 encryptOID = pkcs7->encryptOID; 07196 } 07197 07198 /* get content-encryption key size, based on algorithm */ 07199 cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 07200 if (cekKeySz < 0) 07201 return cekKeySz; 07202 07203 /* get KEK encryption key size, based on algorithm */ 07204 if (encryptOID != pkcs7->encryptOID) { 07205 kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); 07206 } else { 07207 kekKeySz = cekKeySz; 07208 } 07209 07210 /* get KEK encryption block size */ 07211 kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID); 07212 if (kekBlockSz < 0) 07213 return kekBlockSz; 07214 07215 /* generate random CEK */ 07216 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz); 07217 if (ret < 0) 07218 return ret; 07219 07220 /* generate random IV */ 07221 ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz); 07222 if (ret != 0) 07223 return ret; 07224 07225 /* allocate memory for RecipientInfo, KEK, encrypted key */ 07226 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), 07227 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07228 if (recip == NULL) 07229 return MEMORY_E; 07230 07231 kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07232 if (kek == NULL) { 07233 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07234 return MEMORY_E; 07235 } 07236 07237 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, 07238 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07239 if (encryptedKey == NULL) { 07240 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07241 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07242 return MEMORY_E; 07243 } 07244 07245 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 07246 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); 07247 XMEMSET(kek, 0, kekKeySz); 07248 XMEMSET(encryptedKey, 0, encryptedKeySz); 07249 07250 /* generate KEK: expand password into KEK */ 07251 ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, 07252 kdfOID, hashOID, iterations, kek, 07253 kekKeySz); 07254 if (ret < 0) { 07255 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07256 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07257 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07258 return ret; 07259 } 07260 07261 /* generate encrypted key: encrypt CEK with KEK */ 07262 ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek, 07263 pkcs7->cekSz, encryptedKey, &encryptedKeySz, 07264 tmpIv, kekBlockSz, encryptOID); 07265 if (ret < 0) { 07266 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07267 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07268 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07269 return ret; 07270 } 07271 encryptedKeySz = ret; 07272 07273 /* put together encrypted key OCTET STRING */ 07274 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); 07275 totalSz += (encKeyOctetStrSz + encryptedKeySz); 07276 07277 /* put together IV OCTET STRING */ 07278 ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString); 07279 totalSz += (ivOctetStringSz + kekBlockSz); 07280 07281 /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + 07282 blockKeySz) for IV OCTET STRING */ 07283 pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId, 07284 oidBlkType, ivOctetStringSz + kekBlockSz); 07285 totalSz += pwriEncAlgoIdSz; 07286 07287 /* set KeyEncryptionAlgorithms OID */ 07288 ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId)); 07289 if (ret <= 0) { 07290 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07291 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07292 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07293 return ret; 07294 } 07295 keyEncAlgoIdSz = ret; 07296 totalSz += keyEncAlgoIdSz; 07297 07298 /* KeyEncryptionAlgorithm SEQ */ 07299 keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + 07300 ivOctetStringSz + kekBlockSz, 07301 keyEncAlgoIdSeq); 07302 totalSz += keyEncAlgoIdSeqSz; 07303 07304 /* set KDF salt */ 07305 kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr); 07306 totalSz += (kdfSaltOctetStrSz + saltSz); 07307 07308 /* set KDF iteration count */ 07309 kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); 07310 totalSz += kdfIterationsSz; 07311 07312 /* set KDF params SEQ */ 07313 kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz, 07314 kdfParamsSeq); 07315 totalSz += kdfParamsSeqSz; 07316 07317 /* set KDF algo OID */ 07318 ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId)); 07319 if (ret <= 0) { 07320 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07321 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07322 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07323 return ret; 07324 } 07325 kdfAlgoIdSz = ret; 07326 totalSz += kdfAlgoIdSz; 07327 07328 /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ 07329 kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz + 07330 kdfSaltOctetStrSz + saltSz + kdfIterationsSz, 07331 kdfAlgoIdSeq); 07332 totalSz += kdfAlgoIdSeqSz; 07333 07334 /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ 07335 verSz = SetMyVersion(0, ver, 0); 07336 totalSz += verSz; 07337 recip->recipVersion = 0; 07338 07339 /* set PasswordRecipientInfo SEQ */ 07340 recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); 07341 totalSz += recipSeqSz; 07342 07343 if (totalSz > MAX_RECIP_SZ) { 07344 WOLFSSL_MSG("CMS Recipient output buffer too small"); 07345 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07346 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07347 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07348 return BUFFER_E; 07349 } 07350 07351 idx = 0; 07352 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); 07353 idx += recipSeqSz; 07354 XMEMCPY(recip->recip + idx, ver, verSz); 07355 idx += verSz; 07356 XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz); 07357 idx += kdfAlgoIdSeqSz; 07358 XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz); 07359 idx += kdfAlgoIdSz; 07360 XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz); 07361 idx += kdfParamsSeqSz; 07362 XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz); 07363 idx += kdfSaltOctetStrSz; 07364 XMEMCPY(recip->recip + idx, salt, saltSz); 07365 idx += saltSz; 07366 XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz); 07367 idx += kdfIterationsSz; 07368 XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz); 07369 idx += keyEncAlgoIdSeqSz; 07370 XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz); 07371 idx += keyEncAlgoIdSz; 07372 XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz); 07373 idx += pwriEncAlgoIdSz; 07374 XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); 07375 idx += ivOctetStringSz; 07376 XMEMCPY(recip->recip + idx, tmpIv, kekBlockSz); 07377 idx += kekBlockSz; 07378 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); 07379 idx += encKeyOctetStrSz; 07380 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); 07381 idx += encryptedKeySz; 07382 07383 ForceZero(kek, kekBlockSz); 07384 ForceZero(encryptedKey, encryptedKeySz); 07385 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07386 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07387 07388 /* store recipient size */ 07389 recip->recipSz = idx; 07390 recip->recipType = PKCS7_PWRI; 07391 07392 /* add recipient to recip list */ 07393 if (pkcs7->recipList == NULL) { 07394 pkcs7->recipList = recip; 07395 } else { 07396 lastRecip = pkcs7->recipList; 07397 while (lastRecip->next != NULL) { 07398 lastRecip = lastRecip->next; 07399 } 07400 lastRecip->next = recip; 07401 } 07402 07403 (void)options; 07404 07405 return idx; 07406 } 07407 07408 /* Import password and KDF settings into a PKCS7 structure. Used for setting 07409 * the password info for decryption a EnvelopedData PWRI RecipientInfo. 07410 * 07411 * Returns 0 on success, negative upon error */ 07412 int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) 07413 { 07414 if (pkcs7 == NULL || passwd == NULL || pLen == 0) 07415 return BAD_FUNC_ARG; 07416 07417 pkcs7->pass = passwd; 07418 pkcs7->passSz = pLen; 07419 07420 return 0; 07421 } 07422 07423 #endif /* NO_PWDBASED */ 07424 07425 07426 /* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo 07427 * to CMS/PKCS#7 EnvelopedData structure. 07428 * 07429 * pkcs7 - pointer to initialized PKCS7 structure 07430 * keyWrapOID - OID sum of key wrap algorithm identifier 07431 * kek - key encryption key 07432 * kekSz - size of kek, bytes 07433 * keyID - key-encryption key identifier, pre-distributed to endpoints 07434 * keyIDSz - size of keyID, bytes 07435 * timePtr - pointer to "time_t", which is typically "long" (OPTIONAL) 07436 * otherOID - ASN.1 encoded OID of other attribute (OPTIONAL) 07437 * otherOIDSz - size of otherOID, bytes (OPTIONAL) 07438 * other - other attribute (OPTIONAL) 07439 * otherSz - size of other (OPTIONAL) 07440 * 07441 * Returns 0 on success, negative upon error */ 07442 int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, 07443 word32 kekSz, byte* keyId, word32 keyIdSz, 07444 void* timePtr, byte* otherOID, 07445 word32 otherOIDSz, byte* other, word32 otherSz, 07446 int options) 07447 { 07448 Pkcs7EncodedRecip* recip = NULL; 07449 Pkcs7EncodedRecip* lastRecip = NULL; 07450 07451 byte recipSeq[MAX_SEQ_SZ]; 07452 byte ver[MAX_VERSION_SZ]; 07453 byte kekIdSeq[MAX_SEQ_SZ]; 07454 byte kekIdOctetStr[MAX_OCTET_STR_SZ]; 07455 byte genTime[ASN_GENERALIZED_TIME_SIZE]; 07456 byte otherAttSeq[MAX_SEQ_SZ]; 07457 byte encAlgoId[MAX_ALGO_SZ]; 07458 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 07459 #ifdef WOLFSSL_SMALL_STACK 07460 byte* encryptedKey; 07461 #else 07462 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 07463 #endif 07464 07465 int blockKeySz = 0, ret = 0, direction; 07466 word32 idx = 0; 07467 word32 totalSz = 0; 07468 word32 recipSeqSz = 0, verSz = 0; 07469 word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0; 07470 word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0; 07471 int encryptedKeySz; 07472 07473 int timeSz = 0; 07474 #ifndef NO_ASN_TIME 07475 time_t* tm = NULL; 07476 #endif 07477 07478 if (pkcs7 == NULL || kek == NULL || keyId == NULL) 07479 return BAD_FUNC_ARG; 07480 07481 recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, 07482 DYNAMIC_TYPE_PKCS7); 07483 if (recip == NULL) 07484 return MEMORY_E; 07485 07486 XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); 07487 07488 /* get key size for content-encryption key based on algorithm */ 07489 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 07490 if (blockKeySz < 0) { 07491 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07492 return blockKeySz; 07493 } 07494 07495 /* generate random content encryption key, if needed */ 07496 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 07497 if (ret < 0) { 07498 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07499 return ret; 07500 } 07501 07502 /* EncryptedKey */ 07503 #ifdef WOLFSSL_SMALL_STACK 07504 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 07505 DYNAMIC_TYPE_PKCS7); 07506 if (encryptedKey == NULL) { 07507 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07508 return MEMORY_E; 07509 } 07510 #endif 07511 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 07512 XMEMSET(encryptedKey, 0, encryptedKeySz); 07513 07514 #ifndef NO_AES 07515 direction = AES_ENCRYPTION; 07516 #else 07517 direction = DES_ENCRYPTION; 07518 #endif 07519 07520 encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, 07521 encryptedKey, encryptedKeySz, keyWrapOID, 07522 direction); 07523 if (encryptedKeySz < 0) { 07524 #ifdef WOLFSSL_SMALL_STACK 07525 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07526 #endif 07527 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07528 return encryptedKeySz; 07529 } 07530 /* handle a zero size encKey case as WC_KEY_SIZE_E */ 07531 if (encryptedKeySz == 0 || encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { 07532 #ifdef WOLFSSL_SMALL_STACK 07533 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07534 #endif 07535 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07536 return WC_KEY_SIZE_E; 07537 } 07538 07539 encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); 07540 totalSz += (encKeyOctetStrSz + encryptedKeySz); 07541 07542 /* KeyEncryptionAlgorithmIdentifier */ 07543 encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0); 07544 totalSz += encAlgoIdSz; 07545 07546 /* KEKIdentifier: keyIdentifier */ 07547 kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr); 07548 totalSz += (kekIdOctetStrSz + keyIdSz); 07549 07550 /* KEKIdentifier: GeneralizedTime (OPTIONAL) */ 07551 #ifndef NO_ASN_TIME 07552 if (timePtr != NULL) { 07553 tm = (time_t*)timePtr; 07554 timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); 07555 if (timeSz < 0) { 07556 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07557 #ifdef WOLFSSL_SMALL_STACK 07558 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07559 #endif 07560 return timeSz; 07561 } 07562 totalSz += timeSz; 07563 } 07564 #endif 07565 07566 /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */ 07567 if (other != NULL && otherSz > 0) { 07568 otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq); 07569 totalSz += otherAttSeqSz + otherOIDSz + otherSz; 07570 } 07571 07572 /* KEKIdentifier SEQ */ 07573 kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + timeSz + 07574 otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq); 07575 totalSz += kekIdSeqSz; 07576 07577 /* version */ 07578 verSz = SetMyVersion(4, ver, 0); 07579 totalSz += verSz; 07580 recip->recipVersion = 4; 07581 07582 /* KEKRecipientInfo SEQ */ 07583 recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq); 07584 totalSz += recipSeqSz; 07585 07586 if (totalSz > MAX_RECIP_SZ) { 07587 WOLFSSL_MSG("CMS Recipient output buffer too small"); 07588 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07589 #ifdef WOLFSSL_SMALL_STACK 07590 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07591 #endif 07592 return BUFFER_E; 07593 } 07594 07595 XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); 07596 idx += recipSeqSz; 07597 XMEMCPY(recip->recip + idx, ver, verSz); 07598 idx += verSz; 07599 XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz); 07600 idx += kekIdSeqSz; 07601 XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz); 07602 idx += kekIdOctetStrSz; 07603 XMEMCPY(recip->recip + idx, keyId, keyIdSz); 07604 idx += keyIdSz; 07605 if (timePtr != NULL) { 07606 XMEMCPY(recip->recip + idx, genTime, timeSz); 07607 idx += timeSz; 07608 } 07609 if (other != NULL && otherSz > 0) { 07610 XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz); 07611 idx += otherAttSeqSz; 07612 XMEMCPY(recip->recip + idx, otherOID, otherOIDSz); 07613 idx += otherOIDSz; 07614 XMEMCPY(recip->recip + idx, other, otherSz); 07615 idx += otherSz; 07616 } 07617 XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz); 07618 idx += encAlgoIdSz; 07619 XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); 07620 idx += encKeyOctetStrSz; 07621 XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); 07622 idx += encryptedKeySz; 07623 07624 #ifdef WOLFSSL_SMALL_STACK 07625 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07626 #endif 07627 07628 /* store recipient size */ 07629 recip->recipSz = idx; 07630 recip->recipType = PKCS7_KEKRI; 07631 07632 /* add recipient to recip list */ 07633 if (pkcs7->recipList == NULL) { 07634 pkcs7->recipList = recip; 07635 } else { 07636 lastRecip = pkcs7->recipList; 07637 while(lastRecip->next != NULL) { 07638 lastRecip = lastRecip->next; 07639 } 07640 lastRecip->next = recip; 07641 } 07642 07643 (void)options; 07644 07645 return idx; 07646 } 07647 07648 07649 static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType) 07650 { 07651 int version = -1; 07652 07653 if (pkcs7 == NULL) 07654 return BAD_FUNC_ARG; 07655 07656 switch (cmsContentType) { 07657 case ENVELOPED_DATA: 07658 07659 /* NOTE: EnvelopedData does not currently support 07660 originatorInfo or unprotectedAttributes. When either of these 07661 are added, version checking below needs to be updated to match 07662 Section 6.1 of RFC 5652 */ 07663 07664 /* if RecipientInfos include pwri or ori, version is 3 */ 07665 if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) || 07666 wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) { 07667 version = 3; 07668 break; 07669 } 07670 07671 /* if unprotectedAttrs is absent AND all RecipientInfo structs 07672 are version 0, version is 0 */ 07673 if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) { 07674 version = 0; 07675 break; 07676 } 07677 07678 /* otherwise, version is 2 */ 07679 version = 2; 07680 break; 07681 07682 default: 07683 break; 07684 } 07685 07686 return version; 07687 } 07688 07689 07690 /* build PKCS#7 envelopedData content type, return enveloped size */ 07691 int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) 07692 { 07693 int ret, idx = 0; 07694 int totalSz, padSz, encryptedOutSz; 07695 07696 int contentInfoSeqSz = 0, outerContentTypeSz = 0, outerContentSz; 07697 byte contentInfoSeq[MAX_SEQ_SZ]; 07698 byte outerContentType[MAX_ALGO_SZ]; 07699 byte outerContent[MAX_SEQ_SZ]; 07700 07701 int kariVersion; 07702 int envDataSeqSz, verSz; 07703 byte envDataSeq[MAX_SEQ_SZ]; 07704 byte ver[MAX_VERSION_SZ]; 07705 07706 WC_RNG rng; 07707 int blockSz, blockKeySz; 07708 byte* plain; 07709 byte* encryptedContent; 07710 07711 Pkcs7EncodedRecip* tmpRecip = NULL; 07712 int recipSz, recipSetSz; 07713 byte recipSet[MAX_SET_SZ]; 07714 07715 int encContentOctetSz, encContentSeqSz, contentTypeSz; 07716 int contentEncAlgoSz, ivOctetStringSz; 07717 byte encContentSeq[MAX_SEQ_SZ]; 07718 byte contentType[MAX_ALGO_SZ]; 07719 byte contentEncAlgo[MAX_ALGO_SZ]; 07720 byte tmpIv[MAX_CONTENT_IV_SIZE]; 07721 byte ivOctetString[MAX_OCTET_STR_SZ]; 07722 byte encContentOctet[MAX_OCTET_STR_SZ]; 07723 07724 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) 07725 return BAD_FUNC_ARG; 07726 07727 if (output == NULL || outputSz == 0) 07728 return BAD_FUNC_ARG; 07729 07730 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 07731 if (blockKeySz < 0) 07732 return blockKeySz; 07733 07734 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); 07735 if (blockSz < 0) 07736 return blockSz; 07737 07738 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { 07739 /* outer content type */ 07740 ret = wc_SetContentType(ENVELOPED_DATA, outerContentType, 07741 sizeof(outerContentType)); 07742 if (ret < 0) 07743 return ret; 07744 07745 outerContentTypeSz = ret; 07746 } 07747 07748 /* generate random content encryption key */ 07749 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 07750 if (ret != 0) { 07751 return ret; 07752 } 07753 07754 /* build RecipientInfo, only if user manually set singleCert and size */ 07755 if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { 07756 switch (pkcs7->publicKeyOID) { 07757 #ifndef NO_RSA 07758 case RSAk: 07759 ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, 07760 pkcs7->singleCertSz, 0); 07761 break; 07762 #endif 07763 #ifdef HAVE_ECC 07764 case ECDSAk: 07765 ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, 07766 pkcs7->singleCertSz, 07767 pkcs7->keyWrapOID, 07768 pkcs7->keyAgreeOID, pkcs7->ukm, 07769 pkcs7->ukmSz, 0); 07770 break; 07771 #endif 07772 07773 default: 07774 WOLFSSL_MSG("Unsupported RecipientInfo public key type"); 07775 return BAD_FUNC_ARG; 07776 }; 07777 07778 if (ret < 0) { 07779 WOLFSSL_MSG("Failed to create RecipientInfo"); 07780 return ret; 07781 } 07782 } 07783 07784 recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); 07785 if (recipSz < 0) { 07786 return ret; 07787 07788 } else if (recipSz == 0) { 07789 WOLFSSL_MSG("You must add at least one CMS recipient"); 07790 return PKCS7_RECIP_E; 07791 } 07792 recipSetSz = SetSet(recipSz, recipSet); 07793 07794 /* version, defined in Section 6.1 of RFC 5652 */ 07795 kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA); 07796 if (kariVersion < 0) { 07797 WOLFSSL_MSG("Failed to set CMS EnvelopedData version"); 07798 return PKCS7_RECIP_E; 07799 } 07800 07801 verSz = SetMyVersion(kariVersion, ver, 0); 07802 07803 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 07804 if (ret != 0) 07805 return ret; 07806 07807 /* generate IV for block cipher */ 07808 ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz); 07809 wc_FreeRng(&rng); 07810 if (ret != 0) 07811 return ret; 07812 07813 /* EncryptedContentInfo */ 07814 ret = wc_SetContentType(pkcs7->contentOID, contentType, 07815 sizeof(contentType)); 07816 if (ret < 0) 07817 return ret; 07818 07819 contentTypeSz = ret; 07820 07821 /* allocate encrypted content buffer and PKCS#7 padding */ 07822 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); 07823 if (padSz < 0) 07824 return padSz; 07825 07826 encryptedOutSz = pkcs7->contentSz + padSz; 07827 07828 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07829 if (plain == NULL) 07830 return MEMORY_E; 07831 07832 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, 07833 encryptedOutSz, blockSz); 07834 if (ret < 0) { 07835 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07836 return ret; 07837 } 07838 07839 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 07840 DYNAMIC_TYPE_PKCS7); 07841 if (encryptedContent == NULL) { 07842 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07843 return MEMORY_E; 07844 } 07845 07846 /* put together IV OCTET STRING */ 07847 ivOctetStringSz = SetOctetString(blockSz, ivOctetString); 07848 07849 /* build up our ContentEncryptionAlgorithmIdentifier sequence, 07850 * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ 07851 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 07852 oidBlkType, ivOctetStringSz + blockSz); 07853 07854 if (contentEncAlgoSz == 0) { 07855 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07856 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07857 return BAD_FUNC_ARG; 07858 } 07859 07860 /* encrypt content */ 07861 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, 07862 pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, 07863 encryptedOutSz, encryptedContent); 07864 07865 if (ret != 0) { 07866 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07867 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07868 return ret; 07869 } 07870 07871 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, 07872 encContentOctet); 07873 07874 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 07875 ivOctetStringSz + blockSz + 07876 encContentOctetSz + encryptedOutSz, 07877 encContentSeq); 07878 07879 /* keep track of sizes for outer wrapper layering */ 07880 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + 07881 contentEncAlgoSz + ivOctetStringSz + blockSz + 07882 encContentOctetSz + encryptedOutSz; 07883 07884 /* EnvelopedData */ 07885 envDataSeqSz = SetSequence(totalSz, envDataSeq); 07886 totalSz += envDataSeqSz; 07887 07888 /* outer content */ 07889 outerContentSz = SetExplicit(0, totalSz, outerContent); 07890 totalSz += outerContentTypeSz; 07891 totalSz += outerContentSz; 07892 07893 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { 07894 /* ContentInfo */ 07895 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 07896 totalSz += contentInfoSeqSz; 07897 } 07898 07899 if (totalSz > (int)outputSz) { 07900 WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); 07901 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07902 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 07903 return BUFFER_E; 07904 } 07905 07906 if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { 07907 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 07908 idx += contentInfoSeqSz; 07909 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 07910 idx += outerContentTypeSz; 07911 XMEMCPY(output + idx, outerContent, outerContentSz); 07912 idx += outerContentSz; 07913 } 07914 XMEMCPY(output + idx, envDataSeq, envDataSeqSz); 07915 idx += envDataSeqSz; 07916 XMEMCPY(output + idx, ver, verSz); 07917 idx += verSz; 07918 XMEMCPY(output + idx, recipSet, recipSetSz); 07919 idx += recipSetSz; 07920 /* copy in recipients from list */ 07921 tmpRecip = pkcs7->recipList; 07922 while (tmpRecip != NULL) { 07923 XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); 07924 idx += tmpRecip->recipSz; 07925 tmpRecip = tmpRecip->next; 07926 } 07927 wc_PKCS7_FreeEncodedRecipientSet(pkcs7); 07928 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 07929 idx += encContentSeqSz; 07930 XMEMCPY(output + idx, contentType, contentTypeSz); 07931 idx += contentTypeSz; 07932 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 07933 idx += contentEncAlgoSz; 07934 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 07935 idx += ivOctetStringSz; 07936 XMEMCPY(output + idx, tmpIv, blockSz); 07937 idx += blockSz; 07938 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 07939 idx += encContentOctetSz; 07940 XMEMCPY(output + idx, encryptedContent, encryptedOutSz); 07941 idx += encryptedOutSz; 07942 07943 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07944 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 07945 07946 return idx; 07947 } 07948 07949 #ifndef NO_RSA 07950 /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ 07951 static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, 07952 word32* idx, byte* decryptedKey, 07953 word32* decryptedKeySz, int* recipFound) 07954 { 07955 int length, encryptedKeySz = 0, ret = 0; 07956 int keySz, version, sidType = 0; 07957 word32 encOID; 07958 word32 keyIdx; 07959 byte issuerHash[KEYID_SIZE]; 07960 byte* outKey = NULL; 07961 byte* pkiMsg = in; 07962 word32 pkiMsgSz = inSz; 07963 byte tag; 07964 07965 07966 #ifndef NO_PKCS7_STREAM 07967 word32 tmpIdx = *idx; 07968 long rc; 07969 #endif 07970 #ifdef WC_RSA_BLINDING 07971 WC_RNG rng; 07972 #endif 07973 07974 #ifdef WOLFSSL_SMALL_STACK 07975 mp_int* serialNum = NULL; 07976 byte* encryptedKey = NULL; 07977 RsaKey* privKey = NULL; 07978 #else 07979 mp_int serialNum[1]; 07980 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 07981 RsaKey privKey[1]; 07982 #endif 07983 07984 switch (pkcs7->state) { 07985 case WC_PKCS7_DECRYPT_KTRI: 07986 #ifndef NO_PKCS7_STREAM 07987 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ, 07988 &pkiMsg, idx)) != 0) { 07989 return ret; 07990 } 07991 07992 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 07993 in, inSz); 07994 if (rc < 0) { 07995 ret = (int)rc; 07996 break; 07997 } 07998 pkiMsgSz = (word32)rc; 07999 08000 #endif 08001 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) 08002 return ASN_PARSE_E; 08003 08004 if (version == 0) { 08005 sidType = CMS_ISSUER_AND_SERIAL_NUMBER; 08006 } else if (version == 2) { 08007 sidType = CMS_SKID; 08008 } else { 08009 return ASN_VERSION_E; 08010 } 08011 08012 #ifndef NO_PKCS7_STREAM 08013 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 08014 break; 08015 } 08016 wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version); 08017 08018 /* @TODO getting total amount left because of GetInt call later on 08019 * this could be optimized to stream better */ 08020 pkcs7->stream->expected = (pkcs7->stream->maxLen - 08021 pkcs7->stream->totalRd) + pkcs7->stream->length; 08022 #endif 08023 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2); 08024 FALL_THROUGH; 08025 08026 case WC_PKCS7_DECRYPT_KTRI_2: 08027 #ifndef NO_PKCS7_STREAM 08028 08029 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, 08030 &pkiMsg, idx)) != 0) { 08031 return ret; 08032 } 08033 08034 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 08035 in, inSz); 08036 if (rc < 0) { 08037 ret = (int)rc; 08038 break; 08039 } 08040 pkiMsgSz = (word32)rc; 08041 08042 wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); 08043 08044 /* @TODO get expected size for next part, does not account for 08045 * GetInt call well */ 08046 if (pkcs7->stream->expected == MAX_SEQ_SZ) { 08047 int sz; 08048 word32 lidx; 08049 08050 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 08051 lidx = *idx; 08052 ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz); 08053 if (ret < 0) 08054 return ret; 08055 } 08056 else { 08057 lidx = *idx + ASN_TAG_SZ; 08058 ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz); 08059 if (ret < 0) 08060 return ret; 08061 } 08062 08063 pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ + 08064 MAX_LENGTH_SZ; 08065 if (pkcs7->stream->length > 0 && 08066 pkcs7->stream->length < pkcs7->stream->expected) { 08067 return WC_PKCS7_WANT_READ_E; 08068 } 08069 } 08070 #endif /* !NO_PKCS7_STREAM */ 08071 08072 if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { 08073 08074 /* remove IssuerAndSerialNumber */ 08075 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 08076 return ASN_PARSE_E; 08077 08078 if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) 08079 return ASN_PARSE_E; 08080 08081 /* if we found correct recipient, issuer hashes will match */ 08082 if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { 08083 *recipFound = 1; 08084 } 08085 08086 #ifdef WOLFSSL_SMALL_STACK 08087 serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, 08088 DYNAMIC_TYPE_TMP_BUFFER); 08089 if (serialNum == NULL) 08090 return MEMORY_E; 08091 #endif 08092 08093 if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { 08094 #ifdef WOLFSSL_SMALL_STACK 08095 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08096 #endif 08097 return ASN_PARSE_E; 08098 } 08099 08100 mp_clear(serialNum); 08101 08102 #ifdef WOLFSSL_SMALL_STACK 08103 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08104 #endif 08105 08106 } else { 08107 /* remove SubjectKeyIdentifier */ 08108 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08109 return ASN_PARSE_E; 08110 08111 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) 08112 return ASN_PARSE_E; 08113 08114 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08115 return ASN_PARSE_E; 08116 08117 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08118 return ASN_PARSE_E; 08119 08120 if (tag != ASN_OCTET_STRING) 08121 return ASN_PARSE_E; 08122 08123 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08124 return ASN_PARSE_E; 08125 08126 /* if we found correct recipient, SKID will match */ 08127 if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, 08128 KEYID_SIZE) == 0) { 08129 *recipFound = 1; 08130 } 08131 (*idx) += KEYID_SIZE; 08132 } 08133 08134 if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) 08135 return ASN_PARSE_E; 08136 08137 /* key encryption algorithm must be RSA for now */ 08138 if (encOID != RSAk) 08139 return ALGO_ID_E; 08140 08141 /* read encryptedKey */ 08142 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08143 return ASN_PARSE_E; 08144 08145 if (tag != ASN_OCTET_STRING) 08146 return ASN_PARSE_E; 08147 08148 if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { 08149 return ASN_PARSE_E; 08150 } 08151 if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { 08152 return BUFFER_E; 08153 } 08154 08155 #ifndef NO_PKCS7_STREAM 08156 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 08157 break; 08158 } 08159 wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version); 08160 pkcs7->stream->expected = encryptedKeySz; 08161 #endif 08162 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); 08163 FALL_THROUGH; 08164 08165 case WC_PKCS7_DECRYPT_KTRI_3: 08166 #ifndef NO_PKCS7_STREAM 08167 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 08168 pkcs7->stream->expected, &pkiMsg, idx)) != 0) { 08169 return ret; 08170 } 08171 encryptedKeySz = pkcs7->stream->expected; 08172 #endif 08173 08174 #ifdef WOLFSSL_SMALL_STACK 08175 encryptedKey = (byte*)XMALLOC(encryptedKeySz, pkcs7->heap, 08176 DYNAMIC_TYPE_TMP_BUFFER); 08177 if (encryptedKey == NULL) 08178 return MEMORY_E; 08179 #endif 08180 08181 if (*recipFound == 1) 08182 XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); 08183 *idx += encryptedKeySz; 08184 08185 /* load private key */ 08186 #ifdef WOLFSSL_SMALL_STACK 08187 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, 08188 DYNAMIC_TYPE_TMP_BUFFER); 08189 if (privKey == NULL) { 08190 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08191 return MEMORY_E; 08192 } 08193 #endif 08194 08195 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); 08196 if (ret != 0) { 08197 #ifdef WOLFSSL_SMALL_STACK 08198 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08199 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08200 #endif 08201 return ret; 08202 } 08203 08204 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 08205 keyIdx = 0; 08206 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, 08207 privKey, pkcs7->privateKeySz); 08208 } 08209 else if (pkcs7->devId == INVALID_DEVID) { 08210 ret = BAD_FUNC_ARG; 08211 } 08212 if (ret != 0) { 08213 WOLFSSL_MSG("Failed to decode RSA private key"); 08214 wc_FreeRsaKey(privKey); 08215 #ifdef WOLFSSL_SMALL_STACK 08216 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08217 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08218 #endif 08219 return ret; 08220 } 08221 08222 /* decrypt encryptedKey */ 08223 #ifdef WC_RSA_BLINDING 08224 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 08225 if (ret == 0) { 08226 ret = wc_RsaSetRNG(privKey, &rng); 08227 } 08228 #endif 08229 if (ret == 0) { 08230 keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, 08231 &outKey, privKey); 08232 #ifdef WC_RSA_BLINDING 08233 wc_FreeRng(&rng); 08234 #endif 08235 } else { 08236 keySz = ret; 08237 } 08238 wc_FreeRsaKey(privKey); 08239 08240 if (keySz <= 0 || outKey == NULL) { 08241 ForceZero(encryptedKey, encryptedKeySz); 08242 #ifdef WOLFSSL_SMALL_STACK 08243 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08244 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08245 #endif 08246 return keySz; 08247 } else { 08248 *decryptedKeySz = keySz; 08249 XMEMCPY(decryptedKey, outKey, keySz); 08250 ForceZero(encryptedKey, encryptedKeySz); 08251 } 08252 08253 #ifdef WOLFSSL_SMALL_STACK 08254 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08255 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08256 #endif 08257 08258 #ifndef NO_PKCS7_STREAM 08259 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 08260 break; 08261 } 08262 #endif 08263 ret = 0; /* success */ 08264 break; 08265 08266 default: 08267 WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state"); 08268 ret = BAD_FUNC_ARG; 08269 } 08270 08271 return ret; 08272 } 08273 #endif /* !NO_RSA */ 08274 08275 #ifdef HAVE_ECC 08276 08277 /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ 08278 static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, 08279 byte* pkiMsg, word32 pkiMsgSz, word32* idx) 08280 { 08281 int ret, length; 08282 word32 keyOID, oidSum = 0; 08283 int curve_id = ECC_CURVE_DEF; 08284 byte tag; 08285 08286 if (kari == NULL || pkiMsg == NULL || idx == NULL) 08287 return BAD_FUNC_ARG; 08288 08289 /* remove OriginatorIdentifierOrKey */ 08290 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && 08291 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 08292 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08293 return ASN_PARSE_E; 08294 08295 } else { 08296 return ASN_PARSE_E; 08297 } 08298 08299 /* remove OriginatorPublicKey */ 08300 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && 08301 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 08302 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08303 return ASN_PARSE_E; 08304 08305 } else { 08306 return ASN_PARSE_E; 08307 } 08308 08309 /* remove AlgorithmIdentifier */ 08310 if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0) 08311 return ASN_PARSE_E; 08312 08313 if (keyOID != ECDSAk) 08314 return ASN_PARSE_E; 08315 08316 /* optional algorithm parameters */ 08317 ret = GetObjectId(pkiMsg, idx, &oidSum, oidIgnoreType, pkiMsgSz); 08318 if (ret == 0) { 08319 /* get curve id */ 08320 curve_id = wc_ecc_get_oid(oidSum, NULL, 0); 08321 if (curve_id < 0) 08322 return ECC_CURVE_OID_E; 08323 } 08324 08325 /* remove ECPoint BIT STRING */ 08326 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08327 return ASN_PARSE_E; 08328 08329 if (tag != ASN_BIT_STRING) 08330 return ASN_PARSE_E; 08331 08332 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08333 return ASN_PARSE_E; 08334 08335 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08336 return ASN_EXPECT_0_E; 08337 08338 if (tag != ASN_OTHER_TYPE) 08339 return ASN_EXPECT_0_E; 08340 08341 /* get sender ephemeral public ECDSA key */ 08342 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); 08343 if (ret != 0) 08344 return ret; 08345 08346 kari->senderKeyInit = 1; 08347 08348 /* length-1 for unused bits counter */ 08349 ret = wc_ecc_import_x963_ex(pkiMsg + (*idx), length - 1, kari->senderKey, 08350 curve_id); 08351 if (ret != 0) { 08352 ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey, *idx + length - 1); 08353 if (ret != 0) 08354 return ret; 08355 } 08356 else { 08357 (*idx) += length - 1; 08358 } 08359 08360 return 0; 08361 } 08362 08363 08364 /* remove optional UserKeyingMaterial if available, return 0 on success, 08365 * < 0 on error */ 08366 static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, 08367 byte* pkiMsg, word32 pkiMsgSz, word32* idx) 08368 { 08369 int length; 08370 word32 savedIdx; 08371 byte tag; 08372 08373 if (kari == NULL || pkiMsg == NULL || idx == NULL) 08374 return BAD_FUNC_ARG; 08375 08376 savedIdx = *idx; 08377 08378 /* starts with EXPLICIT [1] */ 08379 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08380 *idx = savedIdx; 08381 return 0; 08382 } 08383 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 08384 *idx = savedIdx; 08385 return 0; 08386 } 08387 08388 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 08389 *idx = savedIdx; 08390 return 0; 08391 } 08392 08393 /* get OCTET STRING */ 08394 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08395 *idx = savedIdx; 08396 return 0; 08397 } 08398 if (tag != ASN_OCTET_STRING) { 08399 *idx = savedIdx; 08400 return 0; 08401 } 08402 08403 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 08404 *idx = savedIdx; 08405 return 0; 08406 } 08407 08408 kari->ukm = NULL; 08409 if (length > 0) { 08410 kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); 08411 if (kari->ukm == NULL) 08412 return MEMORY_E; 08413 08414 XMEMCPY(kari->ukm, pkiMsg + (*idx), length); 08415 kari->ukmOwner = 1; 08416 } 08417 08418 (*idx) += length; 08419 kari->ukmSz = length; 08420 08421 return 0; 08422 } 08423 08424 08425 /* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success, 08426 * < 0 on error */ 08427 static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, 08428 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 08429 word32* keyAgreeOID, word32* keyWrapOID) 08430 { 08431 int length = 0; 08432 word32 localIdx; 08433 08434 if (kari == NULL || pkiMsg == NULL || idx == NULL || 08435 keyAgreeOID == NULL || keyWrapOID == NULL) 08436 return BAD_FUNC_ARG; 08437 08438 localIdx = *idx; 08439 08440 /* remove KeyEncryptionAlgorithmIdentifier */ 08441 if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) 08442 return ASN_PARSE_E; 08443 08444 localIdx = *idx; 08445 if (GetAlgoId(pkiMsg, &localIdx, keyAgreeOID, oidCmsKeyAgreeType, 08446 pkiMsgSz) < 0) { 08447 return ASN_PARSE_E; 08448 } 08449 08450 if (localIdx < *idx + length) { 08451 *idx = localIdx; 08452 } 08453 /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */ 08454 if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) 08455 return ASN_PARSE_E; 08456 08457 return 0; 08458 } 08459 08460 08461 /* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error 08462 * if subject key ID matches, recipFound is set to 1 */ 08463 static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, 08464 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 08465 int* recipFound, byte* rid) 08466 { 08467 int length; 08468 byte tag; 08469 08470 if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL || 08471 rid == NULL) 08472 return BAD_FUNC_ARG; 08473 08474 /* remove RecipientKeyIdentifier IMPLICIT [0] */ 08475 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08476 return ASN_PARSE_E; 08477 } 08478 08479 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 08480 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08481 return ASN_PARSE_E; 08482 08483 } else { 08484 return ASN_PARSE_E; 08485 } 08486 08487 /* remove SubjectKeyIdentifier */ 08488 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08489 return ASN_PARSE_E; 08490 } 08491 08492 if (tag != ASN_OCTET_STRING) 08493 return ASN_PARSE_E; 08494 08495 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08496 return ASN_PARSE_E; 08497 08498 if (length != KEYID_SIZE) 08499 return ASN_PARSE_E; 08500 08501 XMEMCPY(rid, pkiMsg + (*idx), KEYID_SIZE); 08502 (*idx) += length; 08503 08504 /* subject key id should match if recipient found */ 08505 if (XMEMCMP(rid, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) { 08506 *recipFound = 1; 08507 } 08508 08509 return 0; 08510 } 08511 08512 08513 /* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error 08514 * if issuer and serial number match, recipFound is set to 1 */ 08515 static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, 08516 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 08517 int* recipFound, byte* rid) 08518 { 08519 int length, ret; 08520 #ifdef WOLFSSL_SMALL_STACK 08521 mp_int* serial; 08522 mp_int* recipSerial; 08523 #else 08524 mp_int serial[1]; 08525 mp_int recipSerial[1]; 08526 #endif 08527 08528 if (rid == NULL) { 08529 return BAD_FUNC_ARG; 08530 } 08531 08532 /* remove IssuerAndSerialNumber */ 08533 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 08534 return ASN_PARSE_E; 08535 08536 if (GetNameHash(pkiMsg, idx, rid, pkiMsgSz) < 0) 08537 return ASN_PARSE_E; 08538 08539 /* if we found correct recipient, issuer hashes will match */ 08540 if (XMEMCMP(rid, kari->decoded->issuerHash, KEYID_SIZE) == 0) { 08541 *recipFound = 1; 08542 } 08543 08544 #ifdef WOLFSSL_SMALL_STACK 08545 serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, 08546 DYNAMIC_TYPE_TMP_BUFFER); 08547 if (serial == NULL) 08548 return MEMORY_E; 08549 08550 recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, 08551 DYNAMIC_TYPE_TMP_BUFFER); 08552 if (recipSerial == NULL) { 08553 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08554 return MEMORY_E; 08555 } 08556 #endif 08557 08558 if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { 08559 #ifdef WOLFSSL_SMALL_STACK 08560 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08561 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08562 #endif 08563 return ASN_PARSE_E; 08564 } 08565 08566 ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial, 08567 kari->decoded->serialSz); 08568 if (ret != MP_OKAY) { 08569 mp_clear(serial); 08570 WOLFSSL_MSG("Failed to parse CMS recipient serial number"); 08571 #ifdef WOLFSSL_SMALL_STACK 08572 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08573 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08574 #endif 08575 return ret; 08576 } 08577 08578 if (mp_cmp(recipSerial, serial) != MP_EQ) { 08579 mp_clear(serial); 08580 mp_clear(recipSerial); 08581 WOLFSSL_MSG("CMS serial number does not match recipient"); 08582 #ifdef WOLFSSL_SMALL_STACK 08583 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08584 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08585 #endif 08586 return PKCS7_RECIP_E; 08587 } 08588 08589 mp_clear(serial); 08590 mp_clear(recipSerial); 08591 08592 #ifdef WOLFSSL_SMALL_STACK 08593 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08594 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 08595 #endif 08596 08597 return 0; 08598 } 08599 08600 08601 /* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ 08602 static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, 08603 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 08604 int* recipFound, byte* encryptedKey, 08605 int* encryptedKeySz, byte* rid) 08606 { 08607 int length; 08608 int ret = 0; 08609 byte tag; 08610 word32 localIdx; 08611 08612 if (kari == NULL || pkiMsg == NULL || idx == NULL || 08613 recipFound == NULL || encryptedKey == NULL) 08614 return BAD_FUNC_ARG; 08615 08616 /* remove RecipientEncryptedKeys */ 08617 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 08618 return ASN_PARSE_E; 08619 08620 /* remove RecipientEncryptedKeys */ 08621 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 08622 return ASN_PARSE_E; 08623 08624 /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber 08625 * or [0] IMMPLICIT RecipientKeyIdentifier */ 08626 localIdx = *idx; 08627 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) 08628 return ASN_PARSE_E; 08629 08630 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 08631 /* try to get RecipientKeyIdentifier */ 08632 ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, 08633 idx, recipFound, rid); 08634 } else { 08635 /* try to get IssuerAndSerialNumber */ 08636 ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, 08637 idx, recipFound, rid); 08638 } 08639 08640 /* if we don't have either option, malformed CMS */ 08641 if (ret != 0) 08642 return ret; 08643 08644 /* remove EncryptedKey */ 08645 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08646 return ASN_PARSE_E; 08647 08648 if (tag != ASN_OCTET_STRING) 08649 return ASN_PARSE_E; 08650 08651 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08652 return ASN_PARSE_E; 08653 08654 /* put encrypted CEK in decryptedKey buffer for now, decrypt later */ 08655 if (length > *encryptedKeySz) 08656 return BUFFER_E; 08657 08658 XMEMCPY(encryptedKey, pkiMsg + (*idx), length); 08659 *encryptedKeySz = length; 08660 (*idx) += length; 08661 08662 return 0; 08663 } 08664 08665 #endif /* HAVE_ECC */ 08666 08667 08668 int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx) 08669 { 08670 if (pkcs7 == NULL) 08671 return BAD_FUNC_ARG; 08672 08673 pkcs7->oriEncryptCtx = ctx; 08674 08675 return 0; 08676 } 08677 08678 08679 int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx) 08680 { 08681 08682 if (pkcs7 == NULL) 08683 return BAD_FUNC_ARG; 08684 08685 pkcs7->oriDecryptCtx = ctx; 08686 08687 return 0; 08688 } 08689 08690 08691 int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb) 08692 { 08693 if (pkcs7 == NULL) 08694 return BAD_FUNC_ARG; 08695 08696 pkcs7->oriDecryptCb = cb; 08697 08698 return 0; 08699 } 08700 08701 08702 /* return 0 on success */ 08703 int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, CallbackWrapCEK cb) 08704 { 08705 if (pkcs7 == NULL) 08706 return BAD_FUNC_ARG; 08707 08708 pkcs7->wrapCEKCb = cb; 08709 08710 return 0; 08711 } 08712 08713 /* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by: 08714 * 08715 * OtherRecipientInfo ::= SEQUENCE { 08716 * oriType OBJECT IDENTIFIER, 08717 * oriValue ANY DEFINED BY oriType } 08718 * 08719 * pkcs7 - pointer to initialized PKCS7 structure 08720 * pkiMsg - pointer to encoded CMS bundle 08721 * pkiMsgSz - size of pkiMsg, bytes 08722 * idx - [IN/OUT] pointer to index into pkiMsg 08723 * decryptedKey - [OUT] output buf for decrypted content encryption key 08724 * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key 08725 * recipFound - [OUT] 1 if recipient has been found, 0 if not 08726 * 08727 * Return 0 on success, negative upon error. 08728 */ 08729 static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, 08730 word32* idx, byte* decryptedKey, 08731 word32* decryptedKeySz, int* recipFound) 08732 { 08733 int ret, seqSz, oriOIDSz; 08734 word32 oriValueSz, tmpIdx; 08735 byte* oriValue; 08736 byte oriOID[MAX_OID_SZ]; 08737 08738 byte* pkiMsg = in; 08739 word32 pkiMsgSz = inSz; 08740 #ifndef NO_PKCS7_STREAM 08741 word32 stateIdx = *idx; 08742 long rc; 08743 #endif 08744 08745 if (pkcs7->oriDecryptCb == NULL) { 08746 WOLFSSL_MSG("You must register an ORI Decrypt callback"); 08747 return BAD_FUNC_ARG; 08748 } 08749 08750 switch (pkcs7->state) { 08751 08752 case WC_PKCS7_DECRYPT_ORI: 08753 #ifndef NO_PKCS7_STREAM 08754 /* @TODO for now just get full buffer, needs divided up */ 08755 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 08756 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + 08757 pkcs7->stream->length, &pkiMsg, idx)) != 0) { 08758 return ret; 08759 } 08760 08761 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 08762 inSz); 08763 if (rc < 0) { 08764 ret = (int)rc; 08765 break; 08766 } 08767 pkiMsgSz = (word32)rc; 08768 #endif 08769 /* get OtherRecipientInfo sequence length */ 08770 if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) 08771 return ASN_PARSE_E; 08772 08773 tmpIdx = *idx; 08774 08775 /* remove and store oriType OBJECT IDENTIFIER */ 08776 if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) 08777 return ASN_PARSE_E; 08778 08779 XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); 08780 *idx += oriOIDSz; 08781 08782 /* get oriValue, increment idx */ 08783 oriValue = pkiMsg + *idx; 08784 oriValueSz = seqSz - (*idx - tmpIdx); 08785 *idx += oriValueSz; 08786 08787 /* pass oriOID and oriValue to user callback, expect back 08788 decryptedKey and size */ 08789 ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, 08790 oriValueSz, decryptedKey, decryptedKeySz, 08791 pkcs7->oriDecryptCtx); 08792 08793 if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { 08794 /* decrypt operation failed */ 08795 *recipFound = 0; 08796 return PKCS7_RECIP_E; 08797 } 08798 08799 /* mark recipFound, since we only support one RecipientInfo for now */ 08800 *recipFound = 1; 08801 08802 #ifndef NO_PKCS7_STREAM 08803 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) { 08804 break; 08805 } 08806 #endif 08807 ret = 0; /* success */ 08808 break; 08809 08810 default: 08811 WOLFSSL_MSG("PKCS7 ORI unknown state"); 08812 ret = BAD_FUNC_ARG; 08813 08814 } 08815 08816 return ret; 08817 } 08818 08819 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 08820 08821 /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, 08822 * < 0 on error */ 08823 static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, 08824 word32* idx, byte* decryptedKey, 08825 word32* decryptedKeySz, int* recipFound) 08826 { 08827 byte* salt; 08828 byte* cek; 08829 byte* kek; 08830 08831 byte tmpIv[MAX_CONTENT_IV_SIZE]; 08832 08833 int ret = 0, length, saltSz, iterations, blockSz, kekKeySz; 08834 int hashOID = WC_SHA; /* default to SHA1 */ 08835 word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; 08836 byte* pkiMsg = in; 08837 word32 pkiMsgSz = inSz; 08838 byte tag; 08839 #ifndef NO_PKCS7_STREAM 08840 word32 tmpIdx = *idx; 08841 long rc; 08842 #endif 08843 08844 switch (pkcs7->state) { 08845 case WC_PKCS7_DECRYPT_PWRI: 08846 #ifndef NO_PKCS7_STREAM 08847 /*@TODO for now just get full buffer, needs divided up */ 08848 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 08849 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + 08850 pkcs7->stream->length, &pkiMsg, idx)) != 0) { 08851 return ret; 08852 } 08853 08854 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 08855 inSz); 08856 if (rc < 0) { 08857 ret = (int)rc; 08858 break; 08859 } 08860 pkiMsgSz = (word32)rc; 08861 #endif 08862 /* remove KeyDerivationAlgorithmIdentifier */ 08863 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08864 return ASN_PARSE_E; 08865 08866 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 08867 return ASN_PARSE_E; 08868 08869 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 08870 return ASN_PARSE_E; 08871 08872 /* get KeyDerivationAlgorithmIdentifier */ 08873 if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) 08874 return ASN_PARSE_E; 08875 08876 /* get KDF params SEQ */ 08877 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 08878 return ASN_PARSE_E; 08879 08880 /* get KDF salt OCTET STRING */ 08881 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 08882 return ASN_PARSE_E; 08883 08884 if (tag != ASN_OCTET_STRING) 08885 return ASN_PARSE_E; 08886 08887 if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) 08888 return ASN_PARSE_E; 08889 08890 salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08891 if (salt == NULL) 08892 return MEMORY_E; 08893 08894 XMEMCPY(salt, pkiMsg + (*idx), saltSz); 08895 *idx += saltSz; 08896 08897 /* get KDF iterations */ 08898 if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { 08899 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08900 return ASN_PARSE_E; 08901 } 08902 08903 /* get KeyEncAlgoId SEQ */ 08904 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { 08905 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08906 return ASN_PARSE_E; 08907 } 08908 08909 /* get KeyEncAlgoId */ 08910 if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { 08911 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08912 return ASN_PARSE_E; 08913 } 08914 08915 /* get pwriEncAlgoId */ 08916 if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { 08917 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08918 return ASN_PARSE_E; 08919 } 08920 08921 blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); 08922 if (blockSz < 0) { 08923 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08924 return blockSz; 08925 } 08926 08927 /* get content-encryption key size, based on algorithm */ 08928 kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId); 08929 if (kekKeySz < 0) { 08930 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08931 return kekKeySz; 08932 } 08933 08934 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 08935 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08936 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08937 return ASN_PARSE_E; 08938 } 08939 08940 if (tag != ASN_OCTET_STRING) { 08941 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08942 return ASN_PARSE_E; 08943 } 08944 08945 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 08946 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08947 return ASN_PARSE_E; 08948 } 08949 08950 if (length != blockSz) { 08951 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); 08952 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08953 return ASN_PARSE_E; 08954 } 08955 08956 XMEMCPY(tmpIv, pkiMsg + (*idx), length); 08957 *idx += length; 08958 08959 /* get EncryptedKey */ 08960 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { 08961 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08962 return ASN_PARSE_E; 08963 } 08964 08965 if (tag != ASN_OCTET_STRING) { 08966 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08967 return ASN_PARSE_E; 08968 } 08969 08970 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 08971 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08972 return ASN_PARSE_E; 08973 } 08974 08975 /* allocate temporary space for decrypted key */ 08976 cekSz = length; 08977 cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 08978 if (cek == NULL) { 08979 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08980 return MEMORY_E; 08981 } 08982 08983 /* generate KEK */ 08984 kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08985 if (kek == NULL) { 08986 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08987 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08988 return MEMORY_E; 08989 } 08990 08991 ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, 08992 salt, saltSz, kdfAlgoId, hashOID, 08993 iterations, kek, kekKeySz); 08994 if (ret < 0) { 08995 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08996 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08997 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 08998 return ASN_PARSE_E; 08999 } 09000 09001 /* decrypt CEK with KEK */ 09002 ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz, 09003 pkiMsg + (*idx), length, cek, 09004 cekSz, tmpIv, blockSz, 09005 pwriEncAlgoId); 09006 if (ret < 0) { 09007 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09008 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09009 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09010 return ret; 09011 } 09012 cekSz = ret; 09013 09014 if (*decryptedKeySz < cekSz) { 09015 WOLFSSL_MSG("Decrypted key buffer too small for CEK"); 09016 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09017 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09018 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09019 return BUFFER_E; 09020 } 09021 09022 XMEMCPY(decryptedKey, cek, cekSz); 09023 *decryptedKeySz = cekSz; 09024 09025 XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09026 XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09027 XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09028 09029 /* mark recipFound, since we only support one RecipientInfo for now */ 09030 *recipFound = 1; 09031 *idx += length; 09032 #ifndef NO_PKCS7_STREAM 09033 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09034 break; 09035 } 09036 #endif 09037 ret = 0; /* success */ 09038 break; 09039 09040 default: 09041 WOLFSSL_MSG("PKCS7 PWRI unknown state"); 09042 ret = BAD_FUNC_ARG; 09043 } 09044 09045 return ret; 09046 } 09047 09048 #endif /* NO_PWDBASED | NO_SHA */ 09049 09050 /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, 09051 * < 0 on error */ 09052 static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, 09053 word32* idx, byte* decryptedKey, 09054 word32* decryptedKeySz, int* recipFound) 09055 { 09056 int length, keySz, dateLen, direction; 09057 byte* keyId = NULL; 09058 const byte* datePtr = NULL; 09059 byte dateFormat, tag; 09060 word32 keyIdSz, kekIdSz, keyWrapOID, localIdx; 09061 09062 int ret = 0; 09063 byte* pkiMsg = in; 09064 word32 pkiMsgSz = inSz; 09065 #ifndef NO_PKCS7_STREAM 09066 word32 tmpIdx = *idx; 09067 long rc; 09068 #endif 09069 09070 WOLFSSL_ENTER("wc_PKCS7_DecryptKekri"); 09071 switch (pkcs7->state) { 09072 case WC_PKCS7_DECRYPT_KEKRI: 09073 #ifndef NO_PKCS7_STREAM 09074 /* @TODO for now just get full buffer, needs divided up */ 09075 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 09076 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + 09077 pkcs7->stream->length, &pkiMsg, idx)) != 0) { 09078 return ret; 09079 } 09080 09081 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 09082 inSz); 09083 if (rc < 0) { 09084 ret = (int)rc; 09085 break; 09086 } 09087 pkiMsgSz = (word32)rc; 09088 #endif 09089 /* remove KEKIdentifier */ 09090 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 09091 return ASN_PARSE_E; 09092 09093 kekIdSz = length; 09094 09095 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 09096 return ASN_PARSE_E; 09097 09098 if (tag != ASN_OCTET_STRING) 09099 return ASN_PARSE_E; 09100 09101 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 09102 return ASN_PARSE_E; 09103 09104 /* save keyIdentifier and length */ 09105 keyId = pkiMsg + *idx; 09106 keyIdSz = length; 09107 *idx += keyIdSz; 09108 09109 /* may have OPTIONAL GeneralizedTime */ 09110 localIdx = *idx; 09111 if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, 09112 pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) { 09113 if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, 09114 &dateLen) != 0) { 09115 return ASN_PARSE_E; 09116 } 09117 *idx += (dateLen + 1); 09118 } 09119 09120 /* may have OPTIONAL OtherKeyAttribute */ 09121 localIdx = *idx; 09122 if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, 09123 pkiMsgSz) == 0 && tag == (ASN_SEQUENCE | 09124 ASN_CONSTRUCTED)) { 09125 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 09126 return ASN_PARSE_E; 09127 09128 /* skip it */ 09129 *idx += length; 09130 } 09131 09132 /* get KeyEncryptionAlgorithmIdentifier */ 09133 if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) 09134 return ASN_PARSE_E; 09135 09136 /* get EncryptedKey */ 09137 if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) 09138 return ASN_PARSE_E; 09139 09140 if (tag != ASN_OCTET_STRING) 09141 return ASN_PARSE_E; 09142 09143 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 09144 return ASN_PARSE_E; 09145 09146 #ifndef NO_AES 09147 direction = AES_DECRYPTION; 09148 #else 09149 direction = DES_DECRYPTION; 09150 #endif 09151 09152 /* decrypt CEK with KEK */ 09153 if (pkcs7->wrapCEKCb) { 09154 keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, length, keyId, 09155 keyIdSz, NULL, 0, decryptedKey, 09156 *decryptedKeySz, keyWrapOID, 09157 (int)PKCS7_KEKRI, direction); 09158 } 09159 else { 09160 keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, 09161 pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, 09162 keyWrapOID, direction); 09163 } 09164 if (keySz <= 0) 09165 return keySz; 09166 09167 *decryptedKeySz = (word32)keySz; 09168 09169 /* mark recipFound, since we only support one RecipientInfo for now */ 09170 *recipFound = 1; 09171 *idx += length; 09172 09173 #ifndef NO_PKCS7_STREAM 09174 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09175 break; 09176 } 09177 #endif 09178 ret = 0; /* success */ 09179 break; 09180 09181 default: 09182 WOLFSSL_MSG("PKCS7 KEKRI unknown state"); 09183 ret = BAD_FUNC_ARG; 09184 09185 } 09186 09187 (void)keyId; 09188 return ret; 09189 } 09190 09191 09192 /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, 09193 * < 0 on error */ 09194 static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, 09195 word32* idx, byte* decryptedKey, 09196 word32* decryptedKeySz, int* recipFound) 09197 { 09198 #ifdef HAVE_ECC 09199 int ret, keySz; 09200 int encryptedKeySz; 09201 int direction = 0; 09202 word32 keyAgreeOID, keyWrapOID; 09203 byte rid[KEYID_SIZE]; 09204 09205 #ifdef WOLFSSL_SMALL_STACK 09206 byte* encryptedKey; 09207 #else 09208 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 09209 #endif 09210 09211 byte* pkiMsg = in; 09212 word32 pkiMsgSz = inSz; 09213 #ifndef NO_PKCS7_STREAM 09214 word32 tmpIdx = (idx) ? *idx : 0; 09215 long rc; 09216 #endif 09217 09218 WOLFSSL_ENTER("wc_PKCS7_DecryptKari"); 09219 if (pkcs7 == NULL || pkiMsg == NULL || 09220 ((pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) && 09221 pkcs7->wrapCEKCb == NULL) || 09222 idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { 09223 return BAD_FUNC_ARG; 09224 } 09225 09226 switch (pkcs7->state) { 09227 case WC_PKCS7_DECRYPT_KARI: { 09228 #ifndef NO_PKCS7_STREAM 09229 /* @TODO for now just get full buffer, needs divided up */ 09230 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 09231 (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + 09232 pkcs7->stream->length, &pkiMsg, idx)) != 0) { 09233 return ret; 09234 } 09235 09236 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 09237 inSz); 09238 if (rc < 0) { 09239 ret = (int)rc; 09240 break; 09241 } 09242 pkiMsgSz = (word32)rc; 09243 #endif 09244 WC_PKCS7_KARI* kari; 09245 09246 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); 09247 if (kari == NULL) 09248 return MEMORY_E; 09249 09250 #ifdef WOLFSSL_SMALL_STACK 09251 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 09252 DYNAMIC_TYPE_PKCS7); 09253 if (encryptedKey == NULL) { 09254 wc_PKCS7_KariFree(kari); 09255 return MEMORY_E; 09256 } 09257 #endif 09258 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 09259 09260 /* parse cert and key */ 09261 if (pkcs7->singleCert != NULL) { 09262 ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, 09263 pkcs7->singleCertSz, pkcs7->privateKey, 09264 pkcs7->privateKeySz); 09265 if (ret != 0) { 09266 wc_PKCS7_KariFree(kari); 09267 #ifdef WOLFSSL_SMALL_STACK 09268 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09269 #endif 09270 return ret; 09271 } 09272 } 09273 09274 /* remove OriginatorIdentifierOrKey */ 09275 ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, 09276 pkiMsgSz, idx); 09277 if (ret != 0) { 09278 wc_PKCS7_KariFree(kari); 09279 #ifdef WOLFSSL_SMALL_STACK 09280 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09281 #endif 09282 return ret; 09283 } 09284 09285 /* try and remove optional UserKeyingMaterial */ 09286 ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); 09287 if (ret != 0) { 09288 wc_PKCS7_KariFree(kari); 09289 #ifdef WOLFSSL_SMALL_STACK 09290 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09291 #endif 09292 return ret; 09293 } 09294 09295 /* remove KeyEncryptionAlgorithmIdentifier */ 09296 ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, 09297 pkiMsgSz, idx, &keyAgreeOID, &keyWrapOID); 09298 if (ret != 0) { 09299 wc_PKCS7_KariFree(kari); 09300 #ifdef WOLFSSL_SMALL_STACK 09301 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09302 #endif 09303 return ret; 09304 } 09305 09306 /* if user has not explicitly set keyAgreeOID, set from one in bundle */ 09307 if (pkcs7->keyAgreeOID == 0) 09308 pkcs7->keyAgreeOID = keyAgreeOID; 09309 09310 /* set direction based on key wrap algorithm */ 09311 switch (keyWrapOID) { 09312 #ifndef NO_AES 09313 #ifdef WOLFSSL_AES_128 09314 case AES128_WRAP: 09315 #endif 09316 #ifdef WOLFSSL_AES_192 09317 case AES192_WRAP: 09318 #endif 09319 #ifdef WOLFSSL_AES_256 09320 case AES256_WRAP: 09321 #endif 09322 direction = AES_DECRYPTION; 09323 break; 09324 #endif 09325 default: 09326 WOLFSSL_MSG("AES key wrap algorithm unsupported"); 09327 if (pkcs7->wrapCEKCb) { 09328 WOLFSSL_MSG("Direction not set!"); 09329 break; /* if unwrapping callback is set then do not 09330 * force restriction of supported wrap 09331 * algorithms */ 09332 } 09333 09334 wc_PKCS7_KariFree(kari); 09335 #ifdef WOLFSSL_SMALL_STACK 09336 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09337 #endif 09338 return BAD_KEYWRAP_ALG_E; 09339 } 09340 09341 /* remove RecipientEncryptedKeys */ 09342 ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, 09343 idx, recipFound, encryptedKey, &encryptedKeySz, rid); 09344 if (ret != 0) { 09345 wc_PKCS7_KariFree(kari); 09346 #ifdef WOLFSSL_SMALL_STACK 09347 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09348 #endif 09349 return ret; 09350 } 09351 09352 /* decrypt CEK with KEK */ 09353 if (pkcs7->wrapCEKCb) { 09354 word32 tmpKeySz = 0; 09355 byte* tmpKeyDer = NULL; 09356 09357 ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz); 09358 if (ret != LENGTH_ONLY_E) { 09359 return ret; 09360 } 09361 09362 /* buffer space for algorithm/curve */ 09363 tmpKeySz += MAX_SEQ_SZ; 09364 tmpKeySz += 2 * MAX_ALGO_SZ; 09365 09366 /* buffer space for public key sequence */ 09367 tmpKeySz += MAX_SEQ_SZ; 09368 tmpKeySz += TRAILING_ZERO; 09369 09370 tmpKeyDer = (byte*)XMALLOC(tmpKeySz, pkcs7->heap, 09371 DYNAMIC_TYPE_TMP_BUFFER); 09372 if (tmpKeyDer == NULL) { 09373 return MEMORY_E; 09374 } 09375 09376 ret = wc_EccPublicKeyToDer(kari->senderKey, tmpKeyDer, 09377 tmpKeySz, 1); 09378 if (ret < 0) { 09379 XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 09380 return ret; 09381 } 09382 tmpKeySz = (word32)ret; 09383 09384 keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz, 09385 rid, KEYID_SIZE, tmpKeyDer, tmpKeySz, 09386 decryptedKey, *decryptedKeySz, 09387 keyWrapOID, (int)PKCS7_KARI, direction); 09388 XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 09389 09390 if (keySz > 0) { 09391 /* If unwrapping was successful then consider recipient 09392 * found. Checking for NULL singleCert to confirm previous 09393 * SID check was not done */ 09394 if (pkcs7->singleCert == NULL) 09395 *recipFound = 1; 09396 } 09397 } 09398 else { 09399 /* create KEK */ 09400 ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); 09401 if (ret != 0) { 09402 wc_PKCS7_KariFree(kari); 09403 #ifdef WOLFSSL_SMALL_STACK 09404 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09405 #endif 09406 return ret; 09407 } 09408 09409 /* decrypt CEK with KEK */ 09410 keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, 09411 kari->kekSz, decryptedKey, *decryptedKeySz, 09412 keyWrapOID, direction); 09413 } 09414 if (keySz <= 0) { 09415 wc_PKCS7_KariFree(kari); 09416 #ifdef WOLFSSL_SMALL_STACK 09417 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09418 #endif 09419 return keySz; 09420 } 09421 *decryptedKeySz = (word32)keySz; 09422 09423 wc_PKCS7_KariFree(kari); 09424 #ifdef WOLFSSL_SMALL_STACK 09425 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09426 #endif 09427 #ifndef NO_PKCS7_STREAM 09428 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09429 break; 09430 } 09431 #endif 09432 ret = 0; /* success */ 09433 } 09434 break; 09435 09436 default: 09437 WOLFSSL_MSG("PKCS7 kari unknown state"); 09438 ret = BAD_FUNC_ARG; 09439 09440 } 09441 09442 (void)pkiMsg; 09443 (void)pkiMsgSz; 09444 09445 return ret; 09446 #else 09447 (void)in; 09448 (void)inSz; 09449 (void)pkcs7; 09450 (void)idx; 09451 (void)decryptedKey; 09452 (void)decryptedKeySz; 09453 (void)recipFound; 09454 09455 return NOT_COMPILED_IN; 09456 #endif /* HAVE_ECC */ 09457 } 09458 09459 09460 /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ 09461 static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, 09462 word32 inSz, word32* idx, byte* decryptedKey, 09463 word32* decryptedKeySz, int* recipFound) 09464 { 09465 word32 savedIdx; 09466 int version, ret = 0, length; 09467 byte* pkiMsg = in; 09468 word32 pkiMsgSz = inSz; 09469 byte tag; 09470 #ifndef NO_PKCS7_STREAM 09471 word32 tmpIdx; 09472 long rc; 09473 #endif 09474 09475 if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || 09476 decryptedKey == NULL || decryptedKeySz == NULL || 09477 recipFound == NULL) { 09478 return BAD_FUNC_ARG; 09479 } 09480 09481 WOLFSSL_ENTER("wc_PKCS7_DecryptRecipientInfos"); 09482 #ifndef NO_PKCS7_STREAM 09483 tmpIdx = *idx; 09484 #endif 09485 09486 /* check if in the process of decrypting */ 09487 switch (pkcs7->state) { 09488 case WC_PKCS7_DECRYPT_KTRI: 09489 case WC_PKCS7_DECRYPT_KTRI_2: 09490 case WC_PKCS7_DECRYPT_KTRI_3: 09491 #ifndef NO_RSA 09492 ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, 09493 decryptedKey, decryptedKeySz, recipFound); 09494 #else 09495 return NOT_COMPILED_IN; 09496 #endif 09497 break; 09498 09499 case WC_PKCS7_DECRYPT_KARI: 09500 ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, 09501 decryptedKey, decryptedKeySz, recipFound); 09502 break; 09503 09504 case WC_PKCS7_DECRYPT_KEKRI: 09505 ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, 09506 decryptedKey, decryptedKeySz, recipFound); 09507 break; 09508 09509 case WC_PKCS7_DECRYPT_PWRI: 09510 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 09511 ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, 09512 decryptedKey, decryptedKeySz, recipFound); 09513 #else 09514 return NOT_COMPILED_IN; 09515 #endif 09516 break; 09517 09518 case WC_PKCS7_DECRYPT_ORI: 09519 ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, 09520 decryptedKey, decryptedKeySz, recipFound); 09521 break; 09522 09523 default: 09524 /* not in decrypting state */ 09525 break; 09526 } 09527 09528 if (ret < 0) { 09529 return ret; 09530 } 09531 09532 savedIdx = *idx; 09533 #ifndef NO_PKCS7_STREAM 09534 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); 09535 if (rc < 0) { 09536 return (int)rc; 09537 } 09538 pkiMsgSz = (word32)rc; 09539 if (pkcs7->stream->length > 0) 09540 pkiMsg = pkcs7->stream->buffer; 09541 #endif 09542 09543 /* when looking for next recipient, use first sequence and version to 09544 * indicate there is another, if not, move on */ 09545 while(*recipFound == 0) { 09546 09547 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to 09548 * last good saved one */ 09549 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) { 09550 09551 #ifndef NO_RSA 09552 /* found ktri */ 09553 #ifndef NO_PKCS7_STREAM 09554 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09555 break; 09556 } 09557 #endif 09558 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI); 09559 ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, 09560 decryptedKey, decryptedKeySz, 09561 recipFound); 09562 if (ret != 0) 09563 return ret; 09564 #else 09565 return NOT_COMPILED_IN; 09566 #endif 09567 } 09568 else { 09569 word32 localIdx; 09570 /* kari is IMPLICIT[1] */ 09571 *idx = savedIdx; 09572 localIdx = *idx; 09573 09574 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) { 09575 /* no room for recipient info */ 09576 break; 09577 } 09578 09579 if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 09580 (*idx)++; 09581 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 09582 return ASN_PARSE_E; 09583 09584 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { 09585 *idx = savedIdx; 09586 break; 09587 } 09588 09589 if (version != 3) 09590 return ASN_VERSION_E; 09591 09592 /* found kari */ 09593 #ifndef NO_PKCS7_STREAM 09594 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09595 break; 09596 } 09597 #endif 09598 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI); 09599 ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, 09600 decryptedKey, decryptedKeySz, 09601 recipFound); 09602 if (ret != 0) 09603 return ret; 09604 09605 /* kekri is IMPLICIT[2] */ 09606 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) { 09607 (*idx)++; 09608 09609 if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) 09610 return ASN_PARSE_E; 09611 09612 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { 09613 *idx = savedIdx; 09614 break; 09615 } 09616 09617 if (version != 4) 09618 return ASN_VERSION_E; 09619 09620 /* found kekri */ 09621 #ifndef NO_PKCS7_STREAM 09622 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09623 break; 09624 } 09625 #endif 09626 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI); 09627 ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, 09628 decryptedKey, decryptedKeySz, 09629 recipFound); 09630 if (ret != 0) 09631 return ret; 09632 09633 /* pwri is IMPLICIT[3] */ 09634 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) { 09635 #if !defined(NO_PWDBASED) && !defined(NO_SHA) 09636 (*idx)++; 09637 09638 if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) 09639 return ASN_PARSE_E; 09640 09641 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { 09642 *idx = savedIdx; 09643 break; 09644 } 09645 09646 if (version != 0) 09647 return ASN_VERSION_E; 09648 09649 /* found pwri */ 09650 #ifndef NO_PKCS7_STREAM 09651 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09652 break; 09653 } 09654 #endif 09655 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI); 09656 ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, 09657 decryptedKey, decryptedKeySz, 09658 recipFound); 09659 if (ret != 0) 09660 return ret; 09661 #else 09662 return NOT_COMPILED_IN; 09663 #endif 09664 09665 /* ori is IMPLICIT[4] */ 09666 } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 4)) { 09667 (*idx)++; 09668 09669 /* found ori */ 09670 #ifndef NO_PKCS7_STREAM 09671 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09672 break; 09673 } 09674 #endif 09675 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI); 09676 ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, 09677 decryptedKey, decryptedKeySz, 09678 recipFound); 09679 if (ret != 0) 09680 return ret; 09681 09682 } else { 09683 /* failed to find RecipientInfo, restore idx and continue */ 09684 *idx = savedIdx; 09685 break; 09686 } 09687 } 09688 09689 /* update good idx */ 09690 savedIdx = *idx; 09691 } 09692 09693 return ret; 09694 } 09695 09696 09697 /* Parse encoded EnvelopedData bundle up to RecipientInfo set. 09698 * 09699 * return size of RecipientInfo SET on success, negative upon error */ 09700 static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, 09701 word32 inSz, word32* idx, 09702 int type) 09703 { 09704 int version = 0, length, ret = 0; 09705 word32 contentType; 09706 byte* pkiMsg = in; 09707 word32 pkiMsgSz = inSz; 09708 byte tag; 09709 #ifndef NO_PKCS7_STREAM 09710 word32 tmpIdx = 0; 09711 long rc; 09712 #endif 09713 09714 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) 09715 return BAD_FUNC_ARG; 09716 09717 if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) && 09718 pkcs7->contentOID != FIRMWARE_PKG_DATA) 09719 return BAD_FUNC_ARG; 09720 09721 #ifndef NO_PKCS7_STREAM 09722 if (pkcs7->stream == NULL) { 09723 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { 09724 return ret; 09725 } 09726 } 09727 #endif 09728 09729 switch (pkcs7->state) { 09730 case WC_PKCS7_INFOSET_START: 09731 case WC_PKCS7_INFOSET_BER: 09732 case WC_PKCS7_INFOSET_STAGE1: 09733 case WC_PKCS7_INFOSET_STAGE2: 09734 case WC_PKCS7_INFOSET_END: 09735 break; 09736 09737 default: 09738 WOLFSSL_MSG("Warning, setting PKCS7 info state to start"); 09739 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START); 09740 } 09741 09742 switch (pkcs7->state) { 09743 case WC_PKCS7_INFOSET_START: 09744 #ifndef NO_PKCS7_STREAM 09745 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + 09746 ASN_TAG_SZ, &pkiMsg, idx)) != 0) { 09747 return ret; 09748 } 09749 09750 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); 09751 if (rc < 0) { 09752 ret = (int)rc; 09753 break; 09754 } 09755 pkiMsgSz = (word32)rc; 09756 #endif 09757 /* read past ContentInfo, verify type is envelopedData */ 09758 if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 09759 { 09760 ret = ASN_PARSE_E; 09761 } 09762 09763 if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) { 09764 #ifdef ASN_BER_TO_DER 09765 word32 len; 09766 09767 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER); 09768 FALL_THROUGH; 09769 09770 /* full buffer is needed for conversion */ 09771 case WC_PKCS7_INFOSET_BER: 09772 #ifndef NO_PKCS7_STREAM 09773 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 09774 pkcs7->stream->maxLen - pkcs7->stream->length, 09775 &pkiMsg, idx)) != 0) { 09776 return ret; 09777 } 09778 09779 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 09780 in, inSz); 09781 if (rc < 0) { 09782 ret = (int)rc; 09783 break; 09784 } 09785 pkiMsgSz = (word32)rc; 09786 #endif 09787 09788 len = 0; 09789 09790 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); 09791 if (ret != LENGTH_ONLY_E) 09792 return ret; 09793 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 09794 if (pkcs7->der == NULL) 09795 return MEMORY_E; 09796 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); 09797 if (ret < 0) 09798 return ret; 09799 09800 pkiMsg = in = pkcs7->der; 09801 pkiMsgSz = pkcs7->derSz = len; 09802 *idx = 0; 09803 09804 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 09805 return ASN_PARSE_E; 09806 #else 09807 return BER_INDEF_E; 09808 #endif 09809 } 09810 #ifndef NO_PKCS7_STREAM 09811 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09812 break; 09813 } 09814 #endif 09815 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1); 09816 FALL_THROUGH; 09817 09818 case WC_PKCS7_INFOSET_STAGE1: 09819 #ifndef NO_PKCS7_STREAM 09820 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + 09821 MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { 09822 return ret; 09823 } 09824 09825 pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; 09826 #endif 09827 if (pkcs7->contentOID != FIRMWARE_PKG_DATA || 09828 type == AUTH_ENVELOPED_DATA) { 09829 if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, 09830 pkiMsgSz) < 0) 09831 ret = ASN_PARSE_E; 09832 09833 if (ret == 0) { 09834 if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { 09835 WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); 09836 ret = PKCS7_OID_E; 09837 } else if (type == AUTH_ENVELOPED_DATA && 09838 contentType != AUTH_ENVELOPED_DATA) { 09839 WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); 09840 ret = PKCS7_OID_E; 09841 } 09842 } 09843 09844 if (ret == 0 && GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) != 0) 09845 ret = ASN_PARSE_E; 09846 09847 if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC 09848 | 0)) 09849 ret = ASN_PARSE_E; 09850 09851 if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz, 09852 NO_USER_CHECK) < 0) 09853 ret = ASN_PARSE_E; 09854 } 09855 09856 if (ret < 0) 09857 break; 09858 09859 #ifndef NO_PKCS7_STREAM 09860 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09861 break; 09862 } 09863 #endif 09864 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2); 09865 FALL_THROUGH; 09866 09867 case WC_PKCS7_INFOSET_STAGE2: 09868 #ifndef NO_PKCS7_STREAM 09869 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + 09870 MAX_VERSION_SZ, &pkiMsg, idx)) != 0) { 09871 return ret; 09872 } 09873 09874 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 09875 inSz); 09876 if (rc < 0) { 09877 ret = (int)rc; 09878 break; 09879 } 09880 pkiMsgSz = (word32)rc; 09881 #endif 09882 /* remove EnvelopedData and version */ 09883 if (pkcs7->contentOID != FIRMWARE_PKG_DATA || 09884 type == AUTH_ENVELOPED_DATA) { 09885 if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 09886 ret = ASN_PARSE_E; 09887 } 09888 09889 if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) 09890 ret = ASN_PARSE_E; 09891 09892 if (ret < 0) 09893 break; 09894 09895 #ifndef NO_PKCS7_STREAM 09896 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09897 break; 09898 } 09899 09900 pkcs7->stream->varOne = version; 09901 #endif 09902 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END); 09903 FALL_THROUGH; 09904 09905 case WC_PKCS7_INFOSET_END: 09906 #ifndef NO_PKCS7_STREAM 09907 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 09908 MAX_SET_SZ, &pkiMsg, idx)) != 0) { 09909 return ret; 09910 } 09911 09912 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 09913 inSz); 09914 if (rc < 0) { 09915 ret = (int)rc; 09916 break; 09917 } 09918 pkiMsgSz = (word32)rc; 09919 version = pkcs7->stream->varOne; 09920 #endif 09921 09922 if (type == ENVELOPED_DATA) { 09923 /* TODO :: make this more accurate */ 09924 if ((pkcs7->publicKeyOID == RSAk && 09925 (version != 0 && version != 2)) 09926 #ifdef HAVE_ECC 09927 || (pkcs7->publicKeyOID == ECDSAk && 09928 (version != 0 && version != 2 && version != 3)) 09929 #endif 09930 ) { 09931 WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); 09932 ret = ASN_VERSION_E; 09933 } 09934 } else { 09935 /* AuthEnvelopedData version MUST be 0 */ 09936 if (version != 0) { 09937 WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); 09938 ret = ASN_VERSION_E; 09939 } 09940 } 09941 09942 /* remove RecipientInfo set, get length of set */ 09943 if (ret == 0 && GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) 09944 ret = ASN_PARSE_E; 09945 09946 if (ret < 0) 09947 break; 09948 09949 #ifndef NO_PKCS7_STREAM 09950 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { 09951 break; 09952 } 09953 #endif 09954 09955 if (ret == 0) 09956 ret = length; 09957 09958 break; 09959 09960 default: 09961 WOLFSSL_MSG("Bad PKCS7 info set state"); 09962 ret = BAD_FUNC_ARG; 09963 break; 09964 } 09965 09966 return ret; 09967 } 09968 09969 09970 /* Import secret/private key into a PKCS7 structure. Used for setting 09971 * the secret key for decryption a EnvelopedData KEKRI RecipientInfo. 09972 * 09973 * Returns 0 on success, negative upon error */ 09974 WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz) 09975 { 09976 if (pkcs7 == NULL || key == NULL || keySz == 0) 09977 return BAD_FUNC_ARG; 09978 09979 pkcs7->privateKey = key; 09980 pkcs7->privateKeySz = keySz; 09981 09982 return 0; 09983 } 09984 09985 09986 /* append data to encrypted content cache in PKCS7 structure 09987 * return 0 on success, negative on error */ 09988 static int PKCS7_CacheEncryptedContent(PKCS7* pkcs7, byte* in, word32 inSz) 09989 { 09990 byte* oldCache; 09991 word32 oldCacheSz; 09992 09993 if (pkcs7 == NULL || in == NULL) 09994 return BAD_FUNC_ARG; 09995 09996 /* save pointer to old cache */ 09997 oldCache = pkcs7->cachedEncryptedContent; 09998 oldCacheSz = pkcs7->cachedEncryptedContentSz; 09999 10000 /* re-allocate new buffer to fit appended data */ 10001 pkcs7->cachedEncryptedContent = (byte*)XMALLOC(oldCacheSz + inSz, 10002 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10003 if (pkcs7->cachedEncryptedContent == NULL) { 10004 pkcs7->cachedEncryptedContentSz = 0; 10005 XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10006 return MEMORY_E; 10007 } 10008 10009 if (oldCache != NULL) { 10010 XMEMCPY(pkcs7->cachedEncryptedContent, oldCache, oldCacheSz); 10011 } 10012 XMEMCPY(pkcs7->cachedEncryptedContent + oldCacheSz, in, inSz); 10013 pkcs7->cachedEncryptedContentSz += inSz; 10014 10015 XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10016 10017 return 0; 10018 } 10019 10020 10021 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ 10022 WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, 10023 word32 inSz, byte* output, 10024 word32 outputSz) 10025 { 10026 int recipFound = 0; 10027 int ret, length = 0; 10028 word32 idx = 0; 10029 #ifndef NO_PKCS7_STREAM 10030 word32 tmpIdx = 0; 10031 long rc; 10032 #endif 10033 word32 contentType, encOID = 0; 10034 word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 10035 10036 int expBlockSz = 0, blockKeySz = 0; 10037 byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; 10038 byte* tmpIv = tmpIvBuf; 10039 10040 byte* pkiMsg = in; 10041 word32 pkiMsgSz = inSz; 10042 byte* decryptedKey = NULL; 10043 int encryptedContentTotalSz = 0; 10044 int encryptedContentSz = 0; 10045 byte padLen; 10046 byte* encryptedContent = NULL; 10047 int explicitOctet = 0; 10048 word32 localIdx; 10049 byte tag; 10050 10051 if (pkcs7 == NULL) 10052 return BAD_FUNC_ARG; 10053 10054 if (pkiMsg == NULL || pkiMsgSz == 0 || 10055 output == NULL || outputSz == 0) 10056 return BAD_FUNC_ARG; 10057 10058 #ifndef NO_PKCS7_STREAM 10059 (void)tmpIv; /* help out static analysis */ 10060 if (pkcs7->stream == NULL) { 10061 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { 10062 return ret; 10063 } 10064 } 10065 #endif 10066 10067 switch (pkcs7->state) { 10068 case WC_PKCS7_START: 10069 case WC_PKCS7_INFOSET_START: 10070 case WC_PKCS7_INFOSET_BER: 10071 case WC_PKCS7_INFOSET_STAGE1: 10072 case WC_PKCS7_INFOSET_STAGE2: 10073 case WC_PKCS7_INFOSET_END: 10074 ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, 10075 &idx, ENVELOPED_DATA); 10076 if (ret < 0) { 10077 break; 10078 } 10079 10080 #ifdef ASN_BER_TO_DER 10081 /* check if content was BER and has been converted to DER */ 10082 if (pkcs7->derSz > 0) 10083 pkiMsg = in = pkcs7->der; 10084 #endif 10085 10086 decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 10087 DYNAMIC_TYPE_PKCS7); 10088 if (decryptedKey == NULL) 10089 return MEMORY_E; 10090 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2); 10091 #ifndef NO_PKCS7_STREAM 10092 tmpIdx = idx; 10093 pkcs7->stream->aad = decryptedKey; 10094 #endif 10095 FALL_THROUGH; 10096 10097 case WC_PKCS7_ENV_2: 10098 #ifndef NO_PKCS7_STREAM 10099 /* store up enough buffer for initial info set decode */ 10100 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 10101 MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { 10102 return ret; 10103 } 10104 #endif 10105 FALL_THROUGH; 10106 10107 case WC_PKCS7_DECRYPT_KTRI: 10108 case WC_PKCS7_DECRYPT_KTRI_2: 10109 case WC_PKCS7_DECRYPT_KTRI_3: 10110 case WC_PKCS7_DECRYPT_KARI: 10111 case WC_PKCS7_DECRYPT_KEKRI: 10112 case WC_PKCS7_DECRYPT_PWRI: 10113 case WC_PKCS7_DECRYPT_ORI: 10114 #ifndef NO_PKCS7_STREAM 10115 decryptedKey = pkcs7->stream->aad; 10116 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 10117 #endif 10118 10119 ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, 10120 decryptedKey, &decryptedKeySz, 10121 &recipFound); 10122 if (ret == 0 && recipFound == 0) { 10123 WOLFSSL_MSG("No recipient found in envelopedData that matches input"); 10124 ret = PKCS7_RECIP_E; 10125 } 10126 10127 if (ret != 0) 10128 break; 10129 #ifndef NO_PKCS7_STREAM 10130 tmpIdx = idx; 10131 pkcs7->stream->aadSz = decryptedKeySz; 10132 #endif 10133 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3); 10134 FALL_THROUGH; 10135 10136 case WC_PKCS7_ENV_3: 10137 10138 #ifndef NO_PKCS7_STREAM 10139 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 10140 MAX_VERSION_SZ + ASN_TAG_SZ + 10141 MAX_LENGTH_SZ, &pkiMsg, &idx)) 10142 != 0) { 10143 return ret; 10144 } 10145 10146 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 10147 inSz); 10148 if (rc < 0) { 10149 ret = (int)rc; 10150 break; 10151 } 10152 pkiMsgSz = (word32)rc; 10153 #else 10154 ret = 0; 10155 #endif 10156 10157 /* remove EncryptedContentInfo */ 10158 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 10159 ret = ASN_PARSE_E; 10160 } 10161 10162 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, 10163 pkiMsgSz) < 0) { 10164 ret = ASN_PARSE_E; 10165 } 10166 10167 if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, 10168 pkiMsgSz) < 0) { 10169 ret = ASN_PARSE_E; 10170 } 10171 10172 blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); 10173 if (ret == 0 && blockKeySz < 0) { 10174 ret = blockKeySz; 10175 } 10176 10177 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); 10178 if (ret == 0 && expBlockSz < 0) { 10179 ret = expBlockSz; 10180 } 10181 10182 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 10183 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) != 0) { 10184 ret = ASN_PARSE_E; 10185 } 10186 10187 if (ret == 0 && tag != ASN_OCTET_STRING) { 10188 ret = ASN_PARSE_E; 10189 } 10190 10191 if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 10192 ret = ASN_PARSE_E; 10193 } 10194 10195 if (ret == 0 && length != expBlockSz) { 10196 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); 10197 ret = ASN_PARSE_E; 10198 } 10199 10200 if (ret != 0) 10201 break; 10202 #ifndef NO_PKCS7_STREAM 10203 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 10204 break; 10205 } 10206 wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length); 10207 pkcs7->stream->contentSz = blockKeySz; 10208 pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 10209 ASN_TAG_SZ + ASN_TAG_SZ; 10210 #endif 10211 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4); 10212 FALL_THROUGH; 10213 10214 case WC_PKCS7_ENV_4: 10215 10216 #ifndef NO_PKCS7_STREAM 10217 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 10218 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 10219 return ret; 10220 } 10221 10222 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 10223 inSz); 10224 if (rc < 0) { 10225 ret = (int)rc; 10226 break; 10227 } 10228 pkiMsgSz = (word32)rc; 10229 10230 wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); 10231 tmpIv = pkcs7->stream->tmpIv; 10232 if (tmpIv == NULL) { 10233 /* check added to help out static analysis tool */ 10234 ret = MEMORY_E; 10235 break; 10236 } 10237 #else 10238 ret = 0; 10239 #endif 10240 10241 XMEMCPY(tmpIv, &pkiMsg[idx], length); 10242 idx += length; 10243 10244 explicitOctet = 0; 10245 localIdx = idx; 10246 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && 10247 tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { 10248 explicitOctet = 1; 10249 } 10250 10251 /* read encryptedContent, cont[0] */ 10252 if (tag != (ASN_CONTEXT_SPECIFIC | 0) && 10253 tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { 10254 ret = ASN_PARSE_E; 10255 } 10256 idx++; 10257 10258 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentTotalSz, 10259 pkiMsgSz) <= 0) { 10260 ret = ASN_PARSE_E; 10261 } 10262 10263 if (ret != 0) 10264 break; 10265 10266 #ifndef NO_PKCS7_STREAM 10267 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 10268 break; 10269 } 10270 pkcs7->stream->expected = encryptedContentTotalSz; 10271 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0); 10272 wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, explicitOctet); 10273 #endif 10274 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5); 10275 FALL_THROUGH; 10276 10277 case WC_PKCS7_ENV_5: 10278 10279 #ifndef NO_PKCS7_STREAM 10280 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 10281 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 10282 return ret; 10283 } 10284 10285 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &explicitOctet); 10286 tmpIv = pkcs7->stream->tmpIv; 10287 encryptedContentTotalSz = pkcs7->stream->expected; 10288 10289 /* restore decrypted key */ 10290 decryptedKey = pkcs7->stream->aad; 10291 decryptedKeySz = pkcs7->stream->aadSz; 10292 blockKeySz = pkcs7->stream->contentSz; 10293 #else 10294 ret = 0; 10295 #endif 10296 10297 if (explicitOctet) { 10298 /* encrypted content may be fragmented into multiple 10299 * consecutive OCTET STRINGs, if so loop through 10300 * collecting and caching encrypted content bytes */ 10301 localIdx = idx; 10302 while (idx < (localIdx + encryptedContentTotalSz)) { 10303 10304 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { 10305 ret = ASN_PARSE_E; 10306 } 10307 10308 if (ret == 0 && (tag != ASN_OCTET_STRING)) { 10309 ret = ASN_PARSE_E; 10310 } 10311 10312 if (ret == 0 && GetLength(pkiMsg, &idx, 10313 &encryptedContentSz, pkiMsgSz) <= 0) { 10314 ret = ASN_PARSE_E; 10315 } 10316 10317 if (ret == 0) { 10318 ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], 10319 encryptedContentSz); 10320 } 10321 10322 if (ret != 0) { 10323 break; 10324 } 10325 10326 /* advance idx past encrypted content */ 10327 idx += encryptedContentSz; 10328 } 10329 10330 if (ret != 0) { 10331 break; 10332 } 10333 10334 } else { 10335 /* cache encrypted content, no OCTET STRING */ 10336 ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], 10337 encryptedContentTotalSz); 10338 if (ret != 0) { 10339 break; 10340 } 10341 idx += encryptedContentTotalSz; 10342 } 10343 10344 /* use cached content */ 10345 encryptedContent = pkcs7->cachedEncryptedContent; 10346 encryptedContentSz = pkcs7->cachedEncryptedContentSz; 10347 10348 /* decrypt encryptedContent */ 10349 ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, 10350 blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, 10351 encryptedContent, encryptedContentSz, encryptedContent); 10352 if (ret != 0) { 10353 break; 10354 } 10355 10356 padLen = encryptedContent[encryptedContentSz-1]; 10357 10358 /* copy plaintext to output */ 10359 if (padLen > encryptedContentSz || 10360 (word32)(encryptedContentSz - padLen) > outputSz) { 10361 ret = BUFFER_E; 10362 break; 10363 } 10364 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 10365 10366 /* free memory, zero out keys */ 10367 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); 10368 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10369 if (pkcs7->cachedEncryptedContent != NULL) { 10370 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, 10371 DYNAMIC_TYPE_PKCS7); 10372 pkcs7->cachedEncryptedContent = NULL; 10373 pkcs7->cachedEncryptedContentSz = 0; 10374 } 10375 10376 ret = encryptedContentSz - padLen; 10377 #ifndef NO_PKCS7_STREAM 10378 pkcs7->stream->aad = NULL; 10379 pkcs7->stream->aadSz = 0; 10380 wc_PKCS7_ResetStream(pkcs7); 10381 #endif 10382 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 10383 break; 10384 10385 default: 10386 WOLFSSL_MSG("PKCS#7 unknown decode enveloped state"); 10387 ret = BAD_FUNC_ARG; 10388 } 10389 10390 #ifndef NO_PKCS7_STREAM 10391 if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { 10392 wc_PKCS7_ResetStream(pkcs7); 10393 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 10394 if (pkcs7->cachedEncryptedContent != NULL) { 10395 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, 10396 DYNAMIC_TYPE_PKCS7); 10397 pkcs7->cachedEncryptedContent = NULL; 10398 pkcs7->cachedEncryptedContentSz = 0; 10399 } 10400 } 10401 #else 10402 if (decryptedKey != NULL && ret < 0) { 10403 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); 10404 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10405 } 10406 if (pkcs7->cachedEncryptedContent != NULL && ret < 0) { 10407 XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10408 pkcs7->cachedEncryptedContent = NULL; 10409 pkcs7->cachedEncryptedContentSz = 0; 10410 } 10411 #endif 10412 return ret; 10413 } 10414 10415 10416 /* build PKCS#7 authEnvelopedData content type, return enveloped size */ 10417 int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, 10418 word32 outputSz) 10419 { 10420 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) 10421 int ret, idx = 0; 10422 int totalSz, encryptedOutSz; 10423 10424 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 10425 byte contentInfoSeq[MAX_SEQ_SZ]; 10426 byte outerContentType[MAX_ALGO_SZ]; 10427 byte outerContent[MAX_SEQ_SZ]; 10428 10429 int envDataSeqSz, verSz; 10430 byte envDataSeq[MAX_SEQ_SZ]; 10431 byte ver[MAX_VERSION_SZ]; 10432 10433 WC_RNG rng; 10434 int blockSz, blockKeySz; 10435 byte* encryptedContent; 10436 10437 Pkcs7EncodedRecip* tmpRecip = NULL; 10438 int recipSz, recipSetSz; 10439 byte recipSet[MAX_SET_SZ]; 10440 10441 int encContentOctetSz, encContentSeqSz, contentTypeSz; 10442 int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz; 10443 byte encContentSeq[MAX_SEQ_SZ]; 10444 byte contentType[MAX_ALGO_SZ]; 10445 byte contentEncAlgo[MAX_ALGO_SZ]; 10446 byte nonceOctetString[MAX_OCTET_STR_SZ]; 10447 byte encContentOctet[MAX_OCTET_STR_SZ]; 10448 byte macOctetString[MAX_OCTET_STR_SZ]; 10449 10450 byte authTag[AES_BLOCK_SIZE]; 10451 byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ 10452 byte macInt[MAX_VERSION_SZ]; 10453 word32 nonceSz = 0, macIntSz = 0; 10454 10455 /* authAttribs */ 10456 byte* flatAuthAttribs = NULL; 10457 byte authAttribSet[MAX_SET_SZ]; 10458 EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ]; 10459 word32 authAttribsSz = 0, authAttribsCount = 0; 10460 word32 authAttribsSetSz = 0; 10461 10462 byte* aadBuffer = NULL; 10463 word32 aadBufferSz = 0; 10464 byte authAttribAadSet[MAX_SET_SZ]; 10465 word32 authAttribsAadSetSz = 0; 10466 10467 /* unauthAttribs */ 10468 byte* flatUnauthAttribs = NULL; 10469 byte unauthAttribSet[MAX_SET_SZ]; 10470 EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ]; 10471 word32 unauthAttribsSz = 0, unauthAttribsCount = 0; 10472 word32 unauthAttribsSetSz = 0; 10473 10474 10475 PKCS7Attrib contentTypeAttrib; 10476 byte contentTypeValue[MAX_OID_SZ]; 10477 /* contentType OID (1.2.840.113549.1.9.3) */ 10478 const byte contentTypeOid[] = 10479 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 10480 0x09, 0x03 }; 10481 10482 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) 10483 return BAD_FUNC_ARG; 10484 10485 if (output == NULL || outputSz == 0) 10486 return BAD_FUNC_ARG; 10487 10488 switch (pkcs7->encryptOID) { 10489 #ifdef HAVE_AESGCM 10490 #ifdef WOLFSSL_AES_128 10491 case AES128GCMb: 10492 break; 10493 #endif 10494 #ifdef WOLFSSL_AES_192 10495 case AES192GCMb: 10496 break; 10497 #endif 10498 #ifdef WOLFSSL_AES_256 10499 case AES256GCMb: 10500 break; 10501 #endif 10502 #endif 10503 #ifdef HAVE_AESCCM 10504 #ifdef WOLFSSL_AES_128 10505 case AES128CCMb: 10506 break; 10507 #endif 10508 #ifdef WOLFSSL_AES_192 10509 case AES192CCMb: 10510 break; 10511 #endif 10512 #ifdef WOLFSSL_AES_256 10513 case AES256CCMb: 10514 break; 10515 #endif 10516 #endif 10517 default: 10518 WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); 10519 return BAD_FUNC_ARG; 10520 } 10521 10522 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 10523 if (blockKeySz < 0) 10524 return blockKeySz; 10525 10526 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); 10527 if (blockSz < 0) 10528 return blockSz; 10529 10530 /* outer content type */ 10531 ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType, 10532 sizeof(outerContentType)); 10533 if (ret < 0) 10534 return ret; 10535 10536 outerContentTypeSz = ret; 10537 10538 /* version, defined as 0 in RFC 5083 */ 10539 verSz = SetMyVersion(0, ver, 0); 10540 10541 /* generate random content encryption key */ 10542 ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); 10543 if (ret != 0) { 10544 return ret; 10545 } 10546 10547 /* build RecipientInfo, only if user manually set singleCert and size */ 10548 if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { 10549 switch (pkcs7->publicKeyOID) { 10550 #ifndef NO_RSA 10551 case RSAk: 10552 ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, 10553 pkcs7->singleCertSz, 0); 10554 break; 10555 #endif 10556 #ifdef HAVE_ECC 10557 case ECDSAk: 10558 ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, 10559 pkcs7->singleCertSz, 10560 pkcs7->keyWrapOID, 10561 pkcs7->keyAgreeOID, pkcs7->ukm, 10562 pkcs7->ukmSz, 0); 10563 break; 10564 #endif 10565 10566 default: 10567 WOLFSSL_MSG("Unsupported RecipientInfo public key type"); 10568 return BAD_FUNC_ARG; 10569 }; 10570 10571 if (ret < 0) { 10572 WOLFSSL_MSG("Failed to create RecipientInfo"); 10573 return ret; 10574 } 10575 } 10576 10577 recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); 10578 if (recipSz < 0) { 10579 return ret; 10580 10581 } else if (recipSz == 0) { 10582 WOLFSSL_MSG("You must add at least one CMS recipient"); 10583 return PKCS7_RECIP_E; 10584 } 10585 recipSetSz = SetSet(recipSz, recipSet); 10586 10587 /* generate random nonce and IV for encryption */ 10588 switch (pkcs7->encryptOID) { 10589 #ifdef HAVE_AESGCM 10590 #ifdef WOLFSSL_AES_128 10591 case AES128GCMb: 10592 FALL_THROUGH; 10593 #endif 10594 #ifdef WOLFSSL_AES_192 10595 case AES192GCMb: 10596 FALL_THROUGH; 10597 #endif 10598 #ifdef WOLFSSL_AES_256 10599 case AES256GCMb: 10600 #endif 10601 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 10602 defined(WOLFSSL_AES_256) 10603 /* GCM nonce is GCM_NONCE_MID_SZ (12) */ 10604 nonceSz = GCM_NONCE_MID_SZ; 10605 break; 10606 #endif 10607 #endif /* HAVE_AESGCM */ 10608 #ifdef HAVE_AESCCM 10609 #ifdef WOLFSSL_AES_128 10610 case AES128CCMb: 10611 FALL_THROUGH; 10612 #endif 10613 #ifdef WOLFSSL_AES_192 10614 case AES192CCMb: 10615 FALL_THROUGH; 10616 #endif 10617 #ifdef WOLFSSL_AES_256 10618 case AES256CCMb: 10619 #endif 10620 #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ 10621 defined(WOLFSSL_AES_256) 10622 /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ 10623 nonceSz = CCM_NONCE_MIN_SZ; 10624 break; 10625 #endif 10626 #endif /* HAVE_AESCCM */ 10627 } 10628 10629 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 10630 if (ret != 0) 10631 return ret; 10632 10633 ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz); 10634 wc_FreeRng(&rng); 10635 if (ret != 0) { 10636 return ret; 10637 } 10638 10639 10640 /* authAttribs: add contentType attrib if needed */ 10641 if (pkcs7->contentOID != DATA) { 10642 10643 /* if type is not id-data, contentType attribute MUST be added */ 10644 contentTypeAttrib.oid = contentTypeOid; 10645 contentTypeAttrib.oidSz = sizeof(contentTypeOid); 10646 10647 /* try to set from contentOID first, known types */ 10648 ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue, 10649 sizeof(contentTypeValue)); 10650 if (ret > 0) { 10651 contentTypeAttrib.value = contentTypeValue; 10652 contentTypeAttrib.valueSz = ret; 10653 10654 /* otherwise, try to set from custom content type */ 10655 } else { 10656 if (pkcs7->contentTypeSz == 0) { 10657 WOLFSSL_MSG("CMS pkcs7->contentType must be set if " 10658 "contentOID is not"); 10659 return BAD_FUNC_ARG; 10660 } 10661 contentTypeAttrib.value = pkcs7->contentType; 10662 contentTypeAttrib.valueSz = pkcs7->contentTypeSz; 10663 } 10664 10665 authAttribsSz += EncodeAttributes(authAttribs, 1, 10666 &contentTypeAttrib, 1); 10667 authAttribsCount += 1; 10668 } 10669 10670 /* authAttribs: add in user authenticated attributes */ 10671 if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) { 10672 authAttribsSz += EncodeAttributes(authAttribs + authAttribsCount, 10673 MAX_AUTH_ATTRIBS_SZ - authAttribsCount, 10674 pkcs7->authAttribs, 10675 pkcs7->authAttribsSz); 10676 authAttribsCount += pkcs7->authAttribsSz; 10677 } 10678 10679 /* authAttribs: flatten authAttribs */ 10680 if (authAttribsSz > 0 && authAttribsCount > 0) { 10681 flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap, 10682 DYNAMIC_TYPE_PKCS7); 10683 if (flatAuthAttribs == NULL) { 10684 return MEMORY_E; 10685 } 10686 10687 FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs, 10688 authAttribsCount); 10689 10690 authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz, 10691 authAttribSet); 10692 10693 /* From RFC5083, "For the purpose of constructing the AAD, the 10694 * IMPLICIT [1] tag in the authAttrs field is not used for the 10695 * DER encoding: rather a universal SET OF tag is used. */ 10696 authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet); 10697 10698 /* allocate temp buffer to hold alternate attrib encoding for aad */ 10699 aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz, 10700 pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 10701 if (aadBuffer == NULL) { 10702 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10703 return MEMORY_E; 10704 } 10705 10706 /* build up alternate attrib encoding for aad */ 10707 aadBufferSz = 0; 10708 XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz); 10709 aadBufferSz += authAttribsAadSetSz; 10710 XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz); 10711 aadBufferSz += authAttribsSz; 10712 } 10713 10714 /* build up unauthenticated attributes (unauthAttrs) */ 10715 if (pkcs7->unauthAttribsSz > 0) { 10716 unauthAttribsSz = EncodeAttributes(unauthAttribs + unauthAttribsCount, 10717 MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount, 10718 pkcs7->unauthAttribs, 10719 pkcs7->unauthAttribsSz); 10720 unauthAttribsCount = pkcs7->unauthAttribsSz; 10721 10722 flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap, 10723 DYNAMIC_TYPE_PKCS7); 10724 if (flatUnauthAttribs == NULL) { 10725 if (aadBuffer) 10726 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 10727 if (flatAuthAttribs) 10728 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10729 return MEMORY_E; 10730 } 10731 10732 FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs, 10733 unauthAttribsCount); 10734 unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz, 10735 unauthAttribSet); 10736 } 10737 10738 /* allocate encrypted content buffer */ 10739 encryptedOutSz = pkcs7->contentSz; 10740 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 10741 DYNAMIC_TYPE_PKCS7); 10742 if (encryptedContent == NULL) { 10743 if (aadBuffer) 10744 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 10745 if (flatUnauthAttribs) 10746 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10747 if (flatAuthAttribs) 10748 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10749 return MEMORY_E; 10750 } 10751 10752 /* encrypt content */ 10753 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, 10754 pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag, 10755 sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent); 10756 10757 if (aadBuffer) { 10758 XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 10759 aadBuffer = NULL; 10760 } 10761 10762 if (ret != 0) { 10763 if (flatUnauthAttribs) 10764 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10765 if (flatAuthAttribs) 10766 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10767 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10768 return ret; 10769 } 10770 10771 /* EncryptedContentInfo */ 10772 ret = wc_SetContentType(pkcs7->contentOID, contentType, 10773 sizeof(contentType)); 10774 if (ret < 0) { 10775 if (flatUnauthAttribs) 10776 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10777 if (flatAuthAttribs) 10778 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10779 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10780 return ret; 10781 } 10782 10783 contentTypeSz = ret; 10784 10785 /* put together nonce OCTET STRING */ 10786 nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString); 10787 10788 /* put together aes-ICVlen INTEGER */ 10789 macIntSz = SetMyVersion(sizeof(authTag), macInt, 0); 10790 10791 /* build up our ContentEncryptionAlgorithmIdentifier sequence, 10792 * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING 10793 * and tag size */ 10794 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 10795 oidBlkType, nonceOctetStringSz + nonceSz + 10796 macIntSz); 10797 10798 if (contentEncAlgoSz == 0) { 10799 if (flatUnauthAttribs) 10800 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10801 if (flatAuthAttribs) 10802 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10803 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10804 return BAD_FUNC_ARG; 10805 } 10806 10807 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, 10808 encContentOctet); 10809 10810 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 10811 nonceOctetStringSz + nonceSz + macIntSz + 10812 encContentOctetSz + encryptedOutSz, 10813 encContentSeq); 10814 10815 macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString); 10816 10817 /* keep track of sizes for outer wrapper layering */ 10818 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + 10819 contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + 10820 encContentOctetSz + encryptedOutSz + authAttribsSz + 10821 authAttribsSetSz + macOctetStringSz + sizeof(authTag) + 10822 unauthAttribsSz + unauthAttribsSetSz; 10823 10824 /* EnvelopedData */ 10825 envDataSeqSz = SetSequence(totalSz, envDataSeq); 10826 totalSz += envDataSeqSz; 10827 10828 /* outer content */ 10829 outerContentSz = SetExplicit(0, totalSz, outerContent); 10830 totalSz += outerContentTypeSz; 10831 totalSz += outerContentSz; 10832 10833 /* ContentInfo */ 10834 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 10835 totalSz += contentInfoSeqSz; 10836 10837 if (totalSz > (int)outputSz) { 10838 WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); 10839 if (flatUnauthAttribs) 10840 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10841 if (flatAuthAttribs) 10842 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10843 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10844 return BUFFER_E; 10845 } 10846 10847 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 10848 idx += contentInfoSeqSz; 10849 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 10850 idx += outerContentTypeSz; 10851 XMEMCPY(output + idx, outerContent, outerContentSz); 10852 idx += outerContentSz; 10853 XMEMCPY(output + idx, envDataSeq, envDataSeqSz); 10854 idx += envDataSeqSz; 10855 XMEMCPY(output + idx, ver, verSz); 10856 idx += verSz; 10857 XMEMCPY(output + idx, recipSet, recipSetSz); 10858 idx += recipSetSz; 10859 /* copy in recipients from list */ 10860 tmpRecip = pkcs7->recipList; 10861 while (tmpRecip != NULL) { 10862 XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); 10863 idx += tmpRecip->recipSz; 10864 tmpRecip = tmpRecip->next; 10865 } 10866 wc_PKCS7_FreeEncodedRecipientSet(pkcs7); 10867 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 10868 idx += encContentSeqSz; 10869 XMEMCPY(output + idx, contentType, contentTypeSz); 10870 idx += contentTypeSz; 10871 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 10872 idx += contentEncAlgoSz; 10873 XMEMCPY(output + idx, nonceOctetString, nonceOctetStringSz); 10874 idx += nonceOctetStringSz; 10875 XMEMCPY(output + idx, nonce, nonceSz); 10876 idx += nonceSz; 10877 XMEMCPY(output + idx, macInt, macIntSz); 10878 idx += macIntSz; 10879 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 10880 idx += encContentOctetSz; 10881 XMEMCPY(output + idx, encryptedContent, encryptedOutSz); 10882 idx += encryptedOutSz; 10883 10884 /* authenticated attributes */ 10885 if (flatAuthAttribs && authAttribsSz > 0) { 10886 XMEMCPY(output + idx, authAttribSet, authAttribsSetSz); 10887 idx += authAttribsSetSz; 10888 XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz); 10889 idx += authAttribsSz; 10890 XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10891 } 10892 10893 XMEMCPY(output + idx, macOctetString, macOctetStringSz); 10894 idx += macOctetStringSz; 10895 XMEMCPY(output + idx, authTag, sizeof(authTag)); 10896 idx += sizeof(authTag); 10897 10898 /* unauthenticated attributes */ 10899 if (unauthAttribsSz > 0) { 10900 XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz); 10901 idx += unauthAttribsSetSz; 10902 XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz); 10903 idx += unauthAttribsSz; 10904 } 10905 10906 if (flatUnauthAttribs != NULL) { 10907 XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10908 } 10909 10910 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 10911 10912 return idx; 10913 10914 #else 10915 WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); 10916 (void)pkcs7; 10917 (void)output; 10918 (void)outputSz; 10919 10920 return NOT_COMPILED_IN; 10921 #endif /* HAVE_AESGCM | HAVE_AESCCM */ 10922 } 10923 10924 10925 /* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */ 10926 WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, 10927 word32 inSz, byte* output, 10928 word32 outputSz) 10929 { 10930 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) 10931 int recipFound = 0; 10932 int ret = 0, length; 10933 word32 idx = 0; 10934 #ifndef NO_PKCS7_STREAM 10935 word32 tmpIdx = 0; 10936 long rc; 10937 #endif 10938 word32 contentType, encOID = 0; 10939 word32 decryptedKeySz = 0; 10940 byte* pkiMsg = in; 10941 word32 pkiMsgSz = inSz; 10942 10943 int expBlockSz = 0, blockKeySz = 0; 10944 byte authTag[AES_BLOCK_SIZE]; 10945 byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ 10946 int nonceSz = 0, authTagSz = 0, macSz = 0; 10947 10948 #ifdef WOLFSSL_SMALL_STACK 10949 byte* decryptedKey = NULL; 10950 #else 10951 byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; 10952 #endif 10953 int encryptedContentSz = 0; 10954 byte* encryptedContent = NULL; 10955 int explicitOctet = 0; 10956 10957 byte authAttribSetByte = 0; 10958 byte* encodedAttribs = NULL; 10959 word32 encodedAttribIdx = 0, encodedAttribSz = 0; 10960 byte* authAttrib = NULL; 10961 int authAttribSz = 0; 10962 word32 localIdx; 10963 byte tag; 10964 10965 if (pkcs7 == NULL) 10966 return BAD_FUNC_ARG; 10967 10968 if (pkiMsg == NULL || pkiMsgSz == 0 || 10969 output == NULL || outputSz == 0) 10970 return BAD_FUNC_ARG; 10971 #ifndef NO_PKCS7_STREAM 10972 if (pkcs7->stream == NULL) { 10973 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { 10974 return ret; 10975 } 10976 } 10977 #endif 10978 10979 switch (pkcs7->state) { 10980 case WC_PKCS7_START: 10981 case WC_PKCS7_INFOSET_START: 10982 case WC_PKCS7_INFOSET_STAGE1: 10983 case WC_PKCS7_INFOSET_STAGE2: 10984 case WC_PKCS7_INFOSET_END: 10985 ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, 10986 &idx, AUTH_ENVELOPED_DATA); 10987 if (ret < 0) 10988 break; 10989 10990 #ifndef NO_PKCS7_STREAM 10991 tmpIdx = idx; 10992 #endif 10993 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2); 10994 FALL_THROUGH; 10995 10996 case WC_PKCS7_AUTHENV_2: 10997 #ifndef NO_PKCS7_STREAM 10998 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 10999 MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { 11000 break; 11001 } 11002 #endif 11003 #ifdef WOLFSSL_SMALL_STACK 11004 decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 11005 DYNAMIC_TYPE_PKCS7); 11006 if (decryptedKey == NULL) { 11007 ret = MEMORY_E; 11008 break; 11009 } 11010 #ifndef NO_PKCS7_STREAM 11011 pkcs7->stream->key = decryptedKey; 11012 #endif 11013 #endif 11014 FALL_THROUGH; 11015 11016 case WC_PKCS7_DECRYPT_KTRI: 11017 case WC_PKCS7_DECRYPT_KTRI_2: 11018 case WC_PKCS7_DECRYPT_KTRI_3: 11019 case WC_PKCS7_DECRYPT_KARI: 11020 case WC_PKCS7_DECRYPT_KEKRI: 11021 case WC_PKCS7_DECRYPT_PWRI: 11022 case WC_PKCS7_DECRYPT_ORI: 11023 11024 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 11025 #ifdef WOLFSSL_SMALL_STACK 11026 #ifndef NO_PKCS7_STREAM 11027 decryptedKey = pkcs7->stream->key; 11028 #endif 11029 #endif 11030 11031 ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, 11032 decryptedKey, &decryptedKeySz, 11033 &recipFound); 11034 if (ret != 0) { 11035 break; 11036 } 11037 11038 if (recipFound == 0) { 11039 WOLFSSL_MSG("No recipient found in envelopedData that matches input"); 11040 ret = PKCS7_RECIP_E; 11041 break; 11042 } 11043 11044 #ifndef NO_PKCS7_STREAM 11045 tmpIdx = idx; 11046 #endif 11047 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3); 11048 FALL_THROUGH; 11049 11050 case WC_PKCS7_AUTHENV_3: 11051 #ifndef NO_PKCS7_STREAM 11052 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + 11053 MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, 11054 &pkiMsg, &idx)) != 0) { 11055 break; 11056 } 11057 11058 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 11059 in, inSz); 11060 if (rc < 0) { 11061 ret = (int)rc; 11062 break; 11063 } 11064 pkiMsgSz = (word32)rc; 11065 #endif 11066 11067 /* remove EncryptedContentInfo */ 11068 if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 11069 ret = ASN_PARSE_E; 11070 } 11071 11072 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, 11073 pkiMsgSz) < 0) { 11074 ret = ASN_PARSE_E; 11075 } 11076 11077 if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, 11078 pkiMsgSz) < 0) { 11079 ret = ASN_PARSE_E; 11080 } 11081 11082 blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); 11083 if (ret == 0 && blockKeySz < 0) { 11084 ret = blockKeySz; 11085 } 11086 11087 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); 11088 if (ret == 0 && expBlockSz < 0) { 11089 ret = expBlockSz; 11090 } 11091 11092 /* get nonce, stored in OPTIONAL parameter of AlgoID */ 11093 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { 11094 ret = ASN_PARSE_E; 11095 } 11096 11097 if (ret == 0 && tag != ASN_OCTET_STRING) { 11098 ret = ASN_PARSE_E; 11099 } 11100 11101 if (ret < 0) 11102 break; 11103 11104 #ifndef NO_PKCS7_STREAM 11105 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11106 break; 11107 } 11108 wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0); 11109 #endif 11110 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4); 11111 FALL_THROUGH; 11112 11113 case WC_PKCS7_AUTHENV_4: 11114 11115 #ifndef NO_PKCS7_STREAM 11116 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 11117 MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, 11118 &pkiMsg, &idx)) != 0) { 11119 break; 11120 } 11121 11122 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 11123 inSz); 11124 if (rc < 0) { 11125 ret = (int)rc; 11126 break; 11127 } 11128 pkiMsgSz = (word32)rc; 11129 #endif 11130 if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { 11131 ret = ASN_PARSE_E; 11132 } 11133 11134 if (ret == 0 && nonceSz > (int)sizeof(nonce)) { 11135 WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); 11136 ret = ASN_PARSE_E; 11137 } 11138 11139 if (ret == 0) { 11140 XMEMCPY(nonce, &pkiMsg[idx], nonceSz); 11141 idx += nonceSz; 11142 } 11143 11144 /* get mac size, also stored in OPTIONAL parameter of AlgoID */ 11145 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { 11146 ret = ASN_PARSE_E; 11147 } 11148 11149 if (ret == 0) { 11150 explicitOctet = 0; 11151 localIdx = idx; 11152 if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && 11153 tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) 11154 explicitOctet = 1; 11155 11156 /* read encryptedContent, cont[0] */ 11157 ret = GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz); 11158 } 11159 11160 if (ret == 0 && 11161 tag != (ASN_CONTEXT_SPECIFIC | 0) && 11162 tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { 11163 ret = ASN_PARSE_E; 11164 } 11165 11166 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, 11167 pkiMsgSz) <= 0) { 11168 ret = ASN_PARSE_E; 11169 } 11170 11171 if (explicitOctet) { 11172 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { 11173 ret = ASN_PARSE_E; 11174 } 11175 if (ret == 0 && tag != ASN_OCTET_STRING) { 11176 ret = ASN_PARSE_E; 11177 } 11178 11179 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, 11180 pkiMsgSz) <= 0) { 11181 ret = ASN_PARSE_E; 11182 } 11183 } 11184 11185 if (ret < 0) 11186 break; 11187 11188 #ifndef NO_PKCS7_STREAM 11189 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11190 break; 11191 } 11192 11193 /* store nonce for later */ 11194 if (nonceSz > 0) { 11195 pkcs7->stream->nonceSz = nonceSz; 11196 pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap, 11197 DYNAMIC_TYPE_PKCS7); 11198 if (pkcs7->stream->nonce == NULL) { 11199 ret = MEMORY_E; 11200 break; 11201 } 11202 else { 11203 XMEMCPY(pkcs7->stream->nonce, nonce, nonceSz); 11204 } 11205 } 11206 11207 pkcs7->stream->expected = encryptedContentSz; 11208 wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 11209 encryptedContentSz); 11210 #endif 11211 11212 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5); 11213 FALL_THROUGH; 11214 11215 case WC_PKCS7_AUTHENV_5: 11216 #ifndef NO_PKCS7_STREAM 11217 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 11218 ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, 11219 &pkiMsg, &idx)) != 0) { 11220 break; 11221 } 11222 11223 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 11224 inSz); 11225 if (rc < 0) { 11226 ret = (int)rc; 11227 break; 11228 } 11229 pkiMsgSz = (word32)rc; 11230 11231 encryptedContentSz = pkcs7->stream->expected; 11232 #endif 11233 11234 encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, 11235 DYNAMIC_TYPE_PKCS7); 11236 if (ret == 0 && encryptedContent == NULL) { 11237 ret = MEMORY_E; 11238 } 11239 11240 if (ret == 0) { 11241 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 11242 idx += encryptedContentSz; 11243 } 11244 #ifndef NO_PKCS7_STREAM 11245 pkcs7->stream->bufferPt = encryptedContent; 11246 #endif 11247 11248 /* may have IMPLICIT [1] authenticatedAttributes */ 11249 localIdx = idx; 11250 if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && 11251 tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 11252 encodedAttribIdx = idx; 11253 encodedAttribs = pkiMsg + idx; 11254 idx++; 11255 11256 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 11257 ret = ASN_PARSE_E; 11258 #ifndef NO_PKCS7_STREAM 11259 pkcs7->stream->expected = length; 11260 #endif 11261 encodedAttribSz = length + (idx - encodedAttribIdx); 11262 11263 if (ret != 0) 11264 break; 11265 11266 #ifndef NO_PKCS7_STREAM 11267 if (encodedAttribSz > 0) { 11268 pkcs7->stream->aadSz = encodedAttribSz; 11269 pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, 11270 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11271 if (pkcs7->stream->aad == NULL) { 11272 ret = MEMORY_E; 11273 break; 11274 } 11275 else { 11276 XMEMCPY(pkcs7->stream->aad, encodedAttribs, 11277 (idx - encodedAttribIdx)); 11278 } 11279 } 11280 11281 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11282 break; 11283 } 11284 #endif 11285 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); 11286 } 11287 else { 11288 #ifndef NO_PKCS7_STREAM 11289 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11290 break; 11291 } 11292 #endif 11293 goto authenv_atrbend; /* jump over attribute cases */ 11294 } 11295 FALL_THROUGH; 11296 11297 case WC_PKCS7_AUTHENV_ATRB: 11298 #ifndef NO_PKCS7_STREAM 11299 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 11300 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 11301 return ret; 11302 } 11303 11304 length = pkcs7->stream->expected; 11305 encodedAttribs = pkcs7->stream->aad; 11306 #else 11307 length = 0; 11308 #endif 11309 11310 /* save pointer and length */ 11311 authAttrib = &pkiMsg[idx]; 11312 authAttribSz = length; 11313 11314 if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { 11315 WOLFSSL_MSG("Error parsing authenticated attributes"); 11316 ret = ASN_PARSE_E; 11317 break; 11318 } 11319 11320 idx += length; 11321 11322 #ifndef NO_PKCS7_STREAM 11323 if (encodedAttribSz > 0) { 11324 XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), 11325 authAttrib, authAttribSz); 11326 } 11327 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11328 break; 11329 } 11330 11331 #endif 11332 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); 11333 FALL_THROUGH; 11334 11335 authenv_atrbend: 11336 case WC_PKCS7_AUTHENV_ATRBEND: 11337 #ifndef NO_PKCS7_STREAM 11338 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + 11339 ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { 11340 return ret; 11341 } 11342 11343 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, 11344 in, inSz); 11345 if (rc < 0) { 11346 ret = (int)rc; 11347 break; 11348 } 11349 pkiMsgSz = (word32)rc; 11350 11351 if (pkcs7->stream->aadSz > 0) { 11352 encodedAttribSz = pkcs7->stream->aadSz; 11353 encodedAttribs = pkcs7->stream->aad; 11354 } 11355 #endif 11356 11357 11358 /* get authTag OCTET STRING */ 11359 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { 11360 ret = ASN_PARSE_E; 11361 } 11362 if (ret == 0 && tag != ASN_OCTET_STRING) { 11363 ret = ASN_PARSE_E; 11364 } 11365 11366 if (ret == 0 && GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { 11367 ret = ASN_PARSE_E; 11368 } 11369 11370 if (ret == 0 && authTagSz > (int)sizeof(authTag)) { 11371 WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); 11372 ret = ASN_PARSE_E; 11373 } 11374 11375 if (ret == 0) { 11376 XMEMCPY(authTag, &pkiMsg[idx], authTagSz); 11377 idx += authTagSz; 11378 } 11379 11380 if (ret == 0 && authAttrib != NULL) { 11381 /* temporarily swap authAttribs byte[0] to SET OF instead of 11382 * IMPLICIT [1], for aad calculation */ 11383 authAttribSetByte = encodedAttribs[0]; 11384 11385 encodedAttribs[0] = ASN_SET | ASN_CONSTRUCTED; 11386 } 11387 11388 if (ret < 0) 11389 break; 11390 11391 #ifndef NO_PKCS7_STREAM 11392 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11393 break; 11394 } 11395 pkcs7->stream->expected = (pkcs7->stream->maxLen - 11396 pkcs7->stream->totalRd) + pkcs7->stream->length; 11397 11398 11399 /* store tag for later */ 11400 if (authTagSz > 0) { 11401 pkcs7->stream->tagSz = authTagSz; 11402 pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap, 11403 DYNAMIC_TYPE_PKCS7); 11404 if (pkcs7->stream->tag == NULL) { 11405 ret = MEMORY_E; 11406 break; 11407 } 11408 else { 11409 XMEMCPY(pkcs7->stream->tag, authTag, authTagSz); 11410 } 11411 } 11412 11413 #endif 11414 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6); 11415 FALL_THROUGH; 11416 11417 case WC_PKCS7_AUTHENV_6: 11418 #ifndef NO_PKCS7_STREAM 11419 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 11420 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 11421 break; 11422 } 11423 11424 /* restore all variables needed */ 11425 if (pkcs7->stream->nonceSz > 0) { 11426 nonceSz = pkcs7->stream->nonceSz; 11427 if (nonceSz > GCM_NONCE_MID_SZ) { 11428 WOLFSSL_MSG("PKCS7 saved nonce is too large"); 11429 ret = BUFFER_E; 11430 break; 11431 } 11432 else { 11433 XMEMCPY(nonce, pkcs7->stream->nonce, nonceSz); 11434 } 11435 } 11436 11437 if (pkcs7->stream->tagSz > 0) { 11438 authTagSz = pkcs7->stream->tagSz; 11439 if (authTagSz > AES_BLOCK_SIZE) { 11440 WOLFSSL_MSG("PKCS7 saved tag is too large"); 11441 ret = BUFFER_E; 11442 break; 11443 } 11444 else { 11445 XMEMCPY(authTag, pkcs7->stream->tag, authTagSz); 11446 } 11447 } 11448 11449 if (pkcs7->stream->aadSz > 0) { 11450 encodedAttribSz = pkcs7->stream->aadSz; 11451 encodedAttribs = pkcs7->stream->aad; 11452 } 11453 11454 wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, 11455 &encryptedContentSz); 11456 encryptedContent = pkcs7->stream->bufferPt; 11457 #ifdef WOLFSSL_SMALL_STACK 11458 decryptedKey = pkcs7->stream->key; 11459 #endif 11460 #endif 11461 11462 /* decrypt encryptedContent */ 11463 ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, 11464 blockKeySz, nonce, nonceSz, encodedAttribs, encodedAttribSz, 11465 authTag, authTagSz, encryptedContent, encryptedContentSz, 11466 encryptedContent); 11467 if (ret != 0) { 11468 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11469 return ret; 11470 } 11471 11472 if (authAttrib != NULL) { 11473 /* restore authAttrib IMPLICIT [1] */ 11474 encodedAttribs[0] = authAttribSetByte; 11475 } 11476 11477 /* copy plaintext to output */ 11478 XMEMCPY(output, encryptedContent, encryptedContentSz); 11479 11480 /* free memory, zero out keys */ 11481 ForceZero(encryptedContent, encryptedContentSz); 11482 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11483 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); 11484 #ifdef WOLFSSL_SMALL_STACK 11485 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11486 decryptedKey = NULL; 11487 #ifdef WOLFSSL_SMALL_STACK 11488 #ifndef NO_PKCS7_STREAM 11489 pkcs7->stream->key = NULL; 11490 #endif 11491 #endif 11492 #endif 11493 ret = encryptedContentSz; 11494 #ifndef NO_PKCS7_STREAM 11495 wc_PKCS7_ResetStream(pkcs7); 11496 #endif 11497 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 11498 break; 11499 default: 11500 WOLFSSL_MSG("Unknown PKCS7 state"); 11501 ret = BAD_FUNC_ARG; 11502 } 11503 11504 #ifdef WOLFSSL_SMALL_STACK 11505 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { 11506 if (decryptedKey != NULL) { 11507 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); 11508 } 11509 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11510 } 11511 #endif 11512 #ifndef NO_PKCS7_STREAM 11513 if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { 11514 wc_PKCS7_ResetStream(pkcs7); 11515 } 11516 #endif 11517 11518 return ret; 11519 11520 #else 11521 WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); 11522 (void)pkcs7; 11523 (void)in; 11524 (void)inSz; 11525 (void)output; 11526 (void)outputSz; 11527 11528 return NOT_COMPILED_IN; 11529 #endif /* HAVE_AESGCM | HAVE_AESCCM */ 11530 } 11531 11532 11533 #ifndef NO_PKCS7_ENCRYPTED_DATA 11534 11535 /* build PKCS#7 encryptedData content type, return encrypted size */ 11536 int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) 11537 { 11538 int ret, idx = 0; 11539 int totalSz, padSz, encryptedOutSz; 11540 11541 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 11542 byte contentInfoSeq[MAX_SEQ_SZ]; 11543 byte outerContentType[MAX_ALGO_SZ]; 11544 byte outerContent[MAX_SEQ_SZ]; 11545 11546 int encDataSeqSz, verSz, blockSz; 11547 byte encDataSeq[MAX_SEQ_SZ]; 11548 byte ver[MAX_VERSION_SZ]; 11549 11550 byte* plain = NULL; 11551 byte* encryptedContent = NULL; 11552 11553 int encContentOctetSz, encContentSeqSz, contentTypeSz; 11554 int contentEncAlgoSz, ivOctetStringSz; 11555 byte encContentSeq[MAX_SEQ_SZ]; 11556 byte contentType[MAX_OID_SZ]; 11557 byte contentEncAlgo[MAX_ALGO_SZ]; 11558 byte tmpIv[MAX_CONTENT_IV_SIZE]; 11559 byte ivOctetString[MAX_OCTET_STR_SZ]; 11560 byte encContentOctet[MAX_OCTET_STR_SZ]; 11561 11562 byte attribSet[MAX_SET_SZ]; 11563 EncodedAttrib* attribs = NULL; 11564 word32 attribsSz; 11565 word32 attribsCount; 11566 word32 attribsSetSz; 11567 11568 byte* flatAttribs = NULL; 11569 11570 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 11571 pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL || 11572 pkcs7->encryptionKeySz == 0) 11573 return BAD_FUNC_ARG; 11574 11575 if (output == NULL || outputSz == 0) 11576 return BAD_FUNC_ARG; 11577 11578 if (pkcs7->version == 3) { 11579 verSz = SetMyVersion(0, ver, 0); 11580 outerContentTypeSz = 0; 11581 } 11582 else { 11583 /* outer content type */ 11584 ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType, 11585 sizeof(outerContentType)); 11586 if (ret < 0) 11587 return ret; 11588 11589 outerContentTypeSz = ret; 11590 11591 /* version, 2 if unprotectedAttrs present, 0 if absent */ 11592 if (pkcs7->unprotectedAttribsSz > 0) { 11593 verSz = SetMyVersion(2, ver, 0); 11594 } else { 11595 verSz = SetMyVersion(0, ver, 0); 11596 } 11597 } 11598 11599 /* EncryptedContentInfo */ 11600 ret = wc_SetContentType(pkcs7->contentOID, contentType, 11601 sizeof(contentType)); 11602 if (ret < 0) 11603 return ret; 11604 11605 contentTypeSz = ret; 11606 11607 /* allocate encrypted content buffer, do PKCS#7 padding */ 11608 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); 11609 if (blockSz < 0) 11610 return blockSz; 11611 11612 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); 11613 if (padSz < 0) 11614 return padSz; 11615 11616 encryptedOutSz = pkcs7->contentSz + padSz; 11617 11618 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 11619 DYNAMIC_TYPE_PKCS7); 11620 if (plain == NULL) 11621 return MEMORY_E; 11622 11623 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, 11624 encryptedOutSz, blockSz); 11625 if (ret < 0) { 11626 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11627 return ret; 11628 } 11629 11630 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 11631 DYNAMIC_TYPE_PKCS7); 11632 if (encryptedContent == NULL) { 11633 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11634 return MEMORY_E; 11635 } 11636 11637 /* put together IV OCTET STRING */ 11638 ivOctetStringSz = SetOctetString(blockSz, ivOctetString); 11639 11640 /* build up ContentEncryptionAlgorithmIdentifier sequence, 11641 adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ 11642 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 11643 oidBlkType, ivOctetStringSz + blockSz); 11644 if (contentEncAlgoSz == 0) { 11645 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11646 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11647 return BAD_FUNC_ARG; 11648 } 11649 11650 /* encrypt content */ 11651 WOLFSSL_MSG("Encrypting the content"); 11652 ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, blockSz); 11653 if (ret != 0) { 11654 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11655 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11656 return ret; 11657 } 11658 11659 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, 11660 pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0, 11661 plain, encryptedOutSz, encryptedContent); 11662 if (ret != 0) { 11663 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11664 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11665 return ret; 11666 } 11667 11668 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, 11669 encryptedOutSz, encContentOctet); 11670 11671 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 11672 ivOctetStringSz + blockSz + 11673 encContentOctetSz + encryptedOutSz, 11674 encContentSeq); 11675 11676 /* optional UnprotectedAttributes */ 11677 if (pkcs7->unprotectedAttribsSz != 0) { 11678 11679 if (pkcs7->unprotectedAttribs == NULL) { 11680 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11681 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11682 return BAD_FUNC_ARG; 11683 } 11684 11685 attribs = (EncodedAttrib*)XMALLOC( 11686 sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz, 11687 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11688 if (attribs == NULL) { 11689 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11690 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11691 return MEMORY_E; 11692 } 11693 11694 attribsCount = pkcs7->unprotectedAttribsSz; 11695 attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz, 11696 pkcs7->unprotectedAttribs, 11697 pkcs7->unprotectedAttribsSz); 11698 11699 flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11700 if (flatAttribs == NULL) { 11701 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11702 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11703 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11704 return MEMORY_E; 11705 } 11706 11707 FlattenAttributes(pkcs7, flatAttribs, attribs, attribsCount); 11708 attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet); 11709 11710 } else { 11711 attribsSz = 0; 11712 attribsSetSz = 0; 11713 } 11714 11715 /* keep track of sizes for outer wrapper layering */ 11716 totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz + 11717 ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz + 11718 attribsSz + attribsSetSz; 11719 11720 /* EncryptedData */ 11721 encDataSeqSz = SetSequence(totalSz, encDataSeq); 11722 totalSz += encDataSeqSz; 11723 11724 if (pkcs7->version != 3) { 11725 /* outer content */ 11726 outerContentSz = SetExplicit(0, totalSz, outerContent); 11727 totalSz += outerContentTypeSz; 11728 totalSz += outerContentSz; 11729 /* ContentInfo */ 11730 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 11731 totalSz += contentInfoSeqSz; 11732 } else { 11733 contentInfoSeqSz = 0; 11734 outerContentSz = 0; 11735 } 11736 11737 if (totalSz > (int)outputSz) { 11738 WOLFSSL_MSG("PKCS#7 output buffer too small"); 11739 if (pkcs7->unprotectedAttribsSz != 0) { 11740 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11741 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11742 } 11743 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11744 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11745 return BUFFER_E; 11746 } 11747 11748 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 11749 idx += contentInfoSeqSz; 11750 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 11751 idx += outerContentTypeSz; 11752 XMEMCPY(output + idx, outerContent, outerContentSz); 11753 idx += outerContentSz; 11754 XMEMCPY(output + idx, encDataSeq, encDataSeqSz); 11755 idx += encDataSeqSz; 11756 XMEMCPY(output + idx, ver, verSz); 11757 idx += verSz; 11758 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 11759 idx += encContentSeqSz; 11760 XMEMCPY(output + idx, contentType, contentTypeSz); 11761 idx += contentTypeSz; 11762 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 11763 idx += contentEncAlgoSz; 11764 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 11765 idx += ivOctetStringSz; 11766 XMEMCPY(output + idx, tmpIv, blockSz); 11767 idx += blockSz; 11768 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 11769 idx += encContentOctetSz; 11770 XMEMCPY(output + idx, encryptedContent, encryptedOutSz); 11771 idx += encryptedOutSz; 11772 11773 if (pkcs7->unprotectedAttribsSz != 0) { 11774 XMEMCPY(output + idx, attribSet, attribsSetSz); 11775 idx += attribsSetSz; 11776 XMEMCPY(output + idx, flatAttribs, attribsSz); 11777 idx += attribsSz; 11778 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11779 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11780 } 11781 11782 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11783 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 11784 11785 return idx; 11786 } 11787 11788 11789 /* decode and store unprotected attributes in PKCS7->decodedAttrib. Return 11790 * 0 on success, negative on error. User must call wc_PKCS7_Free(). */ 11791 static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, 11792 word32 pkiMsgSz, word32* inOutIdx) 11793 { 11794 int ret, attribLen; 11795 word32 idx; 11796 byte tag; 11797 11798 if (pkcs7 == NULL || pkiMsg == NULL || 11799 pkiMsgSz == 0 || inOutIdx == NULL) 11800 return BAD_FUNC_ARG; 11801 11802 idx = *inOutIdx; 11803 11804 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 11805 return ASN_PARSE_E; 11806 11807 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) 11808 return ASN_PARSE_E; 11809 11810 if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0) 11811 return ASN_PARSE_E; 11812 11813 /* loop through attributes */ 11814 if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) { 11815 return ret; 11816 } 11817 11818 *inOutIdx = idx; 11819 11820 return 0; 11821 } 11822 11823 11824 /* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */ 11825 int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, 11826 byte* output, word32 outputSz) 11827 { 11828 int ret = 0, version, length = 0, haveAttribs = 0; 11829 word32 idx = 0; 11830 11831 #ifndef NO_PKCS7_STREAM 11832 word32 tmpIdx = 0; 11833 long rc; 11834 #endif 11835 word32 contentType, encOID; 11836 11837 int expBlockSz = 0; 11838 byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; 11839 byte *tmpIv = tmpIvBuf; 11840 11841 int encryptedContentSz = 0; 11842 byte padLen; 11843 byte* encryptedContent = NULL; 11844 11845 byte* pkiMsg = in; 11846 word32 pkiMsgSz = inSz; 11847 byte tag; 11848 11849 if (pkcs7 == NULL || 11850 ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) && 11851 pkcs7->decryptionCb == NULL)) 11852 return BAD_FUNC_ARG; 11853 11854 if (pkiMsg == NULL || pkiMsgSz == 0 || 11855 output == NULL || outputSz == 0) 11856 return BAD_FUNC_ARG; 11857 11858 #ifndef NO_PKCS7_STREAM 11859 (void)tmpIv; /* help out static analysis */ 11860 if (pkcs7->stream == NULL) { 11861 if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { 11862 return ret; 11863 } 11864 } 11865 #endif 11866 11867 switch (pkcs7->state) { 11868 case WC_PKCS7_START: 11869 #ifndef NO_PKCS7_STREAM 11870 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + 11871 MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) { 11872 return ret; 11873 } 11874 11875 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); 11876 if (rc < 0) { 11877 ret = (int)rc; 11878 break; 11879 } 11880 pkiMsgSz = (word32)rc; 11881 #endif 11882 11883 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 11884 ret = ASN_PARSE_E; 11885 11886 if (pkcs7->version != 3) { /* ContentInfo not in firmware bundles */ 11887 /* read past ContentInfo, verify type is encrypted-data */ 11888 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, 11889 pkiMsgSz) < 0) 11890 ret = ASN_PARSE_E; 11891 11892 if (ret == 0 && contentType != ENCRYPTED_DATA) { 11893 WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); 11894 ret = PKCS7_OID_E; 11895 } 11896 } 11897 if (ret != 0) break; 11898 #ifndef NO_PKCS7_STREAM 11899 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11900 break; 11901 } 11902 #endif 11903 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2); 11904 FALL_THROUGH; 11905 /* end of stage 1 */ 11906 11907 case WC_PKCS7_STAGE2: 11908 #ifndef NO_PKCS7_STREAM 11909 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 11910 MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg, 11911 &idx)) != 0) { 11912 return ret; 11913 } 11914 11915 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 11916 inSz); 11917 if (rc < 0) { 11918 ret = (int)rc; 11919 break; 11920 } 11921 pkiMsgSz = (word32)rc; 11922 #endif 11923 if (pkcs7->version != 3) { 11924 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 11925 ret = ASN_PARSE_E; 11926 if (ret == 0 && tag != 11927 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 11928 ret = ASN_PARSE_E; 11929 11930 if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 11931 ret = ASN_PARSE_E; 11932 11933 /* remove EncryptedData and version */ 11934 if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 11935 ret = ASN_PARSE_E; 11936 } 11937 11938 if (ret != 0) break; 11939 #ifndef NO_PKCS7_STREAM 11940 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11941 break; 11942 } 11943 #endif 11944 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3); 11945 FALL_THROUGH; 11946 /* end of stage 2 */ 11947 11948 case WC_PKCS7_STAGE3: 11949 #ifndef NO_PKCS7_STREAM 11950 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 11951 MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2, 11952 &pkiMsg, &idx)) != 0) { 11953 return ret; 11954 } 11955 11956 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 11957 inSz); 11958 if (rc < 0) { 11959 ret = (int)rc; 11960 break; 11961 } 11962 pkiMsgSz = (word32)rc; 11963 #endif 11964 /* get version, check later */ 11965 haveAttribs = 0; 11966 if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 11967 ret = ASN_PARSE_E; 11968 11969 /* remove EncryptedContentInfo */ 11970 if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 11971 ret = ASN_PARSE_E; 11972 11973 if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, 11974 pkiMsgSz) < 0) 11975 ret = ASN_PARSE_E; 11976 11977 if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, 11978 pkiMsgSz)) < 0) 11979 ret = ASN_PARSE_E; 11980 if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0) 11981 ret = expBlockSz; 11982 11983 if (ret != 0) break; 11984 #ifndef NO_PKCS7_STREAM 11985 /* store expBlockSz for later */ 11986 pkcs7->stream->varOne = expBlockSz; 11987 pkcs7->stream->varTwo = encOID; 11988 11989 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 11990 break; 11991 } 11992 11993 /* store version for later */ 11994 pkcs7->stream->vers = version; 11995 #endif 11996 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4); 11997 FALL_THROUGH; 11998 /* end of stage 3 */ 11999 12000 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 12001 case WC_PKCS7_STAGE4: 12002 #ifndef NO_PKCS7_STREAM 12003 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 12004 ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { 12005 return ret; 12006 } 12007 12008 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 12009 inSz); 12010 if (rc < 0) { 12011 ret = (int)rc; 12012 break; 12013 } 12014 pkiMsgSz = (word32)rc; 12015 12016 /* restore saved variables */ 12017 expBlockSz = pkcs7->stream->varOne; 12018 #endif 12019 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 12020 ret = ASN_PARSE_E; 12021 if (ret == 0 && tag != ASN_OCTET_STRING) 12022 ret = ASN_PARSE_E; 12023 12024 if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12025 ret = ASN_PARSE_E; 12026 12027 if (ret == 0 && length != expBlockSz) { 12028 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); 12029 ret = ASN_PARSE_E; 12030 } 12031 12032 if (ret != 0) break; 12033 #ifndef NO_PKCS7_STREAM 12034 /* next chunk of data expected should have the IV */ 12035 pkcs7->stream->expected = length; 12036 12037 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 12038 break; 12039 } 12040 #endif 12041 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5); 12042 FALL_THROUGH; 12043 /* end of stage 4 */ 12044 12045 case WC_PKCS7_STAGE5: 12046 #ifndef NO_PKCS7_STREAM 12047 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 12048 pkcs7->stream->expected + ASN_TAG_SZ + 12049 MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { 12050 return ret; 12051 } 12052 12053 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 12054 inSz); 12055 if (rc < 0) { 12056 ret = (int)rc; 12057 break; 12058 } 12059 pkiMsgSz = (word32)rc; 12060 12061 /* use IV buffer from stream structure */ 12062 tmpIv = pkcs7->stream->tmpIv; 12063 length = pkcs7->stream->expected; 12064 #endif 12065 XMEMCPY(tmpIv, &pkiMsg[idx], length); 12066 idx += length; 12067 /* read encryptedContent, cont[0] */ 12068 if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 12069 ret = ASN_PARSE_E; 12070 if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0)) 12071 ret = ASN_PARSE_E; 12072 12073 if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, 12074 pkiMsgSz) <= 0) 12075 ret = ASN_PARSE_E; 12076 12077 if (ret < 0) 12078 break; 12079 #ifndef NO_PKCS7_STREAM 12080 /* next chunk of data should contain encrypted content */ 12081 pkcs7->stream->varThree = encryptedContentSz; 12082 if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { 12083 break; 12084 } 12085 12086 if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { 12087 pkcs7->stream->flagOne = 1; 12088 } 12089 12090 pkcs7->stream->expected = (pkcs7->stream->maxLen - 12091 pkcs7->stream->totalRd) + pkcs7->stream->length; 12092 12093 #endif 12094 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6); 12095 FALL_THROUGH; 12096 /* end of stage 5 */ 12097 12098 case WC_PKCS7_STAGE6: 12099 #ifndef NO_PKCS7_STREAM 12100 if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, 12101 pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { 12102 return ret; 12103 } 12104 12105 rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, 12106 inSz); 12107 if (rc < 0) { 12108 ret = (int)rc; 12109 break; 12110 } 12111 pkiMsgSz = (word32)rc; 12112 12113 /* restore saved variables */ 12114 expBlockSz = pkcs7->stream->varOne; 12115 encOID = pkcs7->stream->varTwo; 12116 encryptedContentSz = pkcs7->stream->varThree; 12117 version = pkcs7->stream->vers; 12118 tmpIv = pkcs7->stream->tmpIv; 12119 #else 12120 encOID = 0; 12121 #endif 12122 if (ret == 0 && (encryptedContent = (byte*)XMALLOC( 12123 encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL) { 12124 ret = MEMORY_E; 12125 break; 12126 } 12127 12128 if (ret == 0) { 12129 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 12130 idx += encryptedContentSz; 12131 12132 /* decrypt encryptedContent */ 12133 ret = wc_PKCS7_DecryptContent(pkcs7, encOID, 12134 pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, 12135 expBlockSz, NULL, 0, NULL, 0, encryptedContent, 12136 encryptedContentSz, encryptedContent); 12137 if (ret != 0) { 12138 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12139 } 12140 } 12141 12142 if (ret == 0) { 12143 padLen = encryptedContent[encryptedContentSz-1]; 12144 12145 if (padLen > encryptedContentSz) { 12146 WOLFSSL_MSG("Bad padding size found"); 12147 ret = BUFFER_E; 12148 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12149 break; 12150 } 12151 12152 /* copy plaintext to output */ 12153 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 12154 12155 /* get implicit[1] unprotected attributes, optional */ 12156 wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); 12157 pkcs7->decodedAttrib = NULL; 12158 #ifndef NO_PKCS7_STREAM 12159 if (pkcs7->stream->flagOne) 12160 #else 12161 if (idx < pkiMsgSz) 12162 #endif 12163 { 12164 haveAttribs = 1; 12165 12166 ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, 12167 pkiMsgSz, &idx); 12168 if (ret != 0) { 12169 ForceZero(encryptedContent, encryptedContentSz); 12170 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12171 ret = ASN_PARSE_E; 12172 } 12173 } 12174 } 12175 12176 if (ret == 0) { 12177 ForceZero(encryptedContent, encryptedContentSz); 12178 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12179 12180 /* go back and check the version now that attribs have been processed */ 12181 if (pkcs7->version == 3 && version != 0) { 12182 WOLFSSL_MSG("Wrong PKCS#7 FirmwareEncryptedData version"); 12183 return ASN_VERSION_E; 12184 } 12185 12186 if (pkcs7->version != 3 && 12187 ((haveAttribs == 0 && version != 0) || 12188 (haveAttribs == 1 && version != 2))) { 12189 WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); 12190 return ASN_VERSION_E; 12191 } 12192 ret = encryptedContentSz - padLen; 12193 } 12194 12195 if (ret != 0) break; 12196 #ifndef NO_PKCS7_STREAM 12197 wc_PKCS7_ResetStream(pkcs7); 12198 #endif 12199 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 12200 break; 12201 12202 default: 12203 WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state"); 12204 return BAD_STATE_E; 12205 } 12206 12207 if (ret != 0) { 12208 #ifndef NO_PKCS7_STREAM 12209 /* restart in error case */ 12210 wc_PKCS7_ResetStream(pkcs7); 12211 #endif 12212 wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); 12213 } 12214 return ret; 12215 } 12216 12217 12218 /* Function to set callback during decryption, this overrides the default 12219 * decryption function and can be used for choosing a key at run time based 12220 * on the parsed bundle so far. 12221 * returns 0 on success 12222 */ 12223 int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, 12224 CallbackDecryptContent decryptionCb) 12225 { 12226 if (pkcs7 != NULL) { 12227 pkcs7->decryptionCb = decryptionCb; 12228 } 12229 return 0; 12230 } 12231 12232 12233 /* Set an optional user context that gets passed to callback 12234 * returns 0 on success 12235 */ 12236 int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) 12237 { 12238 if (pkcs7 != NULL) { 12239 pkcs7->decryptionCtx = ctx; 12240 } 12241 return 0; 12242 } 12243 #endif /* NO_PKCS7_ENCRYPTED_DATA */ 12244 12245 #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) 12246 12247 /* build PKCS#7 compressedData content type, return encrypted size */ 12248 int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) 12249 { 12250 byte contentInfoSeq[MAX_SEQ_SZ]; 12251 byte contentInfoTypeOid[MAX_OID_SZ]; 12252 byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ 12253 byte compressedDataSeq[MAX_SEQ_SZ]; 12254 byte cmsVersion[MAX_VERSION_SZ]; 12255 byte compressAlgId[MAX_ALGO_SZ]; 12256 byte encapContentInfoSeq[MAX_SEQ_SZ]; 12257 byte contentTypeOid[MAX_OID_SZ]; 12258 byte contentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ 12259 byte contentOctetStr[MAX_OCTET_STR_SZ]; 12260 12261 int ret; 12262 word32 totalSz, idx; 12263 word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz; 12264 word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz; 12265 word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz; 12266 word32 contentOctetStrSz; 12267 12268 byte* compressed; 12269 word32 compressedSz; 12270 12271 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 12272 output == NULL || outputSz == 0) { 12273 return BAD_FUNC_ARG; 12274 } 12275 12276 /* allocate space for compressed content. The libz code says the compressed 12277 * buffer should be srcSz + 0.1% + 12. */ 12278 compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12); 12279 compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12280 if (compressed == NULL) { 12281 WOLFSSL_MSG("Error allocating memory for CMS compressed content"); 12282 return MEMORY_E; 12283 } 12284 12285 /* compress content */ 12286 ret = wc_Compress(compressed, compressedSz, pkcs7->content, 12287 pkcs7->contentSz, 0); 12288 if (ret < 0) { 12289 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12290 return ret; 12291 } 12292 compressedSz = (word32)ret; 12293 12294 /* eContent OCTET STRING, working backwards */ 12295 contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr); 12296 totalSz = contentOctetStrSz + compressedSz; 12297 12298 /* EXPLICIT [0] eContentType */ 12299 contentSeqSz = SetExplicit(0, totalSz, contentSeq); 12300 totalSz += contentSeqSz; 12301 12302 /* eContentType OBJECT IDENTIFIER */ 12303 ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid, 12304 sizeof(contentTypeOid)); 12305 if (ret < 0) { 12306 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12307 return ret; 12308 } 12309 12310 contentTypeOidSz = ret; 12311 totalSz += contentTypeOidSz; 12312 12313 /* EncapsulatedContentInfo SEQUENCE */ 12314 encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq); 12315 totalSz += encapContentInfoSeqSz; 12316 12317 /* compressionAlgorithm AlgorithmIdentifier */ 12318 /* Only supports zlib for compression currently: 12319 * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ 12320 compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0); 12321 totalSz += compressAlgIdSz; 12322 12323 /* version */ 12324 cmsVersionSz = SetMyVersion(0, cmsVersion, 0); 12325 totalSz += cmsVersionSz; 12326 12327 /* CompressedData SEQUENCE */ 12328 compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq); 12329 totalSz += compressedDataSeqSz; 12330 12331 /* ContentInfo content EXPLICIT SEQUENCE */ 12332 contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); 12333 totalSz += contentInfoContentSeqSz; 12334 12335 /* ContentInfo ContentType (compressedData) */ 12336 if (pkcs7->version == 3) { 12337 contentInfoTypeOidSz = 0; 12338 } 12339 else { 12340 ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid, 12341 sizeof(contentInfoTypeOid)); 12342 if (ret < 0) { 12343 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12344 return ret; 12345 } 12346 12347 contentInfoTypeOidSz = ret; 12348 totalSz += contentInfoTypeOidSz; 12349 } 12350 12351 /* ContentInfo SEQUENCE */ 12352 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 12353 totalSz += contentInfoSeqSz; 12354 12355 if (outputSz < totalSz) { 12356 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12357 return BUFFER_E; 12358 } 12359 12360 idx = 0; 12361 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 12362 idx += contentInfoSeqSz; 12363 XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); 12364 idx += contentInfoTypeOidSz; 12365 XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); 12366 idx += contentInfoContentSeqSz; 12367 XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz); 12368 idx += compressedDataSeqSz; 12369 XMEMCPY(output + idx, cmsVersion, cmsVersionSz); 12370 idx += cmsVersionSz; 12371 XMEMCPY(output + idx, compressAlgId, compressAlgIdSz); 12372 idx += compressAlgIdSz; 12373 XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz); 12374 idx += encapContentInfoSeqSz; 12375 XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz); 12376 idx += contentTypeOidSz; 12377 XMEMCPY(output + idx, contentSeq, contentSeqSz); 12378 idx += contentSeqSz; 12379 XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz); 12380 idx += contentOctetStrSz; 12381 XMEMCPY(output + idx, compressed, compressedSz); 12382 idx += compressedSz; 12383 12384 XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12385 12386 return idx; 12387 } 12388 12389 /* unwrap and decompress PKCS#7/CMS compressedData object, 12390 * returned decoded size */ 12391 int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, 12392 byte* output, word32 outputSz) 12393 { 12394 int length, version, ret; 12395 word32 idx = 0, algOID, contentType; 12396 byte tag; 12397 12398 byte* decompressed; 12399 word32 decompressedSz; 12400 12401 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || 12402 output == NULL || outputSz == 0) { 12403 return BAD_FUNC_ARG; 12404 } 12405 12406 /* get ContentInfo SEQUENCE */ 12407 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12408 return ASN_PARSE_E; 12409 12410 if (pkcs7->version != 3) { 12411 /* get ContentInfo contentType */ 12412 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 12413 return ASN_PARSE_E; 12414 12415 if (contentType != COMPRESSED_DATA) 12416 return ASN_PARSE_E; 12417 } 12418 12419 /* get ContentInfo content EXPLICIT SEQUENCE */ 12420 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 12421 return ASN_PARSE_E; 12422 12423 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 12424 return ASN_PARSE_E; 12425 12426 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12427 return ASN_PARSE_E; 12428 12429 /* get CompressedData SEQUENCE */ 12430 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12431 return ASN_PARSE_E; 12432 12433 /* get version */ 12434 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 12435 return ASN_PARSE_E; 12436 12437 if (version != 0) { 12438 WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not"); 12439 return ASN_PARSE_E; 12440 } 12441 12442 /* get CompressionAlgorithmIdentifier */ 12443 if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0) 12444 return ASN_PARSE_E; 12445 12446 /* Only supports zlib for compression currently: 12447 * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ 12448 if (algOID != ZLIBc) { 12449 WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm"); 12450 return ASN_PARSE_E; 12451 } 12452 12453 /* get EncapsulatedContentInfo SEQUENCE */ 12454 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12455 return ASN_PARSE_E; 12456 12457 /* get ContentType OID */ 12458 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 12459 return ASN_PARSE_E; 12460 12461 pkcs7->contentOID = contentType; 12462 12463 /* get eContent EXPLICIT SEQUENCE */ 12464 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 12465 return ASN_PARSE_E; 12466 12467 if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 12468 return ASN_PARSE_E; 12469 12470 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12471 return ASN_PARSE_E; 12472 12473 /* get content OCTET STRING */ 12474 if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) 12475 return ASN_PARSE_E; 12476 12477 if (tag != ASN_OCTET_STRING) 12478 return ASN_PARSE_E; 12479 12480 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 12481 return ASN_PARSE_E; 12482 12483 /* allocate space for decompressed data */ 12484 decompressed = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12485 if (decompressed == NULL) { 12486 WOLFSSL_MSG("Error allocating memory for CMS decompression buffer"); 12487 return MEMORY_E; 12488 } 12489 12490 /* decompress content */ 12491 ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length); 12492 if (ret < 0) { 12493 XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12494 return ret; 12495 } 12496 decompressedSz = (word32)ret; 12497 12498 /* get content */ 12499 if (outputSz < decompressedSz) { 12500 WOLFSSL_MSG("CMS output buffer too small to hold decompressed data"); 12501 XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12502 return BUFFER_E; 12503 } 12504 12505 XMEMCPY(output, decompressed, decompressedSz); 12506 XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 12507 12508 return decompressedSz; 12509 } 12510 12511 #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ 12512 12513 #else /* HAVE_PKCS7 */ 12514 12515 12516 #ifdef _MSC_VER 12517 /* 4206 warning for blank file */ 12518 #pragma warning(disable: 4206) 12519 #endif 12520 12521 12522 #endif /* HAVE_PKCS7 */ 12523 12524
Generated on Tue Jul 12 2022 20:58:41 by
1.7.2