Skip to content

Commit

Permalink
CMP: add support for central key generation
Browse files Browse the repository at this point in the history
  • Loading branch information
rajeev-0 committed May 29, 2024
1 parent 410f50b commit ac93b80
Show file tree
Hide file tree
Showing 20 changed files with 460 additions and 82 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"crmf.h": "c"
}
}
47 changes: 44 additions & 3 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ static char *opt_profile = NULL;
/* certificate enrollment */
static char *opt_newkey = NULL;
static char *opt_newkeypass = NULL;
static int opt_centralkeygen = 0;
static char *opt_newkeytype = NULL;
static char *opt_newkeyout = NULL;
static char *opt_subject = NULL;
static int opt_days = 0;
static char *opt_reqexts = NULL;
Expand Down Expand Up @@ -229,7 +232,8 @@ typedef enum OPTION_choice {
OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO,
OPT_TEMPLATE, OPT_KEYSPEC,

OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT,
OPT_NEWKEY, OPT_NEWKEYPASS, OPT_CENTRALKEYGEN, OPT_NEWKEYTYPE,
OPT_NEWKEYOUT, OPT_SUBJECT,
OPT_DAYS, OPT_REQEXTS,
OPT_SANS, OPT_SAN_NODEFAULT,
OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
Expand Down Expand Up @@ -325,6 +329,12 @@ const OPTIONS cmp_options[] = {
{"newkey", OPT_NEWKEY, 's',
"Private or public key for the requested cert. Default: CSR key or client key"},
{"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"},
{"centralkeygen", OPT_CENTRALKEYGEN, '-',
"Request central (server-side) key generation. Default is local generation"},
{"newkeytype", OPT_NEWKEYTYPE, 's',
"Request key for ir/cr/kur of given type, e.g., EC:secp521r1"},
{"newkeyout", OPT_NEWKEYOUT, 's',
"File to save new key generated in central key generation"},
{"subject", OPT_SUBJECT, 's',
"Distinguished Name (DN) of subject to use in the requested cert template"},
{OPT_MORE_STR, 0, 0,
Expand Down Expand Up @@ -1671,11 +1681,27 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
if (!set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer"))
return 0;
if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) {
if (opt_reqin == NULL && opt_newkey == NULL
if (opt_reqin == NULL && opt_newkey == NULL && !opt_centralkeygen
&& opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key");
CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key."
"Neither central key generation is requested.");
return 0;
}
if (opt_popo == OSSL_CRMF_POPO_NONE && !opt_centralkeygen) {
CMP_info("POPO is disabled, using -centralkeygen");
opt_centralkeygen = 1;
}
if (opt_centralkeygen) {
if (opt_popo > OSSL_CRMF_POPO_NONE) {
CMP_err1("-popo value %d is inconsistent with -centralkeygen", opt_popo);
return 0;
}
if (opt_newkeyout == NULL) {
CMP_err("-newkeyout not given, nowhere to save newly generated key");
return 0;
}
opt_popo = OSSL_CRMF_POPO_NONE;
}
if (opt_newkey == NULL
&& opt_popo != OSSL_CRMF_POPO_NONE
&& opt_popo != OSSL_CRMF_POPO_RAVERIFIED) {
Expand Down Expand Up @@ -1723,6 +1749,12 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
CMP_warn1("-policies %s", msg);
if (opt_policy_oids != NULL)
CMP_warn1("-policy_oids %s", msg);
if (opt_centralkeygen)
CMP_warn1("-centralkeygen %s", msg);
if (opt_newkeytype != NULL)
CMP_warn1("-newkeytype %s", msg);
if (opt_newkeyout != NULL)
CMP_warn1("-newkeyout %s", msg);
if (opt_cmd != CMP_P10CR) {
if (opt_implicit_confirm)
CMP_warn1("-implicit_confirm %s, and 'p10cr'", msg);
Expand Down Expand Up @@ -2928,6 +2960,15 @@ static int get_opts(int argc, char **argv)
case OPT_NEWKEYPASS:
opt_newkeypass = opt_str();
break;
case OPT_CENTRALKEYGEN:
opt_centralkeygen = 1;
break;
case OPT_NEWKEYTYPE:
opt_newkeytype = opt_str();
break;
case OPT_NEWKEYOUT:
opt_newkeyout = opt_str();
break;
case OPT_SUBJECT:
opt_subject = opt_str();
break;
Expand Down
4 changes: 2 additions & 2 deletions crypto/cmp/cmp_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -889,15 +889,15 @@ ASN1_CHOICE(OSSL_CMP_CERTORENCCERT) = {
/* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.certificate, X509, 0),
ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.encryptedCert,
OSSL_CRMF_ENCRYPTEDVALUE, 1),
OSSL_CRMF_ENCRYPTEDKEY, 1),
} ASN1_CHOICE_END(OSSL_CMP_CERTORENCCERT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)

ASN1_SEQUENCE(OSSL_CMP_CERTIFIEDKEYPAIR) = {
ASN1_SIMPLE(OSSL_CMP_CERTIFIEDKEYPAIR, certOrEncCert,
OSSL_CMP_CERTORENCCERT),
ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, privateKey,
OSSL_CRMF_ENCRYPTEDVALUE, 0),
OSSL_CRMF_ENCRYPTEDKEY, 0),
ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, publicationInfo,
OSSL_CRMF_PKIPUBLICATIONINFO, 1)
} ASN1_SEQUENCE_END(OSSL_CMP_CERTIFIEDKEYPAIR)
Expand Down
4 changes: 3 additions & 1 deletion crypto/cmp/cmp_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,10 +505,12 @@ static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
{
char buf[OSSL_CMP_PKISI_BUFLEN];
X509 *crt = NULL;
EVP_PKEY *privkey;

if (!ossl_assert(ctx != NULL && crep != NULL))
return NULL;

privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
switch (ossl_cmp_pkisi_get_status(crep->status)) {
case OSSL_CMP_PKISTATUS_waiting:
ossl_cmp_err(ctx,
Expand Down Expand Up @@ -546,7 +548,7 @@ static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
crt = ossl_cmp_certresponse_get1_cert(ctx, crep);
crt = ossl_cmp_certresponse_get1_cert_key(crep, ctx, privkey);
if (crt == NULL) /* according to PKIStatus, we can expect a cert */
ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);

Expand Down
6 changes: 6 additions & 0 deletions crypto/cmp/cmp_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_EXPECTED_POLLREQ), "expected pollreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
"failed building own chain"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY),
"failed extracting central gen key"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
"failed extracting pubkey"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM),
Expand All @@ -97,6 +99,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
"invalid rootcakeyupdate"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CENTRAL_GEN_KEY),
"missing central gen key"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
"missing key input for creating protection"},
Expand Down Expand Up @@ -151,6 +155,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"transactionid unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY),
"unexpected central gen key"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
"unexpected certprofile"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST),
Expand Down
8 changes: 4 additions & 4 deletions crypto/cmp/cmp_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ typedef struct ossl_cmp_certorenccert_st {
int type;
union {
X509 *certificate;
OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert;
OSSL_CRMF_ENCRYPTEDKEY *encryptedCert;
} value;
} OSSL_CMP_CERTORENCCERT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
Expand All @@ -326,7 +326,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
*/
typedef struct ossl_cmp_certifiedkeypair_st {
OSSL_CMP_CERTORENCCERT *certOrEncCert;
OSSL_CRMF_ENCRYPTEDVALUE *privateKey;
OSSL_CRMF_ENCRYPTEDKEY *privateKey;
OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo;
} OSSL_CMP_CERTIFIEDKEYPAIR;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
Expand Down Expand Up @@ -988,8 +988,8 @@ ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
OSSL_CMP_CERTRESPONSE *
ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
int rid);
X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_CERTRESPONSE *crep);
X509 *ossl_cmp_certresponse_get1_cert_key(const OSSL_CMP_CERTRESPONSE *crep,
const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg);

