diff options
author | Jack Lloyd <[email protected]> | 2015-12-31 15:42:20 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-12-31 15:42:20 -0500 |
commit | d8b53e9acb370ba9c2f13ef9909e650b24134612 (patch) | |
tree | 284fa6c7dd08edb854237c6950b934c6c8f128f2 /src | |
parent | b42fc5375d5747e98930841a695302f625595dd7 (diff) | |
parent | 50b3cce52d5a02c5c3d039dc792edcc7bb7ee7dc (diff) |
Merge pull request #381 from cordney/fix-load-unencryped-key-from-ber
Fix loading of unencrypted, BER encoded private keys via PKCS8 api
Diffstat (limited to 'src')
-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 4521717e9..70712601d 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -371,8 +371,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)); @@ -386,7 +384,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(); |