Commit fd2309aa authored by Rob Stradling's avatar Rob Stradling Committed by Dr. Stephen Henson
Browse files

Separate the SCT List parser from the SCT List viewer

parent 2f1dffa8
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -1481,6 +1481,28 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void)
#define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st))
#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st))

#define sk_SCT_new(cmp) SKM_sk_new(SCT, (cmp))
#define sk_SCT_new_null() SKM_sk_new_null(SCT)
#define sk_SCT_free(st) SKM_sk_free(SCT, (st))
#define sk_SCT_num(st) SKM_sk_num(SCT, (st))
#define sk_SCT_value(st, i) SKM_sk_value(SCT, (st), (i))
#define sk_SCT_set(st, i, val) SKM_sk_set(SCT, (st), (i), (val))
#define sk_SCT_zero(st) SKM_sk_zero(SCT, (st))
#define sk_SCT_push(st, val) SKM_sk_push(SCT, (st), (val))
#define sk_SCT_unshift(st, val) SKM_sk_unshift(SCT, (st), (val))
#define sk_SCT_find(st, val) SKM_sk_find(SCT, (st), (val))
#define sk_SCT_find_ex(st, val) SKM_sk_find_ex(SCT, (st), (val))
#define sk_SCT_delete(st, i) SKM_sk_delete(SCT, (st), (i))
#define sk_SCT_delete_ptr(st, ptr) SKM_sk_delete_ptr(SCT, (st), (ptr))
#define sk_SCT_insert(st, val, i) SKM_sk_insert(SCT, (st), (val), (i))
#define sk_SCT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SCT, (st), (cmp))
#define sk_SCT_dup(st) SKM_sk_dup(SCT, st)
#define sk_SCT_pop_free(st, free_func) SKM_sk_pop_free(SCT, (st), (free_func))
#define sk_SCT_shift(st) SKM_sk_shift(SCT, (st))
#define sk_SCT_pop(st) SKM_sk_pop(SCT, (st))
#define sk_SCT_sort(st) SKM_sk_sort(SCT, (st))
#define sk_SCT_is_sorted(st) SKM_sk_is_sorted(SCT, (st))

#define sk_SRP_gN_new(cmp) SKM_sk_new(SRP_gN, (cmp))
#define sk_SRP_gN_new_null() SKM_sk_new_null(SRP_gN)
#define sk_SRP_gN_free(st) SKM_sk_free(SRP_gN, (st))
+172 −71
Original line number Diff line number Diff line
@@ -60,61 +60,88 @@
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/x509v3.h>
#include <openssl/bn.h>
#include "../ssl/ssl_locl.h"

#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
#define SCTS_TIMESTAMP unsigned __int64
#define SCT_TIMESTAMP unsigned __int64
#elif defined(__arch64__)
#define SCTS_TIMESTAMP unsigned long
#define SCT_TIMESTAMP unsigned long
#else
#define SCTS_TIMESTAMP unsigned long long
#define SCT_TIMESTAMP unsigned long long
#endif

#define n2l8(c,l)	(l =((SCTS_TIMESTAMP)(*((c)++)))<<56, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<<48, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<<40, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<<32, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<<24, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<<16, \
			 l|=((SCTS_TIMESTAMP)(*((c)++)))<< 8, \
			 l|=((SCTS_TIMESTAMP)(*((c)++))))
#define n2l8(c,l)	(l =((SCT_TIMESTAMP)(*((c)++)))<<56, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<<48, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<<40, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<<32, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<<24, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<<16, \
			 l|=((SCT_TIMESTAMP)(*((c)++)))<< 8, \
			 l|=((SCT_TIMESTAMP)(*((c)++))))

typedef struct SCT_st {
	/* The encoded SCT */
	unsigned char *sct;
	unsigned short sctlen;

static int i2r_scts(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct, BIO *out, int indent);
	/* Components of the SCT.  "logid", "ext" and "sig" point to addresses
	 * inside "sct".
	 */
	unsigned char version;
	unsigned char* logid;
	unsigned short logidlen;
	SCT_TIMESTAMP timestamp;
	unsigned char *ext;
	unsigned short extlen;
	unsigned char hash_alg;
	unsigned char sig_alg;
	unsigned char *sig;
	unsigned short siglen;
} SCT;

