Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: HTTPClient-SSL HTTPClient HTTPClient-SSL http_access ... more
pkcs7.c
00001 /* pkcs7.c 00002 * 00003 * Copyright (C) 2006-2014 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL 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 * CyaSSL 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-1301, USA 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ctaocrypt/settings.h> 00027 00028 #ifdef HAVE_PKCS7 00029 00030 #include <cyassl/ctaocrypt/pkcs7.h> 00031 #include <cyassl/ctaocrypt/error-crypt.h> 00032 #include <cyassl/ctaocrypt/logging.h> 00033 00034 #ifndef min 00035 static INLINE word32 min(word32 a, word32 b) 00036 { 00037 return a > b ? b : a; 00038 } 00039 #endif 00040 00041 00042 /* placed ASN.1 contentType OID into *output, return idx on success, 00043 * 0 upon failure */ 00044 CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output) 00045 { 00046 /* PKCS#7 content types, RFC 2315, section 14 */ 00047 static const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00048 0x0D, 0x01, 0x07 }; 00049 static const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00050 0x0D, 0x01, 0x07, 0x01 }; 00051 static const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00052 0x0D, 0x01, 0x07, 0x02}; 00053 static const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00054 0x0D, 0x01, 0x07, 0x03 }; 00055 static const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00056 0x0D, 0x01, 0x07, 0x04 }; 00057 static const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00058 0x0D, 0x01, 0x07, 0x05 }; 00059 static const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 00060 0x0D, 0x01, 0x07, 0x06 }; 00061 00062 int idSz; 00063 int typeSz = 0, idx = 0; 00064 const byte* typeName = 0; 00065 byte ID_Length[MAX_LENGTH_SZ]; 00066 00067 switch (pkcs7TypeOID) { 00068 case PKCS7_MSG: 00069 typeSz = sizeof(pkcs7); 00070 typeName = pkcs7; 00071 break; 00072 00073 case DATA: 00074 typeSz = sizeof(data); 00075 typeName = data; 00076 break; 00077 00078 case SIGNED_DATA: 00079 typeSz = sizeof(signedData); 00080 typeName = signedData; 00081 break; 00082 00083 case ENVELOPED_DATA: 00084 typeSz = sizeof(envelopedData); 00085 typeName = envelopedData; 00086 break; 00087 00088 case SIGNED_AND_ENVELOPED_DATA: 00089 typeSz = sizeof(signedAndEnveloped); 00090 typeName = signedAndEnveloped; 00091 break; 00092 00093 case DIGESTED_DATA: 00094 typeSz = sizeof(digestedData); 00095 typeName = digestedData; 00096 break; 00097 00098 case ENCRYPTED_DATA: 00099 typeSz = sizeof(encryptedData); 00100 typeName = encryptedData; 00101 break; 00102 00103 default: 00104 CYASSL_MSG("Unknown PKCS#7 Type"); 00105 return 0; 00106 }; 00107 00108 idSz = SetLength(typeSz, ID_Length); 00109 output[idx++] = ASN_OBJECT_ID; 00110 XMEMCPY(output + idx, ID_Length, idSz); 00111 idx += idSz; 00112 XMEMCPY(output + idx, typeName, typeSz); 00113 idx += typeSz; 00114 00115 return idx; 00116 00117 } 00118 00119 00120 /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */ 00121 int GetContentType(const byte* input, word32* inOutIdx, word32* oid, 00122 word32 maxIdx) 00123 { 00124 int length; 00125 word32 i = *inOutIdx; 00126 byte b; 00127 *oid = 0; 00128 00129 CYASSL_ENTER("GetContentType"); 00130 00131 b = input[i++]; 00132 if (b != ASN_OBJECT_ID) 00133 return ASN_OBJECT_ID_E; 00134 00135 if (GetLength(input, &i, &length, maxIdx) < 0) 00136 return ASN_PARSE_E; 00137 00138 while(length--) { 00139 *oid += input[i]; 00140 i++; 00141 } 00142 00143 *inOutIdx = i; 00144 00145 return 0; 00146 } 00147 00148 00149 /* init PKCS7 struct with recipient cert, decode into DecodedCert */ 00150 int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) 00151 { 00152 int ret = 0; 00153 00154 XMEMSET(pkcs7, 0, sizeof(PKCS7)); 00155 if (cert != NULL && certSz > 0) { 00156 DecodedCert dCert; 00157 00158 pkcs7->singleCert = cert; 00159 pkcs7->singleCertSz = certSz; 00160 InitDecodedCert(&dCert, cert, certSz, 0); 00161 00162 ret = ParseCert(&dCert, CA_TYPE, NO_VERIFY, 0); 00163 if (ret < 0) { 00164 FreeDecodedCert(&dCert); 00165 return ret; 00166 } 00167 XMEMCPY(pkcs7->publicKey, dCert.publicKey, dCert.pubKeySize); 00168 pkcs7->publicKeySz = dCert.pubKeySize; 00169 XMEMCPY(pkcs7->issuerHash, dCert.issuerHash, SHA_SIZE); 00170 pkcs7->issuer = dCert.issuerRaw; 00171 pkcs7->issuerSz = dCert.issuerRawLen; 00172 XMEMCPY(pkcs7->issuerSn, dCert.serial, dCert.serialSz); 00173 pkcs7->issuerSnSz = dCert.serialSz; 00174 FreeDecodedCert(&dCert); 00175 } 00176 00177 return ret; 00178 } 00179 00180 00181 /* releases any memory allocated by a PKCS7 initializer */ 00182 void PKCS7_Free(PKCS7* pkcs7) 00183 { 00184 (void)pkcs7; 00185 } 00186 00187 00188 /* build PKCS#7 data content type */ 00189 int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz) 00190 { 00191 static const byte oid[] = 00192 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 00193 0x07, 0x01 }; 00194 byte seq[MAX_SEQ_SZ]; 00195 byte octetStr[MAX_OCTET_STR_SZ]; 00196 word32 seqSz; 00197 word32 octetStrSz; 00198 word32 oidSz = (word32)sizeof(oid); 00199 int idx = 0; 00200 00201 octetStrSz = SetOctetString(pkcs7->contentSz, octetStr); 00202 seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq); 00203 00204 if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz) 00205 return BUFFER_E; 00206 00207 XMEMCPY(output, seq, seqSz); 00208 idx += seqSz; 00209 XMEMCPY(output + idx, oid, oidSz); 00210 idx += oidSz; 00211 XMEMCPY(output + idx, octetStr, octetStrSz); 00212 idx += octetStrSz; 00213 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 00214 idx += pkcs7->contentSz; 00215 00216 return idx; 00217 } 00218 00219 00220 typedef struct EncodedAttrib { 00221 byte valueSeq[MAX_SEQ_SZ]; 00222 const byte* oid; 00223 byte valueSet[MAX_SET_SZ]; 00224 const byte* value; 00225 word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz; 00226 } EncodedAttrib; 00227 00228 00229 typedef struct ESD { 00230 Sha sha; 00231 byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ 00232 byte contentAttribsDigest[SHA_DIGEST_SIZE]; 00233 byte encContentDigest[512]; 00234 00235 byte outerSeq[MAX_SEQ_SZ]; 00236 byte outerContent[MAX_EXP_SZ]; 00237 byte innerSeq[MAX_SEQ_SZ]; 00238 byte version[MAX_VERSION_SZ]; 00239 byte digAlgoIdSet[MAX_SET_SZ]; 00240 byte singleDigAlgoId[MAX_ALGO_SZ]; 00241 00242 byte contentInfoSeq[MAX_SEQ_SZ]; 00243 byte innerContSeq[MAX_EXP_SZ]; 00244 byte innerOctets[MAX_OCTET_STR_SZ]; 00245 00246 byte certsSet[MAX_SET_SZ]; 00247 00248 byte signerInfoSet[MAX_SET_SZ]; 00249 byte signerInfoSeq[MAX_SEQ_SZ]; 00250 byte signerVersion[MAX_VERSION_SZ]; 00251 byte issuerSnSeq[MAX_SEQ_SZ]; 00252 byte issuerName[MAX_SEQ_SZ]; 00253 byte issuerSn[MAX_SN_SZ]; 00254 byte signerDigAlgoId[MAX_ALGO_SZ]; 00255 byte digEncAlgoId[MAX_ALGO_SZ]; 00256 byte signedAttribSet[MAX_SET_SZ]; 00257 EncodedAttrib signedAttribs[6]; 00258 byte signerDigest[MAX_OCTET_STR_SZ]; 00259 word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; 00260 word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, 00261 singleDigAlgoIdSz, certsSetSz; 00262 word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, 00263 issuerSnSeqSz, issuerNameSz, issuerSnSz, 00264 signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; 00265 word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, 00266 signedAttribSetSz; 00267 } ESD; 00268 00269 00270 static int EncodeAttributes(EncodedAttrib* ea, int eaSz, 00271 PKCS7Attrib* attribs, int attribsSz) 00272 { 00273 int i; 00274 int maxSz = min(eaSz, attribsSz); 00275 int allAttribsSz = 0; 00276 00277 for (i = 0; i < maxSz; i++) 00278 { 00279 int attribSz = 0; 00280 00281 ea[i].value = attribs[i].value; 00282 ea[i].valueSz = attribs[i].valueSz; 00283 attribSz += ea[i].valueSz; 00284 ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet); 00285 attribSz += ea[i].valueSetSz; 00286 ea[i].oid = attribs[i].oid; 00287 ea[i].oidSz = attribs[i].oidSz; 00288 attribSz += ea[i].oidSz; 00289 ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq); 00290 attribSz += ea[i].valueSeqSz; 00291 ea[i].totalSz = attribSz; 00292 00293 allAttribsSz += attribSz; 00294 } 00295 return allAttribsSz; 00296 } 00297 00298 00299 static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) 00300 { 00301 int i, idx; 00302 00303 idx = 0; 00304 for (i = 0; i < eaSz; i++) { 00305 XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz); 00306 idx += ea[i].valueSeqSz; 00307 XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz); 00308 idx += ea[i].oidSz; 00309 XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz); 00310 idx += ea[i].valueSetSz; 00311 XMEMCPY(output + idx, ea[i].value, ea[i].valueSz); 00312 idx += ea[i].valueSz; 00313 } 00314 return 0; 00315 } 00316 00317 00318 /* build PKCS#7 signedData content type */ 00319 int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) 00320 { 00321 static const byte outerOid[] = 00322 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 00323 0x07, 0x02 }; 00324 static const byte innerOid[] = 00325 { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 00326 0x07, 0x01 }; 00327 00328 ESD esd; 00329 word32 signerInfoSz = 0; 00330 word32 totalSz = 0; 00331 int idx = 0, ret = 0; 00332 byte* flatSignedAttribs = NULL; 00333 word32 flatSignedAttribsSz = 0; 00334 word32 innerOidSz = sizeof(innerOid); 00335 word32 outerOidSz = sizeof(outerOid); 00336 00337 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 00338 pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || 00339 pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || 00340 pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 || 00341 output == NULL || outputSz == 0) 00342 return BAD_FUNC_ARG; 00343 00344 XMEMSET(&esd, 0, sizeof(esd)); 00345 ret = InitSha(&esd.sha); 00346 if (ret != 0) 00347 return ret; 00348 00349 if (pkcs7->contentSz != 0) 00350 { 00351 ShaUpdate(&esd.sha, pkcs7->content, pkcs7->contentSz); 00352 esd.contentDigest[0] = ASN_OCTET_STRING; 00353 esd.contentDigest[1] = SHA_DIGEST_SIZE; 00354 ShaFinal(&esd.sha, &esd.contentDigest[2]); 00355 } 00356 00357 esd.innerOctetsSz = SetOctetString(pkcs7->contentSz, esd.innerOctets); 00358 esd.innerContSeqSz = SetExplicit(0, esd.innerOctetsSz + pkcs7->contentSz, 00359 esd.innerContSeq); 00360 esd.contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd.innerOctetsSz + 00361 innerOidSz + esd.innerContSeqSz, 00362 esd.contentInfoSeq); 00363 00364 esd.issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, 00365 esd.issuerSn); 00366 signerInfoSz += esd.issuerSnSz; 00367 esd.issuerNameSz = SetSequence(pkcs7->issuerSz, esd.issuerName); 00368 signerInfoSz += esd.issuerNameSz + pkcs7->issuerSz; 00369 esd.issuerSnSeqSz = SetSequence(signerInfoSz, esd.issuerSnSeq); 00370 signerInfoSz += esd.issuerSnSeqSz; 00371 esd.signerVersionSz = SetMyVersion(1, esd.signerVersion, 0); 00372 signerInfoSz += esd.signerVersionSz; 00373 esd.signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.signerDigAlgoId, 00374 hashType, 0); 00375 signerInfoSz += esd.signerDigAlgoIdSz; 00376 esd.digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd.digEncAlgoId, 00377 keyType, 0); 00378 signerInfoSz += esd.digEncAlgoIdSz; 00379 00380 if (pkcs7->signedAttribsSz != 0) { 00381 byte contentTypeOid[] = 00382 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 00383 0x09, 0x03 }; 00384 byte contentType[] = 00385 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 00386 0x07, 0x01 }; 00387 byte messageDigestOid[] = 00388 { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 00389 0x09, 0x04 }; 00390 00391 PKCS7Attrib cannedAttribs[2] = 00392 { 00393 { contentTypeOid, sizeof(contentTypeOid), 00394 contentType, sizeof(contentType) }, 00395 { messageDigestOid, sizeof(messageDigestOid), 00396 esd.contentDigest, sizeof(esd.contentDigest) } 00397 }; 00398 word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); 00399 00400 esd.signedAttribsCount += cannedAttribsCount; 00401 esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[0], 2, 00402 cannedAttribs, cannedAttribsCount); 00403 00404 esd.signedAttribsCount += pkcs7->signedAttribsSz; 00405 esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[2], 4, 00406 pkcs7->signedAttribs, pkcs7->signedAttribsSz); 00407 00408 flatSignedAttribs = (byte*)XMALLOC(esd.signedAttribsSz, 0, NULL); 00409 flatSignedAttribsSz = esd.signedAttribsSz; 00410 if (flatSignedAttribs == NULL) 00411 return MEMORY_E; 00412 FlattenAttributes(flatSignedAttribs, 00413 esd.signedAttribs, esd.signedAttribsCount); 00414 esd.signedAttribSetSz = SetImplicit(ASN_SET, 0, esd.signedAttribsSz, 00415 esd.signedAttribSet); 00416 } 00417 /* Calculate the final hash and encrypt it. */ 00418 { 00419 RsaKey privKey; 00420 int result; 00421 word32 scratch = 0; 00422 00423 byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + 00424 MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; 00425 byte digestInfoSeq[MAX_SEQ_SZ]; 00426 byte digestStr[MAX_OCTET_STR_SZ]; 00427 word32 digestInfoSeqSz, digestStrSz; 00428 int digIdx = 0; 00429 00430 if (pkcs7->signedAttribsSz != 0) { 00431 byte attribSet[MAX_SET_SZ]; 00432 word32 attribSetSz; 00433 00434 attribSetSz = SetSet(flatSignedAttribsSz, attribSet); 00435 00436 ret = InitSha(&esd.sha); 00437 if (ret < 0) { 00438 XFREE(flatSignedAttribs, 0, NULL); 00439 return ret; 00440 } 00441 ShaUpdate(&esd.sha, attribSet, attribSetSz); 00442 ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz); 00443 } 00444 ShaFinal(&esd.sha, esd.contentAttribsDigest); 00445 00446 digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); 00447 digestInfoSeqSz = SetSequence(esd.signerDigAlgoIdSz + 00448 digestStrSz + SHA_DIGEST_SIZE, 00449 digestInfoSeq); 00450 00451 XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); 00452 digIdx += digestInfoSeqSz; 00453 XMEMCPY(digestInfo + digIdx, 00454 esd.signerDigAlgoId, esd.signerDigAlgoIdSz); 00455 digIdx += esd.signerDigAlgoIdSz; 00456 XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); 00457 digIdx += digestStrSz; 00458 XMEMCPY(digestInfo + digIdx, esd.contentAttribsDigest, SHA_DIGEST_SIZE); 00459 digIdx += SHA_DIGEST_SIZE; 00460 00461 result = InitRsaKey(&privKey, NULL); 00462 if (result == 0) 00463 result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey, 00464 pkcs7->privateKeySz); 00465 if (result < 0) { 00466 XFREE(flatSignedAttribs, 0, NULL); 00467 return PUBLIC_KEY_E; 00468 } 00469 result = RsaSSL_Sign(digestInfo, digIdx, 00470 esd.encContentDigest, sizeof(esd.encContentDigest), 00471 &privKey, pkcs7->rng); 00472 FreeRsaKey(&privKey); 00473 if (result < 0) { 00474 XFREE(flatSignedAttribs, 0, NULL); 00475 return result; 00476 } 00477 esd.encContentDigestSz = (word32)result; 00478 } 00479 signerInfoSz += flatSignedAttribsSz + esd.signedAttribSetSz; 00480 00481 esd.signerDigestSz = SetOctetString(esd.encContentDigestSz, 00482 esd.signerDigest); 00483 signerInfoSz += esd.signerDigestSz + esd.encContentDigestSz; 00484 00485 esd.signerInfoSeqSz = SetSequence(signerInfoSz, esd.signerInfoSeq); 00486 signerInfoSz += esd.signerInfoSeqSz; 00487 esd.signerInfoSetSz = SetSet(signerInfoSz, esd.signerInfoSet); 00488 signerInfoSz += esd.signerInfoSetSz; 00489 00490 esd.certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, esd.certsSet); 00491 00492 esd.singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.singleDigAlgoId, 00493 hashType, 0); 00494 esd.digAlgoIdSetSz = SetSet(esd.singleDigAlgoIdSz, esd.digAlgoIdSet); 00495 00496 00497 esd.versionSz = SetMyVersion(1, esd.version, 0); 00498 00499 totalSz = esd.versionSz + esd.singleDigAlgoIdSz + esd.digAlgoIdSetSz + 00500 esd.contentInfoSeqSz + esd.certsSetSz + pkcs7->singleCertSz + 00501 esd.innerOctetsSz + esd.innerContSeqSz + 00502 innerOidSz + pkcs7->contentSz + 00503 signerInfoSz; 00504 esd.innerSeqSz = SetSequence(totalSz, esd.innerSeq); 00505 totalSz += esd.innerSeqSz; 00506 esd.outerContentSz = SetExplicit(0, totalSz, esd.outerContent); 00507 totalSz += esd.outerContentSz + outerOidSz; 00508 esd.outerSeqSz = SetSequence(totalSz, esd.outerSeq); 00509 totalSz += esd.outerSeqSz; 00510 00511 if (outputSz < totalSz) 00512 return BUFFER_E; 00513 00514 idx = 0; 00515 XMEMCPY(output + idx, esd.outerSeq, esd.outerSeqSz); 00516 idx += esd.outerSeqSz; 00517 XMEMCPY(output + idx, outerOid, outerOidSz); 00518 idx += outerOidSz; 00519 XMEMCPY(output + idx, esd.outerContent, esd.outerContentSz); 00520 idx += esd.outerContentSz; 00521 XMEMCPY(output + idx, esd.innerSeq, esd.innerSeqSz); 00522 idx += esd.innerSeqSz; 00523 XMEMCPY(output + idx, esd.version, esd.versionSz); 00524 idx += esd.versionSz; 00525 XMEMCPY(output + idx, esd.digAlgoIdSet, esd.digAlgoIdSetSz); 00526 idx += esd.digAlgoIdSetSz; 00527 XMEMCPY(output + idx, esd.singleDigAlgoId, esd.singleDigAlgoIdSz); 00528 idx += esd.singleDigAlgoIdSz; 00529 XMEMCPY(output + idx, esd.contentInfoSeq, esd.contentInfoSeqSz); 00530 idx += esd.contentInfoSeqSz; 00531 XMEMCPY(output + idx, innerOid, innerOidSz); 00532 idx += innerOidSz; 00533 XMEMCPY(output + idx, esd.innerContSeq, esd.innerContSeqSz); 00534 idx += esd.innerContSeqSz; 00535 XMEMCPY(output + idx, esd.innerOctets, esd.innerOctetsSz); 00536 idx += esd.innerOctetsSz; 00537 XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); 00538 idx += pkcs7->contentSz; 00539 XMEMCPY(output + idx, esd.certsSet, esd.certsSetSz); 00540 idx += esd.certsSetSz; 00541 XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); 00542 idx += pkcs7->singleCertSz; 00543 XMEMCPY(output + idx, esd.signerInfoSet, esd.signerInfoSetSz); 00544 idx += esd.signerInfoSetSz; 00545 XMEMCPY(output + idx, esd.signerInfoSeq, esd.signerInfoSeqSz); 00546 idx += esd.signerInfoSeqSz; 00547 XMEMCPY(output + idx, esd.signerVersion, esd.signerVersionSz); 00548 idx += esd.signerVersionSz; 00549 XMEMCPY(output + idx, esd.issuerSnSeq, esd.issuerSnSeqSz); 00550 idx += esd.issuerSnSeqSz; 00551 XMEMCPY(output + idx, esd.issuerName, esd.issuerNameSz); 00552 idx += esd.issuerNameSz; 00553 XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); 00554 idx += pkcs7->issuerSz; 00555 XMEMCPY(output + idx, esd.issuerSn, esd.issuerSnSz); 00556 idx += esd.issuerSnSz; 00557 XMEMCPY(output + idx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz); 00558 idx += esd.signerDigAlgoIdSz; 00559 00560 /* SignerInfo:Attributes */ 00561 if (pkcs7->signedAttribsSz != 0) { 00562 XMEMCPY(output + idx, esd.signedAttribSet, esd.signedAttribSetSz); 00563 idx += esd.signedAttribSetSz; 00564 XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); 00565 idx += flatSignedAttribsSz; 00566 XFREE(flatSignedAttribs, 0, NULL); 00567 } 00568 00569 XMEMCPY(output + idx, esd.digEncAlgoId, esd.digEncAlgoIdSz); 00570 idx += esd.digEncAlgoIdSz; 00571 XMEMCPY(output + idx, esd.signerDigest, esd.signerDigestSz); 00572 idx += esd.signerDigestSz; 00573 XMEMCPY(output + idx, esd.encContentDigest, esd.encContentDigestSz); 00574 idx += esd.encContentDigestSz; 00575 00576 return idx; 00577 } 00578 00579 00580 /* Finds the certificates in the message and saves it. */ 00581 int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) 00582 { 00583 word32 idx, contentType; 00584 int length, version, ret; 00585 byte* content = NULL; 00586 byte* sig = NULL; 00587 byte* cert = NULL; 00588 int contentSz = 0, sigSz = 0, certSz = 0; 00589 00590 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) 00591 return BAD_FUNC_ARG; 00592 00593 idx = 0; 00594 00595 /* Get the contentInfo sequence */ 00596 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00597 return ASN_PARSE_E; 00598 00599 /* Get the contentInfo contentType */ 00600 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 00601 return ASN_PARSE_E; 00602 00603 if (contentType != SIGNED_DATA) { 00604 CYASSL_MSG("PKCS#7 input not of type SignedData"); 00605 return PKCS7_OID_E; 00606 } 00607 00608 /* get the ContentInfo content */ 00609 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 00610 return ASN_PARSE_E; 00611 00612 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00613 return ASN_PARSE_E; 00614 00615 /* Get the signedData sequence */ 00616 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00617 return ASN_PARSE_E; 00618 00619 /* Get the version */ 00620 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 00621 return ASN_PARSE_E; 00622 00623 if (version != 1) { 00624 CYASSL_MSG("PKCS#7 signedData needs to be of version 1"); 00625 return ASN_VERSION_E; 00626 } 00627 00628 /* Get the set of DigestAlgorithmIdentifiers */ 00629 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00630 return ASN_PARSE_E; 00631 00632 /* Skip the set. */ 00633 idx += length; 00634 00635 /* Get the inner ContentInfo sequence */ 00636 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00637 return ASN_PARSE_E; 00638 00639 /* Get the inner ContentInfo contentType */ 00640 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 00641 return ASN_PARSE_E; 00642 00643 if (contentType != DATA) { 00644 CYASSL_MSG("PKCS#7 inner input not of type Data"); 00645 return PKCS7_OID_E; 00646 } 00647 00648 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 00649 return ASN_PARSE_E; 00650 00651 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00652 return ASN_PARSE_E; 00653 00654 if (pkiMsg[idx++] != ASN_OCTET_STRING) 00655 return ASN_PARSE_E; 00656 00657 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00658 return ASN_PARSE_E; 00659 00660 /* Save the inner data as the content. */ 00661 if (length > 0) { 00662 /* Local pointer for calculating hashes later */ 00663 pkcs7->content = content = &pkiMsg[idx]; 00664 pkcs7->contentSz = contentSz = length; 00665 idx += length; 00666 } 00667 00668 /* Get the implicit[0] set of certificates */ 00669 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 00670 idx++; 00671 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00672 return ASN_PARSE_E; 00673 00674 if (length > 0) { 00675 /* At this point, idx is at the first certificate in 00676 * a set of certificates. There may be more than one, 00677 * or none, or they may be a PKCS 6 extended 00678 * certificate. We want to save the first cert if it 00679 * is X.509. */ 00680 00681 word32 certIdx = idx; 00682 00683 if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 00684 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) 00685 return ASN_PARSE_E; 00686 00687 cert = &pkiMsg[idx]; 00688 certSz += (certIdx - idx); 00689 } 00690 PKCS7_InitWithCert(pkcs7, cert, certSz); 00691 } 00692 idx += length; 00693 } 00694 00695 /* Get the implicit[1] set of crls */ 00696 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 00697 idx++; 00698 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00699 return ASN_PARSE_E; 00700 00701 /* Skip the set */ 00702 idx += length; 00703 } 00704 00705 /* Get the set of signerInfos */ 00706 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00707 return ASN_PARSE_E; 00708 00709 if (length > 0) { 00710 RsaKey key; 00711 word32 scratch = 0; 00712 int plainSz = 0; 00713 byte digest[MAX_SEQ_SZ+MAX_ALGO_SZ+MAX_OCTET_STR_SZ+SHA_DIGEST_SIZE]; 00714 00715 /* Get the sequence of the first signerInfo */ 00716 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00717 return ASN_PARSE_E; 00718 00719 /* Get the version */ 00720 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 00721 return ASN_PARSE_E; 00722 00723 if (version != 1) { 00724 CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1"); 00725 return ASN_VERSION_E; 00726 } 00727 00728 /* Get the sequence of IssuerAndSerialNumber */ 00729 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00730 return ASN_PARSE_E; 00731 00732 /* Skip it */ 00733 idx += length; 00734 00735 /* Get the sequence of digestAlgorithm */ 00736 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00737 return ASN_PARSE_E; 00738 00739 /* Skip it */ 00740 idx += length; 00741 00742 /* Get the IMPLICIT[0] SET OF signedAttributes */ 00743 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 00744 idx++; 00745 00746 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00747 return ASN_PARSE_E; 00748 00749 idx += length; 00750 } 00751 00752 /* Get the sequence of digestEncryptionAlgorithm */ 00753 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00754 return ASN_PARSE_E; 00755 00756 /* Skip it */ 00757 idx += length; 00758 00759 /* Get the signature */ 00760 if (pkiMsg[idx] == ASN_OCTET_STRING) { 00761 idx++; 00762 00763 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00764 return ASN_PARSE_E; 00765 00766 /* save pointer and length */ 00767 sig = &pkiMsg[idx]; 00768 sigSz = length; 00769 00770 idx += length; 00771 } 00772 00773 XMEMSET(digest, 0, sizeof(digest)); 00774 pkcs7->content = content; 00775 pkcs7->contentSz = contentSz; 00776 00777 ret = InitRsaKey(&key, NULL); 00778 if (ret != 0) return ret; 00779 if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &key, 00780 pkcs7->publicKeySz) < 0) { 00781 CYASSL_MSG("ASN RSA key decode error"); 00782 return PUBLIC_KEY_E; 00783 } 00784 plainSz = RsaSSL_Verify(sig, sigSz, digest, sizeof(digest), &key); 00785 FreeRsaKey(&key); 00786 if (plainSz < 0) 00787 return plainSz; 00788 } 00789 00790 return 0; 00791 } 00792 00793 00794 /* create ASN.1 fomatted RecipientInfo structure, returns sequence size */ 00795 CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz, 00796 int keyEncAlgo, int blockKeySz, 00797 RNG* rng, byte* contentKeyPlain, 00798 byte* contentKeyEnc, 00799 int* keyEncSz, byte* out, word32 outSz) 00800 { 00801 word32 idx = 0; 00802 int ret = 0, totalSz = 0; 00803 int verSz, issuerSz, snSz, keyEncAlgSz; 00804 int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; 00805 int encKeyOctetStrSz; 00806 00807 byte ver[MAX_VERSION_SZ]; 00808 byte serial[MAX_SN_SZ]; 00809 byte issuerSerialSeq[MAX_SEQ_SZ]; 00810 byte recipSeq[MAX_SEQ_SZ]; 00811 byte issuerSeq[MAX_SEQ_SZ]; 00812 byte keyAlgArray[MAX_ALGO_SZ]; 00813 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 00814 00815 RsaKey pubKey; 00816 DecodedCert decoded; 00817 00818 InitDecodedCert(&decoded, (byte*)cert, certSz, 0); 00819 ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0); 00820 if (ret < 0) { 00821 FreeDecodedCert(&decoded); 00822 return ret; 00823 } 00824 00825 /* version */ 00826 verSz = SetMyVersion(0, ver, 0); 00827 00828 /* IssuerAndSerialNumber */ 00829 if (decoded.issuerRaw == NULL || decoded.issuerRawLen == 0) { 00830 CYASSL_MSG("DecodedCert lacks raw issuer pointer and length"); 00831 FreeDecodedCert(&decoded); 00832 return -1; 00833 } 00834 issuerSz = decoded.issuerRawLen; 00835 issuerSeqSz = SetSequence(issuerSz, issuerSeq); 00836 00837 if (decoded.serial == NULL || decoded.serialSz == 0) { 00838 CYASSL_MSG("DecodedCert missing serial number"); 00839 FreeDecodedCert(&decoded); 00840 return -1; 00841 } 00842 snSz = SetSerialNumber(decoded.serial, decoded.serialSz, serial); 00843 00844 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, 00845 issuerSerialSeq); 00846 00847 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ 00848 if (keyEncAlgo != RSAk) 00849 return ALGO_ID_E; 00850 00851 keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0); 00852 if (keyEncAlgSz == 0) 00853 return BAD_FUNC_ARG; 00854 00855 /* EncryptedKey */ 00856 ret = InitRsaKey(&pubKey, 0); 00857 if (ret != 0) return ret; 00858 if (RsaPublicKeyDecode(decoded.publicKey, &idx, &pubKey, 00859 decoded.pubKeySize) < 0) { 00860 CYASSL_MSG("ASN RSA key decode error"); 00861 return PUBLIC_KEY_E; 00862 } 00863 00864 *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc, 00865 MAX_ENCRYPTED_KEY_SZ, &pubKey, rng); 00866 FreeRsaKey(&pubKey); 00867 if (*keyEncSz < 0) { 00868 CYASSL_MSG("RSA Public Encrypt failed"); 00869 return *keyEncSz; 00870 } 00871 00872 encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr); 00873 00874 /* RecipientInfo */ 00875 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + 00876 issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + 00877 *keyEncSz, recipSeq); 00878 00879 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + 00880 keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) { 00881 CYASSL_MSG("RecipientInfo output buffer too small"); 00882 return BUFFER_E; 00883 } 00884 00885 XMEMCPY(out + totalSz, recipSeq, recipSeqSz); 00886 totalSz += recipSeqSz; 00887 XMEMCPY(out + totalSz, ver, verSz); 00888 totalSz += verSz; 00889 XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz); 00890 totalSz += issuerSerialSeqSz; 00891 XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz); 00892 totalSz += issuerSeqSz; 00893 XMEMCPY(out + totalSz, decoded.issuerRaw, issuerSz); 00894 totalSz += issuerSz; 00895 XMEMCPY(out + totalSz, serial, snSz); 00896 totalSz += snSz; 00897 XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz); 00898 totalSz += keyEncAlgSz; 00899 XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz); 00900 totalSz += encKeyOctetStrSz; 00901 XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz); 00902 totalSz += *keyEncSz; 00903 00904 FreeDecodedCert(&decoded); 00905 00906 return totalSz; 00907 } 00908 00909 00910 /* build PKCS#7 envelopedData content type, return enveloped size */ 00911 int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) 00912 { 00913 int i, ret = 0, idx = 0; 00914 int totalSz = 0, padSz = 0, desOutSz = 0; 00915 00916 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 00917 byte contentInfoSeq[MAX_SEQ_SZ]; 00918 byte outerContentType[MAX_ALGO_SZ]; 00919 byte outerContent[MAX_SEQ_SZ]; 00920 00921 int envDataSeqSz, verSz; 00922 byte envDataSeq[MAX_SEQ_SZ]; 00923 byte ver[MAX_VERSION_SZ]; 00924 00925 RNG rng; 00926 int contentKeyEncSz, blockKeySz; 00927 int dynamicFlag = 0; 00928 byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; 00929 byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; 00930 byte* plain; 00931 byte* encryptedContent; 00932 00933 int recipSz, recipSetSz; 00934 byte recip[MAX_RECIP_SZ]; 00935 byte recipSet[MAX_SET_SZ]; 00936 00937 int encContentOctetSz, encContentSeqSz, contentTypeSz; 00938 int contentEncAlgoSz, ivOctetStringSz; 00939 byte encContentSeq[MAX_SEQ_SZ]; 00940 byte contentType[MAX_ALGO_SZ]; 00941 byte contentEncAlgo[MAX_ALGO_SZ]; 00942 byte tmpIv[DES_BLOCK_SIZE]; 00943 byte ivOctetString[MAX_OCTET_STR_SZ]; 00944 byte encContentOctet[MAX_OCTET_STR_SZ]; 00945 00946 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 00947 pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL) 00948 return BAD_FUNC_ARG; 00949 00950 if (output == NULL || outputSz == 0) 00951 return BAD_FUNC_ARG; 00952 00953 /* PKCS#7 only supports DES, 3DES for now */ 00954 switch (pkcs7->encryptOID) { 00955 case DESb: 00956 blockKeySz = DES_KEYLEN; 00957 break; 00958 00959 case DES3b: 00960 blockKeySz = DES3_KEYLEN; 00961 break; 00962 00963 default: 00964 CYASSL_MSG("Unsupported content cipher type"); 00965 return ALGO_ID_E; 00966 }; 00967 00968 /* outer content type */ 00969 outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType); 00970 00971 /* version, defined as 0 in RFC 2315 */ 00972 verSz = SetMyVersion(0, ver, 0); 00973 00974 /* generate random content encryption key */ 00975 ret = InitRng(&rng); 00976 if (ret != 0) 00977 return ret; 00978 00979 ret = RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); 00980 if (ret != 0) 00981 return ret; 00982 00983 /* build RecipientInfo, only handle 1 for now */ 00984 recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk, 00985 blockKeySz, &rng, contentKeyPlain, 00986 contentKeyEnc, &contentKeyEncSz, recip, 00987 MAX_RECIP_SZ); 00988 00989 if (recipSz < 0) { 00990 CYASSL_MSG("Failed to create RecipientInfo"); 00991 return recipSz; 00992 } 00993 recipSetSz = SetSet(recipSz, recipSet); 00994 00995 /* generate IV for block cipher */ 00996 ret = RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE); 00997 if (ret != 0) 00998 return ret; 00999 01000 /* EncryptedContentInfo */ 01001 contentTypeSz = SetContentType(pkcs7->contentOID, contentType); 01002 if (contentTypeSz == 0) 01003 return BAD_FUNC_ARG; 01004 01005 /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */ 01006 padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE); 01007 desOutSz = pkcs7->contentSz + padSz; 01008 01009 if (padSz != 0) { 01010 plain = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01011 if (plain == NULL) { 01012 return MEMORY_E; 01013 } 01014 XMEMCPY(plain, pkcs7->content, pkcs7->contentSz); 01015 dynamicFlag = 1; 01016 01017 for (i = 0; i < padSz; i++) { 01018 plain[pkcs7->contentSz + i] = padSz; 01019 } 01020 01021 } else { 01022 plain = pkcs7->content; 01023 desOutSz = pkcs7->contentSz; 01024 } 01025 01026 encryptedContent = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01027 if (encryptedContent == NULL) { 01028 if (dynamicFlag) 01029 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01030 return MEMORY_E; 01031 } 01032 01033 /* put together IV OCTET STRING */ 01034 ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString); 01035 01036 /* build up our ContentEncryptionAlgorithmIdentifier sequence, 01037 * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */ 01038 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 01039 blkType, ivOctetStringSz + DES_BLOCK_SIZE); 01040 if (contentEncAlgoSz == 0) 01041 return BAD_FUNC_ARG; 01042 01043 /* encrypt content */ 01044 if (pkcs7->encryptOID == DESb) { 01045 Des des; 01046 01047 ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION); 01048 01049 if (ret == 0) 01050 Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz); 01051 01052 if (ret != 0) { 01053 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01054 if (dynamicFlag) 01055 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01056 return ret; 01057 } 01058 } 01059 else if (pkcs7->encryptOID == DES3b) { 01060 Des3 des3; 01061 01062 ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION); 01063 01064 if (ret == 0) 01065 ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz); 01066 01067 if (ret != 0) { 01068 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01069 if (dynamicFlag) 01070 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01071 return ret; 01072 } 01073 } 01074 01075 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, 01076 desOutSz, encContentOctet); 01077 01078 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 01079 ivOctetStringSz + DES_BLOCK_SIZE + 01080 encContentOctetSz + desOutSz, encContentSeq); 01081 01082 /* keep track of sizes for outer wrapper layering */ 01083 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + 01084 contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + 01085 encContentOctetSz + desOutSz; 01086 01087 /* EnvelopedData */ 01088 envDataSeqSz = SetSequence(totalSz, envDataSeq); 01089 totalSz += envDataSeqSz; 01090 01091 /* outer content */ 01092 outerContentSz = SetExplicit(0, totalSz, outerContent); 01093 totalSz += outerContentTypeSz; 01094 totalSz += outerContentSz; 01095 01096 /* ContentInfo */ 01097 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 01098 totalSz += contentInfoSeqSz; 01099 01100 if (totalSz > (int)outputSz) { 01101 CYASSL_MSG("Pkcs7_encrypt output buffer too small"); 01102 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01103 if (dynamicFlag) 01104 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01105 return BUFFER_E; 01106 } 01107 01108 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 01109 idx += contentInfoSeqSz; 01110 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 01111 idx += outerContentTypeSz; 01112 XMEMCPY(output + idx, outerContent, outerContentSz); 01113 idx += outerContentSz; 01114 XMEMCPY(output + idx, envDataSeq, envDataSeqSz); 01115 idx += envDataSeqSz; 01116 XMEMCPY(output + idx, ver, verSz); 01117 idx += verSz; 01118 XMEMCPY(output + idx, recipSet, recipSetSz); 01119 idx += recipSetSz; 01120 XMEMCPY(output + idx, recip, recipSz); 01121 idx += recipSz; 01122 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 01123 idx += encContentSeqSz; 01124 XMEMCPY(output + idx, contentType, contentTypeSz); 01125 idx += contentTypeSz; 01126 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 01127 idx += contentEncAlgoSz; 01128 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 01129 idx += ivOctetStringSz; 01130 XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE); 01131 idx += DES_BLOCK_SIZE; 01132 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 01133 idx += encContentOctetSz; 01134 XMEMCPY(output + idx, encryptedContent, desOutSz); 01135 idx += desOutSz; 01136 01137 #ifdef NO_RC4 01138 FreeRng(&rng); 01139 #endif 01140 01141 XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN); 01142 XMEMSET(contentKeyEnc, 0, MAX_ENCRYPTED_KEY_SZ); 01143 01144 if (dynamicFlag) 01145 XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER); 01146 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01147 01148 return idx; 01149 } 01150 01151 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ 01152 CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, 01153 word32 pkiMsgSz, byte* output, 01154 word32 outputSz) 01155 { 01156 int recipFound = 0; 01157 int ret, version, length; 01158 word32 savedIdx = 0, idx = 0; 01159 word32 contentType, encOID; 01160 byte issuerHash[SHA_DIGEST_SIZE]; 01161 mp_int serialNum; 01162 01163 int encryptedKeySz, keySz; 01164 byte tmpIv[DES_BLOCK_SIZE]; 01165 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 01166 byte* decryptedKey = NULL; 01167 01168 RsaKey privKey; 01169 int encryptedContentSz; 01170 byte padLen; 01171 byte* encryptedContent = NULL; 01172 01173 if (pkcs7 == NULL || pkcs7->singleCert == NULL || 01174 pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || 01175 pkcs7->privateKeySz == 0) 01176 return BAD_FUNC_ARG; 01177 01178 if (pkiMsg == NULL || pkiMsgSz == 0 || 01179 output == NULL || outputSz == 0) 01180 return BAD_FUNC_ARG; 01181 01182 /* load private key */ 01183 ret = InitRsaKey(&privKey, 0); 01184 if (ret != 0) return ret; 01185 ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey, 01186 pkcs7->privateKeySz); 01187 if (ret != 0) { 01188 CYASSL_MSG("Failed to decode RSA private key"); 01189 return ret; 01190 } 01191 01192 idx = 0; 01193 01194 /* read past ContentInfo, verify type is envelopedData */ 01195 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01196 return ASN_PARSE_E; 01197 01198 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01199 return ASN_PARSE_E; 01200 01201 if (contentType != ENVELOPED_DATA) { 01202 CYASSL_MSG("PKCS#7 input not of type EnvelopedData"); 01203 return PKCS7_OID_E; 01204 } 01205 01206 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 01207 return ASN_PARSE_E; 01208 01209 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01210 return ASN_PARSE_E; 01211 01212 /* remove EnvelopedData and version */ 01213 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01214 return ASN_PARSE_E; 01215 01216 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 01217 return ASN_PARSE_E; 01218 01219 if (version != 0) { 01220 CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0"); 01221 return ASN_VERSION_E; 01222 } 01223 01224 /* walk through RecipientInfo set, find correct recipient */ 01225 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01226 return ASN_PARSE_E; 01227 01228 savedIdx = idx; 01229 recipFound = 0; 01230 01231 /* when looking for next recipient, use first sequence and version to 01232 * indicate there is another, if not, move on */ 01233 while(recipFound == 0) { 01234 01235 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to 01236 * last good saved one */ 01237 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 01238 idx = savedIdx; 01239 break; 01240 } 01241 01242 if (GetMyVersion(pkiMsg, &idx, &version) < 0) { 01243 idx = savedIdx; 01244 break; 01245 } 01246 01247 if (version != 0) 01248 return ASN_VERSION_E; 01249 01250 /* remove IssuerAndSerialNumber */ 01251 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01252 return ASN_PARSE_E; 01253 01254 if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) 01255 return ASN_PARSE_E; 01256 01257 /* if we found correct recipient, issuer hashes will match */ 01258 if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { 01259 recipFound = 1; 01260 } 01261 01262 if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0) 01263 return ASN_PARSE_E; 01264 mp_clear(&serialNum); 01265 01266 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) 01267 return ASN_PARSE_E; 01268 01269 /* key encryption algorithm must be RSA for now */ 01270 if (encOID != RSAk) 01271 return ALGO_ID_E; 01272 01273 /* read encryptedKey */ 01274 if (pkiMsg[idx++] != ASN_OCTET_STRING) 01275 return ASN_PARSE_E; 01276 01277 if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) 01278 return ASN_PARSE_E; 01279 01280 if (recipFound == 1) 01281 XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz); 01282 idx += encryptedKeySz; 01283 01284 /* update good idx */ 01285 savedIdx = idx; 01286 } 01287 01288 if (recipFound == 0) { 01289 CYASSL_MSG("No recipient found in envelopedData that matches input"); 01290 return PKCS7_RECIP_E; 01291 } 01292 01293 /* remove EncryptedContentInfo */ 01294 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01295 return ASN_PARSE_E; 01296 01297 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01298 return ASN_PARSE_E; 01299 01300 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) 01301 return ASN_PARSE_E; 01302 01303 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 01304 if (pkiMsg[idx++] != ASN_OCTET_STRING) 01305 return ASN_PARSE_E; 01306 01307 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01308 return ASN_PARSE_E; 01309 01310 if (length != DES_BLOCK_SIZE) { 01311 CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE"); 01312 return ASN_PARSE_E; 01313 } 01314 01315 XMEMCPY(tmpIv, &pkiMsg[idx], length); 01316 idx += length; 01317 01318 /* read encryptedContent, cont[0] */ 01319 if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) 01320 return ASN_PARSE_E; 01321 01322 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) 01323 return ASN_PARSE_E; 01324 01325 encryptedContent = XMALLOC(encryptedContentSz, NULL, 01326 DYNAMIC_TYPE_TMP_BUFFER); 01327 01328 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 01329 01330 /* decrypt encryptedKey */ 01331 keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, 01332 &decryptedKey, &privKey); 01333 FreeRsaKey(&privKey); 01334 if (keySz <= 0) 01335 return keySz; 01336 01337 /* decrypt encryptedContent */ 01338 if (encOID == DESb) { 01339 Des des; 01340 ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); 01341 01342 if (ret == 0) 01343 Des_CbcDecrypt(&des, encryptedContent, encryptedContent, 01344 encryptedContentSz); 01345 01346 if (ret != 0) { 01347 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01348 return ret; 01349 } 01350 } 01351 else if (encOID == DES3b) { 01352 Des3 des; 01353 ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); 01354 if (ret == 0) 01355 ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent, 01356 encryptedContentSz); 01357 01358 if (ret != 0) { 01359 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01360 return ret; 01361 } 01362 } else { 01363 CYASSL_MSG("Unsupported content encryption OID type"); 01364 return ALGO_ID_E; 01365 } 01366 01367 padLen = encryptedContent[encryptedContentSz-1]; 01368 01369 /* copy plaintext to output */ 01370 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 01371 01372 /* free memory, zero out keys */ 01373 XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ); 01374 XMEMSET(encryptedContent, 0, encryptedContentSz); 01375 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01376 01377 return encryptedContentSz - padLen; 01378 } 01379 01380 01381 #else /* HAVE_PKCS7 */ 01382 01383 01384 #ifdef _MSC_VER 01385 /* 4206 warning for blank file */ 01386 #pragma warning(disable: 4206) 01387 #endif 01388 01389 01390 #endif /* HAVE_PKCS7 */ 01391 01392
Generated on Wed Jul 13 2022 02:18:39 by
 1.7.2
 1.7.2