Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(546)

Side by Side Diff: net/base/public_key_hashes_check.go

Issue 9863001: net: move HSTS preloaded and pinning info out of code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/public_key_hashes.h ('k') | net/base/transport_security_state.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 // public_key_hashes_check.go runs tests on public_key_hashes.h. It's not run
6 // automatically, but rather as part of the process of manually updating
7 // public_key_hashes.h
8 //
9 // It verifies that each hash in the file is correct given the preceeding
10 // certificate and that the name of the variable matches the name given in the
11 // certifiate.
12 //
13 // Compile and run with:
14 // % cd net/base
15 // % 6g public_key_hashes_check.go && 6l public_key_hashes_check.6 && ./6.out ./ public_key_hashes.h
16
17 package main
18
19 import (
20 "bufio"
21 "bytes"
22 "crypto/sha1"
23 "crypto/x509"
24 "encoding/base64"
25 "encoding/pem"
26 "errors"
27 "fmt"
28 "io"
29 "os"
30 "strings"
31 )
32
33 const (
34 PRECERT = iota
35 INCERT = iota
36 POSTCERT = iota
37 POSTDECL = iota
38 )
39
40 var newLine = []byte("\n")
41 var startOfCert = []byte("-----BEGIN CERTIFICATE")
42 var endOfCert = []byte("-----END CERTIFICATE")
43 var hashDecl = []byte("static const char kSPKIHash_")
44
45 // matchNames returns true if the given variable name is a reasonable match for
46 // the given CN.
47 func matchNames(name, v string) error {
48 words := strings.Split(name, " ")
49 if len(words) == 0 {
50 return errors.New("No words in certificate name")
51 }
52 firstWord := words[0]
53 if strings.HasSuffix(firstWord, ",") {
54 firstWord = firstWord[:len(firstWord)-1]
55 }
56 if pos := strings.Index(firstWord, "."); pos != -1 {
57 firstWord = firstWord[:pos]
58 }
59 if pos := strings.Index(firstWord, "-"); pos != -1 {
60 firstWord = firstWord[:pos]
61 }
62 if !strings.HasPrefix(v, firstWord) {
63 return errors.New("The first word of the certificate name isn't a prefix of the variable name")
64 }
65
66 for i, word := range words {
67 if word == "Class" && i+1 < len(words) {
68 if strings.Index(v, word+words[i+1]) == -1 {
69 return errors.New("Class specification doesn't a ppear in the variable name")
70 }
71 } else if len(word) == 1 && word[0] >= '0' && word[0] <= '9' {
72 if strings.Index(v, word) == -1 {
73 return errors.New("Number doesn't appear in the variable name")
74 }
75 } else if isImportantWordInCertificateName(word) {
76 if strings.Index(v, word) == -1 {
77 return errors.New(word + " doesn't appear in the variable name")
78 }
79 }
80 }
81
82 return nil
83 }
84
85 // isImportantWordInCertificateName returns true if w must be found in any
86 // corresponding variable name.
87 func isImportantWordInCertificateName(w string) bool {
88 switch w {
89 case "Universal", "Global", "EV", "G1", "G2", "G3", "G4", "G5":
90 return true
91 }
92 return false
93 }
94
95 func main() {
96 if len(os.Args) < 2 {
97 fmt.Fprintf(os.Stderr, "Usage: %s <public_key_hashes.h>\n", os.A rgs[0])
98 return
99 }
100
101 inFile, err := os.Open(os.Args[1])
102 if err != nil {
103 fmt.Fprintf(os.Stderr, "Failed to open input file: %s\n", err.Er ror())
104 return
105 }
106
107 in := bufio.NewReader(inFile)
108 defer inFile.Close()
109
110 lineNo := 0
111 var cert []byte
112 state := PRECERT
113 var x509Cert *x509.Certificate
114 seenHashes := make(map[string]bool)
115
116 for {
117 lineNo++
118 line, isPrefix, err := in.ReadLine()
119 if isPrefix {
120 fmt.Fprintf(os.Stderr, "Line %d is too long to process\n ", lineNo)
121 return
122 }
123 if err == io.EOF {
124 return
125 }
126 if err != nil {
127 fmt.Fprintf(os.Stderr, "Error reading from input: %s\n", err.Error())
128 return
129 }
130
131 switch state {
132 case INCERT:
133 cert = append(cert, line...)
134 cert = append(cert, newLine...)
135 case POSTDECL:
136 trimmed := bytes.TrimSpace(line)
137 if len(trimmed) < 8 || !bytes.HasPrefix(trimmed, []byte( "\"sha1/")) {
138 fmt.Fprintf(os.Stderr, "Line %d is immediately a fter a declation, but failed to find a hash on it\n", lineNo)
139 return
140 }
141 trimmed = trimmed[6 : len(trimmed)-2]
142 h := sha1.New()
143 h.Write(x509Cert.RawSubjectPublicKeyInfo)
144 shouldBe := base64.StdEncoding.EncodeToString(h.Sum(nil) )
145 if shouldBe != string(trimmed) {
146 fmt.Fprintf(os.Stderr, "Line %d: hash should be %s, but found %s\n", lineNo, shouldBe, trimmed)
147 return
148 }
149 if _, ok := seenHashes[shouldBe]; ok {
150 fmt.Fprintf(os.Stderr, "Line %d: duplicated hash \n", lineNo)
151 return
152 }
153 seenHashes[shouldBe] = true
154 state = PRECERT
155 x509Cert = nil
156 }
157
158 if bytes.HasPrefix(line, startOfCert) {
159 switch state {
160 case PRECERT:
161 cert = append(cert, line...)
162 cert = append(cert, newLine...)
163 state = INCERT
164 case INCERT:
165 fmt.Fprintf(os.Stderr, "Found start of certifica te while in certificate at line %d\n", lineNo)
166 return
167 case POSTCERT:
168 fmt.Fprintf(os.Stderr, "Found start of certifica te while while looking for hash at line %d\n", lineNo)
169 return
170 case POSTDECL:
171 fmt.Fprintf(os.Stderr, "Found start of certifica te while while looking for hash string at line %d\n", lineNo)
172 return
173 default:
174 panic("bad state")
175 }
176 } else if bytes.HasPrefix(line, endOfCert) {
177 switch state {
178 case PRECERT:
179 fmt.Fprintf(os.Stderr, "Found end of certificate without certificate at line %d\n", lineNo)
180 return
181 case INCERT:
182 block, _ := pem.Decode(cert)
183 if block == nil {
184 fmt.Fprintf(os.Stderr, "Failed to decode certificate ending on line %d\n", lineNo)
185 return
186 }
187 if x509Cert, err = x509.ParseCertificate(block.B ytes); err != nil {
188 fmt.Fprintf(os.Stderr, "Failed to parse certificate ending on line %d: %s\n", lineNo, err.Error())
189 return
190 }
191 cert = nil
192 state = POSTCERT
193 case POSTCERT:
194 fmt.Fprintf(os.Stderr, "Found end of certificate while while looking for hash at line %d\n", lineNo)
195 return
196 case POSTDECL:
197 fmt.Fprintf(os.Stderr, "Found end of certificate while while looking for hash string at line %d\n", lineNo)
198 return
199 default:
200 panic("bad state")
201 }
202 } else if bytes.HasPrefix(line, hashDecl) {
203 switch state {
204 case PRECERT:
205 // No problem here. Not all declations need a ce rtificate
206 case INCERT:
207 fmt.Fprintf(os.Stderr, "Found declation at line %d, but missed the end of the certificate\n", lineNo)
208 return
209 case POSTCERT:
210 varName := line[len(hashDecl):]
211 for i, c := range varName {
212 if c == '[' {
213 varName = varName[:i]
214 break
215 }
216 }
217 name := x509Cert.Subject.CommonName
218 if len(name) == 0 {
219 name = x509Cert.Subject.Organization[0] + " " + x509Cert.Subject.OrganizationalUnit[0]
220 }
221 if err := matchNames(name, string(varName)); err != nil {
222 fmt.Fprintf(os.Stderr, "Name failure on line %d: %s\n%s -> %s\n", lineNo, err, name, varName)
223 return
224 }
225
226 state = POSTDECL
227 case POSTDECL:
228 fmt.Fprintf(os.Stderr, "Found declation at line %d, but missed the hash value of the previous one\n", lineNo)
229 return
230 default:
231 panic("bad state")
232 }
233 }
234 }
235 }
OLDNEW
« no previous file with comments | « net/base/public_key_hashes.h ('k') | net/base/transport_security_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698