summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>1999-06-10 19:32:52 +0200
committerDr. Stephen Henson <steve@openssl.org>1999-06-10 19:32:52 +0200
commitb7d135b353953bf40a58b49d145df5376a8af209 (patch)
tree13d52048866ecf20b4ab22366c467c0871a14ce1
parentAvoid warnings. (diff)
downloadopenssl-b7d135b353953bf40a58b49d145df5376a8af209.tar.xz
openssl-b7d135b353953bf40a58b49d145df5376a8af209.zip
Two new functions to write out PKCS#8 private keys. Also fixes for some of
the the PBE code and a new constant PKCS5_DEFAULT_ITER for the default iteration count if it is passed as zero.
-rw-r--r--CHANGES6
-rw-r--r--crypto/asn1/p5_pbe.c1
-rw-r--r--crypto/asn1/p5_pbev2.c1
-rw-r--r--crypto/evp/evp.h2
-rw-r--r--crypto/evp/p5_crpt.c2
-rw-r--r--crypto/pem/pem.h9
-rw-r--r--crypto/pem/pem_err.c3
-rw-r--r--crypto/pem/pem_info.c1
-rw-r--r--crypto/pem/pem_lib.c59
-rw-r--r--crypto/pkcs12/p12_crpt.c2
-rw-r--r--crypto/pkcs12/pkcs12.h2
-rwxr-xr-xutil/libeay.num2
12 files changed, 85 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 28e929cc28..95ad74f671 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
Changes between 0.9.3a and 0.9.4
+ *) Add a new pair of functions PEM_write_PKCS8PrivateKey() and
+ PEM_write_bio_PKCS8PrivateKey() that are equivalent to
+ PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more
+ secure PKCS#8 private key format with a high iteration count.
+ [Steve Henson]
+
*) Fix determination of Perl interpreter: A perl or perl5
_directory_ in $PATH was also accepted as the interpreter.
[Ralf S. Engelschall]
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
index 5145c6349e..30b9049a45 100644
--- a/crypto/asn1/p5_pbe.c
+++ b/crypto/asn1/p5_pbe.c
@@ -119,6 +119,7 @@ X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt,
ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE);
return NULL;
}
+ if(iter <= 0) iter = PKCS5_DEFAULT_ITER;
ASN1_INTEGER_set (pbe->iter, iter);
if (!saltlen) saltlen = PKCS5_SALT_LEN;
if (!(pbe->salt->data = Malloc (saltlen))) {
diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
index 10364a0561..0fc8df16d0 100644
--- a/crypto/asn1/p5_pbev2.c
+++ b/crypto/asn1/p5_pbev2.c
@@ -206,6 +206,7 @@ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
if (salt) memcpy (osalt->data, salt, saltlen);
else RAND_bytes (osalt->data, saltlen);
+ if(iter <= 0) iter = PKCS5_DEFAULT_ITER;
if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr;
/* Now include salt in kdf structure */
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index e7b55a5885..570fe27d39 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -110,6 +110,8 @@ extern "C" {
#define EVP_MAX_IV_LENGTH 8
#define PKCS5_SALT_LEN 8
+/* Default PKCS#5 iteration count */
+#define PKCS5_DEFAULT_ITER 2048
#ifndef NO_RSA
#include <openssl/rsa.h>
diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c
index 798cbe9b82..abf6af0435 100644
--- a/crypto/evp/p5_crpt.c
+++ b/crypto/evp/p5_crpt.c
@@ -100,7 +100,7 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
/* Extract useful info from parameter */
pbuf = param->value.sequence->data;
- if (!param || (param->type = V_ASN1_SEQUENCE) ||
+ if (!param || (param->type != V_ASN1_SEQUENCE) ||
!(pbe = d2i_PBEPARAM (NULL, &pbuf, param->value.sequence->length))) {
EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
return 0;
diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
index 71953241d0..6c7387b604 100644
--- a/crypto/pem/pem.h
+++ b/crypto/pem/pem.h
@@ -67,6 +67,8 @@ extern "C" {
#include <openssl/x509.h>
#include <openssl/pem2.h>
+#define PEM_BUFSIZE 1024
+
#define PEM_OBJ_UNDEF 0
#define PEM_OBJ_X509 1
#define PEM_OBJ_X509_REQ 2
@@ -499,6 +501,8 @@ int PEM_write_DSAPrivateKey(FILE *fp,DSA *x,const EVP_CIPHER *enc,
#endif
int PEM_write_PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
unsigned char *kstr,int klen, pem_password_cb *);
+int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
+ unsigned char *kstr,int klen, pem_password_cb *);
int PEM_write_PKCS7(FILE *fp,PKCS7 *x);
#ifndef NO_DH
int PEM_write_DHparams(FILE *fp,DH *x);
@@ -548,6 +552,8 @@ int PEM_write_bio_DSAPrivateKey(BIO *fp,DSA *x,const EVP_CIPHER *enc,
#endif
int PEM_write_bio_PrivateKey(BIO *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
unsigned char *kstr,int klen, pem_password_cb *);
+int PEM_write_bio_PKCS8PrivateKey(BIO *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
+ unsigned char *kstr,int klen, pem_password_cb *);
int PEM_write_bio_PKCS7(BIO *bp,PKCS7 *x);
#ifndef NO_DH
int PEM_write_bio_DHparams(BIO *bp,DH *x);
@@ -578,6 +584,7 @@ int PEM_write_bio_PKCS8_PRIV_KEY_INFO(BIO *bp,PKCS8_PRIV_KEY_INFO *x);
#define PEM_F_PEM_ASN1_WRITE 104
#define PEM_F_PEM_ASN1_WRITE_BIO 105
#define PEM_F_PEM_DO_HEADER 106
+#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118
#define PEM_F_PEM_GET_EVP_CIPHER_INFO 107
#define PEM_F_PEM_READ 108
#define PEM_F_PEM_READ_BIO 109
@@ -586,6 +593,7 @@ int PEM_write_bio_PKCS8_PRIV_KEY_INFO(BIO *bp,PKCS8_PRIV_KEY_INFO *x);
#define PEM_F_PEM_SIGNFINAL 112
#define PEM_F_PEM_WRITE 113
#define PEM_F_PEM_WRITE_BIO 114
+#define PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY 119
#define PEM_F_PEM_X509_INFO_READ 115
#define PEM_F_PEM_X509_INFO_READ_BIO 116
#define PEM_F_PEM_X509_INFO_WRITE_BIO 117
@@ -596,6 +604,7 @@ int PEM_write_bio_PKCS8_PRIV_KEY_INFO(BIO *bp,PKCS8_PRIV_KEY_INFO *x);
#define PEM_R_BAD_END_LINE 102
#define PEM_R_BAD_IV_CHARS 103
#define PEM_R_BAD_PASSWORD_READ 104
+#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
#define PEM_R_NOT_DEK_INFO 105
#define PEM_R_NOT_ENCRYPTED 106
#define PEM_R_NOT_PROC_TYPE 107
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index dce31c6252..fa70f60998 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -72,6 +72,7 @@ static ERR_STRING_DATA PEM_str_functs[]=
{ERR_PACK(0,PEM_F_PEM_ASN1_WRITE,0), "PEM_ASN1_write"},
{ERR_PACK(0,PEM_F_PEM_ASN1_WRITE_BIO,0), "PEM_ASN1_write_bio"},
{ERR_PACK(0,PEM_F_PEM_DO_HEADER,0), "PEM_do_header"},
+{ERR_PACK(0,PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY,0), "PEM_F_PEM_WRITE_PKCS8PRIVATEKEY"},
{ERR_PACK(0,PEM_F_PEM_GET_EVP_CIPHER_INFO,0), "PEM_get_EVP_CIPHER_INFO"},
{ERR_PACK(0,PEM_F_PEM_READ,0), "PEM_read"},
{ERR_PACK(0,PEM_F_PEM_READ_BIO,0), "PEM_read_bio"},
@@ -80,6 +81,7 @@ static ERR_STRING_DATA PEM_str_functs[]=
{ERR_PACK(0,PEM_F_PEM_SIGNFINAL,0), "PEM_SignFinal"},
{ERR_PACK(0,PEM_F_PEM_WRITE,0), "PEM_write"},
{ERR_PACK(0,PEM_F_PEM_WRITE_BIO,0), "PEM_write_bio"},
+{ERR_PACK(0,PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY,0), "PEM_write_bio_PKCS8PrivateKey"},
{ERR_PACK(0,PEM_F_PEM_X509_INFO_READ,0), "PEM_X509_INFO_read"},
{ERR_PACK(0,PEM_F_PEM_X509_INFO_READ_BIO,0), "PEM_X509_INFO_read_bio"},
{ERR_PACK(0,PEM_F_PEM_X509_INFO_WRITE_BIO,0), "PEM_X509_INFO_write_bio"},
@@ -93,6 +95,7 @@ static ERR_STRING_DATA PEM_str_reasons[]=
{PEM_R_BAD_END_LINE ,"bad end line"},
{PEM_R_BAD_IV_CHARS ,"bad iv chars"},
{PEM_R_BAD_PASSWORD_READ ,"bad password read"},
+{PEM_R_ERROR_CONVERTING_PRIVATE_KEY ,"error converting private key"},
{PEM_R_NOT_DEK_INFO ,"not dek info"},
{PEM_R_NOT_ENCRYPTED ,"not encrypted"},
{PEM_R_NOT_PROC_TYPE ,"not proc type"},
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index 0c2af93360..ec392ea39c 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -272,7 +272,6 @@ int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
int i,ret=0;
unsigned char *data=NULL;
const char *objstr=NULL;
-#define PEM_BUFSIZE 1024
char buf[PEM_BUFSIZE];
unsigned char *iv=NULL;
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index a8414566de..96221d869b 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -72,7 +72,6 @@
const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT;
#define MIN_LENGTH 4
-#define PEM_BUFSIZE 1024
static int def_callback(char *buf, int num, int w);
static int load_iv(unsigned char **fromp,unsigned char *to, int num);
@@ -742,3 +741,61 @@ err:
BUF_MEM_free(dataB);
return(0);
}
+
+/* This function writes a private key in PKCS#8 format: it is a "drop in"
+ * replacement for PEM_write_bio_PrivateKey(). As usual if 'enc' is NULL then
+ * it uses the unencrypted private key form. It uses PKCS#5 v2.0 password based
+ * encryption algorithms.
+ */
+
+int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen, pem_password_cb *cb)
+{
+ X509_SIG *p8;
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ char buf[PEM_BUFSIZE];
+ int ret;
+ if(!(p8inf = EVP_PKEY2PKCS8(x))) {
+ PEMerr(PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY,
+ PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+ return 0;
+ }
+ if(enc) {
+ if(!kstr) {
+ if(!cb) klen = def_callback(buf, PEM_BUFSIZE, 1);
+ else klen = cb(buf, PEM_BUFSIZE, 1);
+ if(klen <= 0) {
+ PEMerr(PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY,
+ PEM_R_READ_KEY);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 0;
+ }
+
+ kstr = buf;
+ }
+ p8 = PKCS8_encrypt(-1, enc, kstr, klen, NULL, 0, 0, p8inf);
+ if(kstr == (unsigned char *)buf) memset(buf, 0, klen);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ ret = PEM_write_bio_PKCS8(bp, p8);
+ X509_SIG_free(p8);
+ return ret;
+ } else {
+ ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+ }
+}
+
+int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen, pem_password_cb *cb)
+{
+ BIO *bp;
+ int ret;
+ if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+ PEMerr(PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY,ERR_R_BUF_LIB);
+ return(0);
+ }
+ ret = PEM_write_bio_PKCS8PrivateKey(bp, x, enc, kstr, klen, cb);
+ BIO_free(bp);
+ return ret;
+}
diff --git a/crypto/pkcs12/p12_crpt.c b/crypto/pkcs12/p12_crpt.c
index d94265403a..6de6f8128f 100644
--- a/crypto/pkcs12/p12_crpt.c
+++ b/crypto/pkcs12/p12_crpt.c
@@ -92,7 +92,7 @@ int PKCS12_PBE_keyivgen (EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
/* Extract useful info from parameter */
pbuf = param->value.sequence->data;
- if (!param || (param->type = V_ASN1_SEQUENCE) ||
+ if (!param || (param->type != V_ASN1_SEQUENCE) ||
!(pbe = d2i_PBEPARAM (NULL, &pbuf, param->value.sequence->length))) {
EVPerr(PKCS12_F_PKCS12_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
return 0;
diff --git a/crypto/pkcs12/pkcs12.h b/crypto/pkcs12/pkcs12.h
index 5f3b1148fa..4cfba5e6c6 100644
--- a/crypto/pkcs12/pkcs12.h
+++ b/crypto/pkcs12/pkcs12.h
@@ -72,7 +72,7 @@ extern "C" {
/* Default iteration count */
#ifndef PKCS12_DEFAULT_ITER
-#define PKCS12_DEFAULT_ITER 2048
+#define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER
#endif
#define PKCS12_MAC_KEY_LENGTH 20
diff --git a/util/libeay.num b/util/libeay.num
index a4907c1751..0ff1cd9982 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -1769,3 +1769,5 @@ BIO_s_bio 1793
PKCS5_pbe2_set 1794
PKCS5_PBKDF2_HMAC_SHA1 1795
PKCS5_v2_PBE_keyivgen 1796
+PEM_write_bio_PKCS8PrivateKey 1797
+PEM_write_PKCS8PrivateKey 1798