// pem.h - PEM read and write routines. // Written and placed in the public domain by Jeffrey Walton /// \file pem.h /// \brief Functions to read and write PEM encoded objects /// \details This is a library add-on. You must download and compile it /// yourself. Also see PEM /// Pack on the Crypto++ wiki. // Why Not Specialize Function Templates? // http://www.gotw.ca/publications/mill17.htm ///////////////////////////////////////////////////////////////////////////// #ifndef CRYPTOPP_PEM_H #define CRYPTOPP_PEM_H #include "pubkey.h" #include "eccrypto.h" #include "gfpcrypt.h" #include "x509cert.h" #include "elgamal.h" #include "rsa.h" #include "dsa.h" #include "asn.h" NAMESPACE_BEGIN(CryptoPP) /// \brief Get the next PEM object /// \param src the source BufferedTransformation /// \param dest the destination BufferedTransformation /// \returns true if an object was parsed, false otherwise /// \details PEM_NextObject attempts to retrieve the next PEM encoded key or /// parameter from src and transfers it to dest. If there /// are multiple keys or parameters, then only the first is transferred. /// \details If src is empty then PEM_NextObject() returns false. /// If src holds a partial or malformed object is present then /// InvalidDataFormat is thrown. The exception is used to distinguish /// from an empty src, and the exception signals the caller to fix /// src. /// \details PEM_NextObject will parse an invalid object. For example, it /// will parse a key or parameter with -----BEGIN FOO----- and /// -----END BAR-----. The parser only looks for BEGIN and END /// (and the dashes). The malformed input will be caught later when a /// particular key or parameter is parsed. /// \throws InvalidDataFormat bool PEM_NextObject(BufferedTransformation& src, BufferedTransformation& dest); /// \brief Recognized PEM types. /// \details Many PEM types can be read and write, but not all of them. /// \sa Where is the /// PEM file format specified? enum PEM_Type { /// \brief Public key /// \details non-specific public key PEM_PUBLIC_KEY = 1, /// \brief Private key /// \details non-specific private key PEM_PRIVATE_KEY, /// \brief RSA public key PEM_RSA_PUBLIC_KEY, /// \brief RSA private key PEM_RSA_PRIVATE_KEY, /// \brief Encrypted RSA private key PEM_RSA_ENC_PRIVATE_KEY, /// \brief DSA public key PEM_DSA_PUBLIC_KEY, /// \brief DSA private key PEM_DSA_PRIVATE_KEY, /// \brief Encrypted DSA private key PEM_DSA_ENC_PRIVATE_KEY, /// \brief ElGamal public key PEM_ELGAMAL_PUBLIC_KEY, /// \brief ElGamal private key PEM_ELGAMAL_PRIVATE_KEY, /// \brief Encrypted ElGamal private key PEM_ELGAMAL_ENC_PRIVATE_KEY, /// \brief Elliptic curve public key /// \details non-specific elliptic curve public key PEM_EC_PUBLIC_KEY, /// \brief Elliptic curve private key /// \details non-specific elliptic curve private key PEM_EC_PRIVATE_KEY, /// \brief Encrypted elliptic curve private key /// \details non-specific encrypted elliptic curve private key PEM_EC_ENC_PRIVATE_KEY, /// \brief ECDSA public key PEM_ECDSA_PUBLIC_KEY, /// \brief ECDSA private key PEM_ECDSA_PRIVATE_KEY, /// \brief Encrypted ECDSA private key PEM_ENC_ECDSA_PRIVATE_KEY, /// \brief X25519 public key PEM_X25519_PUBLIC_KEY, /// \brief X25519 private key PEM_X25519_PRIVATE_KEY, /// \brief Encrypted X25519 private key PEM_X25519_ENC_PRIVATE_KEY, /// \brief Elliptic curve parameters PEM_EC_PARAMETERS, /// \brief Diffie-Hellman curve parameters PEM_DH_PARAMETERS, /// \brief DSA parameters PEM_DSA_PARAMETERS, /// \brief X.509 certificate PEM_X509_CERTIFICATE, /// \brief Certificate request PEM_REQ_CERTIFICATE, /// \brief Certificate PEM_CERTIFICATE, /// \brief Unsupported type PEM_UNSUPPORTED = 0xFFFFFFFF }; /// \brief Determine the type of key or parameter /// \param bt the source BufferedTransformation /// \returns PEM_Type or PEM_UNSUPPORTED PEM_Type PEM_GetType(const BufferedTransformation& bt); ///////////////////////////////////////////////////////////////////////////// /// \brief Load a PEM encoded RSA public key /// \param bt the source BufferedTransformation /// \param key the RSA public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, RSA::PublicKey& key); /// \brief Load a PEM encoded RSA private key /// \param bt the source BufferedTransformation /// \param key the RSA private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, RSA::PrivateKey& key); /// \brief Load a PEM encoded RSA private key /// \param bt the source BufferedTransformation /// \param key the RSA private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, RSA::PrivateKey& key, const char* password, size_t length); /// \brief Load a PEM encoded DSA public key /// \param bt the source BufferedTransformation /// \param key the DSA public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DSA::PublicKey& key); /// \brief Load a PEM encoded DSA private key /// \param bt the source BufferedTransformation /// \param key the DSA private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DSA::PrivateKey& key); /// \brief Load a PEM encoded DSA private key /// \param bt the source BufferedTransformation /// \param key the DSA private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DSA::PrivateKey& key, const char* password, size_t length); /// \brief Load a PEM encoded ElGamal public key /// \param bt the source BufferedTransformation /// \param key the ElGamal public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, ElGamalKeys::PublicKey& key); /// \brief Load a PEM encoded ElGamal private key /// \param bt the source BufferedTransformation /// \param key the ElGamal private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, ElGamalKeys::PrivateKey& key); /// \brief Load a PEM encoded ElGamal private key /// \param bt the source BufferedTransformation /// \param key the ElGamal private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, ElGamalKeys::PrivateKey& key, const char* password, size_t length); /// \brief Load a PEM encoded ECP public key /// \param bt the source BufferedTransformation /// \param key the ECP public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PublicKey_EC& key); /// \brief Load a PEM encoded ECP private key /// \param bt the source BufferedTransformation /// \param key the ECP private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PrivateKey_EC& key); /// \brief Load a PEM encoded ECP private key /// \param bt the source BufferedTransformation /// \param key the ECP private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PrivateKey_EC& key, const char* password, size_t length); /// \brief Load a PEM encoded EC2N public key /// \param bt the source BufferedTransformation /// \param key the EC2N public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PublicKey_EC& key); /// \brief Load a PEM encoded EC2N private key /// \param bt the source BufferedTransformation /// \param key the EC2N private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PrivateKey_EC& key); /// \brief Load a PEM encoded EC2N private key /// \param bt the source BufferedTransformation /// \param key the EC2N private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_PrivateKey_EC& key, const char* password, size_t length); /// \brief Load a PEM encoded ECDSA private key /// \param bt the source BufferedTransformation /// \param key the ECDSA private key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_Keys_ECDSA::PrivateKey& key); /// \brief Load a PEM encoded ECDSA private key /// \param bt the source BufferedTransformation /// \param key the ECDSA private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_Keys_ECDSA::PrivateKey& key, const char* password, size_t length); /// \brief Load a PEM encoded ECDSA public key /// \param bt the source BufferedTransformation /// \param key the ECDSA public key /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_Keys_ECDSA::PrivateKey& key); /// \brief Load a PEM encoded ECDSA private key /// \param bt the source BufferedTransformation /// \param key the ECDSA private key /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_Keys_ECDSA::PrivateKey& key, const char* password, size_t length); /// \brief Load a PEM encoded DSA group parameters /// \param bt the source BufferedTransformation /// \param params the DSA group parameters /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_GroupParameters_DSA& params); /// \brief Load a PEM encoded ECP group parameters /// \param bt the source BufferedTransformation /// \param params the ECP group parameters /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_GroupParameters_EC& params); /// \brief Load a PEM encoded EC2N group parameters /// \param bt the source BufferedTransformation /// \param params the EC2N group parameters /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, DL_GroupParameters_EC& params); /// \brief Load a PEM encoded X.509 certificate /// \param bt the source BufferedTransformation /// \param cert the X.509 certificate /// \throws Exception on failure void PEM_Load(BufferedTransformation& bt, X509Certificate& cert); /// \brief Load a PEM encoded Diffie-Hellman parameters /// \param bt the source BufferedTransformation /// \param p the prime modulus /// \param g the group generator /// \throws Exception on failure void PEM_DH_Load(BufferedTransformation& bt, Integer& p, Integer& g); /// \brief Load a PEM encoded Diffie-Hellman parameters /// \param bt the source BufferedTransformation /// \param p the prime modulus /// \param q the subgroup order /// \param g the group generator /// \throws Exception on failure void PEM_DH_Load(BufferedTransformation& bt, Integer& p, Integer& q, Integer& g); ///////////////////////////////////////////////////////////////////////////// // Begin the Write routines. The write routines always write the "named curve" // (i.e., the OID of secp256k1) rather than the domain parameters. This is // because RFC 5915 specifies the format. In addition, OpenSSL cannot load and // utilize an EC key with a non-named curve into a server. For encrpted private // keys, the algorithm should be a value like `AES-128-CBC`. See pem_read.cpp // and pem_write.cpp for the values that are recognized. On failure, any number // of Crypto++ exceptions are thrown. No custom exceptions are thrown. /// \brief Save a PEM encoded RSA public key /// \param bt the destination BufferedTransformation /// \param key the RSA public key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const RSA::PublicKey& key); /// \brief Save a PEM encoded RSA private key /// \param bt the destination BufferedTransformation /// \param key the RSA private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const RSA::PrivateKey& key); /// \brief Save a PEM encoded RSA private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the RSA private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that are /// recognized. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const RSA::PrivateKey& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded DSA public key /// \param bt the destination BufferedTransformation /// \param key the DSA public key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DSA::PublicKey& key); /// \brief Save a PEM encoded DSA private key /// \param bt the destination BufferedTransformation /// \param key the DSA private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DSA::PrivateKey& key); /// \brief Save a PEM encoded DSA private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the DSA private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that are /// recognized. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DSA::PrivateKey& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded ElGamal public key /// \param bt the destination BufferedTransformation /// \param key the ElGamal public key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const ElGamalKeys::PublicKey& key); /// \brief Save a PEM encoded ElGamal private key /// \param bt the destination BufferedTransformation /// \param key the ElGamal private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const ElGamalKeys::PrivateKey& key); /// \brief Save a PEM encoded ElGamal private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the ElGamal private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that are /// recognized. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const ElGamalKeys::PrivateKey& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded ECP public key /// \param bt the destination BufferedTransformation /// \param key the ECP public key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PublicKey_EC& key); /// \brief Save a PEM encoded ECP private key /// \param bt the destination BufferedTransformation /// \param key the ECP private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PrivateKey_EC& key); /// \brief Save a PEM encoded ECP private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the ECP private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that are /// recognized. /// \details The "named curve" (i.e., the OID of secp256k1) is used rather /// than the domain parameters. This is because RFC 5915 specifies the format. /// In addition, OpenSSL cannot load and utilize an EC key with a non-named /// curve into a server. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PrivateKey_EC& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded EC2N public key /// \param bt the destination BufferedTransformation /// \param key the EC2N public key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PublicKey_EC& key); /// \brief Save a PEM encoded EC2N private key /// \param bt the destination BufferedTransformation /// \param key the EC2N private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PrivateKey_EC& key); /// \brief Save a PEM encoded EC2N private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the EC2N private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that are /// recognized. /// \details The "named curve" (i.e., the OID of secp256k1) is used rather than /// the domain parameters. This is because RFC 5915 specifies the format. In /// addition, OpenSSL cannot load and utilize an EC key with a non-named curve /// into a server. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_PrivateKey_EC& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded ECDSA private key /// \param bt the destination BufferedTransformation /// \param key the ECDSA private key /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_Keys_ECDSA::PrivateKey& key); /// \brief Save a PEM encoded ECDSA private key /// \param bt the destination BufferedTransformation /// \param rng a RandomNumberGenerator to produce an initialization vector /// \param key the ECDSA private key /// \param algorithm the encryption algorithm /// \param password pointer to the password buffer /// \param length the size of the password buffer /// \details The algorithm should be a value like AES-128-CBC. See /// pem_read.cpp and pem_write.cpp for the values that /// are recognized. /// \details The "named curve" (i.e., the OID of secp256k1) is used rather /// than the domain parameters. This is because RFC 5915 specifies the format. /// In addition, OpenSSL cannot load and utilize an EC key with a non-named /// curve into a server. /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_Keys_ECDSA::PrivateKey& key, RandomNumberGenerator& rng, const std::string& algorithm, const char* password, size_t length); /// \brief Save a PEM encoded DSA group parameters /// \param bt the destination BufferedTransformation /// \param params the DSA group parameters /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_GroupParameters_DSA& params); /// \brief Save a PEM encoded ECP group parameters /// \param bt the destination BufferedTransformation /// \param params the ECP group parameters /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_GroupParameters_EC& params); /// \brief Save a PEM encoded EC2N group parameters /// \param bt the destination BufferedTransformation /// \param params the EC2N group parameters /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const DL_GroupParameters_EC& params); /// \brief Save a PEM encoded X.509 certificate /// \param bt the destination BufferedTransformation /// \param cert the X.509 certificate /// \throws Exception on failure void PEM_Save(BufferedTransformation& bt, const X509Certificate& cert); /// \brief Save a PEM encoded Diffie-Hellman parameters /// \param bt the destination BufferedTransformation /// \param p the prime modulus /// \param g the group generator /// \throws Exception on failure void PEM_DH_Save(BufferedTransformation& bt, const Integer& p, const Integer& g); /// \brief Save a PEM encoded Diffie-Hellman parameters /// \param bt the destination BufferedTransformation /// \param p the prime modulus /// \param q the subgroup order /// \param g the group generator /// \throws Exception on failure void PEM_DH_Save(BufferedTransformation& bt, const Integer& p, const Integer& q, const Integer& g); NAMESPACE_END #endif