Home | History | Annotate | Download | only in crypto
      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/crypto_secret_boxer.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "crypto/secure_hash.h"
     10 #include "crypto/sha2.h"
     11 #include "net/quic/crypto/quic_random.h"
     12 
     13 using base::StringPiece;
     14 using std::string;
     15 
     16 namespace net {
     17 
     18 // Defined kKeySize for GetKeySize() and SetKey().
     19 static const size_t kKeySize = 16;
     20 
     21 // kBoxNonceSize contains the number of bytes of nonce that we use in each box.
     22 static const size_t kBoxNonceSize = 16;
     23 
     24 // static
     25 size_t CryptoSecretBoxer::GetKeySize() { return kKeySize; }
     26 
     27 void CryptoSecretBoxer::SetKey(StringPiece key) {
     28   DCHECK_EQ(static_cast<size_t>(kKeySize), key.size());
     29   key_ = key.as_string();
     30 }
     31 
     32 // TODO(rtenneti): Delete sha256 based code. Use Aes128Gcm12Encrypter to Box the
     33 // plaintext. This is temporary solution for tests to pass.
     34 string CryptoSecretBoxer::Box(QuicRandom* rand, StringPiece plaintext) const {
     35   string ret;
     36   const size_t len = kBoxNonceSize + plaintext.size() + crypto::kSHA256Length;
     37   ret.resize(len);
     38   char* data = &ret[0];
     39 
     40   // Generate nonce.
     41   rand->RandBytes(data, kBoxNonceSize);
     42   memcpy(data + kBoxNonceSize, plaintext.data(), plaintext.size());
     43 
     44   // Compute sha256 for nonce + plaintext.
     45   scoped_ptr<crypto::SecureHash> sha256(crypto::SecureHash::Create(
     46       crypto::SecureHash::SHA256));
     47   sha256->Update(data, kBoxNonceSize + plaintext.size());
     48   sha256->Finish(data + kBoxNonceSize + plaintext.size(),
     49                  crypto::kSHA256Length);
     50 
     51   return ret;
     52 }
     53 
     54 // TODO(rtenneti): Delete sha256 based code. Use Aes128Gcm12Decrypter to Unbox
     55 // the plaintext. This is temporary solution for tests to pass.
     56 bool CryptoSecretBoxer::Unbox(StringPiece ciphertext,
     57                               string* out_storage,
     58                               StringPiece* out) const {
     59   if (ciphertext.size() < kBoxNonceSize + crypto::kSHA256Length) {
     60     return false;
     61   }
     62 
     63   const size_t plaintext_len =
     64       ciphertext.size() - kBoxNonceSize - crypto::kSHA256Length;
     65   out_storage->resize(plaintext_len);
     66   char* data = const_cast<char*>(out_storage->data());
     67 
     68   // Copy plaintext from ciphertext.
     69   if (plaintext_len != 0) {
     70     memcpy(data, ciphertext.data() + kBoxNonceSize, plaintext_len);
     71   }
     72 
     73   // Compute sha256 for nonce + plaintext.
     74   scoped_ptr<crypto::SecureHash> sha256(crypto::SecureHash::Create(
     75       crypto::SecureHash::SHA256));
     76   sha256->Update(ciphertext.data(), ciphertext.size() - crypto::kSHA256Length);
     77   char sha256_bytes[crypto::kSHA256Length];
     78   sha256->Finish(sha256_bytes, sizeof(sha256_bytes));
     79 
     80   // Verify sha256.
     81   if (0 != memcmp(ciphertext.data() + ciphertext.size() - crypto::kSHA256Length,
     82                   sha256_bytes, crypto::kSHA256Length)) {
     83     return false;
     84   }
     85 
     86   out->set(data, plaintext_len);
     87   return true;
     88 }
     89 
     90 }  // namespace net
     91