os/ossrv/ssl/tsrc/topenssl/src/pkcs8.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* pkcs8.c */
sl@0
     2
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
sl@0
     3
 * project 1999-2004.
sl@0
     4
 */
sl@0
     5
/* ====================================================================
sl@0
     6
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
sl@0
     7
 *
sl@0
     8
 * Redistribution and use in source and binary forms, with or without
sl@0
     9
 * modification, are permitted provided that the following conditions
sl@0
    10
 * are met:
sl@0
    11
 *
sl@0
    12
 * 1. Redistributions of source code must retain the above copyright
sl@0
    13
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    14
 *
sl@0
    15
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    16
 *    notice, this list of conditions and the following disclaimer in
sl@0
    17
 *    the documentation and/or other materials provided with the
sl@0
    18
 *    distribution.
sl@0
    19
 *
sl@0
    20
 * 3. All advertising materials mentioning features or use of this
sl@0
    21
 *    software must display the following acknowledgment:
sl@0
    22
 *    "This product includes software developed by the OpenSSL Project
sl@0
    23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
sl@0
    24
 *
sl@0
    25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    26
 *    endorse or promote products derived from this software without
sl@0
    27
 *    prior written permission. For written permission, please contact
sl@0
    28
 *    licensing@OpenSSL.org.
sl@0
    29
 *
sl@0
    30
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    31
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    32
 *    permission of the OpenSSL Project.
sl@0
    33
 *
sl@0
    34
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    35
 *    acknowledgment:
sl@0
    36
 *    "This product includes software developed by the OpenSSL Project
sl@0
    37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
sl@0
    38
 *
sl@0
    39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    51
 * ====================================================================
sl@0
    52
 *
sl@0
    53
 * This product includes cryptographic software written by Eric Young
sl@0
    54
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    55
 * Hudson (tjh@cryptsoft.com).
sl@0
    56
 *
sl@0
    57
 */
sl@0
    58
#include <stdio.h>
sl@0
    59
#include <string.h>
sl@0
    60
#include "apps.h"
sl@0
    61
#include <openssl/pem.h>
sl@0
    62
#include <openssl/err.h>
sl@0
    63
#include <openssl/evp.h>
sl@0
    64
#include <openssl/pkcs12.h>
sl@0
    65
sl@0
    66
#define PROG pkcs8_main
sl@0
    67
sl@0
    68
sl@0
    69
int MAIN(int, char **);
sl@0
    70
sl@0
    71
