tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ssl_aead_unittest.cc (8126B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <memory>
      8 
      9 #include "keyhi.h"
     10 #include "pk11pub.h"
     11 #include "secerr.h"
     12 #include "ssl.h"
     13 #include "sslerr.h"
     14 #include "sslexp.h"
     15 #include "sslproto.h"
     16 
     17 #include "gtest_utils.h"
     18 #include "nss_scoped_ptrs.h"
     19 #include "scoped_ptrs_ssl.h"
     20 #include "tls_connect.h"
     21 
     22 namespace nss_test {
     23 
     24 // From tls_hkdf_unittest.cc:
     25 extern size_t GetHashLength(SSLHashType ht);
     26 
     27 class AeadTest : public ::testing::Test {
     28 public:
     29  AeadTest() : slot_(PK11_GetInternalSlot()) {}
     30 
     31  void InitSecret(SSLHashType hash_type) {
     32    static const uint8_t kData[64] = {'s', 'e', 'c', 'r', 'e', 't'};
     33    SECItem key_item = {siBuffer, const_cast<uint8_t *>(kData),
     34                        static_cast<unsigned int>(GetHashLength(hash_type))};
     35    PK11SymKey *s =
     36        PK11_ImportSymKey(slot_.get(), CKM_SSL3_MASTER_KEY_DERIVE,
     37                          PK11_OriginUnwrap, CKA_DERIVE, &key_item, NULL);
     38    ASSERT_NE(nullptr, s);
     39    secret_.reset(s);
     40  }
     41 
     42  void SetUp() override {
     43    InitSecret(ssl_hash_sha256);
     44    PORT_SetError(0);
     45  }
     46 
     47 protected:
     48  static void EncryptDecrypt(const ScopedSSLAeadContext &ctx,
     49                             const uint8_t *ciphertext, size_t ciphertext_len) {
     50    static const uint8_t kAad[] = {'a', 'a', 'd'};
     51    static const uint8_t kPlaintext[] = {'t', 'e', 'x', 't'};
     52    static const size_t kMaxSize = 32;
     53 
     54    ASSERT_GE(kMaxSize, ciphertext_len);
     55    ASSERT_LT(0U, ciphertext_len);
     56 
     57    uint8_t output[kMaxSize] = {0};
     58    unsigned int output_len = 0;
     59    EXPECT_EQ(SECSuccess, SSL_AeadEncrypt(ctx.get(), 0, kAad, sizeof(kAad),
     60                                          kPlaintext, sizeof(kPlaintext),
     61                                          output, &output_len, sizeof(output)));
     62    ASSERT_EQ(ciphertext_len, static_cast<size_t>(output_len));
     63    EXPECT_EQ(0, memcmp(ciphertext, output, ciphertext_len));
     64 
     65    memset(output, 0, sizeof(output));
     66    EXPECT_EQ(SECSuccess, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
     67                                          ciphertext, ciphertext_len, output,
     68                                          &output_len, sizeof(output)));
     69    ASSERT_EQ(sizeof(kPlaintext), static_cast<size_t>(output_len));
     70    EXPECT_EQ(0, memcmp(kPlaintext, output, sizeof(kPlaintext)));
     71 
     72    // Now for some tests of decryption failure.
     73    // Truncate the input.
     74    EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
     75                                          ciphertext, ciphertext_len - 1,
     76                                          output, &output_len, sizeof(output)));
     77    EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
     78 
     79    // Skip the first byte of the AAD.
     80    EXPECT_EQ(
     81        SECFailure,
     82        SSL_AeadDecrypt(ctx.get(), 0, kAad + 1, sizeof(kAad) - 1, ciphertext,
     83                        ciphertext_len, output, &output_len, sizeof(output)));
     84    EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
     85 
     86    uint8_t input[kMaxSize] = {0};
     87    // Toggle a byte of the input.
     88    memcpy(input, ciphertext, ciphertext_len);
     89    input[0] ^= 9;
     90    EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
     91                                          input, ciphertext_len, output,
     92                                          &output_len, sizeof(output)));
     93    EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
     94 
     95    // Toggle the last byte (the auth tag).
     96    memcpy(input, ciphertext, ciphertext_len);
     97    input[ciphertext_len - 1] ^= 77;
     98    EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
     99                                          input, ciphertext_len, output,
    100                                          &output_len, sizeof(output)));
    101    EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
    102 
    103    // Toggle some of the AAD.
    104    memcpy(input, kAad, sizeof(kAad));
    105    input[1] ^= 23;
    106    EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, input, sizeof(kAad),
    107                                          ciphertext, ciphertext_len, output,
    108                                          &output_len, sizeof(output)));
    109    EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
    110  }
    111 
    112 protected:
    113  ScopedPK11SymKey secret_;
    114 
    115 private:
    116  ScopedPK11SlotInfo slot_;
    117 };
    118 
    119 // These tests all use fixed inputs: a fixed secret, a fixed label, and fixed
    120 // inputs.  So they have fixed outputs.
    121 static const char *kLabel = "test ";
    122 static const uint8_t kCiphertextAes128Gcm[] = {
    123    0x11, 0x14, 0xfc, 0x58, 0x4f, 0x44, 0xff, 0x8c, 0xb6, 0xd8,
    124    0x20, 0xb3, 0xfb, 0x50, 0xd9, 0x3b, 0xd4, 0xc6, 0xe1, 0x14};
    125 static const uint8_t kCiphertextAes256Gcm[] = {
    126    0xf7, 0x27, 0x35, 0x80, 0x88, 0xaf, 0x99, 0x85, 0xf2, 0x83,
    127    0xca, 0xbb, 0x95, 0x42, 0x09, 0x3f, 0x9c, 0xf3, 0x29, 0xf0};
    128 static const uint8_t kCiphertextChaCha20Poly1305[] = {
    129    0x4e, 0x89, 0x2c, 0xfa, 0xfc, 0x8c, 0x40, 0x55, 0x6d, 0x7e,
    130    0x99, 0xac, 0x8e, 0x54, 0x58, 0xb1, 0x18, 0xd2, 0x66, 0x22};
    131 
    132 TEST_F(AeadTest, AeadBadVersion) {
    133  SSLAeadContext *ctx = nullptr;
    134  ASSERT_EQ(SECFailure,
    135            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
    136                         secret_.get(), kLabel, strlen(kLabel), &ctx));
    137  EXPECT_EQ(nullptr, ctx);
    138 }
    139 
    140 TEST_F(AeadTest, AeadUnsupportedCipher) {
    141  SSLAeadContext *ctx = nullptr;
    142  ASSERT_EQ(SECFailure,
    143            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
    144                         secret_.get(), kLabel, strlen(kLabel), &ctx));
    145  EXPECT_EQ(nullptr, ctx);
    146 }
    147 
    148 TEST_F(AeadTest, AeadOlderCipher) {
    149  SSLAeadContext *ctx = nullptr;
    150  ASSERT_EQ(
    151      SECFailure,
    152      SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_AES_128_CBC_SHA,
    153                   secret_.get(), kLabel, strlen(kLabel), &ctx));
    154  EXPECT_EQ(nullptr, ctx);
    155 }
    156 
    157 TEST_F(AeadTest, AeadNoLabel) {
    158  SSLAeadContext *ctx = nullptr;
    159  ASSERT_EQ(SECFailure,
    160            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
    161                         secret_.get(), nullptr, 12, &ctx));
    162  EXPECT_EQ(nullptr, ctx);
    163 }
    164 
    165 TEST_F(AeadTest, AeadLongLabel) {
    166  SSLAeadContext *ctx = nullptr;
    167  ASSERT_EQ(SECFailure,
    168            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
    169                         secret_.get(), "", 254, &ctx));
    170  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    171  EXPECT_EQ(nullptr, ctx);
    172 }
    173 
    174 TEST_F(AeadTest, AeadNoPointer) {
    175  SSLAeadContext *ctx = nullptr;
    176  ASSERT_EQ(SECFailure,
    177            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
    178                         secret_.get(), kLabel, strlen(kLabel), nullptr));
    179  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    180  EXPECT_EQ(nullptr, ctx);
    181 }
    182 
    183 TEST_F(AeadTest, AeadAes128Gcm) {
    184  SSLAeadContext *ctxInit = nullptr;
    185  ASSERT_EQ(SECSuccess,
    186            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
    187                         secret_.get(), kLabel, strlen(kLabel), &ctxInit));
    188  ScopedSSLAeadContext ctx(ctxInit);
    189  EXPECT_NE(nullptr, ctx);
    190 
    191  EncryptDecrypt(ctx, kCiphertextAes128Gcm, sizeof(kCiphertextAes128Gcm));
    192 }
    193 
    194 TEST_F(AeadTest, AeadAes256Gcm) {
    195  SSLAeadContext *ctxInit = nullptr;
    196  ASSERT_EQ(SECSuccess,
    197            SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384,
    198                         secret_.get(), kLabel, strlen(kLabel), &ctxInit));
    199  ScopedSSLAeadContext ctx(ctxInit);
    200  EXPECT_NE(nullptr, ctx);
    201 
    202  EncryptDecrypt(ctx, kCiphertextAes256Gcm, sizeof(kCiphertextAes256Gcm));
    203 }
    204 
    205 TEST_F(AeadTest, AeadChaCha20Poly1305) {
    206  SSLAeadContext *ctxInit = nullptr;
    207  ASSERT_EQ(
    208      SECSuccess,
    209      SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_CHACHA20_POLY1305_SHA256,
    210                   secret_.get(), kLabel, strlen(kLabel), &ctxInit));
    211  ScopedSSLAeadContext ctx(ctxInit);
    212  EXPECT_NE(nullptr, ctx);
    213 
    214  EncryptDecrypt(ctx, kCiphertextChaCha20Poly1305,
    215                 sizeof(kCiphertextChaCha20Poly1305));
    216 }
    217 
    218 }  // namespace nss_test