aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRené Korthaus <[email protected]>2016-08-04 10:55:43 +0200
committerRené Korthaus <[email protected]>2016-08-17 20:26:10 +0200
commit422e1891987b4aec7019282a623ebf57c79e7866 (patch)
tree7c143106128b9f574f2d2dbde9a20620531bc61c
parent8d7087066a5343a6f142643cf50d55a7681746a3 (diff)
Fix GH #425 and run x509 tests with different signature algorithms
-rw-r--r--src/lib/cert/x509/key_constraint.cpp35
-rw-r--r--src/lib/cert/x509/key_constraint.h12
-rw-r--r--src/lib/cert/x509/x509_ca.cpp8
-rw-r--r--src/lib/cert/x509/x509_ext.cpp10
-rw-r--r--src/lib/cert/x509/x509cert.cpp7
-rw-r--r--src/tests/unit_x509.cpp135
6 files changed, 134 insertions, 73 deletions
diff --git a/src/lib/cert/x509/key_constraint.cpp b/src/lib/cert/x509/key_constraint.cpp
index 24791b34a..137c42144 100644
--- a/src/lib/cert/x509/key_constraint.cpp
+++ b/src/lib/cert/x509/key_constraint.cpp
@@ -1,45 +1,16 @@
/*
* KeyUsage
* (C) 1999-2007 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/key_constraint.h>
#include <botan/x509_key.h>
-#include <botan/ber_dec.h>
namespace Botan {
-namespace BER {
-
-/*
-* Decode a BER encoded KeyUsage
-*/
-void decode(BER_Decoder& source, Key_Constraints& key_usage)
- {
- BER_Object obj = source.get_next_object();
-
- if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL)
- throw BER_Bad_Tag("Bad tag for usage constraint",
- obj.type_tag, obj.class_tag);
- if(obj.value.size() != 2 && obj.value.size() != 3)
- throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");
- if(obj.value[0] >= 8)
- throw BER_Decoding_Error("Invalid unused bits in usage constraint");
-
- const byte mask = (0xFF << obj.value[0]);
- obj.value[obj.value.size()-1] &= mask;
-
- u16bit usage = 0;
- for(size_t j = 1; j != obj.value.size(); ++j)
- usage = (obj.value[j] << 8) | usage;
-
- key_usage = Key_Constraints(usage);
- }
-
-}
-
/*
* Find the allowable key constraints
*/
@@ -54,10 +25,10 @@ Key_Constraints find_constraints(const Public_Key& pub_key,
constraints |= KEY_AGREEMENT;
if(name == "RSA" || name == "ElGamal")
- constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+ constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT | ENCIPHER_ONLY | DECIPHER_ONLY;
if(name == "RSA" || name == "RW" || name == "NR" ||
- name == "DSA" || name == "ECDSA")
+ name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA")
constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
if(limits)
diff --git a/src/lib/cert/x509/key_constraint.h b/src/lib/cert/x509/key_constraint.h
index 179e413b5..7ae4e26bd 100644
--- a/src/lib/cert/x509/key_constraint.h
+++ b/src/lib/cert/x509/key_constraint.h
@@ -1,6 +1,7 @@
/*
* Enumerations
* (C) 1999-2007 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -8,7 +9,7 @@
#ifndef BOTAN_ENUMS_H__
#define BOTAN_ENUMS_H__
-#include <botan/ber_dec.h>
+#include <botan/build.h>
namespace Botan {
@@ -44,15 +45,6 @@ class Public_Key;
BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
Key_Constraints limits);
-/**
-* BER Decoding Function for key constraints
-*/
-namespace BER {
-
-void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&);
-
-}
-
}
#endif
diff --git a/src/lib/cert/x509/x509_ca.cpp b/src/lib/cert/x509/x509_ca.cpp
index 147fdd6ad..d64ade6cd 100644
--- a/src/lib/cert/x509/x509_ca.cpp
+++ b/src/lib/cert/x509/x509_ca.cpp
@@ -233,11 +233,17 @@ PK_Signer* choose_sig_format(const Private_Key& key,
std::string padding;
if(algo_name == "RSA")
+ {
padding = "EMSA3";
- else if(algo_name == "DSA" || algo_name == "ECDSA" )
+ }
+ else if(algo_name == "DSA" || algo_name == "ECDSA" || algo_name == "ECGDSA" || algo_name == "ECKCDSA")
+ {
padding = "EMSA1";
+ }
else
+ {
throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
+ }
const Signature_Format format = (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363;
diff --git a/src/lib/cert/x509/x509_ext.cpp b/src/lib/cert/x509/x509_ext.cpp
index 986254bc9..650c20d53 100644
--- a/src/lib/cert/x509/x509_ext.cpp
+++ b/src/lib/cert/x509/x509_ext.cpp
@@ -1,6 +1,7 @@
/*
* X.509 Certificate Extensions
* (C) 1999-2010,2012 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -293,7 +294,9 @@ void Key_Usage::decode_inner(const std::vector<byte>& in)
u16bit usage = 0;
for(size_t i = 1; i != obj.value.size(); ++i)
- usage = (obj.value[i] << 8) | usage;
+ {
+ usage = (obj.value[i] << 8*(sizeof(usage)-i)) | usage;
+ }
m_constraints = Key_Constraints(usage);
}
@@ -818,13 +821,12 @@ std::vector<byte> Unknown_Critical_Extension::encode_inner() const
throw Not_Implemented("Unknown_Critical_Extension encoding");
}
-void Unknown_Critical_Extension::decode_inner(const std::vector<byte>& buf)
+void Unknown_Critical_Extension::decode_inner(const std::vector<byte>&)
{
}
-void Unknown_Critical_Extension::contents_to(Data_Store& info, Data_Store&) const
+void Unknown_Critical_Extension::contents_to(Data_Store&, Data_Store&) const
{
- // TODO: textual representation?
}
}
diff --git a/src/lib/cert/x509/x509cert.cpp b/src/lib/cert/x509/x509cert.cpp
index bd3aff6d5..110014f0e 100644
--- a/src/lib/cert/x509/x509cert.cpp
+++ b/src/lib/cert/x509/x509cert.cpp
@@ -1,6 +1,7 @@
/*
* X.509 Certificates
* (C) 1999-2010,2015 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -565,7 +566,7 @@ std::string X509_Certificate::to_string() const
if(constraints & DIGITAL_SIGNATURE)
out << " Digital Signature\n";
if(constraints & NON_REPUDIATION)
- out << " Non-Repuidation\n";
+ out << " Non-Repudiation\n";
if(constraints & KEY_ENCIPHERMENT)
out << " Key Encipherment\n";
if(constraints & DATA_ENCIPHERMENT)
@@ -576,6 +577,10 @@ std::string X509_Certificate::to_string() const
out << " Cert Sign\n";
if(constraints & CRL_SIGN)
out << " CRL Sign\n";
+ if(constraints & ENCIPHER_ONLY)
+ out << " Encipher Only\n";
+ if(constraints & DECIPHER_ONLY)
+ out << " Decipher Only\n";
}
std::vector<std::string> policies = this->policies();
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index 93e26eee2..a024377d8 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -1,5 +1,6 @@
/*
* (C) 2009 Jack Lloyd
+* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -28,6 +29,14 @@
#include <botan/ecdsa.h>
#endif
+#if defined(BOTAN_HAS_ECGDSA)
+ #include <botan/ecgdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKCDSA)
+ #include <botan/eckcdsa.h>
+#endif
+
#endif
namespace Botan_Tests {
@@ -56,7 +65,7 @@ Botan::X509_Cert_Options ca_opts()
return opts;
}
-Botan::X509_Cert_Options req_opts1()
+Botan::X509_Cert_Options req_opts1(const std::string& algo)
{
Botan::X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
@@ -64,6 +73,18 @@ Botan::X509_Cert_Options req_opts1()
opts.dns = "botan.randombit.net";
opts.email = "[email protected]";
+ opts.not_before("1601012000Z");
+ opts.not_after("3001012000Z");
+
+ if(algo == "RSA")
+ {
+ opts.constraints = Botan::Key_Constraints(Botan::DECIPHER_ONLY);
+ }
+ else if(algo == "DSA" || algo == "ECDSA" || algo == "ECGDSA" || algo == "ECKCDSA")
+ {
+ opts.constraints = Botan::Key_Constraints(Botan::DIGITAL_SIGNATURE);
+ }
+
return opts;
}
@@ -80,19 +101,43 @@ Botan::X509_Cert_Options req_opts2()
return opts;
}
-std::unique_ptr<Botan::Private_Key> make_a_private_key()
+std::unique_ptr<Botan::Private_Key> make_a_private_key(const std::string& algo)
{
+#if defined(BOTAN_HAS_RSA)
+ if(algo == "RSA")
+ {
+ return std::unique_ptr<Botan::Private_Key>(new Botan::RSA_PrivateKey(Test::rng(), 1024));
+ }
+#endif
+#if defined(BOTAN_HAS_DSA)
+ if(algo == "DSA")
+ {
+ Botan::DL_Group grp("dsa/botan/2048");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::DSA_PrivateKey(Test::rng(), grp));
+ }
+#endif
#if defined(BOTAN_HAS_ECDSA)
- Botan::EC_Group grp("secp256r1");
- return std::unique_ptr<Botan::Private_Key>(new Botan::ECDSA_PrivateKey(Test::rng(), grp));
-#elif defined(BOTAN_HAS_RSA)
- return std::unique_ptr<Botan::Private_Key>(new Botan::RSA_PrivateKey(Test::rng(), 1024));
-#elif defined(BOTAN_HAS_DSA)
- Botan::DL_Group grp("dsa/botan/2048");
- return std::unique_ptr<Botan::Private_Key>(new Botan::DSA_PrivateKey(Test::rng(), grp));
-#else
- return std::unique_ptr<Botan::Private_Key>(nullptr);
+ if(algo == "ECDSA")
+ {
+ Botan::EC_Group grp("secp256r1");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::ECDSA_PrivateKey(Test::rng(), grp));
+ }
+#endif
+#if defined(BOTAN_HAS_ECGDSA)
+ if(algo == "ECGDSA")
+ {
+ Botan::EC_Group grp("brainpool256r1");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::ECGDSA_PrivateKey(Test::rng(), grp));
+ }
#endif
+#if defined(BOTAN_HAS_ECKCDSA)
+ if(algo == "ECKCDSA")
+ {
+ Botan::EC_Group grp("brainpool256r1");
+ return std::unique_ptr<Botan::Private_Key>(new Botan::ECKCDSA_PrivateKey(Test::rng(), grp));
+ }
+#endif
+ return std::unique_ptr<Botan::Private_Key>(nullptr);
}
class X509_Cert_Unit_Tests : public Test
@@ -207,22 +252,20 @@ class X509_Cert_Unit_Tests : public Test
}
};
-std::vector<Test::Result> X509_Cert_Unit_Tests::run()
+Test::Result test_x509_cert(const std::string& algo)
{
- std::vector<Test::Result> results;
Test::Result result("X509 Unit");
const std::string hash_fn = "SHA-256";
/* Create the CA's key and self-signed cert */
- std::unique_ptr<Botan::Private_Key> ca_key(make_a_private_key());
+ std::unique_ptr<Botan::Private_Key> ca_key(make_a_private_key(algo));
if(!ca_key)
{
- // Failure because X.509 enabled but no RSA or ECDSA seems off
- result.test_failure("Skipping due to no enabled signature algorithms");
- results.push_back(result);
- return results;
+ // Failure because X.509 enabled but requested algorithm is not present
+ result.test_note("Skipping due to missing signature algorithm: " + algo);
+ return result;
}
Botan::X509_Certificate ca_cert =
@@ -231,17 +274,20 @@ std::vector<Test::Result> X509_Cert_Unit_Tests::run()
hash_fn,
Test::rng());
+ result.test_eq("ca key usage", (ca_cert.constraints() & Botan::Key_Constraints(Botan::KEY_CERT_SIGN | Botan::CRL_SIGN)) ==
+ Botan::Key_Constraints(Botan::KEY_CERT_SIGN | Botan::CRL_SIGN), true);
+
/* Create user #1's key and cert request */
- std::unique_ptr<Botan::Private_Key> user1_key(make_a_private_key());
+ std::unique_ptr<Botan::Private_Key> user1_key(make_a_private_key(algo));
Botan::PKCS10_Request user1_req =
- Botan::X509::create_cert_req(req_opts1(),
+ Botan::X509::create_cert_req(req_opts1(algo),
*user1_key,
hash_fn,
Test::rng());
/* Create user #2's key and cert request */
- std::unique_ptr<Botan::Private_Key> user2_key(make_a_private_key());
+ std::unique_ptr<Botan::Private_Key> user2_key(make_a_private_key(algo));
Botan::PKCS10_Request user2_req =
Botan::X509::create_cert_req(req_opts2(),
@@ -258,9 +304,35 @@ std::vector<Test::Result> X509_Cert_Unit_Tests::run()
from_date(2008, 01, 01),
from_date(2033, 01, 01));
- Botan::X509_Certificate user2_cert = ca.sign_request(user2_req, Test::rng(),
- from_date(2008, 01, 01),
- from_date(2033, 01, 01));
+ Botan::X509_Certificate user2_cert =
+ ca.sign_request(user2_req, Test::rng(),
+ from_date(2008, 01, 01),
+ from_date(2033, 01, 01));
+
+ result.test_eq("user1 key usage", (user1_cert.constraints() & req_opts1(algo).constraints) == req_opts1(algo).constraints, true);
+
+ /* Copy, assign and compare */
+ Botan::X509_Certificate user1_cert_copy(user1_cert);
+ result.test_eq("certificate copy", user1_cert == user1_cert_copy, true);
+
+ user1_cert_copy = user1_cert;
+ result.test_eq("certificate assignment", user1_cert == user1_cert_copy, true);
+
+ Botan::X509_Certificate user1_cert_differ =
+ ca.sign_request(user1_req, Test::rng(),
+ from_date(2008, 01, 01),
+ from_date(2032, 01, 01));
+
+ result.test_eq("certificate differs", user1_cert == user1_cert_differ, false);
+
+ /* Get cert data */
+ result.test_eq("x509 version", user1_cert.x509_version(), size_t(3));
+
+ result.test_eq("issuer info CN", user1_cert.issuer_info("CN").at(0), ca_opts().common_name);
+ result.test_eq("issuer info Country", user1_cert.issuer_info("C").at(0), ca_opts().country);
+ result.test_eq("issuer info Orga", user1_cert.issuer_info("O").at(0), ca_opts().organization);
+ result.test_eq("issuer info OrgaUnit", user1_cert.issuer_info("OU").at(0), ca_opts().org_unit);
+
Botan::X509_CRL crl1 = ca.new_crl(Test::rng());
/* Verify the certs */
@@ -316,7 +388,20 @@ std::vector<Test::Result> X509_Cert_Unit_Tests::run()
result_u2 = Botan::x509_path_validate(user2_cert, restrictions, store);
result.test_eq("user 2 still revoked", result_u2.result_string(), revoked_str);
- results.push_back(result);
+ return result;
+ }
+
+std::vector<Test::Result> X509_Cert_Unit_Tests::run()
+ {
+ std::vector<Test::Result> results;
+ const std::vector<std::string> algos { "RSA", "DSA", "ECDSA", "ECGDSA", "ECKCDSA" };
+ Test::Result cert_result("X509 Unit");
+ for(const auto& algo : algos)
+ {
+ cert_result.merge(test_x509_cert(algo));
+ }
+
+ results.push_back(cert_result);
results.push_back(test_x509_dates());
return results;
}