Documentation for new SSL functions
[openssl.git] / demos / spkigen.c
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)
23 int SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
24
25 /* These are defined in the next version of SSLeay */
26 int 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
31 int main(argc, argv)
32 int argc;
33 char *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 */
101 int EVP_PKEY_assign(pkey, type, key)
102 EVP_PKEY *pkey;
103 int type;
104 char *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  */
125 int SPKI_set_pubkey(x, pkey)
126 NETSCAPE_SPKI *x;
127 EVP_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     X509_PUBKEY_free(pk);
170     return (ok);
171 }