cert_req.c 11 KB
Newer Older
1 2 3
/*
 *  Certificate request generation
 *
4
 *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

29
#if defined(MBEDTLS_PLATFORM_C)
30
#include "mbedtls/platform.h"
31
#else
Rich Evans's avatar
Rich Evans committed
32
#include <stdio.h>
33
#define mbedtls_printf     printf
34 35
#endif

36 37 38
#if !defined(MBEDTLS_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) ||  \
    !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \
    !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
39 40
int main( void )
{
41 42 43
    mbedtls_printf( "MBEDTLS_X509_CSR_WRITE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_SHA256_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
44 45 46 47 48
            "not defined.\n");
    return( 0 );
}
#else

49 50 51 52
#include "mbedtls/x509_csr.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
53

Rich Evans's avatar
Rich Evans committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DFL_FILENAME            "keyfile.key"
#define DFL_DEBUG_LEVEL         0
#define DFL_OUTPUT_FILENAME     "cert.req"
#define DFL_SUBJECT_NAME        "CN=Cert,O=mbed TLS,C=UK"
#define DFL_KEY_USAGE           0
#define DFL_NS_CERT_TYPE        0

#define USAGE \
    "\n usage: cert_req param=<>...\n"                  \
    "\n acceptable parameters:\n"                       \
    "    filename=%%s         default: keyfile.key\n"   \
    "    debug_level=%%d      default: 0 (disabled)\n"  \
    "    output_file=%%s      default: cert.req\n"      \
    "    subject_name=%%s     default: CN=Cert,O=mbed TLS,C=UK\n"   \
    "    key_usage=%%s        default: (empty)\n"       \
    "                        Comma-separated-list of values:\n"     \
    "                          digital_signature\n"     \
    "                          non_repudiation\n"       \
    "                          key_encipherment\n"      \
    "                          data_encipherment\n"     \
    "                          key_agreement\n"         \
    "                          key_certificate_sign\n"  \
    "                          crl_sign\n"              \
    "    ns_cert_type=%%s     default: (empty)\n"       \
    "                        Comma-separated-list of values:\n"     \
    "                          ssl_client\n"            \
    "                          ssl_server\n"            \
    "                          email\n"                 \
    "                          object_signing\n"        \
    "                          ssl_ca\n"                \
    "                          email_ca\n"              \
    "                          object_signing_ca\n"     \
    "\n"

92 93 94 95 96
/*
 * global options
 */
struct options
{
Paul Bakker's avatar
Paul Bakker committed
97
    const char *filename;       /* filename of the key file             */
98
    int debug_level;            /* level of debugging                   */
Paul Bakker's avatar
Paul Bakker committed
99 100
    const char *output_file;    /* where to store the constructed key file  */
    const char *subject_name;   /* subject name for certificate request */
101 102
    unsigned char key_usage;    /* key usage flags                      */
    unsigned char ns_cert_type; /* NS cert type                         */
103 104
} opt;

105
int write_certificate_request( mbedtls_x509write_csr *req, const char *output_file,
106 107
                               int (*f_rng)(void *, unsigned char *, size_t),
                               void *p_rng )
108
{
109
    int ret;
110 111
    FILE *f;
    unsigned char output_buf[4096];
112
    size_t len = 0;
113

114
    memset( output_buf, 0, 4096 );
115
    if( ( ret = mbedtls_x509write_csr_pem( req, output_buf, 4096, f_rng, p_rng ) ) < 0 )
116
        return( ret );
117

118
    len = strlen( (char *) output_buf );
119

120 121 122
    if( ( f = fopen( output_file, "w" ) ) == NULL )
        return( -1 );

123
    if( fwrite( output_buf, 1, len, f ) != len )
124 125
    {
        fclose( f );
126
        return( -1 );
127
    }
128

129
    fclose( f );
130 131

    return( 0 );
132 133 134 135 136
}

int main( int argc, char *argv[] )
{
    int ret = 0;
137
    mbedtls_pk_context key;
138
    char buf[1024];
139
    int i;
140
    char *p, *q, *r;
141 142 143
    mbedtls_x509write_csr req;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
144
    const char *pers = "csr example app";
145 146 147 148

    /*
     * Set to sane values
     */
149 150 151
    mbedtls_x509write_csr_init( &req );
    mbedtls_x509write_csr_set_md_alg( &req, MBEDTLS_MD_SHA256 );
    mbedtls_pk_init( &key );
152
    memset( buf, 0, sizeof( buf ) );
153 154 155 156

    if( argc == 0 )
    {
    usage:
157
        mbedtls_printf( USAGE );
158
        ret = 1;
159 160 161 162 163 164 165
        goto exit;
    }

    opt.filename            = DFL_FILENAME;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.output_file         = DFL_OUTPUT_FILENAME;
    opt.subject_name        = DFL_SUBJECT_NAME;
166 167
    opt.key_usage           = DFL_KEY_USAGE;
    opt.ns_cert_type        = DFL_NS_CERT_TYPE;
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

    for( i = 1; i < argc; i++ )
    {

        p = argv[i];
        if( ( q = strchr( p, '=' ) ) == NULL )
            goto usage;
        *q++ = '\0';

        if( strcmp( p, "filename" ) == 0 )
            opt.filename = q;
        else if( strcmp( p, "output_file" ) == 0 )
            opt.output_file = q;
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "subject_name" ) == 0 )
        {
            opt.subject_name = q;
        }
