#!/usr/bin/env python # Copyright 2015 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. import base64 import copy import os import random import subprocess import sys import tempfile def generate(token, s, out_fn): with tempfile.NamedTemporaryFile() as der_tmpfile: with tempfile.NamedTemporaryFile() as conf_tempfile: conf_tempfile.write(str(s)) conf_tempfile.flush() description_tmpfile = tempfile.NamedTemporaryFile() subprocess.check_call(["openssl", "asn1parse", "-genconf", conf_tempfile.name, "-i", "-out", der_tmpfile.name], stdout=description_tmpfile) with open(out_fn, "w") as output_file: description_tmpfile.seek(0) output_file.write(description_tmpfile.read()) output_file.write("-----BEGIN %s-----\n" % token) output_file.write(base64.encodestring(der_tmpfile.read())) output_file.write("-----END %s-----\n" % token) class CertificatePoliciesGenerator: def __init__(self): self.policies = [] def generate(self, out_fn): generate("CERTIFICATE POLICIES", self, out_fn) def add_policy(self, policy): self.policies.append(policy) def __str__(self): s = "asn1 = SEQUENCE:certificatePoliciesSequence\n" s += "[certificatePoliciesSequence]\n" s_suffix = "" for n, policy in enumerate(self.policies): n1, n2 = (str(policy) + "\n").split("\n", 1) if n2: s_suffix += n2 + "\n" s += "%s%s\n" % (n, n1) return s + s_suffix def policy_qualifier(qualifier_id, qualifier): i = random.randint(0, sys.maxint) s = "asn1 = SEQUENCE:PolicyQualifierInfoSequence%i\n" % i s += "[PolicyQualifierInfoSequence%i]\n" % i s += "policyQualifierId = %s\n" % qualifier_id s += qualifier return s def cps_uri_qualifier(url): return policy_qualifier("OID:id-qt-cps", "cPSUri = IA5STRING:%s\n" % url) def policy_information(policy_id, qualifiers): i = random.randint(0, sys.maxint) s = "policyInformation = SEQUENCE:PolicyInformationSequence%i\n" % i s += "[PolicyInformationSequence%i]\n" % i s += "policyIdentifier = OID:%s\n" % policy_id s_suffix = "" if qualifiers is not None: s += "policyQualifiers = SEQUENCE:PolicyQualifiersSequence%i\n" % i s += "[PolicyQualifiersSequence%i]\n" % i for n, qualifier in enumerate(qualifiers): n1, n2 = (str(qualifier) + "\n").split("\n", 1) if n2: s_suffix += n2 + "\n" s += "%s%s\n" % (n, n1) return s + s_suffix def main(): p = CertificatePoliciesGenerator() p.generate("invalid-empty.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("anyPolicy", None)) p.generate("anypolicy.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("anyPolicy", [ cps_uri_qualifier("https://example.com/1_2_3")])) p.generate("anypolicy_with_qualifier.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("anyPolicy", [ policy_qualifier("OID:1.2.3.4", 'foo = UTF8:"hi"')])) p.generate("invalid-anypolicy_with_custom_qualifier.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", None)) p.generate("policy_1_2_3.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", [ cps_uri_qualifier("https://example.com/1_2_3")])) p.generate("policy_1_2_3_with_qualifier.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", [ policy_qualifier("OID:1.2.3.4", 'foo = UTF8:"hi"')])) p.generate("policy_1_2_3_with_custom_qualifier.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", None)) p.add_policy(policy_information("1.2.3", [ cps_uri_qualifier("https://example.com/1_2_3")])) p.generate("invalid-policy_1_2_3_dupe.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", [])) p.generate("invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", None)) p.add_policy(policy_information("1.2.4", None)) p.generate("policy_1_2_3_and_1_2_4.pem") p = CertificatePoliciesGenerator() p.add_policy(policy_information("1.2.3", [ cps_uri_qualifier("https://example.com/1_2_3")])) p.add_policy(policy_information("1.2.4", [ cps_uri_qualifier("http://example.com/1_2_4")])) p.generate("policy_1_2_3_and_1_2_4_with_qualifiers.pem") generate("CERTIFICATE POLICIES", "asn1 = SEQUENCE:certificatePoliciesSequence\n" "[certificatePoliciesSequence]\n" "policyInformation = SEQUENCE:PolicyInformationSequence\n" 'extradata = IA5STRING:"unconsumed data"\n' "[PolicyInformationSequence]\n" "policyIdentifier = OID:1.2.3\n", "invalid-policy_1_2_3_policyinformation_unconsumed_data.pem") generate("CERTIFICATE POLICIES", "asn1 = SEQUENCE:certificatePoliciesSequence\n" "[certificatePoliciesSequence]\n" "policyInformation = SEQUENCE:PolicyInformationSequence\n" "[PolicyInformationSequence]\n" "policyIdentifier = OID:1.2.3\n" "policyQualifiers = SEQUENCE:PolicyQualifiersSequence\n" "[PolicyQualifiersSequence]\n" "policyQualifierInfo = SEQUENCE:PolicyQualifierInfoSequence\n" "[PolicyQualifierInfoSequence]\n" "policyQualifierId = OID:id-qt-cps\n" "cPSUri = IA5STRING:https://example.com/1_2_3\n" 'extradata = IA5STRING:"unconsumed data"\n', "invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem") generate("CERTIFICATE POLICIES", "asn1 = SEQUENCE:certificatePoliciesSequence\n" "[certificatePoliciesSequence]\n" "policyInformation = SEQUENCE:PolicyInformationSequence\n" "[PolicyInformationSequence]\n" 'policyIdentifier = IA5STRING:"1.2.3"\n', "invalid-policy_identifier_not_oid.pem") if __name__ == "__main__": main()