int MAIN(int argc, char **argv)
sl@0
    72
	{
sl@0
    73
	ENGINE *e = NULL;
sl@0
    74
	char **args, *infile = NULL, *outfile = NULL;
sl@0
    75
	char *passargin = NULL, *passargout = NULL;
sl@0
    76
	BIO *in = NULL, *out = NULL;
sl@0
    77
	int topk8 = 0;
sl@0
    78
	int pbe_nid = -1;
sl@0
    79
	const EVP_CIPHER *cipher = NULL;
sl@0
    80
	int iter = PKCS12_DEFAULT_ITER;
sl@0
    81
	int informat, outformat;
sl@0
    82
	int p8_broken = PKCS8_OK;
sl@0
    83
	int nocrypt = 0;
sl@0
    84
	X509_SIG *p8;
sl@0
    85
	PKCS8_PRIV_KEY_INFO *p8inf;
sl@0
    86
	EVP_PKEY *pkey=NULL;
sl@0
    87
	char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL;
sl@0
    88
	int badarg = 0;
sl@0
    89
#ifndef OPENSSL_NO_ENGINE
sl@0
    90
	char *engine=NULL;
sl@0
    91
#endif
sl@0
    92
sl@0
    93
	if (bio_err == NULL) 
sl@0
    94
	bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
sl@0
    95
	
sl@0
    96
sl@0
    97
	if (!load_config(bio_err, NULL))
sl@0
    98
		goto end;
sl@0
    99
sl@0
   100
	informat=FORMAT_PEM;
sl@0
   101
	outformat=FORMAT_PEM;
sl@0
   102
sl@0
   103
	ERR_load_crypto_strings();
sl@0
   104
	OpenSSL_add_all_algorithms();
sl@0
   105
	args = argv + 1;
sl@0
   106
	while (!badarg && *args && *args[0] == '-')
sl@0
   107
		{
sl@0
   108
		if (!strcmp(*args,"-v2"))
sl@0
   109
			{
sl@0
   110
			if (args[1])
sl@0
   111
				{
sl@0
   112
				args++;
sl@0
   113
				cipher=EVP_get_cipherbyname(*args);
sl@0
   114
				if (!cipher)
sl@0
   115
					{
sl@0
   116
					BIO_printf(bio_err,
sl@0
   117
						 "Unknown cipher %s\n", *args);
sl@0
   118
					badarg = 1;
sl@0
   119
					}
sl@0
   120
				}
sl@0
   121
			else
sl@0
   122
				badarg = 1;
sl@0
   123
			}
sl@0
   124
		else if (!strcmp(*args,"-v1"))
sl@0
   125
			{
sl@0
   126
			if (args[1])
sl@0
   127
				{
sl@0
   128
				args++;
sl@0
   129
				pbe_nid=OBJ_txt2nid(*args);
sl@0
   130
				if (pbe_nid == NID_undef)
sl@0
   131
					{
sl@0
   132
					BIO_printf(bio_err,
sl@0
   133
						 "Unknown PBE algorithm %s\n", *args);
sl@0
   134
					badarg = 1;
sl@0
   135
					}
sl@0
   136
				}
sl@0
   137
			else
sl@0
   138
				badarg = 1;
sl@0
   139
			}
sl@0
   140
		else if (!strcmp(*args,"-inform"))
sl@0
   141
			{
sl@0
   142
			if (args[1])
sl@0
   143
				{
sl@0
   144
				args++;
sl@0
   145
				informat=str2fmt(*args);
sl@0
   146
				}
sl@0
   147
			else badarg = 1;
sl@0
   148
			}
sl@0
   149
		else if (!strcmp(*args,"-outform"))
sl@0
   150
			{
sl@0
   151
			if (args[1])
sl@0
   152
				{
sl@0
   153
				args++;
sl@0
   154
				outformat=str2fmt(*args);
sl@0
   155
				}
sl@0
   156
			else badarg = 1;
sl@0
   157
			}
sl@0
   158
		else if (!strcmp (*args, "-topk8"))
sl@0
   159
			topk8 = 1;
sl@0
   160
		else if (!strcmp (*args, "-noiter"))
sl@0
   161
			iter = 1;
sl@0
   162
		else if (!strcmp (*args, "-nocrypt"))
sl@0
   163
			nocrypt = 1;
sl@0
   164
		else if (!strcmp (*args, "-nooct"))
sl@0
   165
			p8_broken = PKCS8_NO_OCTET;
sl@0
   166
		else if (!strcmp (*args, "-nsdb"))
sl@0
   167
			p8_broken = PKCS8_NS_DB;
sl@0
   168
		else if (!strcmp (*args, "-embed"))
sl@0
   169
			p8_broken = PKCS8_EMBEDDED_PARAM;
sl@0
   170
		else if (!strcmp(*args,"-passin"))
sl@0
   171
			{
sl@0
   172
			if (!args[1]) goto bad;
sl@0
   173
			passargin= *(++args);
sl@0
   174
			}
sl@0
   175
		else if (!strcmp(*args,"-passout"))
sl@0
   176
			{
sl@0
   177
			if (!args[1]) goto bad;
sl@0
   178
			passargout= *(++args);
sl@0
   179
			}
sl@0
   180
#ifndef OPENSSL_NO_ENGINE
sl@0
   181
		else if (strcmp(*args,"-engine") == 0)
sl@0
   182
			{
sl@0
   183
			if (!args[1]) goto bad;
sl@0
   184
			engine= *(++args);
sl@0
   185
			}
sl@0
   186
#endif
sl@0
   187
		else if (!strcmp (*args, "-in"))
sl@0
   188
			{
sl@0
   189
			if (args[1])
sl@0
   190
				{
sl@0
   191
				args++;
sl@0
   192
				infile = *args;
sl@0
   193
				}
sl@0
   194
			else badarg = 1;
sl@0
   195
			}
sl@0
   196
		else if (!strcmp (*args, "-out"))
sl@0
   197
			{
sl@0
   198
			if (args[1])
sl@0
   199
				{
sl@0
   200
				args++;
sl@0
   201
				outfile = *args;
sl@0
   202
				}
sl@0
   203
			else badarg = 1;
sl@0
   204
			}
sl@0
   205
		else badarg = 1;
sl@0
   206
		args++;
sl@0
   207
		}
sl@0
   208
sl@0
   209
	if (badarg)
sl@0
   210
		{
sl@0
   211
		bad:
sl@0
   212
		BIO_printf(bio_err, "Usage pkcs8 [options]\n");
sl@0
   213
		BIO_printf(bio_err, "where options are\n");
sl@0
   214
		BIO_printf(bio_err, "-in file        input file\n");
sl@0
   215
		BIO_printf(bio_err, "-inform X       input format (DER or PEM)\n");
sl@0
   216
		BIO_printf(bio_err, "-passin arg     input file pass phrase source\n");
sl@0
   217
		BIO_printf(bio_err, "-outform X      output format (DER or PEM)\n");
sl@0
   218
		BIO_printf(bio_err, "-out file       output file\n");
sl@0
   219
		BIO_printf(bio_err, "-passout arg    output file pass phrase source\n");
sl@0
   220
		BIO_printf(bio_err, "-topk8          output PKCS8 file\n");
sl@0
   221
		BIO_printf(bio_err, "-nooct          use (nonstandard) no octet format\n");
sl@0
   222
		BIO_printf(bio_err, "-embed          use (nonstandard) embedded DSA parameters format\n");
sl@0
   223
		BIO_printf(bio_err, "-nsdb           use (nonstandard) DSA Netscape DB format\n");
sl@0
   224
		BIO_printf(bio_err, "-noiter         use 1 as iteration count\n");
sl@0
   225
		BIO_printf(bio_err, "-nocrypt        use or expect unencrypted private key\n");
sl@0
   226
		BIO_printf(bio_err, "-v2 alg         use PKCS#5 v2.0 and cipher \"alg\"\n");
sl@0
   227
		BIO_printf(bio_err, "-v1 obj         use PKCS#5 v1.5 and cipher \"alg\"\n");
sl@0
   228
#ifndef OPENSSL_NO_ENGINE
sl@0
   229
		BIO_printf(bio_err," -engine e       use engine e, possibly a hardware device.\n");
sl@0
   230
#endif
sl@0
   231
		return 1;
sl@0
   232
		}
sl@0
   233
sl@0
   234
#ifndef OPENSSL_NO_ENGINE
sl@0
   235
        e = setup_engine(bio_err, engine, 0);
sl@0
   236
#endif
sl@0
   237
sl@0
   238
	if (!app_passwd(bio_err, passargin, passargout, &passin, &passout))
sl@0
   239
		{
sl@0
   240
		BIO_printf(bio_err, "Error getting passwords\n");
sl@0
   241
		return 1;
sl@0
   242
		}
sl@0
   243
sl@0
   244
	if ((pbe_nid == -1) && !cipher)
sl@0
   245
		pbe_nid = NID_pbeWithMD5AndDES_CBC;
sl@0
   246
sl@0
   247
	if (infile)
sl@0
   248
		{
sl@0
   249
		if (!(in = BIO_new_file(infile, "rb")))
sl@0
   250
			{
sl@0
   251
			BIO_printf(bio_err,
sl@0
   252
				 "Can't open input file %s\n", infile);
sl@0
   253
			return (1);
sl@0
   254
			}
sl@0
   255
		}
sl@0
   256
	else
sl@0
   257
		in = BIO_new_fp (stdin, BIO_NOCLOSE);
sl@0
   258
	if (outfile)
sl@0
   259
		{
sl@0
   260
		if (!(out = BIO_new_file (outfile, "wb")))
sl@0
   261
			{
sl@0
   262
			BIO_printf(bio_err,
sl@0
   263
				 "Can't open output file %s\n", outfile);
sl@0
   264
			return (1);
sl@0
   265
			}
sl@0
   266
		}
sl@0
   267
	else
sl@0
   268
		{
sl@0
   269
		out = BIO_new_fp (stdout, BIO_NOCLOSE);
sl@0
   270
#ifdef OPENSSL_SYS_VMS
sl@0
   271
			{
sl@0
   272
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
sl@0
   273
			out = BIO_push(tmpbio, out);
sl@0
   274
			}
sl@0
   275
#endif
sl@0
   276
		}
sl@0
   277
	if (topk8)
sl@0
   278
		{
sl@0
   279
		BIO_free(in); /* Not needed in this section */
sl@0
   280
		pkey = load_key(bio_err, infile, informat, 1,
sl@0
   281
			passin, e, "key");
sl@0
   282
		if (!pkey)
sl@0
   283
			{
sl@0
   284
			BIO_free_all(out);
sl@0
   285
			return 1;
sl@0
   286
			}
sl@0
   287
		if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken)))
