Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SHELL := /bin/bash
SHELL := /usr/bin/env bash

PY_MODULE := limbo

Expand Down Expand Up @@ -51,6 +51,9 @@ edit:
run: $(NEEDS_VENV)
@./$(VENV_BIN)/python -m $(PY_MODULE) $(ARGS)

assets: $(NEEDS_VENV) $(PY_MODULE)/_assets/scripts/generate_crl.py
@./$(VENV_BIN)/python -m limbo._assets.scripts.generate_crl

limbo-schema.json: $(NEEDS_VENV) $(PY_MODULE)/models.py
$(MAKE) run ARGS="schema -o limbo-schema.json"

Expand Down
60 changes: 53 additions & 7 deletions harness/openssl/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
#include <iostream>
#include <sstream>
#include <algorithm>
#include <optional>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/opensslv.h>
#include <openssl/x509_vfy.h>
Expand Down Expand Up @@ -42,6 +44,29 @@ using X509_CRL_ptr = std::unique_ptr<X509_CRL, decltype(&X509_CRL_free)>;
std::exit(1);
}

void warn(const std::string &msg)
{
std::cerr << "Warning: " << msg << std::endl;
}

std::string get_errors()
{
BIO_ptr mem(BIO_new(BIO_s_mem()), BIO_free);
char *mem_ptr = nullptr;

ERR_print_errors(mem.get());
BIO_get_mem_data(mem.get(), &mem_ptr);

if (mem_ptr == nullptr)
{
return "<no errors from OpenSSL>";
}
else
{
return std::string(mem_ptr);
}
}

std::map<std::string, int> create_eku_map()
{
std::map<std::string, int> m;
Expand All @@ -64,14 +89,15 @@ X509_ptr pem_to_x509(const std::string &pem)
return X509_ptr(cert, X509_free);
}

X509_CRL_ptr pem_to_crl(const std::string &pem)
std::optional<X509_CRL_ptr> pem_to_crl(const std::string &pem)
{
X509_CRL *crl = nullptr;
BIO_ptr crl_bio(BIO_new_mem_buf(pem.data(), pem.length()), BIO_free);

if (!PEM_read_bio_X509_CRL(crl_bio.get(), &crl, 0, NULL))
{
barf("failed to parse CRL");
warn("failed to parse CRL");
return std::nullopt;
}

return X509_CRL_ptr(crl, X509_CRL_free);
Expand Down Expand Up @@ -114,6 +140,8 @@ json skip(const std::string &id, const std::string &reason)
json evaluate_testcase(const json &testcase)
{
auto id = testcase["id"].template get<std::string>();
std::ostringstream errors;

std::cerr << "Evaluating case: " << id << std::endl;

if (testcase["validation_kind"] != "SERVER")
Expand Down Expand Up @@ -157,14 +185,28 @@ json evaluate_testcase(const json &testcase)
// Add CRLs to the store if present
if (testcase.contains("crls") && !testcase["crls"].empty())
{
int total_crls = testcase["crls"].size();
int parsed_crls = 0;
for (auto &crl_pem : testcase["crls"])
{
auto crl = pem_to_crl(crl_pem.template get<std::string>());
X509_STORE_add_crl(store.get(), crl.get());
if (crl)
{
parsed_crls++;
X509_STORE_add_crl(store.get(), crl->get());
}
}

// Enable CRL checking
X509_STORE_set_flags(store.get(), X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
if (parsed_crls == total_crls)
{
// Enable CRL checking
X509_STORE_set_flags(store.get(), X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
else
{
errors << total_crls - parsed_crls << " / " << total_crls << " CRLs failed to parse\n";
errors << get_errors() << "\n";
}
}

auto untrusted = x509_stack(testcase["untrusted_intermediates"]);
Expand Down Expand Up @@ -260,11 +302,15 @@ json evaluate_testcase(const json &testcase)
std::cerr << "\tPASS" << std::endl;
}

if (!does_pass)
{
errors << X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx.get()));
};

return {
{"id", id},
{"actual_result", does_pass ? "SUCCESS" : "FAILURE"},
// NOTE: default-constructed json{} is null.
{"context", does_pass ? json{} : X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx.get()))},
{"context", errors.str()},
};
}

Expand Down
1,298 changes: 679 additions & 619 deletions limbo.json

Large diffs are not rendered by default.

