summaryrefslogtreecommitdiffstats
path: root/net/base/dnssec_chain_verifier.h
blob: 9fa80b8761ee7f63a954c04637aae0253b979fee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2011 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.

#ifndef NET_BASE_DNSSEC_CHAIN_VERIFIER_H_
#define NET_BASE_DNSSEC_CHAIN_VERIFIER_H_

#include <map>
#include <string>
#include <vector>

#include "base/string_piece.h"
#include "net/base/net_export.h"

namespace net {

// DNSSECChainVerifier verifies a chain of DNSSEC records. These records
// eventually prove the validity of a set of resource records for the target
// name. For example, if the fingerprint of a certificate was stored in a CERT
// record for a given domain, then a chain could prove the validity of that
// fingerprint.
class NET_EXPORT_PRIVATE DNSSECChainVerifier {
 public:
  enum Error {
    OK = 0,
    BAD_DATA,  // The chain was corrupt in some fashion.
    UNKNOWN_ROOT_KEY,  // The chain is assuming an unknown DNS root.
    UNKNOWN_DIGEST,  // An omitted DS record used an unknown hash function.
    UNKNOWN_TERMINAL_RRTYPE,  // The chain proved an unknown RRTYPE.
    BAD_SIGNATURE,  // One of the signature was incorrect.
    NO_DS_LINK,  // a DS set didn't include the next entry key.
    OFF_COURSE,  // the chain is diverging from the target name.
    BAD_TARGET,  // the chain didn't end up at the target.
  };

  // |target|: the target hostname. This must be in canonical (all
  //     lower-case), length-prefixed DNS form. For example:
  //     "\003www\007example\003com\000"
  // |chain|: the contents of the chain.
  DNSSECChainVerifier(const std::string& target,
                      const base::StringPiece& chain);
  ~DNSSECChainVerifier();

  // If called, timestamps in the signatures will be ignored. This is for
  // testing only.
  void IgnoreTimestamps();

  // Verify verifies the chain. Returns |OK| on success.
  Error Verify();

  // rrtype returns the RRTYPE of the proven resource records. Only call this
  // after Verify has returned OK.
  uint16 rrtype() const;
  // rrdatas returns the contents of the proven resource records. Only call
  // this after Verify has returned OK.
  const std::vector<base::StringPiece>& rrdatas() const;

  // Exposed for testing only.
  static unsigned MatchingLabels(base::StringPiece a,
                                 base::StringPiece b);

 private:
  struct Zone;

  bool U8(uint8*);
  bool U16(uint16*);
  bool VariableLength16(base::StringPiece*);
  bool ReadName(base::StringPiece*);

  bool ReadAheadEntryKey(base::StringPiece*);
  bool ReadAheadKey(base::StringPiece*, uint8 entry_key);
  bool ReadDNSKEYs(std::vector<base::StringPiece>*, bool is_root);
  bool DigestKey(base::StringPiece* digest,
                 const base::StringPiece& name,
                 const base::StringPiece& dnskey,
                 uint8 digest_type,
                 uint16 keyid,
                 uint8 algorithm);

  Error EnterRoot();
  Error EnterZone(const base::StringPiece& zone);
  Error LeaveZone(base::StringPiece* next_name);
  Error ReadDSSet(std::vector<base::StringPiece>*,
                  const base::StringPiece& next_name);
  Error ReadGenericRRs(std::vector<base::StringPiece>*);
  Error ReadCNAME(std::vector<base::StringPiece>*);

  Zone* current_zone_;
  std::string target_;
  base::StringPiece chain_;
  bool ignore_timestamps_;
  bool valid_;
  // already_entered_zone_ is set to true when we unwind a Zone chain and start
  // off from a point where we have already entered a zone.
  bool already_entered_zone_;
  uint16 rrtype_;
  std::vector<base::StringPiece> rrdatas_;
  // A list of pointers which need to be free()ed on destruction.
  std::vector<void*> scratch_pool_;
};

// DnsCAARecord encapsulates code and types for dealing with Certificate
// Authority Authorization records. These are DNS records which can express
// limitations regarding acceptable certificates for a domain. See
// http://tools.ietf.org/html/draft-hallambaker-donotissue-04
class NET_EXPORT_PRIVATE DnsCAARecord {
 public:
  enum ParseResult {
    SUCCESS,  // parse successful.
    DISCARD,  // no policies applying to this client were found.
    SYNTAX_ERROR,  // the record was syntactically invalid.
    UNKNOWN_CRITICAL,  // a critical record was not understood.
  };

  // A CAAPolicy is the result of parsing a set of CAA records. It describes a
  // number of properies of certificates in a chain, any of which is sufficient
  // to validate the chain.
  struct NET_EXPORT_PRIVATE Policy {
   public:
    Policy();
    ~Policy();

    // A HashTarget identifies the object that we are hashing.
    enum HashTarget {
      USER_CERTIFICATE,
      CA_CERTIFICATE,
      SUBJECT_PUBLIC_KEY_INFO,
    };

    // A Hash is a digest of some property of a certificate.
    struct Hash {
      HashTarget target;  // what do we hash?
      int algorithm;  // NSS value, i.e. HASH_AlgSHA1.
      std::string data;  // digest, i.e. 20 bytes for SHA1.
      unsigned port;  // port number or 0 for any.
    };

    std::vector<Hash> authorized_hashes;
  };

  // Parse parses a series of DNS resource records and sets |output| to the
  // result.
  static ParseResult Parse(const std::vector<base::StringPiece>& rrdatas,
                           Policy* output);
};

}  // namespace net

#endif  // NET_BASE_DNSSEC_CHAIN_VERIFIER_H_