spkigen.c 3.7 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
/* NOCW */
/* demos/spkigen.c
 * 18-Mar-1997 - eay - A quick hack :-) 
 * 		version 1.1, it would probably help to save or load the
 *		private key :-)
 */
#include <stdio.h>
#include <stdlib.h>
#include "err.h"
#include "asn1.h"
#include "objects.h"
#include "evp.h"
#include "x509.h"
#include "pem.h"

/* The following two don't exist in SSLeay but they are in here as
 * examples */
#define PEM_write_SPKI(fp,x) \
	PEM_ASN1_write((int (*)())i2d_NETSCAPE_SPKI,"SPKI",fp,\
			(char *)x,NULL,NULL,0,NULL)
int SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);

/* These are defined in the next version of SSLeay */
int EVP_PKEY_assign(EVP_PKEY *pkey, int type,char *key);
#define RSA_F4	0x10001
#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
					(char *)(rsa))

int main(argc,argv)
int argc;
char *argv[];
	{
	RSA *rsa=NULL;
	NETSCAPE_SPKI *spki=NULL;
	EVP_PKEY *pkey=NULL;
	char buf[128];
	int ok=0,i;
	FILE *fp;

	pkey=EVP_PKEY_new();
	 
	if (argc < 2)
		{
		/* Generate an RSA key, the random state should have been seeded
		 * with lots of calls to RAND_seed(....) */
		fprintf(stderr,"generating RSA key, could take some time...\n");
		if ((rsa=RSA_generate_key(512,RSA_F4,NULL)) == NULL) goto err;
		}
	else
		{
		if ((fp=fopen(argv[1],"r")) == NULL)
			{ perror(argv[1]); goto err; }
		if ((rsa=PEM_read_RSAPrivateKey(fp,NULL,NULL)) == NULL)
			goto err;
		fclose(fp);
		}
	
	if (!EVP_PKEY_assign_RSA(pkey,rsa)) goto err;
	rsa=NULL;

	/* lets make the spki and set the public key and challenge */
	if ((spki=NETSCAPE_SPKI_new()) == NULL) goto err;

	if (!SPKI_set_pubkey(spki,pkey)) goto err;

	fprintf(stderr,"please enter challenge string:");
	fflush(stderr);
	fgets(buf,120,stdin);
	i=strlen(buf);
	if (i > 0) buf[--i]='\0';
	if (!ASN1_STRING_set((ASN1_STRING *)spki->spkac->challenge,
		buf,i)) goto err;

	if (!NETSCAPE_SPKI_sign(spki,pkey,EVP_md5())) goto err;
	PEM_write_SPKI(stdout,spki);
	if (argc < 2)
		PEM_write_RSAPrivateKey(stdout,pkey->pkey.rsa,NULL,NULL,0,NULL);

	ok=1;
err:
	if (!ok)
		{
		fprintf(stderr,"something bad happened....");
		ERR_print_errors_fp(stderr);
		}
	NETSCAPE_SPKI_free(spki);
	EVP_PKEY_free(pkey);
	exit(!ok);
	}

/* This function is in the next version of SSLeay */
int EVP_PKEY_assign(pkey,type,key)
EVP_PKEY *pkey;
int type;
char *key;
	{
	if (pkey == NULL) return(0);
	if (pkey->pkey.ptr != NULL)
		{
		if (pkey->type == EVP_PKEY_RSA)
			RSA_free(pkey->pkey.rsa);
		/* else memory leak */
		}
	pkey->type=type;
	pkey->pkey.ptr=key;
	return(1);
	}

/* While I have a 
 * X509_set_pubkey() and X509_REQ_set_pubkey(), SPKI_set_pubkey() does
 * not currently exist so here is a version of it.
 * The next SSLeay release will probably have
 * X509_set_pubkey(),
 * X509_REQ_set_pubkey() and
 * NETSCAPE_SPKI_set_pubkey()
 * as macros calling the same function */
int SPKI_set_pubkey(x,pkey)
NETSCAPE_SPKI *x;
EVP_PKEY *pkey;
	{
	int ok=0;
	X509_PUBKEY *pk;
	X509_ALGOR *a;
	ASN1_OBJECT *o;
	unsigned char *s,*p;
	int i;

	if (x == NULL) return(0);

	if ((pk=X509_PUBKEY_new()) == NULL) goto err;
	a=pk->algor;

	/* set the algorithm id */
	if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
	ASN1_OBJECT_free(a->algorithm);
	a->algorithm=o;

	/* Set the parameter list */
	if ((a->parameter == NULL) || (a->parameter->type != V_ASN1_NULL))
		{
		ASN1_TYPE_free(a->parameter);
		a->parameter=ASN1_TYPE_new();
		a->parameter->type=V_ASN1_NULL;
		}
	i=i2d_PublicKey(pkey,NULL);
	if ((s=(unsigned char *)malloc(i+1)) == NULL) goto err;
	p=s;
	i2d_PublicKey(pkey,&p);
	if (!ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err;
	free(s);

	X509_PUBKEY_free(x->spkac->pubkey);
	x->spkac->pubkey=pk;
	pk=NULL;
	ok=1;
err:
	if (pk != NULL) X509_PUBKEY_free(pk);
	return(ok);
	}