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 CyaSSL by
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 Tue Jul 12 2022 21:40:05 by
1.7.2
