15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/crypto/null_decrypter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_utils.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_data_reader.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NullDecrypter::NullDecrypter() {}
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool NullDecrypter::SetKey(StringPiece key) { return key.empty(); }
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NullDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return nonce_prefix.empty();
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NullDecrypter::Decrypt(StringPiece /*nonce*/,
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            StringPiece associated_data,
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            StringPiece ciphertext,
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            unsigned char* output,
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            size_t* output_length) {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDataReader reader(ciphertext.data(), ciphertext.length());
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint128 hash;
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!ReadHash(&reader, &hash)) {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringPiece plaintext = reader.ReadRemainingPayload();
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(rch): avoid buffer copy here
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string buffer = associated_data.as_string();
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  plaintext.AppendToString(&buffer);
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (hash != ComputeHash(buffer)) {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memcpy(output, plaintext.data(), plaintext.length());
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *output_length = plaintext.length();
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       StringPiece associated_data,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       StringPiece ciphertext) {
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It's worth duplicating |Decrypt|, above, in order to save a copy by using
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the shared-data QuicData constructor directly.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicDataReader reader(ciphertext.data(), ciphertext.length());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint128 hash;
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!ReadHash(&reader, &hash)) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringPiece plaintext = reader.ReadRemainingPayload();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rch): avoid buffer copy here
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string buffer = associated_data.as_string();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plaintext.AppendToString(&buffer);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (hash != ComputeHash(buffer)) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new QuicData(plaintext.data(), plaintext.length());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)StringPiece NullDecrypter::GetKey() const { return StringPiece(); }
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)StringPiece NullDecrypter::GetNoncePrefix() const { return StringPiece(); }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool NullDecrypter::ReadHash(QuicDataReader* reader, uint128* hash) {
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint64 lo;
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32 hi;
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!reader->ReadUInt64(&lo) ||
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      !reader->ReadUInt32(&hi)) {
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *hash = hi;
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *hash <<= 64;
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *hash += lo;
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)uint128 NullDecrypter::ComputeHash(const string& data) const {
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint128 correct_hash = QuicUtils::FNV1a_128_Hash(data.data(), data.length());
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint128 mask(GG_UINT64_C(0x0), GG_UINT64_C(0xffffffff));
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  mask <<= 96;
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  correct_hash &= ~mask;
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return correct_hash;
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
97