Finish documenting <openssl/pem.h> Fixed: 42290574 Change-Id: I4addc0e0b59199e55c9b08eb16c880ff65009c9a Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/97487 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/pem/pem_pkey.cc b/crypto/pem/pem_pkey.cc index 58eb720..836c4a9 100644 --- a/crypto/pem/pem_pkey.cc +++ b/crypto/pem/pem_pkey.cc
@@ -67,7 +67,7 @@ if (!cb) { cb = PEM_def_callback; } - pass_len = cb(psbuf, PEM_BUFSIZE, 0, u); + pass_len = cb(psbuf, PEM_BUFSIZE, /*enc=*/0, u); if (pass_len < 0) { OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); @@ -82,7 +82,7 @@ ret = EVP_PKCS82PKEY(p8inf); if (x) { if (*x) { - EVP_PKEY_free((EVP_PKEY *)*x); + EVP_PKEY_free(*x); } *x = ret; }
diff --git a/include/openssl/pem.h b/include/openssl/pem.h index 6cd1b05..cd36899 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h
@@ -127,19 +127,19 @@ #endif // Sample functions -// Reading and writing objects as PEM. +// Reading and writing X.509 structures as PEM. -// PEM_read_bio_X509 reads a PEM block of type "CERTIFICATE" or "X509 +// PEM_read_bio_X509 reads a PEM block of type "CERTIFICATE" (RFC 7468) or "X509 // CERTIFICATE", as described in `PEM_read_bio_SAMPLE`. OPENSSL_EXPORT X509 *PEM_read_bio_X509(BIO *bio, X509 **out, pem_password_cb *cb, void *userdata); -// PEM_write_bio_X509 writes a PEM block of type "CERTIFICATE", as described in -// `PEM_write_bio_SAMPLE`. +// PEM_write_bio_X509 writes a PEM block of type "CERTIFICATE" (RFC 7468), as +// described in `PEM_write_bio_SAMPLE`. OPENSSL_EXPORT int PEM_write_bio_X509(BIO *bio, const X509 *in); -// PEM_read_bio_X509_AUX reads a PEM block of type "CERTIFICATE", "X509 -// CERTIFICATE", or "TRUSTED CERTIFICATE", as described in +// PEM_read_bio_X509_AUX reads a PEM block of type "CERTIFICATE" (RFC 7468), +// "X509 CERTIFICATE", or "TRUSTED CERTIFICATE", as described in // `PEM_read_bio_SAMPLE`. // // WARNING: This function parses auxiliary properties as in `d2i_X509_AUX`. @@ -155,17 +155,46 @@ // auxiliary properties. See `i2d_X509_AUX`. OPENSSL_EXPORT int PEM_write_bio_X509_AUX(BIO *bio, const X509 *in); -// PEM_write_bio_X509_CRL writes a PEM block of type "X509 CRL", as described in -// `PEM_write_bio_SAMPLE`. -OPENSSL_EXPORT int PEM_write_bio_X509_CRL(BIO *bio, const X509_CRL *in); - -// PEM_read_bio_X509_CRL reads a PEM block of type "X509 CRL", as described in -// `PEM_read_bio_SAMPLE`. +// PEM_read_bio_X509_CRL reads a PEM block of type "X509 CRL" (RFC 7468), as +// described in `PEM_read_bio_SAMPLE`. OPENSSL_EXPORT X509_CRL *PEM_read_bio_X509_CRL(BIO *bio, X509_CRL **out, pem_password_cb *cb, void *userdata); -// PEM_X509_INFO_read_bio reads PEM blocks from `bp` and decodes any +// PEM_write_bio_X509_CRL writes a PEM block of type "X509 CRL" (RFC 7468), as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_X509_CRL(BIO *bio, const X509_CRL *in); + +// PEM_read_bio_X509_REQ reads a PEM block of type "CERTIFICATE REQUEST" +// (RFC 7468) or "NEW CERTIFICATE REQUEST", as described in +// `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT X509_REQ *PEM_read_bio_X509_REQ(BIO *bio, X509_REQ **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_X509_REQ writes a PEM block of type "CERTIFICATE REQUEST" +// (RFC 7468), as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_X509_REQ(BIO *bio, const X509_REQ *in); + +// PEM_write_bio_X509_REQ_NEW writes a PEM block of type "NEW CERTIFICATE +// REQUEST", as described in `PEM_write_bio_SAMPLE`. Prefer to use +// `PEM_write_bio_X509_REQ`. "NEW CERTIFICATE REQUEST" is the older type. +OPENSSL_EXPORT int PEM_write_bio_X509_REQ_NEW(BIO *bio, const X509_REQ *in); + +// PEM_read_bio_PKCS7 reads a PEM block of type "PKCS7" (RFC 7468) or "PKCS #7 +// SIGNED DATA", as described in `PEM_read_bio_SAMPLE`. +// +// This function also accepts type "CERTIFICATE" but decodes the contents as a +// PKCS #7 structure rather than a certificate. This is a historical workaround +// for an old CA bug. +OPENSSL_EXPORT PKCS7 *PEM_read_bio_PKCS7(BIO *bio, PKCS7 **out, + pem_password_cb *cb, void *userdata); + +// PEM_write_bio_PKCS7 writes a PEM block of type "PKCS7" (RFC 7468), as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_PKCS7(BIO *bio, const PKCS7 *in); + +// PEM_X509_INFO_read_bio reads PEM blocks from `bio` and decodes any // certificates, CRLs, and private keys found. It returns a // `STACK_OF(X509_INFO)` structure containing the results, or NULL on error. // @@ -177,7 +206,7 @@ // on success. In this case, the caller retains ownership of `sk` in both // success and failure. // -// This function will decrypt any encrypted certificates in `bp`, using `cb`, +// This function will decrypt any encrypted certificates in `bio`, using `cb`, // but it will not decrypt encrypted private keys. Encrypted private keys are // instead represented as placeholder `X509_INFO` objects with an empty `x_pkey` // field. This allows this function to be used with inputs with unencrypted @@ -190,10 +219,229 @@ // input to this function allows an attacker to influence those properties. See // `d2i_X509_AUX` for details. OPENSSL_EXPORT STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio( - BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *userdata); + BIO *bio, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *userdata); -// The following functions behave like corresponding `PEM_read_bio_*` function, -// but read from `fp`. + +// Reading and writing keys as PEM. +// +// There are multiple PEM formats for public and private keys: +// +// Public keys are generally encoded with type "PUBLIC KEY" (RFC 7468), which +// encodes a SubjectPublicKeyInfo structure (RFC 5280). +// +// Private keys may be encoded with type "PRIVATE KEY" or "ENCRYPTED PRIVATE +// KEY" (RFC 7468), which encode a PrivateKeyInfo or EncryptedPrivateKeyInfo +// (RFC 5208) structure. EncryptedPrivateKeyInfo is, itself, a mechanism for +// encrypting private keys with a password, so private keys may be encrypted +// with PEM encryption, PKCS #8 encryption, or both. +// +// There are also older algorithm-specific PEM types for public and private +// keys, including "RSA PUBLIC KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY", and +// "DSA PRIVATE KEY". Some functions in this library will read or write them. +// +// If unsure, use the "PUBLIC KEY" and "PRIVATE KEY" formats. + +// PEM_read_bio_PrivateKey reads a PEM block containing a private key, as +// described in `PEM_read_bio_SAMPLE`. It handles generic PKCS #8 blocks of type +// "PRIVATE KEY" and "ENCRYPTED PRIVATE KEY", as well as key-specific formats +// like "RSA PRIVATE KEY", "EC PRIVATE KEY", and "DSA PRIVATE KEY". +// +// `cb` and `userdata` are used to look up the password for both PEM-level +// encryption as well as PKCS #8 encryption, in the case of "ENCRYPTED PRIVATE +// KEY" blocks. +OPENSSL_EXPORT EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bio, EVP_PKEY **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_PrivateKey writes `in` to `bio` in PKCS#8 format, as described +// in `PEM_write_bio_SAMPLE`. However, it interprets encryption parameters +// differently: +// +// - If not encrypting (`enc` is NULL), it writes the key as a PEM block of type +// "PRIVATE KEY". +// +// - If encrypted (`enc` is not NULL), it encrypts the key in an +// EncryptedPrivateKeyInfo using PBES2 (see `PKCS8_encrypt`) and writes the +// result as a PEM block of type "ENCRYPTED PRIVATE KEY". +OPENSSL_EXPORT int PEM_write_bio_PrivateKey(BIO *bio, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, + void *userdata); + +// PEM_read_bio_PUBKEY reads a PEM block of type "PUBLIC KEY", as described in +// `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bio, EVP_PKEY **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_PUBKEY writes `in` as a PEM block of type "PUBLIC KEY", as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_PUBKEY(BIO *bio, const EVP_PKEY *in); + +// PEM_write_bio_PKCS8PrivateKey_nid behaves like `PEM_write_bio_PrivateKey` +// but uses the PBES1 algorithm specified by `nid` for encryption. See also +// `PKCS8_encrypt`. If `nid` is -1, it writes the private key unencrypted. +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey_nid( + BIO *bio, const EVP_PKEY *in, int nid, const char *pass, int pass_len, + pem_password_cb *cb, void *userdata); + +// PEM_write_bio_PKCS8PrivateKey is an alias for `PEM_write_bio_PrivateKey`. +OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey(BIO *bio, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const char *pass, int pass_len, + pem_password_cb *cb, + void *userdata); + +// PEM_write_PKCS8PrivateKey_nid behaves like +// `PEM_write_bio_PKCS8PrivateKey_nid` but writes to `fp`. +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *in, + int nid, const char *pass, + int pass_len, + pem_password_cb *cb, + void *userdata); + +// PEM_write_PKCS8PrivateKey behaves like `PEM_write_bio_PKCS8PrivateKey` but +// writes to `fp`. +OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const char *pass, int pass_len, + pem_password_cb *cb, + void *userdata); + +// PEM_read_bio_PKCS8 reads a PEM block of type "ENCRYPTED PRIVATE KEY", as +// described in `PEM_read_bio_SAMPLE`. +// +// Although this function accepts `cb` and `userdata` to decrypt the PEM-level +// encryption, it does not decrypt the EncryptedPrivateKeyInfo structure. It +// returns the encrypted key as an `X509_SIG` object which, despite its name, is +// an algorithm and octet string pair. +OPENSSL_EXPORT X509_SIG *PEM_read_bio_PKCS8(BIO *bio, X509_SIG **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_PKCS8 writes a PEM block of type "ENCRYPTED PRIVATE KEY", as +// described in `PEM_write_bio_SAMPLE`. `in` is used to represent an +// already-encrypted EncryptedPrivateKeyInfo structure. +OPENSSL_EXPORT int PEM_write_bio_PKCS8(BIO *bio, const X509_SIG *in); + +// PEM_read_bio_PKCS8_PRIV_KEY_INFO reads a PEM block of type "PRIVATE KEY", as +// described in `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PEM_read_bio_PKCS8_PRIV_KEY_INFO( + BIO *bio, PKCS8_PRIV_KEY_INFO **out, pem_password_cb *cb, void *userdata); + +// PEM_write_bio_PKCS8_PRIV_KEY_INFO writes a PEM block of type "PRIVATE KEY", +// as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_PKCS8_PRIV_KEY_INFO( + BIO *bio, const PKCS8_PRIV_KEY_INFO *in); + +// PEM_read_bio_RSAPrivateKey behaves like `PEM_read_bio_PrivateKey` but only +// returns RSA keys, represented as an `RSA` object. Keys of other types result +// in an error. +OPENSSL_EXPORT RSA *PEM_read_bio_RSAPrivateKey(BIO *bio, RSA **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_RSAPrivateKey writes `in` as a PEM block of type "RSA PRIVATE +// KEY", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_RSAPrivateKey( + BIO *bio, const RSA *in, const EVP_CIPHER *enc, const uint8_t *pass, + int pass_len, pem_password_cb *cb, void *userdata); + +// PEM_read_bio_RSAPublicKey reads a PEM block of type "RSA PUBLIC KEY", as +// described in `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT RSA *PEM_read_bio_RSAPublicKey(BIO *bio, RSA **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_RSAPublicKey writes a PEM block of type "RSA PUBLIC KEY", as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_RSAPublicKey(BIO *bio, const RSA *in); + +// PEM_read_bio_RSA_PUBKEY behaves like `PEM_read_bio_PUBKEY` but only returns +// RSA keys, represented as an `RSA` object. Keys of other types result in an +// error. +OPENSSL_EXPORT RSA *PEM_read_bio_RSA_PUBKEY(BIO *bio, RSA **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_RSA_PUBKEY writes `in` as a PEM block of type "PUBLIC KEY", as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_RSA_PUBKEY(BIO *bio, const RSA *in); + +// PEM_read_bio_DSAPrivateKey behaves like `PEM_read_bio_PrivateKey` but only +// returns DSA keys, represented as a `DSA` object. Keys of other types result +// in an error. +OPENSSL_EXPORT DSA *PEM_read_bio_DSAPrivateKey(BIO *bio, DSA **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_DSAPrivateKey writes `in` as a PEM block of type "DSA PRIVATE +// KEY", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_DSAPrivateKey( + BIO *bio, const DSA *in, const EVP_CIPHER *enc, const uint8_t *pass, + int pass_len, pem_password_cb *cb, void *userdata); + +// PEM_read_bio_DSA_PUBKEY behaves like `PEM_read_bio_PUBKEY` but only returns +// DSA keys, represented as a `DSA` object. Keys of other types result in an +// error. +OPENSSL_EXPORT DSA *PEM_read_bio_DSA_PUBKEY(BIO *bio, DSA **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_DSA_PUBKEY writes `in` in SubjectPublicKeyInfo format as a PEM +// block of type "PUBLIC KEY", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_DSA_PUBKEY(BIO *bio, const DSA *in); + +// PEM_read_bio_DSAparams reads a PEM block of type "DSA PARAMETERS", as +// described in `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT DSA *PEM_read_bio_DSAparams(BIO *bio, DSA **out, + pem_password_cb *cb, void *userdata); + +// PEM_write_bio_DSAparams writes a PEM block of type "DSA PARAMETERS", as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_DSAparams(BIO *bio, const DSA *in); + +// PEM_read_bio_ECPrivateKey behaves like `PEM_read_bio_PrivateKey` but only +// returns EC keys, represented as an `EC_KEY` object. Keys of other types +// result in an error. +OPENSSL_EXPORT EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bio, EC_KEY **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_ECPrivateKey writes `in` as a PEM block of type "EC PRIVATE +// KEY", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_ECPrivateKey(BIO *bio, const EC_KEY *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, + void *userdata); + +// PEM_read_bio_EC_PUBKEY behaves like `PEM_read_bio_PUBKEY` but only returns +// EC keys, represented as an `EC_KEY` object. Keys of other types result in an +// error. +OPENSSL_EXPORT EC_KEY *PEM_read_bio_EC_PUBKEY(BIO *bio, EC_KEY **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_EC_PUBKEY writes `in` in SubjectPublicKeyInfo format as a PEM +// block of type "PUBLIC KEY", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_EC_PUBKEY(BIO *bio, const EC_KEY *in); + +// PEM_read_bio_DHparams reads a PEM block of type "DH PARAMETERS", as described +// in `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT DH *PEM_read_bio_DHparams(BIO *bio, DH **out, + pem_password_cb *cb, void *userdata); + +// PEM_write_bio_DHparams writes a PEM block of type "DH PARAMETERS", as +// described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_DHparams(BIO *bio, const DH *in); + + +// File-based functions. + +// The following functions behave like the corresponding `PEM_read_bio_*` +// functions, but read from `fp`. OPENSSL_EXPORT X509 *PEM_read_X509(FILE *fp, X509 **out, pem_password_cb *cb, void *userdata); OPENSSL_EXPORT X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **out, @@ -204,12 +452,73 @@ STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT PKCS7 *PEM_read_PKCS7(FILE *fp, PKCS7 **out, pem_password_cb *cb, + void *userdata); +OPENSSL_EXPORT X509_SIG *PEM_read_PKCS8(FILE *fp, X509_SIG **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PEM_read_PKCS8_PRIV_KEY_INFO( + FILE *fp, PKCS8_PRIV_KEY_INFO **out, pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT RSA *PEM_read_RSAPublicKey(FILE *fp, RSA **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT RSA *PEM_read_RSA_PUBKEY(FILE *fp, RSA **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT DSA *PEM_read_DSA_PUBKEY(FILE *fp, DSA **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT DSA *PEM_read_DSAparams(FILE *fp, DSA **out, pem_password_cb *cb, + void *userdata); +OPENSSL_EXPORT EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **out, + pem_password_cb *cb, + void *userdata); +OPENSSL_EXPORT EC_KEY *PEM_read_EC_PUBKEY(FILE *fp, EC_KEY **out, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT DH *PEM_read_DHparams(FILE *fp, DH **out, pem_password_cb *cb, + void *userdata); +OPENSSL_EXPORT EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **out, + pem_password_cb *cb, + void *userdata); +OPENSSL_EXPORT EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **out, + pem_password_cb *cb, void *userdata); -// The following functions behave like corresponding `PEM_write_bio_*` function, -// but write to `fp`. +// The following functions behave like the corresponding `PEM_write_bio_*` +// functions, but write to `fp`. OPENSSL_EXPORT int PEM_write_X509(FILE *fp, const X509 *x); OPENSSL_EXPORT int PEM_write_X509_CRL(FILE *fp, const X509_CRL *in); OPENSSL_EXPORT int PEM_write_X509_AUX(FILE *fp, const X509 *in); +OPENSSL_EXPORT int PEM_write_X509_REQ(FILE *fp, const X509_REQ *in); +OPENSSL_EXPORT int PEM_write_X509_REQ_NEW(FILE *fp, const X509_REQ *in); +OPENSSL_EXPORT int PEM_write_PKCS7(FILE *fp, const PKCS7 *in); +OPENSSL_EXPORT int PEM_write_PKCS8(FILE *fp, const X509_SIG *in); +OPENSSL_EXPORT int PEM_write_PKCS8_PRIV_KEY_INFO(FILE *fp, + const PKCS8_PRIV_KEY_INFO *in); +OPENSSL_EXPORT int PEM_write_RSAPrivateKey(FILE *fp, const RSA *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT int PEM_write_RSAPublicKey(FILE *fp, const RSA *in); +OPENSSL_EXPORT int PEM_write_RSA_PUBKEY(FILE *fp, const RSA *in); +OPENSSL_EXPORT int PEM_write_DSAPrivateKey(FILE *fp, const DSA *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT int PEM_write_DSA_PUBKEY(FILE *fp, const DSA *in); +OPENSSL_EXPORT int PEM_write_DSAparams(FILE *fp, const DSA *in); +OPENSSL_EXPORT int PEM_write_ECPrivateKey(FILE *fp, const EC_KEY *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT int PEM_write_EC_PUBKEY(FILE *fp, const EC_KEY *in); +OPENSSL_EXPORT int PEM_write_DHparams(FILE *fp, const DH *in); +OPENSSL_EXPORT int PEM_write_PrivateKey(FILE *fp, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const uint8_t *pass, int pass_len, + pem_password_cb *cb, void *userdata); +OPENSSL_EXPORT int PEM_write_PUBKEY(FILE *fp, const EVP_PKEY *in); // Reading and writing raw PEM blocks. @@ -333,6 +642,76 @@ pem_password_cb *cb, void *userdata); +// Reading and writing DER-encoded private keys. + +// d2i_PKCS8PrivateKey_bio reads a DER-encoded EncryptedPrivateKey structure +// (RFC 5208) from `bio`, decrypts it with `PKCS8_decrypt`, and returns the +// result as a newly-allocated `EVP_PKEY`, or NULL on error. On success, if +// `out` is non-NULL, it additionally frees the previous value at `*out` and +// updates `*out` to the result. The password is determined by calling `cb`, or +// `PEM_def_callback` if NULL. +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bio, EVP_PKEY **out, + pem_password_cb *cb, + void *userdata); + +// i2d_PKCS8PrivateKey_bio encodes `in` as a DER-encoded structure and writes +// it to `bio`. It returns one on success and zero on error. The structure used +// depends on `enc`: +// +// - If `enc` is NULL, it writes a PrivateKeyInfo structure (RFC 5208). +// +// - If `enc` is non-NULL, it writes an EncryptedPrivateKeyInfo structure (RFC +// 5280). The key is encrypted with PBES2, as in `PKCS8_encrypt`. The password +// is specified by `pass`, `cb`, and `userdata`, as in `PEM_write_bio_SAMPLE`. +// +// WARNING: PrivateKeyInfo and EncryptedPrivateKeyInfo are different formats, +// and DER does not include a type header. The encrypted and unencrypted modes +// of this function should not be mixed in the same context. +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_bio(BIO *bio, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const char *pass, int pass_len, + pem_password_cb *cb, void *userdata); + +// i2d_PKCS8PrivateKey_nid_bio encodes `in` as a DER-encoded structure and +// writes it to `bio`. It returns one on success and zero on error. The +// structure used depends on `nid`: +// +// - If `nid` is -1, it writes a PrivateKeyInfo structure (RFC 5208). +// +// - Otherwise, it writes an EncryptedPrivateKeyInfo structure (RFC 5280). The +// key is encrypted with PBES1, as in `PKCS8_encrypt`. The password is +// specified by `pass`, `cb`, and `userdata`, as in `PEM_write_bio_SAMPLE`. +// +// WARNING: PrivateKeyInfo and EncryptedPrivateKeyInfo are different formats, +// and DER does not include a type header. The encrypted and unencrypted modes +// of this function should not be mixed in the same context. +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_bio(BIO *bio, const EVP_PKEY *in, + int nid, const char *pass, + int pass_len, + pem_password_cb *cb, + void *userdata); + +// i2d_PKCS8PrivateKey_fp behaves like `i2d_PKCS8PrivateKey_bio` but writes to +// `fp`. +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *in, + const EVP_CIPHER *enc, + const char *pass, int pass_len, + pem_password_cb *cb, void *userdata); + +// i2d_PKCS8PrivateKey_nid_fp behaves like `i2d_PKCS8PrivateKey_nid_bio` but +// writes to `fp`. +OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *in, + int nid, const char *pass, + int pass_len, pem_password_cb *cb, + void *userdata); + +// d2i_PKCS8PrivateKey_fp behaves like `d2i_PKCS8PrivateKey_bio` but reads from +// `fp`. +OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **out, + pem_password_cb *cb, + void *userdata); + + // Internal functions. // // The following functions are used to implement `PEM_read_bio_*` and @@ -365,130 +744,6 @@ pem_password_cb *callback, void *userdata); -// Not yet documented functions. -// -// TODO(crbug.com/42290574): Finish documenting and organizing this header. - -#define DECLARE_PEM_read_fp(name, type) \ - OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **out, \ - pem_password_cb *cb, void *userdata); - -#define DECLARE_PEM_write_fp(name, type) \ - OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *in); - -#define DECLARE_PEM_write_cb_fp(name, type) \ - OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *in, \ - const EVP_CIPHER *enc, \ - const unsigned char *pass, int pass_len, \ - pem_password_cb *cb, void *userdata); - -#define DECLARE_PEM_read_bio(name, type) \ - OPENSSL_EXPORT type *PEM_read_bio_##name( \ - BIO *bio, type **out, pem_password_cb *cb, void *userdata); - -#define DECLARE_PEM_write_bio(name, type) \ - OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bio, const type *in); - -#define DECLARE_PEM_write_cb_bio(name, type) \ - OPENSSL_EXPORT int PEM_write_bio_##name( \ - BIO *bio, const type *in, const EVP_CIPHER *enc, \ - const unsigned char *pass, int pass_len, pem_password_cb *cb, \ - void *userdata); - -#define DECLARE_PEM_write(name, type) \ - DECLARE_PEM_write_bio(name, type) \ - DECLARE_PEM_write_fp(name, type) - -#define DECLARE_PEM_write_cb(name, type) \ - DECLARE_PEM_write_cb_bio(name, type) \ - DECLARE_PEM_write_cb_fp(name, type) - -#define DECLARE_PEM_read(name, type) \ - DECLARE_PEM_read_bio(name, type) \ - DECLARE_PEM_read_fp(name, type) - -#define DECLARE_PEM_rw(name, type) \ - DECLARE_PEM_read(name, type) \ - DECLARE_PEM_write(name, type) - -#define DECLARE_PEM_rw_cb(name, type) \ - DECLARE_PEM_read(name, type) \ - DECLARE_PEM_write_cb(name, type) - - -DECLARE_PEM_rw(X509_REQ, X509_REQ) -DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) - - -DECLARE_PEM_rw(PKCS7, PKCS7) -DECLARE_PEM_rw(PKCS8, X509_SIG) - -DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) - -DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) - -DECLARE_PEM_rw(RSAPublicKey, RSA) -DECLARE_PEM_rw(RSA_PUBKEY, RSA) - -DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) - -DECLARE_PEM_rw(DSA_PUBKEY, DSA) - -DECLARE_PEM_rw(DSAparams, DSA) - -DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) -DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) - - -DECLARE_PEM_rw(DHparams, DH) - - -DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) - -DECLARE_PEM_rw(PUBKEY, EVP_PKEY) - -OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, const EVP_PKEY *x, - int nid, const char *pass, - int pass_len, - pem_password_cb *cb, - void *u); -OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey(BIO *bp, const EVP_PKEY *x, - const EVP_CIPHER *enc, - const char *pass, int pass_len, - pem_password_cb *cb, void *u); -OPENSSL_EXPORT int i2d_PKCS8PrivateKey_bio(BIO *bp, const EVP_PKEY *x, - const EVP_CIPHER *enc, - const char *pass, int pass_len, - pem_password_cb *cb, void *u); -OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, const EVP_PKEY *x, - int nid, const char *pass, - int pass_len, - pem_password_cb *cb, void *u); -OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, - pem_password_cb *cb, void *u); - -OPENSSL_EXPORT int i2d_PKCS8PrivateKey_fp(FILE *fp, const EVP_PKEY *x, - const EVP_CIPHER *enc, - const char *pass, int pass_len, - pem_password_cb *cb, void *u); -OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, const EVP_PKEY *x, - int nid, const char *pass, - int pass_len, pem_password_cb *cb, - void *u); -OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey_nid(FILE *fp, const EVP_PKEY *x, - int nid, const char *pass, - int pass_len, - pem_password_cb *cb, void *u); - -OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, - pem_password_cb *cb, void *u); - -OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, - const EVP_CIPHER *enc, - const char *pass, int pass_len, - pem_password_cb *cd, void *u); - - #if defined(__cplusplus) } // extern C #endif
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index ff27b47..8c81152 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -1906,8 +1906,6 @@ // connections within an application-level session will reuse TLS sessions. TLS // sessions may be dropped by the client or ignored by the server at any time. -DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) - // SSL_SESSION_new returns a newly-allocated blank `SSL_SESSION` or NULL on // error. This may be useful when writing tests but should otherwise not be // used. @@ -1940,6 +1938,27 @@ size_t in_len, const SSL_CTX *ctx); +// PEM_read_bio_SSL_SESSION reads an `SSL_SESSION` as a PEM block of type "SSL +// SESSION PARAMETERS", as described in `PEM_read_bio_SAMPLE`. +OPENSSL_EXPORT SSL_SESSION *PEM_read_bio_SSL_SESSION(BIO *bio, + SSL_SESSION **out, + pem_password_cb *cb, + void *userdata); + +// PEM_read_SSL_SESSION behaves like `PEM_read_bio_SSL_SESSION` but reads from +// `fp`. +OPENSSL_EXPORT SSL_SESSION *PEM_read_SSL_SESSION(FILE *fp, SSL_SESSION **out, + pem_password_cb *cb, + void *userdata); + +// PEM_write_bio_SSL_SESSION writes `in` to `bio` as a PEM block of type "SSL +// SESSION PARAMETERS", as described in `PEM_write_bio_SAMPLE`. +OPENSSL_EXPORT int PEM_write_bio_SSL_SESSION(BIO *bio, const SSL_SESSION *in); + +// PEM_write_SSL_SESSION behaves like `PEM_write_bio_SSL_SESSION` but writes to +// `fp`. +OPENSSL_EXPORT int PEM_write_SSL_SESSION(FILE *fp, const SSL_SESSION *in); + // SSL_SESSION_get_version returns a string describing the TLS or DTLS version // `session` was established at. For example, "TLSv1.2" or "DTLSv1". OPENSSL_EXPORT const char *SSL_SESSION_get_version(const SSL_SESSION *session);