1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/quic/crypto/aead_base_decrypter.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <pk11pub.h> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "crypto/scoped_nss_types.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::StringPiece; 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace net { 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AeadBaseDecrypter::AeadBaseDecrypter(CK_MECHANISM_TYPE aead_mechanism, 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PK11_DecryptFunction pk11_decrypt, 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t key_size, 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t auth_tag_size, 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t nonce_prefix_size) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : aead_mechanism_(aead_mechanism), 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pk11_decrypt_(pk11_decrypt), 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_size_(key_size), 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) auth_tag_size_(auth_tag_size), 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) nonce_prefix_size_(nonce_prefix_size) { 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_LE(key_size_, sizeof(key_)); 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_)); 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AeadBaseDecrypter::~AeadBaseDecrypter() {} 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AeadBaseDecrypter::SetKey(StringPiece key) { 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(key.size(), key_size_); 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (key.size() != key_size_) { 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(key_, key.data(), key.size()); 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AeadBaseDecrypter::SetNoncePrefix(StringPiece nonce_prefix) { 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_); 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (nonce_prefix.size() != nonce_prefix_size_) { 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AeadBaseDecrypter::Decrypt(StringPiece nonce, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StringPiece associated_data, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StringPiece ciphertext, 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8* output, 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t* output_length) { 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ciphertext.length() < auth_tag_size_ || 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) { 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // NSS 3.14.x incorrectly requires an output buffer at least as long as 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the ciphertext (NSS bug 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // https://bugzilla.mozilla.org/show_bug.cgi?id= 853674). Fortunately 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // QuicDecrypter::Decrypt() specifies that |output| must be as long as 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |ciphertext| on entry. 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t plaintext_size = ciphertext.length() - auth_tag_size_; 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Import key_ into NSS. 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SECItem key_item; 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_item.type = siBuffer; 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_item.data = key_; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_item.len = key_size_; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PK11SlotInfo* slot = PK11_GetInternalSlot(); 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(wtc): For an AES-GCM key, the correct value for |key_mechanism| is 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // CKM_AES_GCM, but because of NSS bug 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // https://bugzilla.mozilla.org/show_bug.cgi?id=853285, use CKM_AES_ECB as a 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // workaround. Remove this when we require NSS 3.15. 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CK_MECHANISM_TYPE key_mechanism = aead_mechanism_; 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (key_mechanism == CKM_AES_GCM) { 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_mechanism = CKM_AES_ECB; 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The exact value of the |origin| argument doesn't matter to NSS as long as 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // it's not PK11_OriginFortezzaHack, so pass PK11_OriginUnwrap as a 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // placeholder. 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) crypto::ScopedPK11SymKey aead_key(PK11_ImportSymKey( 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) slot, key_mechanism, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL)); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PK11_FreeSlot(slot); 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) slot = NULL; 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!aead_key) { 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "PK11_ImportSymKey failed"; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AeadParams aead_params = {0}; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FillAeadParams(nonce, associated_data, auth_tag_size_, &aead_params); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SECItem param; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) param.type = siBuffer; 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) param.data = reinterpret_cast<unsigned char*>(&aead_params.data); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) param.len = aead_params.len; 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) unsigned int output_len; 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (pk11_decrypt_(aead_key.get(), aead_mechanism_, ¶m, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) output, &output_len, ciphertext.length(), 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<const unsigned char*>(ciphertext.data()), 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ciphertext.length()) != SECSuccess) { 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (output_len != plaintext_size) { 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << "Wrong output length"; 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *output_length = output_len; 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicData* AeadBaseDecrypter::DecryptPacket( 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) QuicPacketSequenceNumber sequence_number, 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StringPiece associated_data, 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StringPiece ciphertext) { 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ciphertext.length() < auth_tag_size_) { 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t plaintext_size; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<char[]> plaintext(new char[ciphertext.length()]); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_LE(nonce_size, sizeof(nonce)); 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(nonce, nonce_prefix_, nonce_prefix_size_); 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) associated_data, ciphertext, 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<uint8*>(plaintext.get()), 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &plaintext_size)) { 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new QuicData(plaintext.release(), plaintext_size, true); 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)StringPiece AeadBaseDecrypter::GetKey() const { 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return StringPiece(reinterpret_cast<const char*>(key_), key_size_); 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)StringPiece AeadBaseDecrypter::GetNoncePrefix() const { 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (nonce_prefix_size_ == 0) { 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return StringPiece(); 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) nonce_prefix_size_); 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace net 155