1#!/usr/bin/env python 2# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- 3# vim: set filetype=python 4 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9# This file generates the certspec files for test_cert_version.js. The naming 10# convention for those files is generally of the form 11# "<subject-description>_<issuer-description>.pem.certspec". End-entity 12# certificates are generally called "ee". Intermediates are called 13# "int". The root CA is called "ca" and self-signed certificates are called 14# "ss". 15# In the case that the subject and issuer are the same, the redundant part is 16# not repeated. 17# If there is nothing particularly special about a certificate, it has no 18# description ("nothing particularly special" meaning the certificate is X509v3 19# and has or does not have the basic constraints extension as expected by where 20# it is in the hierarchy). Otherwise, the description includes its version and 21# details about the extension. If the extension is not present, the string 22# "noBC" is used. If it is present but the cA bit is not asserted, the string 23# "BC-not-cA" is used. If it is present with the cA bit asserted, the string 24# "BC-cA" is used. 25# For example, a v1 intermediate that does not have the extension that was 26# issued by the root CA has the name "int-v1-noBC_ca.pem.certspec". 27# A v4 end-entity that does have the extension but does not assert the cA bit 28# that was issued by the root CA has the name 29# "ee-v4-BC-not-cA_ca.pem.certspec". 30# An end-entity issued by a v3 intermediate with the extension that asserts the 31# cA bit has the name "ee_int-v3-BC-cA.pem.certspec". 32 33versions = { 34 'v1': 1, 35 'v2': 2, 36 'v3': 3, 37 'v4': 4 38} 39 40basicConstraintsTypes = { 41 'noBC': '', 42 'BC-not-cA': 'extension:basicConstraints:,', 43 'BC-cA': 'extension:basicConstraints:cA,' 44} 45 46def writeCertspec(issuer, subject, fields): 47 filename = '%s_%s.pem.certspec' % (subject, issuer) 48 if issuer == subject: 49 filename = '%s.pem.certspec' % subject 50 with open(filename, 'w') as f: 51 f.write('issuer:%s\n' % issuer) 52 f.write('subject:%s\n' % subject) 53 for field in fields: 54 if len(field) > 0: 55 f.write('%s\n' % field) 56 57 58keyUsage = 'extension:keyUsage:keyCertSign,cRLSign' 59basicConstraintsCA = 'extension:basicConstraints:cA,' 60 61writeCertspec('ca', 'ca', [keyUsage, basicConstraintsCA]) 62 63for versionStr, versionVal in versions.iteritems(): 64 # intermediates 65 versionText = 'version:%s' % versionVal 66 for basicConstraintsType, basicConstraintsExtension in basicConstraintsTypes.iteritems(): 67 intermediateName = 'int-%s-%s' % (versionStr, basicConstraintsType) 68 writeCertspec('ca', intermediateName, 69 [keyUsage, versionText, basicConstraintsExtension]) 70 writeCertspec(intermediateName, 'ee', []) 71 72 # end-entities 73 versionText = 'version:%s' % versionVal 74 for basicConstraintsType, basicConstraintsExtension in basicConstraintsTypes.iteritems(): 75 writeCertspec('ca', 'ee-%s-%s' % (versionStr, basicConstraintsType), 76 [versionText, basicConstraintsExtension]) 77 78 # self-signed certificates 79 versionText = 'version:%s' % versionVal 80 for basicConstraintsType, basicConstraintsExtension in basicConstraintsTypes.iteritems(): 81 selfSignedName = 'ss-%s-%s' % (versionStr, basicConstraintsType) 82 writeCertspec(selfSignedName, selfSignedName, 83 [versionText, basicConstraintsExtension]) 84