我正在编写C ++代码以获取TLS 1.x加密的pcap并将数据包解密为未加密的缓冲区。到目前为止,除了TLS 1.2 AEAD密码之外,我已经取得了成功。鉴于已知的premaster,我似乎无法推断出如何正确使用OpenSSL来解密每个TLS记录。 OpenSSL文档还有很多不足之处,因此我将代码简化为单一功能,希望有人可以对我做错的事情有所了解。
您应该假设TLS握手已完成并且我有premaster密钥并从prf计算了4字节隐式nonce(作为saltIV传递)。
任何帮助将不胜感激!我已经好几天了,而且感到很沮丧。
using bytes = std::vector<std::uint8_t>;
// input is the fragment part of TLSCiphertext from the TLS 1.2 RFC
void decryptGCM(bytes premaster, bytes saltIV, bytes input)
{
EVP_CIPHER_CTX evp;
EVP_CIPHER_CTX_init(&evp);
EVP_DecryptInit_ex(&evp, EVP_aes_128_gcm(), nullptr, premaster.data(), nullptr);
std::uint8_t nonce[12] = { 0 };
/*
struct {
opaque nonce_explicit[SecurityParameters.record_iv_length];
aead-ciphered struct {
opaque content[TLSCompressed.length];
};
} GenericAEADCipher;
*/
// The first 8 bytes of a TLS 1.2 record is the explicit nonce
// Create nonce from implicit (generated from prf) and explicit parts
assert(saltIV.size() == 4);
memcpy(nonce, saltIV.data(), saltIV.size());
memcpy(nonce + saltIV.size(), input.data(), EVP_GCM_TLS_EXPLICIT_IV_LEN); // EVP_GCM_TLS_EXPLICIT_IV_LEN == 8
EVP_CIPHER_CTX_ctrl(&evp, EVP_CTRL_GCM_SET_IVLEN, sizeof(nonce), 0);
EVP_CIPHER_CTX_ctrl(&evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, nonce);
/*
Note that each of these AEAD algorithms uses a 128-bit authentication tag with GCM (in
particular, as described in Section 3.5 of [RFC4366]
*/
// Tag is the last 16 bytes of the input buffer, set below
std::uint8_t tag[16];
memcpy(tag, (input.data() + input.size() - sizeof(tag)), sizeof(tag));
EVP_CIPHER_CTX_ctrl(&evp, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag);
n_uint64 sequence(1);
n_uint8 ct(22);
n_uint16 size(static_cast<std::uint16_t>(input.size()));
size = size - EVP_GCM_TLS_EXPLICIT_IV_LEN - static_cast<n_uint16>(sizeof(tag));
// additional authenticated data
output_byte_stream aad;
aad << sequence << ct << tls1_2version << size;
/*
aad becomes this byte sequence
[0] 0 '\0' unsigned char
[1] 0 '\0' unsigned char
[2] 0 '\0' unsigned char
[3] 0 '\0' unsigned char
[4] 0 '\0' unsigned char
[5] 0 '\0' unsigned char
[6] 0 '\0' unsigned char
[7] 1 '\x1' unsigned char
[8] 22 '\x16' unsigned char
[9] 3 '\x3' unsigned char
[10] 3 '\x3' unsigned char
[11] 0 '\0' unsigned char
[12] 16 '\x10' unsigned char
*/
int outlen = 0;
if (!EVP_DecryptUpdate(&evp, nullptr, &outlen, aad.buffer().data(), (unsigned int)aad.buffer().size()))
{
std::cout << "EVP_DecryptUpdate Failed" << std::endl;
}
bytes out;
out.resize(input.size() + 1024);
if (!EVP_DecryptUpdate(&evp, &out[0], &outlen, input.data() + EVP_GCM_TLS_EXPLICIT_IV_LEN, (unsigned int)size))
{
std::cout << "EVP_DecryptUpdate Failed" << std::endl;
}
// Check the tag
if (!EVP_DecryptFinal(&evp, &out[0] + outlen, &outlen))
{
std::cout << "EVP_DecryptFinal Failed" << std::endl;
}
}