aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/cert/x509
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-08-19 16:03:40 -0400
committerJack Lloyd <[email protected]>2016-08-19 16:03:40 -0400
commit165a21393f0061a6f3c68b9244a20b41c16c2a78 (patch)
treeff78cfd1907d0a208c0bb42b73622b0310172633 /src/lib/cert/x509
parentf26dfb3572aaab003e0c80002615d190488fb613 (diff)
parent6cbff45093199d821dee7ee74380474300f49948 (diff)
Merge GH #591
Change behavior of default key usage encoding, default now omits the key usage unless the user set a value. Fix allowed_usage which could produce incorrect results. More X.509 tests
Diffstat (limited to 'src/lib/cert/x509')
-rw-r--r--src/lib/cert/x509/key_constraint.cpp63
-rw-r--r--src/lib/cert/x509/key_constraint.h28
-rw-r--r--src/lib/cert/x509/x509_ca.cpp18
-rw-r--r--src/lib/cert/x509/x509_ext.cpp10
-rw-r--r--src/lib/cert/x509/x509cert.cpp9
-rw-r--r--src/lib/cert/x509/x509self.cpp35
6 files changed, 83 insertions, 80 deletions
diff --git a/src/lib/cert/x509/key_constraint.cpp b/src/lib/cert/x509/key_constraint.cpp
index 24791b34a..a90af013c 100644
--- a/src/lib/cert/x509/key_constraint.cpp
+++ b/src/lib/cert/x509/key_constraint.cpp
@@ -1,69 +1,46 @@
/*
* 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
+* Make sure the given key constraints are permitted for the given key type
*/
-Key_Constraints find_constraints(const Public_Key& pub_key,
- Key_Constraints limits)
+void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
+ Key_Constraints constraints)
{
const std::string name = pub_key.algo_name();
- size_t constraints = 0;
+ size_t permitted = 0;
if(name == "DH" || name == "ECDH")
- constraints |= KEY_AGREEMENT;
+ {
+ permitted |= KEY_AGREEMENT | ENCIPHER_ONLY | DECIPHER_ONLY;
+ }
if(name == "RSA" || name == "ElGamal")
- constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+ {
+ permitted |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+ }
if(name == "RSA" || name == "RW" || name == "NR" ||
- name == "DSA" || name == "ECDSA")
- constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
-
- if(limits)
- constraints &= limits;
-
- return Key_Constraints(constraints);
+ name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA")
+ {
+ permitted |= DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_CERT_SIGN | CRL_SIGN;
+ }
+
+ if ( ( constraints & permitted ) != constraints )
+ {
+ throw Exception("Constraint not permitted for key type " + name);
+ }
}
}
diff --git a/src/lib/cert/x509/key_constraint.h b/src/lib/cert/x509/key_constraint.h
index 179e413b5..b67eb7010 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 {
@@ -32,26 +33,13 @@ enum Key_Constraints {
class Public_Key;
/**
-* Create the key constraints for a specific public key.
-* @param pub_key the public key from which the basic set of
-* constraints to be placed in the return value is derived
-* @param limits additional limits that will be incorporated into the
-* return value
-* @return combination of key type specific constraints and
-* additional limits
+* Check that key constraints are permitted for a specific public key.
+* @param pub_key the public key on which the constraints shall be enforced on
+* @param constrains the constraints that shall be enforced on the key
+* @throw Exception if the given constraints are not permitted for this 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&);
-
-}
+BOTAN_DLL void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
+ Key_Constraints constraints);
}
diff --git a/src/lib/cert/x509/x509_ca.cpp b/src/lib/cert/x509/x509_ca.cpp
index 147fdd6ad..58c6676f4 100644
--- a/src/lib/cert/x509/x509_ca.cpp
+++ b/src/lib/cert/x509/x509_ca.cpp
@@ -52,11 +52,14 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
{
Key_Constraints constraints;
if(req.is_CA())
+ {
constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
+ }
else
{
std::unique_ptr<Public_Key> key(req.subject_public_key());
- constraints = find_constraints(*key, req.constraints());
+ verify_cert_constraints_valid_for_key_type(*key, req.constraints());
+ constraints = req.constraints();
}
Extensions extensions;
@@ -65,7 +68,10 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()),
true);
- extensions.add(new Cert_Extension::Key_Usage(constraints), true);
+ if(constraints != NO_CONSTRAINTS)
+ {
+ extensions.add(new Cert_Extension::Key_Usage(constraints), true);
+ }
extensions.add(new Cert_Extension::Authority_Key_ID(m_cert.subject_key_id()));
extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key()));
@@ -233,11 +239,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..20a4bca25 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)
*/
@@ -257,7 +258,7 @@ bool X509_Certificate::allowed_usage(Key_Constraints usage) const
{
if(constraints() == NO_CONSTRAINTS)
return true;
- return ((constraints() & usage) != 0);
+ return ((constraints() & usage) == usage);
}
bool X509_Certificate::allowed_extended_usage(const std::string& usage) const
@@ -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/lib/cert/x509/x509self.cpp b/src/lib/cert/x509/x509self.cpp
index 8b9aeda09..102e24f77 100644
--- a/src/lib/cert/x509/x509self.cpp
+++ b/src/lib/cert/x509/x509self.cpp
@@ -55,9 +55,14 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
Key_Constraints constraints;
if(opts.is_CA)
+ {
constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
+ }
else
- constraints = find_constraints(key, opts.constraints);
+ {
+ verify_cert_constraints_valid_for_key_type(key, opts.constraints);
+ constraints = opts.constraints;
+ }
Extensions extensions;
@@ -65,7 +70,10 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit),
true);
- extensions.add(new Cert_Extension::Key_Usage(constraints), true);
+ if(constraints != NO_CONSTRAINTS)
+ {
+ extensions.add(new Cert_Extension::Key_Usage(constraints), true);
+ }
extensions.add(new Cert_Extension::Subject_Key_ID(pub_key));
@@ -99,16 +107,27 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
const size_t PKCS10_VERSION = 0;
+ Key_Constraints constraints;
+ if(opts.is_CA)
+ {
+ constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
+ }
+ else
+ {
+ verify_cert_constraints_valid_for_key_type(key, opts.constraints);
+ constraints = opts.constraints;
+ }
+
Extensions extensions;
extensions.add(
new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit));
- extensions.add(
- new Cert_Extension::Key_Usage(
- opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) :
- find_constraints(key, opts.constraints)
- )
- );
+
+ if(constraints != NO_CONSTRAINTS)
+ {
+ extensions.add(
+ new Cert_Extension::Key_Usage(constraints));
+ }
extensions.add(
new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
extensions.add(