int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { int plainLen, ret; byte* tmp; byte* pad = 0; if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) ) return MEMORY_E; XMEMCPY(tmp, in, inLen); if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key)) < 0) { XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return ret; } if (plainLen > (int)outLen) plainLen = BAD_FUNC_ARG; else XMEMCPY(out, pad, plainLen); XMEMSET(tmp, 0x00, inLen); XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; }
int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { int plainLen, ret; byte* tmp; byte* pad = 0; #ifdef HAVE_CAVIUM if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); #endif tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) { return MEMORY_E; } XMEMCPY(tmp, in, inLen); if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key)) < 0) { XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return ret; } if (plainLen > (int)outLen) plainLen = BAD_FUNC_ARG; else XMEMCPY(out, pad, plainLen); XMEMSET(tmp, 0x00, inLen); XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; }
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); }
/* 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; }