DECLARE_STACK_OF(SCT)

static void SCT_LIST_free(STACK_OF(SCT) *a);
static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
				   long length);
static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
			BIO *out, int indent);

const X509V3_EXT_METHOD v3_ct_scts[] = {
{ NID_ct_precert_scts, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
0,0,0,0,
{ NID_ct_precert_scts, 0, NULL,
0,(X509V3_EXT_FREE)SCT_LIST_free,
(X509V3_EXT_D2I)d2i_SCT_LIST, 0,
0,0,0,0,
(X509V3_EXT_I2R)i2r_scts, NULL,
(X509V3_EXT_I2R)i2r_SCT_LIST, 0,
NULL},

{ NID_ct_cert_scts, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
{ NID_ct_cert_scts, 0, NULL,
0,(X509V3_EXT_FREE)SCT_LIST_free,
(X509V3_EXT_D2I)d2i_SCT_LIST, 0,
0,0,0,0,
0,0,0,0,
(X509V3_EXT_I2R)i2r_scts, NULL,
(X509V3_EXT_I2R)i2r_SCT_LIST, 0,
NULL},
};

static void tls12_signature_print(BIO *out, const unsigned char *data)
static void tls12_signature_print(BIO *out, const unsigned char hash_alg,
				  const unsigned char sig_alg)
	{
	int nid = NID_undef;
	/* RFC6962 only permits two signature algorithms */
	if (data[0] == TLSEXT_hash_sha256)
	if (hash_alg == TLSEXT_hash_sha256)
		{
		if (data[1] == TLSEXT_signature_rsa)
		if (sig_alg == TLSEXT_signature_rsa)
			nid = NID_sha256WithRSAEncryption;
		else if (data[1] == TLSEXT_signature_ecdsa)
		else if (sig_alg == TLSEXT_signature_ecdsa)
			nid = NID_ecdsa_with_SHA256;
		}
	if (nid == NID_undef)
		BIO_printf(out, "%02X%02X", data[0], data[1]);
		BIO_printf(out, "%02X%02X", hash_alg, sig_alg);
	else
		BIO_printf(out, "%s", OBJ_nid2ln(nid));
	}

static void timestamp_print(BIO *out, SCTS_TIMESTAMP timestamp)
static void timestamp_print(BIO *out, SCT_TIMESTAMP timestamp)
	{
	ASN1_GENERALIZEDTIME *gen;
	char genstr[20];
@@ -133,38 +160,72 @@ static void timestamp_print(BIO *out, SCTS_TIMESTAMP timestamp)
	ASN1_GENERALIZEDTIME_free(gen);
	}

static int i2r_scts(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct,
		       BIO *out, int indent)
static void SCT_free(SCT *sct)
	{
	if (sct)
		{
		if (sct->sct) OPENSSL_free(sct->sct);
		OPENSSL_free(sct);
		}
	}

static void SCT_LIST_free(STACK_OF(SCT) *a)
	{
	sk_SCT_pop_free(a, SCT_free);
	}

static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
				   long length)
	{
	SCTS_TIMESTAMP timestamp;
	unsigned char* data = oct->data;
	ASN1_OCTET_STRING *oct = NULL;
	STACK_OF(SCT) *sk = NULL;
	SCT *sct;
	unsigned char *p, *p2;
	unsigned short listlen, sctlen = 0, fieldlen;

	if (d2i_ASN1_OCTET_STRING(&oct, pp, length) == NULL)
		return NULL;
	if (oct->length < 2)
		return 0;
	n2s(data, listlen);
		goto done;
	p = oct->data;
	n2s(p, listlen);
	if (listlen != oct->length - 2)
		return 0;
		goto done;

	if ((sk=sk_SCT_new_null()) == NULL)
		goto done;

	while (listlen > 0)
		{
		if (listlen < 2)
			return 0;
		n2s(data, sctlen);
			goto err;
		n2s(p, sctlen);
		listlen -= 2;

		if ((sctlen < 1) || (sctlen > listlen))
			return 0;
			goto err;
		listlen -= sctlen;

		BIO_printf(out, "%*sSigned Certificate Timestamp:", indent,
			   "");
		BIO_printf(out, "\n%*sVersion   : ", indent + 4, "");

		if (*data == 0)		/* SCT v1 */
		sct = OPENSSL_malloc(sizeof(SCT));
		if (!sct)
			goto err;
		if (!sk_SCT_push(sk, sct))
			{
			BIO_printf(out, "v1(0)");
			OPENSSL_free(sct);
			goto err;
			}

		sct->sct = OPENSSL_malloc(sctlen);
		if (!sct->sct)
			goto err;
		memcpy(sct->sct, p, sctlen);
		sct->sctlen = sctlen;
		p += sctlen;
		p2 = sct->sct;

		sct->version = *p2++;
		if (sct->version == 0)		/* SCT v1 */
			{
			/* Fixed-length header:
			 *		struct {
			 * (1 byte)	  Version sct_version;
@@ -173,28 +234,22 @@ static int i2r_scts(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct,
			 * (2 bytes + ?)  CtExtensions extensions;
			 */
			if (sctlen < 43)
				return 0;
				goto err;
			sctlen -= 43;

			BIO_printf(out, "\n%*sLog ID    : ", indent + 4, "");
			BIO_hex_string(out, indent + 16, 16, data + 1, 32);
			sct->logid = p2;
			sct->logidlen = 32;
			p2 += 32;

			data += 33;
			n2l8(data, timestamp);
			BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
			timestamp_print(out, timestamp);
			n2l8(p2, sct->timestamp);

			n2s(data, fieldlen);
			n2s(p2, fieldlen);
			if (sctlen < fieldlen)
				return 0;
				goto err;
			sct->ext = p2;
			sct->extlen = fieldlen;
			p2 += fieldlen;
			sctlen -= fieldlen;
			BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
			if (fieldlen == 0)
				BIO_printf(out, "none");
			else
				BIO_hex_string(out, indent + 16, 16, data,
					       fieldlen);
			data += fieldlen;

			/* digitally-signed struct header:
			 * (1 byte)       Hash algorithm
@@ -202,27 +257,73 @@ static int i2r_scts(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct,
			 * (2 bytes + ?)  Signature
			 */
			if (sctlen < 4)
				return 0;
				goto err;
			sctlen -= 4;

			BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
			tls12_signature_print(out, data);
			data += 2;
			n2s(data, fieldlen);
			sct->hash_alg = *p2++;
			sct->sig_alg = *p2++;
			n2s(p2, fieldlen);
			if (sctlen != fieldlen)
				return 0;
				goto err;
			sct->sig = p2;
			sct->siglen = fieldlen;
			}
		}

	done:
	ASN1_OCTET_STRING_free(oct);
	return sk;

	err:
	SCT_LIST_free(sk);
	sk = NULL;
	goto done;
	}

static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
			BIO *out, int indent)
	{
	SCT *sct;
	int i;

	for (i = 0; i < sk_SCT_num(sct_list);) {
		sct = sk_SCT_value(sct_list, i);

		BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, "");
		BIO_printf(out, "\n%*sVersion   : ", indent + 4, "");

		if (sct->version == 0)	/* SCT v1 */
			{
			BIO_printf(out, "v1(0)");

			BIO_printf(out, "\n%*sLog ID    : ", indent + 4, "");
			BIO_hex_string(out, indent + 16, 16, sct->logid,
				       sct->logidlen);

			BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
			timestamp_print(out, sct->timestamp);

			BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
			if (sct->extlen == 0)
				BIO_printf(out, "none");
			else
				BIO_hex_string(out, indent + 16, 16, sct->ext,
					       sct->extlen);

			BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
			tls12_signature_print(out, sct->hash_alg, sct->sig_alg);
			BIO_printf(out, "\n%*s            ", indent + 4, "");
			BIO_hex_string(out, indent + 16, 16, data, fieldlen);
			data += fieldlen;
			BIO_hex_string(out, indent + 16, 16, sct->sig,
				       sct->siglen);
			}
		else			/* Unknown version */
			{
			BIO_printf(out, "unknown\n%*s", indent + 16, "");
			BIO_hex_string(out, indent + 16, 16, data, sctlen);
			data += sctlen;
			BIO_hex_string(out, indent + 16, 16, sct->sct,
				       sct->sctlen);
			}

		if (listlen > 0) BIO_printf(out, "\n");
		if (++i < sk_SCT_num(sct_list)) BIO_printf(out, "\n");
		}

	return 1;