Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/pem/pem_info.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: pem_info.c,v 1.25 2021/12/12 21:30:14 tb 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
#include "evp_locl.h"
79
80
STACK_OF(X509_INFO) *
81
PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
82
    void *u)
83
0
{
84
0
  BIO *b;
85
0
  STACK_OF(X509_INFO) *ret;
86
87
0
  if ((b = BIO_new(BIO_s_file())) == NULL) {
88
0
    PEMerror(ERR_R_BUF_LIB);
89
0
    return (0);
90
0
  }
91
0
  BIO_set_fp(b, fp, BIO_NOCLOSE);
92
0
  ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
93
0
  BIO_free(b);
94
0
  return (ret);
95
0
}
96
97
STACK_OF(X509_INFO) *
98
PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
99
    void *u)
100
0
{
101
0
  X509_INFO *xi = NULL;
102
0
  char *name = NULL, *header = NULL;
103
0
  void *pp;
104
0
  unsigned char *data = NULL;
105
0
  const unsigned char *p;
106
0
  long len;
107
0
  int ok = 0;
108
0
  int num_in, ptype, raw;
109
0
  STACK_OF(X509_INFO) *ret = sk;
110
0
  d2i_of_void *d2i = NULL;
111
112
0
  if (ret == NULL) {
113
0
    if ((ret = sk_X509_INFO_new_null()) == NULL) {
114
0
      PEMerror(ERR_R_MALLOC_FAILURE);
115
0
      return NULL;
116
0
    }
117
0
  }
118
0
  num_in = sk_X509_INFO_num(ret);
119
120
0
  if ((xi = X509_INFO_new()) == NULL)
121
0
    goto err;
122
0
  for (;;) {
123
0
    raw = 0;
124
0
    ptype = 0;
125
0
    if (!PEM_read_bio(bp, &name, &header, &data, &len)) {
126
0
      if (ERR_GET_REASON(ERR_peek_last_error()) ==
127
0
          PEM_R_NO_START_LINE) {
128
0
        ERR_clear_error();
129
0
        break;
130
0
      }
131
0
      goto err;
132
0
    }
133
0
    if ((strcmp(name, PEM_STRING_X509) == 0) ||
134
0
        (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
135
0
      d2i = (D2I_OF(void))d2i_X509;
136
0
      if (xi->x509 != NULL) {
137
0
        if (!sk_X509_INFO_push(ret, xi))
138
0
          goto err;
139
0
        if ((xi = X509_INFO_new()) == NULL)
140
0
          goto err;
141
0
      }
142
0
      pp = &(xi->x509);
143
0
    } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
144
0
      d2i = (D2I_OF(void))d2i_X509_AUX;
145
0
      if (xi->x509 != NULL) {
146
0
        if (!sk_X509_INFO_push(ret, xi))
147
0
          goto err;
148
0
        if ((xi = X509_INFO_new()) == NULL)
149
0
          goto err;
150
0
      }
151
0
      pp = &(xi->x509);
152
0
    } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
153
0
      d2i = (D2I_OF(void))d2i_X509_CRL;
154
0
      if (xi->crl != NULL) {
155
0
        if (!sk_X509_INFO_push(ret, xi))
156
0
          goto err;
157
0
        if ((xi = X509_INFO_new()) == NULL)
158
0
          goto err;
159
0
      }
160
0
      pp = &(xi->crl);
161
0
    } else
162
0
#ifndef OPENSSL_NO_RSA
163
0
    if (strcmp(name, PEM_STRING_RSA) == 0) {
164
0
      d2i = (D2I_OF(void))d2i_RSAPrivateKey;
165
0
      if (xi->x_pkey != NULL) {
166
0
        if (!sk_X509_INFO_push(ret, xi))
167
0
          goto err;
168
0
        if ((xi = X509_INFO_new()) == NULL)
169
0
          goto err;
170
0
      }
171
0
      xi->enc_data = NULL;
172
0
      xi->enc_len = 0;
173
0
      xi->x_pkey = X509_PKEY_new();
174
0
      if (xi->x_pkey == NULL)
175
0
        goto err;
176
0
      ptype = EVP_PKEY_RSA;
177
0
      pp = &xi->x_pkey->dec_pkey;
178
0
      if (strlen(header) > 10) /* assume encrypted */
179
0
        raw = 1;
180
0
    } else
181
0
#endif
182
0
#ifndef OPENSSL_NO_DSA
183
0
    if (strcmp(name, PEM_STRING_DSA) == 0) {
184
0
      d2i = (D2I_OF(void))d2i_DSAPrivateKey;
185
0
      if (xi->x_pkey != NULL) {
186
0
        if (!sk_X509_INFO_push(ret, xi))
187
0
          goto err;
188
0
        if ((xi = X509_INFO_new()) == NULL)
189
0
          goto err;
190
0
      }
191
0
      xi->enc_data = NULL;
192
0
      xi->enc_len = 0;
193
0
      xi->x_pkey = X509_PKEY_new();
194
0
      if (xi->x_pkey == NULL)
195
0
        goto err;
196
0
      ptype = EVP_PKEY_DSA;
197
0
      pp = &xi->x_pkey->dec_pkey;
198
0
      if (strlen(header) > 10) /* assume encrypted */
199
0
        raw = 1;
200
0
    } else
201
0
#endif
202
0
#ifndef OPENSSL_NO_EC
203
0
    if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
204
0
      d2i = (D2I_OF(void))d2i_ECPrivateKey;
205
0
      if (xi->x_pkey != NULL) {
206
0
        if (!sk_X509_INFO_push(ret, xi))
207
0
          goto err;
208
0
        if ((xi = X509_INFO_new()) == NULL)
209
0
          goto err;
210
0
      }
211
0
      xi->enc_data = NULL;
212
0
      xi->enc_len = 0;
213
0
      xi->x_pkey = X509_PKEY_new();
214
0
      if (xi->x_pkey == NULL)
215
0
        goto err;
216
0
      ptype = EVP_PKEY_EC;
217
0
      pp = &xi->x_pkey->dec_pkey;
218
0
      if (strlen(header) > 10) /* assume encrypted */
219
0
        raw = 1;
220
0
    } else
