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_utils.h"
      6 
      7 #include "crypto/hkdf.h"
      8 #include "net/base/net_util.h"
      9 #include "net/quic/crypto/crypto_handshake.h"
     10 #include "net/quic/crypto/crypto_protocol.h"
     11 #include "net/quic/crypto/quic_decrypter.h"
     12 #include "net/quic/crypto/quic_encrypter.h"
     13 #include "net/quic/crypto/quic_random.h"
     14 #include "net/quic/quic_time.h"
     15 #include "url/url_canon.h"
     16 
     17 using base::StringPiece;
     18 using std::string;
     19 
     20 namespace net {
     21 
     22 // static
     23 void CryptoUtils::GenerateNonce(QuicWallTime now,
     24                                 QuicRandom* random_generator,
     25                                 StringPiece orbit,
     26                                 string* nonce) {
     27   // a 4-byte timestamp + 28 random bytes.
     28   nonce->reserve(kNonceSize);
     29   nonce->resize(kNonceSize);
     30   uint32 gmt_unix_time = now.ToUNIXSeconds();
     31   // The time in the nonce must be encoded in big-endian because the
     32   // strike-register depends on the nonces being ordered by time.
     33   (*nonce)[0] = static_cast<char>(gmt_unix_time >> 24);
     34   (*nonce)[1] = static_cast<char>(gmt_unix_time >> 16);
     35   (*nonce)[2] = static_cast<char>(gmt_unix_time >> 8);
     36   (*nonce)[3] = static_cast<char>(gmt_unix_time);
     37 
     38   size_t bytes_written = sizeof(gmt_unix_time);
     39   if (orbit.size() == 8) {
     40     memcpy(&(*nonce)[bytes_written], orbit.data(), orbit.size());
     41     bytes_written += orbit.size();
     42   }
     43   random_generator->RandBytes(&(*nonce)[bytes_written],
     44                               kNonceSize - bytes_written);
     45 }
     46 
     47 // static
     48 bool CryptoUtils::IsValidSNI(StringPiece sni) {
     49   // TODO(rtenneti): Support RFC2396 hostname.
     50   // NOTE: Microsoft does NOT enforce this spec, so if we throw away hostnames
     51   // based on the above spec, we may be losing some hostnames that windows
     52   // would consider valid. By far the most common hostname character NOT
     53   // accepted by the above spec is '_'.
     54   url::CanonHostInfo host_info;
     55   string canonicalized_host(CanonicalizeHost(sni.as_string(), &host_info));
     56   return !host_info.IsIPAddress() &&
     57       IsCanonicalizedHostCompliant(canonicalized_host, std::string()) &&
     58       sni.find_last_of('.') != string::npos;
     59 }
     60 
     61 // static
     62 string CryptoUtils::NormalizeHostname(const char* hostname) {
     63   url::CanonHostInfo host_info;
     64   string host(CanonicalizeHost(hostname, &host_info));
     65 
     66   // Walk backwards over the string, stopping at the first trailing dot.
     67   size_t host_end = host.length();
     68   while (host_end != 0 && host[host_end - 1] == '.') {
     69     host_end--;
     70   }
     71 
     72   // Erase the trailing dots.
     73   if (host_end != host.length()) {
     74     host.erase(host_end, host.length() - host_end);
     75   }
     76   return host;
     77 }
     78 
     79 // static
     80 bool CryptoUtils::DeriveKeys(StringPiece premaster_secret,
     81                              QuicTag aead,
     82                              StringPiece client_nonce,
     83                              StringPiece server_nonce,
     84                              const string& hkdf_input,
     85                              Perspective perspective,
     86                              CrypterPair* out) {
     87   out->encrypter.reset(QuicEncrypter::Create(aead));
     88   out->decrypter.reset(QuicDecrypter::Create(aead));
     89   size_t key_bytes = out->encrypter->GetKeySize();
     90   size_t nonce_prefix_bytes = out->encrypter->GetNoncePrefixSize();
     91 
     92   StringPiece nonce = client_nonce;
     93   string nonce_storage;
     94   if (!server_nonce.empty()) {
     95     nonce_storage = client_nonce.as_string() + server_nonce.as_string();
     96     nonce = nonce_storage;
     97   }
     98 
     99   crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes,
    100                     nonce_prefix_bytes);
    101   if (perspective == SERVER) {
    102     if (!out->encrypter->SetKey(hkdf.server_write_key()) ||
    103         !out->encrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
    104         !out->decrypter->SetKey(hkdf.client_write_key()) ||
    105         !out->decrypter->SetNoncePrefix(hkdf.client_write_iv())) {
    106       return false;
    107     }
    108   } else {
    109     if (!out->encrypter->SetKey(hkdf.client_write_key()) ||
    110         !out->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
    111         !out->decrypter->SetKey(hkdf.server_write_key()) ||
    112         !out->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
    113       return false;
    114     }
    115   }
    116 
    117   return true;
    118 }
    119 
    120 }  // namespace net
    121