summaryrefslogtreecommitdiffstats
path: root/crypto/x509
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2012-12-04 18:35:36 +0000
committerDr. Stephen Henson <steve@openssl.org>2013-01-17 18:51:50 +0000
commit6a10f38daacb59fa3d61c61b91961fb132c9b193 (patch)
tree7c1fea4fc3af96d41db14117c2cc67d0dc0ec072 /crypto/x509
parentc09507889082f1eb1cf69ed6a1e5f8039552dff9 (diff)
initial support for delta CRL generations by diffing two full CRLs
Diffstat (limited to 'crypto/x509')
-rw-r--r--crypto/x509/x509.h12
-rw-r--r--crypto/x509/x509_err.c10
-rw-r--r--crypto/x509/x509_vfy.c119
3 files changed, 140 insertions, 1 deletions
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index c913e3c39d..ee560d19bf 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -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
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index a01402f416..1731254d48 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -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"},
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 0e109a01d0..afb60163f2 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1945,6 +1945,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)
{