| /* 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); | 
 | 	} | 
 |  |