pem_info.c
Go to the documentation of this file.
1 /* crypto/pem/pem_info.c */
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 <openssl/pem.h>
60 
61 #include <assert.h>
62 #include <stdio.h>
63 #include <string.h>
64 
65 #include <openssl/dsa.h>
66 #include <openssl/err.h>
67 #include <openssl/evp.h>
68 #include <openssl/mem.h>
69 #include <openssl/obj.h>
70 #include <openssl/rsa.h>
71 #include <openssl/x509.h>
72 
74  pem_password_cb *cb, void *u)
75 {
76  BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
77  if (b == NULL) {
79  return 0;
80  }
82  BIO_free(b);
83  return ret;
84 }
85 
90 };
91 
92 static enum parse_result_t parse_x509(X509_INFO *info, const uint8_t *data,
93  size_t len, int key_type)
94 {
95  if (info->x509 != NULL) {
96  return parse_new_entry;
97  }
98  info->x509 = d2i_X509(NULL, &data, len);
99  return info->x509 != NULL ? parse_ok : parse_error;
100 }
101 
103  size_t len, int key_type)
104 {
105  if (info->x509 != NULL) {
106  return parse_new_entry;
107  }
108  info->x509 = d2i_X509_AUX(NULL, &data, len);
109  return info->x509 != NULL ? parse_ok : parse_error;
110 }
111 
112 static enum parse_result_t parse_crl(X509_INFO *info, const uint8_t *data,
113  size_t len, int key_type)
114 {
115  if (info->crl != NULL) {
116  return parse_new_entry;
117  }
118  info->crl = d2i_X509_CRL(NULL, &data, len);
119  return info->crl != NULL ? parse_ok : parse_error;
120 }
121 
122 static enum parse_result_t parse_key(X509_INFO *info, const uint8_t *data,
123  size_t len, int key_type)
124 {
125  if (info->x_pkey != NULL) {
126  return parse_new_entry;
127  }
128  info->x_pkey = X509_PKEY_new();
129  if (info->x_pkey == NULL) {
130  return parse_error;
131  }
132  info->x_pkey->dec_pkey = d2i_PrivateKey(key_type, NULL, &data, len);
133  return info->x_pkey->dec_pkey != NULL ? parse_ok : parse_error;
134 }
135 
137  pem_password_cb *cb, void *u)
138 {
139  X509_INFO *info = NULL;
140  char *name = NULL, *header = NULL;
141  unsigned char *data = NULL;
142  long len;
143  int ok = 0;
144  STACK_OF(X509_INFO) *ret = NULL;
145 
146  if (sk == NULL) {
147  ret = sk_X509_INFO_new_null();
148  if (ret == NULL) {
150  return NULL;
151  }
152  } else {
153  ret = sk;
154  }
155  size_t orig_num = sk_X509_INFO_num(ret);
156 
157  info = X509_INFO_new();
158  if (info == NULL) {
159  goto err;
160  }
161 
162  for (;;) {
163  if (!PEM_read_bio(bp, &name, &header, &data, &len)) {
165  if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
167  ERR_clear_error();
168  break;
169  }
170  goto err;
171  }
172 
173  enum parse_result_t (*parse_function)(X509_INFO *, const uint8_t *,
174  size_t, int) = NULL;
175  int key_type = EVP_PKEY_NONE;
176  if (strcmp(name, PEM_STRING_X509) == 0 ||
177  strcmp(name, PEM_STRING_X509_OLD) == 0) {
178  parse_function = parse_x509;
179  } else if (strcmp(name, PEM_STRING_X509_TRUSTED) == 0) {
180  parse_function = parse_x509_aux;
181  } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
182  parse_function = parse_crl;
183  } else if (strcmp(name, PEM_STRING_RSA) == 0) {
184  parse_function = parse_key;
186  } else if (strcmp(name, PEM_STRING_DSA) == 0) {
187  parse_function = parse_key;
189  } else if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
190  parse_function = parse_key;
192  }
193 
194  /* If a private key has a header, assume it is encrypted. */
195  if (key_type != EVP_PKEY_NONE && strlen(header) > 10) {
196  if (info->x_pkey != NULL) {
197  if (!sk_X509_INFO_push(ret, info)) {
198  goto err;
199  }
200  info = X509_INFO_new();
201  if (info == NULL) {
202  goto err;
203  }
204  }
205  /* Historically, raw entries pushed an empty key. */
206  info->x_pkey = X509_PKEY_new();
207  if (info->x_pkey == NULL ||
209  goto err;
210  }
211  info->enc_data = (char *)data;
212  info->enc_len = (int)len;
213  data = NULL;
214  } else if (parse_function != NULL) {
215  EVP_CIPHER_INFO cipher;
216  if (!PEM_get_EVP_CIPHER_INFO(header, &cipher) ||
217  !PEM_do_header(&cipher, data, &len, cb, u)) {
218  goto err;
219  }
220  enum parse_result_t result =
221  parse_function(info, data, len, key_type);
222  if (result == parse_new_entry) {
223  if (!sk_X509_INFO_push(ret, info)) {
224  goto err;
225  }
226  info = X509_INFO_new();
227  if (info == NULL) {
228  goto err;
229  }
230  result = parse_function(info, data, len, key_type);
231  }
232  if (result != parse_ok) {
234  goto err;
235  }
236  }
240  name = NULL;
241  header = NULL;
242  data = NULL;
243  }
244 
245  /* Push the last entry on the stack if not empty. */
246  if (info->x509 != NULL || info->crl != NULL ||
247  info->x_pkey != NULL || info->enc_data != NULL) {
248  if (!sk_X509_INFO_push(ret, info)) {
249  goto err;
250  }
251  info = NULL;
252  }
253 
254  ok = 1;
255 
256  err:
257  X509_INFO_free(info);
258  if (!ok) {
259  while (sk_X509_INFO_num(ret) > orig_num) {
260  X509_INFO_free(sk_X509_INFO_pop(ret));
261  }
262  if (ret != sk) {
263  sk_X509_INFO_free(ret);
264  }
265  ret = NULL;
266  }
267 
271  return ret;
272 }
273 
274 /* A TJH addition */
276  unsigned char *kstr, int klen,
277  pem_password_cb *cb, void *u)
278 {
279  int i, ret = 0;
280  unsigned char *data = NULL;
281  const char *objstr = NULL;
282  char buf[PEM_BUFSIZE];
283  unsigned char *iv = NULL;
284  unsigned iv_len = 0;
285 
286  if (enc != NULL) {
287  iv_len = EVP_CIPHER_iv_length(enc);
288  objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
289  if (objstr == NULL) {
291  goto err;
292  }
293  }
294 
295  /*
296  * now for the fun part ... if we have a private key then we have to be
297  * able to handle a not-yet-decrypted key being written out correctly ...
298  * if it is decrypted or it is non-encrypted then we use the base code
299  */
300  if (xi->x_pkey != NULL) {
301  if ((xi->enc_data != NULL) && (xi->enc_len > 0)) {
302  if (enc == NULL) {
304  goto err;
305  }
306 
307  /* copy from weirdo names into more normal things */
308  iv = xi->enc_cipher.iv;
309  data = (unsigned char *)xi->enc_data;
310  i = xi->enc_len;
311 
312  /*
313  * we take the encryption data from the internal stuff rather
314  * than what the user has passed us ... as we have to match
315  * exactly for some strange reason
316  */
318  if (objstr == NULL) {
320  goto err;
321  }
322 
323  /* create the right magic header stuff */
324  assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
325  buf[0] = '\0';
327  PEM_dek_info(buf, objstr, iv_len, (char *)iv);
328 
329  /* use the normal code to write things out */
331  if (i <= 0)
332  goto err;
333  } else {
334  /* Add DSA/DH */
335  /* normal optionally encrypted stuff */
337  xi->x_pkey->dec_pkey->pkey.rsa,
338  enc, kstr, klen, cb, u) <= 0)
339  goto err;
340  }
341  }
342 
343  /* if we have a certificate then write it out now */
344  if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
345  goto err;
346 
347  /*
348  * we are ignoring anything else that is loaded into the X509_INFO
349  * structure for the moment ... as I don't need it so I'm not coding it
350  * here and Eric can do it when this makes it into the base library --tjh
351  */
352 
353  ret = 1;
354 
355 err:
357  return ret;
358 }
evp_cipher_info_st
Definition: cipher.h:580
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
X509_info_st::x509
X509 * x509
Definition: x509.h:288
BIO_new_fp
#define BIO_new_fp
Definition: boringssl_prefix_symbols.h:819
EVP_PKEY_EC
#define EVP_PKEY_EC
Definition: evp.h:178
parse_ok
@ parse_ok
Definition: pem_info.c:87
OPENSSL_cleanse
#define OPENSSL_cleanse
Definition: boringssl_prefix_symbols.h:1864
PEM_BUFSIZE
#define PEM_BUFSIZE
Definition: pem.h:78
bio_st
Definition: bio.h:822
kstr
X509 X509_REQ PKCS7 PKCS8_PRIV_KEY_INFO RSA DSA DSA EC_KEY EVP_PKEY EVP_PKEY int char * kstr
Definition: pem.h:425
evp.h
evp_pkey_st::rsa
RSA * rsa
Definition: evp.h:1055
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
EVP_CIPHER_nid
#define EVP_CIPHER_nid
Definition: boringssl_prefix_symbols.h:1488
PEM_write_bio_RSAPrivateKey
#define PEM_write_bio_RSAPrivateKey
Definition: boringssl_prefix_symbols.h:1995
string.h
X509_info_st::enc_cipher
EVP_CIPHER_INFO enc_cipher
Definition: x509.h:292
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
parse_new_entry
@ parse_new_entry
Definition: pem_info.c:89
error
grpc_error_handle error
Definition: retry_filter.cc:499
error_ref_leak.err
err
Definition: error_ref_leak.py:35
EVP_CIPHER_iv_length
#define EVP_CIPHER_iv_length
Definition: boringssl_prefix_symbols.h:1485
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
PEM_proc_type
#define PEM_proc_type
Definition: boringssl_prefix_symbols.h:1920
pem.h
EVP_PKEY_RSA
#define EVP_PKEY_RSA
Definition: evp.h:175
setup.name
name
Definition: setup.py:542
PEM_R_NO_START_LINE
#define PEM_R_NO_START_LINE
Definition: pem.h:477
d2i_X509_CRL
#define d2i_X509_CRL
Definition: boringssl_prefix_symbols.h:3038
PEM_read_bio
#define PEM_read_bio
Definition: boringssl_prefix_symbols.h:1940
pem_password_cb
int pem_password_cb(char *buf, int size, int rwflag, void *userdata)
Definition: pem.h:313
PEM_do_header
#define PEM_do_header
Definition: boringssl_prefix_symbols.h:1918
PEM_get_EVP_CIPHER_INFO
#define PEM_get_EVP_CIPHER_INFO
Definition: boringssl_prefix_symbols.h:1919
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
PEM_STRING_DSA
#define PEM_STRING_DSA
Definition: pem.h:91
PEM_STRING_X509
#define PEM_STRING_X509
Definition: pem.h:81
PEM_STRING_X509_TRUSTED
#define PEM_STRING_X509_TRUSTED
Definition: pem.h:83
private_key_st::dec_pkey
EVP_PKEY * dec_pkey
Definition: x509.h:276
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
EVP_PKEY_DSA
#define EVP_PKEY_DSA
Definition: evp.h:177
PEM_X509_INFO_read
#define PEM_X509_INFO_read
Definition: boringssl_prefix_symbols.h:1912
evp_cipher_st
Definition: cipher.h:585
EVP_PKEY_NONE
#define EVP_PKEY_NONE
Definition: evp.h:174
PEM_R_UNSUPPORTED_CIPHER
#define PEM_R_UNSUPPORTED_CIPHER
Definition: pem.h:480
ERR_GET_REASON
#define ERR_GET_REASON(packed_error)
Definition: err.h:171
xds_interop_client.int
int
Definition: xds_interop_client.py:113
parse_result_t
parse_result_t
Definition: pem_info.c:86
X509_info_st::enc_len
int enc_len
Definition: x509.h:293
parse_crl
static enum parse_result_t parse_crl(X509_INFO *info, const uint8_t *data, size_t len, int key_type)
Definition: pem_info.c:112
X509_INFO_new
#define X509_INFO_new
Definition: boringssl_prefix_symbols.h:2346
PEM_STRING_X509_OLD
#define PEM_STRING_X509_OLD
Definition: pem.h:80
PEM_X509_INFO_read_bio
#define PEM_X509_INFO_read_bio
Definition: boringssl_prefix_symbols.h:1913
evp_cipher_info_st::cipher
const EVP_CIPHER * cipher
Definition: cipher.h:581
ERR_GET_LIB
#define ERR_GET_LIB(packed_error)
Definition: err.h:166
header
struct absl::base_internal::@2940::AllocList::Header header
err.h
PEM_write_bio_X509
#define PEM_write_bio_X509
Definition: boringssl_prefix_symbols.h:1998
rsa.h
PEM_write_bio
#define PEM_write_bio
Definition: boringssl_prefix_symbols.h:1981
PEM_STRING_ECPRIVATEKEY
#define PEM_STRING_ECPRIVATEKEY
Definition: pem.h:102
dsa.h
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
parse_x509
static enum parse_result_t parse_x509(X509_INFO *info, const uint8_t *data, size_t len, int key_type)
Definition: pem_info.c:92
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
ERR_R_BUF_LIB
#define ERR_R_BUF_LIB
Definition: err.h:335
parse_key
static enum parse_result_t parse_key(X509_INFO *info, const uint8_t *data, size_t len, int key_type)
Definition: pem_info.c:122
ERR_peek_last_error
#define ERR_peek_last_error
Definition: boringssl_prefix_symbols.h:1431
ERR_R_ASN1_LIB
#define ERR_R_ASN1_LIB
Definition: err.h:340
PEM_R_CIPHER_IS_NULL
#define PEM_R_CIPHER_IS_NULL
Definition: pem.h:472
PEM_STRING_X509_CRL
#define PEM_STRING_X509_CRL
Definition: pem.h:86
evp_pkey_st::pkey
union evp_pkey_st::@364 pkey
d2i_X509
#define d2i_X509
Definition: boringssl_prefix_symbols.h:3031
X509_info_st::enc_data
char * enc_data
Definition: x509.h:294
BIO_free
#define BIO_free
Definition: boringssl_prefix_symbols.h:787
X509_info_st
Definition: x509.h:287
benchmark.FILE
FILE
Definition: benchmark.py:21
d2i_PrivateKey
#define d2i_PrivateKey
Definition: boringssl_prefix_symbols.h:3016
OBJ_nid2sn
#define OBJ_nid2sn
Definition: boringssl_prefix_symbols.h:1856
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
ERR_LIB_PEM
@ ERR_LIB_PEM
Definition: err.h:300
X509_info_st::x_pkey
X509_PKEY * x_pkey
Definition: x509.h:290
X509_PKEY_new
#define X509_PKEY_new
Definition: boringssl_prefix_symbols.h:2405
ok
bool ok
Definition: async_end2end_test.cc:197
ERR_clear_error
#define ERR_clear_error
Definition: boringssl_prefix_symbols.h:1413
obj.h
BIO_NOCLOSE
#define BIO_NOCLOSE
Definition: bio.h:373
X509_info_st::crl
X509_CRL * crl
Definition: x509.h:289
X509_INFO_free
#define X509_INFO_free
Definition: boringssl_prefix_symbols.h:2345
PEM_dek_info
#define PEM_dek_info
Definition: boringssl_prefix_symbols.h:1917
mem.h
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
key_type
upb_fieldtype_t key_type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1071
PEM_STRING_RSA
#define PEM_STRING_RSA
Definition: pem.h:89
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
klen
X509 X509_REQ PKCS7 PKCS8_PRIV_KEY_INFO RSA DSA DSA EC_KEY EVP_PKEY EVP_PKEY int char int klen
Definition: pem.h:426
STACK_OF
STACK_OF(X509_INFO)
Definition: pem_info.c:73
PEM_X509_INFO_write_bio
int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
Definition: pem_info.c:275
cb
OPENSSL_EXPORT pem_password_cb * cb
Definition: pem.h:351
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
ERR_R_MALLOC_FAILURE
#define ERR_R_MALLOC_FAILURE
Definition: err.h:371
evp_cipher_info_st::iv
unsigned char iv[EVP_MAX_IV_LENGTH]
Definition: cipher.h:582
d2i_X509_AUX
OPENSSL_EXPORT X509 * d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
parse_error
@ parse_error
Definition: pem_info.c:88
x509.h
PEM_TYPE_ENCRYPTED
#define PEM_TYPE_ENCRYPTED
Definition: pem.h:106
parse_x509_aux
static enum parse_result_t parse_x509_aux(X509_INFO *info, const uint8_t *data, size_t len, int key_type)
Definition: pem_info.c:102


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:41