Merge branch 'vendor/LIBRESSL'
[dragonfly.git] / crypto / libressl / crypto / pem / pem_info.c
1 /* $OpenBSD: pem_info.c,v 1.20 2015/02/10 09:52:35 miod Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <string.h>
61
62 #include <openssl/opensslconf.h>
63
64 #include <openssl/buffer.h>
65 #include <openssl/err.h>
66 #include <openssl/evp.h>
67 #include <openssl/objects.h>
68 #include <openssl/pem.h>
69 #include <openssl/x509.h>
70
71 #ifndef OPENSSL_NO_DSA
72 #include <openssl/dsa.h>
73 #endif
74 #ifndef OPENSSL_NO_RSA
75 #include <openssl/rsa.h>
76 #endif
77
78 STACK_OF(X509_INFO) *
79 PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
80     void *u)
81 {
82         BIO *b;
83         STACK_OF(X509_INFO) *ret;
84
85         if ((b = BIO_new(BIO_s_file())) == NULL) {
86                 PEMerr(PEM_F_PEM_X509_INFO_READ, ERR_R_BUF_LIB);
87                 return (0);
88         }
89         BIO_set_fp(b, fp, BIO_NOCLOSE);
90         ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
91         BIO_free(b);
92         return (ret);
93 }
94
95 STACK_OF(X509_INFO) *
96 PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
97     void *u)
98 {
99         X509_INFO *xi = NULL;
100         char *name = NULL, *header = NULL;
101         void *pp;
102         unsigned char *data = NULL;
103         const unsigned char *p;
104         long len, error = 0;
105         int ok = 0;
106         STACK_OF(X509_INFO) *ret = NULL;
107         unsigned int i, raw, ptype;
108         d2i_of_void *d2i = 0;
109
110         if (sk == NULL) {
111                 if ((ret = sk_X509_INFO_new_null()) == NULL) {
112                         PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,
113                             ERR_R_MALLOC_FAILURE);
114                         return 0;
115                 }
116         } else
117                 ret = sk;
118
119         if ((xi = X509_INFO_new()) == NULL)
120                 goto err;
121         for (;;) {
122                 raw = 0;
123                 ptype = 0;
124                 i = PEM_read_bio(bp, &name, &header, &data, &len);
125                 if (i == 0) {
126                         error = ERR_GET_REASON(ERR_peek_last_error());
127                         if (error == PEM_R_NO_START_LINE) {
128                                 ERR_clear_error();
129                                 break;
130                         }
131                         goto err;
132                 }
133 start:
134                 if ((strcmp(name, PEM_STRING_X509) == 0) ||
135                     (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
136                         d2i = (D2I_OF(void))d2i_X509;
137                         if (xi->x509 != NULL) {
138                                 if (!sk_X509_INFO_push(ret, xi))
139                                         goto err;
140                                 if ((xi = X509_INFO_new()) == NULL)
141                                         goto err;
142                                 goto start;
143                         }
144                         pp = &(xi->x509);
145                 } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
146                         d2i = (D2I_OF(void))d2i_X509_AUX;
147                         if (xi->x509 != NULL) {
148                                 if (!sk_X509_INFO_push(ret, xi))
149                                         goto err;
150                                 if ((xi = X509_INFO_new()) == NULL)
151                                         goto err;
152                                 goto start;
153                         }
154                         pp = &(xi->x509);
155                 } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
156                         d2i = (D2I_OF(void))d2i_X509_CRL;
157                         if (xi->crl != NULL) {
158                                 if (!sk_X509_INFO_push(ret, xi))
159                                         goto err;
160                                 if ((xi = X509_INFO_new()) == NULL)
161                                         goto err;
162                                 goto start;
163                         }
164                         pp = &(xi->crl);
165                 } else
166 #ifndef OPENSSL_NO_RSA
167                 if (strcmp(name, PEM_STRING_RSA) == 0) {
168                         d2i = (D2I_OF(void))d2i_RSAPrivateKey;
169                         if (xi->x_pkey != NULL) {
170                                 if (!sk_X509_INFO_push(ret, xi))
171                                         goto err;
172                                 if ((xi = X509_INFO_new()) == NULL)
173                                         goto err;
174                                 goto start;
175                         }
176
177                         xi->enc_data = NULL;
178                         xi->enc_len = 0;
179
180                         xi->x_pkey = X509_PKEY_new();
181                         if (xi->x_pkey == NULL)
182                                 goto err;
183                         ptype = EVP_PKEY_RSA;
184                         pp = &xi->x_pkey->dec_pkey;
185                         if (strlen(header) > 10) /* assume encrypted */
186                                 raw = 1;
187                 } else
188 #endif
189 #ifndef OPENSSL_NO_DSA
190                 if (strcmp(name, PEM_STRING_DSA) == 0) {
191                         d2i = (D2I_OF(void))d2i_DSAPrivateKey;
192                         if (xi->x_pkey != NULL) {
193                                 if (!sk_X509_INFO_push(ret, xi))
194                                         goto err;
195                                 if ((xi = X509_INFO_new()) == NULL)
196                                         goto err;
197                                 goto start;
198                         }
199
200                         xi->enc_data = NULL;
201                         xi->enc_len = 0;
202
203                         xi->x_pkey = X509_PKEY_new();
204                         if (xi->x_pkey == NULL)
205                                 goto err;
206                         ptype = EVP_PKEY_DSA;
207                         pp = &xi->x_pkey->dec_pkey;
208                         if (strlen(header) > 10) /* assume encrypted */
209                                 raw = 1;
210                 } else
211 #endif
212 #ifndef OPENSSL_NO_EC
213                 if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
214                         d2i = (D2I_OF(void))d2i_ECPrivateKey;
215                         if (xi->x_pkey != NULL) {
216                                 if (!sk_X509_INFO_push(ret, xi))
217                                         goto err;
218                                 if ((xi = X509_INFO_new()) == NULL)
219                                         goto err;
220                                 goto start;
221                         }
222
223                         xi->enc_data = NULL;
224                         xi->enc_len = 0;
225
226                         xi->x_pkey = X509_PKEY_new();
227                         if (xi->x_pkey == NULL)
228                                 goto err;
229                         ptype = EVP_PKEY_EC;
230                         pp = &xi->x_pkey->dec_pkey;
231                         if (strlen(header) > 10) /* assume encrypted */
232                                 raw = 1;
233                 } else
234 #endif
235                 {
236                         d2i = NULL;
237                         pp = NULL;
238                 }
239
240                 if (d2i != NULL) {
241                         if (!raw) {
242                                 EVP_CIPHER_INFO cipher;
243
244                                 if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
245                                         goto err;
246                                 if (!PEM_do_header(&cipher, data, &len, cb, u))
247                                         goto err;
248                                 p = data;
249                                 if (ptype) {
250                                         if (!d2i_PrivateKey(ptype, pp, &p,
251                                             len)) {
252                                                 PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,
253                                                     ERR_R_ASN1_LIB);
254                                                 goto err;
255                                         }
256                                 } else if (d2i(pp, &p, len) == NULL) {
257                                         PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,
258                                             ERR_R_ASN1_LIB);
259                                         goto err;
260                                 }
261                         } else { /* encrypted RSA data */
262                                 if (!PEM_get_EVP_CIPHER_INFO(header,
263                                     &xi->enc_cipher))
264                                         goto err;
265                                 xi->enc_data = (char *)data;
266                                 xi->enc_len = (int)len;
267                                 data = NULL;
268                         }
269                 } else {
270                         /* unknown */
271                 }
272                 free(name);
273                 free(header);
274                 free(data);
275                 name = NULL;
276                 header = NULL;
277                 data = NULL;
278         }
279
280         /* if the last one hasn't been pushed yet and there is anything
281          * in it then add it to the stack ...
282          */
283         if ((xi->x509 != NULL) || (xi->crl != NULL) ||
284             (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
285                 if (!sk_X509_INFO_push(ret, xi))
286                         goto err;
287                 xi = NULL;
288         }
289         ok = 1;
290
291 err:
292         if (xi != NULL)
293                 X509_INFO_free(xi);
294         if (!ok) {
295                 for (i = 0; ((int)i) < sk_X509_INFO_num(ret); i++) {
296                         xi = sk_X509_INFO_value(ret, i);
297                         X509_INFO_free(xi);
298                 }
299                 if (ret != sk)
300                         sk_X509_INFO_free(ret);
301                 ret = NULL;
302         }
303
304         free(name);
305         free(header);
306         free(data);
307         return (ret);
308 }
309
310
311 /* A TJH addition */
312 int
313 PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
314     unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
315 {
316         EVP_CIPHER_CTX ctx;
317         int i, ret = 0;
318         unsigned char *data = NULL;
319         const char *objstr = NULL;
320         char buf[PEM_BUFSIZE];
321         unsigned char *iv = NULL;
322
323         if (enc != NULL) {
324                 objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
325                 if (objstr == NULL) {
326                         PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO,
327                             PEM_R_UNSUPPORTED_CIPHER);
328                         goto err;
329                 }
330         }
331
332         /* now for the fun part ... if we have a private key then
333          * we have to be able to handle a not-yet-decrypted key
334          * being written out correctly ... if it is decrypted or
335          * it is non-encrypted then we use the base code
336          */
337         if (xi->x_pkey != NULL) {
338                 if ((xi->enc_data != NULL) && (xi->enc_len > 0) ) {
339                         if (enc == NULL) {
340                                 PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO,
341                                     PEM_R_CIPHER_IS_NULL);
342                                 goto err;
343                         }
344
345                         /* copy from weirdo names into more normal things */
346                         iv = xi->enc_cipher.iv;
347                         data = (unsigned char *)xi->enc_data;
348                         i = xi->enc_len;
349
350                         /* we take the encryption data from the
351                          * internal stuff rather than what the
352                          * user has passed us ... as we have to
353                          * match exactly for some strange reason
354                          */
355                         objstr = OBJ_nid2sn(
356                             EVP_CIPHER_nid(xi->enc_cipher.cipher));
357                         if (objstr == NULL) {
358                                 PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO,
359                                     PEM_R_UNSUPPORTED_CIPHER);
360                                 goto err;
361                         }
362
363                         /* create the right magic header stuff */
364                         if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 >
365                             sizeof buf) {
366                                 PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO,
367                                     ASN1_R_BUFFER_TOO_SMALL);
368                                 goto err;
369                         }
370                         buf[0] = '\0';
371                         PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
372                         PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
373
374                         /* use the normal code to write things out */
375                         i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
376                         if (i <= 0)
377                                 goto err;
378                 } else {
379                         /* Add DSA/DH */
380 #ifndef OPENSSL_NO_RSA
381                         /* normal optionally encrypted stuff */
382                         if (PEM_write_bio_RSAPrivateKey(bp,
383                             xi->x_pkey->dec_pkey->pkey.rsa,
384                             enc, kstr, klen, cb, u) <= 0)
385                                 goto err;
386 #endif
387                 }
388         }
389
390         /* if we have a certificate then write it out now */
391         if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
392                 goto err;
393
394         /* we are ignoring anything else that is loaded into the X509_INFO
395          * structure for the moment ... as I don't need it so I'm not
396          * coding it here and Eric can do it when this makes it into the
397          * base library --tjh
398          */
399
400         ret = 1;
401
402 err:
403         explicit_bzero((char *)&ctx, sizeof(ctx));
404         explicit_bzero(buf, PEM_BUFSIZE);
405         return (ret);
406 }