verify.c 3.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
#include <stdio.h>
#include "asn1.h"
#include "bio.h"
#include "x509.h"
#include "pem.h"

int verify_callback(int ok, X509_STORE_CTX *ctx);

BIO *bio_err=NULL;

main(argc,argv)
int argc;
char *argv[];
	{
	X509 *x509,*x;
	PKCS7 *p7;
	PKCS7_SIGNED *s;
	PKCS7_SIGNER_INFO *si;
	PKCS7_ISSUER_AND_SERIAL *ias;
	X509_STORE_CTX cert_ctx;
	X509_STORE *cert_store=NULL;
	X509_LOOKUP *lookup=NULL;
	BIO *data,*detached=NULL,*p7bio=NULL;
	char buf[1024*4];
	unsigned char *p,*pp;
	int i,j,printit=0;
	STACK *sk;

	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	EVP_add_digest(EVP_md2());
	EVP_add_digest(EVP_md5());
	EVP_add_digest(EVP_sha1());
	EVP_add_digest(EVP_mdc2());

	data=BIO_new(BIO_s_file());
again:
	pp=NULL;
	while (argc > 1)
		{
		argc--;
		argv++;
		if (strcmp(argv[0],"-p") == 0)
			{
			printit=1;
			}
		else if ((strcmp(argv[0],"-d") == 0) && (argc >= 2))
			{
			detached=BIO_new(BIO_s_file());
			if (!BIO_read_filename(detached,argv[1]))
				goto err;
			argc--;
			argv++;
			}
		else
			{
			pp=argv[0];
			if (!BIO_read_filename(data,argv[0]))
				goto err;
			}
		}

	if (pp == NULL)
		BIO_set_fp(data,stdin,BIO_NOCLOSE);


	/* Load the PKCS7 object from a file */
	if ((p7=PEM_read_bio_PKCS7(data,NULL,NULL)) == NULL) goto err;

	/* This stuff is being setup for certificate verification.
	 * When using SSL, it could be replaced with a 
	 * cert_stre=SSL_CTX_get_cert_store(ssl_ctx); */
	cert_store=X509_STORE_new();
	X509_STORE_set_default_paths(cert_store);
	X509_STORE_load_locations(cert_store,NULL,"../../certs");
	X509_STORE_set_verify_cb_func(cert_store,verify_callback);

	ERR_clear_errors();

	/* We need to process the data */
	if (PKCS7_get_detached(p7))
		{
		if (detached == NULL)
			{
			printf("no data to verify the signature on\n");
			exit(1);
			}
		else
			p7bio=PKCS7_dataInit(p7,detached);
		}
	else
		{
		p7bio=PKCS7_dataInit(p7,NULL);
		}

	/* We now have to 'read' from p7bio to calculate digests etc. */
	for (;;)
		{
		i=BIO_read(p7bio,buf,sizeof(buf));
		/* print it? */
		if (i <= 0) break;
		}

	/* We can now verify signatures */
	sk=PKCS7_get_signer_info(p7);
	if (sk == NULL)
		{
		printf("there are no signatures on this data\n");
		exit(1);
		}

	/* Ok, first we need to, for each subject entry, see if we can verify */
	for (i=0; i<sk_num(sk); i++)
		{
		si=(PKCS7_SIGNER_INFO *)sk_value(sk,i);
		i=PKCS7_dataVerify(cert_store,&cert_ctx,p7bio,p7,si);
		if (i <= 0)
			goto err;
		}

	X509_STORE_free(cert_store);

	printf("done\n");
	exit(0);
err:
	ERR_load_crypto_strings();
	ERR_print_errors_fp(stderr);
	exit(1);
	}

/* should be X509 * but we can just have them as char *. */
int verify_callback(ok, ctx)
int ok;
X509_STORE_CTX *ctx;
	{
	char buf[256];
	X509 *err_cert;
	int err,depth;

	err_cert=X509_STORE_CTX_get_current_cert(ctx);
	err=	X509_STORE_CTX_get_error(ctx);
	depth=	X509_STORE_CTX_get_error_depth(ctx);

	X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
	BIO_printf(bio_err,"depth=%d %s\n",depth,buf);
	if (!ok)
		{
		BIO_printf(bio_err,"verify error:num=%d:%s\n",err,
			X509_verify_cert_error_string(err));
		if (depth < 6)
			{
			ok=1;
			X509_STORE_CTX_set_error(ctx,X509_V_OK);
			}
		else
			{
			ok=0;
			X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG);
			}
		}
	switch (ctx->error)
		{
	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
		X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
		BIO_printf(bio_err,"issuer= %s\n",buf);
		break;
	case X509_V_ERR_CERT_NOT_YET_VALID:
	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
		BIO_printf(bio_err,"notBefore=");
		ASN1_UTCTIME_print(bio_err,X509_get_notBefore(ctx->current_cert));
		BIO_printf(bio_err,"\n");
		break;
	case X509_V_ERR_CERT_HAS_EXPIRED:
	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
		BIO_printf(bio_err,"notAfter=");
		ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ctx->current_cert));
		BIO_printf(bio_err,"\n");
		break;
		}
	BIO_printf(bio_err,"verify return:%d\n",ok);
	return(ok);
	}