Binary file added limbo/_assets/bad_version.crl
Binary file not shown.
11 changes: 11 additions & 0 deletions limbo/_assets/crl_cases_ca.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBjzCCATWgAwIBAgIUbPHJLXNKcbhHZxBsO9E9olILsPQwCgYIKoZIzj0EAwIw
GjEYMBYGA1UEAwwPeDUwOS1saW1iby1yb290MCAXDTcwMDEwMTAwMDAwMVoYDzI5
NjkwNTAzMDAwMDAxWjAaMRgwFgYDVQQDDA94NTA5LWxpbWJvLXJvb3QwWTATBgcq
hkjOPQIBBggqhkjOPQMBBwNCAAQjhCLhcUDtiSSAenrdhyuMvIZXaP4qEtsU3QnG
cBwo6A33tzSAgK5bon06jwSEHmOQnALgMagE7ZwvJlegsMTro1cwVTAPBgNVHRMB
Af8EBTADAQH/MAsGA1UdDwQEAwICBDAWBgNVHREEDzANggtleGFtcGxlLmNvbTAd
BgNVHQ4EFgQU4UJBuh7fj1ImHijggnpj9x+SQI0wCgYIKoZIzj0EAwIDSAAwRQIh
AMduyJfCeNC1HLvEOJEuhHUJHRqH5xzimK7rUJo/A9JMAiBlZ7st5Q81gBWgH8F1
jOhAhe6Kj+HJ+ln6+w3Ln/gwHQ==
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions limbo/_assets/crl_cases_ca_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIhnRsMDQjBGMfB+RRIgc7yr6KkLdKSrSnFFasj8AHYRoAoGCCqGSM49
AwEHoUQDQgAEI4Qi4XFA7YkkgHp63YcrjLyGV2j+KhLbFN0JxnAcKOgN97c0gICu
W6J9Oo8EhB5jkJwC4DGoBO2cLyZXoLDE6w==
-----END EC PRIVATE KEY-----
12 changes: 12 additions & 0 deletions limbo/_assets/crl_cases_leaf.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBwzCCAWigAwIBAgIUJYxsxc5Qcq8Wf33wKoVQbKNYpKQwCgYIKoZIzj0EAwIw
GjEYMBYGA1UEAwwPeDUwOS1saW1iby1yb290MCAXDTcwMDEwMTAwMDAwMVoYDzI5
NjkwNTAzMDAwMDAxWjAeMRwwGgYDVQQDDBNyZXZva2VkLmV4YW1wbGUuY29tMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEGnJLA/51lFjA4p+v1wDXqCkMqd+gxbj
j4rsJdDo1H6ZbKqht/GCdmd7lK3OJAi64pp4othmof4/RRbYi3FzHqOBhTCBgjAd
BgNVHQ4EFgQU6/ippqd7TomJSAN7C9FK6FMBc2owHwYDVR0jBBgwFoAU4UJBuh7f
j1ImHijggnpj9x+SQI0wCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMB
MB4GA1UdEQQXMBWCE3Jldm9rZWQuZXhhbXBsZS5jb20wCgYIKoZIzj0EAwIDSQAw
RgIhAPZGZPeCj/8vrjztJywL7cIkZnDOa2OXoEqYGwlK7dGnAiEA2b6+m2u2L+ZI
+B9pGXWK3qSa/J6eESolJhKrrpevtH4=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions limbo/_assets/crl_cases_leaf_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICDY29t+MRWQJBj1yHDVwCLewvHs1jOZ45xkyezNjdp2oAoGCCqGSM49
AwEHoUQDQgAEEGnJLA/51lFjA4p+v1wDXqCkMqd+gxbjj4rsJdDo1H6ZbKqht/GC
dmd7lK3OJAi64pp4othmof4/RRbYi3FzHg==
-----END EC PRIVATE KEY-----
71 changes: 71 additions & 0 deletions limbo/_assets/crl_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
SEQUENCE {
SEQUENCE {
INTEGER { {{ version }} }
SEQUENCE {
# ecdsa-with-SHA256
OBJECT_IDENTIFIER { 1.2.840.10045.4.3.2 }
}
SEQUENCE {
SET {
SEQUENCE {
# commonName
OBJECT_IDENTIFIER { 2.5.4.3 }
PrintableString { "x509-limbo-root" }
}
}

}
{# lastUpdate = 2025-01-01 to nextUpdate = 2025-01-30 #}
{{ last_update.to_der_ascii() }}
{{ next_update.to_der_ascii() }}
SEQUENCE {
{% for cert in certs %}
SEQUENCE {
INTEGER { `{{ cert.serial_hex_bytes }}` }
UTCTime { "{{ cert.revoke_at.value() }}" }
}
{% endfor %}
}
[0] {
SEQUENCE {
{% if ski %}
SEQUENCE {
# authorityKeyIdentifier
OBJECT_IDENTIFIER { 2.5.29.35 }
OCTET_STRING {
SEQUENCE {
[0 PRIMITIVE] { `{{ ski.hex() }}` }
}
}
}
{% endif %}
SEQUENCE {
# cRLNumber
OBJECT_IDENTIFIER { 2.5.29.20 }
OCTET_STRING {
INTEGER { `00` }
}
}
}
}
}

{#
we append the signature's DER post hoc, but here is the expected structure:

{% if signature %}
SEQUENCE {
# ecdsa-with-SHA256
OBJECT_IDENTIFIER { 1.2.840.10045.4.3.2 }
}
BIT_STRING {
`00`
SEQUENCE {
INTEGER { `{{ signature.r }}` }
INTEGER { `{{ signature.s }}` }
}
}
{% endif %}

#}
}
Binary file added limbo/_assets/generalized_time_2025.crl
Binary file not shown.
Empty file.
Loading
Loading