检查 TLS 实施中的错误

Check for errors in TLS implementation

我正在开发一个与 SMTP 一起使用的小型 TLS 客户端。在我的客户端发送加密的完成消息之前,握手运行良好。所以 Client Hello、Server Hello、Certificate、Server Hello Done、Client Key Exchange 和 Change Cipher Spec 都在工作。作为 chiper 套件,我正在使用 TLS_RSA_WITH_AES_256_CBC_SHA256.

我的问题是,在发送完消息后,我从服务器收到 "Bad Record MAC" 警报。但我不知道从哪里开始搜索错误。我仔细检查了所有函数并阅读了两次 RFC。

在我看来,以下几点之一可能会导致 "Bad Record MAC" 警报:

有谁知道我可以做些什么来找到问题。有什么工具可以检查master-secret、MAC和密钥计算是否正确?或者是否可以使用 Wireshark 解密内容?请注意,我没有服务器的私钥。

我已经按照 Steffen Ullrich 的建议使用 OpenSSL 设置了一个本地测试服务器。我已经对 Wireshark 提供的 "debug output" 进行了详细分析。

我能够解决我的填充问题。但我仍然收到 Bad Record MAC 警报。正如调试输出所说,MAC 不正确(消息 ssl_decrypt_record: mac failed)。

有关连接和调试输出的更多信息:

  1. pre-master-secret, master-secret 和所有密钥(client write MAC key, server write MAC key, client write key, server write key, client write IV,服务器写入 IV) 是正确的。我已经将我的软件中的这些与调试输出中的这些进行了比较。所以 Encrypted Finished Message 之前的所有内容都是正确的。
  2. 服务器/Wireshark 可以解密 Encrypted Finished Message 成功。
  3. 服务器/Wireshark 正确检测到填充。
  4. 服务器/Wireshark "skips" IV 仅显示 Finished Message 和 MAC 行 Plaintext[64]:

在我看来,只有两件事会导致此错误:

  1. MAC计算错误
  2. 握手消息中的哈希 (verify_data) 是错误的。

我的Encrypted Finished Message全长80字节,结构如下:

struct
{
    // TLS record
    ContentType type;
    ProtocolVersion version;
    uint16 length;
    // TLS handshake and content (encrypted)
    uint8 IV[16];
    struct
    {
        HandshakeType msg_type;
        uint24 length;
        uint8 verify_data[12];
    } content;
    uint8 MAC[32];
    uint8 padding[15];
    uint8 paddingLength;
} FinishedMessage;

内容如下所示:

     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0000 16 03 03 00 50 XX XX XX XX XX XX XX XX XX XX XX
0010 XX XX XX XX XX 14 00 00 0C YY YY YY YY YY YY YY
0020 YY YY YY YY YY ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ
0030 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ
0040 ZZ ZZ ZZ ZZ ZZ 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
0050 0F 0F 0F 0F 0F

其中 XX 代表随机生成的 IV,YY 代表消息的 verify_data,ZZ 代表消息的 MAC,如 RFC 中所述。

verify_data 包含 SHA-256 哈希的前 12 个字节。哈希由消息 Client HelloServer HelloCertificate(来自服务器)、Server Hello DoneClient Key Exchange 计算得出。对于没有记录头(前 5 个字节)的完整消息进行哈希处理。

MAC 由客户端写入 MAC 密钥和消息计算得出。使用数字 0 作为序列号。用于计算MAC的fragment只包含msg_typelengthverify_data(见上面的结构content)。

有谁知道我怎样才能找到我的 MAC 有什么问题?