Expand Down
56 changes: 46 additions & 10 deletions crypto/cmp/cmp_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR,
OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
{
OSSL_CRMF_MSG *crm = NULL;
int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD)
== OSSL_CRMF_POPO_NONE;
X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
/* refcert defaults to current client cert */
EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
Expand All @@ -311,6 +313,7 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
: X509_get_issuer_name(refcert);
int crit = ctx->setSubjectAltNameCritical || subject == NULL;
/* RFC5280: subjectAltName MUST be critical if subject is null */
OSSL_CRMF_CERTTEMPLATE *tmpl;
X509_EXTENSIONS *exts = NULL;

if (rkey == NULL) {
Expand All @@ -325,6 +328,7 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
}
if ((crm = OSSL_CRMF_MSG_new()) == NULL)
return NULL;
tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
/*
* fill certTemplate, corresponding to CertificationRequestInfo
Expand All @@ -334,6 +338,10 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
|| !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
subject, issuer, NULL /* serial */))
goto err;
if (rkey != NULL && central_keygen)
X509_PUBKEY_set0_public_key(OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl),
NULL, 0);

if (ctx->days != 0) {
time_t now = time(NULL);
ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
Expand Down Expand Up @@ -1071,22 +1079,51 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
}

/*-
* Retrieve the newly enrolled certificate from the given certResponse crep.
* Uses libctx and propq from ctx, in case of indirect POPO also private key.
* Retrieve newly enrolled certificate and key from the given certResponse crep.
* In case of indirect POPO uses the libctx and propq from ctx and private key.
* In case of central key generation, updates ctx->newPkey.
* Returns a pointer to a copy of the found certificate, or NULL if not found.
*/
X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_CERTRESPONSE *crep)
X509 *ossl_cmp_certresponse_get1_cert_key(const OSSL_CMP_CERTRESPONSE *crep,
const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
{
OSSL_CMP_CERTORENCCERT *coec;
X509 *crt = NULL;
EVP_PKEY *pkey;
OSSL_CRMF_ENCRYPTEDKEY *encr_key;
int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD)
== OSSL_CRMF_POPO_NONE;

if (crep->certifiedKeyPair == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
return NULL;
}
encr_key = crep->certifiedKeyPair->privateKey;
if (encr_key == NULL && central_keygen) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CENTRAL_GEN_KEY);
return NULL;
}
if (encr_key != NULL) {
if (!central_keygen) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY);
return NULL;
}
/* found encrypted private key, try to extract */
pkey = OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(encr_key, ctx->trusted,
ctx->untrusted,
ctx->pkey, ctx->cert,
ctx->secretValue,
ctx->libctx, ctx->propq);
if (pkey == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY);
return NULL;
}
OSSL_CMP_CTX_set0_newPkey((OSSL_CMP_CTX *)ctx, 1, pkey);
}

