From 13938acecae8f1b455812d0388e2891abd1c096d Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 29 Nov 1999 01:09:25 +0000 Subject: [PATCH] Add part of chain verify SSL support code: not complete or doing anything yet. Add a function X509_STORE_CTX_purpose_inherit() which implements the logic of "inheriting" purpose and trust from a parent structure and using a default: this will be used in the SSL code and possibly future S/MIME. Partial documentation of the 'verify' utility. Still need to document how all the extension checking works and the various error messages. --- apps/verify.c | 10 +-- apps/x509.c | 6 +- crypto/x509/Makefile.ssl | 31 ++++++++-- crypto/x509/x509.h | 5 +- crypto/x509/x509_err.c | 3 +- crypto/x509/x509_lu.c | 4 +- crypto/x509/x509_v3.c | 22 +++++++ crypto/x509/x509_vfy.c | 67 ++++++++++++++------ crypto/x509/x509_vfy.h | 11 ++-- crypto/x509v3/v3_purp.c | 30 ++++----- crypto/x509v3/x509v3.h | 10 +-- doc/man/dsa.pod | 7 ++- doc/man/rsa.pod | 16 ++--- doc/man/verify.pod | 128 +++++++++++++++++++++++++++++++++++++++ doc/man/x509.pod | 23 +++---- ssl/ssl.h | 6 ++ ssl/ssl_lib.c | 2 + util/libeay.num | 55 ++++++++++++++--- 18 files changed, 335 insertions(+), 101 deletions(-) create mode 100644 doc/man/verify.pod diff --git a/apps/verify.c b/apps/verify.c index 8a03e0f290..f9281a65cf 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -84,9 +84,7 @@ int MAIN(int argc, char **argv) X509_STORE *cert_ctx=NULL; X509_LOOKUP *lookup=NULL; - X509_PURPOSE_add_standard(); - X509_TRUST_add_standard(); - X509V3_add_standard_extensions(); + X509_init(); cert_ctx=X509_STORE_new(); if (cert_ctx == NULL) goto end; X509_STORE_set_verify_cb_func(cert_ctx,cb); @@ -198,9 +196,7 @@ end: } if (cert_ctx != NULL) X509_STORE_free(cert_ctx); sk_X509_pop_free(untrusted, X509_free); - X509V3_EXT_cleanup(); - X509_PURPOSE_cleanup(); - X509_TRUST_cleanup(); + X509_cleanup(); EXIT(ret); } @@ -246,7 +242,7 @@ static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, int purpos goto end; } X509_STORE_CTX_init(csc,ctx,x,uchain); - if(purpose >= 0) X509_STORE_CTX_chain_purpose(csc, purpose); + if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose); i=X509_verify_cert(csc); X509_STORE_CTX_free(csc); diff --git a/apps/x509.c b/apps/x509.c index 86896088fb..caf5946287 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -384,8 +384,7 @@ bad: app_RAND_load_file(NULL, bio_err, 0); ERR_load_crypto_strings(); - X509V3_add_standard_extensions(); - X509_PURPOSE_add_standard(); + X509_init(); if (!X509_STORE_set_default_paths(ctx)) { @@ -871,8 +870,7 @@ end: EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); X509_REQ_free(rq); - X509V3_EXT_cleanup(); - X509_PURPOSE_cleanup(); + X509_cleanup(); EXIT(ret); } diff --git a/crypto/x509/Makefile.ssl b/crypto/x509/Makefile.ssl index db2aa5057d..346ffb2895 100644 --- a/crypto/x509/Makefile.ssl +++ b/crypto/x509/Makefile.ssl @@ -294,6 +294,24 @@ x509_set.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h x509_set.o: ../../include/openssl/sha.h ../../include/openssl/stack.h x509_set.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h x509_set.o: ../cryptlib.h +x509_trs.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +x509_trs.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +x509_trs.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +x509_trs.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +x509_trs.o: ../../include/openssl/des.h ../../include/openssl/dh.h +x509_trs.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h +x509_trs.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +x509_trs.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +x509_trs.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +x509_trs.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +x509_trs.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +x509_trs.o: ../../include/openssl/opensslv.h ../../include/openssl/pkcs7.h +x509_trs.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +x509_trs.o: ../../include/openssl/rc5.h ../../include/openssl/ripemd.h +x509_trs.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +x509_trs.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +x509_trs.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +x509_trs.o: ../../include/openssl/x509v3.h ../cryptlib.h x509_txt.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h x509_txt.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h x509_txt.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h @@ -315,11 +333,12 @@ x509_txt.o: ../cryptlib.h x509_v3.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h x509_v3.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h x509_v3.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h -x509_v3.o: ../../include/openssl/crypto.h ../../include/openssl/des.h -x509_v3.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h -x509_v3.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -x509_v3.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_v3.o: ../../include/openssl/idea.h ../../include/openssl/md2.h +x509_v3.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +x509_v3.o: ../../include/openssl/des.h ../../include/openssl/dh.h +x509_v3.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h +x509_v3.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +x509_v3.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +x509_v3.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h x509_v3.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h x509_v3.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h x509_v3.o: ../../include/openssl/opensslv.h ../../include/openssl/pkcs7.h @@ -328,7 +347,7 @@ x509_v3.o: ../../include/openssl/rc5.h ../../include/openssl/ripemd.h x509_v3.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h x509_v3.o: ../../include/openssl/sha.h ../../include/openssl/stack.h x509_v3.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h -x509_v3.o: ../cryptlib.h +x509_v3.o: ../../include/openssl/x509v3.h ../cryptlib.h x509_vfy.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h x509_vfy.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h x509_vfy.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index 534c3d69f7..ed95058a74 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -1015,6 +1015,8 @@ int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); int X509_EXTENSION_get_critical(X509_EXTENSION *ex); +void X509_init(void); +void X509_cleanup(void); int X509_verify_cert(X509_STORE_CTX *ctx); @@ -1098,9 +1100,9 @@ int X509_TRUST_get_trust(X509_TRUST *xp); #define X509_F_X509_REQ_PRINT 121 #define X509_F_X509_REQ_PRINT_FP 122 #define X509_F_X509_REQ_TO_X509 123 -#define X509_F_X509_SET_PURPOSE_AND_TRUST 134 #define X509_F_X509_STORE_ADD_CERT 124 #define X509_F_X509_STORE_ADD_CRL 125 +#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 #define X509_F_X509_TO_X509_REQ 126 #define X509_F_X509_TRUST_ADD 133 #define X509_F_X509_VERIFY_CERT 127 @@ -1123,6 +1125,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp); #define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 #define X509_R_UNKNOWN_KEY_TYPE 117 #define X509_R_UNKNOWN_NID 109 +#define X509_R_UNKNOWN_PURPOSE_ID 121 #define X509_R_UNKNOWN_TRUST_ID 120 #define X509_R_UNSUPPORTED_ALGORITHM 111 #define X509_R_WRONG_LOOKUP_TYPE 112 diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index acaa99ffae..6c85ddb84d 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -91,9 +91,9 @@ static ERR_STRING_DATA X509_str_functs[]= {ERR_PACK(0,X509_F_X509_REQ_PRINT,0), "X509_REQ_print"}, {ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0), "X509_REQ_print_fp"}, {ERR_PACK(0,X509_F_X509_REQ_TO_X509,0), "X509_REQ_to_X509"}, -{ERR_PACK(0,X509_F_X509_SET_PURPOSE_AND_TRUST,0), "X509_set_purpose_and_trust"}, {ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0), "X509_STORE_add_cert"}, {ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0), "X509_STORE_add_crl"}, +{ERR_PACK(0,X509_F_X509_STORE_CTX_PURPOSE_INHERIT,0), "X509_STORE_CTX_purpose_inherit"}, {ERR_PACK(0,X509_F_X509_TO_X509_REQ,0), "X509_to_X509_REQ"}, {ERR_PACK(0,X509_F_X509_TRUST_ADD,0), "X509_TRUST_add"}, {ERR_PACK(0,X509_F_X509_VERIFY_CERT,0), "X509_verify_cert"}, @@ -119,6 +119,7 @@ static ERR_STRING_DATA X509_str_reasons[]= {X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY ,"unable to get certs public key"}, {X509_R_UNKNOWN_KEY_TYPE ,"unknown key type"}, {X509_R_UNKNOWN_NID ,"unknown nid"}, +{X509_R_UNKNOWN_PURPOSE_ID ,"unknown purpose id"}, {X509_R_UNKNOWN_TRUST_ID ,"unknown trust id"}, {X509_R_UNSUPPORTED_ALGORITHM ,"unsupported algorithm"}, {X509_R_WRONG_LOOKUP_TYPE ,"wrong lookup type"}, diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 837b81f154..95ee24b958 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -403,8 +403,8 @@ void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->cert=x509; ctx->untrusted=chain; ctx->last_untrusted=0; - ctx->chain_purpose=0; - ctx->trust_purpose=0; + ctx->purpose=0; + ctx->trust=0; ctx->valid=0; ctx->chain=NULL; ctx->depth=9; diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 5721f78510..100b08773c 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c @@ -63,6 +63,7 @@ #include #include #include +#include int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) { @@ -264,3 +265,24 @@ int X509_EXTENSION_get_critical(X509_EXTENSION *ex) if (ex == NULL) return(0); return(ex->critical); } + +/* Initialisation routine: used to initialise the X509 and X509v3 tables */ + +static int init_done = 0; + +void X509_init(void) +{ + if(init_done) return; + X509V3_add_standard_extensions(); + X509_PURPOSE_add_standard(); + X509_TRUST_add_standard(); + init_done = 1; +} + +void X509_cleanup(void) +{ + X509V3_EXT_cleanup(); + X509_PURPOSE_cleanup(); + X509_TRUST_cleanup(); + init_done = 0; +} diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 75ab96e506..11f462f461 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -294,13 +294,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx) } /* We have the chain complete: now we need to check its purpose */ - if(ctx->chain_purpose > 0) ok = check_chain_purpose(ctx); + if(ctx->purpose > 0) ok = check_chain_purpose(ctx); if(!ok) goto end; /* The chain extensions are OK: check trust */ - if(ctx->trust_purpose > 0) ok = check_trust(ctx); + if(ctx->trust > 0) ok = check_trust(ctx); if(!ok) goto end; @@ -339,7 +339,7 @@ static int check_chain_purpose(X509_STORE_CTX *ctx) /* Check all untrusted certificates */ for(i = 0; i < ctx->last_untrusted; i++) { x = sk_X509_value(ctx->chain, i); - if(!X509_check_purpose(x, ctx->chain_purpose, i)) { + if(!X509_check_purpose(x, ctx->purpose, i)) { if(i) ctx->error = X509_V_ERR_INVALID_CA; else ctx->error = X509_V_ERR_INVALID_PURPOSE; ctx->error_depth = i; @@ -376,7 +376,7 @@ static int check_trust(X509_STORE_CTX *ctx) /* For now just check the last certificate in the chain */ i = sk_X509_num(ctx->chain) - 1; x = sk_X509_value(ctx->chain, i); - ok = X509_check_trust(x, ctx->trust_purpose, 0); + ok = X509_check_trust(x, ctx->trust, 0); if(ok == X509_TRUST_TRUSTED) return 1; ctx->error_depth = sk_X509_num(ctx->chain) - 1; ctx->current_cert = x; @@ -727,33 +727,62 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) ctx->untrusted=sk; } -int X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose) +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { - return X509_set_purpose_and_trust(purpose, - &ctx->chain_purpose, &ctx->trust_purpose); + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); } -void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose) +void X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { - ctx->trust_purpose = purpose; + ctx->trust = trust; } -int X509_set_purpose_and_trust(int id, int *purp, int *trust) +/* This function is used to set the X509_STORE_CTX purpose and trust + * values. This is intended to be used when another structure has its + * own trust and purpose values which (if set) will be inherited by + * the ctx. If they aren't set then we will usually have a default + * purpose in mind which should then be used to set the trust value. + * An example of this is SSL use: an SSL structure will have its own + * purpose and trust settings which the application can set: if they + * aren't set then we use the default of SSL client/server. + */ + +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust) { - X509_PURPOSE *ptmp; int idx; - idx = X509_PURPOSE_get_by_id(id); - if(idx == -1) { - X509err(X509_F_X509_SET_PURPOSE_AND_TRUST, - X509_R_UNKNOWN_TRUST_ID); - return 0; + /* If purpose not set use default */ + if(!purpose) purpose = def_purpose; + /* If we have a purpose then check it is valid */ + if(purpose) { + idx = X509_PURPOSE_get_by_id(purpose); + if(idx == -1) { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + /* If trust not set then get from purpose default */ + if(!trust) { + X509_PURPOSE *ptmp; + ptmp = X509_PURPOSE_iget(idx); + trust = ptmp->trust; + } } - ptmp = X509_PURPOSE_iget(idx); - if(purp) *purp = id; - if(trust) *trust = ptmp->trust_id; + if(trust) { + idx = X509_TRUST_get_by_id(trust); + if(idx == -1) { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if(purpose) ctx->purpose = purpose; + if(trust) ctx->trust = trust; return 1; } + IMPLEMENT_STACK_OF(X509) IMPLEMENT_ASN1_SET_OF(X509) diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index 5e197040fb..822d9c7ea6 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -202,8 +202,8 @@ struct x509_store_state_st /* X509_STORE_CTX */ /* The following are set by the caller */ X509 *cert; /* The cert to check */ STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ - int chain_purpose; /* purpose to check untrusted certificates */ - int trust_purpose; /* trust setting to check */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ /* The following is built up */ int depth; /* how far to go looking up certs */ @@ -349,9 +349,10 @@ X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); -int X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose); -void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose); -int X509_set_purpose_and_trust(int id, int *purp, int *trust); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +void X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); #ifdef __cplusplus } diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 0eb20d3ef3..e350c8158b 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -91,7 +91,7 @@ static STACK_OF(X509_PURPOSE) *xptable = NULL; static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b) { - return (*a)->purpose_id - (*b)->purpose_id; + return (*a)->purpose - (*b)->purpose; } int X509_check_purpose(X509 *x, int id, int ca) @@ -100,6 +100,7 @@ int X509_check_purpose(X509 *x, int id, int ca) X509_PURPOSE *pt; if(!(x->ex_flags & EXFLAG_SET)) { CRYPTO_w_lock(CRYPTO_LOCK_X509); + X509_init(); x509v3_cache_extensions(x); CRYPTO_w_unlock(CRYPTO_LOCK_X509); } @@ -126,16 +127,16 @@ int X509_PURPOSE_get_by_sname(char *sname) X509_PURPOSE *xptmp; for(i = 0; i < sk_X509_PURPOSE_num(xptable); i++) { xptmp = sk_X509_PURPOSE_value(xptable, i); - if(!strcmp(xptmp->purpose_sname, sname)) return i; + if(!strcmp(xptmp->sname, sname)) return i; } return -1; } -int X509_PURPOSE_get_by_id(int id) +int X509_PURPOSE_get_by_id(int purpose) { X509_PURPOSE tmp; - tmp.purpose_id = id; + tmp.purpose = purpose; if(!xptable) return -1; return sk_X509_PURPOSE_find(xptable, &tmp); } @@ -153,7 +154,7 @@ int X509_PURPOSE_add(X509_PURPOSE *xp) } } - idx = X509_PURPOSE_get_by_id(xp->purpose_id); + idx = X509_PURPOSE_get_by_id(xp->purpose); if(idx != -1) { xptable_free(sk_X509_PURPOSE_value(xptable, idx)); sk_X509_PURPOSE_set(xptable, idx, xp); @@ -169,11 +170,11 @@ int X509_PURPOSE_add(X509_PURPOSE *xp) static void xptable_free(X509_PURPOSE *p) { if(!p) return; - if (p->purpose_flags & X509_PURPOSE_DYNAMIC) + if (p->flags & X509_PURPOSE_DYNAMIC) { - if (p->purpose_flags & X509_PURPOSE_DYNAMIC_NAME) { - Free(p->purpose_name); - Free(p->purpose_sname); + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + Free(p->name); + Free(p->sname); } Free(p); } @@ -188,28 +189,27 @@ void X509_PURPOSE_cleanup(void) void X509_PURPOSE_add_standard(void) { X509_PURPOSE *xp; - for(xp = xstandard; xp->purpose_name; xp++) - X509_PURPOSE_add(xp); + for(xp = xstandard; xp->name; xp++) X509_PURPOSE_add(xp); } int X509_PURPOSE_get_id(X509_PURPOSE *xp) { - return xp->purpose_id; + return xp->purpose; } char *X509_PURPOSE_iget_name(X509_PURPOSE *xp) { - return xp->purpose_name; + return xp->name; } char *X509_PURPOSE_iget_sname(X509_PURPOSE *xp) { - return xp->purpose_sname; + return xp->sname; } int X509_PURPOSE_get_trust(X509_PURPOSE *xp) { - return xp->trust_id; + return xp->trust; } static void x509v3_cache_extensions(X509 *x) diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h index 5a97e09612..bee56ab2d2 100644 --- a/crypto/x509v3/x509v3.h +++ b/crypto/x509v3/x509v3.h @@ -329,12 +329,12 @@ DECLARE_ASN1_SET_OF(POLICYINFO) #define X509_PURPOSE_DYNAMIC_NAME 0x2 typedef struct x509_purpose_st { - int purpose_id; - int trust_id; /* Default trust ID */ - int purpose_flags; + int purpose; + int trust; /* Default trust ID */ + int flags; int (*check_purpose)(struct x509_purpose_st *, X509 *, int); - char *purpose_name; - char *purpose_sname; + char *name; + char *sname; void *usr_data; } X509_PURPOSE; diff --git a/doc/man/dsa.pod b/doc/man/dsa.pod index 4187ef4b49..1235e5598b 100644 --- a/doc/man/dsa.pod +++ b/doc/man/dsa.pod @@ -40,11 +40,12 @@ applications should use the more secure PKCS#8 format using the B This specifies the input format. The B option with a private key uses an ASN1 DER encoded form of an ASN.1 SEQUENCE consisting of the values of version (currently zero), p, q, g, the public and private key components -respectively as ASN.1 INTEGERs. When used with a public key it outputs a -SEQUENCE of the public key component, p, q and g respectively. +respectively as ASN.1 INTEGERs. When used with a public key it uses a +SubjectPublicKeyInfo structure: it is an error if the key is not DSA. The B form is the default format: it consists of the B format base64 -encoded with additional header and footer lines. +encoded with additional header and footer lines. In the case of a private key +PKCS#8 format is also accepted. =item B<-outform DER|PEM> diff --git a/doc/man/rsa.pod b/doc/man/rsa.pod index 9834eb395f..570832a191 100644 --- a/doc/man/rsa.pod +++ b/doc/man/rsa.pod @@ -41,11 +41,12 @@ utility. =item B<-inform DER|NET|PEM> This specifies the input format. The B option uses an ASN1 DER encoded -form compatible with the PKCS#1 RSAPrivateKey or RSAPublicKey format. The B -form is the default format: it consists of the B format base64 encoded with -additional header and footer lines. The B form is a format compatible -with older Netscape servers and MS IIS, this uses unsalted RC4 for its -encryption It is not very secure and so should only be used when necessary. +form compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format. +The B form is the default format: it consists of the B format base64 +encoded with additional header and footer lines. On input PKCS#8 format private +keys are also accepted.The B form is a format compatible with older Netscape +servers and MS IIS, this uses unsalted RC4 for its encryption. It is not very +secure and so should only be used when necessary. =item B<-outform DER|NET|PEM> @@ -152,11 +153,6 @@ To just output the public part of a private key: C -=head1 CAVEATS - -It should be possible to read or produce PKCS#8 format encrypted RSA keys: -at present it isn't. - =head1 SEE ALSO pkcs8(1), dsa(1), genrsa(1), gendsa(1) diff --git a/doc/man/verify.pod b/doc/man/verify.pod new file mode 100644 index 0000000000..36c47109ba --- /dev/null +++ b/doc/man/verify.pod @@ -0,0 +1,128 @@ +=pod + +=head1 NAME + +pkcs7 - PKCS#7 utility + +=head1 SYNOPSIS + +B B +[B<-CApath directory>] +[B<-CAfile file>] +[B<-purpose purpose>] +[B<-untrusted file>] +[B<-help>] +[B<-verbose>] +[B<->] +[certificates] + + +=head1 DESCRIPTION + +The B command verifies certificate chains. + +=head1 COMMAND OPTIONS + +=over 4 + +=item B<-CApath directory> + +A directory of trusted certificates. The certificates should have names +of the form: hash.0 or have symbolic links to them of this +form ("hash" is the hashed certificate subject name: see the B<-hash> option +of the B utility). Under Unix the B script will automatically +create symbolic links to a directory of certificates. + +=item B<-CAfile file> + +A file of trusted certificates. The file should contain multiple certificates +in PEM format concatenated together. + +=item B<-untrusted file> + +A file of untrusted certificates. The file should contain multiple certificates + +=item B<-purpose purpose> + +the intended use for the certificate. Without this option no chain verification +will be done. Currently accepted uses are B, B, +B, B, B. See the B +section for more information. + +=item B<-help> + +prints out a usage message. + +=item B<-verbose> + +print extra information about the operations being performed. + +=item B<-> + +marks the last option. All arguments following this are assumed to be +certificate files. + + +=item B + +one or more certificates to verify. If no certificate filenames are included +then an attempt is made to read a certificate from standard input. They should +all be in PEM format. + + +=back + +=head1 VERIFY OPERATION + +The B program uses the same functions as the internal SSL and S/MIME +verification, therefore this description applies to these verify operations +too. + +There is one crucial difference between the verify operations performed +by the B program: wherever possible an attempt is made to continue +after an error whereas normally the verify operation would halt on the +first error. This allows all the problems with a certificate chain to be +determined. + +The verify operation consists of a number of separate steps. + +Firstly a certificate chain is built up starting from the supplied certificate +and ending in the root CA. It is an error if the whole chain cannot be built +up. The chain is built up by looking up a certificate whose subject name +matches the issuer name of the current certificate. If a certificate is found +whose subject and issuer names are identical it is assumed to be the root CA. +The lookup first looks in the list of untrusted certificates and if no match +is found the remaining lookups are from the trusted certficates. The root CA +is always looked up in the trusted certificate list: if the certificate to +verify is a root certificate then an exact match must be found in the trusted +list. + +The second operation is to check every untrusted certificate's extensions for +consistency with the supplied purpose. If the B<-purpose> option is not included +then no checks are done. The supplied or "leaf" certificate must have extensions +compatible with the supplied purpose and all other certificates must also be valid +CA certificates. The precise extensions required are described in more detail in +the B section. + +The third operation is to check the trust settings on the root CA. The root +CA should be trusted for the supplied purpose. For compatability with previous +versions of SSLeay and OpenSSL a certificate with no trust settings is considered +to be valid for all purposes. + +The final operation is to check the validity of the certificate chain. The validity +period is checked against the current system time and the notBefore and notAfter +dates in the certificate. The certificate signatures are also checked at this +point. + +If all operations complete successfully then certificate is considered valid. If +any operation fails then the certificate is not valid. + +=head1 CERTIFICATE EXTENSIONS + +...to be added... + +=head1 SEE ALSO + +x509(1) + +=cut diff --git a/doc/man/x509.pod b/doc/man/x509.pod index 9f8c947612..135b6f7552 100644 --- a/doc/man/x509.pod +++ b/doc/man/x509.pod @@ -172,20 +172,17 @@ must be "trusted". By default a trusted certificate must be stored locally and must be a root CA: any certificate chain ending in this CA is then usable for any purpose. -Adding trust settings modifies this behaviour: if a certificate is being -verified and one of the certificate chain is marked as trusted for that -specific purpose then the verify succeeds without looking up any more -certificates. Similarly if the use is prohibited then the certificate -is automatically rejected. If a purpose is neither permitted nor prohibited -then the certificate extensions are checked for consistency with the required -purpose and the process continues. - -If a root CA is reached then it must be marked as trusted for the required -purpose or the verify fails. +Trust settings currently are only used with a root CA. They allow a finer +control over the purposes the root CA can be used for. For example a CA +may be trusted for SSL client but not SSL server use. See the description of the B utility for more information on the meaning of trust settings. +Future versions of OpenSSL will recognise trust settings on any +certificate: not just root CAs. + + =over 4 =item B<-trustout> @@ -211,13 +208,13 @@ clears all the permitted or trusted uses of the certificate. =item B<-clrreject> -clears all the prohibited or untrusted uses of the certificate. +clears all the prohibited or rejected uses of the certificate. =item B<-addtrust arg> adds a trusted certificate use. Currently acceptable values -are all (any purpose), sslclient (SSL client use), sslserver -(SSL server use) email (S/MIME email) and objsign (Object signing). +are B (any purpose), B (SSL client use), B +(SSL server use) B (S/MIME email) and B (Object signing). =item B<-addreject arg> diff --git a/ssl/ssl.h b/ssl/ssl.h index f888530625..1b39f0d2ea 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -429,6 +429,9 @@ struct ssl_ctx_st /**/ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; /**/ int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + /* Default password callback. */ /**/ pem_password_cb *default_passwd_callback; @@ -575,6 +578,9 @@ struct ssl_st int read_ahead; /* Read as many input bytes as possible */ int hit; /* reusing a previous session */ + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + /* crypto */ STACK_OF(SSL_CIPHER) *cipher_list; STACK_OF(SSL_CIPHER) *cipher_list_by_id; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index e192fc4cac..9dd6860d96 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -201,6 +201,8 @@ SSL *SSL_new(SSL_CTX *ctx) s->verify_mode=ctx->verify_mode; s->verify_depth=ctx->verify_depth; s->verify_callback=ctx->default_verify_callback; + s->purpose = ctx->purpose; + s->trust = ctx->trust; CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); s->ctx=ctx; diff --git a/util/libeay.num b/util/libeay.num index 811f6ec10e..a14719d529 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -2076,13 +2076,48 @@ sk_ACCESS_DESCRIPTION_delete_ptr 2100 sk_ACCESS_DESCRIPTION_insert 2101 sk_ACCESS_DESCRIPTION_sort 2102 sk_ACCESS_DESCRIPTION_set_cmp_func 2103 -X509_STORE_CTX_chain_purpose 2104 -X509_STORE_CTX_free 2105 -X509_STORE_CTX_trust_purpose 2106 -X509_STORE_CTX_new 2107 -X509_PURPOSE_iget 2108 -X509_PURPOSE_get_by_sname 2109 -X509_PURPOSE_get_id 2110 -X509_PURPOSE_get_trust 2111 -X509_PURPOSE_get_count 2112 -X509_PURPOSE_iget_sname 2113 +sk_X509_TRUST_pop 2104 +X509_cleanup 2105 +sk_X509_TRUST_set_cmp_func 2106 +X509_PURPOSE_get_by_sname 2107 +X509_STORE_CTX_free 2108 +sk_X509_TRUST_pop_free 2109 +X509_STORE_CTX_purpose_inherit 2110 +sk_X509_TRUST_push 2111 +X509_PURPOSE_get_id 2112 +sk_X509_TRUST_find 2113 +X509_TRUST_get_id 2114 +X509_TRUST_iget_name 2115 +X509_TRUST_iget 2116 +sk_X509_TRUST_unshift 2117 +X509_PURPOSE_get_count 2118 +X509_add_reject_object 2119 +sk_X509_TRUST_new_null 2120 +sk_X509_TRUST_new 2121 +sk_X509_TRUST_delete_ptr 2122 +X509_PURPOSE_iget_sname 2123 +X509_TRUST_get_count 2124 +X509_reject_set_bit_asc 2125 +X509_PURPOSE_iget 2126 +sk_X509_TRUST_free 2127 +sk_X509_TRUST_num 2128 +X509_init 2129 +X509_TRUST_add 2130 +X509_TRUST_add_standard 2131 +sk_X509_TRUST_zero 2132 +sk_X509_TRUST_shift 2133 +X509_TRUST_cleanup 2134 +sk_X509_TRUST_set 2135 +X509_TRUST_get_by_id 2136 +X509_PURPOSE_get_trust 2137 +X509_STORE_CTX_set_trust 2138 +X509_STORE_CTX_new 2139 +sk_X509_TRUST_value 2140 +X509_TRUST_get_trust 2141 +X509_STORE_CTX_set_purpose 2142 +sk_X509_TRUST_dup 2143 +sk_X509_TRUST_insert 2144 +X509_check_trust 2145 +sk_X509_TRUST_sort 2146 +X509_reject_set_bit 2147 +sk_X509_TRUST_delete 2148 -- 2.40.0