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
42 changes: 42 additions & 0 deletions certs/crl.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com
Last Update: Jun 11 21:44:40 2026 GMT
Next Update: Mar 7 21:44:40 2029 GMT
CRL extensions:
X509v3 CRL Number:
2
Revoked Certificates:
Serial Number: 02
Revocation Date: Jun 11 21:44:40 2026 GMT
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
53:dc:68:3d:93:47:65:03:ca:a5:07:e8:13:26:72:94:02:3e:
6f:c2:8d:27:fc:f6:64:c6:06:77:bc:1f:26:e4:6e:87:95:f8:
fe:18:ee:d7:24:f9:b8:ad:74:85:76:ec:55:92:6c:58:4f:59:
66:68:f1:17:78:dc:39:6c:4c:2b:38:1e:d4:07:ac:b8:2c:f5:
d4:2b:c1:96:09:79:8a:a2:e2:d1:e5:1e:32:92:1f:12:81:a6:
ad:4d:ce:9d:9a:08:6f:56:e4:fe:58:8d:da:b2:88:54:6a:5a:
19:07:9c:1b:de:4f:7a:62:dd:35:75:25:29:a2:9a:ba:19:a9:
32:fe:61:ad:bb:70:06:0f:37:62:7c:02:61:3e:43:22:e9:62:
12:f2:f7:0b:18:3a:a2:fb:0a:e9:2d:0b:68:fc:e1:41:51:64:
7c:c8:8c:4c:d6:fc:90:0b:24:e7:e3:52:a5:e9:09:f8:85:e9:
73:ca:b2:00:19:05:d6:5f:99:af:bb:9a:41:0f:48:a7:b4:25:
78:d0:b6:ce:3b:3c:c2:2d:fa:65:2e:65:5e:67:01:01:aa:f7:
4d:ad:5a:8f:b4:30:d4:9c:0c:e9:b6:c5:b6:4a:b6:eb:3a:01:
d1:92:b4:94:e8:62:e3:d3:37:ff:aa:38:8d:9f:e3:de:9c:b1:
70:c5:11:64
-----BEGIN X509 CRL-----
MIICBTCB7gIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMxEDAOBgNV
BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3Ro
MRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x
IDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tFw0yNjA2MTEyMTQ0NDBa
Fw0yOTAzMDcyMTQ0NDBaMBQwEgIBAhcNMjYwNjExMjE0NDQwWqAOMAwwCgYDVR0U
BAMCAQIwDQYJKoZIhvcNAQELBQADggEBAFPcaD2TR2UDyqUH6BMmcpQCPm/CjSf8
9mTGBne8HybkboeV+P4Y7tck+bitdIV27FWSbFhPWWZo8Rd43DlsTCs4HtQHrLgs
9dQrwZYJeYqi4tHlHjKSHxKBpq1Nzp2aCG9W5P5YjdqyiFRqWhkHnBveT3pi3TV1
JSmimroZqTL+Ya27cAYPN2J8AmE+QyLpYhLy9wsYOqL7CuktC2j84UFRZHzIjEzW
/JALJOfjUqXpCfiF6XPKsgAZBdZfma+7mkEPSKe0JXjQts47PMIt+mUuZV5nAQGq
902tWo+0MNScDOm2xbZKtus6AdGStJToYuPTN/+qOI2f496csXDFEWQ=
-----END X509 CRL-----
2 changes: 2 additions & 0 deletions certs/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# for test_rsa.c
dist_noinst_SCRIPTS += certs/server-key.pem
dist_noinst_SCRIPTS += certs/server-cert.pem
dist_noinst_SCRIPTS += certs/ca-cert.pem
dist_noinst_SCRIPTS += certs/crl.pem

# for test_ecc.c
dist_noinst_SCRIPTS += certs/server-ecc.pem
Expand Down
5 changes: 5 additions & 0 deletions include/wolfprovider/alg_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ typedef void (*DFUNC)(void);

/* Decoder names. */
#define WP_NAMES_DER "DER"
/* Private name: only the file store fetches these, so no other decoder chain
* picks them up. */
#define WP_NAMES_DER2OBJ "wolfprov-der2obj"