221
0
#endif
222
0
    {
223
0
      d2i = NULL;
224
0
      pp = NULL;
225
0
    }
226
227
0
    if (d2i != NULL) {
228
0
      if (!raw) {
229
0
        EVP_CIPHER_INFO cipher;
230
231
0
        if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
232
0
          goto err;
233
0
        if (!PEM_do_header(&cipher, data, &len, cb, u))
234
0
          goto err;
235
0
        p = data;
236
0
        if (ptype) {
237
0
          if (!d2i_PrivateKey(ptype, pp, &p,
238
0
              len)) {
239
0
            PEMerror(ERR_R_ASN1_LIB);
240
0
            goto err;
241
0
          }
242
0
        } else if (d2i(pp, &p, len) == NULL) {
243
0
          PEMerror(ERR_R_ASN1_LIB);
244
0
          goto err;
245
0
        }
246
0
      } else { /* encrypted RSA data */
247
0
        if (!PEM_get_EVP_CIPHER_INFO(header,
248
0
            &xi->enc_cipher))
249
0
          goto err;
250
0
        xi->enc_data = (char *)data;
251
0
        xi->enc_len = (int)len;
252
0
        data = NULL;
253
0
      }
254
0
    } else {
255
      /* unknown */
256
0
    }
257
0
    free(name);
258
0
    free(header);
259
0
    free(data);
260
0
    name = NULL;
261
0
    header = NULL;
262
0
    data = NULL;
263
0
  }
264
265
  /* if the last one hasn't been pushed yet and there is anything
266
   * in it then add it to the stack ...
267
   */
