diff options
author | René Korthaus <[email protected]> | 2015-12-25 13:46:09 +0100 |
---|---|---|
committer | René Korthaus <[email protected]> | 2015-12-25 13:46:09 +0100 |
commit | 50b3cce52d5a02c5c3d039dc792edcc7bb7ee7dc (patch) | |
tree | eb47191591434d555d94a27a1eb8683e4541aafb | |
parent | 20e7a430425f20c939e872c932c29330f8db5422 (diff) |
Fix loading of unencrypted, BER encoded private keys via PKCS8 api
-rw-r--r-- | src/lib/pubkey/pkcs8.cpp | 82 | ||||
-rw-r--r-- | src/lib/pubkey/pkcs8.h | 48 | ||||
-rw-r--r-- | src/tests/test_pubkey.cpp | 3 |
3 files changed, 99 insertions, 34 deletions
diff --git a/src/lib/pubkey/pkcs8.cpp b/src/lib/pubkey/pkcs8.cpp index 92157a196..1a021a283 100644 --- a/src/lib/pubkey/pkcs8.cpp +++ b/src/lib/pubkey/pkcs8.cpp @@ -44,19 +44,39 @@ secure_vector<byte> PKCS8_extract(DataSource& source, secure_vector<byte> PKCS8_decode( DataSource& source, std::function<std::string ()> get_passphrase, - AlgorithmIdentifier& pk_alg_id) + AlgorithmIdentifier& pk_alg_id, + bool is_encrypted) { AlgorithmIdentifier pbe_alg_id; secure_vector<byte> key_data, key; - bool is_encrypted = true; try { if(ASN1::maybe_BER(source) && !PEM_Code::matches(source)) - key_data = PKCS8_extract(source, pbe_alg_id); + { + if ( is_encrypted ) + { + key_data = PKCS8_extract(source, pbe_alg_id); + } + else + { + // todo read more efficiently + while ( !source.end_of_data() ) + { + byte b; + size_t read = source.read_byte( b ); + if ( read ) + { + key_data.push_back( b ); + } + } + } + } else { std::string label; key_data = PEM_Code::decode(source, label); + + // todo remove autodetect for pem as well? if(label == "PRIVATE KEY") is_encrypted = false; else if(label == "ENCRYPTED PRIVATE KEY") @@ -189,15 +209,18 @@ std::string PEM_encode(const Private_Key& key, "ENCRYPTED PRIVATE KEY"); } +namespace { + /* -* Extract a private key and return it +* Extract a private key (encrypted/unencrypted) and return it */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, - std::function<std::string ()> get_pass) + std::function<std::string ()> get_pass, + bool is_encrypted) { AlgorithmIdentifier alg_id; - secure_vector<byte> pkcs8_key = PKCS8_decode(source, get_pass, alg_id); + secure_vector<byte> pkcs8_key = PKCS8_decode(source, get_pass, alg_id, is_encrypted); const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "" || alg_name == alg_id.oid.as_string()) @@ -207,29 +230,51 @@ Private_Key* load_key(DataSource& source, return make_private_key(alg_id, pkcs8_key, rng); } +} + /* -* Extract a private key and return it +* Extract an encrypted private key and return it */ -Private_Key* load_key(const std::string& fsname, +Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, std::function<std::string ()> get_pass) { - DataSource_Stream source(fsname, true); - return PKCS8::load_key(source, rng, get_pass); + return load_key(source, rng, get_pass, true); } /* -* Extract a private key and return it +* Extract an encrypted private key and return it */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, const std::string& pass) { - return PKCS8::load_key(source, rng, [pass]() { return pass; }); + return load_key(source, rng, [pass]() { return pass; }, true); + } + +/* +* Extract an unencrypted private key and return it +*/ +Private_Key* load_key(DataSource& source, + RandomNumberGenerator& rng) + { + return load_key(source, rng, []() -> std::string { + throw PKCS8_Exception( "Internal error: Attempt to read password for unencrypted key" );}, false); + } + +/* +* Extract an encrypted private key and return it +*/ +Private_Key* load_key(const std::string& fsname, + RandomNumberGenerator& rng, + std::function<std::string ()> get_pass) + { + DataSource_Stream source(fsname, true); + return load_key(source, rng, get_pass, true); } /* -* Extract a private key and return it +* Extract an encrypted private key and return it */ Private_Key* load_key(const std::string& fsname, RandomNumberGenerator& rng, @@ -239,6 +284,17 @@ Private_Key* load_key(const std::string& fsname, } /* +* Extract an unencrypted private key and return it +*/ +Private_Key* load_key(const std::string& fsname, + RandomNumberGenerator& rng) + { + DataSource_Stream source(fsname, true); + return load_key(source, rng, []() -> std::string { + throw PKCS8_Exception( "Internal error: Attempt to read password for unencrypted key" );}, false); + } + +/* * Make a copy of this private key */ Private_Key* copy_key(const Private_Key& key, diff --git a/src/lib/pubkey/pkcs8.h b/src/lib/pubkey/pkcs8.h index ac037407e..9dc5265c7 100644 --- a/src/lib/pubkey/pkcs8.h +++ b/src/lib/pubkey/pkcs8.h @@ -80,50 +80,62 @@ PEM_encode(const Private_Key& key, const std::string& pbe_algo = ""); /** -* Load a key from a data source. +* Load an encrypted key from a data source. * @param source the data source providing the encoded key * @param rng the rng to use * @param get_passphrase a function that returns passphrases * @return loaded private key object */ -BOTAN_DLL Private_Key* load_key( - DataSource& source, - RandomNumberGenerator& rng, - std::function<std::string ()> get_passphrase); +BOTAN_DLL Private_Key* load_key(DataSource& source, + RandomNumberGenerator& rng, + std::function<std::string ()> get_passphrase); -/** Load a key from a data source. +/** Load an encrypted key from a data source. * @param source the data source providing the encoded key * @param rng the rng to use -* @param pass the passphrase to decrypt the key. Provide an empty -* string if the key is not encrypted +* @param pass the passphrase to decrypt the key * @return loaded private key object */ BOTAN_DLL Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, - const std::string& pass = ""); + const std::string& pass); + +/** Load an unencrypted key from a data source. +* @param source the data source providing the encoded key +* @param rng the rng to use +* @return loaded private key object +*/ +BOTAN_DLL Private_Key* load_key(DataSource& source, + RandomNumberGenerator& rng); /** -* Load a key from a file. +* Load an encrypted key from a file. * @param filename the path to the file containing the encoded key * @param rng the rng to use * @param get_passphrase a function that returns passphrases * @return loaded private key object */ -BOTAN_DLL Private_Key* load_key( - const std::string& filename, - RandomNumberGenerator& rng, - std::function<std::string ()> get_passphrase); +BOTAN_DLL Private_Key* load_key(const std::string& filename, + RandomNumberGenerator& rng, + std::function<std::string ()> get_passphrase); -/** Load a key from a file. +/** Load an encrypted key from a file. * @param filename the path to the file containing the encoded key * @param rng the rng to use -* @param pass the passphrase to decrypt the key. Provide an empty -* string if the key is not encrypted +* @param pass the passphrase to decrypt the key * @return loaded private key object */ BOTAN_DLL Private_Key* load_key(const std::string& filename, RandomNumberGenerator& rng, - const std::string& pass = ""); + const std::string& pass); + +/** Load an unencrypted key from a file. +* @param filename the path to the file containing the encoded key +* @param rng the rng to use +* @return loaded private key object +*/ +BOTAN_DLL Private_Key* load_key(const std::string& filename, + RandomNumberGenerator& rng); /** * Copy an existing encoded key object. diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 89d79bec8..648477a1a 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -331,8 +331,6 @@ PK_Key_Generation_Test::test_key(const std::string& algo, const Botan::Private_K result.test_failure("roundtrip PEM private key", e.what()); } - /* - // Currently broken GH #379 try { Botan::DataSource_Memory data_src(Botan::PKCS8::BER_encode(key)); @@ -346,7 +344,6 @@ PK_Key_Generation_Test::test_key(const std::string& algo, const Botan::Private_K { result.test_failure("roundtrip BER private key", e.what()); } - */ const std::string passphrase = Test::random_password(); |