1#!/usr/bin/env python 2# Copyright 2015 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 6import base64 7import copy 8import os 9import random 10import subprocess 11import sys 12import tempfile 13 14 15def generate(token, s, out_fn): 16 with tempfile.NamedTemporaryFile() as der_tmpfile: 17 with tempfile.NamedTemporaryFile() as conf_tempfile: 18 conf_tempfile.write(str(s)) 19 conf_tempfile.flush() 20 description_tmpfile = tempfile.NamedTemporaryFile() 21 subprocess.check_call(["openssl", "asn1parse", "-genconf", 22 conf_tempfile.name, "-i", "-out", 23 der_tmpfile.name], 24 stdout=description_tmpfile) 25 26 with open(out_fn, "w") as output_file: 27 description_tmpfile.seek(0) 28 output_file.write(description_tmpfile.read()) 29 output_file.write("-----BEGIN %s-----\n" % token) 30 output_file.write(base64.encodestring(der_tmpfile.read())) 31 output_file.write("-----END %s-----\n" % token) 32 33 34class CertificatePoliciesGenerator: 35 def __init__(self): 36 self.policies = [] 37 38 def generate(self, out_fn): 39 generate("CERTIFICATE POLICIES", self, out_fn) 40 41 def add_policy(self, policy): 42 self.policies.append(policy) 43 44 def __str__(self): 45 s = "asn1 = SEQUENCE:certificatePoliciesSequence\n" 46 s += "[certificatePoliciesSequence]\n" 47 s_suffix = "" 48 for n, policy in enumerate(self.policies): 49 n1, n2 = (str(policy) + "\n").split("\n", 1) 50 if n2: 51 s_suffix += n2 + "\n" 52 s += "%s%s\n" % (n, n1) 53 54 return s + s_suffix 55 56 57def policy_qualifier(qualifier_id, qualifier): 58 i = random.randint(0, sys.maxint) 59 s = "asn1 = SEQUENCE:PolicyQualifierInfoSequence%i\n" % i 60 s += "[PolicyQualifierInfoSequence%i]\n" % i 61 s += "policyQualifierId = %s\n" % qualifier_id 62 s += qualifier 63 return s 64 65 66def cps_uri_qualifier(url): 67 return policy_qualifier("OID:id-qt-cps", "cPSUri = IA5STRING:%s\n" % url) 68 69 70def policy_information(policy_id, qualifiers): 71 i = random.randint(0, sys.maxint) 72 s = "policyInformation = SEQUENCE:PolicyInformationSequence%i\n" % i 73 s += "[PolicyInformationSequence%i]\n" % i 74 s += "policyIdentifier = OID:%s\n" % policy_id 75 s_suffix = "" 76 if qualifiers is not None: 77 s += "policyQualifiers = SEQUENCE:PolicyQualifiersSequence%i\n" % i 78 s += "[PolicyQualifiersSequence%i]\n" % i 79 for n, qualifier in enumerate(qualifiers): 80 n1, n2 = (str(qualifier) + "\n").split("\n", 1) 81 if n2: 82 s_suffix += n2 + "\n" 83 s += "%s%s\n" % (n, n1) 84 85 return s + s_suffix 86 87 88def main(): 89 p = CertificatePoliciesGenerator() 90 p.generate("invalid-empty.pem") 91 92 p = CertificatePoliciesGenerator() 93 p.add_policy(policy_information("anyPolicy", None)) 94 p.generate("anypolicy.pem") 95 96 p = CertificatePoliciesGenerator() 97 p.add_policy(policy_information("anyPolicy", [ 98 cps_uri_qualifier("https://example.com/1_2_3")])) 99 p.generate("anypolicy_with_qualifier.pem") 100 101 p = CertificatePoliciesGenerator() 102 p.add_policy(policy_information("anyPolicy", [ 103 policy_qualifier("OID:1.2.3.4", 'foo = UTF8:"hi"')])) 104 p.generate("invalid-anypolicy_with_custom_qualifier.pem") 105 106 p = CertificatePoliciesGenerator() 107 p.add_policy(policy_information("1.2.3", None)) 108 p.generate("policy_1_2_3.pem") 109 110 p = CertificatePoliciesGenerator() 111 p.add_policy(policy_information("1.2.3", [ 112 cps_uri_qualifier("https://example.com/1_2_3")])) 113 p.generate("policy_1_2_3_with_qualifier.pem") 114 115 p = CertificatePoliciesGenerator() 116 p.add_policy(policy_information("1.2.3", [ 117 policy_qualifier("OID:1.2.3.4", 'foo = UTF8:"hi"')])) 118 p.generate("policy_1_2_3_with_custom_qualifier.pem") 119 120 p = CertificatePoliciesGenerator() 121 p.add_policy(policy_information("1.2.3", None)) 122 p.add_policy(policy_information("1.2.3", [ 123 cps_uri_qualifier("https://example.com/1_2_3")])) 124 p.generate("invalid-policy_1_2_3_dupe.pem") 125 126 p = CertificatePoliciesGenerator() 127 p.add_policy(policy_information("1.2.3", [])) 128 p.generate("invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem") 129 130 p = CertificatePoliciesGenerator() 131 p.add_policy(policy_information("1.2.3", None)) 132 p.add_policy(policy_information("1.2.4", None)) 133 p.generate("policy_1_2_3_and_1_2_4.pem") 134 135 p = CertificatePoliciesGenerator() 136 p.add_policy(policy_information("1.2.3", [ 137 cps_uri_qualifier("https://example.com/1_2_3")])) 138 p.add_policy(policy_information("1.2.4", [ 139 cps_uri_qualifier("http://example.com/1_2_4")])) 140 p.generate("policy_1_2_3_and_1_2_4_with_qualifiers.pem") 141 142 generate("CERTIFICATE POLICIES", 143 "asn1 = SEQUENCE:certificatePoliciesSequence\n" 144 "[certificatePoliciesSequence]\n" 145 "policyInformation = SEQUENCE:PolicyInformationSequence\n" 146 'extradata = IA5STRING:"unconsumed data"\n' 147 "[PolicyInformationSequence]\n" 148 "policyIdentifier = OID:1.2.3\n", 149 "invalid-policy_1_2_3_policyinformation_unconsumed_data.pem") 150 151 generate("CERTIFICATE POLICIES", 152 "asn1 = SEQUENCE:certificatePoliciesSequence\n" 153 "[certificatePoliciesSequence]\n" 154 "policyInformation = SEQUENCE:PolicyInformationSequence\n" 155 "[PolicyInformationSequence]\n" 156 "policyIdentifier = OID:1.2.3\n" 157 "policyQualifiers = SEQUENCE:PolicyQualifiersSequence\n" 158 "[PolicyQualifiersSequence]\n" 159 "policyQualifierInfo = SEQUENCE:PolicyQualifierInfoSequence\n" 160 "[PolicyQualifierInfoSequence]\n" 161 "policyQualifierId = OID:id-qt-cps\n" 162 "cPSUri = IA5STRING:https://example.com/1_2_3\n" 163 'extradata = IA5STRING:"unconsumed data"\n', 164 "invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem") 165 166 generate("CERTIFICATE POLICIES", 167 "asn1 = SEQUENCE:certificatePoliciesSequence\n" 168 "[certificatePoliciesSequence]\n" 169 "policyInformation = SEQUENCE:PolicyInformationSequence\n" 170 "[PolicyInformationSequence]\n" 171 'policyIdentifier = IA5STRING:"1.2.3"\n', 172 "invalid-policy_identifier_not_oid.pem") 173 174 175if __name__ == "__main__": 176 main() 177