268
0
  if ((xi->x509 != NULL) || (xi->crl != NULL) ||
269
0
      (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
270
0
    if (!sk_X509_INFO_push(ret, xi))
271
0
      goto err;
272
0
    xi = NULL;
273
0
  }
274
0
  ok = 1;
275
276
0
err:
277
0
  if (!ok) {
278
0
    while (sk_X509_INFO_num(ret) > num_in)
279
0
      X509_INFO_free(sk_X509_INFO_pop(ret));
280
0
    if (ret != sk)
281
0
      sk_X509_INFO_free(ret);
282
0
    ret = NULL;
283
0
  }
284
0
  X509_INFO_free(xi);
285
0
  free(name);
286
0
  free(header);
287
0
  free(data);
288
289
0
  return ret;
290
0
}
291
292
293
/* A TJH addition */
294
int
295
PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
296
    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
297
0
{
298
0
  EVP_CIPHER_CTX ctx;
299
0
  int i, ret = 0;
300
0
  unsigned char *data = NULL;
301
0
  const char *objstr = NULL;
302
0
  char buf[PEM_BUFSIZE];
303
0
  unsigned char *iv = NULL;
304
305
0
  if (enc != NULL) {
306
0
    objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
307
0
    if (objstr == NULL) {
308
0
      PEMerror(PEM_R_UNSUPPORTED_CIPHER);
309
0
      goto err;
310
0
    }
311
0
  }
312
313
  /* now for the fun part ... if we have a private key then
314
   * we have to be able to handle a not-yet-decrypted key
315
   * being written out correctly ... if it is decrypted or
316
   * it is non-encrypted then we use the base code
317
   */
318
0
  if (xi->x_pkey != NULL) {
319
0
    if ((xi->enc_data != NULL) && (xi->enc_len > 0) ) {
320
0
      if (enc == NULL) {
321
0
        PEMerror(PEM_R_CIPHER_IS_NULL);
322
0
        goto err;
323
0
      }
324
325
      /* copy from weirdo names into more normal things */
326
0
      iv = xi->enc_cipher.iv;
327
0
      data = (unsigned char *)xi->enc_data;
328
0
      i = xi->enc_len;
329
330
      /* we take the encryption data from the
331
       * internal stuff rather than what the
332
       * user has passed us ... as we have to
333
       * match exactly for some strange reason
334
       */
335
0
      objstr = OBJ_nid2sn(
336
0
          EVP_CIPHER_nid(xi->enc_cipher.cipher));
337
0
      if (objstr == NULL) {
338
0
        PEMerror(PEM_R_UNSUPPORTED_CIPHER);
339
0
        goto err;
340
0
      }
341
342
      /* create the right magic header stuff */
343
0
      if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 >
344
0
          sizeof buf) {
345
0
        PEMerror(ASN1_R_BUFFER_TOO_SMALL);
346
0
        goto err;
347
0
      }
348
0
      buf[0] = '\0';
349
0
      PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
350
0
      PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
351
352
      /* use the normal code to write things out */
353
0
      i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
354
0
      if (i <= 0)
355
0
        goto err;
356
0
    } else {
357
      /* Add DSA/DH */
358
0
#ifndef OPENSSL_NO_RSA
359
      /* normal optionally encrypted stuff */
360
0
      if (PEM_write_bio_RSAPrivateKey(bp,
361
0
          xi->x_pkey->dec_pkey->pkey.rsa,
362
0
          enc, kstr, klen, cb, u) <= 0)
363
0
        goto err;
364
0
#endif
365
0
    }
366
0
  }
367
368
  /* if we have a certificate then write it out now */
369
0
  if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
370
0
    goto err;
371
372
  /* we are ignoring anything else that is loaded into the X509_INFO
373
   * structure for the moment ... as I don't need it so I'm not
374
   * coding it here and Eric can do it when this makes it into the
375
   * base library --tjh
376
   */
377
378
0
  ret = 1;
379
380
0
err:
381
0
  explicit_bzero((char *)&ctx, sizeof(ctx));
382
0
  explicit_bzero(buf, PEM_BUFSIZE);
383
0
  return (ret);
384
0
}