191 192 193 194 195 196 197 198
        else if( strcmp( p, "key_usage" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "digital_signature" ) == 0 )
199
                    opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
200
                else if( strcmp( q, "non_repudiation" ) == 0 )
201
                    opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
202
                else if( strcmp( q, "key_encipherment" ) == 0 )
203
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
204
                else if( strcmp( q, "data_encipherment" ) == 0 )
205
                    opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
206
                else if( strcmp( q, "key_agreement" ) == 0 )
207
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
208
                else if( strcmp( q, "key_cert_sign" ) == 0 )
209
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
210
                else if( strcmp( q, "crl_sign" ) == 0 )
211
                    opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
212 213 214 215 216 217 218 219 220 221 222 223 224 225
                else
                    goto usage;

                q = r;
            }
        }
        else if( strcmp( p, "ns_cert_type" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "ssl_client" ) == 0 )
226
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
227
                else if( strcmp( q, "ssl_server" ) == 0 )
228
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
229
                else if( strcmp( q, "email" ) == 0 )
230
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
231
                else if( strcmp( q, "object_signing" ) == 0 )
232
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
233
                else if( strcmp( q, "ssl_ca" ) == 0 )
234
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
235
                else if( strcmp( q, "email_ca" ) == 0 )
236
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
237
                else if( strcmp( q, "object_signing_ca" ) == 0 )
238
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
239 240 241 242 243 244
                else
                    goto usage;

                q = r;
            }
        }
245 246 247 248
        else
            goto usage;
    }

249
    if( opt.key_usage )
250
        mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );
251 252

    if( opt.ns_cert_type )
253
        mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );
254

255 256 257
    /*
     * 0. Seed the PRNG
     */
258
    mbedtls_printf( "  . Seeding the random number generator..." );
259 260
    fflush( stdout );

261 262
    mbedtls_entropy_init( &entropy );
    if( ( ret = mbedtls_ctr_drbg_init( &ctr_drbg, mbedtls_entropy_func, &entropy,
263 264 265
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
266
        mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_init returned %d", ret );
267 268 269
        goto exit;
    }

270
    mbedtls_printf( " ok\n" );
271

272 273 274
    /*
     * 1.0. Check the subject name for validity
     */
275
    mbedtls_printf( "  . Checking subjet name..." );
276 277
    fflush( stdout );

278
    if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 )
279
    {
280
        mbedtls_printf( " failed\n  !  mbedtls_x509write_csr_set_subject_name returned %d", ret );
281
        goto exit;
282 283
    }

284
    mbedtls_printf( " ok\n" );
285

286 287 288
    /*
     * 1.1. Load the key
     */
289
    mbedtls_printf( "  . Loading the private key ..." );
290 291
    fflush( stdout );

292
    ret = mbedtls_pk_parse_keyfile( &key, opt.filename, NULL );
293 294 295

    if( ret != 0 )
    {
296
        mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned %d", ret );
297 298 299
        goto exit;
    }

300
    mbedtls_x509write_csr_set_key( &req, &key );
301

302
    mbedtls_printf( " ok\n" );
303

304 305 306
    /*
     * 1.2. Writing the request
     */
307
    mbedtls_printf( "  . Writing the certificate request ..." );
308
    fflush( stdout );
309

310
    if( ( ret = write_certificate_request( &req, opt.output_file,
311
                                           mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
312
    {
313
        mbedtls_printf( " failed\n  !  write_certifcate_request %d", ret );
314 315
        goto exit;
    }
316

317
    mbedtls_printf( " ok\n" );
318 319

exit:
320 321 322

    if( ret != 0 && ret != 1)
    {
323 324 325
#ifdef MBEDTLS_ERROR_C
        mbedtls_strerror( ret, buf, sizeof( buf ) );
        mbedtls_printf( " - %s\n", buf );
326
#else
327
        mbedtls_printf("\n");
328 329 330
#endif
    }

331 332 333 334
    mbedtls_x509write_csr_free( &req );
    mbedtls_pk_free( &key );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
335 336

#if defined(_WIN32)
337
    mbedtls_printf( "  + Press Enter to exit this program.\n" );
338 339 340 341 342
    fflush( stdout ); getchar();
#endif

    return( ret );
}
343 344
#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
          MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */