/src/openssl111/crypto/pem/pem_pk8.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include <stdio.h> |
11 | | #include "internal/cryptlib.h" |
12 | | #include <openssl/buffer.h> |
13 | | #include <openssl/objects.h> |
14 | | #include <openssl/evp.h> |
15 | | #include <openssl/x509.h> |
16 | | #include <openssl/pkcs12.h> |
17 | | #include <openssl/pem.h> |
18 | | |
19 | | static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, |
20 | | int nid, const EVP_CIPHER *enc, |
21 | | char *kstr, int klen, pem_password_cb *cb, void *u); |
22 | | |
23 | | #ifndef OPENSSL_NO_STDIO |
24 | | static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, |
25 | | int nid, const EVP_CIPHER *enc, |
26 | | char *kstr, int klen, pem_password_cb *cb, void *u); |
27 | | #endif |
28 | | /* |
29 | | * These functions write a private key in PKCS#8 format: it is a "drop in" |
30 | | * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' |
31 | | * is NULL then it uses the unencrypted private key form. The 'nid' versions |
32 | | * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. |
33 | | */ |
34 | | |
35 | | int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, |
36 | | char *kstr, int klen, |
37 | | pem_password_cb *cb, void *u) |
38 | 0 | { |
39 | 0 | return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); |
40 | 0 | } |
41 | | |
42 | | int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, |
43 | | char *kstr, int klen, |
44 | | pem_password_cb *cb, void *u) |
45 | 0 | { |
46 | 0 | return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); |
47 | 0 | } |
48 | | |
49 | | int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, |
50 | | char *kstr, int klen, |
51 | | pem_password_cb *cb, void *u) |
52 | 0 | { |
53 | 0 | return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); |
54 | 0 | } |
55 | | |
56 | | int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, |
57 | | char *kstr, int klen, |
58 | | pem_password_cb *cb, void *u) |
59 | 0 | { |
60 | 0 | return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); |
61 | 0 | } |
62 | | |
63 | | static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, |
64 | | const EVP_CIPHER *enc, char *kstr, int klen, |
65 | | pem_password_cb *cb, void *u) |
66 | 0 | { |
67 | 0 | X509_SIG *p8; |
68 | 0 | PKCS8_PRIV_KEY_INFO *p8inf; |
69 | 0 | char buf[PEM_BUFSIZE]; |
70 | 0 | int ret; |
71 | |
|
72 | 0 | if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) { |
73 | 0 | PEMerr(PEM_F_DO_PK8PKEY, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); |
74 | 0 | return 0; |
75 | 0 | } |
76 | 0 | if (enc || (nid != -1)) { |
77 | 0 | if (!kstr) { |
78 | 0 | if (!cb) |
79 | 0 | klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u); |
80 | 0 | else |
81 | 0 | klen = cb(buf, PEM_BUFSIZE, 1, u); |
82 | 0 | if (klen <= 0) { |
83 | 0 | PEMerr(PEM_F_DO_PK8PKEY, PEM_R_READ_KEY); |
84 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
85 | 0 | return 0; |
86 | 0 | } |
87 | | |
88 | 0 | kstr = buf; |
89 | 0 | } |
90 | 0 | p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); |
91 | 0 | if (kstr == buf) |
92 | 0 | OPENSSL_cleanse(buf, klen); |
93 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
94 | 0 | if (p8 == NULL) |
95 | 0 | return 0; |
96 | 0 | if (isder) |
97 | 0 | ret = i2d_PKCS8_bio(bp, p8); |
98 | 0 | else |
99 | 0 | ret = PEM_write_bio_PKCS8(bp, p8); |
100 | 0 | X509_SIG_free(p8); |
101 | 0 | return ret; |
102 | 0 | } else { |
103 | 0 | if (isder) |
104 | 0 | ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); |
105 | 0 | else |
106 | 0 | ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); |
107 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
108 | 0 | return ret; |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, |
113 | | void *u) |
114 | 0 | { |
115 | 0 | PKCS8_PRIV_KEY_INFO *p8inf = NULL; |
116 | 0 | X509_SIG *p8 = NULL; |
117 | 0 | int klen; |
118 | 0 | EVP_PKEY *ret; |
119 | 0 | char psbuf[PEM_BUFSIZE]; |
120 | 0 | p8 = d2i_PKCS8_bio(bp, NULL); |
121 | 0 | if (!p8) |
122 | 0 | return NULL; |
123 | 0 | if (cb) |
124 | 0 | klen = cb(psbuf, PEM_BUFSIZE, 0, u); |
125 | 0 | else |
126 | 0 | klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); |
127 | 0 | if (klen < 0) { |
128 | 0 | PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ); |
129 | 0 | X509_SIG_free(p8); |
130 | 0 | return NULL; |
131 | 0 | } |
132 | 0 | p8inf = PKCS8_decrypt(p8, psbuf, klen); |
133 | 0 | X509_SIG_free(p8); |
134 | 0 | OPENSSL_cleanse(psbuf, klen); |
135 | 0 | if (!p8inf) |
136 | 0 | return NULL; |
137 | 0 | ret = EVP_PKCS82PKEY(p8inf); |
138 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
139 | 0 | if (!ret) |
140 | 0 | return NULL; |
141 | 0 | if (x) { |
142 | 0 | EVP_PKEY_free(*x); |
143 | 0 | *x = ret; |
144 | 0 | } |
145 | 0 | return ret; |
146 | 0 | } |
147 | | |
148 | | #ifndef OPENSSL_NO_STDIO |
149 | | |
150 | | int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, |
151 | | char *kstr, int klen, pem_password_cb *cb, void *u) |
152 | 0 | { |
153 | 0 | return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); |
154 | 0 | } |
155 | | |
156 | | int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, |
157 | | char *kstr, int klen, |
158 | | pem_password_cb *cb, void *u) |
159 | 0 | { |
160 | 0 | return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); |
161 | 0 | } |
162 | | |
163 | | int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, |
164 | | char *kstr, int klen, |
165 | | pem_password_cb *cb, void *u) |
166 | 0 | { |
167 | 0 | return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); |
168 | 0 | } |
169 | | |
170 | | int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, |
171 | | char *kstr, int klen, pem_password_cb *cb, |
172 | | void *u) |
173 | 0 | { |
174 | 0 | return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); |
175 | 0 | } |
176 | | |
177 | | static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, |
178 | | const EVP_CIPHER *enc, char *kstr, int klen, |
179 | | pem_password_cb *cb, void *u) |
180 | 0 | { |
181 | 0 | BIO *bp; |
182 | 0 | int ret; |
183 | |
|
184 | 0 | if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
185 | 0 | PEMerr(PEM_F_DO_PK8PKEY_FP, ERR_R_BUF_LIB); |
186 | 0 | return 0; |
187 | 0 | } |
188 | 0 | ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); |
189 | 0 | BIO_free(bp); |
190 | 0 | return ret; |
191 | 0 | } |
192 | | |
193 | | EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, |
194 | | void *u) |
195 | 0 | { |
196 | 0 | BIO *bp; |
197 | 0 | EVP_PKEY *ret; |
198 | |
|
199 | 0 | if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
200 | 0 | PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP, ERR_R_BUF_LIB); |
201 | 0 | return NULL; |
202 | 0 | } |
203 | 0 | ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); |
204 | 0 | BIO_free(bp); |
205 | 0 | return ret; |
206 | 0 | } |
207 | | |
208 | | #endif |
209 | | |
210 | | IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) |
211 | | |
212 | | |
213 | | IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, |
214 | | PKCS8_PRIV_KEY_INFO) |