aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenĂ© Korthaus <[email protected]>2015-12-25 13:46:09 +0100
committerRenĂ© Korthaus <[email protected]>2015-12-25 13:46:09 +0100
commit50b3cce52d5a02c5c3d039dc792edcc7bb7ee7dc (patch)
treeeb47191591434d555d94a27a1eb8683e4541aafb
parent20e7a430425f20c939e872c932c29330f8db5422 (diff)
Fix loading of unencrypted, BER encoded private keys via PKCS8 api
-rw-r--r--src/lib/pubkey/pkcs8.cpp82
-rw-r--r--src/lib/pubkey/pkcs8.h48
-rw-r--r--src/tests/test_pubkey.cpp3
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();