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