• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
7import calendar
8import ipaddress
9
10import six
11
12from cryptography import utils, x509
13from cryptography.hazmat.backends.openssl.decode_asn1 import (
14    _CRL_ENTRY_REASON_ENUM_TO_CODE, _DISTPOINT_TYPE_FULLNAME,
15    _DISTPOINT_TYPE_RELATIVENAME
16)
17from cryptography.x509.name import _ASN1Type
18from cryptography.x509.oid import (
19    CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID,
20)
21
22
23def _encode_asn1_int(backend, x):
24    """
25    Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER
26    will not be garbage collected (to support adding them to structs that take
27    ownership of the object). Be sure to register it for GC if it will be
28    discarded after use.
29
30    """
31    # Convert Python integer to OpenSSL "bignum" in case value exceeds
32    # machine's native integer limits (note: `int_to_bn` doesn't automatically
33    # GC).
34    i = backend._int_to_bn(x)
35    i = backend._ffi.gc(i, backend._lib.BN_free)
36
37    # Wrap in an ASN.1 integer.  Don't GC -- as documented.
38    i = backend._lib.BN_to_ASN1_INTEGER(i, backend._ffi.NULL)
39    backend.openssl_assert(i != backend._ffi.NULL)
40    return i
41
42
43def _encode_asn1_int_gc(backend, x):
44    i = _encode_asn1_int(backend, x)
45    i = backend._ffi.gc(i, backend._lib.ASN1_INTEGER_free)
46    return i
47
48
49def _encode_asn1_str(backend, data):
50    """
51    Create an ASN1_OCTET_STRING from a Python byte string.
52    """
53    s = backend._lib.ASN1_OCTET_STRING_new()
54    res = backend._lib.ASN1_OCTET_STRING_set(s, data, len(data))
55    backend.openssl_assert(res == 1)
56    return s
57
58
59def _encode_asn1_utf8_str(backend, string):
60    """
61    Create an ASN1_UTF8STRING from a Python unicode string.
62    This object will be an ASN1_STRING with UTF8 type in OpenSSL and
63    can be decoded with ASN1_STRING_to_UTF8.
64    """
65    s = backend._lib.ASN1_UTF8STRING_new()
66    res = backend._lib.ASN1_STRING_set(
67        s, string.encode("utf8"), len(string.encode("utf8"))
68    )
69    backend.openssl_assert(res == 1)
70    return s
71
72
73def _encode_asn1_str_gc(backend, data):
74    s = _encode_asn1_str(backend, data)
75    s = backend._ffi.gc(s, backend._lib.ASN1_OCTET_STRING_free)
76    return s
77
78
79def _encode_inhibit_any_policy(backend, inhibit_any_policy):
80    return _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs)
81
82
83def _encode_name(backend, name):
84    """
85    The X509_NAME created will not be gc'd. Use _encode_name_gc if needed.
86    """
87    subject = backend._lib.X509_NAME_new()
88    for rdn in name.rdns:
89        set_flag = 0  # indicate whether to add to last RDN or create new RDN
90        for attribute in rdn:
91            name_entry = _encode_name_entry(backend, attribute)
92            # X509_NAME_add_entry dups the object so we need to gc this copy
93            name_entry = backend._ffi.gc(
94                name_entry, backend._lib.X509_NAME_ENTRY_free
95            )
96            res = backend._lib.X509_NAME_add_entry(
97                subject, name_entry, -1, set_flag)
98            backend.openssl_assert(res == 1)
99            set_flag = -1
100    return subject
101
102
103def _encode_name_gc(backend, attributes):
104    subject = _encode_name(backend, attributes)
105    subject = backend._ffi.gc(subject, backend._lib.X509_NAME_free)
106    return subject
107
108
109def _encode_sk_name_entry(backend, attributes):
110    """
111    The sk_X509_NAME_ENTRY created will not be gc'd.
112    """
113    stack = backend._lib.sk_X509_NAME_ENTRY_new_null()
114    for attribute in attributes:
115        name_entry = _encode_name_entry(backend, attribute)
116        res = backend._lib.sk_X509_NAME_ENTRY_push(stack, name_entry)
117        backend.openssl_assert(res >= 1)
118    return stack
119
120
121def _encode_name_entry(backend, attribute):
122    if attribute._type is _ASN1Type.BMPString:
123        value = attribute.value.encode('utf_16_be')
124    else:
125        value = attribute.value.encode('utf8')
126
127    obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
128
129    name_entry = backend._lib.X509_NAME_ENTRY_create_by_OBJ(
130        backend._ffi.NULL, obj, attribute._type.value, value, len(value)
131    )
132    return name_entry
133
134
135def _encode_crl_number_delta_crl_indicator(backend, ext):
136    return _encode_asn1_int_gc(backend, ext.crl_number)
137
138
139def _encode_issuing_dist_point(backend, ext):
140    idp = backend._lib.ISSUING_DIST_POINT_new()
141    backend.openssl_assert(idp != backend._ffi.NULL)
142    idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free)
143    idp.onlyuser = 255 if ext.only_contains_user_certs else 0
144    idp.onlyCA = 255 if ext.only_contains_ca_certs else 0
145    idp.indirectCRL = 255 if ext.indirect_crl else 0
146    idp.onlyattr = 255 if ext.only_contains_attribute_certs else 0
147    if ext.only_some_reasons:
148        idp.onlysomereasons = _encode_reasonflags(
149            backend, ext.only_some_reasons
150        )
151
152    if ext.full_name:
153        idp.distpoint = _encode_full_name(backend, ext.full_name)
154
155    if ext.relative_name:
156        idp.distpoint = _encode_relative_name(backend, ext.relative_name)
157
158    return idp
159
160
161def _encode_crl_reason(backend, crl_reason):
162    asn1enum = backend._lib.ASN1_ENUMERATED_new()
163    backend.openssl_assert(asn1enum != backend._ffi.NULL)
164    asn1enum = backend._ffi.gc(asn1enum, backend._lib.ASN1_ENUMERATED_free)
165    res = backend._lib.ASN1_ENUMERATED_set(
166        asn1enum, _CRL_ENTRY_REASON_ENUM_TO_CODE[crl_reason.reason]
167    )
168    backend.openssl_assert(res == 1)
169
170    return asn1enum
171
172
173def _encode_invalidity_date(backend, invalidity_date):
174    time = backend._lib.ASN1_GENERALIZEDTIME_set(
175        backend._ffi.NULL, calendar.timegm(
176            invalidity_date.invalidity_date.timetuple()
177        )
178    )
179    backend.openssl_assert(time != backend._ffi.NULL)
180    time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free)
181
182    return time
183
184
185def _encode_certificate_policies(backend, certificate_policies):
186    cp = backend._lib.sk_POLICYINFO_new_null()
187    backend.openssl_assert(cp != backend._ffi.NULL)
188    cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free)
189    for policy_info in certificate_policies:
190        pi = backend._lib.POLICYINFO_new()
191        backend.openssl_assert(pi != backend._ffi.NULL)
192        res = backend._lib.sk_POLICYINFO_push(cp, pi)
193        backend.openssl_assert(res >= 1)
194        oid = _txt2obj(backend, policy_info.policy_identifier.dotted_string)
195        pi.policyid = oid
196        if policy_info.policy_qualifiers:
197            pqis = backend._lib.sk_POLICYQUALINFO_new_null()
198            backend.openssl_assert(pqis != backend._ffi.NULL)
199            for qualifier in policy_info.policy_qualifiers:
200                pqi = backend._lib.POLICYQUALINFO_new()
201                backend.openssl_assert(pqi != backend._ffi.NULL)
202                res = backend._lib.sk_POLICYQUALINFO_push(pqis, pqi)
203                backend.openssl_assert(res >= 1)
204                if isinstance(qualifier, six.text_type):
205                    pqi.pqualid = _txt2obj(
206                        backend, x509.OID_CPS_QUALIFIER.dotted_string
207                    )
208                    pqi.d.cpsuri = _encode_asn1_str(
209                        backend,
210                        qualifier.encode("ascii"),
211                    )
212                else:
213                    assert isinstance(qualifier, x509.UserNotice)
214                    pqi.pqualid = _txt2obj(
215                        backend, x509.OID_CPS_USER_NOTICE.dotted_string
216                    )
217                    un = backend._lib.USERNOTICE_new()
218                    backend.openssl_assert(un != backend._ffi.NULL)
219                    pqi.d.usernotice = un
220                    if qualifier.explicit_text:
221                        un.exptext = _encode_asn1_utf8_str(
222                            backend, qualifier.explicit_text
223                        )
224
225                    un.noticeref = _encode_notice_reference(
226                        backend, qualifier.notice_reference
227                    )
228
229            pi.qualifiers = pqis
230
231    return cp
232
233
234def _encode_notice_reference(backend, notice):
235    if notice is None:
236        return backend._ffi.NULL
237    else:
238        nr = backend._lib.NOTICEREF_new()
239        backend.openssl_assert(nr != backend._ffi.NULL)
240        # organization is a required field
241        nr.organization = _encode_asn1_utf8_str(backend, notice.organization)
242
243        notice_stack = backend._lib.sk_ASN1_INTEGER_new_null()
244        nr.noticenos = notice_stack
245        for number in notice.notice_numbers:
246            num = _encode_asn1_int(backend, number)
247            res = backend._lib.sk_ASN1_INTEGER_push(notice_stack, num)
248            backend.openssl_assert(res >= 1)
249
250        return nr
251
252
253def _txt2obj(backend, name):
254    """
255    Converts a Python string with an ASN.1 object ID in dotted form to a
256    ASN1_OBJECT.
257    """
258    name = name.encode('ascii')
259    obj = backend._lib.OBJ_txt2obj(name, 1)
260    backend.openssl_assert(obj != backend._ffi.NULL)
261    return obj
262
263
264def _txt2obj_gc(backend, name):
265    obj = _txt2obj(backend, name)
266    obj = backend._ffi.gc(obj, backend._lib.ASN1_OBJECT_free)
267    return obj
268
269
270def _encode_ocsp_nocheck(backend, ext):
271    # Doesn't need to be GC'd
272    return backend._lib.ASN1_NULL_new()
273
274
275def _encode_key_usage(backend, key_usage):
276    set_bit = backend._lib.ASN1_BIT_STRING_set_bit
277    ku = backend._lib.ASN1_BIT_STRING_new()
278    ku = backend._ffi.gc(ku, backend._lib.ASN1_BIT_STRING_free)
279    res = set_bit(ku, 0, key_usage.digital_signature)
280    backend.openssl_assert(res == 1)
281    res = set_bit(ku, 1, key_usage.content_commitment)
282    backend.openssl_assert(res == 1)
283    res = set_bit(ku, 2, key_usage.key_encipherment)
284    backend.openssl_assert(res == 1)
285    res = set_bit(ku, 3, key_usage.data_encipherment)
286    backend.openssl_assert(res == 1)
287    res = set_bit(ku, 4, key_usage.key_agreement)
288    backend.openssl_assert(res == 1)
289    res = set_bit(ku, 5, key_usage.key_cert_sign)
290    backend.openssl_assert(res == 1)
291    res = set_bit(ku, 6, key_usage.crl_sign)
292    backend.openssl_assert(res == 1)
293    if key_usage.key_agreement:
294        res = set_bit(ku, 7, key_usage.encipher_only)
295        backend.openssl_assert(res == 1)
296        res = set_bit(ku, 8, key_usage.decipher_only)
297        backend.openssl_assert(res == 1)
298    else:
299        res = set_bit(ku, 7, 0)
300        backend.openssl_assert(res == 1)
301        res = set_bit(ku, 8, 0)
302        backend.openssl_assert(res == 1)
303
304    return ku
305
306
307def _encode_authority_key_identifier(backend, authority_keyid):
308    akid = backend._lib.AUTHORITY_KEYID_new()
309    backend.openssl_assert(akid != backend._ffi.NULL)
310    akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free)
311    if authority_keyid.key_identifier is not None:
312        akid.keyid = _encode_asn1_str(
313            backend,
314            authority_keyid.key_identifier,
315        )
316
317    if authority_keyid.authority_cert_issuer is not None:
318        akid.issuer = _encode_general_names(
319            backend, authority_keyid.authority_cert_issuer
320        )
321
322    if authority_keyid.authority_cert_serial_number is not None:
323        akid.serial = _encode_asn1_int(
324            backend, authority_keyid.authority_cert_serial_number
325        )
326
327    return akid
328
329
330def _encode_basic_constraints(backend, basic_constraints):
331    constraints = backend._lib.BASIC_CONSTRAINTS_new()
332    constraints = backend._ffi.gc(
333        constraints, backend._lib.BASIC_CONSTRAINTS_free
334    )
335    constraints.ca = 255 if basic_constraints.ca else 0
336    if basic_constraints.ca and basic_constraints.path_length is not None:
337        constraints.pathlen = _encode_asn1_int(
338            backend, basic_constraints.path_length
339        )
340
341    return constraints
342
343
344def _encode_authority_information_access(backend, authority_info_access):
345    aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null()
346    backend.openssl_assert(aia != backend._ffi.NULL)
347    aia = backend._ffi.gc(
348        aia, backend._lib.sk_ACCESS_DESCRIPTION_free
349    )
350    for access_description in authority_info_access:
351        ad = backend._lib.ACCESS_DESCRIPTION_new()
352        method = _txt2obj(
353            backend, access_description.access_method.dotted_string
354        )
355        gn = _encode_general_name(backend, access_description.access_location)
356        ad.method = method
357        ad.location = gn
358        res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad)
359        backend.openssl_assert(res >= 1)
360
361    return aia
362
363
364def _encode_general_names(backend, names):
365    general_names = backend._lib.GENERAL_NAMES_new()
366    backend.openssl_assert(general_names != backend._ffi.NULL)
367    for name in names:
368        gn = _encode_general_name(backend, name)
369        res = backend._lib.sk_GENERAL_NAME_push(general_names, gn)
370        backend.openssl_assert(res != 0)
371
372    return general_names
373
374
375def _encode_alt_name(backend, san):
376    general_names = _encode_general_names(backend, san)
377    general_names = backend._ffi.gc(
378        general_names, backend._lib.GENERAL_NAMES_free
379    )
380    return general_names
381
382
383def _encode_subject_key_identifier(backend, ski):
384    return _encode_asn1_str_gc(backend, ski.digest)
385
386
387def _encode_general_name(backend, name):
388    if isinstance(name, x509.DNSName):
389        gn = backend._lib.GENERAL_NAME_new()
390        backend.openssl_assert(gn != backend._ffi.NULL)
391        gn.type = backend._lib.GEN_DNS
392
393        ia5 = backend._lib.ASN1_IA5STRING_new()
394        backend.openssl_assert(ia5 != backend._ffi.NULL)
395        # ia5strings are supposed to be ITU T.50 but to allow round-tripping
396        # of broken certs that encode utf8 we'll encode utf8 here too.
397        value = name.value.encode("utf8")
398
399        res = backend._lib.ASN1_STRING_set(ia5, value, len(value))
400        backend.openssl_assert(res == 1)
401        gn.d.dNSName = ia5
402    elif isinstance(name, x509.RegisteredID):
403        gn = backend._lib.GENERAL_NAME_new()
404        backend.openssl_assert(gn != backend._ffi.NULL)
405        gn.type = backend._lib.GEN_RID
406        obj = backend._lib.OBJ_txt2obj(
407            name.value.dotted_string.encode('ascii'), 1
408        )
409        backend.openssl_assert(obj != backend._ffi.NULL)
410        gn.d.registeredID = obj
411    elif isinstance(name, x509.DirectoryName):
412        gn = backend._lib.GENERAL_NAME_new()
413        backend.openssl_assert(gn != backend._ffi.NULL)
414        dir_name = _encode_name(backend, name.value)
415        gn.type = backend._lib.GEN_DIRNAME
416        gn.d.directoryName = dir_name
417    elif isinstance(name, x509.IPAddress):
418        gn = backend._lib.GENERAL_NAME_new()
419        backend.openssl_assert(gn != backend._ffi.NULL)
420        if isinstance(name.value, ipaddress.IPv4Network):
421            packed = (
422                name.value.network_address.packed +
423                utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4)
424            )
425        elif isinstance(name.value, ipaddress.IPv6Network):
426            packed = (
427                name.value.network_address.packed +
428                utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16)
429            )
430        else:
431            packed = name.value.packed
432        ipaddr = _encode_asn1_str(backend, packed)
433        gn.type = backend._lib.GEN_IPADD
434        gn.d.iPAddress = ipaddr
435    elif isinstance(name, x509.OtherName):
436        gn = backend._lib.GENERAL_NAME_new()
437        backend.openssl_assert(gn != backend._ffi.NULL)
438        other_name = backend._lib.OTHERNAME_new()
439        backend.openssl_assert(other_name != backend._ffi.NULL)
440
441        type_id = backend._lib.OBJ_txt2obj(
442            name.type_id.dotted_string.encode('ascii'), 1
443        )
444        backend.openssl_assert(type_id != backend._ffi.NULL)
445        data = backend._ffi.new("unsigned char[]", name.value)
446        data_ptr_ptr = backend._ffi.new("unsigned char **")
447        data_ptr_ptr[0] = data
448        value = backend._lib.d2i_ASN1_TYPE(
449            backend._ffi.NULL, data_ptr_ptr, len(name.value)
450        )
451        if value == backend._ffi.NULL:
452            backend._consume_errors()
453            raise ValueError("Invalid ASN.1 data")
454        other_name.type_id = type_id
455        other_name.value = value
456        gn.type = backend._lib.GEN_OTHERNAME
457        gn.d.otherName = other_name
458    elif isinstance(name, x509.RFC822Name):
459        gn = backend._lib.GENERAL_NAME_new()
460        backend.openssl_assert(gn != backend._ffi.NULL)
461        # ia5strings are supposed to be ITU T.50 but to allow round-tripping
462        # of broken certs that encode utf8 we'll encode utf8 here too.
463        data = name.value.encode("utf8")
464        asn1_str = _encode_asn1_str(backend, data)
465        gn.type = backend._lib.GEN_EMAIL
466        gn.d.rfc822Name = asn1_str
467    elif isinstance(name, x509.UniformResourceIdentifier):
468        gn = backend._lib.GENERAL_NAME_new()
469        backend.openssl_assert(gn != backend._ffi.NULL)
470        # ia5strings are supposed to be ITU T.50 but to allow round-tripping
471        # of broken certs that encode utf8 we'll encode utf8 here too.
472        data = name.value.encode("utf8")
473        asn1_str = _encode_asn1_str(backend, data)
474        gn.type = backend._lib.GEN_URI
475        gn.d.uniformResourceIdentifier = asn1_str
476    else:
477        raise ValueError(
478            "{0} is an unknown GeneralName type".format(name)
479        )
480
481    return gn
482
483
484def _encode_extended_key_usage(backend, extended_key_usage):
485    eku = backend._lib.sk_ASN1_OBJECT_new_null()
486    eku = backend._ffi.gc(eku, backend._lib.sk_ASN1_OBJECT_free)
487    for oid in extended_key_usage:
488        obj = _txt2obj(backend, oid.dotted_string)
489        res = backend._lib.sk_ASN1_OBJECT_push(eku, obj)
490        backend.openssl_assert(res >= 1)
491
492    return eku
493
494
495_CRLREASONFLAGS = {
496    x509.ReasonFlags.key_compromise: 1,
497    x509.ReasonFlags.ca_compromise: 2,
498    x509.ReasonFlags.affiliation_changed: 3,
499    x509.ReasonFlags.superseded: 4,
500    x509.ReasonFlags.cessation_of_operation: 5,
501    x509.ReasonFlags.certificate_hold: 6,
502    x509.ReasonFlags.privilege_withdrawn: 7,
503    x509.ReasonFlags.aa_compromise: 8,
504}
505
506
507def _encode_reasonflags(backend, reasons):
508    bitmask = backend._lib.ASN1_BIT_STRING_new()
509    backend.openssl_assert(bitmask != backend._ffi.NULL)
510    for reason in reasons:
511        res = backend._lib.ASN1_BIT_STRING_set_bit(
512            bitmask, _CRLREASONFLAGS[reason], 1
513        )
514        backend.openssl_assert(res == 1)
515
516    return bitmask
517
518
519def _encode_full_name(backend, full_name):
520    dpn = backend._lib.DIST_POINT_NAME_new()
521    backend.openssl_assert(dpn != backend._ffi.NULL)
522    dpn.type = _DISTPOINT_TYPE_FULLNAME
523    dpn.name.fullname = _encode_general_names(backend, full_name)
524    return dpn
525
526
527def _encode_relative_name(backend, relative_name):
528    dpn = backend._lib.DIST_POINT_NAME_new()
529    backend.openssl_assert(dpn != backend._ffi.NULL)
530    dpn.type = _DISTPOINT_TYPE_RELATIVENAME
531    dpn.name.relativename = _encode_sk_name_entry(backend, relative_name)
532    return dpn
533
534
535def _encode_cdps_freshest_crl(backend, cdps):
536    cdp = backend._lib.sk_DIST_POINT_new_null()
537    cdp = backend._ffi.gc(cdp, backend._lib.sk_DIST_POINT_free)
538    for point in cdps:
539        dp = backend._lib.DIST_POINT_new()
540        backend.openssl_assert(dp != backend._ffi.NULL)
541
542        if point.reasons:
543            dp.reasons = _encode_reasonflags(backend, point.reasons)
544
545        if point.full_name:
546            dp.distpoint = _encode_full_name(backend, point.full_name)
547
548        if point.relative_name:
549            dp.distpoint = _encode_relative_name(backend, point.relative_name)
550
551        if point.crl_issuer:
552            dp.CRLissuer = _encode_general_names(backend, point.crl_issuer)
553
554        res = backend._lib.sk_DIST_POINT_push(cdp, dp)
555        backend.openssl_assert(res >= 1)
556
557    return cdp
558
559
560def _encode_name_constraints(backend, name_constraints):
561    nc = backend._lib.NAME_CONSTRAINTS_new()
562    backend.openssl_assert(nc != backend._ffi.NULL)
563    nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free)
564    permitted = _encode_general_subtree(
565        backend, name_constraints.permitted_subtrees
566    )
567    nc.permittedSubtrees = permitted
568    excluded = _encode_general_subtree(
569        backend, name_constraints.excluded_subtrees
570    )
571    nc.excludedSubtrees = excluded
572
573    return nc
574
575
576def _encode_policy_constraints(backend, policy_constraints):
577    pc = backend._lib.POLICY_CONSTRAINTS_new()
578    backend.openssl_assert(pc != backend._ffi.NULL)
579    pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free)
580    if policy_constraints.require_explicit_policy is not None:
581        pc.requireExplicitPolicy = _encode_asn1_int(
582            backend, policy_constraints.require_explicit_policy
583        )
584
585    if policy_constraints.inhibit_policy_mapping is not None:
586        pc.inhibitPolicyMapping = _encode_asn1_int(
587            backend, policy_constraints.inhibit_policy_mapping
588        )
589
590    return pc
591
592
593def _encode_general_subtree(backend, subtrees):
594    if subtrees is None:
595        return backend._ffi.NULL
596    else:
597        general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null()
598        for name in subtrees:
599            gs = backend._lib.GENERAL_SUBTREE_new()
600            gs.base = _encode_general_name(backend, name)
601            res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs)
602            assert res >= 1
603
604        return general_subtrees
605
606
607def _encode_nonce(backend, nonce):
608    return _encode_asn1_str_gc(backend, nonce.nonce)
609
610
611_EXTENSION_ENCODE_HANDLERS = {
612    ExtensionOID.BASIC_CONSTRAINTS: _encode_basic_constraints,
613    ExtensionOID.SUBJECT_KEY_IDENTIFIER: _encode_subject_key_identifier,
614    ExtensionOID.KEY_USAGE: _encode_key_usage,
615    ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _encode_alt_name,
616    ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name,
617    ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage,
618    ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
619    ExtensionOID.CERTIFICATE_POLICIES: _encode_certificate_policies,
620    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
621        _encode_authority_information_access
622    ),
623    ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl,
624    ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl,
625    ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy,
626    ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck,
627    ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints,
628    ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints,
629}
630
631_CRL_EXTENSION_ENCODE_HANDLERS = {
632    ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name,
633    ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
634    ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
635        _encode_authority_information_access
636    ),
637    ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator,
638    ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator,
639    ExtensionOID.ISSUING_DISTRIBUTION_POINT: _encode_issuing_dist_point,
640}
641
642_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = {
643    CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_alt_name,
644    CRLEntryExtensionOID.CRL_REASON: _encode_crl_reason,
645    CRLEntryExtensionOID.INVALIDITY_DATE: _encode_invalidity_date,
646}
647
648_OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS = {
649    OCSPExtensionOID.NONCE: _encode_nonce,
650}
651
652_OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS = {
653    OCSPExtensionOID.NONCE: _encode_nonce,
654}
655