]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/pem/pem_info.c
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
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
11 * DSA low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
17 #include "internal/cryptlib.h"
18 #include <openssl/buffer.h>
19 #include <openssl/objects.h>
20 #include <openssl/evp.h>
21 #include <openssl/x509.h>
22 #include <openssl/pem.h>
23 #include <openssl/rsa.h>
24 #include <openssl/dsa.h>
25 #include "crypto/evp.h"
27 #ifndef OPENSSL_NO_STDIO
29 *PEM_X509_INFO_read_ex(FILE *fp
, STACK_OF(X509_INFO
) *sk
, pem_password_cb
*cb
,
30 void *u
, OSSL_LIB_CTX
*libctx
, const char *propq
)
33 STACK_OF(X509_INFO
) *ret
;
35 if ((b
= BIO_new(BIO_s_file())) == NULL
) {
36 ERR_raise(ERR_LIB_PEM
, ERR_R_BUF_LIB
);
39 BIO_set_fp(b
, fp
, BIO_NOCLOSE
);
40 ret
= PEM_X509_INFO_read_bio_ex(b
, sk
, cb
, u
, libctx
, propq
);
45 STACK_OF(X509_INFO
) *PEM_X509_INFO_read(FILE *fp
, STACK_OF(X509_INFO
) *sk
,
46 pem_password_cb
*cb
, void *u
)
48 return PEM_X509_INFO_read_ex(fp
, sk
, cb
, u
, NULL
, NULL
);
52 STACK_OF(X509_INFO
) *PEM_X509_INFO_read_bio_ex(BIO
*bp
, STACK_OF(X509_INFO
) *sk
,
53 pem_password_cb
*cb
, void *u
,
58 char *name
= NULL
, *header
= NULL
, *str
;
60 unsigned char *data
= NULL
;
61 const unsigned char *p
;
64 STACK_OF(X509_INFO
) *ret
= NULL
;
65 unsigned int i
, raw
, ptype
;
69 if ((ret
= sk_X509_INFO_new_null()) == NULL
) {
70 ERR_raise(ERR_LIB_PEM
, ERR_R_CRYPTO_LIB
);
76 if ((xi
= X509_INFO_new()) == NULL
)
82 i
= PEM_read_bio(bp
, &name
, &header
, &data
, &len
);
84 error
= ERR_GET_REASON(ERR_peek_last_error());
85 if (error
== PEM_R_NO_START_LINE
) {
89 ERR_clear_last_mark();
92 ERR_clear_last_mark();
94 if (strcmp(name
, PEM_STRING_X509
) == 0
95 || strcmp(name
, PEM_STRING_X509_OLD
) == 0
96 || strcmp(name
, PEM_STRING_X509_TRUSTED
) == 0) {
97 if (xi
->x509
!= NULL
) {
98 if (!sk_X509_INFO_push(ret
, xi
))
100 if ((xi
= X509_INFO_new()) == NULL
)
104 if ((strcmp(name
, PEM_STRING_X509_TRUSTED
) == 0))
105 d2i
= (D2I_OF(void)) d2i_X509_AUX
;
107 d2i
= (D2I_OF(void)) d2i_X509
;
108 xi
->x509
= X509_new_ex(libctx
, propq
);
109 if (xi
->x509
== NULL
)
112 } else if (strcmp(name
, PEM_STRING_X509_CRL
) == 0) {
113 d2i
= (D2I_OF(void)) d2i_X509_CRL
;
114 if (xi
->crl
!= NULL
) {
115 if (!sk_X509_INFO_push(ret
, xi
))
117 if ((xi
= X509_INFO_new()) == NULL
)
122 } else if ((str
= strstr(name
, PEM_STRING_PKCS8INF
)) != NULL
) {
123 if (xi
->x_pkey
!= NULL
) {
124 if (!sk_X509_INFO_push(ret
, xi
))
126 if ((xi
= X509_INFO_new()) == NULL
)
130 if (str
== name
|| strcmp(name
, PEM_STRING_PKCS8
) == 0) {
131 ptype
= EVP_PKEY_NONE
;
133 /* chop " PRIVATE KEY" */
135 ptype
= evp_pkey_name2type(name
);
140 d2i
= (D2I_OF(void)) d2i_AutoPrivateKey
;
141 xi
->x_pkey
= X509_PKEY_new();
142 if (xi
->x_pkey
== NULL
)
144 pp
= &xi
->x_pkey
->dec_pkey
;
145 if ((int)strlen(header
) > 10 /* assume encrypted */
146 || strcmp(name
, PEM_STRING_PKCS8
) == 0)
148 } else { /* unknown */
155 EVP_CIPHER_INFO cipher
;
157 if (!PEM_get_EVP_CIPHER_INFO(header
, &cipher
))
159 if (!PEM_do_header(&cipher
, data
, &len
, cb
, u
))
163 if (d2i_PrivateKey_ex(ptype
, pp
, &p
, len
,
164 libctx
, propq
) == NULL
) {
165 ERR_raise(ERR_LIB_PEM
, ERR_R_ASN1_LIB
);
168 } else if (d2i(pp
, &p
, len
) == NULL
) {
169 ERR_raise(ERR_LIB_PEM
, ERR_R_ASN1_LIB
);
172 } else { /* encrypted key data */
173 if (!PEM_get_EVP_CIPHER_INFO(header
, &xi
->enc_cipher
))
175 xi
->enc_data
= (char *)data
;
176 xi
->enc_len
= (int)len
;
182 OPENSSL_free(header
);
189 * if the last one hasn't been pushed yet and there is anything in it
190 * then add it to the stack ...
192 if ((xi
->x509
!= NULL
) || (xi
->crl
!= NULL
) ||
193 (xi
->x_pkey
!= NULL
) || (xi
->enc_data
!= NULL
)) {
194 if (!sk_X509_INFO_push(ret
, xi
))
202 for (i
= 0; ((int)i
) < sk_X509_INFO_num(ret
); i
++) {
203 xi
= sk_X509_INFO_value(ret
, i
);
207 sk_X509_INFO_free(ret
);
212 OPENSSL_free(header
);
217 STACK_OF(X509_INFO
) *PEM_X509_INFO_read_bio(BIO
*bp
, STACK_OF(X509_INFO
) *sk
,
218 pem_password_cb
*cb
, void *u
)
220 return PEM_X509_INFO_read_bio_ex(bp
, sk
, cb
, u
, NULL
, NULL
);
224 int PEM_X509_INFO_write_bio(BIO
*bp
, const X509_INFO
*xi
, EVP_CIPHER
*enc
,
225 const unsigned char *kstr
, int klen
,
226 pem_password_cb
*cb
, void *u
)
229 unsigned char *data
= NULL
;
230 const char *objstr
= NULL
;
231 char buf
[PEM_BUFSIZE
];
232 const unsigned char *iv
= NULL
;
235 objstr
= EVP_CIPHER_get0_name(enc
);
238 * Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n"
241 || strlen(objstr
) + 23 + 2 * EVP_CIPHER_get_iv_length(enc
) + 13
243 ERR_raise(ERR_LIB_PEM
, PEM_R_UNSUPPORTED_CIPHER
);
249 * now for the fun part ... if we have a private key then we have to be
250 * able to handle a not-yet-decrypted key being written out correctly ...
251 * if it is decrypted or it is non-encrypted then we use the base code
253 if (xi
->x_pkey
!= NULL
) {
254 if ((xi
->enc_data
!= NULL
) && (xi
->enc_len
> 0)) {
256 ERR_raise(ERR_LIB_PEM
, PEM_R_CIPHER_IS_NULL
);
260 /* copy from weirdo names into more normal things */
261 iv
= xi
->enc_cipher
.iv
;
262 data
= (unsigned char *)xi
->enc_data
;
266 * we take the encryption data from the internal stuff rather
267 * than what the user has passed us ... as we have to match
268 * exactly for some strange reason
270 objstr
= EVP_CIPHER_get0_name(xi
->enc_cipher
.cipher
);
271 if (objstr
== NULL
) {
272 ERR_raise(ERR_LIB_PEM
, PEM_R_UNSUPPORTED_CIPHER
);
276 /* Create the right magic header stuff */
278 PEM_proc_type(buf
, PEM_TYPE_ENCRYPTED
);
279 PEM_dek_info(buf
, objstr
, EVP_CIPHER_get_iv_length(enc
),
282 /* use the normal code to write things out */
283 i
= PEM_write_bio(bp
, PEM_STRING_RSA
, buf
, data
, i
);
288 /* normal optionally encrypted stuff */
289 if (PEM_write_bio_RSAPrivateKey(bp
,
290 EVP_PKEY_get0_RSA(xi
->x_pkey
->dec_pkey
),
291 enc
, kstr
, klen
, cb
, u
) <= 0)
296 /* if we have a certificate then write it out now */
297 if ((xi
->x509
!= NULL
) && (PEM_write_bio_X509(bp
, xi
->x509
) <= 0))
301 * we are ignoring anything else that is loaded into the X509_INFO
302 * structure for the moment ... as I don't need it so I'm not coding it
303 * here and Eric can do it when this makes it into the base library --tjh
309 OPENSSL_cleanse(buf
, PEM_BUFSIZE
);