int rsa_test() { byte tmp[1024], tmp2[2048]; size_t bytes, bytes2; RsaKey key; RNG rng; word32 idx = 0; int ret; byte in[] = "Everyone gets Friday off."; word32 inLen = (word32)strlen((char*)in); byte out[64]; byte plain[64]; DecodedCert cert; FILE* file = fopen(clientKey, "rb"), * file2; if (!file) return -40; bytes = fread(tmp, 1, 1024, file); InitRsaKey(&key, 0); ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) return -41; ret = InitRng(&rng); if (ret != 0) return -42; ret = RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); ret = RsaPrivateDecrypt(out, 64, plain, sizeof(plain), &key); if (memcmp(plain, in, inLen)) return -45; ret = RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); memset(plain, 0, sizeof(plain)); ret = RsaSSL_Verify(out, 64, plain, sizeof(plain), &key); if (memcmp(plain, in, ret)) return -46; file2 = fopen(clientCert, "rb"); if (!file2) return -47; bytes2 = fread(tmp2, 1, 2048, file2); InitDecodedCert(&cert, (byte*)&tmp2, 0); ret = ParseCert(&cert, (word32)bytes2, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) return -48; FreeDecodedCert(&cert); FreeRsaKey(&key); fclose(file2); fclose(file); return 0; }
/* RSA Private key decode ASN.1 */ int CRYPT_RSA_PrivateKeyDecode(CRYPT_RSA_CTX* rsa, const unsigned char* in, unsigned int inSz) { unsigned int idx = 0; (void)idx; if (rsa == NULL || in == NULL) return BAD_FUNC_ARG; return RsaPrivateKeyDecode(in, &idx, (RsaKey*)rsa->holder, inSz); }
void bench_rsa(void) { int i; byte tmp[3072]; size_t bytes; word32 idx = 0; byte message[] = "Everyone gets Friday off."; byte enc[512]; /* for up to 4096 bit */ byte* output; const int len = (int)strlen((char*)message); double start, total, each, milliEach; RsaKey rsaKey; FILE* file = fopen("./certs/rsa2048.der", "rb"); if (!file) { printf("can't find ./certs/rsa2048.der, " "Please run from CyaSSL home dir\n"); return; } InitRng(&rng); bytes = fread(tmp, 1, sizeof(tmp), file); InitRsaKey(&rsaKey, 0); bytes = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); start = current_time(); for (i = 0; i < times; i++) bytes = RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng); total = current_time() - start; each = total / times; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA 2048 encryption took %6.2f milliseconds, avg over %d" " iterations\n", milliEach, times); start = current_time(); for (i = 0; i < times; i++) RsaPrivateDecryptInline(enc, (word32)bytes, &output, &rsaKey); total = current_time() - start; each = total / times; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA 2048 decryption took %6.2f milliseconds, avg over %d" " iterations\n", milliEach, times); fclose(file); FreeRsaKey(&rsaKey); }
void bench_rsa() { int i; byte tmp[1024]; size_t bytes; word32 idx = 0; byte message[] = "Everyone gets Friday off."; byte cipher[128]; /* for 1024 bit */ byte plain[128]; /* for 1024 bit */ const int len = (int)strlen((char*)message); double start, total, each, milliEach; RsaKey key; FILE* file = fopen("./rsa1024.der", "rb"); if (!file) { printf("can't find ./rsa1024.der\n"); return; } bytes = fread(tmp, 1, 1024, file); InitRsaKey(&key, 0); bytes = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); start = current_time(); for (i = 0; i < times; i++) RsaPublicEncrypt(message, len, cipher, sizeof(cipher), &key, &rng); total = current_time() - start; each = total / times; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA 1024 encryption took %6.2f milliseconds, avg over %d" " iterations\n", milliEach, times); start = current_time(); for (i = 0; i < times; i++) RsaPrivateDecrypt(cipher, 128, plain, sizeof(plain), &key); total = current_time() - start; each = total / times; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA 1024 decryption took %6.2f milliseconds, avg over %d" " iterations\n", milliEach, times); fclose(file); FreeRsaKey(&key); }
/* check mcapi rsa */ static int check_rsa(void) { CRYPT_RSA_CTX mcRsa; RsaKey defRsa; int ret; int ret2; unsigned int keySz = (unsigned int)sizeof(client_key_der_1024); unsigned int idx = 0; byte out1[256]; byte out2[256]; InitRsaKey(&defRsa, NULL); ret = CRYPT_RSA_Initialize(&mcRsa); if (ret != 0) { printf("mcapi rsa init failed\n"); return -1; } ret = CRYPT_RSA_PrivateKeyDecode(&mcRsa, client_key_der_1024, keySz); if (ret != 0) { printf("mcapi rsa private key decode failed\n"); return -1; } ret = RsaPrivateKeyDecode(client_key_der_1024, &idx, &defRsa, keySz); if (ret != 0) { printf("default rsa private key decode failed\n"); return -1; } ret = CRYPT_RSA_PublicEncrypt(&mcRsa, out1, sizeof(out1), ourData, RSA_TEST_SIZE, &mcRng); if (ret < 0) { printf("mcapi rsa public encrypt failed\n"); return -1; } ret2 = RsaPublicEncrypt(ourData, RSA_TEST_SIZE, out2, sizeof(out2), &defRsa, &defRng); if (ret2 < 0) { printf("default rsa public encrypt failed\n"); return -1; } if (ret != ret2) { printf("default rsa public encrypt sz != mcapi sz\n"); return -1; } if (ret != CRYPT_RSA_EncryptSizeGet(&mcRsa)) { printf("mcapi encrypt sz get != mcapi sz\n"); return -1; } ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); if (ret < 0) { printf("mcapi rsa private derypt failed\n"); return -1; } if (ret != RSA_TEST_SIZE) { printf("mcapi rsa private derypt plain size wrong\n"); return -1; } if (memcmp(out2, ourData, ret) != 0) { printf("mcapi rsa private derypt plain text bad\n"); return -1; } FreeRsaKey(&defRsa); ret = CRYPT_RSA_Free(&mcRsa); if (ret != 0) { printf("mcapi rsa free failed\n"); return -1; } printf("rsa mcapi test passed\n"); return 0; }
void bench_rsa(void) { int i; int ret; byte tmp[3072]; size_t bytes; word32 idx = 0; byte message[] = "Everyone gets Friday off."; byte enc[512]; /* for up to 4096 bit */ const int len = (int)strlen((char*)message); double start, total, each, milliEach; RsaKey rsaKey; int rsaKeySz = 2048; /* used in printf */ #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, rsa_key_der_1024, sizeof_rsa_key_der_1024); bytes = sizeof_rsa_key_der_1024; rsaKeySz = 1024; #elif defined(USE_CERT_BUFFERS_2048) XMEMCPY(tmp, rsa_key_der_2048, sizeof_rsa_key_der_2048); bytes = sizeof_rsa_key_der_2048; #else FILE* file = fopen(certRSAname, "rb"); if (!file) { printf("can't find %s, Please run from CyaSSL home dir\n", certRSAname); return; } bytes = fread(tmp, 1, sizeof(tmp), file); fclose(file); #endif /* USE_CERT_BUFFERS */ #ifdef HAVE_CAVIUM if (RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0) printf("RSA init cavium failed\n"); #endif ret = InitRng(&rng); if (ret < 0) { printf("InitRNG failed\n"); return; } ret = InitRsaKey(&rsaKey, 0); if (ret < 0) { printf("InitRsaKey failed\n"); return; } ret = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); start = current_time(1); for (i = 0; i < ntimes; i++) ret = RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng); total = current_time(0) - start; each = total / ntimes; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA %d encryption took %6.3f milliseconds, avg over %d" " iterations\n", rsaKeySz, milliEach, ntimes); if (ret < 0) { printf("Rsa Public Encrypt failed\n"); return; } start = current_time(1); for (i = 0; i < ntimes; i++) { byte out[512]; /* for up to 4096 bit */ RsaPrivateDecrypt(enc, (word32)ret, out, sizeof(out), &rsaKey); } total = current_time(0) - start; each = total / ntimes; /* per second */ milliEach = each * 1000; /* milliseconds */ printf("RSA %d decryption took %6.3f milliseconds, avg over %d" " iterations\n", rsaKeySz, milliEach, ntimes); FreeRsaKey(&rsaKey); #ifdef HAVE_CAVIUM RsaFreeCavium(&rsaKey); #endif }
int rsa_test() { byte tmp[1024], tmp2[2048]; size_t bytes, bytes2; RsaKey key; RNG rng; word32 idx = 0; int ret; byte in[] = "Everyone gets Friday off."; word32 inLen = (word32)strlen((char*)in); byte out[64]; byte plain[64]; DecodedCert cert; FILE* file = fopen(clientKey, "rb"), * file2; if (!file) return -40; bytes = fread(tmp, 1, 1024, file); InitRsaKey(&key, 0); ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) return -41; ret = InitRng(&rng); if (ret != 0) return -42; ret = RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); ret = RsaPrivateDecrypt(out, 64, plain, sizeof(plain), &key); if (memcmp(plain, in, inLen)) return -45; ret = RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); memset(plain, 0, sizeof(plain)); ret = RsaSSL_Verify(out, 64, plain, sizeof(plain), &key); if (memcmp(plain, in, ret)) return -46; file2 = fopen(clientCert, "rb"); if (!file2) return -47; bytes2 = fread(tmp2, 1, 2048, file2); InitDecodedCert(&cert, (byte*)&tmp2, 0); ret = ParseCert(&cert, (word32)bytes2, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) return -48; FreeDecodedCert(&cert); fclose(file2); fclose(file); #ifdef CYASSL_KEY_GEN { byte der[4096]; byte pem[4096]; word32 derSz = 0; word32 pemSz = 0; RsaKey derIn; RsaKey genKey; FILE* keyFile; FILE* pemFile; InitRsaKey(&genKey, 0); ret = MakeRsaKey(&genKey, 1024, 65537, &rng); if (ret != 0) return -301; derSz = RsaKeyToDer(&genKey, der, sizeof(der)); if (derSz < 0) return -302; keyFile = fopen("./ker.der", "wb"); if (!keyFile) return -303; ret = fwrite(der, derSz, 1, keyFile); fclose(keyFile); pemSz = DerToPem(der, derSz, pem, sizeof(pem), PRIVATEKEY_TYPE); if (pemSz < 0) return -304; pemFile = fopen("./key.pem", "wb"); if (!pemFile) return -305; ret = fwrite(pem, pemSz, 1, pemFile); fclose(pemFile); InitRsaKey(&derIn, 0); idx = 0; ret = RsaPrivateKeyDecode(der, &idx, &derIn, derSz); if (ret != 0) return -306; } #endif /* CYASSL_KEY_GEN */ #ifdef CYASSL_CERT_GEN { Cert myCert; byte derCert[4096]; byte pem[4096]; DecodedCert decode; FILE* derFile; FILE* pemFile; int certSz; int pemSz; InitCert(&myCert); strncpy(myCert.subject.country, "US", NAME_SIZE); strncpy(myCert.subject.state, "OR", NAME_SIZE); strncpy(myCert.subject.locality, "Portland", NAME_SIZE); strncpy(myCert.subject.org, "yaSSL", NAME_SIZE); strncpy(myCert.subject.unit, "Development", NAME_SIZE); strncpy(myCert.subject.commonName, "www.yassl.com", NAME_SIZE); strncpy(myCert.subject.email, "*****@*****.**", NAME_SIZE); certSz = MakeCert(&myCert, derCert, sizeof(derCert), &key, &rng); if (certSz < 0) return -401; InitDecodedCert(&decode, derCert, 0); ret = ParseCert(&decode, certSz, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) return -402; derFile = fopen("./cert.der", "wb"); if (!derFile) return -403; ret = fwrite(derCert, certSz, 1, derFile); fclose(derFile); pemSz = DerToPem(derCert, certSz, pem, sizeof(pem), CERT_TYPE); if (pemSz < 0) return -404; pemFile = fopen("./cert.pem", "wb"); if (!pemFile) return -405; ret = fwrite(pem, pemSz, 1, pemFile); fclose(pemFile); FreeDecodedCert(&decode); } #endif /* CYASSL_CERT_GEN */ FreeRsaKey(&key); return 0; }
/* build PKCS#7 signedData content type */ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { static const byte outerOid[] = { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 }; static const byte innerOid[] = { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; ESD esd; word32 signerInfoSz = 0; word32 totalSz = 0; int idx = 0, ret = 0; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; word32 innerOidSz = sizeof(innerOid); word32 outerOidSz = sizeof(outerOid); if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; XMEMSET(&esd, 0, sizeof(esd)); ret = InitSha(&esd.sha); if (ret != 0) return ret; if (pkcs7->contentSz != 0) { ShaUpdate(&esd.sha, pkcs7->content, pkcs7->contentSz); esd.contentDigest[0] = ASN_OCTET_STRING; esd.contentDigest[1] = SHA_DIGEST_SIZE; ShaFinal(&esd.sha, &esd.contentDigest[2]); } esd.innerOctetsSz = SetOctetString(pkcs7->contentSz, esd.innerOctets); esd.innerContSeqSz = SetExplicit(0, esd.innerOctetsSz + pkcs7->contentSz, esd.innerContSeq); esd.contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd.innerOctetsSz + innerOidSz + esd.innerContSeqSz, esd.contentInfoSeq); esd.issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, esd.issuerSn); signerInfoSz += esd.issuerSnSz; esd.issuerNameSz = SetSequence(pkcs7->issuerSz, esd.issuerName); signerInfoSz += esd.issuerNameSz + pkcs7->issuerSz; esd.issuerSnSeqSz = SetSequence(signerInfoSz, esd.issuerSnSeq); signerInfoSz += esd.issuerSnSeqSz; esd.signerVersionSz = SetMyVersion(1, esd.signerVersion, 0); signerInfoSz += esd.signerVersionSz; esd.signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.signerDigAlgoId, hashType, 0); signerInfoSz += esd.signerDigAlgoIdSz; esd.digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd.digEncAlgoId, keyType, 0); signerInfoSz += esd.digEncAlgoIdSz; if (pkcs7->signedAttribsSz != 0) { byte contentTypeOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 0x09, 0x03 }; byte contentType[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; byte messageDigestOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; PKCS7Attrib cannedAttribs[2] = { { contentTypeOid, sizeof(contentTypeOid), contentType, sizeof(contentType) }, { messageDigestOid, sizeof(messageDigestOid), esd.contentDigest, sizeof(esd.contentDigest) } }; word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); esd.signedAttribsCount += cannedAttribsCount; esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[0], 2, cannedAttribs, cannedAttribsCount); esd.signedAttribsCount += pkcs7->signedAttribsSz; esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[2], 4, pkcs7->signedAttribs, pkcs7->signedAttribsSz); flatSignedAttribs = (byte*)XMALLOC(esd.signedAttribsSz, 0, NULL); flatSignedAttribsSz = esd.signedAttribsSz; if (flatSignedAttribs == NULL) return MEMORY_E; FlattenAttributes(flatSignedAttribs, esd.signedAttribs, esd.signedAttribsCount); esd.signedAttribSetSz = SetImplicit(ASN_SET, 0, esd.signedAttribsSz, esd.signedAttribSet); } /* Calculate the final hash and encrypt it. */ { RsaKey privKey; int result; word32 scratch = 0; byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; byte digestInfoSeq[MAX_SEQ_SZ]; byte digestStr[MAX_OCTET_STR_SZ]; word32 digestInfoSeqSz, digestStrSz; int digIdx = 0; if (pkcs7->signedAttribsSz != 0) { byte attribSet[MAX_SET_SZ]; word32 attribSetSz; attribSetSz = SetSet(flatSignedAttribsSz, attribSet); ret = InitSha(&esd.sha); if (ret < 0) { XFREE(flatSignedAttribs, 0, NULL); return ret; } ShaUpdate(&esd.sha, attribSet, attribSetSz); ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz); } ShaFinal(&esd.sha, esd.contentAttribsDigest); digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); digestInfoSeqSz = SetSequence(esd.signerDigAlgoIdSz + digestStrSz + SHA_DIGEST_SIZE, digestInfoSeq); XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); digIdx += digestInfoSeqSz; XMEMCPY(digestInfo + digIdx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz); digIdx += esd.signerDigAlgoIdSz; XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); digIdx += digestStrSz; XMEMCPY(digestInfo + digIdx, esd.contentAttribsDigest, SHA_DIGEST_SIZE); digIdx += SHA_DIGEST_SIZE; result = InitRsaKey(&privKey, NULL); if (result == 0) result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey, pkcs7->privateKeySz); if (result < 0) { XFREE(flatSignedAttribs, 0, NULL); return PUBLIC_KEY_E; } result = RsaSSL_Sign(digestInfo, digIdx, esd.encContentDigest, sizeof(esd.encContentDigest), &privKey, pkcs7->rng); FreeRsaKey(&privKey); if (result < 0) { XFREE(flatSignedAttribs, 0, NULL); return result; } esd.encContentDigestSz = (word32)result; } signerInfoSz += flatSignedAttribsSz + esd.signedAttribSetSz; esd.signerDigestSz = SetOctetString(esd.encContentDigestSz, esd.signerDigest); signerInfoSz += esd.signerDigestSz + esd.encContentDigestSz; esd.signerInfoSeqSz = SetSequence(signerInfoSz, esd.signerInfoSeq); signerInfoSz += esd.signerInfoSeqSz; esd.signerInfoSetSz = SetSet(signerInfoSz, esd.signerInfoSet); signerInfoSz += esd.signerInfoSetSz; esd.certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, esd.certsSet); esd.singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.singleDigAlgoId, hashType, 0); esd.digAlgoIdSetSz = SetSet(esd.singleDigAlgoIdSz, esd.digAlgoIdSet); esd.versionSz = SetMyVersion(1, esd.version, 0); totalSz = esd.versionSz + esd.singleDigAlgoIdSz + esd.digAlgoIdSetSz + esd.contentInfoSeqSz + esd.certsSetSz + pkcs7->singleCertSz + esd.innerOctetsSz + esd.innerContSeqSz + innerOidSz + pkcs7->contentSz + signerInfoSz; esd.innerSeqSz = SetSequence(totalSz, esd.innerSeq); totalSz += esd.innerSeqSz; esd.outerContentSz = SetExplicit(0, totalSz, esd.outerContent); totalSz += esd.outerContentSz + outerOidSz; esd.outerSeqSz = SetSequence(totalSz, esd.outerSeq); totalSz += esd.outerSeqSz; if (outputSz < totalSz) return BUFFER_E; idx = 0; XMEMCPY(output + idx, esd.outerSeq, esd.outerSeqSz); idx += esd.outerSeqSz; XMEMCPY(output + idx, outerOid, outerOidSz); idx += outerOidSz; XMEMCPY(output + idx, esd.outerContent, esd.outerContentSz); idx += esd.outerContentSz; XMEMCPY(output + idx, esd.innerSeq, esd.innerSeqSz); idx += esd.innerSeqSz; XMEMCPY(output + idx, esd.version, esd.versionSz); idx += esd.versionSz; XMEMCPY(output + idx, esd.digAlgoIdSet, esd.digAlgoIdSetSz); idx += esd.digAlgoIdSetSz; XMEMCPY(output + idx, esd.singleDigAlgoId, esd.singleDigAlgoIdSz); idx += esd.singleDigAlgoIdSz; XMEMCPY(output + idx, esd.contentInfoSeq, esd.contentInfoSeqSz); idx += esd.contentInfoSeqSz; XMEMCPY(output + idx, innerOid, innerOidSz); idx += innerOidSz; XMEMCPY(output + idx, esd.innerContSeq, esd.innerContSeqSz); idx += esd.innerContSeqSz; XMEMCPY(output + idx, esd.innerOctets, esd.innerOctetsSz); idx += esd.innerOctetsSz; XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); idx += pkcs7->contentSz; XMEMCPY(output + idx, esd.certsSet, esd.certsSetSz); idx += esd.certsSetSz; XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); idx += pkcs7->singleCertSz; XMEMCPY(output + idx, esd.signerInfoSet, esd.signerInfoSetSz); idx += esd.signerInfoSetSz; XMEMCPY(output + idx, esd.signerInfoSeq, esd.signerInfoSeqSz); idx += esd.signerInfoSeqSz; XMEMCPY(output + idx, esd.signerVersion, esd.signerVersionSz); idx += esd.signerVersionSz; XMEMCPY(output + idx, esd.issuerSnSeq, esd.issuerSnSeqSz); idx += esd.issuerSnSeqSz; XMEMCPY(output + idx, esd.issuerName, esd.issuerNameSz); idx += esd.issuerNameSz; XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); idx += pkcs7->issuerSz; XMEMCPY(output + idx, esd.issuerSn, esd.issuerSnSz); idx += esd.issuerSnSz; XMEMCPY(output + idx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz); idx += esd.signerDigAlgoIdSz; /* SignerInfo:Attributes */ if (pkcs7->signedAttribsSz != 0) { XMEMCPY(output + idx, esd.signedAttribSet, esd.signedAttribSetSz); idx += esd.signedAttribSetSz; XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); idx += flatSignedAttribsSz; XFREE(flatSignedAttribs, 0, NULL); } XMEMCPY(output + idx, esd.digEncAlgoId, esd.digEncAlgoIdSz); idx += esd.digEncAlgoIdSz; XMEMCPY(output + idx, esd.signerDigest, esd.signerDigestSz); idx += esd.signerDigestSz; XMEMCPY(output + idx, esd.encContentDigest, esd.encContentDigestSz); idx += esd.encContentDigestSz; return idx; }
/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz) { int recipFound = 0; int ret, version, length; word32 savedIdx = 0, idx = 0; word32 contentType, encOID; byte issuerHash[SHA_DIGEST_SIZE]; mp_int serialNum; int encryptedKeySz, keySz; byte tmpIv[DES_BLOCK_SIZE]; byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; byte* decryptedKey = NULL; RsaKey privKey; int encryptedContentSz; byte padLen; byte* encryptedContent = NULL; if (pkcs7 == NULL || pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0) return BAD_FUNC_ARG; if (pkiMsg == NULL || pkiMsgSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; /* load private key */ ret = InitRsaKey(&privKey, 0); if (ret != 0) return ret; ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey, pkcs7->privateKeySz); if (ret != 0) { CYASSL_MSG("Failed to decode RSA private key"); return ret; } idx = 0; /* read past ContentInfo, verify type is envelopedData */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) return ASN_PARSE_E; if (contentType != ENVELOPED_DATA) { CYASSL_MSG("PKCS#7 input not of type EnvelopedData"); return PKCS7_OID_E; } if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; /* remove EnvelopedData and version */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; if (GetMyVersion(pkiMsg, &idx, &version) < 0) return ASN_PARSE_E; if (version != 0) { CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0"); return ASN_VERSION_E; } /* walk through RecipientInfo set, find correct recipient */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; savedIdx = idx; recipFound = 0; /* when looking for next recipient, use first sequence and version to * indicate there is another, if not, move on */ while(recipFound == 0) { /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to * last good saved one */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { idx = savedIdx; break; } if (GetMyVersion(pkiMsg, &idx, &version) < 0) { idx = savedIdx; break; } if (version != 0) return ASN_VERSION_E; /* remove IssuerAndSerialNumber */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) return ASN_PARSE_E; /* if we found correct recipient, issuer hashes will match */ if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { recipFound = 1; } if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0) return ASN_PARSE_E; mp_clear(&serialNum); if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) return ASN_PARSE_E; /* key encryption algorithm must be RSA for now */ if (encOID != RSAk) return ALGO_ID_E; /* read encryptedKey */ if (pkiMsg[idx++] != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) return ASN_PARSE_E; if (recipFound == 1) XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz); idx += encryptedKeySz; /* update good idx */ savedIdx = idx; } if (recipFound == 0) { CYASSL_MSG("No recipient found in envelopedData that matches input"); return PKCS7_RECIP_E; } /* remove EncryptedContentInfo */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) return ASN_PARSE_E; if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) return ASN_PARSE_E; /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ if (pkiMsg[idx++] != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; if (length != DES_BLOCK_SIZE) { CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE"); return ASN_PARSE_E; } XMEMCPY(tmpIv, &pkiMsg[idx], length); idx += length; /* read encryptedContent, cont[0] */ if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) return ASN_PARSE_E; encryptedContent = XMALLOC(encryptedContentSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); /* decrypt encryptedKey */ keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, &decryptedKey, &privKey); FreeRsaKey(&privKey); if (keySz <= 0) return keySz; /* decrypt encryptedContent */ if (encOID == DESb) { Des des; ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); if (ret == 0) Des_CbcDecrypt(&des, encryptedContent, encryptedContent, encryptedContentSz); if (ret != 0) { XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } } else if (encOID == DES3b) { Des3 des; ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); if (ret == 0) ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent, encryptedContentSz); if (ret != 0) { XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } } else { CYASSL_MSG("Unsupported content encryption OID type"); return ALGO_ID_E; } padLen = encryptedContent[encryptedContentSz-1]; /* copy plaintext to output */ XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); /* free memory, zero out keys */ XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ); XMEMSET(encryptedContent, 0, encryptedContentSz); XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); return encryptedContentSz - padLen; }
#ifndef NO_RSA if (ssl->specs.sig_algo == rsa_sa_algo) { /* rsa sig size */ word32 i = 0; ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i, &rsaKey, ssl->buffers.key.length); if (ret != 0) goto done_a; sigSz = RsaEncryptSize(&rsaKey); } else #endif if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { /* ecdsa sig size */ word32 i = 0; ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, &dsaKey, ssl->buffers.key.length); if (ret != 0) goto done_a; sigSz = ecc_sig_size(&dsaKey); /* worst case estimate */ } else { #ifndef NO_RSA FreeRsaKey(&rsaKey); #endif ecc_free(&dsaKey); ERROR_OUT(ALGO_ID_E, done_a); /* unsupported type */ }