if (!ossl_assert(crep != NULL && ctx != NULL))
return NULL;

if (crep->certifiedKeyPair
&& (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
if ((coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
switch (coec->type) {
case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
crt = X509_dup(coec->value.certificate);
Expand All @@ -1099,10 +1136,9 @@ X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
return NULL;
}
crt =
OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
crt = OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(coec->value.encryptedCert,
ctx->libctx, ctx->propq,
pkey);
pkey, 0);
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
Expand Down
3 changes: 2 additions & 1 deletion crypto/cmp/cmp_vfy.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,11 @@ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx,
* verify that the newly enrolled certificate (which assumed rid ==
* OSSL_CMP_CERTREQID) can also be validated with the same trusted store
*/
EVP_PKEY *pkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
OSSL_CMP_CERTREQID);
X509 *newcrt = ossl_cmp_certresponse_get1_cert(ctx, crep);
X509 *newcrt = ossl_cmp_certresponse_get1_cert_key(crep, ctx, pkey);

/*
* maybe better use get_cert_status() from cmp_client.c, which catches
Expand Down
13 changes: 13 additions & 0 deletions crypto/crmf/crmf_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = {
} ASN1_SEQUENCE_END(OSSL_CRMF_ENCRYPTEDVALUE)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)

/*
* Note from CMP Updates defining CMPv3:
* The EncryptedKey structure defined in CRMF [RFC4211] is reused
* here, which makes the update backward compatible. Using the new
* syntax with the untagged default choice EncryptedValue is bits-on-
* the-wire compatible with the old syntax.
*/
ASN1_CHOICE(OSSL_CRMF_ENCRYPTEDKEY) = {
ASN1_SIMPLE(OSSL_CRMF_ENCRYPTEDKEY, value.encryptedValue, OSSL_CRMF_ENCRYPTEDVALUE),
ASN1_IMP(OSSL_CRMF_ENCRYPTEDKEY, value.envelopedData, CMS_EnvelopedData, 0),
} ASN1_CHOICE_END(OSSL_CRMF_ENCRYPTEDKEY)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDKEY)

ASN1_SEQUENCE(OSSL_CRMF_SINGLEPUBINFO) = {
ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER),
ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME)
Expand Down
13 changes: 12 additions & 1 deletion crypto/crmf/crmf_err.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
Expand All @@ -19,14 +19,25 @@
static const ERR_STRING_DATA CRMF_str_reasons[] = {
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_BAD_PBM_ITERATIONCOUNT),
"bad pbm iterationcount"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CMS_NOT_SUPPORTED), "cms not supported"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CRMFERROR), "crmferror"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR), "error"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_CERTIFICATE),
"error decoding certificate"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY),
"error decoding encryptedkey"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_CERTIFICATE),
"error decrypting certificate"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY),
"error decrypting encryptedkey"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE),
"error decrypting encryptedvalue"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY),
"error decrypting symmetric key"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_SETTING_PURPOSE),
"error setting purpose"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY),
"error verifying encryptedkey"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_FAILURE_OBTAINING_RANDOM),
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ITERATIONCOUNT_BELOW_100),
Expand Down
Loading

0 comments on commit ac93b80

Please sign in to comment.