/* Store names. */
#define WP_NAMES_FILE "file"
Expand Down Expand Up @@ -547,6 +550,8 @@ extern const OSSL_DISPATCH wp_mldsa87_spki_decoder_functions[];
extern const OSSL_DISPATCH wp_mldsa87_pki_decoder_functions[];
extern const OSSL_DISPATCH wp_pem_to_der_decoder_functions[];
extern const OSSL_DISPATCH wp_epki_to_pki_decoder_functions[];
extern const OSSL_DISPATCH wp_der_to_cert_decoder_functions[];
extern const OSSL_DISPATCH wp_der_to_crl_decoder_functions[];
/* Encode implementations. */
extern const OSSL_DISPATCH wp_rsa_spki_der_encoder_functions[];
extern const OSSL_DISPATCH wp_rsa_spki_pem_encoder_functions[];
Expand Down
270 changes: 251 additions & 19 deletions src/wp_file_store.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,210 @@ static int wp_file_decoder_set_input_structure(OSSL_DECODER_CTX* decCtx,
return ok;
}

/**
* DER certificate/CRL to object decoder context.
*/
typedef struct wp_Der2Obj {
/** Provider context - used to read the core BIO. */
WOLFPROV_CTX* provCtx;
} wp_Der2Obj;

/**
* Create a new DER to object decoder context.
*
* @param [in] provCtx Provider context.
* @return Pointer to context.
*/
static wp_Der2Obj* wp_der2obj_newctx(WOLFPROV_CTX* provCtx)
{
wp_Der2Obj* ctx = NULL;

if (wolfssl_prov_is_running()) {
ctx = (wp_Der2Obj*)OPENSSL_zalloc(sizeof(*ctx));
}
if (ctx != NULL) {
ctx->provCtx = provCtx;
}

return ctx;
}

/**
* Dispose of DER to object decoder context.
*
* @param [in] ctx DER to object decoder context.
*/
static void wp_der2obj_freectx(wp_Der2Obj* ctx)
{
OPENSSL_free(ctx);
}

/**
* Read exactly len bytes from the BIO.
*
* @param [in] bio BIO to read from.
* @param [out] buf Buffer to read into.
* @param [in] len Number of bytes to read. At most INT_MAX.
* @return 1 when all bytes were read.
* @return 0 otherwise.
*/
static int wp_der2obj_read(BIO* bio, unsigned char* buf, word32 len)
{
int readLen = 1;

while ((len > 0) && (readLen > 0)) {
readLen = BIO_read(bio, buf, (int)len);
if (readLen > 0) {
buf += readLen;
len -= (word32)readLen;
}
}

return len == 0;
}

/**
* Read the header of the DER SEQUENCE at the BIO's position.
*
* @param [in] bio BIO to read from.
* @param [out] hdr Buffer of at least 6 bytes to hold the header.
* @param [out] hdrLen Length of the header in bytes.
* @param [out] objLen Length of the SEQUENCE including its header.
* @return 1 when a DER SEQUENCE header was read.
* @return 0 otherwise.
*/
static int wp_der2obj_read_hdr(BIO* bio, unsigned char* hdr, word32* hdrLen,
word32* objLen)
{
int ok;
word32 n = 0;
word32 contentLen = 0;
word32 i;

ok = wp_der2obj_read(bio, hdr, 2) && (hdr[0] == 0x30);
if (ok && (hdr[1] < 0x80)) {
contentLen = hdr[1];
}
else if (ok) {
n = hdr[1] & 0x7f;
ok = (n >= 1) && (n <= 4) && wp_der2obj_read(bio, hdr + 2, n);
for (i = 0; ok && (i < n); i++) {
contentLen = (contentLen << 8) | hdr[2 + i];
}
}
/* Keep the whole object within BIO_read's int length. */
if (ok && (contentLen > (word32)INT_MAX - 2 - n)) {
ok = 0;
}
if (ok) {
*hdrLen = 2 + n;
*objLen = 2 + n + contentLen;
}

return ok;
}

