summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2001-01-17 01:31:34 +0000
committerDr. Stephen Henson <steve@openssl.org>2001-01-17 01:31:34 +0000
commit81f169e95c86fe9b2c3a7ba51a85f7a00763a0e7 (patch)
tree9c61e9161ee5332e99d091153a4cd242160b9180 /crypto
parenta068630a2038ff167d29cdaed828161719355531 (diff)
Initial OCSP certificate verify. Not complete,
it just supports a "trusted OCSP global root CA".
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ocsp/ocsp.h9
-rw-r--r--crypto/ocsp/ocsp_err.c2
-rw-r--r--crypto/ocsp/ocsp_lib.c11
-rw-r--r--crypto/ocsp/ocsp_vfy.c63
-rw-r--r--crypto/x509/x509.h3
-rw-r--r--crypto/x509/x509_trs.c8
-rw-r--r--crypto/x509v3/v3_purp.c34
-rw-r--r--crypto/x509v3/x509v3.h6
8 files changed, 126 insertions, 10 deletions
diff --git a/crypto/ocsp/ocsp.h b/crypto/ocsp/ocsp.h
index 60b843a2fa..1cb6eadfbb 100644
--- a/crypto/ocsp/ocsp.h
+++ b/crypto/ocsp/ocsp.h
@@ -79,6 +79,12 @@ extern "C" {
#define OCSP_NOCERTS 0x1
#define OCSP_NOINTERN 0x2
#define OCSP_NOSIGS 0x4
+#define OCSP_NOCHAIN 0x8
+#define OCSP_NOVERIFY 0x10
+#define OCSP_NOEXPLICIT 0x20
+#define OCSP_NOCASIGN 0x40
+#define OCSP_NODELEGATED 0x80
+#define OCSP_NOCHECKS 0x100
/* CertID ::= SEQUENCE {
* hashAlgorithm AlgorithmIdentifier,
@@ -434,6 +440,7 @@ int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey);
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
OCSP_BASICRESP *OCSP_basic_response_new(int tag,
@@ -565,6 +572,7 @@ void ERR_load_OCSP_strings(void);
/* Reason codes. */
#define OCSP_R_BAD_DATA 108
#define OCSP_R_BAD_TAG 100
+#define OCSP_R_CERTIFICATE_VERIFY_ERROR 126
#define OCSP_R_DIGEST_ERR 101
#define OCSP_R_FAILED_TO_OPEN 109
#define OCSP_R_FAILED_TO_READ 110
@@ -579,6 +587,7 @@ void ERR_load_OCSP_strings(void);
#define OCSP_R_NO_RESPONSE_DATA 104
#define OCSP_R_NO_SIGNATURE 105
#define OCSP_R_REVOKED_NO_TIME 106
+#define OCSP_R_ROOT_CA_NOT_TRUSTED 127
#define OCSP_R_SERVER_READ_ERROR 116
#define OCSP_R_SERVER_RESPONSE_ERROR 117
#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 118
diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c
index 70a27561b1..f4335d28c9 100644
--- a/crypto/ocsp/ocsp_err.c
+++ b/crypto/ocsp/ocsp_err.c
@@ -87,6 +87,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
{
{OCSP_R_BAD_DATA ,"bad data"},
{OCSP_R_BAD_TAG ,"bad tag"},
+{OCSP_R_CERTIFICATE_VERIFY_ERROR ,"certificate verify error"},
{OCSP_R_DIGEST_ERR ,"digest err"},
{OCSP_R_FAILED_TO_OPEN ,"failed to open"},
{OCSP_R_FAILED_TO_READ ,"failed to read"},
@@ -101,6 +102,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
{OCSP_R_NO_RESPONSE_DATA ,"no response data"},
{OCSP_R_NO_SIGNATURE ,"no signature"},
{OCSP_R_REVOKED_NO_TIME ,"revoked no time"},
+{OCSP_R_ROOT_CA_NOT_TRUSTED ,"root ca not trusted"},
{OCSP_R_SERVER_READ_ERROR ,"server read error"},
{OCSP_R_SERVER_RESPONSE_ERROR ,"server response error"},
{OCSP_R_SERVER_RESPONSE_PARSE_ERROR ,"server response parse error"},
diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c
index f9d2978402..bdd4cfccff 100644
--- a/crypto/ocsp/ocsp_lib.c
+++ b/crypto/ocsp/ocsp_lib.c
@@ -163,14 +163,21 @@ err:
return NULL;
}
-int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
{
int ret;
ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm);
if (ret) return ret;
ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash);
if (ret) return ret;
- ret = ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash);
+ return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash);
+ }
+
+int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+ {
+ int ret;
+ ret = OCSP_id_issuer_cmp(a, b);
if (ret) return ret;
return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
}
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index 2ea3f4a923..6110825b19 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -68,13 +68,15 @@ static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
X509_STORE *st, unsigned long flags)
{
- X509 *signer;
- int ret;
+ X509 *signer, *x;
+ STACK_OF(X509) *chain = NULL;
+ X509_STORE_CTX ctx;
+ int i, ret = 0;
signer = ocsp_find_signer(bs, certs, st, flags);
if (!signer)
{
OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
- return 0;
+ goto end;
}
if(!(flags & OCSP_NOSIGS))
{
@@ -85,9 +87,62 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
if(ret <= 0)
{
OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
- return 0;
+ goto end;
}
}
+ if(!(flags & OCSP_NOVERIFY))
+ {
+ if(flags & OCSP_NOCHAIN)
+ X509_STORE_CTX_init(&ctx, st, signer, NULL);
+ else
+ X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
+
+ X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
+ ret = X509_verify_cert(&ctx);
+ chain = X509_STORE_CTX_get1_chain(&ctx);
+ X509_STORE_CTX_cleanup(&ctx);
+ if (ret <= 0)
+ {
+ i = X509_STORE_CTX_get_error(&ctx);
+ OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
+ ERR_add_error_data(2, "Verify error:",
+ X509_verify_cert_error_string(i));
+ goto end;
+ }
+ if(flags & OCSP_NOCHECKS)
+ {
+ ret = 1;
+ goto end;
+ }
+ /* At this point we have a valid certificate chain
+ * need to verify it against the OCSP criteria.
+ */
+#if 0
+ if(ocsp_check_issuer(bs, chain, flags))
+ {
+ ret = 1;
+ goto end;
+ }
+#endif
+
+ /* Easy case: explicitly trusted. Get root CA and
+ * check for explicit trust
+ */
+ if(flags & OCSP_NOEXPLICIT) goto end;
+
+ x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ if(X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED)
+ {
+ OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_ROOT_CA_NOT_TRUSTED);
+ goto end;
+ }
+ ret = 1;
+ }
+
+
+
+ end:
+ if(chain) sk_X509_pop_free(chain, X509_free);
return 1;
}
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 332cad553a..4b1957253d 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -300,10 +300,11 @@ DECLARE_STACK_OF(X509_TRUST)
#define X509_TRUST_SSL_SERVER 3
#define X509_TRUST_EMAIL 4
#define X509_TRUST_OBJECT_SIGN 5
+#define X509_TRUST_OCSP_SIGN 6
/* Keep these up to date! */
#define X509_TRUST_MIN 1
-#define X509_TRUST_MAX 5
+#define X509_TRUST_MAX 6
/* trust_flags values */
diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c
index a7b1543461..0de252c65d 100644
--- a/crypto/x509/x509_trs.c
+++ b/crypto/x509/x509_trs.c
@@ -66,6 +66,7 @@ static int tr_cmp(const X509_TRUST * const *a,
static void trtable_free(X509_TRUST *p);
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
static int obj_trust(int id, X509 *x, int flags);
@@ -81,6 +82,7 @@ static X509_TRUST trstandard[] = {
{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL},
{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Client", NID_server_auth, NULL},
{X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL},
+{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL}
};
#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
@@ -235,6 +237,12 @@ static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
return trust_compat(trust, x, flags);
}
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
+{
+ if(x->aux) return obj_trust(trust->arg1, x, flags);
+ return X509_TRUST_UNTRUSTED;
+}
+
static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
X509_check_purpose(x, -1, 0);
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 717e23d5c6..9d67bd92d5 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -61,7 +61,6 @@
#include <openssl/x509v3.h>
#include <openssl/x509_vfy.h>
-
static void x509v3_cache_extensions(X509 *x);
static int ca_check(const X509 *x);
@@ -74,6 +73,7 @@ static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int c
static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
static int xp_cmp(const X509_PURPOSE * const *a,
const X509_PURPOSE * const *b);
@@ -87,6 +87,7 @@ static X509_PURPOSE xstandard[] = {
{X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
{X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL},
{X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL},
+ {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL},
};
#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
@@ -144,7 +145,6 @@ int X509_PURPOSE_get_by_sname(char *sname)
return -1;
}
-
int X509_PURPOSE_get_by_id(int purpose)
{
X509_PURPOSE tmp;
@@ -320,6 +320,15 @@ static void x509v3_cache_extensions(X509 *x)
case NID_ms_sgc:
case NID_ns_sgc:
x->ex_xkusage |= XKU_SGC;
+ break;
+
+ case NID_OCSP_sign:
+ x->ex_xkusage |= XKU_OCSP_SIGN;
+ break;
+
+ case NID_time_stamp:
+ x->ex_xkusage |= XKU_TIMESTAMP;
+ break;
}
}
sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
@@ -470,6 +479,27 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
return 1;
}
+/* OCSP helper: this is *not* a full OCSP check. It just checks that
+ * each CA is valid. Additional checks must be made on the chain.
+ */
+
+static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ /* Must be a valid CA */
+ if(ca) {
+ int ca_ret;
+ ca_ret = ca_check(x);
+ if(ca_ret != 2) return ca_ret;
+ if(x->ex_flags & EXFLAG_NSCERT) {
+ if(x->ex_nscert & NS_ANY_CA) return ca_ret;
+ return 0;
+ }
+ return 0;
+ }
+ /* leaf certificate is checked in OCSP_verify() */
+ return 1;
+}
+
static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
{
return 1;
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index 8bf67bcbe0..29421b754d 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -342,12 +342,15 @@ DECLARE_ASN1_SET_OF(POLICYINFO)
#define NS_SSL_CA 0x04
#define NS_SMIME_CA 0x02
#define NS_OBJSIGN_CA 0x01
+#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
#define XKU_SSL_SERVER 0x1
#define XKU_SSL_CLIENT 0x2
#define XKU_SMIME 0x4
#define XKU_CODE_SIGN 0x8
#define XKU_SGC 0x10
+#define XKU_OCSP_SIGN 0x20
+#define XKU_TIMESTAMP 0x40
#define X509_PURPOSE_DYNAMIC 0x1
#define X509_PURPOSE_DYNAMIC_NAME 0x2
@@ -370,9 +373,10 @@ typedef struct x509_purpose_st {
#define X509_PURPOSE_SMIME_ENCRYPT 5
#define X509_PURPOSE_CRL_SIGN 6
#define X509_PURPOSE_ANY 7
+#define X509_PURPOSE_OCSP_HELPER 8
#define X509_PURPOSE_MIN 1
-#define X509_PURPOSE_MAX 7
+#define X509_PURPOSE_MAX 8
/* Flags for X509V3_EXT_print() */