selfencrypt_unittest.cc (9423B)
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 <functional> 8 #include <memory> 9 #include "nss.h" 10 #include "pk11pub.h" 11 #include "prerror.h" 12 #include "secerr.h" 13 #include "ssl.h" 14 #include "sslerr.h" 15 extern "C" { 16 #include "sslimpl.h" 17 #include "selfencrypt.h" 18 } 19 20 #include "databuffer.h" 21 #include "gtest_utils.h" 22 #include "nss_scoped_ptrs.h" 23 24 namespace nss_test { 25 26 static const uint8_t kAesKey1Buf[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 27 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 28 0x0c, 0x0d, 0x0e, 0x0f}; 29 static const DataBuffer kAesKey1(kAesKey1Buf, sizeof(kAesKey1Buf)); 30 31 static const uint8_t kAesKey2Buf[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 32 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 33 0x1c, 0x1d, 0x1e, 0x1f}; 34 static const DataBuffer kAesKey2(kAesKey2Buf, sizeof(kAesKey2Buf)); 35 36 static const uint8_t kHmacKey1Buf[] = { 37 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 38 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 39 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; 40 static const DataBuffer kHmacKey1(kHmacKey1Buf, sizeof(kHmacKey1Buf)); 41 42 static const uint8_t kHmacKey2Buf[] = { 43 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 44 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 45 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f}; 46 static const DataBuffer kHmacKey2(kHmacKey2Buf, sizeof(kHmacKey2Buf)); 47 48 static const uint8_t* kKeyName1 = 49 reinterpret_cast<const unsigned char*>("KEY1KEY1KEY1KEY1"); 50 static const uint8_t* kKeyName2 = 51 reinterpret_cast<const uint8_t*>("KEY2KEY2KEY2KEY2"); 52 53 static void ImportKey(const DataBuffer& key, PK11SlotInfo* slot, 54 CK_MECHANISM_TYPE mech, CK_ATTRIBUTE_TYPE cka, 55 ScopedPK11SymKey* to) { 56 SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()), 57 static_cast<unsigned int>(key.len())}; 58 59 PK11SymKey* inner = 60 PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, cka, &key_item, nullptr); 61 ASSERT_NE(nullptr, inner); 62 to->reset(inner); 63 } 64 65 extern "C" { 66 extern char ssl_trace; 67 extern FILE* ssl_trace_iob; 68 } 69 70 class SelfEncryptTestBase : public ::testing::Test { 71 public: 72 SelfEncryptTestBase(size_t message_size) 73 : aes1_(), 74 aes2_(), 75 hmac1_(), 76 hmac2_(), 77 message_(), 78 slot_(PK11_GetInternalSlot()) { 79 EXPECT_NE(nullptr, slot_); 80 char* ev = getenv("SSLTRACE"); 81 if (ev && ev[0]) { 82 ssl_trace = atoi(ev); 83 ssl_trace_iob = stderr; 84 } 85 message_.Allocate(message_size); 86 for (size_t i = 0; i < message_.len(); ++i) { 87 message_.data()[i] = i; 88 } 89 } 90 91 void SetUp() { 92 message_.Allocate(100); 93 for (size_t i = 0; i < 100; ++i) { 94 message_.data()[i] = i; 95 } 96 ImportKey(kAesKey1, slot_.get(), CKM_AES_CBC, CKA_ENCRYPT, &aes1_); 97 ImportKey(kAesKey2, slot_.get(), CKM_AES_CBC, CKA_ENCRYPT, &aes2_); 98 ImportKey(kHmacKey1, slot_.get(), CKM_SHA256_HMAC, CKA_SIGN, &hmac1_); 99 ImportKey(kHmacKey2, slot_.get(), CKM_SHA256_HMAC, CKA_SIGN, &hmac2_); 100 } 101 102 void SelfTest( 103 const uint8_t* writeKeyName, const ScopedPK11SymKey& writeAes, 104 const ScopedPK11SymKey& writeHmac, const uint8_t* readKeyName, 105 const ScopedPK11SymKey& readAes, const ScopedPK11SymKey& readHmac, 106 PRErrorCode protect_error_code = 0, PRErrorCode unprotect_error_code = 0, 107 std::function<void(uint8_t* ciphertext, unsigned int* ciphertext_len)> 108 mutate = nullptr) { 109 uint8_t ciphertext[1000]; 110 unsigned int ciphertext_len; 111 uint8_t plaintext[1000]; 112 unsigned int plaintext_len; 113 114 SECStatus rv = ssl_SelfEncryptProtectInt( 115 writeAes.get(), writeHmac.get(), writeKeyName, message_.data(), 116 message_.len(), ciphertext, &ciphertext_len, sizeof(ciphertext)); 117 if (rv != SECSuccess) { 118 std::cerr << "Error: " << PORT_ErrorToName(PORT_GetError()) << std::endl; 119 } 120 if (protect_error_code) { 121 ASSERT_EQ(protect_error_code, PORT_GetError()); 122 return; 123 } 124 ASSERT_EQ(SECSuccess, rv); 125 126 if (mutate) { 127 mutate(ciphertext, &ciphertext_len); 128 } 129 rv = ssl_SelfEncryptUnprotectInt(readAes.get(), readHmac.get(), readKeyName, 130 ciphertext, ciphertext_len, plaintext, 131 &plaintext_len, sizeof(plaintext)); 132 if (rv != SECSuccess) { 133 std::cerr << "Error: " << PORT_ErrorToName(PORT_GetError()) << std::endl; 134 } 135 if (!unprotect_error_code) { 136 ASSERT_EQ(SECSuccess, rv); 137 EXPECT_EQ(message_.len(), plaintext_len); 138 EXPECT_EQ(0, memcmp(message_.data(), plaintext, message_.len())); 139 } else { 140 ASSERT_EQ(SECFailure, rv); 141 EXPECT_EQ(unprotect_error_code, PORT_GetError()); 142 } 143 } 144 145 protected: 146 ScopedPK11SymKey aes1_; 147 ScopedPK11SymKey aes2_; 148 ScopedPK11SymKey hmac1_; 149 ScopedPK11SymKey hmac2_; 150 DataBuffer message_; 151 152 private: 153 ScopedPK11SlotInfo slot_; 154 }; 155 156 class SelfEncryptTestVariable : public SelfEncryptTestBase, 157 public ::testing::WithParamInterface<size_t> { 158 public: 159 SelfEncryptTestVariable() : SelfEncryptTestBase(GetParam()) {} 160 }; 161 162 class SelfEncryptTest128 : public SelfEncryptTestBase { 163 public: 164 SelfEncryptTest128() : SelfEncryptTestBase(128) {} 165 }; 166 167 TEST_P(SelfEncryptTestVariable, SuccessCase) { 168 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_); 169 } 170 171 TEST_P(SelfEncryptTestVariable, WrongMacKey) { 172 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac2_, 0, 173 SEC_ERROR_BAD_DATA); 174 } 175 176 TEST_P(SelfEncryptTestVariable, WrongKeyName) { 177 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName2, aes1_, hmac1_, 0, 178 SEC_ERROR_NOT_A_RECIPIENT); 179 } 180 181 TEST_P(SelfEncryptTestVariable, AddAByte) { 182 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 183 SEC_ERROR_BAD_DATA, 184 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 185 (*ciphertext_len)++; 186 }); 187 } 188 189 TEST_P(SelfEncryptTestVariable, SubtractAByte) { 190 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 191 SEC_ERROR_BAD_DATA, 192 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 193 (*ciphertext_len)--; 194 }); 195 } 196 197 TEST_P(SelfEncryptTestVariable, BogusIv) { 198 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 199 SEC_ERROR_BAD_DATA, 200 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 201 ciphertext[16]++; 202 }); 203 } 204 205 TEST_P(SelfEncryptTestVariable, BogusCiphertext) { 206 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 207 SEC_ERROR_BAD_DATA, 208 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 209 ciphertext[32]++; 210 }); 211 } 212 213 TEST_P(SelfEncryptTestVariable, BadMac) { 214 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 215 SEC_ERROR_BAD_DATA, 216 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 217 ciphertext[*ciphertext_len - 1]++; 218 }); 219 } 220 221 TEST_F(SelfEncryptTest128, DISABLED_BadPadding) { 222 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes2_, hmac1_, 0, 223 SEC_ERROR_BAD_DATA); 224 } 225 226 TEST_F(SelfEncryptTest128, ShortKeyName) { 227 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 228 SEC_ERROR_BAD_DATA, 229 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 230 *ciphertext_len = 15; 231 }); 232 } 233 234 TEST_F(SelfEncryptTest128, ShortIv) { 235 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 236 SEC_ERROR_BAD_DATA, 237 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 238 *ciphertext_len = 31; 239 }); 240 } 241 242 TEST_F(SelfEncryptTest128, ShortCiphertextLen) { 243 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 244 SEC_ERROR_BAD_DATA, 245 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 246 *ciphertext_len = 32; 247 }); 248 } 249 250 TEST_F(SelfEncryptTest128, ShortCiphertext) { 251 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, hmac1_, 0, 252 SEC_ERROR_BAD_DATA, 253 [](uint8_t* ciphertext, unsigned int* ciphertext_len) { 254 *ciphertext_len -= 17; 255 }); 256 } 257 258 TEST_F(SelfEncryptTest128, MacWithAESKeyEncrypt) { 259 SelfTest(kKeyName1, aes1_, aes1_, kKeyName1, aes1_, hmac1_, 260 SEC_ERROR_LIBRARY_FAILURE); 261 } 262 263 TEST_F(SelfEncryptTest128, AESWithMacKeyEncrypt) { 264 SelfTest(kKeyName1, hmac1_, hmac1_, kKeyName1, aes1_, hmac1_, 265 SEC_ERROR_INVALID_KEY); 266 } 267 268 TEST_F(SelfEncryptTest128, MacWithAESKeyDecrypt) { 269 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, aes1_, aes1_, 0, 270 SEC_ERROR_LIBRARY_FAILURE); 271 } 272 273 TEST_F(SelfEncryptTest128, AESWithMacKeyDecrypt) { 274 SelfTest(kKeyName1, aes1_, hmac1_, kKeyName1, hmac1_, hmac1_, 0, 275 SEC_ERROR_INVALID_KEY); 276 } 277 278 INSTANTIATE_TEST_SUITE_P(VariousSizes, SelfEncryptTestVariable, 279 ::testing::Values(0, 15, 16, 31, 255, 256, 257)); 280 281 } // namespace nss_test