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