| /* 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 <openssl/err.h> |
| #include <openssl/asn1.h> |
| #include <openssl/objects.h> |
| #include <openssl/evp.h> |
| #include <openssl/x509.h> |
| #include <openssl/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); |
| buf[0] = '\0'; |
| fgets(buf, sizeof buf, 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); |
| } |