From 762e640f88447a4d2a4a41f4fffb81b7a3f28a78 Mon Sep 17 00:00:00 2001 From: Florian Wernli Date: Fri, 16 Feb 2024 14:44:50 +0100 Subject: [PATCH] decoder: return certificates when decoding pem --- src/decoder.c | 81 +++++++++++++++++++++++++++++++--------------- src/provider.h | 1 + src/store.c | 2 +- tests/tpem_encoder | 17 +++++----- 4 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/decoder.c b/src/decoder.c index 01c1f13e..03b148bb 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -75,37 +75,21 @@ static int filter_for_desired_data_type(const OSSL_PARAM params[], void *arg) if (p && OSSL_PARAM_get_utf8_string_ptr(p, &data_type) && 0 == strcmp(cbdata->desired_data_type, data_type)) { - cbdata->cb(params, cbdata->cbarg); + return cbdata->cb(params, cbdata->cbarg); } - P11PROV_debug("%s %p %s", cbdata->desired_data_type, p, data_type); - return RET_OSSL_CARRY_ON_DECODING; } -static int p11prov_der_decoder_p11prov_obj_decode( - const char *desired_data_type, void *inctx, OSSL_CORE_BIO *cin, - int selection, OSSL_CALLBACK *object_cb, void *object_cbarg, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +static int load_obj(struct desired_data_type_cbdata *cbdata, + const P11PROV_DECODER_CTX *ctx, const unsigned char *der, + long der_len, OSSL_CALLBACK *object_cb, void *object_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) { - P11PROV_DECODER_CTX *const ctx = inctx; - P11PROV_PK11_URI *obj = NULL; - BIO *bin; int ret = RET_OSSL_CARRY_ON_DECODING; + P11PROV_PK11_URI *obj = NULL; char *uri = NULL; - bin = BIO_new_from_core_bio(p11prov_ctx_get_libctx(ctx->provctx), cin); - if (!bin) { - P11PROV_debug("P11 DECODER BIO_new_from_core_bio failed"); - goto done; - } - - const unsigned char *der; - long der_len = BIO_get_mem_data(bin, &der); - if (der_len <= 0) { - P11PROV_debug("P11 DECODER BIO_get_mem_data failed"); - goto done; - } obj = d2i_P11PROV_PK11_URI(NULL, &der, der_len); if (!obj) { P11PROV_debug("P11 KEY DECODER d2i_P11PROV_PK11_URI failed"); @@ -123,18 +107,52 @@ static int p11prov_der_decoder_p11prov_obj_decode( p11prov_set_error_mark(ctx->provctx); - struct desired_data_type_cbdata cbdata = { desired_data_type, object_cb, - object_cbarg }; p11prov_store_direct_fetch(ctx->provctx, uri, filter_for_desired_data_type, - &cbdata, pw_cb, pw_cbarg); + cbdata, pw_cb, pw_cbarg); + ret = RET_OSSL_STOP_DECODING; p11prov_pop_error_to_mark(ctx->provctx); p11prov_clear_last_error_mark(ctx->provctx); - done: OPENSSL_free(uri); P11PROV_PK11_URI_free(obj); + return ret; +} + +static int p11prov_der_decoder_p11prov_obj_decode( + const char *desired_data_type, void *inctx, OSSL_CORE_BIO *cin, + int selection, OSSL_CALLBACK *object_cb, void *object_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + const P11PROV_DECODER_CTX *ctx = inctx; + BIO *bin; + unsigned char *der = NULL; + long der_len; + int ret = RET_OSSL_CARRY_ON_DECODING; + + bin = BIO_new_from_core_bio(p11prov_ctx_get_libctx(ctx->provctx), cin); + if (!bin) { + P11PROV_debug("P11 DECODER BIO_new_from_core_bio failed"); + goto done; + } + + der_len = BIO_get_mem_data(bin, &der); + if (der_len <= 0) { + P11PROV_debug("P11 DECODER BIO_get_mem_data failed"); + goto done; + } + + struct desired_data_type_cbdata cbdata = { + .desired_data_type = desired_data_type, + .cb = object_cb, + .cbarg = object_cbarg, + }; + + ret = load_obj(&cbdata, ctx, der, der_len, object_cb, object_cbarg, pw_cb, + pw_cbarg); + +done: BIO_free(bin); P11PROV_debug("der decoder (carry on:%d)", ret); return ret; @@ -196,6 +214,17 @@ static int p11prov_pem_decoder_p11prov_der_decode( if (PEM_read_bio(bin, &pem_label, &pem_header, &der_data, &der_len) > 0 && strcmp(pem_label, P11PROV_PEM_LABEL) == 0) { + + /* special case certificates */ + struct desired_data_type_cbdata cbdata = { + .desired_data_type = P11PROV_NAME_CERTIFICATE, + .cb = object_cb, + .cbarg = object_cbarg, + }; + load_obj(&cbdata, ctx, der_data, der_len, object_cb, object_cbarg, + pw_cb, pw_cbarg); + /* */ + params[0] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, der_data, der_len); params[1] = OSSL_PARAM_construct_utf8_string( diff --git a/src/provider.h b/src/provider.h index 8294c119..5fdf4a0e 100644 --- a/src/provider.h +++ b/src/provider.h @@ -59,6 +59,7 @@ #define P11PROV_DESCS_RAND "PKCS11 Random Generator" #define P11PROV_NAMES_RSAKEY "RSA" #define P11PROV_DESCS_RSAKEY "PKCS11 RSA Key" +#define P11PROV_NAME_CERTIFICATE "CERTIFICATE" #define P11PROV_PARAM_URI "pkcs11_uri" #define P11PROV_PARAM_KEY_USAGE "pkcs11_key_usage" diff --git a/src/store.c b/src/store.c index 330f2fd0..27d2e5f3 100644 --- a/src/store.c +++ b/src/store.c @@ -384,7 +384,7 @@ static int p11prov_store_load(void *pctx, OSSL_CALLBACK *object_cb, break; case CKO_CERTIFICATE: object_type = OSSL_OBJECT_CERT; - data_type = (char *)"CERTIFICATE"; + data_type = (char *)P11PROV_NAME_CERTIFICATE; cert = p11prov_obj_get_attr(obj, CKA_VALUE); if (cert == NULL) { return RET_OSSL_ERR; diff --git a/tests/tpem_encoder b/tests/tpem_encoder index b1fd65da..1361c2c8 100755 --- a/tests/tpem_encoder +++ b/tests/tpem_encoder @@ -145,18 +145,19 @@ if [[ ! ${DATA} =~ "Total found: 1" ]]; then echo "Should return public key" exit 1 fi -ossl 'storeutl "${TMPPDIR}/puburi-key.pem"' | grep "Total found: 1" -title PARA "Test ambiguous key is unusable" - -make-uri-pem "${BASEURI}" "${TMPPDIR}/baseuri-key.pem" -FAIL=0 +title PARA "Test certificate is usable" +make-uri-pem "${ECCRTURI}" "${TMPPDIR}/eccrturi-cert.pem" ossl ' -pkey -in "${TMPPDIR}/baseuri-key.pem"' || FAIL=1 -if [ $FAIL -eq 0 ]; then - echo "Should fail for now URI from PEM need to be unique" +storeutl + -out "${TMPPDIR}/storeutl-eccrturi-cert.txt" + "${TMPPDIR}/eccrturi-cert.pem"' +DATA=$(cat "${TMPPDIR}/storeutl-eccrturi-cert.txt") +if [[ ! ${DATA} =~ "Total found: 1" ]]; then + echo "Should return certificate" exit 1 fi + exit 0