普通文本  |  91行  |  2.9 KB

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/crypto/crypto_secret_boxer.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "net/quic/crypto/quic_random.h"

using base::StringPiece;
using std::string;

namespace net {

// Defined kKeySize for GetKeySize() and SetKey().
static const size_t kKeySize = 16;

// kBoxNonceSize contains the number of bytes of nonce that we use in each box.
static const size_t kBoxNonceSize = 16;

// static
size_t CryptoSecretBoxer::GetKeySize() { return kKeySize; }

void CryptoSecretBoxer::SetKey(StringPiece key) {
  DCHECK_EQ(static_cast<size_t>(kKeySize), key.size());
  key_ = key.as_string();
}

// TODO(rtenneti): Delete sha256 based code. Use Aes128Gcm12Encrypter to Box the
// plaintext. This is temporary solution for tests to pass.
string CryptoSecretBoxer::Box(QuicRandom* rand, StringPiece plaintext) const {
  string ret;
  const size_t len = kBoxNonceSize + plaintext.size() + crypto::kSHA256Length;
  ret.resize(len);
  char* data = &ret[0];

  // Generate nonce.
  rand->RandBytes(data, kBoxNonceSize);
  memcpy(data + kBoxNonceSize, plaintext.data(), plaintext.size());

  // Compute sha256 for nonce + plaintext.
  scoped_ptr<crypto::SecureHash> sha256(crypto::SecureHash::Create(
      crypto::SecureHash::SHA256));
  sha256->Update(data, kBoxNonceSize + plaintext.size());
  sha256->Finish(data + kBoxNonceSize + plaintext.size(),
                 crypto::kSHA256Length);

  return ret;
}

// TODO(rtenneti): Delete sha256 based code. Use Aes128Gcm12Decrypter to Unbox
// the plaintext. This is temporary solution for tests to pass.
bool CryptoSecretBoxer::Unbox(StringPiece ciphertext,
                              string* out_storage,
                              StringPiece* out) const {
  if (ciphertext.size() < kBoxNonceSize + crypto::kSHA256Length) {
    return false;
  }

  const size_t plaintext_len =
      ciphertext.size() - kBoxNonceSize - crypto::kSHA256Length;
  out_storage->resize(plaintext_len);
  char* data = const_cast<char*>(out_storage->data());

  // Copy plaintext from ciphertext.
  if (plaintext_len != 0) {
    memcpy(data, ciphertext.data() + kBoxNonceSize, plaintext_len);
  }

  // Compute sha256 for nonce + plaintext.
  scoped_ptr<crypto::SecureHash> sha256(crypto::SecureHash::Create(
      crypto::SecureHash::SHA256));
  sha256->Update(ciphertext.data(), ciphertext.size() - crypto::kSHA256Length);
  char sha256_bytes[crypto::kSHA256Length];
  sha256->Finish(sha256_bytes, sizeof(sha256_bytes));

  // Verify sha256.
  if (0 != memcmp(ciphertext.data() + ciphertext.size() - crypto::kSHA256Length,
                  sha256_bytes, crypto::kSHA256Length)) {
    return false;
  }

  out->set(data, plaintext_len);
  return true;
}

}  // namespace net