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