aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_cffi_src/openssl/asn1.py5
-rw-r--r--src/_cffi_src/openssl/x509v3.py1
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py13
-rw-r--r--src/cryptography/x509.py53
4 files changed, 54 insertions, 18 deletions
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 44e9de17..96084721 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -43,6 +43,7 @@ typedef struct asn1_string_st ASN1_IA5STRING;
typedef ... ASN1_BIT_STRING;
typedef ... ASN1_OBJECT;
typedef struct asn1_string_st ASN1_STRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
typedef ... ASN1_TYPE;
typedef ... ASN1_GENERALIZEDTIME;
typedef ... ASN1_ENUMERATED;
@@ -125,9 +126,13 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *, int, int);
"""
MACROS = """
+ASN1_UTF8STRING *ASN1_UTF8STRING_new(void);
+void ASN1_UTF8STRING_free(ASN1_UTF8STRING *);
+
ASN1_BIT_STRING *ASN1_BIT_STRING_new(void);
void ASN1_BIT_STRING_free(ASN1_BIT_STRING *);
int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *, unsigned char **);
+int i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *, unsigned char **);
/* This is not a macro, but is const on some versions of OpenSSL */
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *, int);
ASN1_TIME *M_ASN1_TIME_dup(void *);
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 6e35dacc..84e49640 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -279,6 +279,7 @@ void sk_ASN1_INTEGER_free(Cryptography_STACK_OF_ASN1_INTEGER *);
int sk_ASN1_INTEGER_num(Cryptography_STACK_OF_ASN1_INTEGER *);
ASN1_INTEGER *sk_ASN1_INTEGER_value(Cryptography_STACK_OF_ASN1_INTEGER *, int);
int sk_ASN1_INTEGER_push(Cryptography_STACK_OF_ASN1_INTEGER *, ASN1_INTEGER *);
+Cryptography_STACK_OF_ASN1_INTEGER *sk_ASN1_INTEGER_new_null(void);
X509_EXTENSION *X509V3_EXT_i2d(int, int, void *);
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 2752d98d..fdd38fa3 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -254,6 +254,17 @@ def _encode_subject_alt_name(backend, san):
return pp, r
+def _encode_subject_key_identifier(backend, ski):
+ asn1_str = _encode_asn1_str_gc(backend, ski.digest, len(ski.digest))
+ pp = backend._ffi.new("unsigned char **")
+ r = backend._lib.i2d_ASN1_OCTET_STRING(asn1_str, pp)
+ assert r > 0
+ pp = backend._ffi.gc(
+ pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+ )
+ return pp, r
+
+
def _encode_general_name(backend, name):
if isinstance(name, x509.DNSName):
gn = backend._lib.GENERAL_NAME_new()
@@ -1235,6 +1246,8 @@ class Backend(object):
pp, r = _encode_extended_key_usage(self, extension.value)
elif isinstance(extension.value, x509.SubjectAlternativeName):
pp, r = _encode_subject_alt_name(self, extension.value)
+ elif isinstance(extension.value, x509.SubjectKeyIdentifier):
+ pp, r = _encode_subject_key_identifier(self, extension.value)
elif isinstance(extension.value, x509.AuthorityInformationAccess):
pp, r = _encode_authority_information_access(
self, extension.value
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 5ed3c094..da7603c4 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -32,6 +32,27 @@ class _SubjectPublicKeyInfo(univ.Sequence):
)
+def _key_identifier_from_public_key(public_key):
+ # This is a very slow way to do this.
+ serialized = public_key.public_bytes(
+ serialization.Encoding.DER,
+ serialization.PublicFormat.SubjectPublicKeyInfo
+ )
+ spki, remaining = decoder.decode(
+ serialized, asn1Spec=_SubjectPublicKeyInfo()
+ )
+ assert not remaining
+ # the univ.BitString object is a tuple of bits. We need bytes and
+ # pyasn1 really doesn't want to give them to us. To get it we'll
+ # build an integer and convert that to bytes.
+ bits = 0
+ for bit in spki.getComponentByName("subjectPublicKey"):
+ bits = bits << 1 | bit
+
+ data = utils.int_to_bytes(bits)
+ return hashlib.sha1(data).digest()
+
+
_OID_NAMES = {
"2.5.4.3": "commonName",
"2.5.4.6": "countryName",
@@ -710,24 +731,7 @@ class SubjectKeyIdentifier(object):
@classmethod
def from_public_key(cls, public_key):
- # This is a very slow way to do this.
- serialized = public_key.public_bytes(
- serialization.Encoding.DER,
- serialization.PublicFormat.SubjectPublicKeyInfo
- )
- spki, remaining = decoder.decode(
- serialized, asn1Spec=_SubjectPublicKeyInfo()
- )
- assert not remaining
- # the univ.BitString object is a tuple of bits. We need bytes and
- # pyasn1 really doesn't want to give them to us. To get it we'll
- # build an integer and convert that to bytes.
- bits = 0
- for bit in spki.getComponentByName("subjectPublicKey"):
- bits = bits << 1 | bit
-
- data = utils.int_to_bytes(bits)
- return cls(hashlib.sha1(data).digest())
+ return cls(_key_identifier_from_public_key(public_key))
digest = utils.read_only_property("_digest")
@@ -1318,6 +1322,15 @@ class AuthorityKeyIdentifier(object):
self._authority_cert_issuer = authority_cert_issuer
self._authority_cert_serial_number = authority_cert_serial_number
+ @classmethod
+ def from_issuer_public_key(cls, public_key):
+ digest = _key_identifier_from_public_key(public_key)
+ return cls(
+ key_identifier=digest,
+ authority_cert_issuer=None,
+ authority_cert_serial_number=None
+ )
+
def __repr__(self):
return (
"<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
@@ -1811,6 +1824,10 @@ class CertificateBuilder(object):
extension = Extension(
OID_AUTHORITY_INFORMATION_ACCESS, critical, extension
)
+ elif isinstance(extension, SubjectKeyIdentifier):
+ extension = Extension(
+ OID_SUBJECT_KEY_IDENTIFIER, critical, extension
+ )
elif isinstance(extension, InhibitAnyPolicy):
extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension)
elif isinstance(extension, CRLDistributionPoints):