1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/quic/crypto/aes_128_gcm_12_decrypter.h" 6 7#include <nss.h> 8#include <pk11pub.h> 9#include <secerr.h> 10 11#include "base/lazy_instance.h" 12#include "base/memory/scoped_ptr.h" 13#include "crypto/ghash.h" 14#include "crypto/scoped_nss_types.h" 15 16#if defined(USE_NSS) 17#include <dlfcn.h> 18#endif 19 20using base::StringPiece; 21 22namespace net { 23 24namespace { 25 26// The pkcs11t.h header in NSS versions older than 3.14 does not have the CTR 27// and GCM types, so define them here. 28#if !defined(CKM_AES_CTR) 29#define CKM_AES_CTR 0x00001086 30#define CKM_AES_GCM 0x00001087 31 32struct CK_AES_CTR_PARAMS { 33 CK_ULONG ulCounterBits; 34 CK_BYTE cb[16]; 35}; 36 37struct CK_GCM_PARAMS { 38 CK_BYTE_PTR pIv; 39 CK_ULONG ulIvLen; 40 CK_BYTE_PTR pAAD; 41 CK_ULONG ulAADLen; 42 CK_ULONG ulTagBits; 43}; 44#endif // CKM_AES_CTR 45 46typedef SECStatus 47(*PK11_DecryptFunction)( 48 PK11SymKey* symKey, CK_MECHANISM_TYPE mechanism, SECItem* param, 49 unsigned char* out, unsigned int* outLen, unsigned int maxLen, 50 const unsigned char* enc, unsigned encLen); 51 52// On Linux, dynamically link against the system version of libnss3.so. In 53// order to continue working on systems without up-to-date versions of NSS, 54// lookup PK11_Decrypt with dlsym. 55 56// GcmSupportChecker is a singleton which caches the results of runtime symbol 57// resolution of PK11_Decrypt. 58class GcmSupportChecker { 59 public: 60 static PK11_DecryptFunction pk11_decrypt_func() { 61 return pk11_decrypt_func_; 62 } 63 64 static CK_MECHANISM_TYPE aes_key_mechanism() { 65 return aes_key_mechanism_; 66 } 67 68 private: 69 friend struct base::DefaultLazyInstanceTraits<GcmSupportChecker>; 70 71 GcmSupportChecker() { 72#if !defined(USE_NSS) 73 // Using a bundled version of NSS that is guaranteed to have this symbol. 74 pk11_decrypt_func_ = PK11_Decrypt; 75#else 76 // Using system NSS libraries and PCKS #11 modules, which may not have the 77 // necessary function (PK11_Decrypt) or mechanism support (CKM_AES_GCM). 78 79 // If PK11_Decrypt() was successfully resolved, then NSS will support 80 // AES-GCM directly. This was introduced in NSS 3.15. 81 pk11_decrypt_func_ = (PK11_DecryptFunction)dlsym(RTLD_DEFAULT, 82 "PK11_Decrypt"); 83 if (pk11_decrypt_func_ == NULL) { 84 aes_key_mechanism_ = CKM_AES_ECB; 85 } 86#endif 87 } 88 89 // |pk11_decrypt_func_| stores the runtime symbol resolution of PK11_Decrypt. 90 static PK11_DecryptFunction pk11_decrypt_func_; 91 92 // The correct value for |aes_key_mechanism_| is CKM_AES_GCM, but because of 93 // NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=853285 (to be fixed in 94 // NSS 3.15), use CKM_AES_ECB for NSS versions older than 3.15. 95 static CK_MECHANISM_TYPE aes_key_mechanism_; 96}; 97 98// static 99PK11_DecryptFunction GcmSupportChecker::pk11_decrypt_func_ = NULL; 100 101// static 102CK_MECHANISM_TYPE GcmSupportChecker::aes_key_mechanism_ = CKM_AES_GCM; 103 104base::LazyInstance<GcmSupportChecker>::Leaky g_gcm_support_checker = 105 LAZY_INSTANCE_INITIALIZER; 106 107const size_t kKeySize = 16; 108const size_t kNoncePrefixSize = 4; 109const size_t kAESNonceSize = 12; 110 111// Calls PK11_Decrypt if it's available. Otherwise, emulates CKM_AES_GCM using 112// CKM_AES_CTR and the GaloisHash class. 113SECStatus My_Decrypt(PK11SymKey* key, 114 CK_MECHANISM_TYPE mechanism, 115 SECItem* param, 116 unsigned char* out, 117 unsigned int* out_len, 118 unsigned int max_len, 119 const unsigned char* enc, 120 unsigned int enc_len) { 121 // If PK11_Decrypt() was successfully resolved or if bundled version of NSS is 122 // being used, then NSS will support AES-GCM directly. 123 PK11_DecryptFunction pk11_decrypt_func = 124 GcmSupportChecker::pk11_decrypt_func(); 125 if (pk11_decrypt_func != NULL) { 126 return pk11_decrypt_func(key, mechanism, param, out, out_len, max_len, enc, 127 enc_len); 128 } 129 130 // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x 131 // has a bug in the AES GCM code 132 // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing 133 // the PK11_Decrypt function 134 // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are 135 // resolved in NSS 3.15. 136 137 DCHECK_EQ(mechanism, static_cast<CK_MECHANISM_TYPE>(CKM_AES_GCM)); 138 DCHECK_EQ(param->len, sizeof(CK_GCM_PARAMS)); 139 140 const CK_GCM_PARAMS* gcm_params = 141 reinterpret_cast<CK_GCM_PARAMS*>(param->data); 142 143 DCHECK_EQ(gcm_params->ulTagBits, 144 static_cast<CK_ULONG>(Aes128Gcm12Decrypter::kAuthTagSize * 8)); 145 if (gcm_params->ulIvLen != 12u) { 146 DLOG(INFO) << "ulIvLen is not equal to 12"; 147 PORT_SetError(SEC_ERROR_INPUT_LEN); 148 return SECFailure; 149 } 150 151 SECItem my_param = { siBuffer, NULL, 0 }; 152 153 // Step 2. Let H = CIPH_K(128 '0' bits). 154 unsigned char ghash_key[16] = {0}; 155 crypto::ScopedPK11Context ctx(PK11_CreateContextBySymKey( 156 CKM_AES_ECB, CKA_ENCRYPT, key, &my_param)); 157 if (!ctx) { 158 DLOG(INFO) << "PK11_CreateContextBySymKey failed"; 159 return SECFailure; 160 } 161 int output_len; 162 if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key), 163 ghash_key, sizeof(ghash_key)) != SECSuccess) { 164 DLOG(INFO) << "PK11_CipherOp failed"; 165 return SECFailure; 166 } 167 168 PK11_Finalize(ctx.get()); 169 170 if (output_len != sizeof(ghash_key)) { 171 DLOG(INFO) << "Wrong output length"; 172 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 173 return SECFailure; 174 } 175 176 // Step 3. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1. 177 CK_AES_CTR_PARAMS ctr_params = {0}; 178 ctr_params.ulCounterBits = 32; 179 memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen); 180 ctr_params.cb[12] = 0; 181 ctr_params.cb[13] = 0; 182 ctr_params.cb[14] = 0; 183 ctr_params.cb[15] = 1; 184 185 my_param.type = siBuffer; 186 my_param.data = reinterpret_cast<unsigned char*>(&ctr_params); 187 my_param.len = sizeof(ctr_params); 188 189 ctx.reset(PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, 190 &my_param)); 191 if (!ctx) { 192 DLOG(INFO) << "PK11_CreateContextBySymKey failed"; 193 return SECFailure; 194 } 195 196 // Step 6. Calculate the encryption mask of GCTR_K(J0, ...). 197 unsigned char tag_mask[16] = {0}; 198 if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask), 199 tag_mask, sizeof(tag_mask)) != SECSuccess) { 200 DLOG(INFO) << "PK11_CipherOp failed"; 201 return SECFailure; 202 } 203 if (output_len != sizeof(tag_mask)) { 204 DLOG(INFO) << "Wrong output length"; 205 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 206 return SECFailure; 207 } 208 209 if (enc_len < Aes128Gcm12Decrypter::kAuthTagSize) { 210 PORT_SetError(SEC_ERROR_INPUT_LEN); 211 return SECFailure; 212 } 213 214 // The const_cast for |enc| can be removed if system NSS libraries are 215 // NSS 3.14.1 or later (NSS bug 216 // https://bugzilla.mozilla.org/show_bug.cgi?id=808218). 217 if (PK11_CipherOp(ctx.get(), out, &output_len, max_len, 218 const_cast<unsigned char*>(enc), 219 enc_len - Aes128Gcm12Decrypter::kAuthTagSize) != SECSuccess) { 220 DLOG(INFO) << "PK11_CipherOp failed"; 221 return SECFailure; 222 } 223 224 PK11_Finalize(ctx.get()); 225 226 if (static_cast<unsigned int>(output_len) != 227 enc_len - Aes128Gcm12Decrypter::kAuthTagSize) { 228 DLOG(INFO) << "Wrong output length"; 229 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 230 return SECFailure; 231 } 232 233 crypto::GaloisHash ghash(ghash_key); 234 ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen); 235 ghash.UpdateCiphertext(enc, output_len); 236 unsigned char auth_tag[Aes128Gcm12Decrypter::kAuthTagSize]; 237 ghash.Finish(auth_tag, Aes128Gcm12Decrypter::kAuthTagSize); 238 for (unsigned int i = 0; i < Aes128Gcm12Decrypter::kAuthTagSize; i++) { 239 auth_tag[i] ^= tag_mask[i]; 240 } 241 242 if (NSS_SecureMemcmp(auth_tag, enc + output_len, 243 Aes128Gcm12Decrypter::kAuthTagSize) != 0) { 244 PORT_SetError(SEC_ERROR_BAD_DATA); 245 return SECFailure; 246 } 247 248 *out_len = output_len; 249 return SECSuccess; 250} 251 252} // namespace 253 254Aes128Gcm12Decrypter::Aes128Gcm12Decrypter() { 255 ignore_result(g_gcm_support_checker.Get()); 256} 257 258Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {} 259 260// static 261bool Aes128Gcm12Decrypter::IsSupported() { 262 // NSS 3.15 supports CKM_AES_GCM directly. 263 // NSS 3.14 supports CKM_AES_CTR, which can be used to emulate CKM_AES_GCM. 264 // Versions earlier than NSS 3.14 are not supported. 265 return NSS_VersionCheck("3.14") != PR_FALSE; 266} 267 268bool Aes128Gcm12Decrypter::SetKey(StringPiece key) { 269 DCHECK_EQ(key.size(), sizeof(key_)); 270 if (key.size() != sizeof(key_)) { 271 return false; 272 } 273 memcpy(key_, key.data(), key.size()); 274 return true; 275} 276 277bool Aes128Gcm12Decrypter::SetNoncePrefix(StringPiece nonce_prefix) { 278 DCHECK_EQ(nonce_prefix.size(), kNoncePrefixSize); 279 if (nonce_prefix.size() != kNoncePrefixSize) { 280 return false; 281 } 282 COMPILE_ASSERT(sizeof(nonce_prefix_) == kNoncePrefixSize, bad_nonce_length); 283 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); 284 return true; 285} 286 287bool Aes128Gcm12Decrypter::Decrypt(StringPiece nonce, 288 StringPiece associated_data, 289 StringPiece ciphertext, 290 uint8* output, 291 size_t* output_length) { 292 if (ciphertext.length() < kAuthTagSize || 293 nonce.size() != kNoncePrefixSize + sizeof(QuicPacketSequenceNumber)) { 294 return false; 295 } 296 // NSS 3.14.x incorrectly requires an output buffer at least as long as 297 // the ciphertext (NSS bug 298 // https://bugzilla.mozilla.org/show_bug.cgi?id= 853674). Fortunately 299 // QuicDecrypter::Decrypt() specifies that |output| must be as long as 300 // |ciphertext| on entry. 301 size_t plaintext_size = ciphertext.length() - kAuthTagSize; 302 303 // Import key_ into NSS. 304 SECItem key_item; 305 key_item.type = siBuffer; 306 key_item.data = key_; 307 key_item.len = sizeof(key_); 308 PK11SlotInfo* slot = PK11_GetInternalSlot(); 309 // The exact value of the |origin| argument doesn't matter to NSS as long as 310 // it's not PK11_OriginFortezzaHack, so pass PK11_OriginUnwrap as a 311 // placeholder. 312 crypto::ScopedPK11SymKey aes_key(PK11_ImportSymKey( 313 slot, GcmSupportChecker::aes_key_mechanism(), PK11_OriginUnwrap, 314 CKA_DECRYPT, &key_item, NULL)); 315 PK11_FreeSlot(slot); 316 slot = NULL; 317 if (!aes_key) { 318 DLOG(INFO) << "PK11_ImportSymKey failed"; 319 return false; 320 } 321 322 CK_GCM_PARAMS gcm_params = {0}; 323 gcm_params.pIv = 324 reinterpret_cast<CK_BYTE*>(const_cast<char*>(nonce.data())); 325 gcm_params.ulIvLen = nonce.size(); 326 gcm_params.pAAD = 327 reinterpret_cast<CK_BYTE*>(const_cast<char*>(associated_data.data())); 328 gcm_params.ulAADLen = associated_data.size(); 329 gcm_params.ulTagBits = kAuthTagSize * 8; 330 331 SECItem param; 332 param.type = siBuffer; 333 param.data = reinterpret_cast<unsigned char*>(&gcm_params); 334 param.len = sizeof(gcm_params); 335 336 unsigned int output_len; 337 // If an incorrect authentication tag causes a decryption failure, the NSS 338 // error is SEC_ERROR_BAD_DATA (-8190). 339 if (My_Decrypt(aes_key.get(), CKM_AES_GCM, ¶m, 340 output, &output_len, ciphertext.length(), 341 reinterpret_cast<const unsigned char*>(ciphertext.data()), 342 ciphertext.length()) != SECSuccess) { 343 DLOG(INFO) << "My_Decrypt failed: NSS error " << PORT_GetError(); 344 return false; 345 } 346 347 if (output_len != plaintext_size) { 348 DLOG(INFO) << "Wrong output length"; 349 return false; 350 } 351 *output_length = output_len; 352 return true; 353} 354 355QuicData* Aes128Gcm12Decrypter::DecryptPacket( 356 QuicPacketSequenceNumber sequence_number, 357 StringPiece associated_data, 358 StringPiece ciphertext) { 359 if (ciphertext.length() < kAuthTagSize) { 360 return NULL; 361 } 362 size_t plaintext_size; 363 scoped_ptr<char[]> plaintext(new char[ciphertext.length()]); 364 365 uint8 nonce[kNoncePrefixSize + sizeof(sequence_number)]; 366 COMPILE_ASSERT(sizeof(nonce) == kAESNonceSize, bad_sequence_number_size); 367 memcpy(nonce, nonce_prefix_, kNoncePrefixSize); 368 memcpy(nonce + kNoncePrefixSize, &sequence_number, sizeof(sequence_number)); 369 if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), sizeof(nonce)), 370 associated_data, ciphertext, 371 reinterpret_cast<uint8*>(plaintext.get()), 372 &plaintext_size)) { 373 return NULL; 374 } 375 return new QuicData(plaintext.release(), plaintext_size, true); 376} 377 378StringPiece Aes128Gcm12Decrypter::GetKey() const { 379 return StringPiece(reinterpret_cast<const char*>(key_), sizeof(key_)); 380} 381 382StringPiece Aes128Gcm12Decrypter::GetNoncePrefix() const { 383 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), 384 kNoncePrefixSize); 385} 386 387} // namespace net 388