2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
17 def add_attr(self
, attr_type
, attr_value_type
, attr_value
,
19 self
.attrs
.append((attr_type
, attr_value_type
, attr_value
, attr_modifier
))
24 for n
, attr
in enumerate(self
.attrs
):
25 s
+= 'attrTypeAndValue%i=SEQUENCE:attrTypeAndValueSequence%i_%i\n' % (
29 for n
, attr
in enumerate(self
.attrs
):
30 attr_type
, attr_value_type
, attr_value
, attr_modifier
= attr
31 s
+= '[attrTypeAndValueSequence%i_%i]\n' % (id(self
), n
)
32 # Note the quotes around the string value here, which is necessary for
33 # trailing whitespace to be included by openssl.
34 s
+= 'type=OID:%s\n' % attr_type
37 s
+= attr_modifier
+ ','
38 s
+= '%s:"%s"\n' % (attr_value_type
, attr_value
)
53 s
= 'asn1 = SEQUENCE:rdnSequence\n\n[rdnSequence]\n'
54 for n
, rdn
in enumerate(self
.rdns
):
55 s
+= 'rdn%i = SET:rdnSet%i\n' % (n
, n
)
59 for n
, rdn
in enumerate(self
.rdns
):
60 s
+= '[rdnSet%i]\n%s\n' % (n
, rdn
)
66 out_fn
= os
.path
.join('..', 'names', fn
+ '.pem')
67 conf_tempfile
= tempfile
.NamedTemporaryFile()
68 conf_tempfile
.write(str(s
))
70 der_tmpfile
= tempfile
.NamedTemporaryFile()
71 description_tmpfile
= tempfile
.NamedTemporaryFile()
72 subprocess
.check_call(['openssl', 'asn1parse', '-genconf', conf_tempfile
.name
,
73 '-i', '-out', der_tmpfile
.name
],
74 stdout
=description_tmpfile
)
77 output_file
= open(out_fn
, 'w')
78 description_tmpfile
.seek(0)
79 output_file
.write(description_tmpfile
.read())
80 output_file
.write('-----BEGIN NAME-----\n')
81 output_file
.write(base64
.encodestring(der_tmpfile
.read()))
82 output_file
.write('-----END NAME-----\n')
90 def extra_whitespace(s
):
91 return ' ' + s
.replace(' ', ' ') + ' '
99 for valuetype
in ('PRINTABLESTRING', 'T61STRING', 'UTF8', 'BMPSTRING',
101 for string_mangler
in (unmangled
, extra_whitespace
, case_swap
):
103 n
.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'US')
104 n
.add_rdn().add_attr('stateOrProvinceName',
106 string_mangler('New York'))
107 n
.add_rdn().add_attr('localityName',
109 string_mangler("ABCDEFGHIJKLMNOPQRSTUVWXYZ "
110 "abcdefghijklmnopqrstuvwxyz "
111 "0123456789 '()+,-./:=?"))
113 n_extra_attr
= copy
.deepcopy(n
)
114 n_extra_attr
.rdns
[-1].add_attr('organizationName',
116 string_mangler('Name of company'))
118 n_extra_rdn
= copy
.deepcopy(n
)
119 n_extra_rdn
.add_rdn().add_attr('organizationName',
121 string_mangler('Name of company'))
123 filename_base
= 'ascii-' + valuetype
+ '-' + string_mangler
.__name
__
125 generate(n
, filename_base
)
126 generate(n_extra_attr
, filename_base
+ '-extra_attr')
127 generate(n_extra_rdn
, filename_base
+ '-extra_rdn')
129 for valuetype
in ('UTF8', 'BMPSTRING', 'UNIVERSALSTRING'):
131 n
.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
132 n
.add_rdn().add_attr('localityName',
134 "\xe6\x9d\xb1\xe4\xba\xac",
137 filename_base
= 'unicode_bmp-' + valuetype
+ '-' + 'unmangled'
138 generate(n
, filename_base
)
140 for valuetype
in ('UTF8', 'UNIVERSALSTRING'):
142 n
.add_rdn().add_attr('countryName', 'PRINTABLESTRING', 'JP')
143 n
.add_rdn().add_attr('localityName',
145 "\xf0\x9d\x90\x80\xf0\x9d\x90\x99",
148 filename_base
= 'unicode_supplementary-' + valuetype
+ '-' + 'unmangled'
149 generate(n
, filename_base
)
151 generate("""asn1 = SEQUENCE:rdnSequence
155 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
156 [attrTypeAndValueSequence0_0]
158 value=PRINTABLESTRING:"US"
159 extra=PRINTABLESTRING:"hello world"
160 """, "invalid-AttributeTypeAndValue-extradata")
162 generate("""asn1 = SEQUENCE:rdnSequence
166 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
167 [attrTypeAndValueSequence0_0]
169 """, "invalid-AttributeTypeAndValue-onlyOneElement")
171 generate("""asn1 = SEQUENCE:rdnSequence
175 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
176 [attrTypeAndValueSequence0_0]
177 """, "invalid-AttributeTypeAndValue-empty")
179 generate("""asn1 = SEQUENCE:rdnSequence
183 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
184 [attrTypeAndValueSequence0_0]
185 type=PRINTABLESTRING:"hello world"
186 value=PRINTABLESTRING:"US"
187 """, "invalid-AttributeTypeAndValue-badAttributeType")
189 generate("""asn1 = SEQUENCE:rdnSequence
193 attrTypeAndValue0=SET:attrTypeAndValueSequence0_0
194 [attrTypeAndValueSequence0_0]
196 value=PRINTABLESTRING:"US"
197 """, "invalid-AttributeTypeAndValue-setNotSequence")
199 generate("""asn1 = SEQUENCE:rdnSequence
201 rdn0 = SEQUENCE:rdnSet0
203 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
204 [attrTypeAndValueSequence0_0]
206 value=PRINTABLESTRING:"US"
207 """, "invalid-RDN-sequenceInsteadOfSet")
209 generate("""asn1 = SEQUENCE:rdnSequence
213 """, "invalid-RDN-empty")
215 generate("""asn1 = SET:rdnSequence
219 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
220 [attrTypeAndValueSequence0_0]
222 value=PRINTABLESTRING:"US"
223 """, "invalid-Name-setInsteadOfSequence")
225 generate("""asn1 = SEQUENCE:rdnSequence
227 """, "valid-Name-empty")
229 # Certs with a RDN that is sorted differently due to length of the values, but
230 # which should compare equal when normalized.
231 generate("""asn1 = SEQUENCE:rdnSequence
235 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
236 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
237 [attrTypeAndValueSequence0_0]
238 type=OID:stateOrProvinceName
239 value=PRINTABLESTRING:" state"
240 [attrTypeAndValueSequence0_1]
241 type=OID:localityName
242 value=PRINTABLESTRING:"locality"
243 """, "ascii-PRINTABLESTRING-rdn_sorting_1")
245 generate("""asn1 = SEQUENCE:rdnSequence
249 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
250 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
251 [attrTypeAndValueSequence0_0]
252 type=OID:stateOrProvinceName
253 value=PRINTABLESTRING:"state"
254 [attrTypeAndValueSequence0_1]
255 type=OID:localityName
256 value=PRINTABLESTRING:" locality"
257 """, "ascii-PRINTABLESTRING-rdn_sorting_2")
259 # Certs with a RDN that is sorted differently due to length of the values, and
260 # also contains multiple values with the same type.
261 generate("""asn1 = SEQUENCE:rdnSequence
265 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
266 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
267 attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
268 attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
269 attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
270 [attrTypeAndValueSequence0_0]
271 type=OID:domainComponent
272 value=IA5STRING:" cOm"
273 [attrTypeAndValueSequence0_1]
274 type=OID:domainComponent
275 value=IA5STRING:"eXaMple"
276 [attrTypeAndValueSequence0_2]
277 type=OID:domainComponent
278 value=IA5STRING:"wWw"
279 [attrTypeAndValueSequence0_3]
280 type=OID:localityName
281 value=PRINTABLESTRING:"NEw"
282 [attrTypeAndValueSequence0_4]
283 type=OID:localityName
284 value=PRINTABLESTRING:" yORk "
285 """, "ascii-mixed-rdn_dupetype_sorting_1")
287 generate("""asn1 = SEQUENCE:rdnSequence
291 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
292 attrTypeAndValue1=SEQUENCE:attrTypeAndValueSequence0_1
293 attrTypeAndValue2=SEQUENCE:attrTypeAndValueSequence0_2
294 attrTypeAndValue3=SEQUENCE:attrTypeAndValueSequence0_3
295 attrTypeAndValue4=SEQUENCE:attrTypeAndValueSequence0_4
296 [attrTypeAndValueSequence0_0]
297 type=OID:domainComponent
298 value=IA5STRING:"cOM"
299 [attrTypeAndValueSequence0_1]
300 type=OID:domainComponent
301 value=IA5STRING:"eXampLE"
302 [attrTypeAndValueSequence0_2]
303 type=OID:domainComponent
304 value=IA5STRING:" Www "
305 [attrTypeAndValueSequence0_3]
306 type=OID:localityName
307 value=PRINTABLESTRING:" nEw "
308 [attrTypeAndValueSequence0_4]
309 type=OID:localityName
310 value=PRINTABLESTRING:"yoRK"
311 """, "ascii-mixed-rdn_dupetype_sorting_2")
313 # Minimal valid config. Copy and modify this one when generating new invalid
315 generate("""asn1 = SEQUENCE:rdnSequence
319 attrTypeAndValue0=SEQUENCE:attrTypeAndValueSequence0_0
320 [attrTypeAndValueSequence0_0]
322 value=PRINTABLESTRING:"US"
323 """, "valid-minimal")
325 if __name__
== '__main__':