[openssl-users] Differences in openssl 0.9.8 and 1.0.1x for private pem key file
Jaya Nageswar
jaya.nageswar at gmail.com
Mon Dec 22 10:50:36 UTC 2014
Dear openssl community,
In our application, we have been using openssl 0.9.8 and trying to move to
openssl 1.0.1x as 0.9.8 is going to be EOS by December 2015. We have a
sample application where we try to read a sample pem key file, create an
EVP_PKEY indirectly using PEM_read_bio_PrivateKey(BIO *bio, NULL, NULL,
NULL) defined in crypto/pem/pem_pkey.c. Once we have the EVP_PKEY, we try
to create pem key files encrypted using different ciphers like (RC2, RC4
etc.). As per the latest openssl (1.0.1x), the method
PEM_write_bio_PrivateKey defined in crypto/pem/pem_pkey.c gets called in
the call flow while writing the pem key to a file.
The output of the application is different for openssl 0.9.8 and 1.0.1x.
This may be due to the following observations.
1. The structure evp_pkey_st at evp.h for EVP_PKEY got additional members
(members const EVP_PKEY_ASN1_METHOD *ameth and ENGINE *engine) got added in
openssl 1.0.1x versions
2. The logic in PEM_read_bio_PrivateKey n crypto/pem/pem_pkey.c got changed
a little bit and the the data related new membebrs ameth for the structure
evp_pkey_st (EVP_PKEY) is getting populated in the else if ((slen =
pem_check_suffix(nm, "PRIVATE KEY")) > 0) condition.
3. A new method PEM_write_bio_PrivateKey got added(in 1.0.1x) instead of a
MACRO ( IMPLEMENT_PEM_write_cb(crypto/pem/pem_all in 0.9.8) which will
indirectly call PEM_ASN1_write_bio.
The new method PEM_write_bio_PrivateKey in openssl 1.0.1x calls this
PEM_ASN1_write_bio in the else condition. However the if condition of this
method has a different call and it is always getting satisfied and hence my
output is getting changed.
I am using the following private key pem file.
-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJBAJNw3CZ0Z15+zkvkigtY1vH75Ow0FIFS3li3sj3OQY5pwYWE/PlE
5FEZxogIi5SEtEY/ZXgy5nGiCAILq8p1ynUCAwEAAQJAeIy+c3KZUdm8MrEZbU2l
8RRTiAzM9zAaO892HLKXRyhTL4l3v+wKt7Y/Yd+q1VUHXLr8VXJ8r/Gjr6NCofBO
AQIhAMJTTxqkoomY9hWeHSy5Y9FMG5+qI2IroayqfyyoLIBJAiEAwjw9fk0f+Ntz
TvRR5K4HcpnQLf3XebaHt0tI/RVakM0CIFdjX497uhxmzUOrdzNFq73TnBiRSpg7
Rtl/UvGiL2EBAiBQPZah0La+ldoC6gfS0tocy9ImzdDwZSmX3TAf7WxmmQIgJRiG
wXMpWytUHRvxPD9scrNyCQ96q7x5w88+yWzXFtE=
-----END RSA PRIVATE KEY-----
I have highlighted the executing part of the code for the methods
PEM_read_bio_PrivateKey and PEM_write_bio_PrivateKey in the openssl 1.0.1x
version.
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb
*cb, void *u)
{
char *nm=NULL;
const unsigned char *p=NULL;
unsigned char *data=NULL;
long len;
int slen;
EVP_PKEY *ret=NULL;
if (!PEM_bytes_read_bio(&data, &len, &nm,
PEM_STRING_EVP_PKEY, bp, cb, u))
return NULL;
p = data;
if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
PKCS8_PRIV_KEY_INFO *p8inf;
p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p,
len);
if(!p8inf) goto p8err;
ret = EVP_PKCS82PKEY(p8inf);
if(x) {
if(*x)
EVP_PKEY_free((EVP_PKEY *)*x);
*x = ret;
}
PKCS8_PRIV_KEY_INFO_free(p8inf);
} else if (strcmp(nm,PEM_STRING_PKCS8) == 0) {
PKCS8_PRIV_KEY_INFO *p8inf;
X509_SIG *p8;
int klen;
char psbuf[PEM_BUFSIZE];
p8 = d2i_X509_SIG(NULL, &p, len);
if(!p8) goto p8err;
if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u);
else
klen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);
if (klen <= 0) {
PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,
PEM_R_BAD_PASSWORD_READ);
X509_SIG_free(p8);
goto err;
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
if(!p8inf) goto p8err;
ret = EVP_PKCS82PKEY(p8inf);
if(x) {
if(*x)
EVP_PKEY_free((EVP_PKEY *)*x);
*x = ret;
}
PKCS8_PRIV_KEY_INFO_free(p8inf);
* } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) >
0)*
* {*
* const EVP_PKEY_ASN1_METHOD *ameth;*
* ameth = EVP_PKEY_asn1_find_str(NULL, nm,
slen);*
* if (!ameth || !ameth->old_priv_decode)*
* goto p8err;*
*
ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);*
* }*
p8err:
if (ret == NULL)
PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY,ERR_R_ASN1_LIB);
err:
OPENSSL_free(nm);
OPENSSL_cleanse(data, len);
OPENSSL_free(data);
return(ret);
}
int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int
klen,
pem_password_cb *cb, void *u)
{
char pem_str[80];
* if (!x->ameth || x->ameth->priv_encode)*
* return PEM_write_bio_PKCS8PrivateKey(bp,
x, enc,*
*
(char *)kstr, klen,*
*
cb, u);*
BIO_snprintf(pem_str, 80, "%s PRIVATE KEY",
x->ameth->pem_str);
return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
pem_str,bp,x,enc,kstr,klen,cb,u);
}
I am expecting that the else part of the PEM_write_bio_PrivateKey should
be executed to get the output similar to the 0.9.8. However the if
condition is getting satisfied and it is not getting to the else condition.
I tried to explain the problem to the best of my abilities. However I can
provide more details about it if required.
I would like to know if there is any bug in the latest openssl (1.0.1x)
regarding the reading/writing the private pem key files.
I appreciate any assistance from the openssl experts on this problem. Thank
you in advance and hoping to get reply soon.
Regards,
-Jay.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.opensslfoundation.net/pipermail/openssl-users/attachments/20141222/3f3baa01/attachment-0001.html>
More information about the openssl-users
mailing list