sl@0
   288
			{
sl@0
   289
			BIO_printf(bio_err, "Error converting key\n");
sl@0
   290
			ERR_print_errors(bio_err);
sl@0
   291
			EVP_PKEY_free(pkey);
sl@0
   292
			BIO_free_all(out);
sl@0
   293
			return 1;
sl@0
   294
			}
sl@0
   295
		if (nocrypt)
sl@0
   296
			{
sl@0
   297
			if (outformat == FORMAT_PEM) 
sl@0
   298
				PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
sl@0
   299
			else if (outformat == FORMAT_ASN1)
sl@0
   300
				i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
sl@0
   301
			else
sl@0
   302
				{
sl@0
   303
				BIO_printf(bio_err, "Bad format specified for key\n");
sl@0
   304
				PKCS8_PRIV_KEY_INFO_free(p8inf);
sl@0
   305
				EVP_PKEY_free(pkey);
sl@0
   306
				BIO_free_all(out);
sl@0
   307
				return (1);
sl@0
   308
				}
sl@0
   309
			}
sl@0
   310
		else
sl@0
   311
			{
sl@0
   312
			if (passout)
sl@0
   313
				p8pass = passout;
sl@0
   314
			else
sl@0
   315
				{
sl@0
   316
				p8pass = pass;
sl@0
   317
				if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1))
