提交 81f169e9 编写于 作者: D Dr. Stephen Henson

Initial OCSP certificate verify. Not complete,
it just supports a "trusted OCSP global root CA".
上级 a068630a
......@@ -3,6 +3,16 @@
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
*) Initial OCSP certificate verification added to OCSP_basic_verify()
and related routines. This uses the standard OpenSSL certificate
verify routines to perform initial checks (just CA validity) and
to obtain the certificate chain. Then additional checks will be
performed on the chain. Currently the root CA is checked to see
if it is explicitly trusted for OCSP signing. This is used to set
a root CA as a global signing root: that is any certificate that
chains to that CA is an acceptable OCSP signing certificate.
[Steve Henson]
*) New '-extfile ...' option to 'openssl ca' for reading X.509v3
extensions from a separate configuration file.
As when reading extensions from the main configuration file,
......
......@@ -837,3 +837,32 @@ void print_name(BIO *out, char *title, X509_NAME *nm, unsigned long lflags)
}
}
X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
{
X509_STORE *store;
X509_LOOKUP *lookup;
if(!(store = X509_STORE_new())) goto end;
lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
if (lookup == NULL) goto end;
if (CAfile) {
if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
BIO_printf(bp, "Error loading file %s\n", CAfile);
goto end;
}
} else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
if (lookup == NULL) goto end;
if (CApath) {
if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
BIO_printf(bp, "Error loading directory %s\n", CApath);
goto end;
}
} else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
ERR_clear_error();
return store;
end:
X509_STORE_free(store);
return NULL;
}
......@@ -158,6 +158,7 @@ X509 *load_cert(BIO *err, char *file, int format);
EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e);
EVP_PKEY *load_pubkey(BIO *err, char *file, int format, ENGINE *e);
STACK_OF(X509) *load_certs(BIO *err, char *file, int format);
X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath);
#define FORMAT_UNDEF 0
#define FORMAT_ASN1 1
......
......@@ -82,14 +82,18 @@ int MAIN(int argc, char **argv)
int add_nonce = 1;
OCSP_REQUEST *req = NULL;
OCSP_RESPONSE *resp = NULL;
OCSP_BASICRESP *bs = NULL;
X509 *issuer = NULL, *cert = NULL;
X509 *signer = NULL;
EVP_PKEY *key = NULL;
BIO *cbio = NULL, *derbio = NULL;
BIO *out = NULL;
int req_text = 0, resp_text = 0;
char *CAfile = NULL, *CApath = NULL;
X509_STORE *store = NULL;
int ret = 1;
int badarg = 0;
int i;
if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
ERR_load_crypto_strings();
args = argv + 1;
......@@ -153,6 +157,24 @@ int MAIN(int argc, char **argv)
}
else badarg = 1;
}
else if (!strcmp (*args, "-CAfile"))
{
if (args[1])
{
args++;
CAfile = *args;
}
else badarg = 1;
}
else if (!strcmp (*args, "-CApath"))
{
if (args[1])
{
args++;
CApath = *args;
}
else badarg = 1;
}
else if (!strcmp(*args, "-signkey"))
{
if (args[1])
......@@ -386,11 +408,25 @@ int MAIN(int argc, char **argv)
if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
store = setup_verify(bio_err, CAfile, CApath);
if(!store) goto end;
bs = OCSP_response_get1_basic(resp);
i = OCSP_basic_verify(bs, NULL, store, 0);
if(i <= 0)
{
BIO_printf(bio_err, "Response verify error (%d)\n", i);
ERR_print_errors(bio_err);
}
ret = 0;
end:
ERR_print_errors(bio_err);
X509_free(signer);
X509_STORE_free(store);
EVP_PKEY_free(key);
X509_free(issuer);
X509_free(cert);
......@@ -398,6 +434,7 @@ end:
BIO_free(out);
OCSP_REQUEST_free(req);
OCSP_RESPONSE_free(resp);
OCSP_BASICRESP_free(bs);
EXIT(ret);
}
......
......@@ -68,7 +68,6 @@
#undef PROG
#define PROG smime_main
static X509_STORE *setup_verify(char *CAfile, char *CApath);
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
#define SMIME_OP 0x10
......@@ -431,7 +430,7 @@ int MAIN(int argc, char **argv)
}
if(operation == SMIME_VERIFY) {
if(!(store = setup_verify(CAfile, CApath))) goto end;
if(!(store = setup_verify(bio_err, CAfile, CApath))) goto end;
}
ret = 3;
......@@ -530,36 +529,6 @@ end:
return (ret);
}
static X509_STORE *setup_verify(char *CAfile, char *CApath)
{
X509_STORE *store;
X509_LOOKUP *lookup;
if(!(store = X509_STORE_new())) goto end;
lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
if (lookup == NULL) goto end;
if (CAfile) {
if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto end;
}
} else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
if (lookup == NULL) goto end;
if (CApath) {
if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto end;
}
} else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
ERR_clear_error();
return store;
end:
X509_STORE_free(store);
return NULL;
}
static int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
int i;
......
......@@ -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
......
......@@ -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"},
......
......@@ -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);
}
......
......@@ -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;
}
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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;
......
......@@ -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() */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册