OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import asn1 | 5 import asn1 |
6 import datetime | 6 import datetime |
7 import hashlib | 7 import hashlib |
8 import itertools | 8 import itertools |
9 import os | 9 import os |
10 import time | 10 import time |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 AUTHORITY_INFORMATION_ACCESS = asn1.OID([1, 3, 6, 1, 5, 5, 7, 1, 1]) | 209 AUTHORITY_INFORMATION_ACCESS = asn1.OID([1, 3, 6, 1, 5, 5, 7, 1, 1]) |
210 BASIC_CONSTRAINTS = asn1.OID([2, 5, 29, 19]) | 210 BASIC_CONSTRAINTS = asn1.OID([2, 5, 29, 19]) |
211 CERT_POLICIES = asn1.OID([2, 5, 29, 32]) | 211 CERT_POLICIES = asn1.OID([2, 5, 29, 32]) |
212 COMMON_NAME = asn1.OID([2, 5, 4, 3]) | 212 COMMON_NAME = asn1.OID([2, 5, 4, 3]) |
213 COUNTRY = asn1.OID([2, 5, 4, 6]) | 213 COUNTRY = asn1.OID([2, 5, 4, 6]) |
214 HASH_SHA1 = asn1.OID([1, 3, 14, 3, 2, 26]) | 214 HASH_SHA1 = asn1.OID([1, 3, 14, 3, 2, 26]) |
215 OCSP_TYPE_BASIC = asn1.OID([1, 3, 6, 1, 5, 5, 7, 48, 1, 1]) | 215 OCSP_TYPE_BASIC = asn1.OID([1, 3, 6, 1, 5, 5, 7, 48, 1, 1]) |
216 ORGANIZATION = asn1.OID([2, 5, 4, 10]) | 216 ORGANIZATION = asn1.OID([2, 5, 4, 10]) |
217 PUBLIC_KEY_RSA = asn1.OID([1, 2, 840, 113549, 1, 1, 1]) | 217 PUBLIC_KEY_RSA = asn1.OID([1, 2, 840, 113549, 1, 1, 1]) |
218 SHA256_WITH_RSA_ENCRYPTION = asn1.OID([1, 2, 840, 113549, 1, 1, 11]) | 218 SHA256_WITH_RSA_ENCRYPTION = asn1.OID([1, 2, 840, 113549, 1, 1, 11]) |
219 | 219 SUBJECT_ALTERNATIVE_NAME = asn1.OID([2, 5, 29, 17]) |
220 | 220 |
221 def MakeCertificate( | 221 def MakeCertificate( |
222 issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url = None, | 222 issuer_cn, subject_cn, serial, pubkey, privkey, ocsp_url = None, |
223 ca_issuers_url = None, is_ca=False, path_len=None): | 223 ca_issuers_url = None, is_ca=False, path_len=None, ip_sans=None, |
| 224 dns_sans=None): |
224 '''MakeCertificate returns a DER encoded certificate, signed by privkey.''' | 225 '''MakeCertificate returns a DER encoded certificate, signed by privkey.''' |
225 extensions = asn1.SEQUENCE([]) | 226 extensions = asn1.SEQUENCE([]) |
226 | 227 |
227 # Default subject name fields | 228 # Default subject name fields |
228 c = "XX" | 229 c = "XX" |
229 o = "Testing Org" | 230 o = "Testing Org" |
230 | 231 |
231 if is_ca: | 232 if is_ca: |
232 # Root certificate. | 233 # Root certificate. |
233 c = None | 234 c = None |
234 o = None | 235 o = None |
235 extensions.children.append( | 236 extensions.children.append( |
236 asn1.SEQUENCE([ | 237 asn1.SEQUENCE([ |
237 BASIC_CONSTRAINTS, | 238 BASIC_CONSTRAINTS, |
238 True, | 239 True, |
239 asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([ | 240 asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE([ |
240 True, # IsCA | 241 True, # IsCA |
241 ] + ([path_len] if path_len is not None else []) # Path len | 242 ] + ([path_len] if path_len is not None else []) # Path len |
242 ))), | 243 ))), |
243 ])) | 244 ])) |
244 | 245 |
| 246 if ip_sans is not None or dns_sans is not None: |
| 247 sans = [] |
| 248 if dns_sans is not None: |
| 249 for dns_name in dns_sans: |
| 250 sans.append( |
| 251 asn1.Raw(asn1.TagAndLength(0x82, len(dns_name)) + dns_name)) |
| 252 if ip_sans is not None: |
| 253 for ip_addr in ip_sans: |
| 254 sans.append( |
| 255 asn1.Raw(asn1.TagAndLength(0x87, len(ip_addr)) + ip_addr)) |
| 256 extensions.children.append( |
| 257 asn1.SEQUENCE([ |
| 258 SUBJECT_ALTERNATIVE_NAME, |
| 259 # There is implicitly a critical=False here. Since false is the |
| 260 # default, encoding the value would be invalid DER. |
| 261 asn1.OCTETSTRING(asn1.ToDER(asn1.SEQUENCE(sans))) |
| 262 ])) |
| 263 |
245 if ocsp_url is not None or ca_issuers_url is not None: | 264 if ocsp_url is not None or ca_issuers_url is not None: |
246 aia_entries = [] | 265 aia_entries = [] |
247 if ocsp_url is not None: | 266 if ocsp_url is not None: |
248 aia_entries.append( | 267 aia_entries.append( |
249 asn1.SEQUENCE([ | 268 asn1.SEQUENCE([ |
250 AIA_OCSP, | 269 AIA_OCSP, |
251 asn1.Raw(asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url), | 270 asn1.Raw(asn1.TagAndLength(0x86, len(ocsp_url)) + ocsp_url), |
252 ])) | 271 ])) |
253 if ca_issuers_url is not None: | 272 if ca_issuers_url is not None: |
254 aia_entries.append( | 273 aia_entries.append( |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 438 |
420 # unauthorizedDER is an OCSPResponse with a status of 6: | 439 # unauthorizedDER is an OCSPResponse with a status of 6: |
421 # SEQUENCE { ENUM(6) } | 440 # SEQUENCE { ENUM(6) } |
422 unauthorizedDER = '30030a0106'.decode('hex') | 441 unauthorizedDER = '30030a0106'.decode('hex') |
423 | 442 |
424 def GenerateCertKeyAndOCSP(subject = "127.0.0.1", | 443 def GenerateCertKeyAndOCSP(subject = "127.0.0.1", |
425 ocsp_url = "http://127.0.0.1", | 444 ocsp_url = "http://127.0.0.1", |
426 ocsp_states = None, | 445 ocsp_states = None, |
427 ocsp_dates = None, | 446 ocsp_dates = None, |
428 ocsp_produced = OCSP_PRODUCED_VALID, | 447 ocsp_produced = OCSP_PRODUCED_VALID, |
| 448 ip_sans = ["\x7F\x00\x00\x01"], |
| 449 dns_sans = None, |
429 serial = 0): | 450 serial = 0): |
430 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: | 451 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: |
431 * cert_and_key_pem contains a certificate and private key in PEM format | 452 * cert_and_key_pem contains a certificate and private key in PEM format |
432 with the given subject common name and OCSP URL. | 453 with the given subject common name and OCSP URL. |
433 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is | 454 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is |
434 None''' | 455 None''' |
435 | 456 |
436 if ocsp_states is None: | 457 if ocsp_states is None: |
437 ocsp_states = [OCSP_STATE_GOOD] | 458 ocsp_states = [OCSP_STATE_GOOD] |
438 if ocsp_dates is None: | 459 if ocsp_dates is None: |
439 ocsp_dates = [OCSP_DATE_VALID] | 460 ocsp_dates = [OCSP_DATE_VALID] |
440 | 461 |
441 if serial == 0: | 462 if serial == 0: |
442 serial = RandomNumber(16) | 463 serial = RandomNumber(16) |
443 cert_der = MakeCertificate(ROOT_CN, bytes(subject), serial, LEAF_KEY, | 464 cert_der = MakeCertificate(ROOT_CN, bytes(subject), serial, LEAF_KEY, |
444 ROOT_KEY, bytes(ocsp_url)) | 465 ROOT_KEY, bytes(ocsp_url), ip_sans=ip_sans, |
| 466 dns_sans=dns_sans) |
445 cert_pem = DERToPEM(cert_der) | 467 cert_pem = DERToPEM(cert_der) |
446 | 468 |
447 ocsp_der = None | 469 ocsp_der = None |
448 if ocsp_url is not None: | 470 if ocsp_url is not None: |
449 if ocsp_states[0] == OCSP_STATE_UNAUTHORIZED: | 471 if ocsp_states[0] == OCSP_STATE_UNAUTHORIZED: |
450 ocsp_der = unauthorizedDER | 472 ocsp_der = unauthorizedDER |
451 elif ocsp_states[0] == OCSP_STATE_INVALID_RESPONSE: | 473 elif ocsp_states[0] == OCSP_STATE_INVALID_RESPONSE: |
452 ocsp_der = '3' | 474 ocsp_der = '3' |
453 elif ocsp_states[0] == OCSP_STATE_TRY_LATER: | 475 elif ocsp_states[0] == OCSP_STATE_TRY_LATER: |
454 resp = asn1.SEQUENCE([ | 476 resp = asn1.SEQUENCE([ |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 print 'ocsp-test-root.pem:' | 538 print 'ocsp-test-root.pem:' |
517 print DERToPEM(der_root) | 539 print DERToPEM(der_root) |
518 | 540 |
519 print | 541 print |
520 print 'kOCSPTestCertFingerprint:' | 542 print 'kOCSPTestCertFingerprint:' |
521 print bin_to_array(hashlib.sha1(der_root).digest()) | 543 print bin_to_array(hashlib.sha1(der_root).digest()) |
522 | 544 |
523 print | 545 print |
524 print 'kOCSPTestCertSPKI:' | 546 print 'kOCSPTestCertSPKI:' |
525 print bin_to_array(crlsetutil.der_cert_to_spki_hash(der_root)) | 547 print bin_to_array(crlsetutil.der_cert_to_spki_hash(der_root)) |
OLD | NEW |