sl@0
   318
					{
sl@0
   319
					PKCS8_PRIV_KEY_INFO_free(p8inf);
sl@0
   320
					EVP_PKEY_free(pkey);
sl@0
   321
					BIO_free_all(out);
sl@0
   322
					return (1);
sl@0
   323
					}
sl@0
   324
				}
sl@0
   325
			app_RAND_load_file(NULL, bio_err, 0);
sl@0
   326
			if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
sl@0
   327
					p8pass, strlen(p8pass),
sl@0
   328
					NULL, 0, iter, p8inf)))
sl@0
   329
				{
sl@0
   330
				BIO_printf(bio_err, "Error encrypting key\n");
sl@0
   331
				ERR_print_errors(bio_err);
sl@0
   332
				PKCS8_PRIV_KEY_INFO_free(p8inf);
sl@0
   333
				EVP_PKEY_free(pkey);
sl@0
   334
				BIO_free_all(out);
sl@0
   335
				return (1);
sl@0
   336
				}
sl@0
   337
			app_RAND_write_file(NULL, bio_err);
sl@0
   338
			if (outformat == FORMAT_PEM) 
sl@0
   339
				PEM_write_bio_PKCS8(out, p8);
sl@0
   340
			else if (outformat == FORMAT_ASN1)
sl@0
   341
				i2d_PKCS8_bio(out, p8);
sl@0
   342
			else
sl@0
   343
				{
sl@0
   344
				BIO_printf(bio_err, "Bad format specified for key\n");
sl@0
   345
				PKCS8_PRIV_KEY_INFO_free(p8inf);
sl@0
   346
				EVP_PKEY_free(pkey);
sl@0
   347
				BIO_free_all(out);
sl@0
   348
				return (1);
sl@0
   349
				}
sl@0
   350
			X509_SIG_free(p8);
sl@0
   351
			}
sl@0
   352
sl@0
   353
		PKCS8_PRIV_KEY_INFO_free (p8inf);
sl@0
   354
		EVP_PKEY_free(pkey);
sl@0
   355
		BIO_free_all(out);
sl@0
   356
		if (passin)
sl@0
   357
			OPENSSL_free(passin);
sl@0
   358
		if (passout)
sl@0
   359
			OPENSSL_free(passout);
sl@0
   360
		return (0);
sl@0
   361
		}
sl@0
   362
sl@0
   363
	if (nocrypt)
