For some client testing I need to generate certificates and revocation lists "on the fly". I am able to setup a revocation list with the CRL number extension using OpenSSL console commands and configuration files. However I can't make this work in code.
Here are my relevant functions:
X509* g_certificate[MAX_CERTIFICATE_COUNT];
EVP_PKEY* g_certificateKeyPair[MAX_CERTIFICATE_COUNT];
X509_CRL* g_crl;
UINT16 GenerateCrl(UINT16 issuerCertificateIndex, UINT16 crlNumber, INT32 lastUpdate, INT32 nextUpdate)
{
ASN1_TIME* lastUpdateTime = ASN1_TIME_new();
ASN1_TIME* nextUpdateTime = ASN1_TIME_new();
char crlNumberString[32];
int result = 1;
if (g_crl != NULL) X509_CRL_free(g_crl);
g_crl = X509_CRL_new();
result &= X509_CRL_set_version(g_crl, 1);
result &= X509_CRL_set_issuer_name(g_crl, X509_get_subject_name(g_certificate[issuerCertificateIndex]));
// there are multiple X509 certificate objects stored in memory, which I use to setup certificate chains
ASN1_TIME_set(lastUpdateTime, time(NULL) + lastUpdate);
ASN1_TIME_set(nextUpdateTime, time(NULL) + nextUpdate);
result &= X509_CRL_set1_lastUpdate(g_crl, lastUpdateTime);
result &= X509_CRL_set1_nextUpdate(g_crl, nextUpdateTime);
ASN1_TIME_free(lastUpdateTime);
ASN1_TIME_free(nextUpdateTime);
_itoa_s((int)crlNumber, crlNumberString, 10);
// my CRLs need to have the authority key identifier and CRL number extensions
result &= SetCrlExtension(issuerCertificateIndex, NID_authority_key_identifier, "keyid:always"); // this does add the auth key id extension
result &= SetCrlExtension(issuerCertificateIndex, NID_crl_number, crlNumberString); // this does not add CRL number the extension
result &= X509_CRL_sign(g_crl, g_certificateKeyPair[issuerCertificateIndex], EVP_sha256());
return result;
}
INT16 SetCrlExtension(UINT16 issuerCertificateIndex, INT16 extensionNid, const char* extensionData)
{
X509V3_CTX ctx;
X509_EXTENSION* extension;
lhash_st_CONF_VALUE conf; // actually I have no idea what this is for, probably it is not required here
int result = 1;
X509V3_set_ctx(&ctx, g_certificate[issuerCertificateIndex], NULL, NULL, g_crl, 0);
extension = X509V3_EXT_conf_nid(&conf, &ctx, extensionNid, (char*)extensionData);
result &= X509_CRL_add_ext(g_crl, extension, -1);
return result;
}
void SaveCrlAsPem(const char* fileName)
{
FILE* f;
fopen_s(&f, fileName, "wb");
PEM_write_X509_CRL(f, g_crl);
if (f != NULL) fclose(f);
}
So e.g.
GenerateCrl(1, 1234, -3600, 36000);
SaveCrlAsPem("crl.pem");
should result in a CRL having said extension. But it does only contain the authority key identifier extension. Everything else is fine. Im also adding the certificate extensions in basically the same way and dont't have any issues there.
So how can I get the CRL number attached to my CRL?
You mention that you are able to setup the
CRL numberextension from OpenSSL command line. You should probably take a look at the source code of the particular command then.I haven't used CRLs, but I believe you are using the
cacommand. Looking forNID_crl_numberin its source atapps/ca.c(from OpenSSL 1.1.1g) shows the following code:So, it seems you can use
X509V3_EXT_CRL_add_nconforX509_CRL_add1_ext_i2dfor the purpose. Please refer theapps/ca.cof the OpenSSL version that you are using.Another solution: Maybe not the best approach, but you can probably launch the same OpenSSL commands as processes from code and process their output if it's acceptable.