Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
btwise
openssl
提交
a0156a92
O
openssl
项目概览
btwise
/
openssl
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
openssl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a0156a92
编写于
8月 31, 2005
作者:
D
Dr. Stephen Henson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Integrated support for PVK files.
上级
96998822
变更
9
显示空白变更内容
内联
并排
Showing
9 changed file
with
1059 addition
and
16 deletion
+1059
-16
CHANGES
CHANGES
+5
-0
apps/apps.c
apps/apps.c
+19
-5
apps/apps.h
apps/apps.h
+2
-0
apps/dsa.c
apps/dsa.c
+24
-9
apps/rsa.c
apps/rsa.c
+19
-0
crypto/pem/Makefile
crypto/pem/Makefile
+2
-2
crypto/pem/pem.h
crypto/pem/pem.h
+35
-0
crypto/pem/pem_err.c
crypto/pem/pem_err.c
+23
-0
crypto/pem/pvkfmt.c
crypto/pem/pvkfmt.c
+930
-0
未找到文件。
CHANGES
浏览文件 @
a0156a92
...
...
@@ -4,6 +4,11 @@
Changes between 0.9.8a and 0.9.9 [xx XXX xxxx]
*) Integrated support for PVK file format and some related formats such
as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support
these in the 'rsa' and 'dsa' utilities.
[Steve Henson]
*) Support for PKCS#1 RSAPublicKey format on rsa utility command line.
[Steve Henson]
...
...
apps/apps.c
浏览文件 @
a0156a92
...
...
@@ -239,11 +239,18 @@ int str2fmt(char *s)
else
if
((
*
s
==
'T'
)
||
(
*
s
==
't'
))
return
(
FORMAT_TEXT
);
else
if
((
*
s
==
'P'
)
||
(
*
s
==
'p'
))
{
if
(
s
[
1
]
==
'V'
||
s
[
1
]
==
'v'
)
return
FORMAT_PVK
;
else
return
(
FORMAT_PEM
);
}
else
if
((
*
s
==
'N'
)
||
(
*
s
==
'n'
))
return
(
FORMAT_NETSCAPE
);
else
if
((
*
s
==
'S'
)
||
(
*
s
==
's'
))
return
(
FORMAT_SMIME
);
else
if
((
*
s
==
'M'
)
||
(
*
s
==
'm'
))
return
(
FORMAT_MSBLOB
);
else
if
((
*
s
==
'1'
)
||
(
strcmp
(
s
,
"PKCS12"
)
==
0
)
||
(
strcmp
(
s
,
"pkcs12"
)
==
0
)
||
(
strcmp
(
s
,
"P12"
)
==
0
)
||
(
strcmp
(
s
,
"p12"
)
==
0
))
...
...
@@ -879,6 +886,11 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
&
pkey
,
NULL
,
NULL
))
goto
end
;
}
else
if
(
format
==
FORMAT_MSBLOB
)
pkey
=
b2i_PrivateKey_bio
(
key
);
else
if
(
format
==
FORMAT_PVK
)
pkey
=
b2i_PVK_bio
(
key
,
(
pem_password_cb
*
)
password_callback
,
&
cb_data
);
else
{
BIO_printf
(
err
,
"bad input format specified for key file
\n
"
);
...
...
@@ -979,6 +991,8 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
else
if
(
format
==
FORMAT_NETSCAPE
||
format
==
FORMAT_IISSGC
)
pkey
=
load_netscape_key
(
err
,
key
,
file
,
key_descrip
,
format
);
#endif
else
if
(
format
==
FORMAT_MSBLOB
)
pkey
=
b2i_PublicKey_bio
(
key
);
else
{
BIO_printf
(
err
,
"bad input format specified for key file
\n
"
);
...
...
apps/apps.h
浏览文件 @
a0156a92
...
...
@@ -333,6 +333,8 @@ void policies_print(BIO *out, X509_STORE_CTX *ctx);
* adding yet another param to load_*key() */
#define FORMAT_PEMRSA 9
/* PEM RSAPubicKey format */
#define FORMAT_ASN1RSA 10
/* DER RSAPubicKey format */
#define FORMAT_MSBLOB 11
/* MS Key blob format */
#define FORMAT_PVK 12
/* MS PVK file format */
#define EXT_COPY_NONE 0
#define EXT_COPY_ADD 1
...
...
apps/dsa.c
浏览文件 @
a0156a92
...
...
@@ -249,16 +249,22 @@ bad:
}
BIO_printf
(
bio_err
,
"read DSA key
\n
"
);
if
(
informat
==
FORMAT_ASN1
)
{
if
(
pubin
)
dsa
=
d2i_DSA_PUBKEY_bio
(
in
,
NULL
);
else
dsa
=
d2i_DSAPrivateKey_bio
(
in
,
NULL
);
}
else
if
(
informat
==
FORMAT_PEM
)
{
if
(
pubin
)
dsa
=
PEM_read_bio_DSA_PUBKEY
(
in
,
NULL
,
NULL
,
NULL
);
else
dsa
=
PEM_read_bio_DSAPrivateKey
(
in
,
NULL
,
NULL
,
passin
);
}
else
{
BIO_printf
(
bio_err
,
"bad input format specified for key
\n
"
);
goto
end
;
EVP_PKEY
*
pkey
;
if
(
pubin
)
pkey
=
load_pubkey
(
bio_err
,
infile
,
informat
,
1
,
passin
,
e
,
"Public Key"
);
else
pkey
=
load_key
(
bio_err
,
infile
,
informat
,
1
,
passin
,
e
,
"Private Key"
);
if
(
pkey
)
{
dsa
=
EVP_PKEY_get1_DSA
(
pkey
);
EVP_PKEY_free
(
pkey
);
}
}
if
(
dsa
==
NULL
)
{
...
...
@@ -311,6 +317,15 @@ bad:
i
=
PEM_write_bio_DSA_PUBKEY
(
out
,
dsa
);
else
i
=
PEM_write_bio_DSAPrivateKey
(
out
,
dsa
,
enc
,
NULL
,
0
,
NULL
,
passout
);
}
else
if
(
outformat
==
FORMAT_MSBLOB
)
{
EVP_PKEY
*
pk
;
pk
=
EVP_PKEY_new
();
EVP_PKEY_set1_DSA
(
pk
,
dsa
);
if
(
pubin
||
pubout
)
i
=
i2b_PublicKey_bio
(
out
,
pk
);
else
i
=
i2b_PrivateKey_bio
(
out
,
pk
);
EVP_PKEY_free
(
pk
);
}
else
{
BIO_printf
(
bio_err
,
"bad output format specified for outfile
\n
"
);
goto
end
;
...
...
apps/rsa.c
浏览文件 @
a0156a92
...
...
@@ -111,6 +111,8 @@ int MAIN(int argc, char **argv)
#endif
int
modulus
=
0
;
int
pvk_encr
=
2
;
apps_startup
();
if
(
bio_err
==
NULL
)
...
...
@@ -177,6 +179,12 @@ int MAIN(int argc, char **argv)
pubin
=
2
;
else
if
(
strcmp
(
*
argv
,
"-RSAPublicKey_out"
)
==
0
)
pubout
=
2
;
else
if
(
strcmp
(
*
argv
,
"-pvk-strong"
)
==
0
)
pvk_encr
=
2
;
else
if
(
strcmp
(
*
argv
,
"-pvk-weak"
)
==
0
)
pvk_encr
=
1
;
else
if
(
strcmp
(
*
argv
,
"-pvk-none"
)
==
0
)
pvk_encr
=
0
;
else
if
(
strcmp
(
*
argv
,
"-noout"
)
==
0
)
noout
=
1
;
else
if
(
strcmp
(
*
argv
,
"-text"
)
==
0
)
...
...
@@ -390,6 +398,17 @@ bad:
}
else
i
=
PEM_write_bio_RSAPrivateKey
(
out
,
rsa
,
enc
,
NULL
,
0
,
NULL
,
passout
);
}
else
if
(
outformat
==
FORMAT_MSBLOB
||
outformat
==
FORMAT_PVK
)
{
EVP_PKEY
*
pk
;
pk
=
EVP_PKEY_new
();
EVP_PKEY_set1_RSA
(
pk
,
rsa
);
if
(
outformat
==
FORMAT_PVK
)
i
=
i2b_PVK_bio
(
out
,
pk
,
pvk_encr
,
0
,
passout
);
else
if
(
pubin
||
pubout
)
i
=
i2b_PublicKey_bio
(
out
,
pk
);
else
i
=
i2b_PrivateKey_bio
(
out
,
pk
);
EVP_PKEY_free
(
pk
);
}
else
{
BIO_printf
(
bio_err
,
"bad output format specified for outfile
\n
"
);
goto
end
;
...
...
crypto/pem/Makefile
浏览文件 @
a0156a92
...
...
@@ -18,10 +18,10 @@ APPS=
LIB
=
$(TOP)
/libcrypto.a
LIBSRC
=
pem_sign.c pem_seal.c pem_info.c pem_lib.c pem_all.c pem_err.c
\
pem_x509.c pem_xaux.c pem_oth.c pem_pk8.c pem_pkey.c
pem_x509.c pem_xaux.c pem_oth.c pem_pk8.c pem_pkey.c
pvkfmt.c
LIBOBJ
=
pem_sign.o pem_seal.o pem_info.o pem_lib.o pem_all.o pem_err.o
\
pem_x509.o pem_xaux.o pem_oth.o pem_pk8.o pem_pkey.o
pem_x509.o pem_xaux.o pem_oth.o pem_pk8.o pem_pkey.o
pvkfmt.o
SRC
=
$(LIBSRC)
...
...
crypto/pem/pem.h
浏览文件 @
a0156a92
...
...
@@ -677,6 +677,18 @@ int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
#endif
/* SSLEAY_MACROS */
EVP_PKEY
*
b2i_PrivateKey
(
const
unsigned
char
**
in
,
long
length
);
EVP_PKEY
*
b2i_PublicKey
(
const
unsigned
char
**
in
,
long
length
);
EVP_PKEY
*
b2i_PrivateKey_bio
(
BIO
*
in
);
EVP_PKEY
*
b2i_PublicKey_bio
(
BIO
*
in
);
int
i2b_PrivateKey_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
);
int
i2b_PublicKey_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
);
EVP_PKEY
*
b2i_PVK_bio
(
BIO
*
in
,
pem_password_cb
*
cb
,
void
*
u
);
int
i2b_PVK_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
,
int
enclevel
,
pem_password_cb
*
cb
,
void
*
u
);
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
...
...
@@ -686,10 +698,22 @@ void ERR_load_PEM_strings(void);
/* Error codes for the PEM functions. */
/* Function codes. */
#define PEM_F_B2I_DSS 127
#define PEM_F_B2I_PVK_BIO 128
#define PEM_F_B2I_RSA 129
#define PEM_F_CHECK_BITLEN_DSA 130
#define PEM_F_CHECK_BITLEN_RSA 131
#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120
#define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121
#define PEM_F_DO_B2I 132
#define PEM_F_DO_B2I_BIO 133
#define PEM_F_DO_BLOB_HEADER 134
#define PEM_F_DO_PK8PKEY 126
#define PEM_F_DO_PK8PKEY_FP 125
#define PEM_F_DO_PVK_BODY 135
#define PEM_F_DO_PVK_HEADER 136
#define PEM_F_I2B_PVK 137
#define PEM_F_I2B_PVK_BIO 138
#define PEM_F_LOAD_IV 101
#define PEM_F_PEM_ASN1_READ 102
#define PEM_F_PEM_ASN1_READ_BIO 103
...
...
@@ -718,18 +742,29 @@ void ERR_load_PEM_strings(void);
#define PEM_R_BAD_DECRYPT 101
#define PEM_R_BAD_END_LINE 102
#define PEM_R_BAD_IV_CHARS 103
#define PEM_R_BAD_MAGIC_NUMBER 116
#define PEM_R_BAD_PASSWORD_READ 104
#define PEM_R_BAD_VERSION_NUMBER 117
#define PEM_R_BIO_WRITE_FAILURE 118
#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
#define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119
#define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120
#define PEM_R_INCONSISTENT_HEADER 121
#define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122
#define PEM_R_KEYBLOB_TOO_SHORT 123
#define PEM_R_NOT_DEK_INFO 105
#define PEM_R_NOT_ENCRYPTED 106
#define PEM_R_NOT_PROC_TYPE 107
#define PEM_R_NO_START_LINE 108
#define PEM_R_PROBLEMS_GETTING_PASSWORD 109
#define PEM_R_PUBLIC_KEY_NO_RSA 110
#define PEM_R_PVK_DATA_TOO_SHORT 124
#define PEM_R_PVK_TOO_SHORT 125
#define PEM_R_READ_KEY 111
#define PEM_R_SHORT_HEADER 112
#define PEM_R_UNSUPPORTED_CIPHER 113
#define PEM_R_UNSUPPORTED_ENCRYPTION 114
#define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126
#ifdef __cplusplus
}
...
...
crypto/pem/pem_err.c
浏览文件 @
a0156a92
...
...
@@ -70,10 +70,22 @@
static
ERR_STRING_DATA
PEM_str_functs
[]
=
{
{
ERR_FUNC
(
PEM_F_B2I_DSS
),
"B2I_DSS"
},
{
ERR_FUNC
(
PEM_F_B2I_PVK_BIO
),
"B2I_PVK_BIO"
},
{
ERR_FUNC
(
PEM_F_B2I_RSA
),
"B2I_RSA"
},
{
ERR_FUNC
(
PEM_F_CHECK_BITLEN_DSA
),
"CHECK_BITLEN_DSA"
},
{
ERR_FUNC
(
PEM_F_CHECK_BITLEN_RSA
),
"CHECK_BITLEN_RSA"
},
{
ERR_FUNC
(
PEM_F_D2I_PKCS8PRIVATEKEY_BIO
),
"d2i_PKCS8PrivateKey_bio"
},
{
ERR_FUNC
(
PEM_F_D2I_PKCS8PRIVATEKEY_FP
),
"d2i_PKCS8PrivateKey_fp"
},
{
ERR_FUNC
(
PEM_F_DO_B2I
),
"DO_B2I"
},
{
ERR_FUNC
(
PEM_F_DO_B2I_BIO
),
"DO_B2I_BIO"
},
{
ERR_FUNC
(
PEM_F_DO_BLOB_HEADER
),
"DO_BLOB_HEADER"
},
{
ERR_FUNC
(
PEM_F_DO_PK8PKEY
),
"DO_PK8PKEY"
},
{
ERR_FUNC
(
PEM_F_DO_PK8PKEY_FP
),
"DO_PK8PKEY_FP"
},
{
ERR_FUNC
(
PEM_F_DO_PVK_BODY
),
"DO_PVK_BODY"
},
{
ERR_FUNC
(
PEM_F_DO_PVK_HEADER
),
"DO_PVK_HEADER"
},
{
ERR_FUNC
(
PEM_F_I2B_PVK
),
"I2B_PVK"
},
{
ERR_FUNC
(
PEM_F_I2B_PVK_BIO
),
"I2B_PVK_BIO"
},
{
ERR_FUNC
(
PEM_F_LOAD_IV
),
"LOAD_IV"
},
{
ERR_FUNC
(
PEM_F_PEM_ASN1_READ
),
"PEM_ASN1_read"
},
{
ERR_FUNC
(
PEM_F_PEM_ASN1_READ_BIO
),
"PEM_ASN1_read_bio"
},
...
...
@@ -105,18 +117,29 @@ static ERR_STRING_DATA PEM_str_reasons[]=
{
ERR_REASON
(
PEM_R_BAD_DECRYPT
)
,
"bad decrypt"
},
{
ERR_REASON
(
PEM_R_BAD_END_LINE
)
,
"bad end line"
},
{
ERR_REASON
(
PEM_R_BAD_IV_CHARS
)
,
"bad iv chars"
},
{
ERR_REASON
(
PEM_R_BAD_MAGIC_NUMBER
)
,
"bad magic number"
},
{
ERR_REASON
(
PEM_R_BAD_PASSWORD_READ
)
,
"bad password read"
},
{
ERR_REASON
(
PEM_R_BAD_VERSION_NUMBER
)
,
"bad version number"
},
{
ERR_REASON
(
PEM_R_BIO_WRITE_FAILURE
)
,
"bio write failure"
},
{
ERR_REASON
(
PEM_R_ERROR_CONVERTING_PRIVATE_KEY
),
"error converting private key"
},
{
ERR_REASON
(
PEM_R_EXPECTING_PRIVATE_KEY_BLOB
),
"expecting private key blob"
},
{
ERR_REASON
(
PEM_R_EXPECTING_PUBLIC_KEY_BLOB
),
"expecting public key blob"
},
{
ERR_REASON
(
PEM_R_INCONSISTENT_HEADER
)
,
"inconsistent header"
},
{
ERR_REASON
(
PEM_R_KEYBLOB_HEADER_PARSE_ERROR
),
"keyblob header parse error"
},
{
ERR_REASON
(
PEM_R_KEYBLOB_TOO_SHORT
)
,
"keyblob too short"
},
{
ERR_REASON
(
PEM_R_NOT_DEK_INFO
)
,
"not dek info"
},
{
ERR_REASON
(
PEM_R_NOT_ENCRYPTED
)
,
"not encrypted"
},
{
ERR_REASON
(
PEM_R_NOT_PROC_TYPE
)
,
"not proc type"
},
{
ERR_REASON
(
PEM_R_NO_START_LINE
)
,
"no start line"
},
{
ERR_REASON
(
PEM_R_PROBLEMS_GETTING_PASSWORD
),
"problems getting password"
},
{
ERR_REASON
(
PEM_R_PUBLIC_KEY_NO_RSA
)
,
"public key no rsa"
},
{
ERR_REASON
(
PEM_R_PVK_DATA_TOO_SHORT
)
,
"pvk data too short"
},
{
ERR_REASON
(
PEM_R_PVK_TOO_SHORT
)
,
"pvk too short"
},
{
ERR_REASON
(
PEM_R_READ_KEY
)
,
"read key"
},
{
ERR_REASON
(
PEM_R_SHORT_HEADER
)
,
"short header"
},
{
ERR_REASON
(
PEM_R_UNSUPPORTED_CIPHER
)
,
"unsupported cipher"
},
{
ERR_REASON
(
PEM_R_UNSUPPORTED_ENCRYPTION
),
"unsupported encryption"
},
{
ERR_REASON
(
PEM_R_UNSUPPORTED_KEY_COMPONENTS
),
"unsupported key components"
},
{
0
,
NULL
}
};
...
...
crypto/pem/pvkfmt.c
0 → 100644
浏览文件 @
a0156a92
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 2005.
*/
/* ====================================================================
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB
* and PRIVATEKEYBLOB).
*/
#include "cryptlib.h"
#include <openssl/pem.h>
#include <openssl/rand.h>
/* Utility function: read a DWORD (4 byte unsigned integer) in little endian
* format
*/
static
unsigned
int
read_ledword
(
const
unsigned
char
**
in
)
{
const
unsigned
char
*
p
=
*
in
;
unsigned
int
ret
;
ret
=
*
p
++
;
ret
|=
(
*
p
++
<<
8
);
ret
|=
(
*
p
++
<<
16
);
ret
|=
(
*
p
++
<<
24
);
*
in
=
p
;
return
ret
;
}
/* Read a BIGNUM in little endian format. The docs say that this should take up
* bitlen/8 bytes.
*/
static
int
read_lebn
(
const
unsigned
char
**
in
,
unsigned
int
nbyte
,
BIGNUM
**
r
)
{
const
unsigned
char
*
p
;
unsigned
char
*
tmpbuf
,
*
q
;
unsigned
int
i
;
p
=
*
in
+
nbyte
-
1
;
tmpbuf
=
OPENSSL_malloc
(
nbyte
);
if
(
!
tmpbuf
)
return
0
;
q
=
tmpbuf
;
for
(
i
=
0
;
i
<
nbyte
;
i
++
)
*
q
++
=
*
p
--
;
*
r
=
BN_bin2bn
(
tmpbuf
,
nbyte
,
NULL
);
OPENSSL_free
(
tmpbuf
);
if
(
*
r
)
{
*
in
+=
nbyte
;
return
1
;
}
else
return
0
;
}
/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */
#define MS_PUBLICKEYBLOB 0x6
#define MS_PRIVATEKEYBLOB 0x7
#define MS_RSA1MAGIC 0x31415352L
#define MS_RSA2MAGIC 0x32415352L
#define MS_DSS1MAGIC 0x31535344L
#define MS_DSS2MAGIC 0x32535344L
#define MS_KEYALG_RSA_KEYX 0xa400
#define MS_KEYALG_DSS_SIGN 0x2200
#define MS_KEYTYPE_KEYX 0x1
#define MS_KEYTYPE_SIGN 0x2
/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
#define MS_PVKMAGIC 0xb0b5f11eL
/* Salt length for PVK files */
#define PVK_SALTLEN 0x10
static
EVP_PKEY
*
b2i_rsa
(
const
unsigned
char
**
in
,
unsigned
int
length
,
unsigned
int
bitlen
,
int
ispub
);
static
EVP_PKEY
*
b2i_dss
(
const
unsigned
char
**
in
,
unsigned
int
length
,
unsigned
int
bitlen
,
int
ispub
);
static
int
do_blob_header
(
const
unsigned
char
**
in
,
unsigned
int
length
,
unsigned
int
*
pmagic
,
unsigned
int
*
pbitlen
,
int
*
pisdss
,
int
*
pispub
)
{
const
unsigned
char
*
p
=
*
in
;
if
(
length
<
16
)
return
0
;
/* bType */
if
(
*
p
==
MS_PUBLICKEYBLOB
)
{
if
(
*
pispub
==
0
)
{
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_EXPECTING_PRIVATE_KEY_BLOB
);
return
0
;
}
*
pispub
=
1
;
}
else
if
(
*
p
==
MS_PRIVATEKEYBLOB
)
{
if
(
*
pispub
==
1
)
{
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_EXPECTING_PUBLIC_KEY_BLOB
);
return
0
;
}
*
pispub
=
0
;
}
else
return
0
;
p
++
;
/* Version */
if
(
*
p
++
!=
0x2
)
{
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_BAD_VERSION_NUMBER
);
return
0
;
}
/* Ignore reserved, aiKeyAlg */
p
+=
6
;
*
pmagic
=
read_ledword
(
&
p
);
*
pbitlen
=
read_ledword
(
&
p
);
*
pisdss
=
0
;
switch
(
*
pmagic
)
{
case
MS_DSS1MAGIC
:
*
pisdss
=
1
;
case
MS_RSA1MAGIC
:
if
(
*
pispub
==
0
)
{
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_EXPECTING_PRIVATE_KEY_BLOB
);
return
0
;
}
break
;
case
MS_DSS2MAGIC
:
*
pisdss
=
1
;
case
MS_RSA2MAGIC
:
if
(
*
pispub
==
1
)
{
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_EXPECTING_PUBLIC_KEY_BLOB
);
return
0
;
}
break
;
default:
PEMerr
(
PEM_F_DO_BLOB_HEADER
,
PEM_R_BAD_MAGIC_NUMBER
);
return
-
1
;
}
*
in
=
p
;
return
1
;
}
static
unsigned
int
blob_length
(
unsigned
bitlen
,
int
isdss
,
int
ispub
)
{
unsigned
int
nbyte
,
hnbyte
;
nbyte
=
(
bitlen
+
7
)
>>
3
;
hnbyte
=
(
bitlen
+
15
)
>>
4
;
if
(
isdss
)
{
/* Expected length: 20 for q + 3 components bitlen each + 24
* for seed structure.
*/
if
(
ispub
)
return
44
+
3
*
nbyte
;
/* Expected length: 20 for q, priv, 2 bitlen components + 24
* for seed structure.
*/
else
return
64
+
2
*
nbyte
;
}
else
{
/* Expected length: 4 for 'e' + 'n' */
if
(
ispub
)
return
4
+
nbyte
;
else
/* Expected length: 4 for 'e' and 7 other components.
* 2 components are bitlen size, 5 are bitlen/2
*/
return
4
+
2
*
nbyte
+
5
*
hnbyte
;
}
}
static
EVP_PKEY
*
do_b2i
(
const
unsigned
char
**
in
,
unsigned
int
length
,
int
ispub
)
{
const
unsigned
char
*
p
=
*
in
;
unsigned
int
bitlen
,
magic
;
int
isdss
;
if
(
do_blob_header
(
&
p
,
length
,
&
magic
,
&
bitlen
,
&
isdss
,
&
ispub
)
<=
0
)
{
PEMerr
(
PEM_F_DO_B2I
,
PEM_R_KEYBLOB_HEADER_PARSE_ERROR
);
return
NULL
;
}
length
-=
16
;
if
(
length
<
blob_length
(
bitlen
,
isdss
,
ispub
))
{
PEMerr
(
PEM_F_DO_B2I
,
PEM_R_KEYBLOB_TOO_SHORT
);
return
NULL
;
}
if
(
isdss
)
return
b2i_dss
(
&
p
,
length
,
bitlen
,
ispub
);
else
return
b2i_rsa
(
&
p
,
length
,
bitlen
,
ispub
);
}
static
EVP_PKEY
*
do_b2i_bio
(
BIO
*
in
,
int
ispub
)
{
const
unsigned
char
*
p
;
unsigned
char
hdr_buf
[
16
],
*
buf
=
NULL
;
unsigned
int
bitlen
,
magic
,
length
;
int
isdss
;
EVP_PKEY
*
ret
=
NULL
;
if
(
BIO_read
(
in
,
hdr_buf
,
16
)
!=
16
)
{
PEMerr
(
PEM_F_DO_B2I_BIO
,
PEM_R_KEYBLOB_TOO_SHORT
);
return
NULL
;
}
p
=
hdr_buf
;
if
(
do_blob_header
(
&
p
,
16
,
&
magic
,
&
bitlen
,
&
isdss
,
&
ispub
)
<=
0
)
return
NULL
;
length
=
blob_length
(
bitlen
,
isdss
,
ispub
);
buf
=
OPENSSL_malloc
(
length
);
if
(
!
buf
)
{
PEMerr
(
PEM_F_DO_B2I_BIO
,
ERR_R_MALLOC_FAILURE
);
goto
err
;
}
p
=
buf
;
if
(
BIO_read
(
in
,
buf
,
length
)
!=
(
int
)
length
)
{
PEMerr
(
PEM_F_DO_B2I_BIO
,
PEM_R_KEYBLOB_TOO_SHORT
);
goto
err
;
}
if
(
isdss
)
ret
=
b2i_dss
(
&
p
,
length
,
bitlen
,
ispub
);
else
ret
=
b2i_rsa
(
&
p
,
length
,
bitlen
,
ispub
);
err:
if
(
buf
)
OPENSSL_free
(
buf
);
return
ret
;
}
static
EVP_PKEY
*
b2i_dss
(
const
unsigned
char
**
in
,
unsigned
int
length
,
unsigned
int
bitlen
,
int
ispub
)
{
const
unsigned
char
*
p
=
*
in
;
EVP_PKEY
*
ret
=
NULL
;
DSA
*
dsa
=
NULL
;
BN_CTX
*
ctx
=
NULL
;
unsigned
int
nbyte
;
nbyte
=
(
bitlen
+
7
)
>>
3
;
dsa
=
DSA_new
();
ret
=
EVP_PKEY_new
();
if
(
!
dsa
||
!
ret
)
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
nbyte
,
&
dsa
->
p
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
20
,
&
dsa
->
q
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
nbyte
,
&
dsa
->
g
))
goto
memerr
;
if
(
ispub
)
{
if
(
!
read_lebn
(
&
p
,
nbyte
,
&
dsa
->
pub_key
))
goto
memerr
;
}
else
{
if
(
!
read_lebn
(
&
p
,
20
,
&
dsa
->
priv_key
))
goto
memerr
;
/* Calculate public key */
if
(
!
(
dsa
->
pub_key
=
BN_new
()))
goto
memerr
;
if
(
!
(
ctx
=
BN_CTX_new
()))
goto
memerr
;
if
(
!
BN_mod_exp
(
dsa
->
pub_key
,
dsa
->
g
,
dsa
->
priv_key
,
dsa
->
p
,
ctx
))
goto
memerr
;
BN_CTX_free
(
ctx
);
}
EVP_PKEY_set1_DSA
(
ret
,
dsa
);
DSA_free
(
dsa
);
*
in
=
p
;
return
ret
;
memerr:
PEMerr
(
PEM_F_B2I_DSS
,
ERR_R_MALLOC_FAILURE
);
if
(
dsa
)
DSA_free
(
dsa
);
if
(
ret
)
EVP_PKEY_free
(
ret
);
if
(
ctx
)
BN_CTX_free
(
ctx
);
return
NULL
;
}
static
EVP_PKEY
*
b2i_rsa
(
const
unsigned
char
**
in
,
unsigned
int
length
,
unsigned
int
bitlen
,
int
ispub
)
{
const
unsigned
char
*
p
=
*
in
;
EVP_PKEY
*
ret
=
NULL
;
RSA
*
rsa
=
NULL
;
unsigned
int
nbyte
,
hnbyte
;
nbyte
=
(
bitlen
+
7
)
>>
3
;
hnbyte
=
(
bitlen
+
15
)
>>
4
;
rsa
=
RSA_new
();
ret
=
EVP_PKEY_new
();
if
(
!
rsa
||
!
ret
)
goto
memerr
;
rsa
->
e
=
BN_new
();
if
(
!
rsa
->
e
)
goto
memerr
;
if
(
!
BN_set_word
(
rsa
->
e
,
read_ledword
(
&
p
)))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
nbyte
,
&
rsa
->
n
))
goto
memerr
;
if
(
!
ispub
)
{
if
(
!
read_lebn
(
&
p
,
hnbyte
,
&
rsa
->
p
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
hnbyte
,
&
rsa
->
q
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
hnbyte
,
&
rsa
->
dmp1
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
hnbyte
,
&
rsa
->
dmq1
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
hnbyte
,
&
rsa
->
iqmp
))
goto
memerr
;
if
(
!
read_lebn
(
&
p
,
nbyte
,
&
rsa
->
d
))
goto
memerr
;
}
EVP_PKEY_set1_RSA
(
ret
,
rsa
);
RSA_free
(
rsa
);
*
in
=
p
;
return
ret
;
memerr:
PEMerr
(
PEM_F_B2I_RSA
,
ERR_R_MALLOC_FAILURE
);
if
(
rsa
)
RSA_free
(
rsa
);
if
(
ret
)
EVP_PKEY_free
(
ret
);
return
NULL
;
}
EVP_PKEY
*
b2i_PrivateKey
(
const
unsigned
char
**
in
,
long
length
)
{
return
do_b2i
(
in
,
length
,
0
);
}
EVP_PKEY
*
b2i_PublicKey
(
const
unsigned
char
**
in
,
long
length
)
{
return
do_b2i
(
in
,
length
,
1
);
}
EVP_PKEY
*
b2i_PrivateKey_bio
(
BIO
*
in
)
{
return
do_b2i_bio
(
in
,
0
);
}
EVP_PKEY
*
b2i_PublicKey_bio
(
BIO
*
in
)
{
return
do_b2i_bio
(
in
,
1
);
}
static
void
write_ledword
(
unsigned
char
**
out
,
unsigned
int
dw
)
{
unsigned
char
*
p
=
*
out
;
*
p
++
=
dw
&
0xff
;
*
p
++
=
(
dw
>>
8
)
&
0xff
;
*
p
++
=
(
dw
>>
16
)
&
0xff
;
*
p
++
=
(
dw
>>
24
)
&
0xff
;
*
out
=
p
;
}
static
void
write_lebn
(
unsigned
char
**
out
,
const
BIGNUM
*
bn
,
int
len
)
{
int
nb
,
i
;
unsigned
char
*
p
=
*
out
,
*
q
,
c
;
nb
=
BN_num_bytes
(
bn
);
BN_bn2bin
(
bn
,
p
);
q
=
p
+
nb
-
1
;
/* In place byte order reversal */
for
(
i
=
0
;
i
<
nb
/
2
;
i
++
)
{
c
=
*
p
;
*
p
++
=
*
q
;
*
q
--
=
c
;
}
*
out
+=
nb
;
/* Pad with zeroes if we have to */
if
(
len
>
0
)
{
len
-=
nb
;
if
(
len
>
0
)
{
memset
(
*
out
,
0
,
len
);
*
out
+=
len
;
}
}
}
static
int
check_bitlen_rsa
(
RSA
*
rsa
,
int
ispub
,
unsigned
int
*
magic
);
static
int
check_bitlen_dsa
(
DSA
*
dsa
,
int
ispub
,
unsigned
int
*
magic
);
static
void
write_rsa
(
unsigned
char
**
out
,
RSA
*
rsa
,
int
ispub
);
static
void
write_dsa
(
unsigned
char
**
out
,
DSA
*
dsa
,
int
ispub
);
static
int
do_i2b
(
unsigned
char
**
out
,
EVP_PKEY
*
pk
,
int
ispub
)
{
unsigned
char
*
p
;
unsigned
int
bitlen
,
magic
,
keyalg
;
int
outlen
,
noinc
=
0
;
if
(
pk
->
type
==
EVP_PKEY_DSA
)
{
bitlen
=
check_bitlen_dsa
(
pk
->
pkey
.
dsa
,
ispub
,
&
magic
);
keyalg
=
MS_KEYALG_DSS_SIGN
;
}
else
if
(
pk
->
type
==
EVP_PKEY_RSA
)
{
bitlen
=
check_bitlen_rsa
(
pk
->
pkey
.
rsa
,
ispub
,
&
magic
);
keyalg
=
MS_KEYALG_RSA_KEYX
;
}
else
return
-
1
;
if
(
bitlen
==
0
)
return
-
1
;
outlen
=
16
+
blob_length
(
bitlen
,
keyalg
==
MS_KEYALG_DSS_SIGN
?
1
:
0
,
ispub
);
if
(
out
==
NULL
)
return
outlen
;
if
(
*
out
)
p
=
*
out
;
else
{
p
=
OPENSSL_malloc
(
outlen
);
if
(
!
p
)
return
-
1
;
*
out
=
p
;
noinc
=
1
;
}
if
(
ispub
)
*
p
++
=
MS_PUBLICKEYBLOB
;
else
*
p
++
=
MS_PRIVATEKEYBLOB
;
*
p
++
=
0x2
;
*
p
++
=
0
;
*
p
++
=
0
;
write_ledword
(
&
p
,
keyalg
);
write_ledword
(
&
p
,
magic
);
write_ledword
(
&
p
,
bitlen
);
if
(
keyalg
==
MS_KEYALG_DSS_SIGN
)
write_dsa
(
&
p
,
pk
->
pkey
.
dsa
,
ispub
);
else
write_rsa
(
&
p
,
pk
->
pkey
.
rsa
,
ispub
);
if
(
!
noinc
)
*
out
+=
outlen
;
return
outlen
;
}
static
int
do_i2b_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
,
int
ispub
)
{
unsigned
char
*
tmp
=
NULL
;
int
outlen
,
wrlen
;
outlen
=
do_i2b
(
&
tmp
,
pk
,
ispub
);
if
(
outlen
<
0
)
return
-
1
;
wrlen
=
BIO_write
(
out
,
tmp
,
outlen
);
OPENSSL_free
(
tmp
);
if
(
wrlen
==
outlen
)
return
outlen
;
return
-
1
;
}
static
int
check_bitlen_dsa
(
DSA
*
dsa
,
int
ispub
,
unsigned
int
*
pmagic
)
{
int
bitlen
;
bitlen
=
BN_num_bits
(
dsa
->
p
);
if
((
bitlen
&
7
)
||
(
BN_num_bits
(
dsa
->
q
)
!=
160
)
||
(
BN_num_bits
(
dsa
->
g
)
>
bitlen
))
goto
badkey
;
if
(
ispub
)
{
if
(
BN_num_bits
(
dsa
->
pub_key
)
>
bitlen
)
goto
badkey
;
*
pmagic
=
MS_DSS1MAGIC
;
}
else
{
if
(
BN_num_bits
(
dsa
->
priv_key
)
>
160
)
goto
badkey
;
*
pmagic
=
MS_DSS2MAGIC
;
}
return
bitlen
;
badkey:
PEMerr
(
PEM_F_CHECK_BITLEN_DSA
,
PEM_R_UNSUPPORTED_KEY_COMPONENTS
);
return
0
;
}
static
int
check_bitlen_rsa
(
RSA
*
rsa
,
int
ispub
,
unsigned
int
*
pmagic
)
{
int
nbyte
,
hnbyte
,
bitlen
;
if
(
BN_num_bits
(
rsa
->
e
)
>
32
)
goto
badkey
;
bitlen
=
BN_num_bits
(
rsa
->
n
);
nbyte
=
BN_num_bytes
(
rsa
->
n
);
hnbyte
=
(
BN_num_bits
(
rsa
->
n
)
+
15
)
>>
4
;
if
(
ispub
)
{
*
pmagic
=
MS_RSA1MAGIC
;
return
bitlen
;
}
else
{
*
pmagic
=
MS_RSA2MAGIC
;
/* For private key each component must fit within nbyte or
* hnbyte.
*/
if
(
BN_num_bytes
(
rsa
->
d
)
>
nbyte
)
goto
badkey
;
if
((
BN_num_bytes
(
rsa
->
iqmp
)
>
hnbyte
)
||
(
BN_num_bytes
(
rsa
->
p
)
>
hnbyte
)
||
(
BN_num_bytes
(
rsa
->
q
)
>
hnbyte
)
||
(
BN_num_bytes
(
rsa
->
dmp1
)
>
hnbyte
)
||
(
BN_num_bytes
(
rsa
->
dmq1
)
>
hnbyte
))
goto
badkey
;
}
return
bitlen
;
badkey:
PEMerr
(
PEM_F_CHECK_BITLEN_RSA
,
PEM_R_UNSUPPORTED_KEY_COMPONENTS
);
return
0
;
}
static
void
write_rsa
(
unsigned
char
**
out
,
RSA
*
rsa
,
int
ispub
)
{
int
nbyte
,
hnbyte
;
nbyte
=
BN_num_bytes
(
rsa
->
n
);
hnbyte
=
(
BN_num_bits
(
rsa
->
n
)
+
15
)
>>
4
;
write_lebn
(
out
,
rsa
->
e
,
4
);
write_lebn
(
out
,
rsa
->
n
,
-
1
);
if
(
ispub
)
return
;
write_lebn
(
out
,
rsa
->
p
,
hnbyte
);
write_lebn
(
out
,
rsa
->
q
,
hnbyte
);
write_lebn
(
out
,
rsa
->
dmp1
,
hnbyte
);
write_lebn
(
out
,
rsa
->
dmq1
,
hnbyte
);
write_lebn
(
out
,
rsa
->
iqmp
,
hnbyte
);
write_lebn
(
out
,
rsa
->
d
,
nbyte
);
}
static
void
write_dsa
(
unsigned
char
**
out
,
DSA
*
dsa
,
int
ispub
)
{
int
nbyte
;
nbyte
=
BN_num_bytes
(
dsa
->
p
);
write_lebn
(
out
,
dsa
->
p
,
nbyte
);
write_lebn
(
out
,
dsa
->
q
,
20
);
write_lebn
(
out
,
dsa
->
g
,
nbyte
);
if
(
ispub
)
write_lebn
(
out
,
dsa
->
pub_key
,
nbyte
);
else
write_lebn
(
out
,
dsa
->
priv_key
,
20
);
/* Set "invalid" for seed structure values */
memset
(
*
out
,
0xff
,
24
);
*
out
+=
24
;
return
;
}
int
i2b_PrivateKey_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
)
{
return
do_i2b_bio
(
out
,
pk
,
0
);
}
int
i2b_PublicKey_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
)
{
return
do_i2b_bio
(
out
,
pk
,
1
);
}
static
int
do_PVK_header
(
const
unsigned
char
**
in
,
unsigned
int
length
,
int
skip_magic
,
unsigned
int
*
psaltlen
,
unsigned
int
*
pkeylen
)
{
const
unsigned
char
*
p
=
*
in
;
unsigned
int
pvk_magic
,
keytype
,
is_encrypted
;
if
(
skip_magic
)
{
if
(
length
<
20
)
{
PEMerr
(
PEM_F_DO_PVK_HEADER
,
PEM_R_PVK_TOO_SHORT
);
return
0
;
}
length
-=
20
;
}
else
{
if
(
length
<
24
)
{
PEMerr
(
PEM_F_DO_PVK_HEADER
,
PEM_R_PVK_TOO_SHORT
);
return
0
;
}
length
-=
24
;
pvk_magic
=
read_ledword
(
&
p
);
if
(
pvk_magic
!=
MS_PVKMAGIC
)
{
PEMerr
(
PEM_F_DO_PVK_HEADER
,
PEM_R_BAD_MAGIC_NUMBER
);
return
0
;
}
}
/* Skip reserved */
p
+=
4
;
keytype
=
read_ledword
(
&
p
);
is_encrypted
=
read_ledword
(
&
p
);
*
psaltlen
=
read_ledword
(
&
p
);
*
pkeylen
=
read_ledword
(
&
p
);
if
(
is_encrypted
&&
!*
psaltlen
)
{
PEMerr
(
PEM_F_DO_PVK_HEADER
,
PEM_R_INCONSISTENT_HEADER
);
return
0
;
}
*
in
=
p
;
return
1
;
}
static
int
derive_pvk_key
(
unsigned
char
*
key
,
const
unsigned
char
*
salt
,
unsigned
int
saltlen
,
const
unsigned
char
*
pass
,
int
passlen
)
{
EVP_MD_CTX
mctx
;
EVP_MD_CTX_init
(
&
mctx
);
EVP_DigestInit_ex
(
&
mctx
,
EVP_sha1
(),
NULL
);
EVP_DigestUpdate
(
&
mctx
,
salt
,
saltlen
);
EVP_DigestUpdate
(
&
mctx
,
pass
,
passlen
);
EVP_DigestFinal_ex
(
&
mctx
,
key
,
NULL
);
EVP_MD_CTX_cleanup
(
&
mctx
);
return
1
;
}
static
EVP_PKEY
*
do_PVK_body
(
const
unsigned
char
**
in
,
unsigned
int
saltlen
,
unsigned
int
keylen
,
pem_password_cb
*
cb
,
void
*
u
)
{
EVP_PKEY
*
ret
=
NULL
;
const
unsigned
char
*
p
=
*
in
;
unsigned
int
magic
;
unsigned
char
*
enctmp
=
NULL
,
*
q
;
if
(
saltlen
)
{
char
psbuf
[
PEM_BUFSIZE
];
unsigned
char
keybuf
[
20
];
EVP_CIPHER_CTX
cctx
;
int
enctmplen
,
inlen
;
if
(
cb
)
inlen
=
cb
(
psbuf
,
PEM_BUFSIZE
,
0
,
u
);
else
inlen
=
PEM_def_callback
(
psbuf
,
PEM_BUFSIZE
,
0
,
u
);
if
(
inlen
<=
0
)
{
PEMerr
(
PEM_F_DO_PVK_BODY
,
PEM_R_BAD_PASSWORD_READ
);
return
NULL
;
}
enctmp
=
OPENSSL_malloc
(
keylen
+
8
);
if
(
!
enctmp
)
{
PEMerr
(
PEM_F_DO_PVK_BODY
,
ERR_R_MALLOC_FAILURE
);
return
NULL
;
}
if
(
!
derive_pvk_key
(
keybuf
,
p
,
saltlen
,
psbuf
,
inlen
))
return
NULL
;
p
+=
saltlen
;
/* Copy BLOBHEADER across, decrypt rest */
memcpy
(
enctmp
,
p
,
8
);
p
+=
8
;
inlen
=
keylen
-
8
;
q
=
enctmp
+
8
;
EVP_CIPHER_CTX_init
(
&
cctx
);
EVP_DecryptInit_ex
(
&
cctx
,
EVP_rc4
(),
NULL
,
keybuf
,
NULL
);
EVP_DecryptUpdate
(
&
cctx
,
q
,
&
enctmplen
,
p
,
inlen
);
EVP_DecryptFinal_ex
(
&
cctx
,
q
+
enctmplen
,
&
enctmplen
);
magic
=
read_ledword
((
const
unsigned
char
**
)
&
q
);
if
(
magic
!=
MS_RSA2MAGIC
&&
magic
!=
MS_DSS2MAGIC
)
{
q
=
enctmp
+
8
;
memset
(
keybuf
+
5
,
0
,
11
);
EVP_DecryptInit_ex
(
&
cctx
,
EVP_rc4
(),
NULL
,
keybuf
,
NULL
);
OPENSSL_cleanse
(
keybuf
,
20
);
EVP_DecryptUpdate
(
&
cctx
,
q
,
&
enctmplen
,
p
,
inlen
);
EVP_DecryptFinal_ex
(
&
cctx
,
q
+
enctmplen
,
&
enctmplen
);
magic
=
read_ledword
((
const
unsigned
char
**
)
&
q
);
if
(
magic
!=
MS_RSA2MAGIC
&&
magic
!=
MS_DSS2MAGIC
)
{
EVP_CIPHER_CTX_cleanup
(
&
cctx
);
PEMerr
(
PEM_F_DO_PVK_BODY
,
PEM_R_BAD_DECRYPT
);
goto
err
;
}
}
else
OPENSSL_cleanse
(
keybuf
,
20
);
EVP_CIPHER_CTX_cleanup
(
&
cctx
);
p
=
enctmp
;
}
ret
=
b2i_PrivateKey
(
&
p
,
keylen
);
err:
if
(
enctmp
&&
saltlen
)
OPENSSL_free
(
enctmp
);
return
ret
;
}
EVP_PKEY
*
b2i_PVK_bio
(
BIO
*
in
,
pem_password_cb
*
cb
,
void
*
u
)
{
unsigned
char
pvk_hdr
[
24
],
*
buf
=
NULL
;
const
unsigned
char
*
p
;
int
buflen
;
EVP_PKEY
*
ret
=
NULL
;
unsigned
int
saltlen
,
keylen
;
if
(
BIO_read
(
in
,
pvk_hdr
,
24
)
!=
24
)
{
PEMerr
(
PEM_F_B2I_PVK_BIO
,
PEM_R_PVK_DATA_TOO_SHORT
);
return
NULL
;
}
p
=
pvk_hdr
;
if
(
!
do_PVK_header
(
&
p
,
24
,
0
,
&
saltlen
,
&
keylen
))
return
0
;
buflen
=
(
int
)
keylen
+
saltlen
;
buf
=
OPENSSL_malloc
(
buflen
);
if
(
!
buf
)
{
PEMerr
(
PEM_F_B2I_PVK_BIO
,
ERR_R_MALLOC_FAILURE
);
return
0
;
}
p
=
buf
;
if
(
BIO_read
(
in
,
buf
,
buflen
)
!=
buflen
)
{
PEMerr
(
PEM_F_B2I_PVK_BIO
,
PEM_R_PVK_DATA_TOO_SHORT
);
goto
err
;
}
ret
=
do_PVK_body
(
&
p
,
saltlen
,
keylen
,
cb
,
u
);
err:
if
(
buf
)
{
OPENSSL_cleanse
(
buf
,
buflen
);
OPENSSL_free
(
buf
);
}
return
ret
;
}
static
int
i2b_PVK
(
unsigned
char
**
out
,
EVP_PKEY
*
pk
,
int
enclevel
,
pem_password_cb
*
cb
,
void
*
u
)
{
int
outlen
=
24
,
noinc
,
pklen
;
unsigned
char
*
p
,
*
salt
=
NULL
;
if
(
enclevel
)
outlen
+=
PVK_SALTLEN
;
pklen
=
do_i2b
(
NULL
,
pk
,
0
);
if
(
pklen
<
0
)
return
-
1
;
outlen
+=
pklen
;
if
(
!
out
)
return
outlen
;
if
(
*
out
)
{
p
=
*
out
;
noinc
=
0
;
}
else
{
p
=
OPENSSL_malloc
(
outlen
);
if
(
!
p
)
{
PEMerr
(
PEM_F_I2B_PVK
,
ERR_R_MALLOC_FAILURE
);
return
-
1
;
}
*
out
=
p
;
noinc
=
1
;
}
write_ledword
(
&
p
,
MS_PVKMAGIC
);
write_ledword
(
&
p
,
0
);
if
(
pk
->
type
==
EVP_PKEY_DSA
)
write_ledword
(
&
p
,
MS_KEYTYPE_SIGN
);
else
write_ledword
(
&
p
,
MS_KEYTYPE_KEYX
);
write_ledword
(
&
p
,
enclevel
?
1
:
0
);
write_ledword
(
&
p
,
enclevel
?
PVK_SALTLEN
:
0
);
write_ledword
(
&
p
,
pklen
);
if
(
enclevel
)
{
if
(
RAND_bytes
(
p
,
PVK_SALTLEN
)
<=
0
)
goto
error
;
salt
=
p
;
p
+=
PVK_SALTLEN
;
}
do_i2b
(
&
p
,
pk
,
0
);
if
(
enclevel
==
0
)
return
outlen
;
else
{
char
psbuf
[
PEM_BUFSIZE
];
unsigned
char
keybuf
[
20
];
EVP_CIPHER_CTX
cctx
;
int
enctmplen
,
inlen
;
if
(
cb
)
inlen
=
cb
(
psbuf
,
PEM_BUFSIZE
,
1
,
u
);
else
inlen
=
PEM_def_callback
(
psbuf
,
PEM_BUFSIZE
,
1
,
u
);
if
(
inlen
<=
0
)
{
PEMerr
(
PEM_F_I2B_PVK
,
PEM_R_BAD_PASSWORD_READ
);
goto
error
;
}
if
(
!
derive_pvk_key
(
keybuf
,
salt
,
PVK_SALTLEN
,
psbuf
,
inlen
))
goto
error
;
if
(
enclevel
==
1
)
memset
(
keybuf
+
5
,
0
,
11
);
p
=
salt
+
PVK_SALTLEN
+
8
;
EVP_CIPHER_CTX_init
(
&
cctx
);
EVP_EncryptInit_ex
(
&
cctx
,
EVP_rc4
(),
NULL
,
keybuf
,
NULL
);
OPENSSL_cleanse
(
keybuf
,
20
);
EVP_DecryptUpdate
(
&
cctx
,
p
,
&
enctmplen
,
p
,
pklen
-
8
);
EVP_DecryptFinal_ex
(
&
cctx
,
p
+
enctmplen
,
&
enctmplen
);
EVP_CIPHER_CTX_cleanup
(
&
cctx
);
}
return
outlen
;
error:
return
-
1
;
}
int
i2b_PVK_bio
(
BIO
*
out
,
EVP_PKEY
*
pk
,
int
enclevel
,
pem_password_cb
*
cb
,
void
*
u
)
{
unsigned
char
*
tmp
=
NULL
;
int
outlen
,
wrlen
;
outlen
=
i2b_PVK
(
&
tmp
,
pk
,
enclevel
,
cb
,
u
);
if
(
outlen
<
0
)
return
-
1
;
wrlen
=
BIO_write
(
out
,
tmp
,
outlen
);
OPENSSL_free
(
tmp
);
if
(
wrlen
==
outlen
)
{
PEMerr
(
PEM_F_I2B_PVK_BIO
,
PEM_R_BIO_WRITE_FAILURE
);
return
outlen
;
}
return
-
1
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录