sl@0
   364
		{
sl@0
   365
		if (informat == FORMAT_PEM) 
sl@0
   366
			p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL, NULL);
sl@0
   367
		else if (informat == FORMAT_ASN1)
sl@0
   368
			p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
sl@0
   369
		else
sl@0
   370
			{
sl@0
   371
			BIO_printf(bio_err, "Bad format specified for key\n");
sl@0
   372
			return (1);
sl@0
   373
			}
sl@0
   374
		}
sl@0
   375
	else
sl@0
   376
		{
sl@0
   377
		if (informat == FORMAT_PEM) 
sl@0
   378
			p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
sl@0
   379
		else if (informat == FORMAT_ASN1)
sl@0
   380
			p8 = d2i_PKCS8_bio(in, NULL);
sl@0
   381
		else
sl@0
   382
			{
sl@0
   383
			BIO_printf(bio_err, "Bad format specified for key\n");
sl@0
   384
			return (1);
sl@0
   385
			}
sl@0
   386
sl@0
   387
		if (!p8)
sl@0
   388
			{
sl@0
   389
			BIO_printf (bio_err, "Error reading key\n");
sl@0
   390
			ERR_print_errors(bio_err);
sl@0
   391
			return (1);
sl@0
   392
			}
sl@0
   393
		if (passin)
sl@0
   394
			p8pass = passin;
sl@0
   395
		else
sl@0
   396
			{
sl@0
   397
			p8pass = pass;
sl@0
   398
			EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
sl@0
   399
			}
sl@0
   400
		p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
sl@0
   401
		X509_SIG_free(p8);
sl@0
   402
		}
sl@0
   403
sl@0
   404
	if (!p8inf)
sl@0
   405
		{
sl@0
   406
		BIO_printf(bio_err, "Error decrypting key\n");
sl@0
   407
		ERR_print_errors(bio_err);
sl@0
   408
		return (1);
sl@0
   409
		}
sl@0
   410
sl@0
   411
	if (!(pkey = EVP_PKCS82PKEY(p8inf)))
sl@0
   412
		{
sl@0
   413
		BIO_printf(bio_err, "Error converting key\n");
sl@0
   414
		ERR_print_errors(bio_err);
sl@0
   415
		return (1);
sl@0
   416
		}
sl@0
   417
	
sl@0
   418
	if (p8inf->broken)
sl@0
   419
		{
sl@0
   420
		BIO_printf(bio_err, "Warning: broken key encoding: ");
sl@0
   421
		switch (p8inf->broken)
sl@0
   422
			{
sl@0
   423
			case PKCS8_NO_OCTET:
sl@0
   424
			BIO_printf(bio_err, "No Octet String in PrivateKey\n");
sl@0
   425
			break;
sl@0
   426
sl@0
   427
			case PKCS8_EMBEDDED_PARAM:
sl@0
   428
			BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
sl@0
   429
			break;
sl@0
   430
sl@0
   431
			case PKCS8_NS_DB:
sl@0
   432
			BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
sl@0
   433
			break;
sl@0
   434
sl@0
   435
			default:
sl@0
   436
			BIO_printf(bio_err, "Unknown broken type\n");
sl@0
   437
			break;
sl@0
   438
		}
sl@0
   439
	}
sl@0
   440
	
sl@0
   441
	PKCS8_PRIV_KEY_INFO_free(p8inf);
sl@0
   442
	if (outformat == FORMAT_PEM) 
sl@0
   443
		PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
sl@0
   444
	else if (outformat == FORMAT_ASN1)
sl@0
   445
		i2d_PrivateKey_bio(out, pkey);
sl@0
   446
	else
sl@0
   447
		{
sl@0
   448
		BIO_printf(bio_err, "Bad format specified for key\n");
sl@0
   449
			return (1);
sl@0
   450
		}
sl@0
   451
sl@0
   452
	end:
sl@0
   453
	EVP_PKEY_free(pkey);
sl@0
   454
	BIO_free_all(out);
sl@0
   455
	BIO_free(in);
sl@0
   456
	if (passin)
sl@0
   457
		OPENSSL_free(passin);
sl@0
   458
	if (passout)
sl@0
   459
		OPENSSL_free(passout);
sl@0
   460
sl@0
   461
	return (0);
sl@0
   462
	}