initial support for delta CRL generations by diffing two full CRLs
This commit is contained in:
parent
256f9573c5
commit
2e8cb108dc
6 changed files with 198 additions and 3 deletions
4
CHANGES
4
CHANGES
|
@ -4,6 +4,10 @@
|
|||
|
||||
Changes between 1.0.x and 1.1.0 [xx XXX xxxx]
|
||||
|
||||
*) New function X509_CRL_diff to generate a delta CRL from the difference
|
||||
of two full CRLs. Add support to "crl" utility.
|
||||
[Steve Henson]
|
||||
|
||||
*) New options -CRL and -CRLform for s_client and s_server for CRLs.
|
||||
[Steve Henson]
|
||||
|
||||
|
|
55
apps/crl.c
55
apps/crl.c
|
@ -104,8 +104,8 @@ int MAIN(int argc, char **argv)
|
|||
char *CAfile = NULL, *CApath = NULL;
|
||||
int ret=1,i,num,badops=0,badsig=0;
|
||||
BIO *out=NULL;
|
||||
int informat,outformat;
|
||||
char *infile=NULL,*outfile=NULL;
|
||||
int informat,outformat, keyformat;
|
||||
char *infile=NULL,*outfile=NULL, *crldiff = NULL, *keyfile = NULL;
|
||||
int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0;
|
||||
int fingerprint = 0, crlnumber = 0;
|
||||
const char **pp;
|
||||
|
@ -140,6 +140,7 @@ int MAIN(int argc, char **argv)
|
|||
|
||||
informat=FORMAT_PEM;
|
||||
outformat=FORMAT_PEM;
|
||||
keyformat=FORMAT_PEM;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
@ -168,6 +169,21 @@ int MAIN(int argc, char **argv)
|
|||
if (--argc < 1) goto bad;
|
||||
infile= *(++argv);
|
||||
}
|
||||
else if (strcmp(*argv,"-gendelta") == 0)
|
||||
{
|
||||
if (--argc < 1) goto bad;
|
||||
crldiff= *(++argv);
|
||||
}
|
||||
else if (strcmp(*argv,"-key") == 0)
|
||||
{
|
||||
if (--argc < 1) goto bad;
|
||||
keyfile= *(++argv);
|
||||
}
|
||||
else if (strcmp(*argv,"-keyform") == 0)
|
||||
{
|
||||
if (--argc < 1) goto bad;
|
||||
keyformat=str2fmt(*(++argv));
|
||||
}
|
||||
else if (strcmp(*argv,"-out") == 0)
|
||||
{
|
||||
if (--argc < 1) goto bad;
|
||||
|
@ -277,6 +293,39 @@ bad:
|
|||
else BIO_printf(bio_err, "verify OK\n");
|
||||
}
|
||||
|
||||
if (crldiff)
|
||||
{
|
||||
X509_CRL *newcrl, *delta;
|
||||
if (!keyfile)
|
||||
{
|
||||
BIO_puts(bio_err, "Missing CRL signing key\n");
|
||||
goto end;
|
||||
}
|
||||
newcrl = load_crl(crldiff,informat);
|
||||
if (!newcrl)
|
||||
goto end;
|
||||
pkey = load_key(bio_err, keyfile, keyformat, 0, NULL, NULL,
|
||||
"CRL signing key");
|
||||
if (!pkey)
|
||||
{
|
||||
X509_CRL_free(newcrl);
|
||||
goto end;
|
||||
}
|
||||
delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
|
||||
X509_CRL_free(newcrl);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (delta)
|
||||
{
|
||||
X509_CRL_free(x);
|
||||
x = delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_puts(bio_err, "Error creating delta CRL\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (num)
|
||||
{
|
||||
for (i=1; i<=num; i++)
|
||||
|
@ -394,6 +443,8 @@ bad:
|
|||
if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; }
|
||||
ret=0;
|
||||
end:
|
||||
if (ret != 0)
|
||||
ERR_print_errors(bio_err);
|
||||
BIO_free_all(out);
|
||||
BIO_free_all(bio_out);
|
||||
bio_out=NULL;
|
||||
|
|
|
@ -356,6 +356,7 @@ ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
|
|||
} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
|
||||
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
|
||||
IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
|
||||
|
|
|
@ -765,6 +765,7 @@ X509 *X509_dup(X509 *x509);
|
|||
X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
|
||||
X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
|
||||
X509_CRL *X509_CRL_dup(X509_CRL *crl);
|
||||
X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev);
|
||||
X509_REQ *X509_REQ_dup(X509_REQ *req);
|
||||
X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
|
||||
int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
|
||||
|
@ -965,6 +966,9 @@ int X509_CRL_sort(X509_CRL *crl);
|
|||
int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
|
||||
int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
|
||||
|
||||
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
|
||||
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags);
|
||||
|
||||
int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
|
||||
|
||||
int X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
|
||||
|
@ -1245,6 +1249,7 @@ void ERR_load_X509_strings(void);
|
|||
#define X509_F_X509_ATTRIBUTE_GET0_DATA 139
|
||||
#define X509_F_X509_ATTRIBUTE_SET1_DATA 138
|
||||
#define X509_F_X509_CHECK_PRIVATE_KEY 128
|
||||
#define X509_F_X509_CRL_DIFF 105
|
||||
#define X509_F_X509_CRL_PRINT_FP 147
|
||||
#define X509_F_X509_EXTENSION_CREATE_BY_NID 108
|
||||
#define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109
|
||||
|
@ -1277,20 +1282,27 @@ void ERR_load_X509_strings(void);
|
|||
#define X509_F_X509_VERIFY_CERT 127
|
||||
|
||||
/* Reason codes. */
|
||||
#define X509_R_AKID_MISMATCH 110
|
||||
#define X509_R_BAD_X509_FILETYPE 100
|
||||
#define X509_R_BASE64_DECODE_ERROR 118
|
||||
#define X509_R_CANT_CHECK_DH_KEY 114
|
||||
#define X509_R_CERT_ALREADY_IN_HASH_TABLE 101
|
||||
#define X509_R_CRL_ALREADY_DELTA 127
|
||||
#define X509_R_CRL_VERIFY_FAILURE 131
|
||||
#define X509_R_ERR_ASN1_LIB 102
|
||||
#define X509_R_IDP_MISMATCH 128
|
||||
#define X509_R_INVALID_DIRECTORY 113
|
||||
#define X509_R_INVALID_FIELD_NAME 119
|
||||
#define X509_R_INVALID_TRUST 123
|
||||
#define X509_R_ISSUER_MISMATCH 129
|
||||
#define X509_R_KEY_TYPE_MISMATCH 115
|
||||
#define X509_R_KEY_VALUES_MISMATCH 116
|
||||
#define X509_R_LOADING_CERT_DIR 103
|
||||
#define X509_R_LOADING_DEFAULTS 104
|
||||
#define X509_R_METHOD_NOT_SUPPORTED 124
|
||||
#define X509_R_NEWER_CRL_NOT_NEWER 132
|
||||
#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105
|
||||
#define X509_R_NO_CRL_NUMBER 130
|
||||
#define X509_R_PUBLIC_KEY_DECODE_ERROR 125
|
||||
#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126
|
||||
#define X509_R_SHOULD_RETRY 106
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* crypto/x509/x509_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1999-2012 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -85,6 +85,7 @@ static ERR_STRING_DATA X509_str_functs[]=
|
|||
{ERR_FUNC(X509_F_X509_ATTRIBUTE_GET0_DATA), "X509_ATTRIBUTE_get0_data"},
|
||||
{ERR_FUNC(X509_F_X509_ATTRIBUTE_SET1_DATA), "X509_ATTRIBUTE_set1_data"},
|
||||
{ERR_FUNC(X509_F_X509_CHECK_PRIVATE_KEY), "X509_check_private_key"},
|
||||
{ERR_FUNC(X509_F_X509_CRL_DIFF), "X509_CRL_diff"},
|
||||
{ERR_FUNC(X509_F_X509_CRL_PRINT_FP), "X509_CRL_print_fp"},
|
||||
{ERR_FUNC(X509_F_X509_EXTENSION_CREATE_BY_NID), "X509_EXTENSION_create_by_NID"},
|
||||
{ERR_FUNC(X509_F_X509_EXTENSION_CREATE_BY_OBJ), "X509_EXTENSION_create_by_OBJ"},
|
||||
|
@ -120,20 +121,27 @@ static ERR_STRING_DATA X509_str_functs[]=
|
|||
|
||||
static ERR_STRING_DATA X509_str_reasons[]=
|
||||
{
|
||||
{ERR_REASON(X509_R_AKID_MISMATCH) ,"akid mismatch"},
|
||||
{ERR_REASON(X509_R_BAD_X509_FILETYPE) ,"bad x509 filetype"},
|
||||
{ERR_REASON(X509_R_BASE64_DECODE_ERROR) ,"base64 decode error"},
|
||||
{ERR_REASON(X509_R_CANT_CHECK_DH_KEY) ,"cant check dh key"},
|
||||
{ERR_REASON(X509_R_CERT_ALREADY_IN_HASH_TABLE),"cert already in hash table"},
|
||||
{ERR_REASON(X509_R_CRL_ALREADY_DELTA) ,"crl already delta"},
|
||||
{ERR_REASON(X509_R_CRL_VERIFY_FAILURE) ,"crl verify failure"},
|
||||
{ERR_REASON(X509_R_ERR_ASN1_LIB) ,"err asn1 lib"},
|
||||
{ERR_REASON(X509_R_IDP_MISMATCH) ,"idp mismatch"},
|
||||
{ERR_REASON(X509_R_INVALID_DIRECTORY) ,"invalid directory"},
|
||||
{ERR_REASON(X509_R_INVALID_FIELD_NAME) ,"invalid field name"},
|
||||
{ERR_REASON(X509_R_INVALID_TRUST) ,"invalid trust"},
|
||||
{ERR_REASON(X509_R_ISSUER_MISMATCH) ,"issuer mismatch"},
|
||||
{ERR_REASON(X509_R_KEY_TYPE_MISMATCH) ,"key type mismatch"},
|
||||
{ERR_REASON(X509_R_KEY_VALUES_MISMATCH) ,"key values mismatch"},
|
||||
{ERR_REASON(X509_R_LOADING_CERT_DIR) ,"loading cert dir"},
|
||||
{ERR_REASON(X509_R_LOADING_DEFAULTS) ,"loading defaults"},
|
||||
{ERR_REASON(X509_R_METHOD_NOT_SUPPORTED) ,"method not supported"},
|
||||
{ERR_REASON(X509_R_NEWER_CRL_NOT_NEWER) ,"newer crl not newer"},
|
||||
{ERR_REASON(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY),"no cert set for us to verify"},
|
||||
{ERR_REASON(X509_R_NO_CRL_NUMBER) ,"no crl number"},
|
||||
{ERR_REASON(X509_R_PUBLIC_KEY_DECODE_ERROR),"public key decode error"},
|
||||
{ERR_REASON(X509_R_PUBLIC_KEY_ENCODE_ERROR),"public key encode error"},
|
||||
{ERR_REASON(X509_R_SHOULD_RETRY) ,"should retry"},
|
||||
|
|
|
@ -1888,6 +1888,125 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Make a delta CRL as the diff between two full CRLs */
|
||||
|
||||
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
|
||||
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
|
||||
{
|
||||
X509_CRL *crl = NULL;
|
||||
int i;
|
||||
STACK_OF(X509_REVOKED) *revs = NULL;
|
||||
/* CRLs can't be delta already */
|
||||
if (base->base_crl_number || newer->base_crl_number)
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_ALREADY_DELTA);
|
||||
return NULL;
|
||||
}
|
||||
/* Base and new CRL must have a CRL number */
|
||||
if (!base->crl_number || !newer->crl_number)
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_NO_CRL_NUMBER);
|
||||
return NULL;
|
||||
}
|
||||
/* Issuer names must match */
|
||||
if (X509_NAME_cmp(X509_CRL_get_issuer(base),
|
||||
X509_CRL_get_issuer(newer)))
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_ISSUER_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
/* AKID and IDP must match */
|
||||
if (!crl_extension_match(base, newer, NID_authority_key_identifier))
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_AKID_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
if (!crl_extension_match(base, newer, NID_issuing_distribution_point))
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_IDP_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
/* Newer CRL number must exceed full CRL number */
|
||||
if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0)
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_NEWER_CRL_NOT_NEWER);
|
||||
return NULL;
|
||||
}
|
||||
/* CRLs must verify */
|
||||
if (skey && (X509_CRL_verify(base, skey) <= 0 ||
|
||||
X509_CRL_verify(newer, skey) <= 0))
|
||||
{
|
||||
X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_VERIFY_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
/* Create new CRL */
|
||||
crl = X509_CRL_new();
|
||||
if (!crl || !X509_CRL_set_version(crl, 1))
|
||||
goto memerr;
|
||||
/* Set issuer name */
|
||||
if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
|
||||
goto memerr;
|
||||
|
||||
if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
|
||||
goto memerr;
|
||||
if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
|
||||
goto memerr;
|
||||
|
||||
/* Set base CRL number: must be critical */
|
||||
|
||||
if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
|
||||
goto memerr;
|
||||
|
||||
/* Copy extensions across from newest CRL to delta: this will set
|
||||
* CRL number to correct value too.
|
||||
*/
|
||||
|
||||
for (i = 0; i < X509_CRL_get_ext_count(newer); i++)
|
||||
{
|
||||
X509_EXTENSION *ext;
|
||||
ext = X509_CRL_get_ext(newer, i);
|
||||
if (!X509_CRL_add_ext(crl, ext, -1))
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
/* Go through revoked entries, copying as needed */
|
||||
|
||||
revs = X509_CRL_get_REVOKED(newer);
|
||||
|
||||
for (i = 0; i < sk_X509_REVOKED_num(revs); i++)
|
||||
{
|
||||
X509_REVOKED *rvn, *rvtmp;
|
||||
rvn = sk_X509_REVOKED_value(revs, i);
|
||||
/* Add only if not also in base.
|
||||
* TODO: need something cleverer here for some more complex
|
||||
* CRLs covering multiple CAs.
|
||||
*/
|
||||
if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber))
|
||||
{
|
||||
rvtmp = X509_REVOKED_dup(rvn);
|
||||
if (!rvtmp)
|
||||
goto memerr;
|
||||
if (!X509_CRL_add0_revoked(crl, rvtmp))
|
||||
{
|
||||
X509_REVOKED_free(rvtmp);
|
||||
goto memerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: optionally prune deleted entries */
|
||||
|
||||
if (skey && md && !X509_CRL_sign(crl, skey, md))
|
||||
goto memerr;
|
||||
|
||||
return crl;
|
||||
|
||||
memerr:
|
||||
X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE);
|
||||
if (crl)
|
||||
X509_CRL_free(crl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue