3dfc65f16435f7056af02f4f00c473028f1593a0
[openssl.git] / demos / x509 / mkreq.c
1 /* Certificate request creation. Demonstrates some request related
2  * operations.
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include <openssl/pem.h>
9 #include <openssl/conf.h>
10 #include <openssl/x509v3.h>
11 #ifndef OPENSSL_NO_ENGINE
12 #include <openssl/engine.h>
13 #endif
14
15 int mkreq(X509_REQ **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
16 int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value);
17
18 int main(int argc, char **argv)
19         {
20         BIO *bio_err;
21         X509_REQ *req=NULL;
22         EVP_PKEY *pkey=NULL;
23
24         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
25
26         bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
27
28         mkreq(&req,&pkey,512,0,365);
29
30         RSA_print_fp(stdout,pkey->pkey.rsa,0);
31         X509_REQ_print_fp(stdout,req);
32
33         PEM_write_X509_REQ(stdout,req);
34
35         X509_REQ_free(req);
36         EVP_PKEY_free(pkey);
37
38 #ifndef OPENSSL_NO_ENGINE
39         ENGINE_cleanup();
40 #endif
41         CRYPTO_cleanup_all_ex_data();
42
43         CRYPTO_mem_leaks(bio_err);
44         BIO_free(bio_err);
45         return(0);
46         }
47
48 static void callback(int p, int n, void *arg)
49         {
50         char c='B';
51
52         if (p == 0) c='.';
53         if (p == 1) c='+';
54         if (p == 2) c='*';
55         if (p == 3) c='\n';
56         fputc(c,stderr);
57         }
58
59 int mkreq(X509_REQ **req, EVP_PKEY **pkeyp, int bits, int serial, int days)
60         {
61         X509_REQ *x;
62         EVP_PKEY *pk;
63         RSA *rsa;
64         X509_NAME *name=NULL;
65         STACK_OF(X509_EXTENSION) *exts = NULL;
66         
67         if ((pk=EVP_PKEY_new()) == NULL)
68                 goto err;
69
70         if ((x=X509_REQ_new()) == NULL)
71                 goto err;
72
73         rsa=RSA_generate_key(bits,RSA_F4,callback,NULL);
74         if (!EVP_PKEY_assign_RSA(pk,rsa))
75                 goto err;
76
77         rsa=NULL;
78
79         X509_REQ_set_pubkey(x,pk);
80
81         name=X509_REQ_get_subject_name(x);
82
83         /* This function creates and adds the entry, working out the
84          * correct string type and performing checks on its length.
85          * Normally we'd check the return value for errors...
86          */
87         X509_NAME_add_entry_by_txt(name,"C",
88                                 MBSTRING_ASC, "UK", -1, -1, 0);
89         X509_NAME_add_entry_by_txt(name,"CN",
90                                 MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);
91
92 #ifdef REQUEST_EXTENSIONS
93         /* Certificate requests can contain extensions, which can be used
94          * to indicate the extensions the requestor would like added to 
95          * their certificate. CAs might ignore them however or even choke
96          * if they are present.
97          */
98
99         /* For request extensions they are all packed in a single attribute.
100          * We save them in a STACK and add them all at once later...
101          */
102
103         exts = sk_X509_EXTENSION_new_null();
104         /* Standard extenions */
105
106         add_ext(exts, NID_key_usage, "critical,digitalSignature,keyEncipherment");
107
108         /* This is a typical use for request extensions: requesting a value for
109          * subject alternative name.
110          */
111
112         add_ext(exts, NID_subject_alt_name, "email:steve@openssl.org");
113
114         /* Some Netscape specific extensions */
115         add_ext(exts, NID_netscape_cert_type, "client,email");
116
117
118
119 #ifdef CUSTOM_EXT
120         /* Maybe even add our own extension based on existing */
121         {
122                 int nid;
123                 nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
124                 X509V3_EXT_add_alias(nid, NID_netscape_comment);
125                 add_ext(x, nid, "example comment alias");
126         }
127 #endif
128
129         /* Now we've created the extensions we add them to the request */
130
131         X509_REQ_add_extensions(x, exts);
132
133         sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
134
135 #endif
136         
137         if (!X509_REQ_sign(x,pk,EVP_md5()))
138                 goto err;
139
140         *req=x;
141         *pkeyp=pk;
142         return(1);
143 err:
144         return(0);
145         }
146
147 /* Add extension using V3 code: we can set the config file as NULL
148  * because we wont reference any other sections.
149  */
150
151 int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value)
152         {
153         X509_EXTENSION *ex;
154         ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
155         if (!ex)
156                 return 0;
157         sk_X509_EXTENSION_push(sk, ex);
158
159         return 1;
160         }
161