What is the correct way to use OSSL_DECODER

Milan Kaše milan.kase at gmail.com
Tue Jan 11 15:51:13 UTC 2022


Hi,
in follow up to https://github.com/openssl/openssl/issues/17456 where
Matt Caswell writes

> The normal way of using the decoder APIs is to set up an OSSL_DECODER_CTX and then call OSSL_DECODER_from_bio or similar function to iterate through the available decoders to find the right one for the data that we are trying to decode.

I'm still struggling to get the OSSL_DECODER to work. I'm trying to
implement a provider with a store loader and use it to load a
certificate (and in the future also a private key) from my HSM-like
device and use them to sign a CMS. In my STORE_LOAD function I create
a new OSSL_DECODER_CTX and I add all the decoders enumerated with
OSSL_DECODER_do_all_provided. It is my understanding that during
decoding the best decoders are selected automatically (in this case
PEM -> DER -> X509). Then I read certificate from the HSM in PEM
format and use OSSL_DECODER_from_data to construct X509 instance. This
seems fine until later when CMS_add1_signer calls
X509_check_private_key and it turns out that the *public* key from the
decoded certificate is empty (X509->cert_info.key.pkey is NULL). It
seems that x509_pubkey_ex_d2i_ex fails to decode the public key using
the inner context created by OSSL_DECODER_CTX_new_for_pkey.

command: openssl cms -sign -signer myprov:cert=0014 -provider myprov

provider (interesting parts):
int OSSL_provider_init() {
   ...
   OSSL_PROVIDER_load(myprov->libctx, "default"); // I load default
provider into child lib ctx
   ...
}

int store_load(void *loaderctx, OSSL_CALLBACK *object_cb, void
*object_cbarg, ...) {
  char *cert_pem = "----BEGIN CERTIFICATE..." // I load certificate from HSM
  OSSL_DECODER_CTX *dctx = OSSL_DECODER_CTX_new();
  OSSL_DECODER_do_add_provided(loader->libctx, add_decoder, dctx);
  OSSL_DECODER_CTX_set_input_type(dctx, "pem");
  OSSL_DECODER_CTX_set_input_structure(dctx, "Certificate");
  OSSL_DECODER_CTX_set_construct(dctx, constructor);
  struct closure closure = { .callback = object_cb, .arg = object_cbarg };
  OSSL_DECODER_CTX_set_construct_data(dctx, &closure);
  return OSSL_DECODER_from_data(dctx, pem, strlen(pem));
}

Certificates obtained through the default file loader are ok. I don't
know how to populate DECODER_CTX with actual DECODERs. File loader
uses some relatively complex algorithm which I am unable to
comprehend.

Thanks,
Milan


More information about the openssl-users mailing list