1#!/usr/bin/env python3 2# Copyright 2017 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Generator for a C++ file mapping known trust anchors to histogram values. 7 8The generated structure will be sorted by SHA-256 hash of the 9subjectPublicKeyInfo, to allow efficient lookup. The value '0' is reserved 10as a sentinel value to indicate 'not found'. 11""" 12 13import json 14import os.path 15import platform 16import sys 17from subprocess import call 18 19THIS_DIR = os.path.dirname(os.path.abspath(__file__)) 20SRC_DIR = os.path.normpath(os.path.join(THIS_DIR, '..', '..', '..', '..')) 21 22ROOT_CERT_LIST_PATH = 'net/cert/root_cert_list_generated.h' 23ROOT_STORE_FILE_PATH = 'net/data/ssl/root_stores/root_stores.json' 24 25LICENSE_AND_HEADER = b"""\ 26// Copyright 2017 The Chromium Authors 27// Use of this source code is governed by a BSD-style license that can be 28// found in the LICENSE file. 29// 30// This file is generated by 31// net/data/ssl/root_stores/update_root_stores.py 32// It's formatted by clang-format using Chromium coding style: 33// clang-format -i -style=chromium filename 34// DO NOT EDIT! 35// 36 37#ifndef NET_CERT_ROOT_CERT_LIST_GENERATED_H_ 38#define NET_CERT_ROOT_CERT_LIST_GENERATED_H_ 39 40#include <stdint.h> 41 42namespace net { 43 44namespace { 45 46// The list of known trust anchors, sorted by sha256_spki_hash. 47const struct RootCertData { 48 // The SHA-256 hash of the associated certificate's subjectPublicKeyInfo. 49 unsigned char sha256_spki_hash[32]; 50 51 // A value suitable for histograms using the NetTrustAnchors enum. 52 int16_t histogram_id : 15; 53 54 // If true, indicates the CA is considered a "Legacy" CA, formerly trusted 55 // or not yet trusted. 56 bool legacy_ca : 1; 57} kRootCerts[] = { 58""" 59 60FOOTER = b"""\ 61 62}; 63 64} // namespace 65 66} // namespace net 67 68#endif // NET_CERT_ROOT_CERT_LIST_GENERATED_H_ 69""" 70 71def _GetInputFile(src_relative_file_path): 72 """Converts a src/-relative path into a path that can be opened.""" 73 return os.path.join(SRC_DIR, src_relative_file_path) 74 75def ClangFormat(filename): 76 formatter = 'clang-format' 77 if sys.platform == 'win32': 78 formatter += '.bat' 79 return call([formatter, '-i', '-style=chromium', filename]) 80 81def main(): 82 if len(sys.argv) > 1: 83 print >>sys.stderr, 'No arguments expected!' 84 sys.stderr.write(__doc__) 85 return 1 86 87 with open(_GetInputFile(ROOT_STORE_FILE_PATH), 'r') as root_store_file: 88 root_stores = json.load(root_store_file) 89 90 with open(_GetInputFile(ROOT_CERT_LIST_PATH), 'wb') as header_file: 91 header_file.write(LICENSE_AND_HEADER) 92 for spki, data in sorted(root_stores['spkis'].items()): 93 cpp_str = ''.join('0x{:02X}, '.format(x) for x in bytearray.fromhex(spki)) 94 log_id = int(data['id']) 95 legacy = 'legacy' in data and data['legacy'] 96 header_file.write( 97 ('{ { %s },\n%d, %s }, ' % 98 (cpp_str, log_id, "true" if legacy else "false")).encode('utf-8')) 99 100 header_file.write(FOOTER) 101 102 return ClangFormat(_GetInputFile(ROOT_CERT_LIST_PATH)) 103 104if __name__ == '__main__': 105 sys.exit(main()) 106