Skip to content

Commit

Permalink
fixes pyca#4531 -- support encoding SCTs in certificates (pyca#5594)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored Dec 1, 2020
1 parent f133a30 commit 6d858c8
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
10 changes: 6 additions & 4 deletions src/_cffi_src/openssl/ct.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@
int SCT_set_source(SCT *, sct_source_t);
Cryptography_STACK_OF_SCT *sk_SCT_new_null(void);
void sk_SCT_free(Cryptography_STACK_OF_SCT *);
int sk_SCT_num(const Cryptography_STACK_OF_SCT *);
SCT *sk_SCT_value(const Cryptography_STACK_OF_SCT *, int);
int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *);
void SCT_LIST_free(Cryptography_STACK_OF_SCT *);
int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *);
Cryptography_STACK_OF_SCT *sk_SCT_new_null(void);
SCT *SCT_new(void);
int SCT_set1_log_id(SCT *, unsigned char *, size_t);
void SCT_set_timestamp(SCT *, uint64_t);
Expand Down Expand Up @@ -101,12 +102,13 @@
int (*SCT_set_source)(SCT *, sct_source_t) = NULL;
Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL;
void (*sk_SCT_free)(Cryptography_STACK_OF_SCT *) = NULL;
int (*sk_SCT_num)(const Cryptography_STACK_OF_SCT *) = NULL;
SCT *(*sk_SCT_value)(const Cryptography_STACK_OF_SCT *, int) = NULL;
int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL;
void (*SCT_LIST_free)(Cryptography_STACK_OF_SCT *) = NULL;
int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL;
Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL;
SCT *(*SCT_new)(void) = NULL;
int (*SCT_set1_log_id)(SCT *, unsigned char *, size_t) = NULL;
void (*SCT_set_timestamp)(SCT *, uint64_t) = NULL;
Expand Down
15 changes: 14 additions & 1 deletion src/cryptography/hazmat/backends/openssl/encode_asn1.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,11 +604,21 @@ def _encode_general_subtree(backend, subtrees):
gs = backend._lib.GENERAL_SUBTREE_new()
gs.base = _encode_general_name(backend, name)
res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs)
assert res >= 1
backend.openssl_assert(res >= 1)

return general_subtrees


def _encode_precert_signed_certificate_timestamps(backend, scts):
sct_stack = backend._lib.sk_SCT_new_null()
backend.openssl_assert(sct_stack != backend._ffi.NULL)
sct_stack = backend._ffi.gc(sct_stack, backend._lib.sk_SCT_free)
for sct in scts:
res = backend._lib.sk_SCT_push(sct_stack, sct._sct)
backend.openssl_assert(res >= 1)
return sct_stack


def _encode_nonce(backend, nonce):
return _encode_asn1_str_gc(backend, nonce.nonce)

Expand All @@ -630,6 +640,9 @@ def _encode_nonce(backend, nonce):
ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck,
ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints,
ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints,
ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
_encode_precert_signed_certificate_timestamps
),
}

_CRL_EXTENSION_ENCODE_HANDLERS = {
Expand Down
5 changes: 3 additions & 2 deletions src/cryptography/hazmat/bindings/openssl/_conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ def cryptography_has_sct():
"SCT_get0_signature",
"SCT_get_timestamp",
"SCT_set_source",
"sk_SCT_new_null",
"sk_SCT_free",
"sk_SCT_num",
"sk_SCT_value",
"SCT_LIST_free",
"sk_SCT_push",
"sk_SCT_new_null",
"SCT_LIST_free",
"SCT_new",
"SCT_set1_log_id",
"SCT_set_timestamp",
Expand Down
27 changes: 27 additions & 0 deletions tests/x509/test_x509_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -5678,6 +5678,33 @@ def test_simple(self, backend):
== x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
)

@pytest.mark.supported(
only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
skip_message="Requires CT support",
)
def test_generate(self, backend):
cert = _load_cert(
os.path.join("x509", "badssl-sct.pem"),
x509.load_pem_x509_certificate,
backend,
)
scts = cert.extensions.get_extension_for_class(
x509.PrecertificateSignedCertificateTimestamps
).value
assert len(scts) == 1
[sct] = scts

private_key = RSA_KEY_2048.private_key(backend)
builder = _make_certbuilder(private_key).add_extension(
x509.PrecertificateSignedCertificateTimestamps([sct]),
critical=False,
)
cert = builder.sign(private_key, hashes.SHA256(), backend)
ext = cert.extensions.get_extension_for_class(
x509.PrecertificateSignedCertificateTimestamps
).value
assert list(ext) == [sct]

@pytest.mark.supported(
only_if=lambda backend: backend._lib.CRYPTOGRAPHY_IS_LIBRESSL,
skip_message="Requires LibreSSL",
Expand Down

0 comments on commit 6d858c8

Please sign in to comment.