aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-18 15:18:13 -0500
committerJack Lloyd <[email protected]>2016-11-18 15:18:13 -0500
commit7c522b481ac2adc441335812062cd1e06daa42af (patch)
treeb89a50dff9011de26fe74e4ad3d2578c8358de94 /src
parenteb59bf8c33ed4dbb3990351954bfb7112e6cf273 (diff)
Add key_constraints_to_string, GOST-34.10 cert handling
Add some try/catch blocks to the X.509 tests, and use create_private_key API
Diffstat (limited to 'src')
-rw-r--r--src/build-data/oids.txt2
-rw-r--r--src/lib/asn1/oids.cpp4
-rw-r--r--src/lib/x509/key_constraint.cpp60
-rw-r--r--src/lib/x509/key_constraint.h3
-rw-r--r--src/lib/x509/x509_ca.cpp6
-rw-r--r--src/tests/unit_x509.cpp127
6 files changed, 127 insertions, 75 deletions
diff --git a/src/build-data/oids.txt b/src/build-data/oids.txt
index b59e0a05e..4a42ff9ca 100644
--- a/src/build-data/oids.txt
+++ b/src/build-data/oids.txt
@@ -143,6 +143,8 @@
1.2.643.2.2.3 = GOST-34.10/EMSA1(GOST-R-34.11-94)
+1.3.6.1.4.1.25258.1.6.1 = GOST-34.10/EMSA1(SHA-256)
+
# DN
[dn]
2.5.4.3 = X520.CommonName
diff --git a/src/lib/asn1/oids.cpp b/src/lib/asn1/oids.cpp
index 88752bc4d..2f7597981 100644
--- a/src/lib/asn1/oids.cpp
+++ b/src/lib/asn1/oids.cpp
@@ -1,7 +1,7 @@
/*
* OID maps
*
-* This file was automatically generated by ./src/scripts/oids.py on 2016-11-17
+* This file was automatically generated by ./src/scripts/oids.py on 2016-11-18
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -99,6 +99,7 @@ std::string lookup(const OID& oid)
if(oid_str == "1.3.6.1.4.1.25258.1.3") return "McEliece";
if(oid_str == "1.3.6.1.4.1.25258.1.4") return "Curve25519";
if(oid_str == "1.3.6.1.4.1.25258.1.5") return "XMSS";
+ if(oid_str == "1.3.6.1.4.1.25258.1.6.1") return "GOST-34.10/EMSA1(SHA-256)";
if(oid_str == "1.3.6.1.4.1.25258.3.1") return "Serpent/CBC";
if(oid_str == "1.3.6.1.4.1.25258.3.101") return "Serpent/GCM";
if(oid_str == "1.3.6.1.4.1.25258.3.102") return "Twofish/GCM";
@@ -257,6 +258,7 @@ OID lookup(const std::string& name)
if(name == "ElGamal") return OID("1.3.6.1.4.1.3029.1.2.1");
if(name == "GOST-34.10") return OID("1.2.643.2.2.19");
if(name == "GOST-34.10/EMSA1(GOST-R-34.11-94)") return OID("1.2.643.2.2.3");
+ if(name == "GOST-34.10/EMSA1(SHA-256)") return OID("1.3.6.1.4.1.25258.1.6.1");
if(name == "HMAC(SHA-160)") return OID("1.2.840.113549.2.7");
if(name == "HMAC(SHA-224)") return OID("1.2.840.113549.2.8");
if(name == "HMAC(SHA-256)") return OID("1.2.840.113549.2.9");
diff --git a/src/lib/x509/key_constraint.cpp b/src/lib/x509/key_constraint.cpp
index 30d1cb3b8..a39747f9a 100644
--- a/src/lib/x509/key_constraint.cpp
+++ b/src/lib/x509/key_constraint.cpp
@@ -1,6 +1,6 @@
/*
* KeyUsage
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2016 Jack Lloyd
* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -11,6 +11,58 @@
namespace Botan {
+std::string key_constraints_to_string(Key_Constraints constraints)
+ {
+ std::vector<std::string> str;
+
+ if(constraints == NO_CONSTRAINTS)
+ return "no_constraints";
+
+ if(constraints & DIGITAL_SIGNATURE)
+ str.push_back("digital_signature");
+
+ if(constraints & NON_REPUDIATION)
+ str.push_back("non_repudiation");
+
+ if(constraints & KEY_ENCIPHERMENT)
+ str.push_back("key_encipherment");
+
+ if(constraints & DATA_ENCIPHERMENT)
+ str.push_back("data_encipherment");
+
+ if(constraints & KEY_AGREEMENT)
+ str.push_back("key_agreement");
+
+ if(constraints & KEY_CERT_SIGN)
+ str.push_back("key_cert_sign");
+
+ if(constraints & CRL_SIGN)
+ str.push_back("crl_sign");
+
+ if(constraints & ENCIPHER_ONLY)
+ str.push_back("encipher_only");
+
+ if(constraints & DECIPHER_ONLY)
+ str.push_back("decipher_only");
+
+ // Not 0 (checked at start) but nothing matched above!
+ if(str.empty())
+ return "other_unknown_constraints";
+
+ if(str.size() == 1)
+ return str[0];
+
+ std::string out;
+ for(size_t i = 0; i < str.size() - 1; ++i)
+ {
+ out += str[i];
+ out += ',';
+ }
+ out += str[str.size() - 1];
+
+ return out;
+ }
+
/*
* Make sure the given key constraints are permitted for the given key type
*/
@@ -31,14 +83,14 @@ void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
permitted |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
}
- if(name == "RSA" || name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA")
+ if(name == "RSA" || name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA" || name == "GOST-34.10")
{
permitted |= DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_CERT_SIGN | CRL_SIGN;
}
- if ( ( constraints & permitted ) != constraints )
+ if((constraints & permitted) != constraints)
{
- throw Exception("Constraint not permitted for key type " + name);
+ throw Exception("Invalid " + name + " constraints " + key_constraints_to_string(constraints));
}
}
diff --git a/src/lib/x509/key_constraint.h b/src/lib/x509/key_constraint.h
index 02c65acec..1158a4772 100644
--- a/src/lib/x509/key_constraint.h
+++ b/src/lib/x509/key_constraint.h
@@ -10,6 +10,7 @@
#define BOTAN_ENUMS_H__
#include <botan/build.h>
+#include <string>
namespace Botan {
@@ -41,6 +42,8 @@ class Public_Key;
BOTAN_DLL void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
Key_Constraints constraints);
+std::string BOTAN_DLL key_constraints_to_string(Key_Constraints);
+
}
#endif
diff --git a/src/lib/x509/x509_ca.cpp b/src/lib/x509/x509_ca.cpp
index f7f5471f4..6aba7311c 100644
--- a/src/lib/x509/x509_ca.cpp
+++ b/src/lib/x509/x509_ca.cpp
@@ -239,7 +239,11 @@ PK_Signer* choose_sig_format(const Private_Key& key,
{
padding = "EMSA3";
}
- else if(algo_name == "DSA" || algo_name == "ECDSA" || algo_name == "ECGDSA" || algo_name == "ECKCDSA")
+ else if(algo_name == "DSA" ||
+ algo_name == "ECDSA" ||
+ algo_name == "ECGDSA" ||
+ algo_name == "ECKCDSA" ||
+ algo_name == "GOST-34.10")
{
padding = "EMSA1";
}
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index d08fe96fe..ae860067c 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -16,26 +16,7 @@
#include <botan/x509self.h>
#include <botan/x509path.h>
#include <botan/x509_ca.h>
-
-#if defined(BOTAN_HAS_RSA)
- #include <botan/rsa.h>
-#endif
-
-#if defined(BOTAN_HAS_DSA)
- #include <botan/dsa.h>
-#endif
-
-#if defined(BOTAN_HAS_ECDSA)
- #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
+#include <botan/pk_algs.h>
#endif
@@ -103,41 +84,17 @@ Botan::X509_Cert_Options req_opts2()
std::unique_ptr<Botan::Private_Key> make_a_private_key(const std::string& algo)
{
-#if defined(BOTAN_HAS_RSA)
+ std::string params = ""; // default "" means choose acceptable algo-specific params
+
+ // Here we override defaults as needed
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)
- 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);
+ params = "1024";
+ if(algo == "GOST-34.10")
+ params = "gost_256A";
+ if(algo == "ECKCDSA" || algo == "ECGDSA")
+ params = "brainpool256r1";
+
+ return Botan::create_private_key(algo, Test::rng(), params);
}
@@ -302,6 +259,13 @@ Test::Result test_x509_cert(const std::string& sig_algo, const std::string& hash
from_date(2008, 01, 01),
from_date(2033, 01, 01));
+ // user#1 creates a self-signed cert on the side
+ Botan::X509_Certificate user1_ss_cert =
+ Botan::X509::create_self_signed_cert(req_opts1(sig_algo),
+ *user1_key,
+ hash_fn,
+ Test::rng());
+
result.test_eq("user1 key usage", (user1_cert.constraints() & req_opts1(sig_algo).constraints) == req_opts1(sig_algo).constraints, true);
/* Copy, assign and compare */
@@ -329,11 +293,16 @@ Test::Result test_x509_cert(const std::string& sig_algo, const std::string& hash
Botan::X509_CRL crl1 = ca.new_crl(Test::rng());
/* Verify the certs */
+ Botan::Path_Validation_Restrictions restrictions(false);
Botan::Certificate_Store_In_Memory store;
- store.add_certificate(ca.ca_certificate());
+ // First try with an empty store
+ Botan::Path_Validation_Result result_no_issuer = Botan::x509_path_validate(user1_cert, restrictions, store);
+ result.test_eq("user 1 issuer not found",
+ result_no_issuer.result_string(),
+ Botan::Path_Validation_Result::status_string(Botan::Certificate_Status_Code::CERT_ISSUER_NOT_FOUND));
- Botan::Path_Validation_Restrictions restrictions(false);
+ store.add_certificate(ca.ca_certificate());
Botan::Path_Validation_Result result_u1 = Botan::x509_path_validate(user1_cert, restrictions, store);
if(!result.confirm("user 1 validates", result_u1.successful_validation()))
@@ -347,6 +316,10 @@ Test::Result test_x509_cert(const std::string& sig_algo, const std::string& hash
result.test_note("user 2 validation result was " + result_u2.result_string());
}
+ Botan::Path_Validation_Result result_self_signed = Botan::x509_path_validate(user1_ss_cert, restrictions, store);
+ result.test_eq("user 1 issuer not found",
+ result_no_issuer.result_string(),
+ Botan::Path_Validation_Result::status_string(Botan::Certificate_Status_Code::CERT_ISSUER_NOT_FOUND));
store.add_crl(crl1);
std::vector<Botan::CRL_Entry> revoked;
@@ -632,12 +605,8 @@ Test::Result test_valid_constraints(const std::string& pk_algo)
result.test_throws("cert sign not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
typical_usage.ca); });
- verify_cert_constraints_valid_for_key_type(*key, typical_usage.non_repudiation);
-
- result.test_throws("key encipherment not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
- typical_usage.key_encipherment); });
- result.test_throws("data encipherment not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
- typical_usage.data_encipherment); });
+ verify_cert_constraints_valid_for_key_type(*key, typical_usage.data_encipherment);
+ verify_cert_constraints_valid_for_key_type(*key, typical_usage.key_encipherment);
result.test_throws("key agreement not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
typical_usage.key_agreement); });
@@ -650,8 +619,7 @@ Test::Result test_valid_constraints(const std::string& pk_algo)
result.test_throws("sign, cert sign, crl sign not permitted not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
typical_usage.sign_everything); });
}
- else if(pk_algo == "RW" || pk_algo == "NR" || pk_algo == "DSA" ||
- pk_algo == "ECDSA" || pk_algo == "ECGDSA" || pk_algo == "ECKCDSA")
+ else if(pk_algo == "DSA" || pk_algo == "ECDSA" || pk_algo == "ECGDSA" || pk_algo == "ECKCDSA" || pk_algo == "GOST-34.10")
{
// these are signature algorithms only
result.test_throws("all constraints not permitted", [&key, &typical_usage]() { verify_cert_constraints_valid_for_key_type(*key,
@@ -686,23 +654,44 @@ class X509_Cert_Unit_Tests : public Test
std::vector<Test::Result> run() override
{
std::vector<Test::Result> results;
- const std::vector<std::string> sig_algos { "RSA", "DSA", "ECDSA", "ECGDSA", "ECKCDSA" };
+
+ const std::vector<std::string> sig_algos { "RSA", "DSA", "ECDSA", "ECGDSA", "ECKCDSA", "GOST-34.10" };
Test::Result cert_result("X509 Unit");
Test::Result usage_result("X509 Usage");
Test::Result self_issued_result("X509 Self Issued");
for(const auto& algo : sig_algos)
{
- cert_result.merge(test_x509_cert(algo));
- usage_result.merge(test_usage(algo));
- self_issued_result.merge(test_self_issued(algo));
+ try {
+ cert_result.merge(test_x509_cert(algo));
+ }
+ catch(std::exception& e)
+ {
+ cert_result.test_failure("test_x509_cert " + algo, e.what());
+ }
+
+ try {
+ usage_result.merge(test_usage(algo));
+ }
+ catch(std::exception& e)
+ {
+ usage_result.test_failure("test_usage " + algo, e.what());
+ }
+
+ try {
+ self_issued_result.merge(test_self_issued(algo));
+ }
+ catch(std::exception& e)
+ {
+ self_issued_result.test_failure("test_self_issued " + algo, e.what());
+ }
}
results.push_back(cert_result);
results.push_back(usage_result);
results.push_back(self_issued_result);
- const std::vector<std::string> pk_algos { "DH", "ECDH", "RSA", "ElGamal", "RW", "NR",
+ const std::vector<std::string> pk_algos { "DH", "ECDH", "RSA", "ElGamal", "GOST-34.10",
"DSA", "ECDSA", "ECGDSA", "ECKCDSA" };
Test::Result valid_constraints_result("X509 Valid Constraints");