Fix running mingw dhparam test under wine
[openssl.git] / crypto / pem / pem_pk8.c
1 /*
2  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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/core_dispatch.h>
13 #include <openssl/buffer.h>
14 #include <openssl/objects.h>
15 #include <openssl/evp.h>
16 #include <openssl/x509.h>
17 #include <openssl/pkcs12.h>
18 #include <openssl/pem.h>
19 #include <openssl/encoder.h>
20
21 static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder,
22                       int nid, const EVP_CIPHER *enc,
23                       const char *kstr, int klen,
24                       pem_password_cb *cb, void *u,
25                       OSSL_LIB_CTX *libctx, const char *propq);
26
27 #ifndef OPENSSL_NO_STDIO
28 static int do_pk8pkey_fp(FILE *bp, const EVP_PKEY *x, int isder,
29                          int nid, const EVP_CIPHER *enc,
30                          const char *kstr, int klen,
31                          pem_password_cb *cb, void *u,
32                          OSSL_LIB_CTX *libctx, const char *propq);
33 #endif
34 /*
35  * These functions write a private key in PKCS#8 format: it is a "drop in"
36  * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
37  * is NULL then it uses the unencrypted private key form. The 'nid' versions
38  * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
39  */
40
41 int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, int nid,
42                                       const char *kstr, int klen,
43                                       pem_password_cb *cb, void *u)
44 {
45     return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u, NULL, NULL);
46 }
47
48 int PEM_write_bio_PKCS8PrivateKey(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
49                                   const char *kstr, int klen,
50                                   pem_password_cb *cb, void *u)
51 {
52     return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u, NULL, NULL);
53 }
54
55 int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc,
56                             const char *kstr, int klen,
57                             pem_password_cb *cb, void *u)
58 {
59     return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u, NULL, NULL);
60 }
61
62 int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, int nid,
63                                 const char *kstr, int klen,
64                                 pem_password_cb *cb, void *u)
65 {
66     return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u, NULL, NULL);
67 }
68
69 static int do_pk8pkey(BIO *bp, const EVP_PKEY *x, int isder, int nid,
70                       const EVP_CIPHER *enc, const char *kstr, int klen,
71                       pem_password_cb *cb, void *u,
72                       OSSL_LIB_CTX *libctx, const char *propq)
73 {
74     int ret = 0;
75     const char *outtype = isder ? "DER" : "PEM";
76     OSSL_ENCODER_CTX *ctx =
77         OSSL_ENCODER_CTX_new_by_EVP_PKEY(x, OSSL_KEYMGMT_SELECT_ALL,
78                                          outtype, "pkcs8", libctx, propq);
79
80     if (ctx == NULL)
81         return 0;
82
83     /*
84      * If no keystring or callback is set, OpenSSL traditionally uses the
85      * user's cb argument as a password string, or if that's NULL, it falls
86      * back on PEM_def_callback().
87      */
88     if (kstr == NULL && cb == NULL) {
89         if (u != NULL) {
90             kstr = u;
91             klen = strlen(u);
92         } else {
93             cb = PEM_def_callback;
94         }
95     }
96
97     if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0) {
98         ret = 1;
99         if (enc != NULL) {
100             ret = 0;
101             if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_name(enc), NULL)) {
102                 const unsigned char *ukstr = (const unsigned char *)kstr;
103
104                 /*
105                  * Try to pass the passphrase if one was given, or the
106                  * passphrase callback if one was given.  If none of them
107                  * are given and that's wrong, we rely on the _to_bio()
108                  * call to generate errors.
109                  */
110                 ret = 1;
111                 if (kstr != NULL
112                     && !OSSL_ENCODER_CTX_set_passphrase(ctx, ukstr, klen))
113                     ret = 0;
114                 else if (cb != NULL
115                          && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, cb, u))
116                     ret = 0;
117             }
118         }
119         ret = ret && OSSL_ENCODER_to_bio(ctx, bp);
120     } else {
121         X509_SIG *p8;
122         PKCS8_PRIV_KEY_INFO *p8inf;
123         char buf[PEM_BUFSIZE];
124
125         ret = 0;
126         if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) {
127             ERR_raise(ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
128             goto legacy_end;
129         }
130         if (enc || (nid != -1)) {
131             if (kstr == NULL) {
132                 klen = cb(buf, PEM_BUFSIZE, 1, u);
133                 if (klen <= 0) {
134                     ERR_raise(ERR_LIB_PEM, PEM_R_READ_KEY);
135                     goto legacy_end;
136                 }
137
138                 kstr = buf;
139             }
140             p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
141             if (kstr == buf)
142                 OPENSSL_cleanse(buf, klen);
143             if (p8 == NULL)
144                 goto legacy_end;
145             if (isder)
146                 ret = i2d_PKCS8_bio(bp, p8);
147             else
148                 ret = PEM_write_bio_PKCS8(bp, p8);
149             X509_SIG_free(p8);
150         } else {
151             if (isder)
152                 ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
153             else
154                 ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
155         }
156      legacy_end:
157         PKCS8_PRIV_KEY_INFO_free(p8inf);
158     }
159     OSSL_ENCODER_CTX_free(ctx);
160     return ret;
161 }
162
163 EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
164                                   void *u)
165 {
166     PKCS8_PRIV_KEY_INFO *p8inf = NULL;
167     X509_SIG *p8 = NULL;
168     int klen;
169     EVP_PKEY *ret;
170     char psbuf[PEM_BUFSIZE];
171
172     p8 = d2i_PKCS8_bio(bp, NULL);
173     if (p8 == NULL)
174         return NULL;
175     if (cb != NULL)
176         klen = cb(psbuf, PEM_BUFSIZE, 0, u);
177     else
178         klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
179     if (klen < 0) {
180         ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
181         X509_SIG_free(p8);
182         return NULL;
183     }
184     p8inf = PKCS8_decrypt(p8, psbuf, klen);
185     X509_SIG_free(p8);
186     OPENSSL_cleanse(psbuf, klen);
187     if (p8inf == NULL)
188         return NULL;
189     ret = EVP_PKCS82PKEY(p8inf);
190     PKCS8_PRIV_KEY_INFO_free(p8inf);
191     if (!ret)
192         return NULL;
193     if (x != NULL) {
194         EVP_PKEY_free(*x);
195         *x = ret;
196     }
197     return ret;
198 }
199
200 #ifndef OPENSSL_NO_STDIO
201
202 int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
203                            const char *kstr, int klen,
204                            pem_password_cb *cb, void *u)
205 {
206     return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u, NULL, NULL);
207 }
208
209 int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, int nid,
210                                const char *kstr, int klen,
211                                pem_password_cb *cb, void *u)
212 {
213     return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u, NULL, NULL);
214 }
215
216 int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, int nid,
217                                   const char *kstr, int klen,
218                                   pem_password_cb *cb, void *u)
219 {
220     return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u, NULL, NULL);
221 }
222
223 int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc,
224                               const char *kstr, int klen,
225                               pem_password_cb *cb, void *u)
226 {
227     return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u, NULL, NULL);
228 }
229
230 static int do_pk8pkey_fp(FILE *fp, const EVP_PKEY *x, int isder, int nid,
231                          const EVP_CIPHER *enc, const char *kstr, int klen,
232                          pem_password_cb *cb, void *u,
233                          OSSL_LIB_CTX *libctx, const char *propq)
234 {
235     BIO *bp;
236     int ret;
237
238     if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
239         ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
240         return 0;
241     }
242     ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u, libctx, propq);
243     BIO_free(bp);
244     return ret;
245 }
246
247 EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
248                                  void *u)
249 {
250     BIO *bp;
251     EVP_PKEY *ret;
252
253     if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
254         ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);
255         return NULL;
256     }
257     ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
258     BIO_free(bp);
259     return ret;
260 }
261
262 #endif
263
264 IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
265
266
267 IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
268                  PKCS8_PRIV_KEY_INFO)