Commit 6dbb6219 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Make tls1_check_chain return a set of flags indicating checks passed

by a certificate chain. Add additional tests to handle client
certificates: checks for matching certificate type and issuer name
comparison.

Print out results of checks for each candidate chain tested in
s_server/s_client.
parent ec4a50b3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@

 Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]

  *) Make tls1_check_chain return a set of flags indicating checks passed
     by a certificate chain. Add additional tests to handle client
     certificates: checks for matching certificate type and issuer name
     comparison.
     [Steve Henson]

  *) If an attempt is made to use a signature algorithm not in the peer
     preference list abort the handshake. If client has no suitable
     signature algorithms in response to a certificate request do not
+45 −2
Original line number Diff line number Diff line
@@ -1134,12 +1134,45 @@ struct ssl_excert_st
	struct ssl_excert_st *next, *prev;
	};

struct chain_flags
	{
	int flag;
	const char *name;
	};

struct chain_flags chain_flags_list[] =
	{
		{CERT_PKEY_VALID, "Overall Validity"},
		{CERT_PKEY_SIGN,  "Sign with EE key"},
		{CERT_PKEY_EE_SIGNATURE, "EE signature"},
		{CERT_PKEY_CA_SIGNATURE, "CA signature"},
		{CERT_PKEY_EE_PARAM, "EE key parameters"},
		{CERT_PKEY_CA_PARAM, "CA key parameters"},
		{CERT_PKEY_EXPLICIT_SIGN,  "Explicity sign with EE key"},
		{CERT_PKEY_ISSUER_NAME,  "Issuer Name"},
		{CERT_PKEY_CERT_TYPE,  "Certificate Type"},
		{0, NULL}
	};


static void print_chain_flags(BIO *out, int flags)
	{
	struct chain_flags *ctmp = chain_flags_list;
	while(ctmp->name)
		{
		BIO_printf(out, "\t%s: %s\n", ctmp->name,
				flags & ctmp->flag ? "OK" : "NOT OK");
		ctmp++;
		}
	}

/* Very basic selection callback: just use any certificate chain
 * reported as valid. More sophisticated could prioritise according
 * to local policy.
 */
static int set_cert_cb(SSL *ssl, void *arg)
	{
	int i, rv;
	SSL_EXCERT *exc = arg;
	SSL_certs_clear(ssl);

@@ -1152,9 +1185,19 @@ static int set_cert_cb(SSL *ssl, void *arg)
	while (exc->next)
		exc = exc->next;

	i = 0;	

	while(exc)
		{
		if (SSL_check_chain(ssl, exc->cert, exc->key, exc->chain))
		i++;
		rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
		BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
		X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
							XN_FLAG_ONELINE);
		BIO_puts(bio_err, "\n");
		
		print_chain_flags(bio_err, rv);
		if (rv & CERT_PKEY_VALID)
			{
			SSL_use_certificate(ssl, exc->cert);
			SSL_use_PrivateKey(ssl, exc->key);
+6 −0
Original line number Diff line number Diff line
@@ -1963,6 +1963,12 @@ int ssl3_get_certificate_request(SSL *s)
			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
			goto err;
			}
		/* Clear certificate digests and validity flags */
		for (i = 0; i < SSL_PKEY_NUM; i++)
			{
			s->cert->pkeys[i].digest = NULL;
			s->cert->pkeys[i].valid_flags = 0;
			}
		if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
			{
			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+20 −0
Original line number Diff line number Diff line
@@ -662,6 +662,26 @@ struct ssl_session_st
/* Con't include root CA in chain */
#define SSL_BUILD_CHAIN_FLAG_NO_ROOT	0x2

/* Flags returned by SSL_check_chain */
/* Certificate can be used with this session */
#define CERT_PKEY_VALID		0x1
/* Certificate can also be used for signing */
#define CERT_PKEY_SIGN		0x2
/* EE certificate signing algorithm OK */
#define CERT_PKEY_EE_SIGNATURE	0x10
/* CA signature algorithms OK */
#define CERT_PKEY_CA_SIGNATURE	0x20
/* EE certificate parameters OK */
#define CERT_PKEY_EE_PARAM	0x40
/* CA certificate parameters OK */
#define CERT_PKEY_CA_PARAM	0x80
/* Signing explicitly allowed as opposed to SHA1 fallback */
#define CERT_PKEY_EXPLICIT_SIGN	0x100
/* Client CA issuer names match (always set for server cert) */
#define CERT_PKEY_ISSUER_NAME	0x200
/* Cert type matches client types (always set for server cert) */
#define CERT_PKEY_CERT_TYPE	0x400

/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
 * they cannot be used to clear bits. */

+2 −1
Original line number Diff line number Diff line
@@ -467,7 +467,8 @@ void ssl_cert_clear_certs(CERT *c)
                if (cpk->authz != NULL)
			OPENSSL_free(cpk->authz);
#endif
		cpk->valid_flags = 0;
		/* Clear all flags apart from explicit sign */
		cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN;
		}
	}

Loading