I am trying to find the C source code for the definition of the crypto function PEM_read_bio_X509(). See for example this application in C++. I thought it would be part of the openssl source code. But if I do:
$ git clone [email protected]:openssl/openssl.git
$ cd openssl
$ find . -type f -exec grep -I -Hn --color=auto PEM_read_bio_X509 {} \;
I get some matches, but only use cases, not the definition of the function.
I can also generate the shared library (libcrypto.so):
$ ./config
$ make
$ nm -g ./libcrypto.so | grep PEM_read_bio_X509
00000000001cb050 T PEM_read_bio_X509
00000000001cb0f0 T PEM_read_bio_X509_AUX
00000000001c6070 T PEM_read_bio_X509_CRL
00000000001c5f70 T PEM_read_bio_X509_REQ
So the symbol PEM_read_bio_X509 is indeed defined in the generated libcrypto.so. What am I missing?
Where can I find the definition of the function PEM_read_bio_X509()?
I believe PEM_read_bio_X509 is spliced together with macros. In particular, DECLARE_PEM_rw(X509, X509) (declaration) and IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) (implementation).
$ cat include/openssl/pem.h | grep X509
# define PEM_STRING_X509_OLD "X509 CERTIFICATE"
# define PEM_STRING_X509 "CERTIFICATE"
# define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
# define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
# define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
# define PEM_STRING_X509_CRL "X509 CRL"
STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
DECLARE_PEM_rw(X509, X509)
DECLARE_PEM_rw(X509_AUX, X509)
DECLARE_PEM_rw(X509_REQ, X509_REQ)
DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
DECLARE_PEM_rw(X509_CRL, X509_CRL)
DECLARE_PEM_rw(PKCS8, X509_SIG)
And:
$ grep -IR -A 2 DECLARE_PEM_rw ./* | grep define -A 2
./include/openssl/pem.h:# define DECLARE_PEM_rw(name, type) \
./include/openssl/pem.h- DECLARE_PEM_read(name, type) \
./include/openssl/pem.h- DECLARE_PEM_write(name, type)
./include/openssl/pem.h:# define DECLARE_PEM_rw_const(name, type) \
./include/openssl/pem.h- DECLARE_PEM_read(name, type) \
./include/openssl/pem.h- DECLARE_PEM_write_const(name, type)
./include/openssl/pem.h:# define DECLARE_PEM_rw_cb(name, type) \
./include/openssl/pem.h- DECLARE_PEM_read(name, type) \
./include/openssl/pem.h- DECLARE_PEM_write_cb(name, type)
And:
$ grep -IR -A 2 DECLARE_PEM_read ./* | grep define -A 2
./include/openssl/pem.h:# define DECLARE_PEM_read_fp(name, type) /**/
./include/openssl/pem.h-# define DECLARE_PEM_write_fp(name, type) /**/
./include/openssl/pem.h-# define DECLARE_PEM_write_fp_const(name, type) /**/
--
./include/openssl/pem.h:# define DECLARE_PEM_read_fp(name, type) \
./include/openssl/pem.h- type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
./include/openssl/pem.h-
--
./include/openssl/pem.h:# define DECLARE_PEM_read_bio(name, type) \
./include/openssl/pem.h- type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
You should be able to see the implementation in crypto/pem/pem_x509.c:
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pkcs7.h>
#include <openssl/pem.h>
IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509)
That's not very useful. So preprocess the source file with -E (instead of compiling with -c):
$ cd openssl
$ ./config
...
# No good...
$ make CFLAGS="-I include -E" crypto/pem/pem_x509.o
gcc -I include -E -c -o crypto/pem/pem_x509.o crypto/pem/pem_x509.c
# Try again manually...
$ gcc -I include -E -o crypto/pem/pem_x509.i crypto/pem/pem_x509.c
And then:
$ grep PEM_read_bio_X509 crypto/pem/pem_x509.i
X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u); X509 *
PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u); int PEM_write_b
io_X509(BIO *bp, X509 *x); int PEM_write_X509(FILE *fp, X509 *x);
X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u); X5
09 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u); int PEM
_write_bio_X509_AUX(BIO *bp, X509 *x); int PEM_write_X509_AUX(FILE *fp, X509 *x)
;
X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x, pem_password_cb *cb, void
*u); X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x, pem_password_cb *cb, v
oid *u); int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x); int PEM_write_X509_RE
Q(FILE *fp, X509_REQ *x);
X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x, pem_password_cb *cb, void
*u); X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **x, pem_password_cb *cb, v
oid *u); int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x); int PEM_write_X509_CR
L(FILE *fp, X509_CRL *x);
X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u){ return
PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, "CERTIFICATE",bp,(void **)x,cb,u); }
X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u){ return P
EM_ASN1_read((d2i_of_void *)d2i_X509, "CERTIFICATE",fp,(void **)x,cb,u); } int P
EM_write_bio_X509(BIO *bp, X509 *x) { return PEM_ASN1_write_bio((i2d_of_void *)i
2d_X509,"CERTIFICATE",bp,x,
You are interested in the last hit (reformatted):
X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u)
{
return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, "CERTIFICATE",bp,(void **)x,cb,u);
}
Lather, rinse, repeat for PEM_ASN1_read_bio.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With