spkigen.c revision 296465
1/* NOCW */
2/*-
3 * demos/spkigen.c
4 * 18-Mar-1997 - eay - A quick hack :-)
5 *              version 1.1, it would probably help to save or load the
6 *              private key :-)
7 */
8#include <stdio.h>
9#include <stdlib.h>
10#include <openssl/err.h>
11#include <openssl/asn1.h>
12#include <openssl/objects.h>
13#include <openssl/evp.h>
14#include <openssl/x509.h>
15#include <openssl/pem.h>
16
17/*
18 * The following two don't exist in SSLeay but they are in here as examples
19 */
20#define PEM_write_SPKI(fp,x) \
21        PEM_ASN1_write((int (*)())i2d_NETSCAPE_SPKI,"SPKI",fp,\
22                        (char *)x,NULL,NULL,0,NULL)
23int SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
24
25/* These are defined in the next version of SSLeay */
26int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key);
27#define RSA_F4  0x10001
28#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
29                                        (char *)(rsa))
30
31int main(argc, argv)
32int argc;
33char *argv[];
34{
35    RSA *rsa = NULL;
36    NETSCAPE_SPKI *spki = NULL;
37    EVP_PKEY *pkey = NULL;
38    char buf[128];
39    int ok = 0, i;
40    FILE *fp;
41
42    pkey = EVP_PKEY_new();
43
44    if (argc < 2) {
45        /*
46         * Generate an RSA key, the random state should have been seeded with
47         * lots of calls to RAND_seed(....)
48         */
49        fprintf(stderr, "generating RSA key, could take some time...\n");
50        if ((rsa = RSA_generate_key(512, RSA_F4, NULL)) == NULL)
51            goto err;
52    } else {
53        if ((fp = fopen(argv[1], "r")) == NULL) {
54            perror(argv[1]);
55            goto err;
56        }
57        if ((rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL)) == NULL)
58            goto err;
59        fclose(fp);
60    }
61
62    if (!EVP_PKEY_assign_RSA(pkey, rsa))
63        goto err;
64    rsa = NULL;
65
66    /* lets make the spki and set the public key and challenge */
67    if ((spki = NETSCAPE_SPKI_new()) == NULL)
68        goto err;
69
70    if (!SPKI_set_pubkey(spki, pkey))
71        goto err;
72
73    fprintf(stderr, "please enter challenge string:");
74    fflush(stderr);
75    buf[0] = '\0';
76    fgets(buf, sizeof buf, stdin);
77    i = strlen(buf);
78    if (i > 0)
79        buf[--i] = '\0';
80    if (!ASN1_STRING_set((ASN1_STRING *)spki->spkac->challenge, buf, i))
81        goto err;
82
83    if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()))
84        goto err;
85    PEM_write_SPKI(stdout, spki);
86    if (argc < 2)
87        PEM_write_RSAPrivateKey(stdout, pkey->pkey.rsa, NULL, NULL, 0, NULL);
88
89    ok = 1;
90 err:
91    if (!ok) {
92        fprintf(stderr, "something bad happened....");
93        ERR_print_errors_fp(stderr);
94    }
95    NETSCAPE_SPKI_free(spki);
96    EVP_PKEY_free(pkey);
97    exit(!ok);
98}
99
100/* This function is in the next version of SSLeay */
101int EVP_PKEY_assign(pkey, type, key)
102EVP_PKEY *pkey;
103int type;
104char *key;
105{
106    if (pkey == NULL)
107        return (0);
108    if (pkey->pkey.ptr != NULL) {
109        if (pkey->type == EVP_PKEY_RSA)
110            RSA_free(pkey->pkey.rsa);
111        /* else memory leak */
112    }
113    pkey->type = type;
114    pkey->pkey.ptr = key;
115    return (1);
116}
117
118/*
119 * While I have a X509_set_pubkey() and X509_REQ_set_pubkey(),
120 * SPKI_set_pubkey() does not currently exist so here is a version of it. The
121 * next SSLeay release will probably have X509_set_pubkey(),
122 * X509_REQ_set_pubkey() and NETSCAPE_SPKI_set_pubkey() as macros calling the
123 * same function
124 */
125int SPKI_set_pubkey(x, pkey)
126NETSCAPE_SPKI *x;
127EVP_PKEY *pkey;
128{
129    int ok = 0;
130    X509_PUBKEY *pk;
131    X509_ALGOR *a;
132    ASN1_OBJECT *o;
133    unsigned char *s, *p;
134    int i;
135
136    if (x == NULL)
137        return (0);
138
139    if ((pk = X509_PUBKEY_new()) == NULL)
140        goto err;
141    a = pk->algor;
142
143    /* set the algorithm id */
144    if ((o = OBJ_nid2obj(pkey->type)) == NULL)
145        goto err;
146    ASN1_OBJECT_free(a->algorithm);
147    a->algorithm = o;
148
149    /* Set the parameter list */
150    if ((a->parameter == NULL) || (a->parameter->type != V_ASN1_NULL)) {
151        ASN1_TYPE_free(a->parameter);
152        a->parameter = ASN1_TYPE_new();
153        a->parameter->type = V_ASN1_NULL;
154    }
155    i = i2d_PublicKey(pkey, NULL);
156    if ((s = (unsigned char *)malloc(i + 1)) == NULL)
157        goto err;
158    p = s;
159    i2d_PublicKey(pkey, &p);
160    if (!ASN1_BIT_STRING_set(pk->public_key, s, i))
161        goto err;
162    free(s);
163
164    X509_PUBKEY_free(x->spkac->pubkey);
165    x->spkac->pubkey = pk;
166    pk = NULL;
167    ok = 1;
168 err:
169    if (pk != NULL)
170        X509_PUBKEY_free(pk);
171    return (ok);
172}
173