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