1 // Copyright 2016 The Chromium Authors
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/tools/transport_security_state_generator/transport_security_state_entry.h"
6 #include "net/tools/huffman_trie/trie/trie_bit_buffer.h"
7 
8 namespace net::transport_security_state {
9 
10 namespace {
11 
12 // Returns true if the entry only configures HSTS with includeSubdomains.
13 // Such entries, when written, can be represented more compactly, and thus
14 // reduce the overall size of the trie.
IsSimpleEntry(const TransportSecurityStateEntry * entry)15 bool IsSimpleEntry(const TransportSecurityStateEntry* entry) {
16   return entry->force_https && entry->include_subdomains &&
17          entry->pinset.empty();
18 }
19 
20 }  // namespace
21 
22 TransportSecurityStateEntry::TransportSecurityStateEntry() = default;
23 TransportSecurityStateEntry::~TransportSecurityStateEntry() = default;
24 
TransportSecurityStateTrieEntry(const NameIDMap & pinsets_map,TransportSecurityStateEntry * entry)25 TransportSecurityStateTrieEntry::TransportSecurityStateTrieEntry(
26     const NameIDMap& pinsets_map,
27     TransportSecurityStateEntry* entry)
28     : pinsets_map_(pinsets_map), entry_(entry) {}
29 
30 TransportSecurityStateTrieEntry::~TransportSecurityStateTrieEntry() = default;
31 
name() const32 std::string TransportSecurityStateTrieEntry::name() const {
33   return entry_->hostname;
34 }
35 
WriteEntry(huffman_trie::TrieBitBuffer * writer) const36 bool TransportSecurityStateTrieEntry::WriteEntry(
37     huffman_trie::TrieBitBuffer* writer) const {
38   if (IsSimpleEntry(entry_)) {
39     writer->WriteBit(1);
40     return true;
41   } else {
42     writer->WriteBit(0);
43   }
44 
45   uint8_t include_subdomains = 0;
46   if (entry_->include_subdomains) {
47     include_subdomains = 1;
48   }
49   writer->WriteBit(include_subdomains);
50 
51   uint8_t force_https = 0;
52   if (entry_->force_https) {
53     force_https = 1;
54   }
55   writer->WriteBit(force_https);
56 
57   if (entry_->pinset.size()) {
58     writer->WriteBit(1);
59 
60     auto pin_id_it = pinsets_map_.find(entry_->pinset);
61     if (pin_id_it == pinsets_map_.cend()) {
62       return false;
63     }
64 
65     const uint8_t& pin_id = pin_id_it->second;
66     if (pin_id > 15) {
67       return false;
68     }
69 
70     writer->WriteBits(pin_id, 4);
71 
72     if (!entry_->include_subdomains) {
73       uint8_t include_subdomains_for_pinning = 0;
74       if (entry_->hpkp_include_subdomains) {
75         include_subdomains_for_pinning = 1;
76       }
77       writer->WriteBit(include_subdomains_for_pinning);
78     }
79   } else {
80     writer->WriteBit(0);
81   }
82 
83   return true;
84 }
85 
86 }  // namespace net::transport_security_state
87