Security fixes brought forward from 0.9.7.
[openssl.git] / demos / x509 / mkcert.c
1 /* Certificate creation. Demonstrates some certificate related
2  * operations.
3  */
4
5
6 #include <stdio.h>
7 #include <stdlib.h>
8
9 #include <openssl/pem.h>
10 #include <openssl/conf.h>
11 #include <openssl/x509v3.h>
12 #include <openssl/engine.h>
13
14 int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
15 int add_ext(X509 *cert, int nid, char *value);
16
17 int main(int argc, char **argv)
18         {
19         BIO *bio_err;
20         X509 *x509=NULL;
21         EVP_PKEY *pkey=NULL;
22
23         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
24
25         bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
26
27         mkcert(&x509,&pkey,512,0,365);
28
29         RSA_print_fp(stdout,pkey->pkey.rsa,0);
30         X509_print_fp(stdout,x509);
31
32         PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL);
33         PEM_write_X509(stdout,x509);
34
35         X509_free(x509);
36         EVP_PKEY_free(pkey);
37
38         ENGINE_cleanup();
39         CRYPTO_cleanup_all_ex_data();
40
41         CRYPTO_mem_leaks(bio_err);
42         BIO_free(bio_err);
43         return(0);
44         }
45
46 static void callback(int p, int n, void *arg)
47         {
48         char c='B';
49
50         if (p == 0) c='.';
51         if (p == 1) c='+';
52         if (p == 2) c='*';
53         if (p == 3) c='\n';
54         fputc(c,stderr);
55         }
56
57 int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
58         {
59         X509 *x;
60         EVP_PKEY *pk;
61         RSA *rsa;
62         X509_NAME *name=NULL;
63         
64         if ((pkeyp == NULL) || (*pkeyp == NULL))
65                 {
66                 if ((pk=EVP_PKEY_new()) == NULL)
67                         {
68                         abort(); 
69                         return(0);
70                         }
71                 }
72         else
73                 pk= *pkeyp;
74
75         if ((x509p == NULL) || (*x509p == NULL))
76                 {
77                 if ((x=X509_new()) == NULL)
78                         goto err;
79                 }
80         else
81                 x= *x509p;
82
83         rsa=RSA_generate_key(bits,RSA_F4,callback,NULL);
84         if (!EVP_PKEY_assign_RSA(pk,rsa))
85                 {
86                 abort();
87                 goto err;
88                 }
89         rsa=NULL;
90
91         X509_set_version(x,2);
92         ASN1_INTEGER_set(X509_get_serialNumber(x),serial);
93         X509_gmtime_adj(X509_get_notBefore(x),0);
94         X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
95         X509_set_pubkey(x,pk);
96
97         name=X509_get_subject_name(x);
98
99         /* This function creates and adds the entry, working out the
100          * correct string type and performing checks on its length.
101          * Normally we'd check the return value for errors...
102          */
103         X509_NAME_add_entry_by_txt(name,"C",
104                                 MBSTRING_ASC, "UK", -1, -1, 0);
105         X509_NAME_add_entry_by_txt(name,"CN",
106                                 MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);
107
108         /* Its self signed so set the issuer name to be the same as the
109          * subject.
110          */
111         X509_set_issuer_name(x,name);
112
113         /* Add various extensions: standard extensions */
114         add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
115         add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");
116
117         add_ext(x, NID_subject_key_identifier, "hash");
118
119         /* Some Netscape specific extensions */
120         add_ext(x, NID_netscape_cert_type, "sslCA");
121
122         add_ext(x, NID_netscape_comment, "example comment extension");
123
124
125 #ifdef CUSTOM_EXT
126         /* Maybe even add our own extension based on existing */
127         {
128                 int nid;
129                 nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
130                 X509V3_EXT_add_alias(nid, NID_netscape_comment);
131                 add_ext(x, nid, "example comment alias");
132         }
133 #endif
134         
135         if (!X509_sign(x,pk,EVP_md5()))
136                 goto err;
137
138         *x509p=x;
139         *pkeyp=pk;
140         return(1);
141 err:
142         return(0);
143         }
144
145 /* Add extension using V3 code: we can set the config file as NULL
146  * because we wont reference any other sections.
147  */
148
149 int add_ext(X509 *cert, int nid, char *value)
150         {
151         X509_EXTENSION *ex;
152         X509V3_CTX ctx;
153         /* This sets the 'context' of the extensions. */
154         /* No configuration database */
155         X509V3_set_ctx_nodb(&ctx);
156         /* Issuer and subject certs: both the target since it is self signed,
157          * no request and no CRL
158          */
159         X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
160         ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
161         if (!ex)
162                 return 0;
163
164         X509_add_ext(cert,ex,-1);
165         X509_EXTENSION_free(ex);
166         return 1;
167         }
168