/**
* Pass DER data up as a certificate or CRL object, unparsed.
*
* The file store needs this for DER input, as OpenSSL's file store does
* (file_store_any2obj.c): the PEM to DER decoder does the same for PEM input.
* No cryptographic operation is performed.
*
* @param [in] ctx DER to object decoder context.
* @param [in, out] coreBio BIO wrapped for the core.
* @param [in] obj Object type: OSSL_OBJECT_CERT or OSSL_OBJECT_CRL.
* @param [in] dataCb Callback to pass the object to.
* @param [in] dataCbArg Argument to pass to callback.
* @return 1 on success or when the data is not a DER SEQUENCE.
* @return 0 on failure.
*/
static int wp_der2obj_decode(wp_Der2Obj* ctx, OSSL_CORE_BIO* coreBio, int obj,
OSSL_CALLBACK* dataCb, void* dataCbArg)
{
int ok = 1;
BIO* bio;
unsigned char hdr[6];
word32 hdrLen = 0;
word32 objLen = 0;
unsigned char* data = NULL;
OSSL_PARAM params[3];

WOLFPROV_ENTER(WP_LOG_COMP_PROVIDER, "wp_der2obj_decode");

bio = wp_corebio_get_bio(ctx->provCtx, coreBio);
if (bio == NULL) {
ok = 0;
}
/* Read one object only so the next load starts at the next object.
* Not a complete DER SEQUENCE: not for this decoder, let others try. */
else if (wp_der2obj_read_hdr(bio, hdr, &hdrLen, &objLen)) {
data = (unsigned char*)OPENSSL_malloc(objLen);
if (data == NULL) {
ok = 0;
}
else {
XMEMCPY(data, hdr, hdrLen);
}
if (ok && wp_der2obj_read(bio, data + hdrLen, objLen - hdrLen)) {
params[0] = OSSL_PARAM_construct_octet_string(
OSSL_OBJECT_PARAM_DATA, data, objLen);
params[1] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &obj);
params[2] = OSSL_PARAM_construct_end();
ok = dataCb(params, dataCbArg);
}
}
OPENSSL_free(data);
BIO_free(bio);

WOLFPROV_LEAVE(WP_LOG_COMP_PROVIDER, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok);
return ok;
}

/**
* Decode DER certificate: pass it up as a certificate object.
*/
static int wp_der2cert_decode(wp_Der2Obj* ctx, OSSL_CORE_BIO* coreBio,
int selection, OSSL_CALLBACK* dataCb, void* dataCbArg,
OSSL_PASSPHRASE_CALLBACK* pwCb, void* pwCbArg)
{
(void)selection;
(void)pwCb;
(void)pwCbArg;
return wp_der2obj_decode(ctx, coreBio, OSSL_OBJECT_CERT, dataCb,
dataCbArg);
}

/**
* Decode DER CRL: pass it up as a CRL object.
*/
static int wp_der2crl_decode(wp_Der2Obj* ctx, OSSL_CORE_BIO* coreBio,
Comment thread
MarkAtwood marked this conversation as resolved.
Resolved
int selection, OSSL_CALLBACK* dataCb, void* dataCbArg,
OSSL_PASSPHRASE_CALLBACK* pwCb, void* pwCbArg)
{
(void)selection;
(void)pwCb;
(void)pwCbArg;
return wp_der2obj_decode(ctx, coreBio, OSSL_OBJECT_CRL, dataCb,
dataCbArg);
}

/** Dispatch table for DER certificate to object decoder. */
const OSSL_DISPATCH wp_der_to_cert_decoder_functions[] = {
{ OSSL_FUNC_DECODER_NEWCTX, (DFUNC)wp_der2obj_newctx },
{ OSSL_FUNC_DECODER_FREECTX, (DFUNC)wp_der2obj_freectx },
{ OSSL_FUNC_DECODER_DECODE, (DFUNC)wp_der2cert_decode },
{ 0, NULL }
};

