static CURLcode Curl_cyassl_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { RNG rng; (void)data; if(InitRng(&rng)) return CURLE_FAILED_INIT; if(length > UINT_MAX) return CURLE_FAILED_INIT; if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) return CURLE_FAILED_INIT; if(FreeRng(&rng)) return CURLE_FAILED_INIT; return CURLE_OK; }
/* build PKCS#7 envelopedData content type, return enveloped size */ int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) { int i, ret = 0, idx = 0; int totalSz = 0, padSz = 0, desOutSz = 0; int contentInfoSeqSz, outerContentTypeSz, outerContentSz; byte contentInfoSeq[MAX_SEQ_SZ]; byte outerContentType[MAX_ALGO_SZ]; byte outerContent[MAX_SEQ_SZ]; int envDataSeqSz, verSz; byte envDataSeq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; RNG rng; int contentKeyEncSz, blockKeySz; int dynamicFlag = 0; byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; byte* plain; byte* encryptedContent; int recipSz, recipSetSz; byte recip[MAX_RECIP_SZ]; byte recipSet[MAX_SET_SZ]; int encContentOctetSz, encContentSeqSz, contentTypeSz; int contentEncAlgoSz, ivOctetStringSz; byte encContentSeq[MAX_SEQ_SZ]; byte contentType[MAX_ALGO_SZ]; byte contentEncAlgo[MAX_ALGO_SZ]; byte tmpIv[DES_BLOCK_SIZE]; byte ivOctetString[MAX_OCTET_STR_SZ]; byte encContentOctet[MAX_OCTET_STR_SZ]; if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL) return BAD_FUNC_ARG; if (output == NULL || outputSz == 0) return BAD_FUNC_ARG; /* PKCS#7 only supports DES, 3DES for now */ switch (pkcs7->encryptOID) { case DESb: blockKeySz = DES_KEYLEN; break; case DES3b: blockKeySz = DES3_KEYLEN; break; default: CYASSL_MSG("Unsupported content cipher type"); return ALGO_ID_E; }; /* outer content type */ outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType); /* version, defined as 0 in RFC 2315 */ verSz = SetMyVersion(0, ver, 0); /* generate random content encryption key */ ret = InitRng(&rng); if (ret != 0) return ret; ret = RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); if (ret != 0) return ret; /* build RecipientInfo, only handle 1 for now */ recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk, blockKeySz, &rng, contentKeyPlain, contentKeyEnc, &contentKeyEncSz, recip, MAX_RECIP_SZ); if (recipSz < 0) { CYASSL_MSG("Failed to create RecipientInfo"); return recipSz; } recipSetSz = SetSet(recipSz, recipSet); /* generate IV for block cipher */ ret = RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE); if (ret != 0) return ret; /* EncryptedContentInfo */ contentTypeSz = SetContentType(pkcs7->contentOID, contentType); if (contentTypeSz == 0) return BAD_FUNC_ARG; /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */ padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE); desOutSz = pkcs7->contentSz + padSz; if (padSz != 0) { plain = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plain == NULL) { return MEMORY_E; } XMEMCPY(plain, pkcs7->content, pkcs7->contentSz); dynamicFlag = 1; for (i = 0; i < padSz; i++) { plain[pkcs7->contentSz + i] = padSz; } } else { plain = pkcs7->content; desOutSz = pkcs7->contentSz; } encryptedContent = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (encryptedContent == NULL) { if (dynamicFlag) XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } /* put together IV OCTET STRING */ ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString); /* build up our ContentEncryptionAlgorithmIdentifier sequence, * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */ contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, blkType, ivOctetStringSz + DES_BLOCK_SIZE); if (contentEncAlgoSz == 0) return BAD_FUNC_ARG; /* encrypt content */ if (pkcs7->encryptOID == DESb) { Des des; ret = Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION); if (ret == 0) Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz); if (ret != 0) { XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dynamicFlag) XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } } else if (pkcs7->encryptOID == DES3b) { Des3 des3; ret = Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION); if (ret == 0) ret = Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz); if (ret != 0) { XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dynamicFlag) XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } } encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, desOutSz, encContentOctet); encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + encContentOctetSz + desOutSz, encContentSeq); /* keep track of sizes for outer wrapper layering */ totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + encContentOctetSz + desOutSz; /* EnvelopedData */ envDataSeqSz = SetSequence(totalSz, envDataSeq); totalSz += envDataSeqSz; /* outer content */ outerContentSz = SetExplicit(0, totalSz, outerContent); totalSz += outerContentTypeSz; totalSz += outerContentSz; /* ContentInfo */ contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); totalSz += contentInfoSeqSz; if (totalSz > (int)outputSz) { CYASSL_MSG("Pkcs7_encrypt output buffer too small"); XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dynamicFlag) XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); return BUFFER_E; } XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); idx += contentInfoSeqSz; XMEMCPY(output + idx, outerContentType, outerContentTypeSz); idx += outerContentTypeSz; XMEMCPY(output + idx, outerContent, outerContentSz); idx += outerContentSz; XMEMCPY(output + idx, envDataSeq, envDataSeqSz); idx += envDataSeqSz; XMEMCPY(output + idx, ver, verSz); idx += verSz; XMEMCPY(output + idx, recipSet, recipSetSz); idx += recipSetSz; XMEMCPY(output + idx, recip, recipSz); idx += recipSz; XMEMCPY(output + idx, encContentSeq, encContentSeqSz); idx += encContentSeqSz; XMEMCPY(output + idx, contentType, contentTypeSz); idx += contentTypeSz; XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); idx += contentEncAlgoSz; XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); idx += ivOctetStringSz; XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE); idx += DES_BLOCK_SIZE; XMEMCPY(output + idx, encContentOctet, encContentOctetSz); idx += encContentOctetSz; XMEMCPY(output + idx, encryptedContent, desOutSz); idx += desOutSz; #ifdef NO_RC4 FreeRng(&rng); #endif XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN); XMEMSET(contentKeyEnc, 0, MAX_ENCRYPTED_KEY_SZ); if (dynamicFlag) XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER); XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); return idx; }