/* check mcapi des3 */ static int check_des3(void) { CRYPT_TDES_CTX mcDes3; Des3 defDes3; int ret; byte out1[TDES_TEST_SIZE]; byte out2[TDES_TEST_SIZE]; strncpy((char*)key, "1234567890abcdefghijklmn", 24); strncpy((char*)iv, "12345678", 8); /* cbc encrypt */ ret = CRYPT_TDES_KeySet(&mcDes3, key, iv, CRYPT_TDES_ENCRYPTION); if (ret != 0) { printf("mcapi tdes key set failed\n"); return -1; } Des3_SetKey(&defDes3, key, iv, DES_ENCRYPTION); ret = CRYPT_TDES_CBC_Encrypt(&mcDes3, out1, ourData, TDES_TEST_SIZE); if (ret != 0) { printf("mcapi tdes cbc encrypt failed\n"); return -1; } Des3_CbcEncrypt(&defDes3, out2, ourData, TDES_TEST_SIZE); if (memcmp(out1, out2, TDES_TEST_SIZE) != 0) { printf("mcapi tdes cbc encrypt cmp failed\n"); return -1; } /* cbc decrypt */ ret = CRYPT_TDES_KeySet(&mcDes3, key, iv, CRYPT_TDES_DECRYPTION); if (ret != 0) { printf("mcapi tdes key set failed\n"); return -1; } Des3_SetKey(&defDes3, key, iv, DES_DECRYPTION); ret = CRYPT_TDES_CBC_Decrypt(&mcDes3, out2, out1, TDES_TEST_SIZE); if (ret != 0) { printf("mcapi tdes cbc decrypt failed\n"); return -1; } Des3_CbcDecrypt(&defDes3, out1, out1, TDES_TEST_SIZE); if (memcmp(out1, out2, TDES_TEST_SIZE) != 0) { printf("mcapi tdes cbc decrypt cmp failed\n"); return -1; } if (memcmp(out1, ourData, TDES_TEST_SIZE) != 0) { printf("mcapi tdes cbc decrypt orig cmp failed\n"); return -1; } printf("tdes mcapi test passed\n"); return 0; }
int des3_test() { const byte vector[] = { /* "Now is the time for all " w/o trailing 0 */ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 }; byte plain[24]; byte cipher[24]; Des3 enc; Des3 dec; const byte key3[] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; const byte iv3[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 }; const byte verify3[] = { 0x43,0xa0,0x29,0x7e,0xd1,0x84,0xf8,0x0e, 0x89,0x64,0x84,0x32,0x12,0xd5,0x08,0x98, 0x18,0x94,0x15,0x74,0x87,0x12,0x7d,0xb0 }; Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION); Des3_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); Des3_SetKey(&dec, key3, iv3, DES_DECRYPTION); Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); if (memcmp(plain, vector, sizeof(plain))) return -33; if (memcmp(cipher, verify3, sizeof(cipher))) return -34; return 0; }
void bench_des(void) { Des3 enc; double start, total, persec; int i, ret; #ifdef HAVE_CAVIUM if (Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0) printf("des3 init cavium failed\n"); #endif ret = Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); if (ret != 0) { printf("Des3_SetKey failed, ret = %d\n", ret); return; } start = current_time(1); for(i = 0; i < numBlocks; i++) Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain)); total = current_time(0) - start; persec = 1 / total * numBlocks; #ifdef BENCH_EMBEDDED /* since using kB, convert to MB/s */ persec = persec / 1024; #endif printf("3DES %d %s took %5.3f seconds, %7.3f MB/s\n", numBlocks, blockType, total, persec); #ifdef HAVE_CAVIUM Des3_FreeCavium(&enc); #endif }
/* Triple DES Key Set, may have iv, will have direction */ int CRYPT_TDES_KeySet(CRYPT_TDES_CTX* tdes, const unsigned char* key, const unsigned char* iv, int dir) { typedef char tdes_test[sizeof(CRYPT_TDES_CTX) >= sizeof(Des3) ? 1 : -1]; (void)sizeof(tdes_test); if (tdes == NULL || key == NULL) return BAD_FUNC_ARG; return Des3_SetKey((Des3*)tdes, key, iv, dir); }
/* * k5_des3_encrypt: Encrypt data buffer using 3DES. * * @key DES key (with odd parity) * @ivec Initialization Vector * @data Input/Output buffer (in-place encryption, block-by-block) * @num_data Number of blocks * * Returns 0 on success, krb5_error_code on error */ static krb5_error_code k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { int ret; Des3 des3; unsigned char iv[DES_BLOCK_SIZE]; unsigned char iblock[DES_BLOCK_SIZE]; unsigned char oblock[DES_BLOCK_SIZE]; //struct iov_block_state input_pos, output_pos; struct iov_cursor cursor; krb5_boolean empty; ret = validate(key, ivec, data, num_data, &empty); if (ret != 0 || empty) return ret; memset(iv, 0, sizeof(iv)); /* Check if IV exists and is the correct size */ if (ivec && ivec->data) { if (ivec->length != sizeof(iv)) return KRB5_CRYPTO_INTERNAL; memcpy(iv, ivec->data, ivec->length); } Des3_SetKey(&des3, key->keyblock.contents, iv, DES_ENCRYPTION); k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE); for (;;) { if (!k5_iov_cursor_get(&cursor, iblock)) break; Des3_CbcEncrypt(&des3, oblock, iblock, DES_BLOCK_SIZE); k5_iov_cursor_put(&cursor, oblock); } if (ivec != NULL) memcpy(ivec->data, oblock, DES_BLOCK_SIZE); zap(iv, sizeof(iv)); zap(iblock, sizeof(iblock)); zap(oblock, sizeof(oblock)); return 0; }
void bench_des(void) { Des3 enc; double start, total, persec; int i; Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); start = current_time(); for(i = 0; i < megs; i++) Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain)); total = current_time() - start; persec = 1 / total * megs; printf("3DES %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); }
static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, byte side) { #ifdef BUILD_ARC4 word32 sz = specs->key_size; if (specs->bulk_cipher_algorithm == rc4) { if (side == CLIENT_END) { Arc4SetKey(&enc->arc4, keys->client_write_key, sz); Arc4SetKey(&dec->arc4, keys->server_write_key, sz); } else { Arc4SetKey(&enc->arc4, keys->server_write_key, sz); Arc4SetKey(&dec->arc4, keys->client_write_key, sz); } } #endif #ifdef BUILD_HC128 if (specs->bulk_cipher_algorithm == hc128) { if (side == CLIENT_END) { Hc128_SetKey(&enc->hc128, keys->client_write_key, keys->client_write_IV); Hc128_SetKey(&dec->hc128, keys->server_write_key, keys->server_write_IV); } else { Hc128_SetKey(&enc->hc128, keys->server_write_key, keys->server_write_IV); Hc128_SetKey(&dec->hc128, keys->client_write_key, keys->client_write_IV); } } #endif #ifdef BUILD_RABBIT if (specs->bulk_cipher_algorithm == rabbit) { if (side == CLIENT_END) { RabbitSetKey(&enc->rabbit, keys->client_write_key, keys->client_write_IV); RabbitSetKey(&dec->rabbit, keys->server_write_key, keys->server_write_IV); } else { RabbitSetKey(&enc->rabbit, keys->server_write_key, keys->server_write_IV); RabbitSetKey(&dec->rabbit, keys->client_write_key, keys->client_write_IV); } } #endif #ifdef BUILD_DES3 if (specs->bulk_cipher_algorithm == triple_des) { if (side == CLIENT_END) { Des3_SetKey(&enc->des3, keys->client_write_key, keys->client_write_IV, DES_ENCRYPTION); Des3_SetKey(&dec->des3, keys->server_write_key, keys->server_write_IV, DES_DECRYPTION); } else { Des3_SetKey(&enc->des3, keys->server_write_key, keys->server_write_IV, DES_ENCRYPTION); Des3_SetKey(&dec->des3, keys->client_write_key, keys->client_write_IV, DES_DECRYPTION); } } #endif #ifdef BUILD_AES if (specs->bulk_cipher_algorithm == aes) { if (side == CLIENT_END) { AesSetKey(&enc->aes, keys->client_write_key, specs->key_size, keys->client_write_IV, AES_ENCRYPTION); AesSetKey(&dec->aes, keys->server_write_key, specs->key_size, keys->server_write_IV, AES_DECRYPTION); } else { AesSetKey(&enc->aes, keys->server_write_key, specs->key_size, keys->server_write_IV, AES_ENCRYPTION); AesSetKey(&dec->aes, keys->client_write_key, specs->key_size, keys->client_write_IV, AES_DECRYPTION); } } #endif keys->sequence_number = 0; keys->peer_sequence_number = 0; keys->encryptionOn = 0; return 0; }
static int SetKeys(SSL* ssl) { #ifdef BUILD_ARC4 word32 sz = ssl->specs.key_size; if (ssl->specs.bulk_cipher_algorithm == rc4) { if (ssl->options.side == CLIENT_END) { Arc4SetKey(&ssl->encrypt.arc4, ssl->keys.client_write_key, sz); Arc4SetKey(&ssl->decrypt.arc4, ssl->keys.server_write_key, sz); } else { Arc4SetKey(&ssl->encrypt.arc4, ssl->keys.server_write_key, sz); Arc4SetKey(&ssl->decrypt.arc4, ssl->keys.client_write_key, sz); } } #endif #ifdef BUILD_HC128 if (ssl->specs.bulk_cipher_algorithm == hc128) { if (ssl->options.side == CLIENT_END) { Hc128_SetKey(&ssl->encrypt.hc128, ssl->keys.client_write_key, ssl->keys.client_write_IV); Hc128_SetKey(&ssl->decrypt.hc128, ssl->keys.server_write_key, ssl->keys.server_write_IV); } else { Hc128_SetKey(&ssl->encrypt.hc128, ssl->keys.server_write_key, ssl->keys.server_write_IV); Hc128_SetKey(&ssl->decrypt.hc128, ssl->keys.client_write_key, ssl->keys.client_write_IV); } } #endif #ifdef BUILD_RABBIT if (ssl->specs.bulk_cipher_algorithm == rabbit) { if (ssl->options.side == CLIENT_END) { RabbitSetKey(&ssl->encrypt.rabbit, ssl->keys.client_write_key, ssl->keys.client_write_IV); RabbitSetKey(&ssl->decrypt.rabbit, ssl->keys.server_write_key, ssl->keys.server_write_IV); } else { RabbitSetKey(&ssl->encrypt.rabbit, ssl->keys.server_write_key, ssl->keys.server_write_IV); RabbitSetKey(&ssl->decrypt.rabbit, ssl->keys.client_write_key, ssl->keys.client_write_IV); } } #endif #ifdef BUILD_DES3 if (ssl->specs.bulk_cipher_algorithm == triple_des) { if (ssl->options.side == CLIENT_END) { Des3_SetKey(&ssl->encrypt.des3, ssl->keys.client_write_key, ssl->keys.client_write_IV, DES_ENCRYPTION); Des3_SetKey(&ssl->decrypt.des3, ssl->keys.server_write_key, ssl->keys.server_write_IV, DES_DECRYPTION); } else { Des3_SetKey(&ssl->encrypt.des3, ssl->keys.server_write_key, ssl->keys.server_write_IV, DES_ENCRYPTION); Des3_SetKey(&ssl->decrypt.des3, ssl->keys.client_write_key, ssl->keys.client_write_IV, DES_DECRYPTION); } } #endif #ifdef BUILD_AES if (ssl->specs.bulk_cipher_algorithm == aes) { if (ssl->options.side == CLIENT_END) { AesSetKey(&ssl->encrypt.aes, ssl->keys.client_write_key, ssl->specs.key_size, ssl->keys.client_write_IV, AES_ENCRYPTION); AesSetKey(&ssl->decrypt.aes, ssl->keys.server_write_key, ssl->specs.key_size, ssl->keys.server_write_IV, AES_DECRYPTION); } else { AesSetKey(&ssl->encrypt.aes, ssl->keys.server_write_key, ssl->specs.key_size, ssl->keys.server_write_IV, AES_ENCRYPTION); AesSetKey(&ssl->decrypt.aes, ssl->keys.client_write_key, ssl->specs.key_size, ssl->keys.client_write_IV, AES_DECRYPTION); } } #endif ssl->keys.sequence_number = 0; ssl->keys.peer_sequence_number = 0; ssl->keys.encryptionOn = 0; return 0; }
/* 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; }
/* 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; }
static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, byte side, void* heap, RNG* rng) { #ifdef BUILD_ARC4 word32 sz = specs->key_size; if (specs->bulk_cipher_algorithm == rc4) { enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (enc->arc4 == NULL) return MEMORY_E; dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (dec->arc4 == NULL) return MEMORY_E; if (side == CLIENT_END) { Arc4SetKey(enc->arc4, keys->client_write_key, sz); Arc4SetKey(dec->arc4, keys->server_write_key, sz); } else { Arc4SetKey(enc->arc4, keys->server_write_key, sz); Arc4SetKey(dec->arc4, keys->client_write_key, sz); } } #endif #ifdef HAVE_HC128 if (specs->bulk_cipher_algorithm == hc128) { enc->hc128 = (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER); if (enc->hc128 == NULL) return MEMORY_E; dec->hc128 = (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER); if (dec->hc128 == NULL) return MEMORY_E; if (side == CLIENT_END) { Hc128_SetKey(enc->hc128, keys->client_write_key, keys->client_write_IV); Hc128_SetKey(dec->hc128, keys->server_write_key, keys->server_write_IV); } else { Hc128_SetKey(enc->hc128, keys->server_write_key, keys->server_write_IV); Hc128_SetKey(dec->hc128, keys->client_write_key, keys->client_write_IV); } } #endif #ifdef BUILD_RABBIT if (specs->bulk_cipher_algorithm == rabbit) { enc->rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),heap,DYNAMIC_TYPE_CIPHER); if (enc->rabbit == NULL) return MEMORY_E; dec->rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),heap,DYNAMIC_TYPE_CIPHER); if (dec->rabbit == NULL) return MEMORY_E; if (side == CLIENT_END) { RabbitSetKey(enc->rabbit, keys->client_write_key, keys->client_write_IV); RabbitSetKey(dec->rabbit, keys->server_write_key, keys->server_write_IV); } else { RabbitSetKey(enc->rabbit, keys->server_write_key, keys->server_write_IV); RabbitSetKey(dec->rabbit, keys->client_write_key, keys->client_write_IV); } } #endif #ifdef BUILD_DES3 if (specs->bulk_cipher_algorithm == triple_des) { enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); if (enc->des3 == NULL) return MEMORY_E; dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); if (dec->des3 == NULL) return MEMORY_E; if (side == CLIENT_END) { Des3_SetKey(enc->des3, keys->client_write_key, keys->client_write_IV, DES_ENCRYPTION); Des3_SetKey(dec->des3, keys->server_write_key, keys->server_write_IV, DES_DECRYPTION); } else { Des3_SetKey(enc->des3, keys->server_write_key, keys->server_write_IV, DES_ENCRYPTION); Des3_SetKey(dec->des3, keys->client_write_key, keys->client_write_IV, DES_DECRYPTION); } } #endif #ifdef BUILD_AES if (specs->bulk_cipher_algorithm == aes) { enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (enc->aes == NULL) return MEMORY_E; dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (dec->aes == NULL) return MEMORY_E; if (side == CLIENT_END) { AesSetKey(enc->aes, keys->client_write_key, specs->key_size, keys->client_write_IV, AES_ENCRYPTION); AesSetKey(dec->aes, keys->server_write_key, specs->key_size, keys->server_write_IV, AES_DECRYPTION); } else { AesSetKey(enc->aes, keys->server_write_key, specs->key_size, keys->server_write_IV, AES_ENCRYPTION); AesSetKey(dec->aes, keys->client_write_key, specs->key_size, keys->client_write_IV, AES_DECRYPTION); } } #endif #ifdef BUILD_AESGCM if (specs->bulk_cipher_algorithm == aes_gcm) { byte iv[AES_GCM_EXP_IV_SZ]; enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (enc->aes == NULL) return MEMORY_E; dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (dec->aes == NULL) return MEMORY_E; /* Initialize the AES-GCM explicit IV to a random number. */ RNG_GenerateBlock(rng, iv, sizeof(iv)); AesGcmSetExpIV(enc->aes, iv); if (side == CLIENT_END) { AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size, keys->client_write_IV); AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size, keys->server_write_IV); } else { AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size, keys->server_write_IV); AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size, keys->client_write_IV); } } #endif keys->sequence_number = 0; keys->peer_sequence_number = 0; keys->encryptionOn = 0; (void)rng; return 0; }