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