/** Dispatch table for DER CRL to object decoder. */
const OSSL_DISPATCH wp_der_to_crl_decoder_functions[] = {
{ OSSL_FUNC_DECODER_NEWCTX, (DFUNC)wp_der2obj_newctx },
{ OSSL_FUNC_DECODER_FREECTX, (DFUNC)wp_der2obj_freectx },
{ OSSL_FUNC_DECODER_DECODE, (DFUNC)wp_der2crl_decode },
{ 0, NULL }
};

/**
* Information about supported decoders from file data.
*/
Expand Down Expand Up @@ -404,6 +608,41 @@ static int wp_file_decoder_prop_query(const char* base, const char* caller,
return ok;
}

/**
* Fetch a decoder and add it to the decoder context.
*
* @param [in] ctx File system context object.
* @param [in, out] decCtx OpenSSL decoder context.
* @param [in] name Decoder name.
* @param [in] propQuery Structure property query. May be NULL.
* @return 1 on success.
* @return 0 on failure.
*/
static int wp_file_add_decoder(wp_FileCtx* ctx, OSSL_DECODER_CTX* decCtx,
const char* name, const char* propQuery)
{
int ok = 1;
OSSL_DECODER* decoder = NULL;
char* query = NULL;

if (!wp_file_decoder_prop_query(propQuery, ctx->propQuery, &query)) {
ok = 0;
}
if (ok) {
decoder = OSSL_DECODER_fetch(ctx->provCtx->libCtx, name, query);
if (decoder == NULL) {
ok = 0;
}
}
if (ok && !OSSL_DECODER_CTX_add_decoder(decCtx, decoder)) {
ok = 0;
}
OSSL_DECODER_free(decoder);
OPENSSL_free(query);

return ok;
}

/**
* Set the decoders into the decoder context.
*
Expand All @@ -416,29 +655,22 @@ static int wp_file_set_decoder(wp_FileCtx* ctx, OSSL_DECODER_CTX* decCtx)
{
int ok = 1;
size_t i;
OSSL_DECODER* decoder;
char* query = NULL;

WOLFPROV_ENTER(WP_LOG_COMP_PROVIDER, "wp_file_set_decoder");

for (i = 0; ok && (i < WP_DECODERS_SIZE); i++) {
if (!wp_file_decoder_prop_query(wp_decoders[i].propQuery,
ctx->propQuery, &query)) {
ok = 0;
}
if (ok) {
decoder = OSSL_DECODER_fetch(ctx->provCtx->libCtx,
wp_decoders[i].name, query);
if (decoder == NULL) {
ok = 0;
}
if (ok && !OSSL_DECODER_CTX_add_decoder(decCtx, decoder)) {
ok = 0;
}
OSSL_DECODER_free(decoder);
}
OPENSSL_free(query);
query = NULL;
ok = wp_file_add_decoder(ctx, decCtx, wp_decoders[i].name,
wp_decoders[i].propQuery);
}
/* DER certificates and CRLs are passed up unparsed, as OpenSSL's file
* store does. Only added when one is expected: key loading is unchanged. */
if (ok && (ctx->type == OSSL_STORE_INFO_CERT)) {
ok = wp_file_add_decoder(ctx, decCtx, WP_NAMES_DER2OBJ,
"structure=Certificate");
}
else if (ok && (ctx->type == OSSL_STORE_INFO_CRL)) {
ok = wp_file_add_decoder(ctx, decCtx, WP_NAMES_DER2OBJ,
"structure=CertificateList");
}

WOLFPROV_LEAVE(WP_LOG_COMP_PROVIDER, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok);
Expand Down
8 changes: 8 additions & 0 deletions src/wp_wolfprov.c
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,14 @@ static const OSSL_ALGORITHM wolfprov_decoder[] = {
wp_epki_to_pki_decoder_functions,
"" },

/* DER certificate and CRL pass-through for the file store. */
{ WP_NAMES_DER2OBJ, WP_DECODER_PROPERTIES(Certificate),
wp_der_to_cert_decoder_functions,
"" },
{ WP_NAMES_DER2OBJ, WP_DECODER_PROPERTIES(CertificateList),
wp_der_to_crl_decoder_functions,
"" },

{ NULL, NULL, NULL, NULL }
};

Expand Down
Loading
Loading