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.
pkcs7.c
00001 /* pkcs7.c 00002 * 00003 * Copyright (C) 2006-2017 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 <wolfcrypt/settings.h> 00028 00029 #ifdef HAVE_PKCS7 00030 00031 #include <wolfcrypt/pkcs7.h> 00032 #include <wolfcrypt/error-crypt.h> 00033 #include <wolfcrypt/logging.h> 00034 #include <wolfcrypt/hash.h> 00035 #ifndef NO_RSA 00036 #include <wolfcrypt/rsa.h> 00037 #endif 00038 #ifdef HAVE_ECC 00039 #include <wolfcrypt/ecc.h> 00040 #endif 00041 #ifdef NO_INLINE 00042 #include <wolfcrypt/misc.h> 00043 #else 00044 #define WOLFSSL_MISC_INCLUDED 00045 #include <wolfcrypt/src/misc.c> 00046 #endif 00047 00048 00049 /* direction for processing, encoding or decoding */ 00050 typedef enum { 00051 WC_PKCS7_ENCODE, 00052 WC_PKCS7_DECODE 00053 } pkcs7Direction; 00054 00055 #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ 00056 MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) 00057 00058 00059 /* placed ASN.1 contentType OID into *output, return idx on success, 00060 * 0 upon failure */ 00061 static int wc_SetContentType(int pkcs7TypeOID, byte* output) 00062 { 00063 /* PKCS#7 content types, RFC 2315, section 14 */ 00064 const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00065 0x0D, 0x01, 0x07 }; 00066 const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00067 0x0D, 0x01, 0x07, 0x01 }; 00068 const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00069 0x0D, 0x01, 0x07, 0x02}; 00070 const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00071 0x0D, 0x01, 0x07, 0x03 }; 00072 const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00073 0x0D, 0x01, 0x07, 0x04 }; 00074 const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00075 0x0D, 0x01, 0x07, 0x05 }; 00076 00077 #ifndef NO_PKCS7_ENCRYPTED_DATA 00078 const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00079 0x0D, 0x01, 0x07, 0x06 }; 00080 #endif 00081 00082 int idSz; 00083 int typeSz = 0, idx = 0; 00084 const byte* typeName = 0; 00085 byte ID_Length[MAX_LENGTH_SZ]; 00086 00087 switch (pkcs7TypeOID) { 00088 case PKCS7_MSG: 00089 typeSz = sizeof(pkcs7); 00090 typeName = pkcs7; 00091 break; 00092 00093 case DATA: 00094 typeSz = sizeof(data); 00095 typeName = data; 00096 break; 00097 00098 case SIGNED_DATA: 00099 typeSz = sizeof(signedData); 00100 typeName = signedData; 00101 break; 00102 00103 case ENVELOPED_DATA: 00104 typeSz = sizeof(envelopedData); 00105 typeName = envelopedData; 00106 break; 00107 00108 case SIGNED_AND_ENVELOPED_DATA: 00109 typeSz = sizeof(signedAndEnveloped); 00110 typeName = signedAndEnveloped; 00111 break; 00112 00113 case DIGESTED_DATA: 00114 typeSz = sizeof(digestedData); 00115 typeName = digestedData; 00116 break; 00117 00118 #ifndef NO_PKCS7_ENCRYPTED_DATA 00119 case ENCRYPTED_DATA: 00120 typeSz = sizeof(encryptedData); 00121 typeName = encryptedData; 00122 break; 00123 #endif 00124 00125 default: 00126 WOLFSSL_MSG("Unknown PKCS#7 Type"); 00127 return 0; 00128 }; 00129 00130 idSz = SetLength(typeSz, ID_Length); 00131 output[idx++] = ASN_OBJECT_ID; 00132 XMEMCPY(output + idx, ID_Length, idSz); 00133 idx += idSz; 00134 XMEMCPY(output + idx, typeName, typeSz); 00135 idx += typeSz; 00136 00137 return idx; 00138 } 00139 00140 00141 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */ 00142 static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, 00143 word32 maxIdx) 00144 { 00145 WOLFSSL_ENTER("wc_GetContentType"); 00146 if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) 00147 return ASN_PARSE_E; 00148 00149 return 0; 00150 } 00151 00152 00153 /* return block size for algorithm represented by oid, or <0 on error */ 00154 static int wc_PKCS7_GetOIDBlockSize(int oid) 00155 { 00156 int blockSz; 00157 00158 switch (oid) { 00159 #ifndef NO_AES 00160 #ifdef WOLFSSL_AES_128 00161 case AES128CBCb: 00162 #endif 00163 #ifdef WOLFSSL_AES_192 00164 case AES192CBCb: 00165 #endif 00166 #ifdef WOLFSSL_AES_256 00167 case AES256CBCb: 00168 #endif 00169 blockSz = AES_BLOCK_SIZE; 00170 break; 00171 #endif 00172 #ifndef NO_DES3 00173 case DESb: 00174 case DES3b: 00175 blockSz = DES_BLOCK_SIZE; 00176 break; 00177 #endif 00178 default: 00179 WOLFSSL_MSG("Unsupported content cipher type"); 00180 return ALGO_ID_E; 00181 }; 00182 00183 return blockSz; 00184 } 00185 00186 00187 /* get key size for algorithm represented by oid, or <0 on error */ 00188 static int wc_PKCS7_GetOIDKeySize(int oid) 00189 { 00190 int blockKeySz; 00191 00192 switch (oid) { 00193 #ifndef NO_AES 00194 #ifdef WOLFSSL_AES_128 00195 case AES128CBCb: 00196 case AES128_WRAP: 00197 blockKeySz = 16; 00198 break; 00199 #endif 00200 #ifdef WOLFSSL_AES_192 00201 case AES192CBCb: 00202 case AES192_WRAP: 00203 blockKeySz = 24; 00204 break; 00205 #endif 00206 #ifdef WOLFSSL_AES_256 00207 case AES256CBCb: 00208 case AES256_WRAP: 00209 blockKeySz = 32; 00210 break; 00211 #endif 00212 #endif 00213 #ifndef NO_DES3 00214 case DESb: 00215 blockKeySz = DES_KEYLEN; 00216 break; 00217 00218 case DES3b: 00219 blockKeySz = DES3_KEYLEN; 00220 break; 00221 #endif 00222 default: 00223 WOLFSSL_MSG("Unsupported content cipher type"); 00224 return ALGO_ID_E; 00225 }; 00226 00227 return blockKeySz; 00228 } 00229 00230 00231 PKCS7* wc_PKCS7_New(void* heap, int devId) 00232 { 00233 PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7); 00234 if (pkcs7) { 00235 XMEMSET(pkcs7, 0, sizeof(PKCS7)); 00236 if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) { 00237 pkcs7->isDynamic = 1; 00238 } 00239 else { 00240 XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7); 00241 pkcs7 = NULL; 00242 } 00243 } 00244 return pkcs7; 00245 } 00246 00247 /* This is to initialize a PKCS7 structure. It sets all values to 0 and can be 00248 * used to set the heap hint. 00249 * 00250 * pkcs7 PKCS7 structure to initialize 00251 * heap memory heap hint for PKCS7 structure to use 00252 * devId currently not used but a place holder for async operations 00253 * 00254 * returns 0 on success or a negative value for failure 00255 */ 00256 int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) 00257 { 00258 WOLFSSL_ENTER("wc_PKCS7_Init"); 00259 00260 if (pkcs7 == NULL) { 00261 return BAD_FUNC_ARG; 00262 } 00263 00264 XMEMSET(pkcs7, 0, sizeof(PKCS7)); 00265 #ifdef WOLFSSL_HEAP_TEST 00266 pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; 00267 #else 00268 pkcs7->heap = heap; 00269 #endif 00270 pkcs7->devId = devId; 00271 00272 return 0; 00273 } 00274 00275 00276 /* init PKCS7 struct with recipient cert, decode into DecodedCert 00277 * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ 00278 int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) 00279 { 00280 int ret = 0; 00281 void* heap; 00282 int devId; 00283 word16 isDynamic; 00284 00285 if (pkcs7 == NULL || (cert == NULL && certSz != 0)) { 00286 return BAD_FUNC_ARG; 00287 } 00288 00289 heap = pkcs7->heap; 00290 devId = pkcs7->devId; 00291 isDynamic = pkcs7->isDynamic; 00292 ret = wc_PKCS7_Init(pkcs7, heap, devId); 00293 if (ret != 0) 00294 return ret; 00295 pkcs7->isDynamic = isDynamic; 00296 00297 if (cert != NULL && certSz > 0) { 00298 #ifdef WOLFSSL_SMALL_STACK 00299 DecodedCert* dCert; 00300 00301 dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 00302 DYNAMIC_TYPE_DCERT); 00303 if (dCert == NULL) 00304 return MEMORY_E; 00305 #else 00306 DecodedCert stack_dCert; 00307 DecodedCert* dCert = &stack_dCert; 00308 #endif 00309 00310 pkcs7->singleCert = cert; 00311 pkcs7->singleCertSz = certSz; 00312 InitDecodedCert(dCert, cert, certSz, pkcs7->heap); 00313 00314 ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); 00315 if (ret < 0) { 00316 FreeDecodedCert(dCert); 00317 #ifdef WOLFSSL_SMALL_STACK 00318 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 00319 #endif 00320 return ret; 00321 } 00322 00323 XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); 00324 pkcs7->publicKeySz = dCert->pubKeySize; 00325 pkcs7->publicKeyOID = dCert->keyOID; 00326 XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE); 00327 pkcs7->issuer = dCert->issuerRaw; 00328 pkcs7->issuerSz = dCert->issuerRawLen; 00329 XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); 00330 pkcs7->issuerSnSz = dCert->serialSz; 00331 FreeDecodedCert(dCert); 00332 00333 #ifdef WOLFSSL_SMALL_STACK 00334 XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); 00335 #endif 00336 } 00337 00338 return ret; 00339 } 00340 00341 00342 /* free linked list of PKCS7DecodedAttrib structs */ 00343 static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) 00344 { 00345 PKCS7DecodedAttrib* current; 00346 00347 if (attrib == NULL) { 00348 return; 00349 } 00350 00351 current = attrib; 00352 while (current != NULL) { 00353 PKCS7DecodedAttrib* next = current->next; 00354 if (current->oid != NULL) { 00355 XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7); 00356 } 00357 if (current->value != NULL) { 00358 XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7); 00359 } 00360 XFREE(current, heap, DYNAMIC_TYPE_PKCS7); 00361 current = next; 00362 } 00363 00364 (void)heap; 00365 } 00366 00367 00368 /* releases any memory allocated by a PKCS7 initializer */ 00369 void wc_PKCS7_Free(PKCS7* pkcs7) 00370 { 00371 if (pkcs7 == NULL) 00372 return; 00373 00374 wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); 00375 00376 #ifdef ASN_BER_TO_DER 00377 if (pkcs7->der != NULL) 00378 XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00379 #endif 00380 00381 if (pkcs7->isDynamic) { 00382 pkcs7->isDynamic = 0; 00383 XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 00384 } 00385 } 00386 00387 00388 /* helper function for parsing through attributes and finding a specific one. 00389 * returns PKCS7DecodedAttrib pointer on success */ 00390 static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz) 00391 { 00392 PKCS7DecodedAttrib* list; 00393 00394 if (pkcs7 == NULL || oid == NULL) { 00395 return NULL; 00396 } 00397 00398 /* search attributes for pkiStatus */ 00399 list = pkcs7->decodedAttrib; 00400 while (list != NULL) { 00401 word32 sz = oidSz; 00402 word32 idx = 0; 00403 int length = 0; 00404 00405 if (list->oid[idx++] != ASN_OBJECT_ID) { 00406 WOLFSSL_MSG("Bad attribute ASN1 syntax"); 00407 return NULL; 00408 } 00409 00410 if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) { 00411 WOLFSSL_MSG("Bad attribute length"); 00412 return NULL; 00413 } 00414 00415 sz = (sz < (word32)length)? sz : (word32)length; 00416 if (XMEMCMP(oid, list->oid + idx, sz) == 0) { 00417 return list; 00418 } 00419 list = list->next; 00420 } 00421 return NULL; 00422 } 00423 00424 00425 /* Searches through decoded attributes and returns the value for the first one 00426 * matching the oid passed in. Note that this value includes the leading ASN1 00427 * syntax. So for a printable string of "3" this would be something like 00428 * 00429 * 0x13, 0x01, 0x33 00430 * ID SIZE "3" 00431 * 00432 * pkcs7 structure to get value from 00433 * oid OID value to search for with attributes 00434 * oidSz size of oid buffer 00435 * out buffer to hold result 00436 * outSz size of out buffer (if out is NULL this is set to needed size and 00437 LENGTH_ONLY_E is returned) 00438 * 00439 * returns size of value on success 00440 */ 00441 int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz, 00442 byte* out, word32* outSz) 00443 { 00444 PKCS7DecodedAttrib* attrib; 00445 00446 if (pkcs7 == NULL || oid == NULL || outSz == NULL) { 00447 return BAD_FUNC_ARG; 00448 } 00449 00450 attrib = findAttrib(pkcs7, oid, oidSz); 00451 if (attrib == NULL) { 00452 return ASN_PARSE_E; 00453 } 00454 00455 if (out == NULL) { 00456 *outSz = attrib->valueSz; 00457 return LENGTH_ONLY_E; 00458 } 00459 00460 if (*outSz < attrib->valueSz) { 00461 return BUFFER_E; 00462 } 00463 00464 XMEMCPY(out, attrib->value, attrib->valueSz); 00465 return attrib->valueSz; 00466 } 00467 00468 00469 /* build PKCS#7 data content type */ 00470 int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz) 00471 { 00472 static const byte oid[] = 00473 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 00474 0x07, 0x01 }; 00475 byte seq[MAX_SEQ_SZ]; 00476 byte octetStr[MAX_OCTET_STR_SZ]; 00477 word32 seqSz; 00478 word32 octetStrSz; 00479 word32 oidSz = (word32)sizeof(oid); 00480 int idx = 0; 00481 00482 if (pkcs7 == NULL || output == NULL) { 00483 return BAD_FUNC_ARG; 00484 } 00485 00486 octetStrSz = SetOctetString(pkcs7->contentSz, octetStr); 00487 seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq); 00488 00489 if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz) 00490 return BUFFER_E; 00491 00492 XMEMCPY(output, seq, seqSz); 00493 idx += seqSz; 00494 XMEMCPY(output + idx, oid, oidSz); 00495 idx += oidSz; 00496 XMEMCPY(output + idx, octetStr, octetStrSz); 00497 idx += octetStrSz; 00498 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 00499 idx += pkcs7->contentSz; 00500 00501 return idx; 00502 } 00503 00504 00505 typedef struct EncodedAttrib { 00506 byte valueSeq[MAX_SEQ_SZ]; 00507 const byte* oid; 00508 byte valueSet[MAX_SET_SZ]; 00509 const byte* value; 00510 word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz; 00511 } EncodedAttrib; 00512 00513 00514 typedef struct ESD { 00515 wc_HashAlg hash; 00516 enum wc_HashType hashType; 00517 byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ 00518 byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; 00519 byte encContentDigest[MAX_ENCRYPTED_KEY_SZ]; 00520 00521 byte outerSeq[MAX_SEQ_SZ]; 00522 byte outerContent[MAX_EXP_SZ]; 00523 byte innerSeq[MAX_SEQ_SZ]; 00524 byte version[MAX_VERSION_SZ]; 00525 byte digAlgoIdSet[MAX_SET_SZ]; 00526 byte singleDigAlgoId[MAX_ALGO_SZ]; 00527 00528 byte contentInfoSeq[MAX_SEQ_SZ]; 00529 byte innerContSeq[MAX_EXP_SZ]; 00530 byte innerOctets[MAX_OCTET_STR_SZ]; 00531 00532 byte certsSet[MAX_SET_SZ]; 00533 00534 byte signerInfoSet[MAX_SET_SZ]; 00535 byte signerInfoSeq[MAX_SEQ_SZ]; 00536 byte signerVersion[MAX_VERSION_SZ]; 00537 byte issuerSnSeq[MAX_SEQ_SZ]; 00538 byte issuerName[MAX_SEQ_SZ]; 00539 byte issuerSn[MAX_SN_SZ]; 00540 byte signerDigAlgoId[MAX_ALGO_SZ]; 00541 byte digEncAlgoId[MAX_ALGO_SZ]; 00542 byte signedAttribSet[MAX_SET_SZ]; 00543 EncodedAttrib signedAttribs[6]; 00544 byte signerDigest[MAX_OCTET_STR_SZ]; 00545 word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; 00546 word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, 00547 singleDigAlgoIdSz, certsSetSz; 00548 word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, 00549 issuerSnSeqSz, issuerNameSz, issuerSnSz, 00550 signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; 00551 word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, 00552 signedAttribSetSz; 00553 } ESD; 00554 00555 00556 static int EncodeAttributes(EncodedAttrib* ea, int eaSz, 00557 PKCS7Attrib* attribs, int attribsSz) 00558 { 00559 int i; 00560 int maxSz = min(eaSz, attribsSz); 00561 int allAttribsSz = 0; 00562 00563 for (i = 0; i < maxSz; i++) 00564 { 00565 int attribSz = 0; 00566 00567 ea[i].value = attribs[i].value; 00568 ea[i].valueSz = attribs[i].valueSz; 00569 attribSz += ea[i].valueSz; 00570 ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet); 00571 attribSz += ea[i].valueSetSz; 00572 ea[i].oid = attribs[i].oid; 00573 ea[i].oidSz = attribs[i].oidSz; 00574 attribSz += ea[i].oidSz; 00575 ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq); 00576 attribSz += ea[i].valueSeqSz; 00577 ea[i].totalSz = attribSz; 00578 00579 allAttribsSz += attribSz; 00580 } 00581 return allAttribsSz; 00582 } 00583 00584 00585 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) 00586 { 00587 int i, idx; 00588 00589 idx = 0; 00590 for (i = 0; i < eaSz; i++) { 00591 XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz); 00592 idx += ea[i].valueSeqSz; 00593 XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz); 00594 idx += ea[i].oidSz; 00595 XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz); 00596 idx += ea[i].valueSetSz; 00597 XMEMCPY(output + idx, ea[i].value, ea[i].valueSz); 00598 idx += ea[i].valueSz; 00599 } 00600 return 0; 00601 } 00602 00603 00604 #ifndef NO_RSA 00605 00606 /* returns size of signature put into out, negative on error */ 00607 static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) 00608 { 00609 int ret; 00610 word32 idx; 00611 #ifdef WOLFSSL_SMALL_STACK 00612 RsaKey* privKey; 00613 #else 00614 RsaKey stack_privKey; 00615 RsaKey* privKey = &stack_privKey; 00616 #endif 00617 00618 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { 00619 return BAD_FUNC_ARG; 00620 } 00621 00622 #ifdef WOLFSSL_SMALL_STACK 00623 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, 00624 DYNAMIC_TYPE_TMP_BUFFER); 00625 if (privKey == NULL) 00626 return MEMORY_E; 00627 #endif 00628 00629 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); 00630 if (ret == 0) { 00631 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 00632 idx = 0; 00633 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, 00634 pkcs7->privateKeySz); 00635 } 00636 else if (pkcs7->devId == INVALID_DEVID) { 00637 ret = BAD_FUNC_ARG; 00638 } 00639 } 00640 if (ret == 0) { 00641 ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, 00642 sizeof(esd->encContentDigest), 00643 privKey, pkcs7->rng); 00644 } 00645 00646 wc_FreeRsaKey(privKey); 00647 #ifdef WOLFSSL_SMALL_STACK 00648 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 00649 #endif 00650 00651 return ret; 00652 } 00653 00654 #endif /* NO_RSA */ 00655 00656 00657 #ifdef HAVE_ECC 00658 00659 /* returns size of signature put into out, negative on error */ 00660 static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) 00661 { 00662 int ret; 00663 word32 outSz, idx; 00664 #ifdef WOLFSSL_SMALL_STACK 00665 ecc_key* privKey; 00666 #else 00667 ecc_key stack_privKey; 00668 ecc_key* privKey = &stack_privKey; 00669 #endif 00670 00671 if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { 00672 return BAD_FUNC_ARG; 00673 } 00674 00675 #ifdef WOLFSSL_SMALL_STACK 00676 privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 00677 DYNAMIC_TYPE_TMP_BUFFER); 00678 if (privKey == NULL) 00679 return MEMORY_E; 00680 #endif 00681 00682 ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); 00683 if (ret == 0) { 00684 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 00685 idx = 0; 00686 ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, 00687 pkcs7->privateKeySz); 00688 } 00689 else if (pkcs7->devId == INVALID_DEVID) { 00690 ret = BAD_FUNC_ARG; 00691 } 00692 } 00693 if (ret == 0) { 00694 outSz = sizeof(esd->encContentDigest); 00695 ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, 00696 &outSz, pkcs7->rng, privKey); 00697 if (ret == 0) 00698 ret = (int)outSz; 00699 } 00700 00701 wc_ecc_free(privKey); 00702 #ifdef WOLFSSL_SMALL_STACK 00703 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 00704 #endif 00705 00706 return ret; 00707 } 00708 00709 #endif /* HAVE_ECC */ 00710 00711 00712 /* builds up SignedData signed attributes, including default ones. 00713 * 00714 * pkcs7 - pointer to initialized PKCS7 structure 00715 * esd - pointer to initialized ESD structure, used for output 00716 * 00717 * return 0 on success, negative on error */ 00718 static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, 00719 byte* contentTypeOid, word32 contentTypeOidSz, 00720 byte* contentType, word32 contentTypeSz, 00721 byte* messageDigestOid, word32 messageDigestOidSz) 00722 { 00723 int hashSz; 00724 00725 PKCS7Attrib cannedAttribs[2]; 00726 word32 cannedAttribsCount; 00727 00728 if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || 00729 contentType == NULL || messageDigestOid == NULL) 00730 return BAD_FUNC_ARG; 00731 00732 hashSz = wc_HashGetDigestSize(esd->hashType); 00733 if (hashSz < 0) 00734 return hashSz; 00735 00736 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); 00737 00738 cannedAttribs[0].oid = contentTypeOid; 00739 cannedAttribs[0].oidSz = contentTypeOidSz; 00740 cannedAttribs[0].value = contentType; 00741 cannedAttribs[0].valueSz = contentTypeSz; 00742 cannedAttribs[1].oid = messageDigestOid; 00743 cannedAttribs[1].oidSz = messageDigestOidSz; 00744 cannedAttribs[1].value = esd->contentDigest; 00745 cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ 00746 00747 esd->signedAttribsCount += cannedAttribsCount; 00748 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, 00749 cannedAttribs, cannedAttribsCount); 00750 00751 esd->signedAttribsCount += pkcs7->signedAttribsSz; 00752 esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, 00753 pkcs7->signedAttribs, pkcs7->signedAttribsSz); 00754 00755 return 0; 00756 } 00757 00758 00759 /* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or 00760 * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID. 00761 * 00762 * pkcs7 - pointer to PKCS7 structure 00763 * digEncAlgoId - [OUT] output int to store correct algo ID in 00764 * digEncAlgoType - [OUT] output for algo ID type 00765 * 00766 * return 0 on success, negative on error */ 00767 static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, 00768 int* digEncAlgoType) 00769 { 00770 int algoId = 0; 00771 int algoType = 0; 00772 00773 if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) 00774 return BAD_FUNC_ARG; 00775 00776 if (pkcs7->publicKeyOID == RSAk) { 00777 00778 algoType = oidSigType; 00779 00780 switch (pkcs7->hashOID) { 00781 #ifndef NO_SHA 00782 case SHAh: 00783 algoId = CTC_SHAwRSA; 00784 break; 00785 #endif 00786 #ifdef WOLFSSL_SHA224 00787 case SHA224h: 00788 algoId = CTC_SHA224wRSA; 00789 break; 00790 #endif 00791 #ifndef NO_SHA256 00792 case SHA256h: 00793 algoId = CTC_SHA256wRSA; 00794 break; 00795 #endif 00796 #ifdef WOLFSSL_SHA384 00797 case SHA384h: 00798 algoId = CTC_SHA384wRSA; 00799 break; 00800 #endif 00801 #ifdef WOLFSSL_SHA512 00802 case SHA512h: 00803 algoId = CTC_SHA512wRSA; 00804 break; 00805 #endif 00806 } 00807 00808 } 00809 #ifdef HAVE_ECC 00810 else if (pkcs7->publicKeyOID == ECDSAk) { 00811 00812 algoType = oidSigType; 00813 00814 switch (pkcs7->hashOID) { 00815 #ifndef NO_SHA 00816 case SHAh: 00817 algoId = CTC_SHAwECDSA; 00818 break; 00819 #endif 00820 #ifdef WOLFSSL_SHA224 00821 case SHA224h: 00822 algoId = CTC_SHA224wECDSA; 00823 break; 00824 #endif 00825 #ifndef NO_SHA256 00826 case SHA256h: 00827 algoId = CTC_SHA256wECDSA; 00828 break; 00829 #endif 00830 #ifdef WOLFSSL_SHA384 00831 case SHA384h: 00832 algoId = CTC_SHA384wECDSA; 00833 break; 00834 #endif 00835 #ifdef WOLFSSL_SHA512 00836 case SHA512h: 00837 algoId = CTC_SHA512wECDSA; 00838 break; 00839 #endif 00840 } 00841 } 00842 #endif /* HAVE_ECC */ 00843 00844 if (algoId == 0) { 00845 WOLFSSL_MSG("Invalid signature algorithm type"); 00846 return BAD_FUNC_ARG; 00847 } 00848 00849 *digEncAlgoId = algoId; 00850 *digEncAlgoType = algoType; 00851 00852 return 0; 00853 } 00854 00855 00856 /* build SignedData DigestInfo for use with PKCS#7/RSA 00857 * 00858 * pkcs7 - pointer to initialized PKCS7 struct 00859 * flatSignedAttribs - flattened, signed attributes 00860 * flatSignedAttrbsSz - size of flatSignedAttribs, octets 00861 * esd - pointer to initialized ESD struct 00862 * digestInfo - [OUT] output array for DigestInfo 00863 * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo 00864 * 00865 * return 0 on success, negative on error */ 00866 static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, 00867 word32 flatSignedAttribsSz, ESD* esd, 00868 byte* digestInfo, word32* digestInfoSz) 00869 { 00870 int ret, hashSz, digIdx = 0; 00871 byte digestInfoSeq[MAX_SEQ_SZ]; 00872 byte digestStr[MAX_OCTET_STR_SZ]; 00873 byte attribSet[MAX_SET_SZ]; 00874 byte algoId[MAX_ALGO_SZ]; 00875 word32 digestInfoSeqSz, digestStrSz, algoIdSz; 00876 word32 attribSetSz; 00877 00878 if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || 00879 digestInfoSz == NULL) { 00880 return BAD_FUNC_ARG; 00881 } 00882 00883 hashSz = wc_HashGetDigestSize(esd->hashType); 00884 if (hashSz < 0) 00885 return hashSz; 00886 00887 if (pkcs7->signedAttribsSz != 0) { 00888 00889 if (flatSignedAttribs == NULL) 00890 return BAD_FUNC_ARG; 00891 00892 attribSetSz = SetSet(flatSignedAttribsSz, attribSet); 00893 00894 ret = wc_HashInit(&esd->hash, esd->hashType); 00895 if (ret < 0) 00896 return ret; 00897 00898 ret = wc_HashUpdate(&esd->hash, esd->hashType, 00899 attribSet, attribSetSz); 00900 if (ret < 0) 00901 return ret; 00902 00903 ret = wc_HashUpdate(&esd->hash, esd->hashType, 00904 flatSignedAttribs, flatSignedAttribsSz); 00905 if (ret < 0) 00906 return ret; 00907 00908 ret = wc_HashFinal(&esd->hash, esd->hashType, 00909 esd->contentAttribsDigest); 00910 if (ret < 0) 00911 return ret; 00912 00913 } else { 00914 /* when no attrs, digest is contentDigest without tag and length */ 00915 XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); 00916 } 00917 00918 /* set algoID, with NULL attributes */ 00919 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); 00920 00921 digestStrSz = SetOctetString(hashSz, digestStr); 00922 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, 00923 digestInfoSeq); 00924 00925 if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { 00926 return BUFFER_E; 00927 } 00928 00929 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); 00930 digIdx += digestInfoSeqSz; 00931 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); 00932 digIdx += algoIdSz; 00933 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); 00934 digIdx += digestStrSz; 00935 XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); 00936 digIdx += hashSz; 00937 00938 *digestInfoSz = digIdx; 00939 00940 return 0; 00941 } 00942 00943 00944 /* build SignedData signature over DigestInfo or content digest 00945 * 00946 * pkcs7 - pointer to initizlied PKCS7 struct 00947 * flatSignedAttribs - flattened, signed attributes 00948 * flatSignedAttribsSz - size of flatSignedAttribs, octets 00949 * esd - pointer to initialized ESD struct 00950 * 00951 * returns length of signature on success, negative on error */ 00952 static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, 00953 byte* flatSignedAttribs, 00954 word32 flatSignedAttribsSz, 00955 ESD* esd) 00956 { 00957 int ret; 00958 #ifdef HAVE_ECC 00959 int hashSz; 00960 #endif 00961 word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; 00962 #ifdef WOLFSSL_SMALL_STACK 00963 byte* digestInfo; 00964 #else 00965 byte digestInfo[MAX_PKCS7_DIGEST_SZ]; 00966 #endif 00967 00968 if (pkcs7 == NULL || esd == NULL) 00969 return BAD_FUNC_ARG; 00970 00971 #ifdef WOLFSSL_SMALL_STACK 00972 digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap, 00973 DYNAMIC_TYPE_TMP_BUFFER); 00974 if (digestInfo == NULL) { 00975 return MEMORY_E; 00976 } 00977 #endif 00978 00979 ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, 00980 flatSignedAttribsSz, esd, digestInfo, 00981 &digestInfoSz); 00982 if (ret < 0) { 00983 #ifdef WOLFSSL_SMALL_STACK 00984 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 00985 #endif 00986 return ret; 00987 } 00988 00989 /* sign digestInfo */ 00990 switch (pkcs7->publicKeyOID) { 00991 00992 #ifndef NO_RSA 00993 case RSAk: 00994 ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); 00995 break; 00996 #endif 00997 00998 #ifdef HAVE_ECC 00999 case ECDSAk: 01000 /* CMS with ECDSA does not sign DigestInfo structure 01001 * like PKCS#7 with RSA does */ 01002 hashSz = wc_HashGetDigestSize(esd->hashType); 01003 if (hashSz < 0) { 01004 #ifdef WOLFSSL_SMALL_STACK 01005 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01006 #endif 01007 return hashSz; 01008 } 01009 01010 ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, 01011 hashSz, esd); 01012 break; 01013 #endif 01014 01015 default: 01016 WOLFSSL_MSG("Unsupported public key type"); 01017 ret = BAD_FUNC_ARG; 01018 } 01019 01020 #ifdef WOLFSSL_SMALL_STACK 01021 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01022 #endif 01023 01024 if (ret >= 0) { 01025 esd->encContentDigestSz = (word32)ret; 01026 } 01027 01028 return ret; 01029 } 01030 01031 /* build PKCS#7 signedData content type */ 01032 int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) 01033 { 01034 static const byte outerOid[] = 01035 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 01036 0x07, 0x02 }; 01037 static const byte innerOid[] = 01038 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 01039 0x07, 0x01 }; 01040 01041 byte contentTypeOid[] = 01042 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 01043 0x09, 0x03 }; 01044 byte contentType[] = 01045 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 01046 0x07, 0x01 }; 01047 byte messageDigestOid[] = 01048 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 01049 0x09, 0x04 }; 01050 01051 #ifdef WOLFSSL_SMALL_STACK 01052 ESD* esd = NULL; 01053 #else 01054 ESD stack_esd; 01055 ESD* esd = &stack_esd; 01056 #endif 01057 01058 word32 signerInfoSz = 0; 01059 word32 totalSz = 0; 01060 int idx = 0, ret = 0; 01061 int digEncAlgoId, digEncAlgoType, hashSz; 01062 byte* flatSignedAttribs = NULL; 01063 word32 flatSignedAttribsSz = 0; 01064 word32 innerOidSz = sizeof(innerOid); 01065 word32 outerOidSz = sizeof(outerOid); 01066 01067 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 01068 pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || 01069 pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || 01070 output == NULL || outputSz == 0) { 01071 return BAD_FUNC_ARG; 01072 } 01073 01074 #ifdef WOLFSSL_SMALL_STACK 01075 esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01076 if (esd == NULL) 01077 return MEMORY_E; 01078 #endif 01079 01080 XMEMSET(esd, 0, sizeof(ESD)); 01081 01082 esd->hashType = wc_OidGetHash(pkcs7->hashOID); 01083 ret = wc_HashGetDigestSize(esd->hashType); 01084 if (ret < 0) { 01085 #ifdef WOLFSSL_SMALL_STACK 01086 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01087 #endif 01088 return ret; 01089 } 01090 hashSz = ret; 01091 01092 ret = wc_HashInit(&esd->hash, esd->hashType); 01093 if (ret != 0) { 01094 #ifdef WOLFSSL_SMALL_STACK 01095 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01096 #endif 01097 return ret; 01098 } 01099 01100 if (pkcs7->contentSz != 0) 01101 { 01102 ret = wc_HashUpdate(&esd->hash, esd->hashType, 01103 pkcs7->content, pkcs7->contentSz); 01104 if (ret < 0) { 01105 #ifdef WOLFSSL_SMALL_STACK 01106 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01107 #endif 01108 return ret; 01109 } 01110 esd->contentDigest[0] = ASN_OCTET_STRING; 01111 esd->contentDigest[1] = (byte)hashSz; 01112 ret = wc_HashFinal(&esd->hash, esd->hashType, 01113 &esd->contentDigest[2]); 01114 if (ret < 0) { 01115 #ifdef WOLFSSL_SMALL_STACK 01116 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01117 #endif 01118 return ret; 01119 } 01120 } 01121 01122 esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); 01123 esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz, 01124 esd->innerContSeq); 01125 esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz + 01126 innerOidSz + esd->innerContSeqSz, 01127 esd->contentInfoSeq); 01128 01129 esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, 01130 esd->issuerSn, MAX_SN_SZ); 01131 signerInfoSz += esd->issuerSnSz; 01132 esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); 01133 signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; 01134 esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); 01135 signerInfoSz += esd->issuerSnSeqSz; 01136 esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); 01137 signerInfoSz += esd->signerVersionSz; 01138 esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, 01139 oidHashType, 0); 01140 signerInfoSz += esd->signerDigAlgoIdSz; 01141 01142 /* set signatureAlgorithm */ 01143 ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, 01144 &digEncAlgoType); 01145 if (ret < 0) { 01146 #ifdef WOLFSSL_SMALL_STACK 01147 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01148 #endif 01149 return ret; 01150 } 01151 esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, 01152 digEncAlgoType, 0); 01153 signerInfoSz += esd->digEncAlgoIdSz; 01154 01155 if (pkcs7->signedAttribsSz != 0) { 01156 01157 /* build up signed attributes */ 01158 ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, 01159 contentTypeOid, sizeof(contentTypeOid), 01160 contentType, sizeof(contentType), 01161 messageDigestOid, sizeof(messageDigestOid)); 01162 if (ret < 0) { 01163 #ifdef WOLFSSL_SMALL_STACK 01164 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01165 #endif 01166 return MEMORY_E; 01167 } 01168 01169 flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, 01170 DYNAMIC_TYPE_PKCS7); 01171 flatSignedAttribsSz = esd->signedAttribsSz; 01172 if (flatSignedAttribs == NULL) { 01173 #ifdef WOLFSSL_SMALL_STACK 01174 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01175 #endif 01176 return MEMORY_E; 01177 } 01178 01179 FlattenAttributes(flatSignedAttribs, 01180 esd->signedAttribs, esd->signedAttribsCount); 01181 esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, 01182 esd->signedAttribSet); 01183 } 01184 01185 /* Calculate the final hash and encrypt it. */ 01186 ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, 01187 flatSignedAttribsSz, esd); 01188 if (ret < 0) { 01189 if (pkcs7->signedAttribsSz != 0) 01190 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01191 #ifdef WOLFSSL_SMALL_STACK 01192 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01193 #endif 01194 return ret; 01195 } 01196 01197 signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; 01198 01199 esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, 01200 esd->signerDigest); 01201 signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; 01202 01203 esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); 01204 signerInfoSz += esd->signerInfoSeqSz; 01205 esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); 01206 signerInfoSz += esd->signerInfoSetSz; 01207 01208 esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, 01209 esd->certsSet); 01210 01211 esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, 01212 oidHashType, 0); 01213 esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); 01214 01215 01216 esd->versionSz = SetMyVersion(1, esd->version, 0); 01217 01218 totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + 01219 esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz + 01220 esd->innerOctetsSz + esd->innerContSeqSz + 01221 innerOidSz + pkcs7->contentSz + 01222 signerInfoSz; 01223 esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq); 01224 totalSz += esd->innerSeqSz; 01225 esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent); 01226 totalSz += esd->outerContentSz + outerOidSz; 01227 esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq); 01228 totalSz += esd->outerSeqSz; 01229 01230 if (outputSz < totalSz) { 01231 if (pkcs7->signedAttribsSz != 0) 01232 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01233 #ifdef WOLFSSL_SMALL_STACK 01234 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01235 #endif 01236 return BUFFER_E; 01237 } 01238 01239 idx = 0; 01240 XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); 01241 idx += esd->outerSeqSz; 01242 XMEMCPY(output + idx, outerOid, outerOidSz); 01243 idx += outerOidSz; 01244 XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); 01245 idx += esd->outerContentSz; 01246 XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); 01247 idx += esd->innerSeqSz; 01248 XMEMCPY(output + idx, esd->version, esd->versionSz); 01249 idx += esd->versionSz; 01250 XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); 01251 idx += esd->digAlgoIdSetSz; 01252 XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); 01253 idx += esd->singleDigAlgoIdSz; 01254 XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); 01255 idx += esd->contentInfoSeqSz; 01256 XMEMCPY(output + idx, innerOid, innerOidSz); 01257 idx += innerOidSz; 01258 XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); 01259 idx += esd->innerContSeqSz; 01260 XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); 01261 idx += esd->innerOctetsSz; 01262 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 01263 idx += pkcs7->contentSz; 01264 XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz); 01265 idx += esd->certsSetSz; 01266 XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); 01267 idx += pkcs7->singleCertSz; 01268 XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz); 01269 idx += esd->signerInfoSetSz; 01270 XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); 01271 idx += esd->signerInfoSeqSz; 01272 XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz); 01273 idx += esd->signerVersionSz; 01274 XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); 01275 idx += esd->issuerSnSeqSz; 01276 XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz); 01277 idx += esd->issuerNameSz; 01278 XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); 01279 idx += pkcs7->issuerSz; 01280 XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz); 01281 idx += esd->issuerSnSz; 01282 XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); 01283 idx += esd->signerDigAlgoIdSz; 01284 01285 /* SignerInfo:Attributes */ 01286 if (flatSignedAttribsSz > 0) { 01287 XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); 01288 idx += esd->signedAttribSetSz; 01289 XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); 01290 idx += flatSignedAttribsSz; 01291 XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01292 } 01293 01294 XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); 01295 idx += esd->digEncAlgoIdSz; 01296 XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz); 01297 idx += esd->signerDigestSz; 01298 XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz); 01299 idx += esd->encContentDigestSz; 01300 01301 #ifdef WOLFSSL_SMALL_STACK 01302 XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01303 #endif 01304 01305 return idx; 01306 } 01307 01308 01309 #ifndef NO_RSA 01310 01311 /* returns size of signature put into out, negative on error */ 01312 static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, 01313 byte* hash, word32 hashSz) 01314 { 01315 int ret = 0; 01316 word32 scratch = 0; 01317 #ifdef WOLFSSL_SMALL_STACK 01318 byte* digest; 01319 RsaKey* key; 01320 #else 01321 byte digest[MAX_PKCS7_DIGEST_SZ]; 01322 RsaKey stack_key; 01323 RsaKey* key = &stack_key; 01324 #endif 01325 01326 if (pkcs7 == NULL || sig == NULL || hash == NULL) { 01327 return BAD_FUNC_ARG; 01328 } 01329 01330 #ifdef WOLFSSL_SMALL_STACK 01331 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 01332 DYNAMIC_TYPE_TMP_BUFFER); 01333 01334 if (digest == NULL) 01335 return MEMORY_E; 01336 01337 key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01338 if (key == NULL) { 01339 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01340 return MEMORY_E; 01341 } 01342 #endif 01343 01344 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); 01345 01346 ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); 01347 if (ret != 0) { 01348 #ifdef WOLFSSL_SMALL_STACK 01349 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01350 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01351 #endif 01352 return ret; 01353 } 01354 01355 if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, 01356 pkcs7->publicKeySz) < 0) { 01357 WOLFSSL_MSG("ASN RSA key decode error"); 01358 wc_FreeRsaKey(key); 01359 #ifdef WOLFSSL_SMALL_STACK 01360 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01361 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01362 #endif 01363 return PUBLIC_KEY_E; 01364 } 01365 01366 ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); 01367 01368 wc_FreeRsaKey(key); 01369 01370 if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { 01371 ret = SIG_VERIFY_E; 01372 } 01373 01374 #ifdef WOLFSSL_SMALL_STACK 01375 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01376 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01377 #endif 01378 01379 return ret; 01380 } 01381 01382 #endif /* NO_RSA */ 01383 01384 01385 #ifdef HAVE_ECC 01386 01387 /* returns size of signature put into out, negative on error */ 01388 static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, 01389 byte* hash, word32 hashSz) 01390 { 01391 int ret = 0; 01392 int res = 0; 01393 #ifdef WOLFSSL_SMALL_STACK 01394 byte* digest; 01395 ecc_key* key; 01396 #else 01397 byte digest[MAX_PKCS7_DIGEST_SZ]; 01398 ecc_key stack_key; 01399 ecc_key* key = &stack_key; 01400 #endif 01401 word32 idx = 0; 01402 01403 if (pkcs7 == NULL || sig == NULL) 01404 return BAD_FUNC_ARG; 01405 01406 #ifdef WOLFSSL_SMALL_STACK 01407 digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 01408 DYNAMIC_TYPE_TMP_BUFFER); 01409 01410 if (digest == NULL) 01411 return MEMORY_E; 01412 01413 key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01414 if (key == NULL) { 01415 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01416 return MEMORY_E; 01417 } 01418 #endif 01419 01420 XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); 01421 01422 ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); 01423 if (ret != 0) { 01424 #ifdef WOLFSSL_SMALL_STACK 01425 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01426 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01427 #endif 01428 return ret; 01429 } 01430 01431 if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, 01432 pkcs7->publicKeySz) < 0) { 01433 WOLFSSL_MSG("ASN ECDSA key decode error"); 01434 wc_ecc_free(key); 01435 #ifdef WOLFSSL_SMALL_STACK 01436 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01437 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01438 #endif 01439 return PUBLIC_KEY_E; 01440 } 01441 01442 ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); 01443 01444 wc_ecc_free(key); 01445 01446 if (ret == 0 && res != 1) { 01447 ret = SIG_VERIFY_E; 01448 } 01449 01450 #ifdef WOLFSSL_SMALL_STACK 01451 XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01452 XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01453 #endif 01454 01455 return ret; 01456 } 01457 01458 #endif /* HAVE_ECC */ 01459 01460 01461 /* build SignedData digest, both in PKCS#7 DigestInfo format and 01462 * as plain digest for CMS. 01463 * 01464 * pkcs7 - pointer to initialized PKCS7 struct 01465 * signedAttrib - signed attributes 01466 * signedAttribSz - size of signedAttrib, octets 01467 * pkcs7Digest - [OUT] PKCS#7 DigestInfo 01468 * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest 01469 * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest 01470 * plainDigestSz - [OUT] size of digest at plainDigest 01471 * 01472 * returns 0 on success, negative on error */ 01473 static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, 01474 word32 signedAttribSz, byte* pkcs7Digest, 01475 word32* pkcs7DigestSz, byte** plainDigest, 01476 word32* plainDigestSz) 01477 { 01478 int ret = 0, digIdx = 0, hashSz; 01479 word32 attribSetSz; 01480 byte attribSet[MAX_SET_SZ]; 01481 byte digest[WC_MAX_DIGEST_SIZE]; 01482 byte digestInfoSeq[MAX_SEQ_SZ]; 01483 byte digestStr[MAX_OCTET_STR_SZ]; 01484 byte algoId[MAX_ALGO_SZ]; 01485 word32 digestInfoSeqSz, digestStrSz, algoIdSz; 01486 #ifdef WOLFSSL_SMALL_STACK 01487 byte* digestInfo; 01488 #else 01489 byte digestInfo[MAX_PKCS7_DIGEST_SZ]; 01490 #endif 01491 01492 wc_HashAlg hash; 01493 enum wc_HashType hashType; 01494 01495 if (pkcs7 == NULL || pkcs7Digest == NULL || 01496 pkcs7DigestSz == NULL || plainDigest == NULL) { 01497 return BAD_FUNC_ARG; 01498 } 01499 01500 #ifdef WOLFSSL_SMALL_STACK 01501 digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 01502 DYNAMIC_TYPE_TMP_BUFFER); 01503 if (digestInfo == NULL) 01504 return MEMORY_E; 01505 #endif 01506 01507 XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); 01508 XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); 01509 XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); 01510 01511 hashType = wc_OidGetHash(pkcs7->hashOID); 01512 ret = wc_HashGetDigestSize(hashType); 01513 if (ret < 0) { 01514 #ifdef WOLFSSL_SMALL_STACK 01515 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01516 #endif 01517 return ret; 01518 } 01519 hashSz = ret; 01520 01521 /* calculate digest */ 01522 ret = wc_HashInit(&hash, hashType); 01523 if (ret < 0) { 01524 #ifdef WOLFSSL_SMALL_STACK 01525 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01526 #endif 01527 return ret; 01528 } 01529 01530 if (signedAttribSz > 0) { 01531 01532 if (signedAttrib == NULL) { 01533 #ifdef WOLFSSL_SMALL_STACK 01534 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01535 #endif 01536 return BAD_FUNC_ARG; 01537 } 01538 01539 attribSetSz = SetSet(signedAttribSz, attribSet); 01540 ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); 01541 if (ret < 0) { 01542 #ifdef WOLFSSL_SMALL_STACK 01543 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01544 #endif 01545 return ret; 01546 } 01547 01548 ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); 01549 if (ret < 0) { 01550 #ifdef WOLFSSL_SMALL_STACK 01551 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01552 #endif 01553 return ret; 01554 } 01555 01556 ret = wc_HashFinal(&hash, hashType, digest); 01557 if (ret < 0) { 01558 #ifdef WOLFSSL_SMALL_STACK 01559 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01560 #endif 01561 return ret; 01562 } 01563 01564 } else { 01565 01566 if (pkcs7->content == NULL) { 01567 #ifdef WOLFSSL_SMALL_STACK 01568 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01569 #endif 01570 return BAD_FUNC_ARG; 01571 } 01572 01573 ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); 01574 if (ret < 0) { 01575 #ifdef WOLFSSL_SMALL_STACK 01576 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01577 #endif 01578 return ret; 01579 } 01580 01581 ret = wc_HashFinal(&hash, hashType, digest); 01582 if (ret < 0) { 01583 #ifdef WOLFSSL_SMALL_STACK 01584 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01585 #endif 01586 return ret; 01587 } 01588 } 01589 01590 /* Set algoID, with NULL attributes */ 01591 algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); 01592 01593 digestStrSz = SetOctetString(hashSz, digestStr); 01594 digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, 01595 digestInfoSeq); 01596 01597 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); 01598 digIdx += digestInfoSeqSz; 01599 XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); 01600 digIdx += algoIdSz; 01601 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); 01602 digIdx += digestStrSz; 01603 XMEMCPY(digestInfo + digIdx, digest, hashSz); 01604 digIdx += hashSz; 01605 01606 XMEMCPY(pkcs7Digest, digestInfo, digIdx); 01607 *pkcs7DigestSz = digIdx; 01608 01609 /* set plain digest pointer */ 01610 *plainDigest = pkcs7Digest + digIdx - hashSz; 01611 *plainDigestSz = hashSz; 01612 01613 #ifdef WOLFSSL_SMALL_STACK 01614 XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01615 #endif 01616 return 0; 01617 } 01618 01619 01620 /* verifies SignedData signature, over either PKCS#7 DigestInfo or 01621 * content digest. 01622 * 01623 * pkcs7 - pointer to initialized PKCS7 struct 01624 * sig - signature to verify 01625 * sigSz - size of sig 01626 * signedAttrib - signed attributes, or null if empty 01627 * signedAttribSz - size of signedAttributes 01628 * 01629 * return 0 on success, negative on error */ 01630 static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, 01631 word32 sigSz, byte* signedAttrib, 01632 word32 signedAttribSz) 01633 { 01634 int ret = 0; 01635 word32 plainDigestSz = 0, pkcs7DigestSz; 01636 byte* plainDigest = NULL; /* offset into pkcs7Digest */ 01637 #ifdef WOLFSSL_SMALL_STACK 01638 byte* pkcs7Digest; 01639 #else 01640 byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; 01641 #endif 01642 01643 if (pkcs7 == NULL) 01644 return BAD_FUNC_ARG; 01645 01646 #ifdef WOLFSSL_SMALL_STACK 01647 pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, 01648 DYNAMIC_TYPE_TMP_BUFFER); 01649 if (pkcs7Digest == NULL) 01650 return MEMORY_E; 01651 #endif 01652 01653 /* build hash to verify against */ 01654 pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; 01655 ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, 01656 signedAttribSz, pkcs7Digest, 01657 &pkcs7DigestSz, &plainDigest, 01658 &plainDigestSz); 01659 if (ret < 0) { 01660 #ifdef WOLFSSL_SMALL_STACK 01661 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01662 #endif 01663 return ret; 01664 } 01665 01666 switch (pkcs7->publicKeyOID) { 01667 01668 #ifndef NO_RSA 01669 case RSAk: 01670 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, 01671 pkcs7DigestSz); 01672 if (ret < 0) { 01673 WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); 01674 ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, 01675 plainDigestSz); 01676 } 01677 break; 01678 #endif 01679 01680 #ifdef HAVE_ECC 01681 case ECDSAk: 01682 ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, 01683 plainDigestSz); 01684 break; 01685 #endif 01686 01687 default: 01688 WOLFSSL_MSG("Unsupported public key type"); 01689 ret = BAD_FUNC_ARG; 01690 } 01691 01692 #ifdef WOLFSSL_SMALL_STACK 01693 XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 01694 #endif 01695 return ret; 01696 } 01697 01698 01699 /* set correct public key OID based on signature OID, stores in 01700 * pkcs7->publicKeyOID and returns same value */ 01701 static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) 01702 { 01703 if (pkcs7 == NULL) 01704 return BAD_FUNC_ARG; 01705 01706 pkcs7->publicKeyOID = 0; 01707 01708 switch (sigOID) { 01709 01710 #ifndef NO_RSA 01711 /* RSA signature types */ 01712 case CTC_MD2wRSA: 01713 case CTC_MD5wRSA: 01714 case CTC_SHAwRSA: 01715 case CTC_SHA224wRSA: 01716 case CTC_SHA256wRSA: 01717 case CTC_SHA384wRSA: 01718 case CTC_SHA512wRSA: 01719 pkcs7->publicKeyOID = RSAk; 01720 break; 01721 01722 /* if sigOID is already RSAk */ 01723 case RSAk: 01724 pkcs7->publicKeyOID = sigOID; 01725 break; 01726 #endif 01727 01728 #ifndef NO_DSA 01729 /* DSA signature types */ 01730 case CTC_SHAwDSA: 01731 pkcs7->publicKeyOID = DSAk; 01732 break; 01733 01734 /* if sigOID is already DSAk */ 01735 case DSAk: 01736 pkcs7->publicKeyOID = sigOID; 01737 break; 01738 #endif 01739 01740 #ifdef HAVE_ECC 01741 /* ECDSA signature types */ 01742 case CTC_SHAwECDSA: 01743 case CTC_SHA224wECDSA: 01744 case CTC_SHA256wECDSA: 01745 case CTC_SHA384wECDSA: 01746 case CTC_SHA512wECDSA: 01747 pkcs7->publicKeyOID = ECDSAk; 01748 break; 01749 01750 /* if sigOID is already ECDSAk */ 01751 case ECDSAk: 01752 pkcs7->publicKeyOID = sigOID; 01753 break; 01754 #endif 01755 01756 default: 01757 WOLFSSL_MSG("Unsupported public key algorithm"); 01758 return ASN_SIG_KEY_E; 01759 } 01760 01761 return pkcs7->publicKeyOID; 01762 } 01763 01764 01765 /* Parses through the attributes and adds them to the PKCS7 structure 01766 * Creates dynamic attribute structures that are free'd with calling 01767 * wc_PKCS7_Free() 01768 * 01769 * NOTE: An attribute has the ASN1 format of 01770 ** Sequence 01771 ****** Object ID 01772 ****** Set 01773 ********** {PritnableString, UTCTime, OCTET STRING ...} 01774 * 01775 * pkcs7 the PKCS7 structure to put the parsed attributes into 01776 * in buffer holding all attributes 01777 * inSz size of in buffer 01778 * 01779 * returns the number of attributes parsed on success 01780 */ 01781 static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) 01782 { 01783 int found = 0; 01784 word32 idx = 0; 01785 word32 oid; 01786 01787 if (pkcs7 == NULL || in == NULL || inSz < 0) { 01788 return BAD_FUNC_ARG; 01789 } 01790 01791 while (idx < (word32)inSz) { 01792 int length = 0; 01793 int oidIdx; 01794 PKCS7DecodedAttrib* attrib; 01795 01796 if (GetSequence(in, &idx, &length, inSz) < 0) 01797 return ASN_PARSE_E; 01798 01799 attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), 01800 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01801 if (attrib == NULL) { 01802 return MEMORY_E; 01803 } 01804 XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib)); 01805 01806 oidIdx = idx; 01807 if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz) 01808 < 0) { 01809 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01810 return ASN_PARSE_E; 01811 } 01812 attrib->oidSz = idx - oidIdx; 01813 attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap, 01814 DYNAMIC_TYPE_PKCS7); 01815 if (attrib->oid == NULL) { 01816 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01817 return MEMORY_E; 01818 } 01819 XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz); 01820 01821 01822 /* Get Set that contains the printable string value */ 01823 if (GetSet(in, &idx, &length, inSz) < 0) { 01824 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01825 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01826 return ASN_PARSE_E; 01827 } 01828 01829 if ((inSz - idx) < (word32)length) { 01830 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01831 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01832 return ASN_PARSE_E; 01833 } 01834 01835 attrib->valueSz = (word32)length; 01836 attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap, 01837 DYNAMIC_TYPE_PKCS7); 01838 if (attrib->value == NULL) { 01839 XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01840 XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01841 return MEMORY_E; 01842 } 01843 XMEMCPY(attrib->value, in + idx, attrib->valueSz); 01844 idx += length; 01845 01846 /* store attribute in linked list */ 01847 if (pkcs7->decodedAttrib != NULL) { 01848 attrib->next = pkcs7->decodedAttrib; 01849 pkcs7->decodedAttrib = attrib; 01850 } else { 01851 pkcs7->decodedAttrib = attrib; 01852 } 01853 found++; 01854 } 01855 01856 return found; 01857 } 01858 01859 01860 /* Finds the certificates in the message and saves it. */ 01861 int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) 01862 { 01863 word32 idx, contentType, hashOID, sigOID; 01864 int length, version, ret; 01865 byte* content = NULL; 01866 byte* sig = NULL; 01867 byte* cert = NULL; 01868 byte* signedAttrib = NULL; 01869 int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; 01870 byte degenerate; 01871 #ifdef ASN_BER_TO_DER 01872 byte* der; 01873 #endif 01874 01875 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) 01876 return BAD_FUNC_ARG; 01877 01878 idx = 0; 01879 01880 /* Get the contentInfo sequence */ 01881 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01882 return ASN_PARSE_E; 01883 01884 if (length == 0 && pkiMsg[idx-1] == 0x80) { 01885 #ifdef ASN_BER_TO_DER 01886 word32 len = 0; 01887 01888 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); 01889 if (ret != LENGTH_ONLY_E) 01890 return ret; 01891 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 01892 if (pkcs7->der == NULL) 01893 return MEMORY_E; 01894 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); 01895 if (ret < 0) 01896 return ret; 01897 01898 pkiMsg = pkcs7->der; 01899 pkiMsgSz = len; 01900 idx = 0; 01901 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01902 return ASN_PARSE_E; 01903 #else 01904 return BER_INDEF_E; 01905 #endif 01906 } 01907 01908 /* Get the contentInfo contentType */ 01909 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01910 return ASN_PARSE_E; 01911 01912 if (contentType != SIGNED_DATA) { 01913 WOLFSSL_MSG("PKCS#7 input not of type SignedData"); 01914 return PKCS7_OID_E; 01915 } 01916 01917 /* get the ContentInfo content */ 01918 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 01919 return ASN_PARSE_E; 01920 01921 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01922 return ASN_PARSE_E; 01923 01924 /* Get the signedData sequence */ 01925 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01926 return ASN_PARSE_E; 01927 01928 /* Get the version */ 01929 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 01930 return ASN_PARSE_E; 01931 01932 if (version != 1) { 01933 WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1"); 01934 return ASN_VERSION_E; 01935 } 01936 01937 /* Get the set of DigestAlgorithmIdentifiers */ 01938 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01939 return ASN_PARSE_E; 01940 01941 /* Skip the set. */ 01942 idx += length; 01943 degenerate = (length == 0)? 1 : 0; 01944 01945 /* Get the inner ContentInfo sequence */ 01946 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01947 return ASN_PARSE_E; 01948 01949 /* Get the inner ContentInfo contentType */ 01950 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01951 return ASN_PARSE_E; 01952 01953 if (contentType != DATA) { 01954 WOLFSSL_MSG("PKCS#7 inner input not of type Data"); 01955 return PKCS7_OID_E; 01956 } 01957 01958 /* Check for content info, it could be omitted when degenerate */ 01959 { 01960 word32 localIdx = idx; 01961 ret = 0; 01962 if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 01963 ret = ASN_PARSE_E; 01964 01965 if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) <= 0) 01966 ret = ASN_PARSE_E; 01967 01968 if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) 01969 ret = ASN_PARSE_E; 01970 01971 if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) 01972 ret = ASN_PARSE_E; 01973 01974 /* Save the inner data as the content. */ 01975 if (length > 0) { 01976 /* Local pointer for calculating hashes later */ 01977 content = &pkiMsg[localIdx]; 01978 contentSz = length; 01979 localIdx += length; 01980 } 01981 01982 /* update idx if successful */ 01983 if (ret == 0) { 01984 idx = localIdx; 01985 } 01986 } 01987 01988 /* If getting the content info failed with non degenerate then return the 01989 * error case. Otherwise with a degenerate it is ok if the content 01990 * info was omitted */ 01991 if (!degenerate && ret != 0) { 01992 return ret; 01993 } 01994 01995 /* Get the implicit[0] set of certificates */ 01996 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 01997 idx++; 01998 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01999 return ASN_PARSE_E; 02000 02001 if (length > 0) { 02002 /* At this point, idx is at the first certificate in 02003 * a set of certificates. There may be more than one, 02004 * or none, or they may be a PKCS 6 extended 02005 * certificate. We want to save the first cert if it 02006 * is X.509. */ 02007 02008 word32 certIdx = idx; 02009 02010 if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 02011 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) 02012 return ASN_PARSE_E; 02013 02014 cert = &pkiMsg[idx]; 02015 certSz += (certIdx - idx); 02016 } 02017 02018 #ifdef ASN_BER_TO_DER 02019 der = pkcs7->der; 02020 #endif 02021 /* This will reset PKCS7 structure and then set the certificate */ 02022 wc_PKCS7_InitWithCert(pkcs7, cert, certSz); 02023 #ifdef ASN_BER_TO_DER 02024 pkcs7->der = der; 02025 #endif 02026 02027 /* iterate through any additional certificates */ 02028 if (MAX_PKCS7_CERTS > 0) { 02029 word32 localIdx; 02030 int sz = 0; 02031 int i; 02032 02033 pkcs7->cert[0] = cert; 02034 pkcs7->certSz[0] = certSz; 02035 certIdx = idx + certSz; 02036 02037 for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsgSz; i++) { 02038 localIdx = certIdx; 02039 02040 if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 02041 if (GetLength(pkiMsg, &certIdx, &sz, pkiMsgSz) < 0) 02042 return ASN_PARSE_E; 02043 02044 pkcs7->cert[i] = &pkiMsg[localIdx]; 02045 pkcs7->certSz[i] = sz + (certIdx - localIdx); 02046 certIdx += sz; 02047 } 02048 } 02049 } 02050 } 02051 idx += length; 02052 } 02053 02054 /* set content and size after init of PKCS7 structure */ 02055 pkcs7->content = content; 02056 pkcs7->contentSz = contentSz; 02057 02058 /* Get the implicit[1] set of crls */ 02059 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 02060 idx++; 02061 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02062 return ASN_PARSE_E; 02063 02064 /* Skip the set */ 02065 idx += length; 02066 } 02067 02068 /* Get the set of signerInfos */ 02069 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02070 return ASN_PARSE_E; 02071 02072 if (length > 0) { 02073 /* Get the sequence of the first signerInfo */ 02074 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02075 return ASN_PARSE_E; 02076 02077 /* Get the version */ 02078 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 02079 return ASN_PARSE_E; 02080 02081 if (version != 1) { 02082 WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1"); 02083 return ASN_VERSION_E; 02084 } 02085 02086 /* Get the sequence of IssuerAndSerialNumber */ 02087 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02088 return ASN_PARSE_E; 02089 02090 /* Skip it */ 02091 idx += length; 02092 02093 /* Get the sequence of digestAlgorithm */ 02094 if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) { 02095 return ASN_PARSE_E; 02096 } 02097 pkcs7->hashOID = (int)hashOID; 02098 02099 /* Get the IMPLICIT[0] SET OF signedAttributes */ 02100 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 02101 idx++; 02102 02103 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02104 return ASN_PARSE_E; 02105 02106 /* save pointer and length */ 02107 signedAttrib = &pkiMsg[idx]; 02108 signedAttribSz = length; 02109 02110 if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) { 02111 WOLFSSL_MSG("Error parsing signed attributes"); 02112 return ASN_PARSE_E; 02113 } 02114 02115 idx += length; 02116 } 02117 02118 /* Get digestEncryptionAlgorithm */ 02119 if (GetAlgoId(pkiMsg, &idx, &sigOID, oidSigType, pkiMsgSz) < 0) { 02120 return ASN_PARSE_E; 02121 } 02122 02123 /* store public key type based on digestEncryptionAlgorithm */ 02124 ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); 02125 if (ret <= 0) { 02126 WOLFSSL_MSG("Failed to set public key OID from signature"); 02127 return ret; 02128 } 02129 02130 /* Get the signature */ 02131 if (pkiMsg[idx] == ASN_OCTET_STRING) { 02132 idx++; 02133 02134 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 02135 return ASN_PARSE_E; 02136 02137 /* save pointer and length */ 02138 sig = &pkiMsg[idx]; 02139 sigSz = length; 02140 02141 idx += length; 02142 } 02143 02144 pkcs7->content = content; 02145 pkcs7->contentSz = contentSz; 02146 02147 ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, 02148 signedAttrib, signedAttribSz); 02149 if (ret < 0) 02150 return ret; 02151 } 02152 02153 return 0; 02154 } 02155 02156 02157 #ifdef HAVE_ECC 02158 02159 /* KARI == KeyAgreeRecipientInfo (key agreement) */ 02160 typedef struct WC_PKCS7_KARI { 02161 DecodedCert* decoded; /* decoded recip cert */ 02162 void* heap; /* user heap, points to PKCS7->heap */ 02163 int devId; /* device ID for HW based private key */ 02164 ecc_key* recipKey; /* recip key (pub | priv) */ 02165 ecc_key* senderKey; /* sender key (pub | priv) */ 02166 byte* senderKeyExport; /* sender ephemeral key DER */ 02167 byte* kek; /* key encryption key */ 02168 byte* ukm; /* OPTIONAL user keying material */ 02169 byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ 02170 word32 senderKeyExportSz; /* size of sender ephemeral key DER */ 02171 word32 kekSz; /* size of key encryption key */ 02172 word32 ukmSz; /* size of user keying material */ 02173 word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ 02174 byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ 02175 byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ 02176 byte decodedInit : 1; /* indicates decoded was initialized */ 02177 byte recipKeyInit : 1; /* indicates recipKey was initialized */ 02178 byte senderKeyInit : 1; /* indicates senderKey was initialized */ 02179 } WC_PKCS7_KARI; 02180 02181 02182 /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ 02183 static int wc_PKCS7_KariKeyWrap(byte* cek, word32 cekSz, byte* kek, 02184 word32 kekSz, byte* out, word32 outSz, 02185 int keyWrapAlgo, int direction) 02186 { 02187 int ret; 02188 02189 if (cek == NULL || kek == NULL || out == NULL) 02190 return BAD_FUNC_ARG; 02191 02192 switch (keyWrapAlgo) { 02193 #ifndef NO_AES 02194 #ifdef WOLFSSL_AES_128 02195 case AES128_WRAP: 02196 #endif 02197 #ifdef WOLFSSL_AES_192 02198 case AES192_WRAP: 02199 #endif 02200 #ifdef WOLFSSL_AES_256 02201 case AES256_WRAP: 02202 #endif 02203 02204 if (direction == AES_ENCRYPTION) { 02205 02206 ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz, 02207 out, outSz, NULL); 02208 02209 } else if (direction == AES_DECRYPTION) { 02210 02211 ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz, 02212 out, outSz, NULL); 02213 } else { 02214 WOLFSSL_MSG("Bad key un/wrap direction"); 02215 return BAD_FUNC_ARG; 02216 } 02217 02218 if (ret <= 0) 02219 return ret; 02220 02221 break; 02222 #endif /* NO_AES */ 02223 02224 default: 02225 WOLFSSL_MSG("Unsupported key wrap algorithm"); 02226 return BAD_KEYWRAP_ALG_E; 02227 }; 02228 02229 (void)cekSz; 02230 (void)kekSz; 02231 (void)outSz; 02232 (void)direction; 02233 return ret; 02234 } 02235 02236 02237 /* allocate and create new WC_PKCS7_KARI struct, 02238 * returns struct pointer on success, NULL on failure */ 02239 static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) 02240 { 02241 WC_PKCS7_KARI* kari = NULL; 02242 02243 if (pkcs7 == NULL) 02244 return NULL; 02245 02246 kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap, 02247 DYNAMIC_TYPE_PKCS7); 02248 if (kari == NULL) { 02249 WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI"); 02250 return NULL; 02251 } 02252 02253 kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, 02254 DYNAMIC_TYPE_PKCS7); 02255 if (kari->decoded == NULL) { 02256 WOLFSSL_MSG("Failed to allocate DecodedCert"); 02257 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02258 return NULL; 02259 } 02260 02261 kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 02262 DYNAMIC_TYPE_PKCS7); 02263 if (kari->recipKey == NULL) { 02264 WOLFSSL_MSG("Failed to allocate recipient ecc_key"); 02265 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02266 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02267 return NULL; 02268 } 02269 02270 kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, 02271 DYNAMIC_TYPE_PKCS7); 02272 if (kari->senderKey == NULL) { 02273 WOLFSSL_MSG("Failed to allocate sender ecc_key"); 02274 XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02275 XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02276 XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 02277 return NULL; 02278 } 02279 02280 kari->senderKeyExport = NULL; 02281 kari->senderKeyExportSz = 0; 02282 kari->kek = NULL; 02283 kari->kekSz = 0; 02284 kari->ukm = NULL; 02285 kari->ukmSz = 0; 02286 kari->ukmOwner = 0; 02287 kari->sharedInfo = NULL; 02288 kari->sharedInfoSz = 0; 02289 kari->direction = direction; 02290 kari->decodedInit = 0; 02291 kari->recipKeyInit = 0; 02292 kari->senderKeyInit = 0; 02293 02294 kari->heap = pkcs7->heap; 02295 kari->devId = pkcs7->devId; 02296 02297 return kari; 02298 } 02299 02300 02301 /* free WC_PKCS7_KARI struct, return 0 on success */ 02302 static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) 02303 { 02304 void* heap; 02305 02306 if (kari) { 02307 heap = kari->heap; 02308 02309 if (kari->decoded) { 02310 if (kari->decodedInit) 02311 FreeDecodedCert(kari->decoded); 02312 XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); 02313 } 02314 if (kari->senderKey) { 02315 if (kari->senderKeyInit) 02316 wc_ecc_free(kari->senderKey); 02317 XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7); 02318 } 02319 if (kari->recipKey) { 02320 if (kari->recipKeyInit) 02321 wc_ecc_free(kari->recipKey); 02322 XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); 02323 } 02324 if (kari->senderKeyExport) { 02325 ForceZero(kari->senderKeyExport, kari->senderKeyExportSz); 02326 XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7); 02327 kari->senderKeyExportSz = 0; 02328 } 02329 if (kari->kek) { 02330 ForceZero(kari->kek, kari->kekSz); 02331 XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7); 02332 kari->kekSz = 0; 02333 } 02334 if (kari->ukm) { 02335 if (kari->ukmOwner == 1) { 02336 XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7); 02337 } 02338 kari->ukmSz = 0; 02339 } 02340 if (kari->sharedInfo) { 02341 ForceZero(kari->sharedInfo, kari->sharedInfoSz); 02342 XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7); 02343 kari->sharedInfoSz = 0; 02344 } 02345 XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); 02346 } 02347 02348 (void)heap; 02349 02350 return 0; 02351 } 02352 02353 02354 /* parse recipient cert/key, return 0 on success, negative on error 02355 * key/keySz only needed during decoding (WC_PKCS7_DECODE) */ 02356 static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, 02357 word32 certSz, const byte* key, 02358 word32 keySz) 02359 { 02360 int ret; 02361 word32 idx; 02362 02363 if (kari == NULL || kari->decoded == NULL || 02364 cert == NULL || certSz == 0) 02365 return BAD_FUNC_ARG; 02366 02367 /* decode certificate */ 02368 InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap); 02369 kari->decodedInit = 1; 02370 ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0); 02371 if (ret < 0) 02372 return ret; 02373 02374 /* make sure subject key id was read from cert */ 02375 if (kari->decoded->extSubjKeyIdSet == 0) { 02376 WOLFSSL_MSG("Failed to read subject key ID from recipient cert"); 02377 return BAD_FUNC_ARG; 02378 } 02379 02380 ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId); 02381 if (ret != 0) 02382 return ret; 02383 02384 kari->recipKeyInit = 1; 02385 02386 /* get recip public key */ 02387 if (kari->direction == WC_PKCS7_ENCODE) { 02388 02389 idx = 0; 02390 ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx, 02391 kari->recipKey, kari->decoded->pubKeySize); 02392 if (ret != 0) 02393 return ret; 02394 } 02395 /* get recip private key */ 02396 else if (kari->direction == WC_PKCS7_DECODE) { 02397 if (key != NULL && keySz > 0) { 02398 idx = 0; 02399 ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); 02400 } 02401 else if (kari->devId == INVALID_DEVID) { 02402 ret = BAD_FUNC_ARG; 02403 } 02404 if (ret != 0) 02405 return ret; 02406 02407 } else { 02408 /* bad direction */ 02409 return BAD_FUNC_ARG; 02410 } 02411 02412 (void)idx; 02413 02414 return 0; 02415 } 02416 02417 02418 /* create ephemeral ECC key, places ecc_key in kari->senderKey, 02419 * DER encoded in kari->senderKeyExport. return 0 on success, 02420 * negative on error */ 02421 static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) 02422 { 02423 int ret; 02424 02425 if (kari == NULL || kari->decoded == NULL || 02426 kari->recipKey == NULL || kari->recipKey->dp == NULL || 02427 rng == NULL) 02428 return BAD_FUNC_ARG; 02429 02430 kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize, 02431 kari->heap, DYNAMIC_TYPE_PKCS7); 02432 if (kari->senderKeyExport == NULL) 02433 return MEMORY_E; 02434 02435 kari->senderKeyExportSz = kari->decoded->pubKeySize; 02436 02437 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); 02438 if (ret != 0) 02439 return ret; 02440 02441 kari->senderKeyInit = 1; 02442 02443 ret = wc_ecc_make_key_ex(rng, kari->recipKey->dp->size, 02444 kari->senderKey, kari->recipKey->dp->id); 02445 if (ret != 0) 02446 return ret; 02447 02448 /* dump generated key to X.963 DER for output in CMS bundle */ 02449 ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport, 02450 &kari->senderKeyExportSz); 02451 if (ret != 0) 02452 return ret; 02453 02454 return 0; 02455 } 02456 02457 02458 /* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm, 02459 * place in kari->sharedInfo. returns 0 on success, negative on error */ 02460 static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) 02461 { 02462 int idx = 0; 02463 int sharedInfoSeqSz = 0; 02464 int keyInfoSz = 0; 02465 int suppPubInfoSeqSz = 0; 02466 int entityUInfoOctetSz = 0; 02467 int entityUInfoExplicitSz = 0; 02468 int kekOctetSz = 0; 02469 int sharedInfoSz = 0; 02470 02471 word32 kekBitSz = 0; 02472 02473 byte sharedInfoSeq[MAX_SEQ_SZ]; 02474 byte keyInfo[MAX_ALGO_SZ]; 02475 byte suppPubInfoSeq[MAX_SEQ_SZ]; 02476 byte entityUInfoOctet[MAX_OCTET_STR_SZ]; 02477 byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; 02478 byte kekOctet[MAX_OCTET_STR_SZ]; 02479 02480 if (kari == NULL) 02481 return BAD_FUNC_ARG; 02482 02483 if ((kari->ukmSz > 0) && (kari->ukm == NULL)) 02484 return BAD_FUNC_ARG; 02485 02486 /* kekOctet */ 02487 kekOctetSz = SetOctetString(sizeof(word32), kekOctet); 02488 sharedInfoSz += (kekOctetSz + sizeof(word32)); 02489 02490 /* suppPubInfo */ 02491 suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2, 02492 kekOctetSz + sizeof(word32), 02493 suppPubInfoSeq); 02494 sharedInfoSz += suppPubInfoSeqSz; 02495 02496 /* optional ukm/entityInfo */ 02497 if (kari->ukmSz > 0) { 02498 entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); 02499 sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); 02500 02501 entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + 02502 kari->ukmSz, 02503 entityUInfoExplicitSeq); 02504 sharedInfoSz += entityUInfoExplicitSz; 02505 } 02506 02507 /* keyInfo */ 02508 keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); 02509 sharedInfoSz += keyInfoSz; 02510 02511 /* sharedInfo */ 02512 sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq); 02513 sharedInfoSz += sharedInfoSeqSz; 02514 02515 kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap, 02516 DYNAMIC_TYPE_PKCS7); 02517 if (kari->sharedInfo == NULL) 02518 return MEMORY_E; 02519 02520 kari->sharedInfoSz = sharedInfoSz; 02521 02522 XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz); 02523 idx += sharedInfoSeqSz; 02524 XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); 02525 idx += keyInfoSz; 02526 if (kari->ukmSz > 0) { 02527 XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, 02528 entityUInfoExplicitSz); 02529 idx += entityUInfoExplicitSz; 02530 XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); 02531 idx += entityUInfoOctetSz; 02532 XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); 02533 idx += kari->ukmSz; 02534 } 02535 XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz); 02536 idx += suppPubInfoSeqSz; 02537 XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz); 02538 idx += kekOctetSz; 02539 02540 kekBitSz = (kari->kekSz) * 8; /* convert to bits */ 02541 #ifdef LITTLE_ENDIAN_ORDER 02542 kekBitSz = ByteReverseWord32(kekBitSz); /* network byte order */ 02543 #endif 02544 XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz)); 02545 02546 return 0; 02547 } 02548 02549 02550 /* create key encryption key (KEK) using key wrap algorithm and key encryption 02551 * algorithm, place in kari->kek. return 0 on success, <0 on error. */ 02552 static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, 02553 int keyWrapOID, int keyEncOID) 02554 { 02555 int ret; 02556 int kSz; 02557 enum wc_HashType kdfType; 02558 byte* secret; 02559 word32 secretSz; 02560 02561 if (kari == NULL || kari->recipKey == NULL || 02562 kari->senderKey == NULL || kari->senderKey->dp == NULL) 02563 return BAD_FUNC_ARG; 02564 02565 /* get KEK size, allocate buff */ 02566 kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID); 02567 if (kSz < 0) 02568 return kSz; 02569 02570 kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7); 02571 if (kari->kek == NULL) 02572 return MEMORY_E; 02573 02574 kari->kekSz = (word32)kSz; 02575 02576 /* generate ECC-CMS-SharedInfo */ 02577 ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID); 02578 if (ret != 0) 02579 return ret; 02580 02581 /* generate shared secret */ 02582 secretSz = kari->senderKey->dp->size; 02583 secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7); 02584 if (secret == NULL) 02585 return MEMORY_E; 02586 02587 if (kari->direction == WC_PKCS7_ENCODE) { 02588 02589 ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey, 02590 secret, &secretSz); 02591 02592 } else if (kari->direction == WC_PKCS7_DECODE) { 02593 02594 ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey, 02595 secret, &secretSz); 02596 02597 } else { 02598 /* bad direction */ 02599 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 02600 return BAD_FUNC_ARG; 02601 } 02602 02603 if (ret != 0) { 02604 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 02605 return ret; 02606 } 02607 02608 /* run through KDF */ 02609 switch (keyEncOID) { 02610 02611 #ifndef NO_SHA 02612 case dhSinglePass_stdDH_sha1kdf_scheme: 02613 kdfType = WC_HASH_TYPE_SHA; 02614 break; 02615 #endif 02616 #ifndef WOLFSSL_SHA224 02617 case dhSinglePass_stdDH_sha224kdf_scheme: 02618 kdfType = WC_HASH_TYPE_SHA224; 02619 break; 02620 #endif 02621 #ifndef NO_SHA256 02622 case dhSinglePass_stdDH_sha256kdf_scheme: 02623 kdfType = WC_HASH_TYPE_SHA256; 02624 break; 02625 #endif 02626 #ifdef WOLFSSL_SHA384 02627 case dhSinglePass_stdDH_sha384kdf_scheme: 02628 kdfType = WC_HASH_TYPE_SHA384; 02629 break; 02630 #endif 02631 #ifdef WOLFSSL_SHA512 02632 case dhSinglePass_stdDH_sha512kdf_scheme: 02633 kdfType = WC_HASH_TYPE_SHA512; 02634 break; 02635 #endif 02636 default: 02637 WOLFSSL_MSG("Unsupported key agreement algorithm"); 02638 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 02639 return BAD_FUNC_ARG; 02640 }; 02641 02642 ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo, 02643 kari->sharedInfoSz, kari->kek, kari->kekSz); 02644 if (ret != 0) { 02645 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 02646 return ret; 02647 } 02648 02649 XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); 02650 02651 return 0; 02652 } 02653 02654 02655 /* create ASN.1 formatted KeyAgreeRecipientInfo (kari) for use with ECDH, 02656 * return sequence size or negative on error */ 02657 static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, 02658 word32 certSz, int keyAgreeAlgo, int blockKeySz, 02659 int keyWrapAlgo, int keyEncAlgo, WC_RNG* rng, 02660 byte* contentKeyPlain, byte* contentKeyEnc, 02661 int* keyEncSz, byte* out, word32 outSz) 02662 { 02663 int ret = 0, idx = 0; 02664 int keySz, direction = 0; 02665 02666 /* ASN.1 layout */ 02667 int totalSz = 0; 02668 int kariSeqSz = 0; 02669 byte kariSeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ 02670 int verSz = 0; 02671 byte ver[MAX_VERSION_SZ]; 02672 02673 int origIdOrKeySeqSz = 0; 02674 byte origIdOrKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ 02675 int origPubKeySeqSz = 0; 02676 byte origPubKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ 02677 int origAlgIdSz = 0; 02678 byte origAlgId[MAX_ALGO_SZ]; 02679 int origPubKeyStrSz = 0; 02680 byte origPubKeyStr[MAX_OCTET_STR_SZ]; 02681 02682 /* optional user keying material */ 02683 int ukmOctetSz = 0; 02684 byte ukmOctetStr[MAX_OCTET_STR_SZ]; 02685 int ukmExplicitSz = 0; 02686 byte ukmExplicitSeq[MAX_SEQ_SZ]; 02687 02688 int keyEncryptAlgoIdSz = 0; 02689 byte keyEncryptAlgoId[MAX_ALGO_SZ]; 02690 int keyWrapAlgSz = 0; 02691 byte keyWrapAlg[MAX_ALGO_SZ]; 02692 02693 int recipEncKeysSeqSz = 0; 02694 byte recipEncKeysSeq[MAX_SEQ_SZ]; 02695 int recipEncKeySeqSz = 0; 02696 byte recipEncKeySeq[MAX_SEQ_SZ]; 02697 int recipKeyIdSeqSz = 0; 02698 byte recipKeyIdSeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ 02699 int subjKeyIdOctetSz = 0; 02700 byte subjKeyIdOctet[MAX_OCTET_STR_SZ]; 02701 int encryptedKeyOctetSz = 0; 02702 byte encryptedKeyOctet[MAX_OCTET_STR_SZ]; 02703 02704 WC_PKCS7_KARI* kari; 02705 02706 /* only supports ECDSA for now */ 02707 if (keyAgreeAlgo != ECDSAk) 02708 return BAD_FUNC_ARG; 02709 02710 /* set direction based on keyWrapAlgo */ 02711 switch (keyWrapAlgo) { 02712 #ifndef NO_AES 02713 #ifdef WOLFSSL_AES_128 02714 case AES128_WRAP: 02715 #endif 02716 #ifdef WOLFSSL_AES_192 02717 case AES192_WRAP: 02718 #endif 02719 #ifdef WOLFSSL_AES_256 02720 case AES256_WRAP: 02721 #endif 02722 direction = AES_ENCRYPTION; 02723 break; 02724 #endif 02725 default: 02726 WOLFSSL_MSG("Unsupported key wrap algorithm"); 02727 return BAD_KEYWRAP_ALG_E; 02728 } 02729 02730 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE); 02731 if (kari == NULL) 02732 return MEMORY_E; 02733 02734 /* set user keying material if available */ 02735 if ((pkcs7->ukmSz > 0) && (pkcs7->ukm != NULL)) { 02736 kari->ukm = pkcs7->ukm; 02737 kari->ukmSz = pkcs7->ukmSz; 02738 kari->ukmOwner = 0; 02739 } 02740 02741 /* parse recipient cert, get public key */ 02742 ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0); 02743 if (ret != 0) { 02744 wc_PKCS7_KariFree(kari); 02745 return ret; 02746 } 02747 02748 /* generate sender ephemeral ECC key */ 02749 ret = wc_PKCS7_KariGenerateEphemeralKey(kari, rng); 02750 if (ret != 0) { 02751 wc_PKCS7_KariFree(kari); 02752 return ret; 02753 } 02754 02755 /* generate KEK (key encryption key) */ 02756 ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapAlgo, keyEncAlgo); 02757 if (ret != 0) { 02758 wc_PKCS7_KariFree(kari); 02759 return ret; 02760 } 02761 02762 /* encrypt CEK with KEK */ 02763 keySz = wc_PKCS7_KariKeyWrap(contentKeyPlain, blockKeySz, kari->kek, 02764 kari->kekSz, contentKeyEnc, *keyEncSz, keyWrapAlgo, 02765 direction); 02766 if (keySz <= 0) { 02767 wc_PKCS7_KariFree(kari); 02768 return ret; 02769 } 02770 *keyEncSz = (word32)keySz; 02771 02772 /* Start of RecipientEncryptedKeys */ 02773 02774 /* EncryptedKey */ 02775 encryptedKeyOctetSz = SetOctetString(*keyEncSz, encryptedKeyOctet); 02776 totalSz += (encryptedKeyOctetSz + *keyEncSz); 02777 02778 /* SubjectKeyIdentifier */ 02779 subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet); 02780 totalSz += (subjKeyIdOctetSz + KEYID_SIZE); 02781 02782 /* RecipientKeyIdentifier IMPLICIT [0] */ 02783 recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz + 02784 KEYID_SIZE, recipKeyIdSeq); 02785 totalSz += recipKeyIdSeqSz; 02786 02787 /* RecipientEncryptedKey */ 02788 recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq); 02789 totalSz += recipEncKeySeqSz; 02790 02791 /* RecipientEncryptedKeys */ 02792 recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq); 02793 totalSz += recipEncKeysSeqSz; 02794 02795 /* Start of optional UserKeyingMaterial */ 02796 02797 if (kari->ukmSz > 0) { 02798 ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr); 02799 totalSz += (ukmOctetSz + kari->ukmSz); 02800 02801 ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz, 02802 ukmExplicitSeq); 02803 totalSz += ukmExplicitSz; 02804 } 02805 02806 /* Start of KeyEncryptionAlgorithmIdentifier */ 02807 02808 /* KeyWrapAlgorithm */ 02809 keyWrapAlgSz = SetAlgoID(keyWrapAlgo, keyWrapAlg, oidKeyWrapType, 0); 02810 totalSz += keyWrapAlgSz; 02811 02812 /* KeyEncryptionAlgorithmIdentifier */ 02813 keyEncryptAlgoIdSz = SetAlgoID(keyEncAlgo, keyEncryptAlgoId, 02814 oidCmsKeyAgreeType, keyWrapAlgSz); 02815 totalSz += keyEncryptAlgoIdSz; 02816 02817 /* Start of OriginatorIdentifierOrKey */ 02818 02819 /* recipient ECPoint, public key */ 02820 XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */ 02821 origPubKeyStr[0] = ASN_BIT_STRING; 02822 origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1, 02823 origPubKeyStr + 1) + 2; 02824 totalSz += (origPubKeyStrSz + kari->senderKeyExportSz); 02825 02826 /* Originator AlgorithmIdentifier */ 02827 origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 0); 02828 totalSz += origAlgIdSz; 02829 02830 /* outer OriginatorPublicKey IMPLICIT [1] */ 02831 origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1, 02832 origAlgIdSz + origPubKeyStrSz + 02833 kari->senderKeyExportSz, origPubKeySeq); 02834 totalSz += origPubKeySeqSz; 02835 02836 /* outer OriginatorIdentiferOrKey IMPLICIT [0] */ 02837 origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0, 02838 origPubKeySeqSz + origAlgIdSz + 02839 origPubKeyStrSz + kari->senderKeyExportSz, 02840 origIdOrKeySeq); 02841 totalSz += origIdOrKeySeqSz; 02842 02843 /* version, always 3 */ 02844 verSz = SetMyVersion(3, ver, 0); 02845 totalSz += verSz; 02846 02847 /* outer IMPLICIT [1] kari */ 02848 kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); 02849 totalSz += kariSeqSz; 02850 02851 if ((word32)totalSz > outSz) { 02852 WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small"); 02853 wc_PKCS7_KariFree(kari); 02854 02855 return BUFFER_E; 02856 } 02857 02858 XMEMCPY(out + idx, kariSeq, kariSeqSz); 02859 idx += kariSeqSz; 02860 XMEMCPY(out + idx, ver, verSz); 02861 idx += verSz; 02862 02863 XMEMCPY(out + idx, origIdOrKeySeq, origIdOrKeySeqSz); 02864 idx += origIdOrKeySeqSz; 02865 XMEMCPY(out + idx, origPubKeySeq, origPubKeySeqSz); 02866 idx += origPubKeySeqSz; 02867 XMEMCPY(out + idx, origAlgId, origAlgIdSz); 02868 idx += origAlgIdSz; 02869 XMEMCPY(out + idx, origPubKeyStr, origPubKeyStrSz); 02870 idx += origPubKeyStrSz; 02871 /* ephemeral public key */ 02872 XMEMCPY(out + idx, kari->senderKeyExport, kari->senderKeyExportSz); 02873 idx += kari->senderKeyExportSz; 02874 02875 if (kari->ukmSz > 0) { 02876 XMEMCPY(out + idx, ukmExplicitSeq, ukmExplicitSz); 02877 idx += ukmExplicitSz; 02878 XMEMCPY(out + idx, ukmOctetStr, ukmOctetSz); 02879 idx += ukmOctetSz; 02880 XMEMCPY(out + idx, kari->ukm, kari->ukmSz); 02881 idx += kari->ukmSz; 02882 } 02883 02884 XMEMCPY(out + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); 02885 idx += keyEncryptAlgoIdSz; 02886 XMEMCPY(out + idx, keyWrapAlg, keyWrapAlgSz); 02887 idx += keyWrapAlgSz; 02888 02889 XMEMCPY(out + idx, recipEncKeysSeq, recipEncKeysSeqSz); 02890 idx += recipEncKeysSeqSz; 02891 XMEMCPY(out + idx, recipEncKeySeq, recipEncKeySeqSz); 02892 idx += recipEncKeySeqSz; 02893 XMEMCPY(out + idx, recipKeyIdSeq, recipKeyIdSeqSz); 02894 idx += recipKeyIdSeqSz; 02895 XMEMCPY(out + idx, subjKeyIdOctet, subjKeyIdOctetSz); 02896 idx += subjKeyIdOctetSz; 02897 /* subject key id */ 02898 XMEMCPY(out + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); 02899 idx += KEYID_SIZE; 02900 XMEMCPY(out + idx, encryptedKeyOctet, encryptedKeyOctetSz); 02901 idx += encryptedKeyOctetSz; 02902 /* encrypted CEK */ 02903 XMEMCPY(out + idx, contentKeyEnc, *keyEncSz); 02904 idx += *keyEncSz; 02905 02906 wc_PKCS7_KariFree(kari); 02907 02908 return idx; 02909 } 02910 02911 #endif /* HAVE_ECC */ 02912 02913 #ifndef NO_RSA 02914 02915 /* create ASN.1 formatted RecipientInfo structure, returns sequence size */ 02916 static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, 02917 int keyEncAlgo, int blockKeySz, 02918 WC_RNG* rng, byte* contentKeyPlain, 02919 byte* contentKeyEnc, int* keyEncSz, 02920 byte* out, word32 outSz, void* heap) 02921 { 02922 word32 idx = 0; 02923 int ret = 0, totalSz = 0; 02924 int verSz, issuerSz, snSz, keyEncAlgSz; 02925 int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; 02926 int encKeyOctetStrSz; 02927 02928 byte ver[MAX_VERSION_SZ]; 02929 byte issuerSerialSeq[MAX_SEQ_SZ]; 02930 byte recipSeq[MAX_SEQ_SZ]; 02931 byte issuerSeq[MAX_SEQ_SZ]; 02932 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 02933 02934 #ifdef WOLFSSL_SMALL_STACK 02935 byte *serial; 02936 byte *keyAlgArray; 02937 02938 RsaKey* pubKey; 02939 DecodedCert* decoded; 02940 02941 serial = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER); 02942 keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER); 02943 decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, 02944 DYNAMIC_TYPE_TMP_BUFFER); 02945 02946 if (decoded == NULL || serial == NULL || keyAlgArray == NULL) { 02947 if (serial) XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 02948 if (keyAlgArray) XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 02949 if (decoded) XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 02950 return MEMORY_E; 02951 } 02952 02953 #else 02954 byte serial[MAX_SN_SZ]; 02955 byte keyAlgArray[MAX_ALGO_SZ]; 02956 02957 RsaKey stack_pubKey; 02958 RsaKey* pubKey = &stack_pubKey; 02959 DecodedCert stack_decoded; 02960 DecodedCert* decoded = &stack_decoded; 02961 #endif 02962 02963 InitDecodedCert(decoded, (byte*)cert, certSz, heap); 02964 ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); 02965 if (ret < 0) { 02966 FreeDecodedCert(decoded); 02967 #ifdef WOLFSSL_SMALL_STACK 02968 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 02969 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 02970 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 02971 #endif 02972 return ret; 02973 } 02974 02975 /* version */ 02976 verSz = SetMyVersion(0, ver, 0); 02977 02978 /* IssuerAndSerialNumber */ 02979 if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { 02980 WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); 02981 FreeDecodedCert(decoded); 02982 #ifdef WOLFSSL_SMALL_STACK 02983 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 02984 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 02985 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 02986 #endif 02987 return -1; 02988 } 02989 issuerSz = decoded->issuerRawLen; 02990 issuerSeqSz = SetSequence(issuerSz, issuerSeq); 02991 02992 if (decoded->serialSz == 0) { 02993 WOLFSSL_MSG("DecodedCert missing serial number"); 02994 FreeDecodedCert(decoded); 02995 #ifdef WOLFSSL_SMALL_STACK 02996 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 02997 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 02998 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 02999 #endif 03000 return -1; 03001 } 03002 snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, MAX_SN_SZ); 03003 03004 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, 03005 issuerSerialSeq); 03006 03007 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ 03008 if (keyEncAlgo != RSAk) { 03009 FreeDecodedCert(decoded); 03010 #ifdef WOLFSSL_SMALL_STACK 03011 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03012 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03013 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03014 #endif 03015 return ALGO_ID_E; 03016 } 03017 03018 keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, oidKeyType, 0); 03019 if (keyEncAlgSz == 0) { 03020 FreeDecodedCert(decoded); 03021 #ifdef WOLFSSL_SMALL_STACK 03022 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03023 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03024 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03025 #endif 03026 return BAD_FUNC_ARG; 03027 } 03028 03029 #ifdef WOLFSSL_SMALL_STACK 03030 pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_TMP_BUFFER); 03031 if (pubKey == NULL) { 03032 FreeDecodedCert(decoded); 03033 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03034 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03035 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03036 return MEMORY_E; 03037 } 03038 #endif 03039 03040 /* EncryptedKey */ 03041 ret = wc_InitRsaKey_ex(pubKey, heap, INVALID_DEVID); 03042 if (ret != 0) { 03043 FreeDecodedCert(decoded); 03044 #ifdef WOLFSSL_SMALL_STACK 03045 XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); 03046 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03047 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03048 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03049 #endif 03050 return ret; 03051 } 03052 03053 if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey, 03054 decoded->pubKeySize) < 0) { 03055 WOLFSSL_MSG("ASN RSA key decode error"); 03056 wc_FreeRsaKey(pubKey); 03057 FreeDecodedCert(decoded); 03058 #ifdef WOLFSSL_SMALL_STACK 03059 XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); 03060 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03061 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03062 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03063 #endif 03064 return PUBLIC_KEY_E; 03065 } 03066 03067 *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc, 03068 MAX_ENCRYPTED_KEY_SZ, pubKey, rng); 03069 wc_FreeRsaKey(pubKey); 03070 03071 #ifdef WOLFSSL_SMALL_STACK 03072 XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); 03073 #endif 03074 03075 if (*keyEncSz < 0) { 03076 WOLFSSL_MSG("RSA Public Encrypt failed"); 03077 FreeDecodedCert(decoded); 03078 #ifdef WOLFSSL_SMALL_STACK 03079 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03080 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03081 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03082 #endif 03083 return *keyEncSz; 03084 } 03085 03086 encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr); 03087 03088 /* RecipientInfo */ 03089 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + 03090 issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + 03091 *keyEncSz, recipSeq); 03092 03093 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + 03094 keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) { 03095 WOLFSSL_MSG("RecipientInfo output buffer too small"); 03096 FreeDecodedCert(decoded); 03097 #ifdef WOLFSSL_SMALL_STACK 03098 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03099 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03100 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03101 #endif 03102 return BUFFER_E; 03103 } 03104 03105 XMEMCPY(out + totalSz, recipSeq, recipSeqSz); 03106 totalSz += recipSeqSz; 03107 XMEMCPY(out + totalSz, ver, verSz); 03108 totalSz += verSz; 03109 XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz); 03110 totalSz += issuerSerialSeqSz; 03111 XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz); 03112 totalSz += issuerSeqSz; 03113 XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz); 03114 totalSz += issuerSz; 03115 XMEMCPY(out + totalSz, serial, snSz); 03116 totalSz += snSz; 03117 XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz); 03118 totalSz += keyEncAlgSz; 03119 XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz); 03120 totalSz += encKeyOctetStrSz; 03121 XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz); 03122 totalSz += *keyEncSz; 03123 03124 FreeDecodedCert(decoded); 03125 03126 #ifdef WOLFSSL_SMALL_STACK 03127 XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); 03128 XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); 03129 XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); 03130 #endif 03131 03132 return totalSz; 03133 } 03134 #endif /* !NO_RSA */ 03135 03136 03137 /* encrypt content using encryptOID algo */ 03138 static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, 03139 byte* iv, int ivSz, byte* in, int inSz, 03140 byte* out) 03141 { 03142 int ret; 03143 #ifndef NO_AES 03144 Aes aes; 03145 #endif 03146 #ifndef NO_DES3 03147 Des des; 03148 Des3 des3; 03149 #endif 03150 03151 if (key == NULL || iv == NULL || in == NULL || out == NULL) 03152 return BAD_FUNC_ARG; 03153 03154 switch (encryptOID) { 03155 #ifndef NO_AES 03156 #ifdef WOLFSSL_AES_128 03157 case AES128CBCb: 03158 #endif 03159 #ifdef WOLFSSL_AES_192 03160 case AES192CBCb: 03161 #endif 03162 #ifdef WOLFSSL_AES_256 03163 case AES256CBCb: 03164 #endif 03165 if ( 03166 #ifdef WOLFSSL_AES_128 03167 (encryptOID == AES128CBCb && keySz != 16 ) || 03168 #endif 03169 #ifdef WOLFSSL_AES_192 03170 (encryptOID == AES192CBCb && keySz != 24 ) || 03171 #endif 03172 #ifdef WOLFSSL_AES_256 03173 (encryptOID == AES256CBCb && keySz != 32 ) || 03174 #endif 03175 (ivSz != AES_BLOCK_SIZE) ) 03176 return BAD_FUNC_ARG; 03177 03178 ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION); 03179 if (ret == 0) 03180 ret = wc_AesCbcEncrypt(&aes, out, in, inSz); 03181 03182 break; 03183 #endif 03184 #ifndef NO_DES3 03185 case DESb: 03186 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) 03187 return BAD_FUNC_ARG; 03188 03189 ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); 03190 if (ret == 0) 03191 ret = wc_Des_CbcEncrypt(&des, out, in, inSz); 03192 03193 break; 03194 03195 case DES3b: 03196 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) 03197 return BAD_FUNC_ARG; 03198 03199 ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION); 03200 if (ret == 0) 03201 ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz); 03202 03203 break; 03204 #endif 03205 default: 03206 WOLFSSL_MSG("Unsupported content cipher type"); 03207 return ALGO_ID_E; 03208 }; 03209 03210 return ret; 03211 } 03212 03213 03214 /* decrypt content using encryptOID algo */ 03215 static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, 03216 byte* iv, int ivSz, byte* in, int inSz, 03217 byte* out) 03218 { 03219 int ret; 03220 #ifndef NO_AES 03221 Aes aes; 03222 #endif 03223 #ifndef NO_DES3 03224 Des des; 03225 Des3 des3; 03226 #endif 03227 03228 if (key == NULL || iv == NULL || in == NULL || out == NULL) 03229 return BAD_FUNC_ARG; 03230 03231 switch (encryptOID) { 03232 #ifndef NO_AES 03233 #ifdef WOLFSSL_AES_128 03234 case AES128CBCb: 03235 #endif 03236 #ifdef WOLFSSL_AES_192 03237 case AES192CBCb: 03238 #endif 03239 #ifdef WOLFSSL_AES_256 03240 case AES256CBCb: 03241 #endif 03242 if ( 03243 #ifdef WOLFSSL_AES_128 03244 (encryptOID == AES128CBCb && keySz != 16 ) || 03245 #endif 03246 #ifdef WOLFSSL_AES_192 03247 (encryptOID == AES192CBCb && keySz != 24 ) || 03248 #endif 03249 #ifdef WOLFSSL_AES_256 03250 (encryptOID == AES256CBCb && keySz != 32 ) || 03251 #endif 03252 (ivSz != AES_BLOCK_SIZE) ) 03253 return BAD_FUNC_ARG; 03254 03255 ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION); 03256 if (ret == 0) 03257 ret = wc_AesCbcDecrypt(&aes, out, in, inSz); 03258 03259 break; 03260 #endif 03261 #ifndef NO_DES3 03262 case DESb: 03263 if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) 03264 return BAD_FUNC_ARG; 03265 03266 ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION); 03267 if (ret == 0) 03268 ret = wc_Des_CbcDecrypt(&des, out, in, inSz); 03269 03270 break; 03271 case DES3b: 03272 if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) 03273 return BAD_FUNC_ARG; 03274 03275 ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION); 03276 if (ret == 0) 03277 ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz); 03278 03279 break; 03280 #endif 03281 default: 03282 WOLFSSL_MSG("Unsupported content cipher type"); 03283 return ALGO_ID_E; 03284 }; 03285 03286 return ret; 03287 } 03288 03289 03290 /* generate random IV, place in iv, return 0 on success negative on error */ 03291 static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) 03292 { 03293 int ret; 03294 WC_RNG* rnd = NULL; 03295 03296 if (iv == NULL || ivSz == 0) 03297 return BAD_FUNC_ARG; 03298 03299 /* input RNG is optional, init local one if input rng is NULL */ 03300 if (rng == NULL) { 03301 rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG); 03302 if (rnd == NULL) 03303 return MEMORY_E; 03304 03305 ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId); 03306 if (ret != 0) { 03307 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); 03308 return ret; 03309 } 03310 03311 } else { 03312 rnd = rng; 03313 } 03314 03315 ret = wc_RNG_GenerateBlock(rnd, iv, ivSz); 03316 03317 if (rng == NULL) { 03318 wc_FreeRng(rnd); 03319 XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); 03320 } 03321 03322 return ret; 03323 } 03324 03325 03326 /* return size of padded data, padded to blockSz chunks, or negative on error */ 03327 int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) 03328 { 03329 int padSz; 03330 03331 if (blockSz == 0) 03332 return BAD_FUNC_ARG; 03333 03334 padSz = blockSz - (inputSz % blockSz); 03335 03336 return padSz; 03337 } 03338 03339 03340 /* pad input data to blockSz chunk, place in outSz. out must be big enough 03341 * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */ 03342 int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, 03343 word32 blockSz) 03344 { 03345 int i, padSz; 03346 03347 if (in == NULL || inSz == 0 || 03348 out == NULL || outSz == 0) 03349 return BAD_FUNC_ARG; 03350 03351 padSz = wc_PKCS7_GetPadSize(inSz, blockSz); 03352 03353 if (outSz < (inSz + padSz)) 03354 return BAD_FUNC_ARG; 03355 03356 XMEMCPY(out, in, inSz); 03357 03358 for (i = 0; i < padSz; i++) { 03359 out[inSz + i] = (byte)padSz; 03360 } 03361 03362 return inSz + padSz; 03363 } 03364 03365 03366 /* build PKCS#7 envelopedData content type, return enveloped size */ 03367 int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) 03368 { 03369 int ret, idx = 0; 03370 int totalSz, padSz, encryptedOutSz; 03371 03372 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 03373 byte contentInfoSeq[MAX_SEQ_SZ]; 03374 byte outerContentType[MAX_ALGO_SZ]; 03375 byte outerContent[MAX_SEQ_SZ]; 03376 03377 int envDataSeqSz, verSz; 03378 byte envDataSeq[MAX_SEQ_SZ]; 03379 byte ver[MAX_VERSION_SZ]; 03380 03381 WC_RNG rng; 03382 int contentKeyEncSz, blockSz, blockKeySz; 03383 byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; 03384 #ifdef WOLFSSL_SMALL_STACK 03385 byte* contentKeyEnc; 03386 #else 03387 byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; 03388 #endif 03389 byte* plain; 03390 byte* encryptedContent; 03391 03392 int recipSz, recipSetSz; 03393 #ifdef WOLFSSL_SMALL_STACK 03394 byte* recip; 03395 #else 03396 byte recip[MAX_RECIP_SZ]; 03397 #endif 03398 byte recipSet[MAX_SET_SZ]; 03399 03400 int encContentOctetSz, encContentSeqSz, contentTypeSz; 03401 int contentEncAlgoSz, ivOctetStringSz; 03402 byte encContentSeq[MAX_SEQ_SZ]; 03403 byte contentType[MAX_ALGO_SZ]; 03404 byte contentEncAlgo[MAX_ALGO_SZ]; 03405 byte tmpIv[MAX_CONTENT_IV_SIZE]; 03406 byte ivOctetString[MAX_OCTET_STR_SZ]; 03407 byte encContentOctet[MAX_OCTET_STR_SZ]; 03408 03409 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 03410 pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL || 03411 pkcs7->publicKeyOID == 0) 03412 return BAD_FUNC_ARG; 03413 03414 if (output == NULL || outputSz == 0) 03415 return BAD_FUNC_ARG; 03416 03417 blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); 03418 if (blockKeySz < 0) 03419 return blockKeySz; 03420 03421 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); 03422 if (blockSz < 0) 03423 return blockSz; 03424 03425 /* outer content type */ 03426 outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType); 03427 03428 /* version, defined as 0 in RFC 2315 */ 03429 #ifdef HAVE_ECC 03430 if (pkcs7->publicKeyOID == ECDSAk) { 03431 verSz = SetMyVersion(2, ver, 0); 03432 } else 03433 #endif 03434 { 03435 verSz = SetMyVersion(0, ver, 0); 03436 } 03437 03438 /* generate random content encryption key */ 03439 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 03440 if (ret != 0) 03441 return ret; 03442 03443 ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); 03444 if (ret != 0) { 03445 wc_FreeRng(&rng); 03446 return ret; 03447 } 03448 03449 #ifdef WOLFSSL_SMALL_STACK 03450 recip = (byte*)XMALLOC(MAX_RECIP_SZ, pkcs7->heap, 03451 DYNAMIC_TYPE_PKCS7); 03452 contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 03453 DYNAMIC_TYPE_PKCS7); 03454 if (contentKeyEnc == NULL || recip == NULL) { 03455 if (recip) XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03456 if (contentKeyEnc) XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03457 wc_FreeRng(&rng); 03458 return MEMORY_E; 03459 } 03460 #endif 03461 contentKeyEncSz = MAX_ENCRYPTED_KEY_SZ; 03462 03463 /* build RecipientInfo, only handle 1 for now */ 03464 switch (pkcs7->publicKeyOID) { 03465 #ifndef NO_RSA 03466 case RSAk: 03467 recipSz = wc_CreateRecipientInfo(pkcs7->singleCert, 03468 pkcs7->singleCertSz, 03469 pkcs7->publicKeyOID, 03470 blockKeySz, &rng, contentKeyPlain, 03471 contentKeyEnc, &contentKeyEncSz, recip, 03472 MAX_RECIP_SZ, pkcs7->heap); 03473 break; 03474 #endif 03475 #ifdef HAVE_ECC 03476 case ECDSAk: 03477 recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, 03478 pkcs7->singleCertSz, 03479 pkcs7->publicKeyOID, 03480 blockKeySz, pkcs7->keyWrapOID, 03481 pkcs7->keyAgreeOID, &rng, 03482 contentKeyPlain, contentKeyEnc, 03483 &contentKeyEncSz, recip, MAX_RECIP_SZ); 03484 break; 03485 #endif 03486 03487 default: 03488 WOLFSSL_MSG("Unsupported RecipientInfo public key type"); 03489 return BAD_FUNC_ARG; 03490 }; 03491 03492 ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ); 03493 03494 #ifdef WOLFSSL_SMALL_STACK 03495 XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03496 #endif 03497 03498 if (recipSz < 0) { 03499 WOLFSSL_MSG("Failed to create RecipientInfo"); 03500 wc_FreeRng(&rng); 03501 #ifdef WOLFSSL_SMALL_STACK 03502 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03503 #endif 03504 return recipSz; 03505 } 03506 recipSetSz = SetSet(recipSz, recipSet); 03507 03508 /* generate IV for block cipher */ 03509 ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz); 03510 wc_FreeRng(&rng); 03511 if (ret != 0) { 03512 #ifdef WOLFSSL_SMALL_STACK 03513 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03514 #endif 03515 return ret; 03516 } 03517 03518 /* EncryptedContentInfo */ 03519 contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); 03520 if (contentTypeSz == 0) { 03521 #ifdef WOLFSSL_SMALL_STACK 03522 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03523 #endif 03524 return BAD_FUNC_ARG; 03525 } 03526 03527 /* allocate encrypted content buffer and PKCS#7 padding */ 03528 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); 03529 if (padSz < 0) 03530 return padSz; 03531 03532 encryptedOutSz = pkcs7->contentSz + padSz; 03533 03534 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 03535 DYNAMIC_TYPE_PKCS7); 03536 if (plain == NULL) 03537 return MEMORY_E; 03538 03539 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, 03540 encryptedOutSz, blockSz); 03541 if (ret < 0) { 03542 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03543 return ret; 03544 } 03545 03546 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 03547 DYNAMIC_TYPE_PKCS7); 03548 if (encryptedContent == NULL) { 03549 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03550 #ifdef WOLFSSL_SMALL_STACK 03551 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03552 #endif 03553 return MEMORY_E; 03554 } 03555 03556 /* put together IV OCTET STRING */ 03557 ivOctetStringSz = SetOctetString(blockSz, ivOctetString); 03558 03559 /* build up our ContentEncryptionAlgorithmIdentifier sequence, 03560 * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ 03561 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 03562 oidBlkType, ivOctetStringSz + blockSz); 03563 03564 if (contentEncAlgoSz == 0) { 03565 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03566 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03567 #ifdef WOLFSSL_SMALL_STACK 03568 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03569 #endif 03570 return BAD_FUNC_ARG; 03571 } 03572 03573 /* encrypt content */ 03574 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, contentKeyPlain, 03575 blockKeySz, tmpIv, blockSz, plain, encryptedOutSz, 03576 encryptedContent); 03577 03578 if (ret != 0) { 03579 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03580 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03581 #ifdef WOLFSSL_SMALL_STACK 03582 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03583 #endif 03584 return ret; 03585 } 03586 03587 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, 03588 encContentOctet); 03589 03590 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 03591 ivOctetStringSz + blockSz + 03592 encContentOctetSz + encryptedOutSz, 03593 encContentSeq); 03594 03595 /* keep track of sizes for outer wrapper layering */ 03596 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + 03597 contentEncAlgoSz + ivOctetStringSz + blockSz + 03598 encContentOctetSz + encryptedOutSz; 03599 03600 /* EnvelopedData */ 03601 envDataSeqSz = SetSequence(totalSz, envDataSeq); 03602 totalSz += envDataSeqSz; 03603 03604 /* outer content */ 03605 outerContentSz = SetExplicit(0, totalSz, outerContent); 03606 totalSz += outerContentTypeSz; 03607 totalSz += outerContentSz; 03608 03609 /* ContentInfo */ 03610 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 03611 totalSz += contentInfoSeqSz; 03612 03613 if (totalSz > (int)outputSz) { 03614 WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); 03615 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03616 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03617 #ifdef WOLFSSL_SMALL_STACK 03618 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03619 #endif 03620 return BUFFER_E; 03621 } 03622 03623 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 03624 idx += contentInfoSeqSz; 03625 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 03626 idx += outerContentTypeSz; 03627 XMEMCPY(output + idx, outerContent, outerContentSz); 03628 idx += outerContentSz; 03629 XMEMCPY(output + idx, envDataSeq, envDataSeqSz); 03630 idx += envDataSeqSz; 03631 XMEMCPY(output + idx, ver, verSz); 03632 idx += verSz; 03633 XMEMCPY(output + idx, recipSet, recipSetSz); 03634 idx += recipSetSz; 03635 XMEMCPY(output + idx, recip, recipSz); 03636 idx += recipSz; 03637 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 03638 idx += encContentSeqSz; 03639 XMEMCPY(output + idx, contentType, contentTypeSz); 03640 idx += contentTypeSz; 03641 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 03642 idx += contentEncAlgoSz; 03643 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 03644 idx += ivOctetStringSz; 03645 XMEMCPY(output + idx, tmpIv, blockSz); 03646 idx += blockSz; 03647 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 03648 idx += encContentOctetSz; 03649 XMEMCPY(output + idx, encryptedContent, encryptedOutSz); 03650 idx += encryptedOutSz; 03651 03652 ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN); 03653 03654 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03655 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 03656 03657 #ifdef WOLFSSL_SMALL_STACK 03658 XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03659 #endif 03660 03661 return idx; 03662 } 03663 03664 #ifndef NO_RSA 03665 /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ 03666 static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, 03667 word32* idx, byte* decryptedKey, 03668 word32* decryptedKeySz, int* recipFound) 03669 { 03670 int length, encryptedKeySz, ret; 03671 int keySz; 03672 word32 encOID; 03673 word32 keyIdx; 03674 byte issuerHash[KEYID_SIZE]; 03675 byte* outKey = NULL; 03676 03677 #ifdef WC_RSA_BLINDING 03678 WC_RNG rng; 03679 #endif 03680 03681 #ifdef WOLFSSL_SMALL_STACK 03682 mp_int* serialNum; 03683 byte* encryptedKey; 03684 RsaKey* privKey; 03685 #else 03686 mp_int stack_serialNum; 03687 mp_int* serialNum = &stack_serialNum; 03688 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 03689 03690 RsaKey stack_privKey; 03691 RsaKey* privKey = &stack_privKey; 03692 #endif 03693 03694 /* remove IssuerAndSerialNumber */ 03695 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 03696 return ASN_PARSE_E; 03697 03698 if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) 03699 return ASN_PARSE_E; 03700 03701 /* if we found correct recipient, issuer hashes will match */ 03702 if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { 03703 *recipFound = 1; 03704 } 03705 03706 #ifdef WOLFSSL_SMALL_STACK 03707 serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, 03708 DYNAMIC_TYPE_TMP_BUFFER); 03709 if (serialNum == NULL) 03710 return MEMORY_E; 03711 #endif 03712 03713 if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { 03714 #ifdef WOLFSSL_SMALL_STACK 03715 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03716 #endif 03717 return ASN_PARSE_E; 03718 } 03719 03720 mp_clear(serialNum); 03721 03722 #ifdef WOLFSSL_SMALL_STACK 03723 XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03724 #endif 03725 03726 if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) 03727 return ASN_PARSE_E; 03728 03729 /* key encryption algorithm must be RSA for now */ 03730 if (encOID != RSAk) 03731 return ALGO_ID_E; 03732 03733 /* read encryptedKey */ 03734 #ifdef WOLFSSL_SMALL_STACK 03735 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 03736 DYNAMIC_TYPE_TMP_BUFFER); 03737 if (encryptedKey == NULL) 03738 return MEMORY_E; 03739 #endif 03740 03741 if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) { 03742 #ifdef WOLFSSL_SMALL_STACK 03743 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03744 #endif 03745 return ASN_PARSE_E; 03746 } 03747 03748 if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { 03749 #ifdef WOLFSSL_SMALL_STACK 03750 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03751 #endif 03752 return ASN_PARSE_E; 03753 } 03754 03755 if (*recipFound == 1) 03756 XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); 03757 *idx += encryptedKeySz; 03758 03759 /* load private key */ 03760 #ifdef WOLFSSL_SMALL_STACK 03761 privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, 03762 DYNAMIC_TYPE_TMP_BUFFER); 03763 if (privKey == NULL) { 03764 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03765 return MEMORY_E; 03766 } 03767 #endif 03768 03769 ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); 03770 if (ret != 0) { 03771 #ifdef WOLFSSL_SMALL_STACK 03772 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03773 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03774 #endif 03775 return ret; 03776 } 03777 03778 if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { 03779 keyIdx = 0; 03780 ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey, 03781 pkcs7->privateKeySz); 03782 } 03783 else if (pkcs7->devId == INVALID_DEVID) { 03784 ret = BAD_FUNC_ARG; 03785 } 03786 if (ret != 0) { 03787 WOLFSSL_MSG("Failed to decode RSA private key"); 03788 wc_FreeRsaKey(privKey); 03789 #ifdef WOLFSSL_SMALL_STACK 03790 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03791 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03792 #endif 03793 return ret; 03794 } 03795 03796 /* decrypt encryptedKey */ 03797 #ifdef WC_RSA_BLINDING 03798 ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); 03799 if (ret == 0) { 03800 ret = wc_RsaSetRNG(privKey, &rng); 03801 } 03802 #endif 03803 if (ret == 0) { 03804 keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, 03805 &outKey, privKey); 03806 #ifdef WC_RSA_BLINDING 03807 wc_FreeRng(&rng); 03808 #endif 03809 } else { 03810 keySz = ret; 03811 } 03812 wc_FreeRsaKey(privKey); 03813 03814 if (keySz <= 0 || outKey == NULL) { 03815 ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); 03816 #ifdef WOLFSSL_SMALL_STACK 03817 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03818 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03819 #endif 03820 return keySz; 03821 } else { 03822 *decryptedKeySz = keySz; 03823 XMEMCPY(decryptedKey, outKey, keySz); 03824 ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); 03825 } 03826 03827 #ifdef WOLFSSL_SMALL_STACK 03828 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03829 XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); 03830 #endif 03831 03832 return 0; 03833 } 03834 #endif /* !NO_RSA */ 03835 03836 #ifdef HAVE_ECC 03837 03838 /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ 03839 static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, 03840 byte* pkiMsg, word32 pkiMsgSz, word32* idx) 03841 { 03842 int ret, length; 03843 word32 keyOID; 03844 03845 if (kari == NULL || pkiMsg == NULL || idx == NULL) 03846 return BAD_FUNC_ARG; 03847 03848 /* remove OriginatorIdentifierOrKey */ 03849 if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 03850 (*idx)++; 03851 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 03852 return ASN_PARSE_E; 03853 03854 } else { 03855 return ASN_PARSE_E; 03856 } 03857 03858 /* remove OriginatorPublicKey */ 03859 if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 03860 (*idx)++; 03861 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 03862 return ASN_PARSE_E; 03863 03864 } else { 03865 return ASN_PARSE_E; 03866 } 03867 03868 /* remove AlgorithmIdentifier */ 03869 if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0) 03870 return ASN_PARSE_E; 03871 03872 if (keyOID != ECDSAk) 03873 return ASN_PARSE_E; 03874 03875 /* remove ECPoint BIT STRING */ 03876 if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING)) 03877 return ASN_PARSE_E; 03878 03879 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 03880 return ASN_PARSE_E; 03881 03882 if ((pkiMsgSz < (*idx + 1)) || (pkiMsg[(*idx)++] != 0x00)) 03883 return ASN_EXPECT_0_E; 03884 03885 /* get sender ephemeral public ECDSA key */ 03886 ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); 03887 if (ret != 0) 03888 return ret; 03889 03890 kari->senderKeyInit = 1; 03891 03892 /* length-1 for unused bits counter */ 03893 ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey); 03894 if (ret != 0) 03895 return ret; 03896 03897 (*idx) += length - 1; 03898 03899 return 0; 03900 } 03901 03902 03903 /* remove optional UserKeyingMaterial if available, return 0 on success, 03904 * < 0 on error */ 03905 static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, 03906 byte* pkiMsg, word32 pkiMsgSz, word32* idx) 03907 { 03908 int length; 03909 word32 savedIdx; 03910 03911 if (kari == NULL || pkiMsg == NULL || idx == NULL) 03912 return BAD_FUNC_ARG; 03913 03914 savedIdx = *idx; 03915 03916 /* starts with EXPLICIT [1] */ 03917 if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 03918 *idx = savedIdx; 03919 return 0; 03920 } 03921 03922 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 03923 *idx = savedIdx; 03924 return 0; 03925 } 03926 03927 /* get OCTET STRING */ 03928 if ( (pkiMsgSz > ((*idx) + 1)) && 03929 (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { 03930 *idx = savedIdx; 03931 return 0; 03932 } 03933 03934 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { 03935 *idx = savedIdx; 03936 return 0; 03937 } 03938 03939 kari->ukm = NULL; 03940 if (length > 0) { 03941 kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); 03942 if (kari->ukm == NULL) 03943 return MEMORY_E; 03944 03945 XMEMCPY(kari->ukm, pkiMsg + (*idx), length); 03946 kari->ukmOwner = 1; 03947 } 03948 03949 (*idx) += length; 03950 kari->ukmSz = length; 03951 03952 return 0; 03953 } 03954 03955 03956 /* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success, 03957 * < 0 on error */ 03958 static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, 03959 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 03960 word32* keyAgreeOID, word32* keyWrapOID) 03961 { 03962 if (kari == NULL || pkiMsg == NULL || idx == NULL || 03963 keyAgreeOID == NULL || keyWrapOID == NULL) 03964 return BAD_FUNC_ARG; 03965 03966 /* remove KeyEncryptionAlgorithmIdentifier */ 03967 if (GetAlgoId(pkiMsg, idx, keyAgreeOID, oidCmsKeyAgreeType, 03968 pkiMsgSz) < 0) 03969 return ASN_PARSE_E; 03970 03971 /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */ 03972 if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) 03973 return ASN_PARSE_E; 03974 03975 return 0; 03976 } 03977 03978 03979 /* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error 03980 * if subject key ID matches, recipFound is set to 1 */ 03981 static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, 03982 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 03983 int* recipFound) 03984 { 03985 int length; 03986 byte subjKeyId[KEYID_SIZE]; 03987 03988 if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL) 03989 return BAD_FUNC_ARG; 03990 03991 /* remove RecipientKeyIdentifier IMPLICIT [0] */ 03992 if ( (pkiMsgSz > (*idx + 1)) && 03993 (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { 03994 03995 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 03996 return ASN_PARSE_E; 03997 03998 } else { 03999 return ASN_PARSE_E; 04000 } 04001 04002 /* remove SubjectKeyIdentifier */ 04003 if ( (pkiMsgSz > (*idx + 1)) && 04004 (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) 04005 return ASN_PARSE_E; 04006 04007 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 04008 return ASN_PARSE_E; 04009 04010 if (length != KEYID_SIZE) 04011 return ASN_PARSE_E; 04012 04013 XMEMCPY(subjKeyId, pkiMsg + (*idx), KEYID_SIZE); 04014 (*idx) += length; 04015 04016 /* subject key id should match if recipient found */ 04017 if (XMEMCMP(subjKeyId, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) { 04018 *recipFound = 1; 04019 } 04020 04021 return 0; 04022 } 04023 04024 04025 /* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error 04026 * if issuer and serial number match, recipFound is set to 1 */ 04027 static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, 04028 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 04029 int* recipFound) 04030 { 04031 int length, ret; 04032 byte issuerHash[KEYID_SIZE]; 04033 #ifdef WOLFSSL_SMALL_STACK 04034 mp_int* serial; 04035 mp_int* recipSerial; 04036 #else 04037 mp_int stack_serial; 04038 mp_int* serial = &stack_serial; 04039 04040 mp_int stack_recipSerial; 04041 mp_int* recipSerial = &stack_recipSerial; 04042 #endif 04043 04044 /* remove IssuerAndSerialNumber */ 04045 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 04046 return ASN_PARSE_E; 04047 04048 if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) 04049 return ASN_PARSE_E; 04050 04051 /* if we found correct recipient, issuer hashes will match */ 04052 if (XMEMCMP(issuerHash, kari->decoded->issuerHash, KEYID_SIZE) == 0) { 04053 *recipFound = 1; 04054 } 04055 04056 #ifdef WOLFSSL_SMALL_STACK 04057 serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, 04058 DYNAMIC_TYPE_TMP_BUFFER); 04059 if (serial == NULL) 04060 return MEMORY_E; 04061 04062 recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, 04063 DYNAMIC_TYPE_TMP_BUFFER); 04064 if (recipSerial == NULL) { 04065 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04066 return MEMORY_E; 04067 } 04068 #endif 04069 04070 if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { 04071 #ifdef WOLFSSL_SMALL_STACK 04072 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04073 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04074 #endif 04075 return ASN_PARSE_E; 04076 } 04077 04078 ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial, 04079 kari->decoded->serialSz); 04080 if (ret != MP_OKAY) { 04081 mp_clear(serial); 04082 WOLFSSL_MSG("Failed to parse CMS recipient serial number"); 04083 #ifdef WOLFSSL_SMALL_STACK 04084 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04085 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04086 #endif 04087 return ret; 04088 } 04089 04090 if (mp_cmp(recipSerial, serial) != MP_EQ) { 04091 mp_clear(serial); 04092 mp_clear(recipSerial); 04093 WOLFSSL_MSG("CMS serial number does not match recipient"); 04094 #ifdef WOLFSSL_SMALL_STACK 04095 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04096 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04097 #endif 04098 return PKCS7_RECIP_E; 04099 } 04100 04101 mp_clear(serial); 04102 mp_clear(recipSerial); 04103 04104 #ifdef WOLFSSL_SMALL_STACK 04105 XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04106 XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); 04107 #endif 04108 04109 return 0; 04110 } 04111 04112 04113 /* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ 04114 static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, 04115 byte* pkiMsg, word32 pkiMsgSz, word32* idx, 04116 int* recipFound, byte* encryptedKey, 04117 int* encryptedKeySz) 04118 { 04119 int length; 04120 int ret = 0; 04121 04122 if (kari == NULL || pkiMsg == NULL || idx == NULL || 04123 recipFound == NULL || encryptedKey == NULL) 04124 return BAD_FUNC_ARG; 04125 04126 /* remove RecipientEncryptedKeys */ 04127 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 04128 return ASN_PARSE_E; 04129 04130 /* remove RecipientEncryptedKeys */ 04131 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) 04132 return ASN_PARSE_E; 04133 04134 /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber 04135 * or [0] IMMPLICIT RecipientKeyIdentifier */ 04136 if ( (pkiMsgSz > (*idx + 1)) && 04137 (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { 04138 04139 /* try to get RecipientKeyIdentifier */ 04140 ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, 04141 idx, recipFound); 04142 } else { 04143 /* try to get IssuerAndSerialNumber */ 04144 ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, 04145 idx, recipFound); 04146 } 04147 04148 /* if we don't have either option, malformed CMS */ 04149 if (ret != 0) 04150 return ret; 04151 04152 /* remove EncryptedKey */ 04153 if ( (pkiMsgSz > (*idx + 1)) && 04154 (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) 04155 return ASN_PARSE_E; 04156 04157 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 04158 return ASN_PARSE_E; 04159 04160 /* put encrypted CEK in decryptedKey buffer for now, decrypt later */ 04161 if (length > *encryptedKeySz) 04162 return BUFFER_E; 04163 04164 XMEMCPY(encryptedKey, pkiMsg + (*idx), length); 04165 *encryptedKeySz = length; 04166 (*idx) += length; 04167 04168 return 0; 04169 } 04170 04171 #endif /* HAVE_ECC */ 04172 04173 04174 /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, 04175 * < 0 on error */ 04176 static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, 04177 word32* idx, byte* decryptedKey, 04178 word32* decryptedKeySz, int* recipFound) 04179 { 04180 #ifdef HAVE_ECC 04181 int ret, keySz; 04182 int encryptedKeySz; 04183 int direction = 0; 04184 word32 keyAgreeOID, keyWrapOID; 04185 04186 #ifdef WOLFSSL_SMALL_STACK 04187 byte* encryptedKey; 04188 #else 04189 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 04190 #endif 04191 04192 WC_PKCS7_KARI* kari; 04193 04194 if (pkcs7 == NULL || pkcs7->singleCert == NULL || 04195 pkcs7->singleCertSz == 0 || pkiMsg == NULL || 04196 idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { 04197 return BAD_FUNC_ARG; 04198 } 04199 04200 kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); 04201 if (kari == NULL) 04202 return MEMORY_E; 04203 04204 #ifdef WOLFSSL_SMALL_STACK 04205 encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 04206 DYNAMIC_TYPE_PKCS7); 04207 if (encryptedKey == NULL) { 04208 wc_PKCS7_KariFree(kari); 04209 return MEMORY_E; 04210 } 04211 #endif 04212 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 04213 04214 /* parse cert and key */ 04215 ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, 04216 pkcs7->singleCertSz, pkcs7->privateKey, 04217 pkcs7->privateKeySz); 04218 if (ret != 0) { 04219 wc_PKCS7_KariFree(kari); 04220 #ifdef WOLFSSL_SMALL_STACK 04221 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04222 #endif 04223 return ret; 04224 } 04225 04226 /* remove OriginatorIdentifierOrKey */ 04227 ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, 04228 pkiMsgSz, idx); 04229 if (ret != 0) { 04230 wc_PKCS7_KariFree(kari); 04231 #ifdef WOLFSSL_SMALL_STACK 04232 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04233 #endif 04234 return ret; 04235 } 04236 04237 /* try and remove optional UserKeyingMaterial */ 04238 ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); 04239 if (ret != 0) { 04240 wc_PKCS7_KariFree(kari); 04241 #ifdef WOLFSSL_SMALL_STACK 04242 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04243 #endif 04244 return ret; 04245 } 04246 04247 /* remove KeyEncryptionAlgorithmIdentifier */ 04248 ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, pkiMsgSz, 04249 idx, &keyAgreeOID, 04250 &keyWrapOID); 04251 if (ret != 0) { 04252 wc_PKCS7_KariFree(kari); 04253 #ifdef WOLFSSL_SMALL_STACK 04254 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04255 #endif 04256 return ret; 04257 } 04258 04259 /* if user has not explicitly set keyAgreeOID, set from one in bundle */ 04260 if (pkcs7->keyAgreeOID == 0) 04261 pkcs7->keyAgreeOID = keyAgreeOID; 04262 04263 /* set direction based on key wrap algorithm */ 04264 switch (keyWrapOID) { 04265 #ifndef NO_AES 04266 #ifdef WOLFSSL_AES_128 04267 case AES128_WRAP: 04268 #endif 04269 #ifdef WOLFSSL_AES_192 04270 case AES192_WRAP: 04271 #endif 04272 #ifdef WOLFSSL_AES_256 04273 case AES256_WRAP: 04274 #endif 04275 direction = AES_DECRYPTION; 04276 break; 04277 #endif 04278 default: 04279 wc_PKCS7_KariFree(kari); 04280 #ifdef WOLFSSL_SMALL_STACK 04281 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04282 #endif 04283 WOLFSSL_MSG("AES key wrap algorithm unsupported"); 04284 return BAD_KEYWRAP_ALG_E; 04285 } 04286 04287 /* remove RecipientEncryptedKeys */ 04288 ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, 04289 idx, recipFound, encryptedKey, &encryptedKeySz); 04290 if (ret != 0) { 04291 wc_PKCS7_KariFree(kari); 04292 #ifdef WOLFSSL_SMALL_STACK 04293 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04294 #endif 04295 return ret; 04296 } 04297 04298 /* create KEK */ 04299 ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); 04300 if (ret != 0) { 04301 wc_PKCS7_KariFree(kari); 04302 #ifdef WOLFSSL_SMALL_STACK 04303 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04304 #endif 04305 return ret; 04306 } 04307 04308 /* decrypt CEK with KEK */ 04309 keySz = wc_PKCS7_KariKeyWrap(encryptedKey, encryptedKeySz, kari->kek, 04310 kari->kekSz, decryptedKey, *decryptedKeySz, 04311 keyWrapOID, direction); 04312 if (keySz <= 0) { 04313 wc_PKCS7_KariFree(kari); 04314 #ifdef WOLFSSL_SMALL_STACK 04315 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04316 #endif 04317 return keySz; 04318 } 04319 *decryptedKeySz = (word32)keySz; 04320 04321 wc_PKCS7_KariFree(kari); 04322 #ifdef WOLFSSL_SMALL_STACK 04323 XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04324 #endif 04325 04326 return 0; 04327 #else 04328 (void)pkcs7; 04329 (void)pkiMsg; 04330 (void)pkiMsgSz; 04331 (void)idx; 04332 (void)decryptedKey; 04333 (void)decryptedKeySz; 04334 (void)recipFound; 04335 04336 return NOT_COMPILED_IN; 04337 #endif /* HAVE_ECC */ 04338 } 04339 04340 04341 /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ 04342 static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, 04343 word32 pkiMsgSz, word32* idx, byte* decryptedKey, 04344 word32* decryptedKeySz, int* recipFound) 04345 { 04346 word32 savedIdx; 04347 int version, ret, length; 04348 04349 if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || 04350 decryptedKey == NULL || decryptedKeySz == NULL || 04351 recipFound == NULL) { 04352 return BAD_FUNC_ARG; 04353 } 04354 04355 savedIdx = *idx; 04356 04357 /* when looking for next recipient, use first sequence and version to 04358 * indicate there is another, if not, move on */ 04359 while(*recipFound == 0) { 04360 04361 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to 04362 * last good saved one */ 04363 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) { 04364 04365 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { 04366 *idx = savedIdx; 04367 break; 04368 } 04369 04370 if (version != 0) 04371 return ASN_VERSION_E; 04372 04373 #ifndef NO_RSA 04374 /* found ktri */ 04375 ret = wc_PKCS7_DecodeKtri(pkcs7, pkiMsg, pkiMsgSz, idx, 04376 decryptedKey, decryptedKeySz, 04377 recipFound); 04378 if (ret != 0) 04379 return ret; 04380 #else 04381 return NOT_COMPILED_IN; 04382 #endif 04383 } 04384 else { 04385 /* kari is IMPLICIT[1] */ 04386 *idx = savedIdx; 04387 if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 04388 (*idx)++; 04389 04390 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) 04391 return ASN_PARSE_E; 04392 04393 if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { 04394 *idx = savedIdx; 04395 break; 04396 } 04397 04398 if (version != 3) 04399 return ASN_VERSION_E; 04400 04401 /* found kari */ 04402 ret = wc_PKCS7_DecodeKari(pkcs7, pkiMsg, pkiMsgSz, idx, 04403 decryptedKey, decryptedKeySz, 04404 recipFound); 04405 if (ret != 0) 04406 return ret; 04407 } 04408 else { 04409 /* failed to find RecipientInfo, restore idx and continue */ 04410 *idx = savedIdx; 04411 break; 04412 } 04413 } 04414 04415 /* update good idx */ 04416 savedIdx = *idx; 04417 } 04418 04419 return 0; 04420 } 04421 04422 04423 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ 04424 WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, 04425 word32 pkiMsgSz, byte* output, 04426 word32 outputSz) 04427 { 04428 int recipFound = 0; 04429 int ret, version, length; 04430 word32 idx = 0; 04431 word32 contentType, encOID; 04432 word32 decryptedKeySz; 04433 04434 int expBlockSz, blockKeySz; 04435 byte tmpIv[MAX_CONTENT_IV_SIZE]; 04436 04437 #ifdef WOLFSSL_SMALL_STACK 04438 byte* decryptedKey; 04439 #else 04440 byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; 04441 #endif 04442 int encryptedContentSz; 04443 byte padLen; 04444 byte* encryptedContent = NULL; 04445 int explicitOctet; 04446 04447 if (pkcs7 == NULL || pkcs7->singleCert == NULL || 04448 pkcs7->singleCertSz == 0) 04449 return BAD_FUNC_ARG; 04450 04451 if (pkiMsg == NULL || pkiMsgSz == 0 || 04452 output == NULL || outputSz == 0) 04453 return BAD_FUNC_ARG; 04454 04455 /* read past ContentInfo, verify type is envelopedData */ 04456 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04457 return ASN_PARSE_E; 04458 04459 if (length == 0 && pkiMsg[idx-1] == 0x80) { 04460 #ifdef ASN_BER_TO_DER 04461 word32 len = 0; 04462 04463 ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); 04464 if (ret != LENGTH_ONLY_E) 04465 return ret; 04466 pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04467 if (pkcs7->der == NULL) 04468 return MEMORY_E; 04469 ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); 04470 if (ret < 0) 04471 return ret; 04472 04473 pkiMsg = pkcs7->der; 04474 pkiMsgSz = len; 04475 idx = 0; 04476 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04477 return ASN_PARSE_E; 04478 #else 04479 return BER_INDEF_E; 04480 #endif 04481 } 04482 04483 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 04484 return ASN_PARSE_E; 04485 04486 if (contentType != ENVELOPED_DATA) { 04487 WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); 04488 return PKCS7_OID_E; 04489 } 04490 04491 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 04492 return ASN_PARSE_E; 04493 04494 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04495 return ASN_PARSE_E; 04496 04497 /* remove EnvelopedData and version */ 04498 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04499 return ASN_PARSE_E; 04500 04501 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 04502 return ASN_PARSE_E; 04503 04504 /* TODO :: make this more accurate */ 04505 if ((pkcs7->publicKeyOID == RSAk && version != 0) 04506 #ifdef HAVE_ECC 04507 || (pkcs7->publicKeyOID == ECDSAk && version != 2) 04508 #endif 04509 ) { 04510 WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0"); 04511 return ASN_VERSION_E; 04512 } 04513 04514 /* walk through RecipientInfo set, find correct recipient */ 04515 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04516 return ASN_PARSE_E; 04517 04518 #ifdef WOLFSSL_SMALL_STACK 04519 decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, 04520 DYNAMIC_TYPE_PKCS7); 04521 if (decryptedKey == NULL) 04522 return MEMORY_E; 04523 #endif 04524 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; 04525 04526 ret = wc_PKCS7_DecodeRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, 04527 decryptedKey, &decryptedKeySz, 04528 &recipFound); 04529 if (ret != 0) { 04530 #ifdef WOLFSSL_SMALL_STACK 04531 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04532 #endif 04533 return ret; 04534 } 04535 04536 if (recipFound == 0) { 04537 WOLFSSL_MSG("No recipient found in envelopedData that matches input"); 04538 #ifdef WOLFSSL_SMALL_STACK 04539 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04540 #endif 04541 return PKCS7_RECIP_E; 04542 } 04543 04544 /* remove EncryptedContentInfo */ 04545 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 04546 #ifdef WOLFSSL_SMALL_STACK 04547 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04548 #endif 04549 return ASN_PARSE_E; 04550 } 04551 04552 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { 04553 #ifdef WOLFSSL_SMALL_STACK 04554 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04555 #endif 04556 return ASN_PARSE_E; 04557 } 04558 04559 if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { 04560 #ifdef WOLFSSL_SMALL_STACK 04561 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04562 #endif 04563 return ASN_PARSE_E; 04564 } 04565 04566 blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); 04567 if (blockKeySz < 0) { 04568 #ifdef WOLFSSL_SMALL_STACK 04569 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04570 #endif 04571 return blockKeySz; 04572 } 04573 04574 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); 04575 if (expBlockSz < 0) { 04576 #ifdef WOLFSSL_SMALL_STACK 04577 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04578 #endif 04579 return expBlockSz; 04580 } 04581 04582 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 04583 if (pkiMsg[idx++] != ASN_OCTET_STRING) { 04584 #ifdef WOLFSSL_SMALL_STACK 04585 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04586 #endif 04587 return ASN_PARSE_E; 04588 } 04589 04590 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 04591 #ifdef WOLFSSL_SMALL_STACK 04592 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04593 #endif 04594 return ASN_PARSE_E; 04595 } 04596 04597 if (length != expBlockSz) { 04598 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); 04599 #ifdef WOLFSSL_SMALL_STACK 04600 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04601 #endif 04602 return ASN_PARSE_E; 04603 } 04604 04605 XMEMCPY(tmpIv, &pkiMsg[idx], length); 04606 idx += length; 04607 04608 explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); 04609 04610 /* read encryptedContent, cont[0] */ 04611 if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && 04612 pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { 04613 #ifdef WOLFSSL_SMALL_STACK 04614 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04615 #endif 04616 return ASN_PARSE_E; 04617 } 04618 idx++; 04619 04620 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { 04621 #ifdef WOLFSSL_SMALL_STACK 04622 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04623 #endif 04624 return ASN_PARSE_E; 04625 } 04626 04627 if (explicitOctet) { 04628 if (pkiMsg[idx++] != ASN_OCTET_STRING) { 04629 #ifdef WOLFSSL_SMALL_STACK 04630 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04631 #endif 04632 return ASN_PARSE_E; 04633 } 04634 04635 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { 04636 #ifdef WOLFSSL_SMALL_STACK 04637 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04638 #endif 04639 return ASN_PARSE_E; 04640 } 04641 } 04642 04643 encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, 04644 DYNAMIC_TYPE_PKCS7); 04645 if (encryptedContent == NULL) { 04646 #ifdef WOLFSSL_SMALL_STACK 04647 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04648 #endif 04649 return MEMORY_E; 04650 } 04651 04652 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 04653 04654 /* decrypt encryptedContent */ 04655 ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, 04656 tmpIv, expBlockSz, encryptedContent, 04657 encryptedContentSz, encryptedContent); 04658 if (ret != 0) { 04659 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04660 #ifdef WOLFSSL_SMALL_STACK 04661 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04662 #endif 04663 return ret; 04664 } 04665 04666 padLen = encryptedContent[encryptedContentSz-1]; 04667 04668 /* copy plaintext to output */ 04669 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 04670 04671 /* free memory, zero out keys */ 04672 ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); 04673 ForceZero(encryptedContent, encryptedContentSz); 04674 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04675 #ifdef WOLFSSL_SMALL_STACK 04676 XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04677 #endif 04678 04679 return encryptedContentSz - padLen; 04680 } 04681 04682 04683 #ifndef NO_PKCS7_ENCRYPTED_DATA 04684 04685 /* build PKCS#7 encryptedData content type, return encrypted size */ 04686 int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) 04687 { 04688 int ret, idx = 0; 04689 int totalSz, padSz, encryptedOutSz; 04690 04691 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 04692 byte contentInfoSeq[MAX_SEQ_SZ]; 04693 byte outerContentType[MAX_ALGO_SZ]; 04694 byte outerContent[MAX_SEQ_SZ]; 04695 04696 int encDataSeqSz, verSz, blockSz; 04697 byte encDataSeq[MAX_SEQ_SZ]; 04698 byte ver[MAX_VERSION_SZ]; 04699 04700 byte* plain = NULL; 04701 byte* encryptedContent = NULL; 04702 04703 int encContentOctetSz, encContentSeqSz, contentTypeSz; 04704 int contentEncAlgoSz, ivOctetStringSz; 04705 byte encContentSeq[MAX_SEQ_SZ]; 04706 byte contentType[MAX_ALGO_SZ]; 04707 byte contentEncAlgo[MAX_ALGO_SZ]; 04708 byte tmpIv[MAX_CONTENT_IV_SIZE]; 04709 byte ivOctetString[MAX_OCTET_STR_SZ]; 04710 byte encContentOctet[MAX_OCTET_STR_SZ]; 04711 04712 byte attribSet[MAX_SET_SZ]; 04713 EncodedAttrib* attribs = NULL; 04714 word32 attribsSz; 04715 word32 attribsCount; 04716 word32 attribsSetSz; 04717 04718 byte* flatAttribs = NULL; 04719 04720 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 04721 pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL || 04722 pkcs7->encryptionKeySz == 0) 04723 return BAD_FUNC_ARG; 04724 04725 if (output == NULL || outputSz == 0) 04726 return BAD_FUNC_ARG; 04727 04728 /* outer content type */ 04729 outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType); 04730 04731 /* version, 2 if unprotectedAttrs present, 0 if absent */ 04732 if (pkcs7->unprotectedAttribsSz > 0) { 04733 verSz = SetMyVersion(2, ver, 0); 04734 } else { 04735 verSz = SetMyVersion(0, ver, 0); 04736 } 04737 04738 /* EncryptedContentInfo */ 04739 contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); 04740 if (contentTypeSz == 0) 04741 return BAD_FUNC_ARG; 04742 04743 /* allocate encrypted content buffer, do PKCS#7 padding */ 04744 blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); 04745 if (blockSz < 0) 04746 return blockSz; 04747 04748 padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); 04749 if (padSz < 0) 04750 return padSz; 04751 04752 encryptedOutSz = pkcs7->contentSz + padSz; 04753 04754 plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 04755 DYNAMIC_TYPE_PKCS7); 04756 if (plain == NULL) 04757 return MEMORY_E; 04758 04759 ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, 04760 encryptedOutSz, blockSz); 04761 if (ret < 0) { 04762 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04763 return ret; 04764 } 04765 04766 encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, 04767 DYNAMIC_TYPE_PKCS7); 04768 if (encryptedContent == NULL) { 04769 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04770 return MEMORY_E; 04771 } 04772 04773 /* put together IV OCTET STRING */ 04774 ivOctetStringSz = SetOctetString(blockSz, ivOctetString); 04775 04776 /* build up ContentEncryptionAlgorithmIdentifier sequence, 04777 adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ 04778 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 04779 oidBlkType, ivOctetStringSz + blockSz); 04780 if (contentEncAlgoSz == 0) { 04781 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04782 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04783 return BAD_FUNC_ARG; 04784 } 04785 04786 /* encrypt content */ 04787 ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockSz); 04788 if (ret != 0) { 04789 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04790 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04791 return ret; 04792 } 04793 04794 ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, 04795 pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz, 04796 encryptedContent); 04797 if (ret != 0) { 04798 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04799 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04800 return ret; 04801 } 04802 04803 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, 04804 encryptedOutSz, encContentOctet); 04805 04806 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 04807 ivOctetStringSz + blockSz + 04808 encContentOctetSz + encryptedOutSz, 04809 encContentSeq); 04810 04811 /* optional UnprotectedAttributes */ 04812 if (pkcs7->unprotectedAttribsSz != 0) { 04813 04814 if (pkcs7->unprotectedAttribs == NULL) { 04815 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04816 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04817 return BAD_FUNC_ARG; 04818 } 04819 04820 attribs = (EncodedAttrib*)XMALLOC( 04821 sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz, 04822 pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04823 if (attribs == NULL) { 04824 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04825 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04826 return MEMORY_E; 04827 } 04828 04829 attribsCount = pkcs7->unprotectedAttribsSz; 04830 attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz, 04831 pkcs7->unprotectedAttribs, 04832 pkcs7->unprotectedAttribsSz); 04833 04834 flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04835 if (flatAttribs == NULL) { 04836 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04837 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04838 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04839 return MEMORY_E; 04840 } 04841 04842 FlattenAttributes(flatAttribs, attribs, attribsCount); 04843 attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet); 04844 04845 } else { 04846 attribsSz = 0; 04847 attribsSetSz = 0; 04848 } 04849 04850 /* keep track of sizes for outer wrapper layering */ 04851 totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz + 04852 ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz + 04853 attribsSz + attribsSetSz;; 04854 04855 /* EncryptedData */ 04856 encDataSeqSz = SetSequence(totalSz, encDataSeq); 04857 totalSz += encDataSeqSz; 04858 04859 /* outer content */ 04860 outerContentSz = SetExplicit(0, totalSz, outerContent); 04861 totalSz += outerContentTypeSz; 04862 totalSz += outerContentSz; 04863 04864 /* ContentInfo */ 04865 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 04866 totalSz += contentInfoSeqSz; 04867 04868 if (totalSz > (int)outputSz) { 04869 WOLFSSL_MSG("PKCS#7 output buffer too small"); 04870 if (pkcs7->unprotectedAttribsSz != 0) { 04871 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04872 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04873 } 04874 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04875 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04876 return BUFFER_E; 04877 } 04878 04879 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 04880 idx += contentInfoSeqSz; 04881 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 04882 idx += outerContentTypeSz; 04883 XMEMCPY(output + idx, outerContent, outerContentSz); 04884 idx += outerContentSz; 04885 XMEMCPY(output + idx, encDataSeq, encDataSeqSz); 04886 idx += encDataSeqSz; 04887 XMEMCPY(output + idx, ver, verSz); 04888 idx += verSz; 04889 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 04890 idx += encContentSeqSz; 04891 XMEMCPY(output + idx, contentType, contentTypeSz); 04892 idx += contentTypeSz; 04893 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 04894 idx += contentEncAlgoSz; 04895 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 04896 idx += ivOctetStringSz; 04897 XMEMCPY(output + idx, tmpIv, blockSz); 04898 idx += blockSz; 04899 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 04900 idx += encContentOctetSz; 04901 XMEMCPY(output + idx, encryptedContent, encryptedOutSz); 04902 idx += encryptedOutSz; 04903 04904 if (pkcs7->unprotectedAttribsSz != 0) { 04905 XMEMCPY(output + idx, attribSet, attribsSetSz); 04906 idx += attribsSetSz; 04907 XMEMCPY(output + idx, flatAttribs, attribsSz); 04908 idx += attribsSz; 04909 XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04910 XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04911 } 04912 04913 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04914 XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 04915 04916 return idx; 04917 } 04918 04919 04920 /* decode and store unprotected attributes in PKCS7->decodedAttrib. Return 04921 * 0 on success, negative on error. User must call wc_PKCS7_Free(). */ 04922 static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, 04923 word32 pkiMsgSz, word32* inOutIdx) 04924 { 04925 int ret, attribLen; 04926 word32 idx; 04927 04928 if (pkcs7 == NULL || pkiMsg == NULL || 04929 pkiMsgSz == 0 || inOutIdx == NULL) 04930 return BAD_FUNC_ARG; 04931 04932 idx = *inOutIdx; 04933 04934 if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) 04935 return ASN_PARSE_E; 04936 idx++; 04937 04938 if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0) 04939 return ASN_PARSE_E; 04940 04941 /* loop through attributes */ 04942 if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) { 04943 return ret; 04944 } 04945 04946 *inOutIdx = idx; 04947 04948 return 0; 04949 } 04950 04951 04952 /* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */ 04953 int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, 04954 byte* output, word32 outputSz) 04955 { 04956 int ret, version, length, haveAttribs; 04957 word32 idx = 0; 04958 word32 contentType, encOID; 04959 04960 int expBlockSz; 04961 byte tmpIv[MAX_CONTENT_IV_SIZE]; 04962 04963 int encryptedContentSz; 04964 byte padLen; 04965 byte* encryptedContent = NULL; 04966 04967 if (pkcs7 == NULL || pkcs7->encryptionKey == NULL || 04968 pkcs7->encryptionKeySz == 0) 04969 return BAD_FUNC_ARG; 04970 04971 if (pkiMsg == NULL || pkiMsgSz == 0 || 04972 output == NULL || outputSz == 0) 04973 return BAD_FUNC_ARG; 04974 /* read past ContentInfo, verify type is encrypted-data */ 04975 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04976 return ASN_PARSE_E; 04977 04978 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 04979 return ASN_PARSE_E; 04980 04981 if (contentType != ENCRYPTED_DATA) { 04982 WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); 04983 return PKCS7_OID_E; 04984 } 04985 04986 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 04987 return ASN_PARSE_E; 04988 04989 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04990 return ASN_PARSE_E; 04991 04992 /* remove EncryptedData and version */ 04993 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 04994 return ASN_PARSE_E; 04995 04996 /* get version, check later */ 04997 haveAttribs = 0; 04998 if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) 04999 return ASN_PARSE_E; 05000 05001 /* remove EncryptedContentInfo */ 05002 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 05003 return ASN_PARSE_E; 05004 05005 if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 05006 return ASN_PARSE_E; 05007 05008 if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) 05009 return ASN_PARSE_E; 05010 05011 expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); 05012 if (expBlockSz < 0) 05013 return expBlockSz; 05014 05015 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 05016 if (pkiMsg[idx++] != ASN_OCTET_STRING) 05017 return ASN_PARSE_E; 05018 05019 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 05020 return ASN_PARSE_E; 05021 05022 if (length != expBlockSz) { 05023 WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); 05024 return ASN_PARSE_E; 05025 } 05026 05027 XMEMCPY(tmpIv, &pkiMsg[idx], length); 05028 idx += length; 05029 05030 /* read encryptedContent, cont[0] */ 05031 if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) 05032 return ASN_PARSE_E; 05033 05034 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) 05035 return ASN_PARSE_E; 05036 05037 encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, 05038 DYNAMIC_TYPE_PKCS7); 05039 if (encryptedContent == NULL) 05040 return MEMORY_E; 05041 05042 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 05043 idx += encryptedContentSz; 05044 05045 /* decrypt encryptedContent */ 05046 ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, 05047 pkcs7->encryptionKeySz, tmpIv, expBlockSz, 05048 encryptedContent, encryptedContentSz, 05049 encryptedContent); 05050 if (ret != 0) { 05051 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05052 return ret; 05053 } 05054 05055 padLen = encryptedContent[encryptedContentSz-1]; 05056 05057 /* copy plaintext to output */ 05058 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 05059 05060 /* get implicit[1] unprotected attributes, optional */ 05061 pkcs7->decodedAttrib = NULL; 05062 if (idx < pkiMsgSz) { 05063 05064 haveAttribs = 1; 05065 05066 ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, 05067 pkiMsgSz, &idx); 05068 if (ret != 0) { 05069 ForceZero(encryptedContent, encryptedContentSz); 05070 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05071 return ASN_PARSE_E; 05072 } 05073 } 05074 05075 /* go back and check the version now that attribs have been processed */ 05076 if ((haveAttribs == 0 && version != 0) || 05077 (haveAttribs == 1 && version != 2) ) { 05078 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05079 WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); 05080 return ASN_VERSION_E; 05081 } 05082 05083 ForceZero(encryptedContent, encryptedContentSz); 05084 XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 05085 05086 return encryptedContentSz - padLen; 05087 } 05088 05089 #endif /* NO_PKCS7_ENCRYPTED_DATA */ 05090 05091 #else /* HAVE_PKCS7 */ 05092 05093 05094 #ifdef _MSC_VER 05095 /* 4206 warning for blank file */ 05096 #pragma warning(disable: 4206) 05097 #endif 05098 05099 05100 #endif /* HAVE_PKCS7 */ 05101 05102
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2