Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pkcs7.c
00001 /* pkcs7.c 00002 * 00003 * Copyright (C) 2006-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 byte* signedAttr = NULL; 00589 int contentSz = 0, sigSz = 0, certSz = 0, signedAttrSz = 0; 00590 00591 (void)signedAttr; /* not used yet, just set */ 00592 (void)signedAttrSz; 00593 00594 if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) 00595 return BAD_FUNC_ARG; 00596 00597 idx = 0; 00598 00599 /* Get the contentInfo sequence */ 00600 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00601 return ASN_PARSE_E; 00602 00603 /* Get the contentInfo contentType */ 00604 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 00605 return ASN_PARSE_E; 00606 00607 if (contentType != SIGNED_DATA) { 00608 CYASSL_MSG("PKCS#7 input not of type SignedData"); 00609 return PKCS7_OID_E; 00610 } 00611 00612 /* get the ContentInfo content */ 00613 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 00614 return ASN_PARSE_E; 00615 00616 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00617 return ASN_PARSE_E; 00618 00619 /* Get the signedData sequence */ 00620 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00621 return ASN_PARSE_E; 00622 00623 /* Get the version */ 00624 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 00625 return ASN_PARSE_E; 00626 00627 if (version != 1) { 00628 CYASSL_MSG("PKCS#7 signedData needs to be of version 1"); 00629 return ASN_VERSION_E; 00630 } 00631 00632 /* Get the set of DigestAlgorithmIdentifiers */ 00633 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00634 return ASN_PARSE_E; 00635 00636 /* Skip the set. */ 00637 idx += length; 00638 00639 /* Get the inner ContentInfo sequence */ 00640 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00641 return ASN_PARSE_E; 00642 00643 /* Get the inner ContentInfo contentType */ 00644 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 00645 return ASN_PARSE_E; 00646 00647 if (contentType != DATA) { 00648 CYASSL_MSG("PKCS#7 inner input not of type Data"); 00649 return PKCS7_OID_E; 00650 } 00651 00652 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 00653 return ASN_PARSE_E; 00654 00655 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00656 return ASN_PARSE_E; 00657 00658 if (pkiMsg[idx++] != ASN_OCTET_STRING) 00659 return ASN_PARSE_E; 00660 00661 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00662 return ASN_PARSE_E; 00663 00664 /* Save the inner data as the content. */ 00665 if (length > 0) { 00666 /* Local pointer for calculating hashes later */ 00667 pkcs7->content = content = &pkiMsg[idx]; 00668 pkcs7->contentSz = contentSz = length; 00669 idx += length; 00670 } 00671 00672 /* Get the implicit[0] set of certificates */ 00673 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 00674 idx++; 00675 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00676 return ASN_PARSE_E; 00677 00678 if (length > 0) { 00679 /* At this point, idx is at the first certificate in 00680 * a set of certificates. There may be more than one, 00681 * or none, or they may be a PKCS 6 extended 00682 * certificate. We want to save the first cert if it 00683 * is X.509. */ 00684 00685 word32 certIdx = idx; 00686 00687 if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { 00688 if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) 00689 return ASN_PARSE_E; 00690 00691 cert = &pkiMsg[idx]; 00692 certSz += (certIdx - idx); 00693 } 00694 PKCS7_InitWithCert(pkcs7, cert, certSz); 00695 } 00696 idx += length; 00697 } 00698 00699 /* Get the implicit[1] set of crls */ 00700 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { 00701 idx++; 00702 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00703 return ASN_PARSE_E; 00704 00705 /* Skip the set */ 00706 idx += length; 00707 } 00708 00709 /* Get the set of signerInfos */ 00710 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00711 return ASN_PARSE_E; 00712 00713 if (length > 0) { 00714 RsaKey key; 00715 word32 scratch = 0; 00716 int plainSz = 0; 00717 byte digest[MAX_SEQ_SZ+MAX_ALGO_SZ+MAX_OCTET_STR_SZ+SHA_DIGEST_SIZE]; 00718 00719 /* Get the sequence of the first signerInfo */ 00720 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00721 return ASN_PARSE_E; 00722 00723 /* Get the version */ 00724 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 00725 return ASN_PARSE_E; 00726 00727 if (version != 1) { 00728 CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1"); 00729 return ASN_VERSION_E; 00730 } 00731 00732 /* Get the sequence of IssuerAndSerialNumber */ 00733 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00734 return ASN_PARSE_E; 00735 00736 /* Skip it */ 00737 idx += length; 00738 00739 /* Get the sequence of digestAlgorithm */ 00740 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00741 return ASN_PARSE_E; 00742 00743 /* Skip it */ 00744 idx += length; 00745 00746 /* Get the IMPLICIT[0] SET OF signedAttributes */ 00747 if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { 00748 idx++; 00749 00750 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00751 return ASN_PARSE_E; 00752 00753 /* save pointer and length */ 00754 signedAttr = &pkiMsg[idx]; 00755 signedAttrSz = length; 00756 00757 idx += length; 00758 } 00759 00760 /* Get the sequence of digestEncryptionAlgorithm */ 00761 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00762 return ASN_PARSE_E; 00763 00764 /* Skip it */ 00765 idx += length; 00766 00767 /* Get the signature */ 00768 if (pkiMsg[idx] == ASN_OCTET_STRING) { 00769 idx++; 00770 00771 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 00772 return ASN_PARSE_E; 00773 00774 /* save pointer and length */ 00775 sig = &pkiMsg[idx]; 00776 sigSz = length; 00777 00778 idx += length; 00779 } 00780 00781 XMEMSET(digest, 0, sizeof(digest)); 00782 pkcs7->content = content; 00783 pkcs7->contentSz = contentSz; 00784 00785 ret = InitRsaKey(&key, NULL); 00786 if (ret != 0) return ret; 00787 if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &key, 00788 pkcs7->publicKeySz) < 0) { 00789 CYASSL_MSG("ASN RSA key decode error"); 00790 return PUBLIC_KEY_E; 00791 } 00792 plainSz = RsaSSL_Verify(sig, sigSz, digest, sizeof(digest), &key); 00793 FreeRsaKey(&key); 00794 if (plainSz < 0) 00795 return plainSz; 00796 } 00797 00798 return 0; 00799 } 00800 00801 00802 /* create ASN.1 fomatted RecipientInfo structure, returns sequence size */ 00803 CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz, 00804 int keyEncAlgo, int blockKeySz, 00805 RNG* rng, byte* contentKeyPlain, 00806 byte* contentKeyEnc, 00807 int* keyEncSz, byte* out, word32 outSz) 00808 { 00809 word32 idx = 0; 00810 int ret = 0, totalSz = 0; 00811 int verSz, issuerSz, snSz, keyEncAlgSz; 00812 int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; 00813 int encKeyOctetStrSz; 00814 00815 byte ver[MAX_VERSION_SZ]; 00816 byte serial[MAX_SN_SZ]; 00817 byte issuerSerialSeq[MAX_SEQ_SZ]; 00818 byte recipSeq[MAX_SEQ_SZ]; 00819 byte issuerSeq[MAX_SEQ_SZ]; 00820 byte keyAlgArray[MAX_ALGO_SZ]; 00821 byte encKeyOctetStr[MAX_OCTET_STR_SZ]; 00822 00823 RsaKey pubKey; 00824 DecodedCert decoded; 00825 00826 InitDecodedCert(&decoded, (byte*)cert, certSz, 0); 00827 ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0); 00828 if (ret < 0) { 00829 FreeDecodedCert(&decoded); 00830 return ret; 00831 } 00832 00833 /* version */ 00834 verSz = SetMyVersion(0, ver, 0); 00835 00836 /* IssuerAndSerialNumber */ 00837 if (decoded.issuerRaw == NULL || decoded.issuerRawLen == 0) { 00838 CYASSL_MSG("DecodedCert lacks raw issuer pointer and length"); 00839 FreeDecodedCert(&decoded); 00840 return -1; 00841 } 00842 issuerSz = decoded.issuerRawLen; 00843 issuerSeqSz = SetSequence(issuerSz, issuerSeq); 00844 00845 if (decoded.serial == NULL || decoded.serialSz == 0) { 00846 CYASSL_MSG("DecodedCert missing serial number"); 00847 FreeDecodedCert(&decoded); 00848 return -1; 00849 } 00850 snSz = SetSerialNumber(decoded.serial, decoded.serialSz, serial); 00851 00852 issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, 00853 issuerSerialSeq); 00854 00855 /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ 00856 if (keyEncAlgo != RSAk) 00857 return ALGO_ID_E; 00858 00859 keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0); 00860 if (keyEncAlgSz == 0) 00861 return BAD_FUNC_ARG; 00862 00863 /* EncryptedKey */ 00864 ret = InitRsaKey(&pubKey, 0); 00865 if (ret != 0) return ret; 00866 if (RsaPublicKeyDecode(decoded.publicKey, &idx, &pubKey, 00867 decoded.pubKeySize) < 0) { 00868 CYASSL_MSG("ASN RSA key decode error"); 00869 return PUBLIC_KEY_E; 00870 } 00871 00872 *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc, 00873 MAX_ENCRYPTED_KEY_SZ, &pubKey, rng); 00874 FreeRsaKey(&pubKey); 00875 if (*keyEncSz < 0) { 00876 CYASSL_MSG("RSA Public Encrypt failed"); 00877 return *keyEncSz; 00878 } 00879 00880 encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr); 00881 00882 /* RecipientInfo */ 00883 recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + 00884 issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + 00885 *keyEncSz, recipSeq); 00886 00887 if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + 00888 keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) { 00889 CYASSL_MSG("RecipientInfo output buffer too small"); 00890 return BUFFER_E; 00891 } 00892 00893 XMEMCPY(out + totalSz, recipSeq, recipSeqSz); 00894 totalSz += recipSeqSz; 00895 XMEMCPY(out + totalSz, ver, verSz); 00896 totalSz += verSz; 00897 XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz); 00898 totalSz += issuerSerialSeqSz; 00899 XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz); 00900 totalSz += issuerSeqSz; 00901 XMEMCPY(out + totalSz, decoded.issuerRaw, issuerSz); 00902 totalSz += issuerSz; 00903 XMEMCPY(out + totalSz, serial, snSz); 00904 totalSz += snSz; 00905 XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz); 00906 totalSz += keyEncAlgSz; 00907 XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz); 00908 totalSz += encKeyOctetStrSz; 00909 XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz); 00910 totalSz += *keyEncSz; 00911 00912 FreeDecodedCert(&decoded); 00913 00914 return totalSz; 00915 } 00916 00917 00918 /* build PKCS#7 envelopedData content type, return enveloped size */ 00919 int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) 00920 { 00921 int i, ret = 0, idx = 0; 00922 int totalSz = 0, padSz = 0, desOutSz = 0; 00923 00924 int contentInfoSeqSz, outerContentTypeSz, outerContentSz; 00925 byte contentInfoSeq[MAX_SEQ_SZ]; 00926 byte outerContentType[MAX_ALGO_SZ]; 00927 byte outerContent[MAX_SEQ_SZ]; 00928 00929 int envDataSeqSz, verSz; 00930 byte envDataSeq[MAX_SEQ_SZ]; 00931 byte ver[MAX_VERSION_SZ]; 00932 00933 RNG rng; 00934 int contentKeyEncSz, blockKeySz; 00935 int dynamicFlag = 0; 00936 byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; 00937 byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; 00938 byte* plain; 00939 byte* encryptedContent; 00940 00941 int recipSz, recipSetSz; 00942 byte recip[MAX_RECIP_SZ]; 00943 byte recipSet[MAX_SET_SZ]; 00944 00945 int encContentOctetSz, encContentSeqSz, contentTypeSz; 00946 int contentEncAlgoSz, ivOctetStringSz; 00947 byte encContentSeq[MAX_SEQ_SZ]; 00948 byte contentType[MAX_ALGO_SZ]; 00949 byte contentEncAlgo[MAX_ALGO_SZ]; 00950 byte tmpIv[DES_BLOCK_SIZE]; 00951 byte ivOctetString[MAX_OCTET_STR_SZ]; 00952 byte encContentOctet[MAX_OCTET_STR_SZ]; 00953 00954 if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || 00955 pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL) 00956 return BAD_FUNC_ARG; 00957 00958 if (output == NULL || outputSz == 0) 00959 return BAD_FUNC_ARG; 00960 00961 /* PKCS#7 only supports DES, 3DES for now */ 00962 switch (pkcs7->encryptOID) { 00963 case DESb: 00964 blockKeySz = DES_KEYLEN; 00965 break; 00966 00967 case DES3b: 00968 blockKeySz = DES3_KEYLEN; 00969 break; 00970 00971 default: 00972 CYASSL_MSG("Unsupported content cipher type"); 00973 return ALGO_ID_E; 00974 }; 00975 00976 /* outer content type */ 00977 outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType); 00978 00979 /* version, defined as 0 in RFC 2315 */ 00980 verSz = SetMyVersion(0, ver, 0); 00981 00982 /* generate random content encryption key */ 00983 InitRng(&rng); 00984 RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); 00985 00986 /* build RecipientInfo, only handle 1 for now */ 00987 recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk, 00988 blockKeySz, &rng, contentKeyPlain, 00989 contentKeyEnc, &contentKeyEncSz, recip, 00990 MAX_RECIP_SZ); 00991 00992 if (recipSz < 0) { 00993 CYASSL_MSG("Failed to create RecipientInfo"); 00994 return recipSz; 00995 } 00996 recipSetSz = SetSet(recipSz, recipSet); 00997 00998 /* EncryptedContentInfo */ 00999 contentTypeSz = SetContentType(pkcs7->contentOID, contentType); 01000 if (contentTypeSz == 0) 01001 return BAD_FUNC_ARG; 01002 01003 /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */ 01004 padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE); 01005 desOutSz = pkcs7->contentSz + padSz; 01006 01007 if (padSz != 0) { 01008 plain = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01009 if (plain == NULL) { 01010 return MEMORY_E; 01011 } 01012 XMEMCPY(plain, pkcs7->content, pkcs7->contentSz); 01013 dynamicFlag = 1; 01014 01015 for (i = 0; i < padSz; i++) { 01016 plain[pkcs7->contentSz + i] = padSz; 01017 } 01018 01019 } else { 01020 plain = pkcs7->content; 01021 desOutSz = pkcs7->contentSz; 01022 } 01023 01024 encryptedContent = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01025 if (encryptedContent == NULL) { 01026 if (dynamicFlag) 01027 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01028 return MEMORY_E; 01029 } 01030 01031 /* generate IV for block cipher */ 01032 RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE); 01033 01034 /* put together IV OCTET STRING */ 01035 ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString); 01036 01037 /* build up our ContentEncryptionAlgorithmIdentifier sequence, 01038 * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */ 01039 contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, 01040 blkType, ivOctetStringSz + DES_BLOCK_SIZE); 01041 if (contentEncAlgoSz == 0) 01042 return BAD_FUNC_ARG; 01043 01044 /* encrypt content */ 01045 if (pkcs7->encryptOID == DESb) { 01046 Des des; 01047 01048 ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION); 01049 01050 if (ret == 0) 01051 Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz); 01052 01053 if (ret != 0) { 01054 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01055 if (dynamicFlag) 01056 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01057 return ret; 01058 } 01059 } 01060 else if (pkcs7->encryptOID == DES3b) { 01061 Des3 des3; 01062 01063 ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION); 01064 01065 if (ret == 0) 01066 ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz); 01067 01068 if (ret != 0) { 01069 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01070 if (dynamicFlag) 01071 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01072 return ret; 01073 } 01074 } 01075 01076 encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, 01077 desOutSz, encContentOctet); 01078 01079 encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + 01080 ivOctetStringSz + DES_BLOCK_SIZE + 01081 encContentOctetSz + desOutSz, encContentSeq); 01082 01083 /* keep track of sizes for outer wrapper layering */ 01084 totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + 01085 contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + 01086 encContentOctetSz + desOutSz; 01087 01088 /* EnvelopedData */ 01089 envDataSeqSz = SetSequence(totalSz, envDataSeq); 01090 totalSz += envDataSeqSz; 01091 01092 /* outer content */ 01093 outerContentSz = SetExplicit(0, totalSz, outerContent); 01094 totalSz += outerContentTypeSz; 01095 totalSz += outerContentSz; 01096 01097 /* ContentInfo */ 01098 contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); 01099 totalSz += contentInfoSeqSz; 01100 01101 if (totalSz > (int)outputSz) { 01102 CYASSL_MSG("Pkcs7_encrypt output buffer too small"); 01103 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01104 if (dynamicFlag) 01105 XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01106 return BUFFER_E; 01107 } 01108 01109 XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); 01110 idx += contentInfoSeqSz; 01111 XMEMCPY(output + idx, outerContentType, outerContentTypeSz); 01112 idx += outerContentTypeSz; 01113 XMEMCPY(output + idx, outerContent, outerContentSz); 01114 idx += outerContentSz; 01115 XMEMCPY(output + idx, envDataSeq, envDataSeqSz); 01116 idx += envDataSeqSz; 01117 XMEMCPY(output + idx, ver, verSz); 01118 idx += verSz; 01119 XMEMCPY(output + idx, recipSet, recipSetSz); 01120 idx += recipSetSz; 01121 XMEMCPY(output + idx, recip, recipSz); 01122 idx += recipSz; 01123 XMEMCPY(output + idx, encContentSeq, encContentSeqSz); 01124 idx += encContentSeqSz; 01125 XMEMCPY(output + idx, contentType, contentTypeSz); 01126 idx += contentTypeSz; 01127 XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); 01128 idx += contentEncAlgoSz; 01129 XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); 01130 idx += ivOctetStringSz; 01131 XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE); 01132 idx += DES_BLOCK_SIZE; 01133 XMEMCPY(output + idx, encContentOctet, encContentOctetSz); 01134 idx += encContentOctetSz; 01135 XMEMCPY(output + idx, encryptedContent, desOutSz); 01136 idx += desOutSz; 01137 01138 #ifdef NO_RC4 01139 FreeRng(&rng); 01140 #endif 01141 01142 XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN); 01143 XMEMSET(contentKeyEnc, 0, MAX_ENCRYPTED_KEY_SZ); 01144 01145 if (dynamicFlag) 01146 XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER); 01147 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01148 01149 return idx; 01150 } 01151 01152 /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ 01153 CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, 01154 word32 pkiMsgSz, byte* output, 01155 word32 outputSz) 01156 { 01157 int recipFound = 0; 01158 int ret, version, length; 01159 word32 savedIdx = 0, idx = 0; 01160 word32 contentType, encOID; 01161 byte issuerHash[SHA_DIGEST_SIZE]; 01162 mp_int serialNum; 01163 01164 int encryptedKeySz, keySz; 01165 byte tmpIv[DES_BLOCK_SIZE]; 01166 byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; 01167 byte* decryptedKey = NULL; 01168 01169 RsaKey privKey; 01170 int encryptedContentSz; 01171 byte padLen; 01172 byte* encryptedContent = NULL; 01173 01174 if (pkcs7 == NULL || pkcs7->singleCert == NULL || 01175 pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || 01176 pkcs7->privateKeySz == 0) 01177 return BAD_FUNC_ARG; 01178 01179 if (pkiMsg == NULL || pkiMsgSz == 0 || 01180 output == NULL || outputSz == 0) 01181 return BAD_FUNC_ARG; 01182 01183 /* load private key */ 01184 ret = InitRsaKey(&privKey, 0); 01185 if (ret != 0) return ret; 01186 ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey, 01187 pkcs7->privateKeySz); 01188 if (ret != 0) { 01189 CYASSL_MSG("Failed to decode RSA private key"); 01190 return ret; 01191 } 01192 01193 idx = 0; 01194 01195 /* read past ContentInfo, verify type is envelopedData */ 01196 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01197 return ASN_PARSE_E; 01198 01199 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01200 return ASN_PARSE_E; 01201 01202 if (contentType != ENVELOPED_DATA) { 01203 CYASSL_MSG("PKCS#7 input not of type EnvelopedData"); 01204 return PKCS7_OID_E; 01205 } 01206 01207 if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) 01208 return ASN_PARSE_E; 01209 01210 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01211 return ASN_PARSE_E; 01212 01213 /* remove EnvelopedData and version */ 01214 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01215 return ASN_PARSE_E; 01216 01217 if (GetMyVersion(pkiMsg, &idx, &version) < 0) 01218 return ASN_PARSE_E; 01219 01220 if (version != 0) { 01221 CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0"); 01222 return ASN_VERSION_E; 01223 } 01224 01225 /* walk through RecipientInfo set, find correct recipient */ 01226 if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01227 return ASN_PARSE_E; 01228 01229 savedIdx = idx; 01230 recipFound = 0; 01231 01232 /* when looking for next recipient, use first sequence and version to 01233 * indicate there is another, if not, move on */ 01234 while(recipFound == 0) { 01235 01236 /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to 01237 * last good saved one */ 01238 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { 01239 idx = savedIdx; 01240 break; 01241 } 01242 01243 if (GetMyVersion(pkiMsg, &idx, &version) < 0) { 01244 idx = savedIdx; 01245 break; 01246 } 01247 01248 if (version != 0) 01249 return ASN_VERSION_E; 01250 01251 /* remove IssuerAndSerialNumber */ 01252 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01253 return ASN_PARSE_E; 01254 01255 if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) 01256 return ASN_PARSE_E; 01257 01258 /* if we found correct recipient, issuer hashes will match */ 01259 if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { 01260 recipFound = 1; 01261 } 01262 01263 if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0) 01264 return ASN_PARSE_E; 01265 mp_clear(&serialNum); 01266 01267 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) 01268 return ASN_PARSE_E; 01269 01270 /* key encryption algorithm must be RSA for now */ 01271 if (encOID != RSAk) 01272 return ALGO_ID_E; 01273 01274 /* read encryptedKey */ 01275 if (pkiMsg[idx++] != ASN_OCTET_STRING) 01276 return ASN_PARSE_E; 01277 01278 if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) 01279 return ASN_PARSE_E; 01280 01281 if (recipFound == 1) 01282 XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz); 01283 idx += encryptedKeySz; 01284 01285 /* update good idx */ 01286 savedIdx = idx; 01287 } 01288 01289 if (recipFound == 0) { 01290 CYASSL_MSG("No recipient found in envelopedData that matches input"); 01291 return PKCS7_RECIP_E; 01292 } 01293 01294 /* remove EncryptedContentInfo */ 01295 if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01296 return ASN_PARSE_E; 01297 01298 if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) 01299 return ASN_PARSE_E; 01300 01301 if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) 01302 return ASN_PARSE_E; 01303 01304 /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ 01305 if (pkiMsg[idx++] != ASN_OCTET_STRING) 01306 return ASN_PARSE_E; 01307 01308 if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) 01309 return ASN_PARSE_E; 01310 01311 if (length != DES_BLOCK_SIZE) { 01312 CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE"); 01313 return ASN_PARSE_E; 01314 } 01315 01316 XMEMCPY(tmpIv, &pkiMsg[idx], length); 01317 idx += length; 01318 01319 /* read encryptedContent, cont[0] */ 01320 if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) 01321 return ASN_PARSE_E; 01322 01323 if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) 01324 return ASN_PARSE_E; 01325 01326 encryptedContent = XMALLOC(encryptedContentSz, NULL, 01327 DYNAMIC_TYPE_TMP_BUFFER); 01328 01329 XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); 01330 01331 /* decrypt encryptedKey */ 01332 keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, 01333 &decryptedKey, &privKey); 01334 FreeRsaKey(&privKey); 01335 if (keySz <= 0) 01336 return keySz; 01337 01338 /* decrypt encryptedContent */ 01339 if (encOID == DESb) { 01340 Des des; 01341 ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); 01342 01343 if (ret == 0) 01344 Des_CbcDecrypt(&des, encryptedContent, encryptedContent, 01345 encryptedContentSz); 01346 01347 if (ret != 0) { 01348 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01349 return ret; 01350 } 01351 } 01352 else if (encOID == DES3b) { 01353 Des3 des; 01354 ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); 01355 if (ret == 0) 01356 ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent, 01357 encryptedContentSz); 01358 01359 if (ret != 0) { 01360 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01361 return ret; 01362 } 01363 } else { 01364 CYASSL_MSG("Unsupported content encryption OID type"); 01365 return ALGO_ID_E; 01366 } 01367 01368 padLen = encryptedContent[encryptedContentSz-1]; 01369 01370 /* copy plaintext to output */ 01371 XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); 01372 01373 /* free memory, zero out keys */ 01374 XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ); 01375 XMEMSET(encryptedContent, 0, encryptedContentSz); 01376 XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01377 01378 return encryptedContentSz - padLen; 01379 } 01380 01381 01382 #else /* HAVE_PKCS7 */ 01383 01384 01385 #ifdef _MSC_VER 01386 /* 4206 warning for blank file */ 01387 #pragma warning(disable: 4206) 01388 #endif 01389 01390 01391 #endif /* HAVE_PKCS7 */ 01392
Generated on Tue Jul 12 2022 20:12:51 by
