aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-11-09 13:22:52 +0000
committerlloyd <[email protected]>2009-11-09 13:22:52 +0000
commit4049ba134674d78c07c8b0453cb5e5f312469639 (patch)
treeb9214ede8da1600a46560fe061017fa124b2b465
parentb5d4cf01a893718c8796652f3cf0f68b867bab94 (diff)
In creating X.509 certificates and PKCS #10 requests, let (actually: require)
the user to specify the hash function to use, instead of always using SHA-1. This was a sensible default a few years ago, when there wasn't a ~2^60 attack on SHA-1 and support for SHA-2 was pretty much nil, but using something else makes a lot more sense these days.
-rw-r--r--checks/x509.cpp10
-rw-r--r--doc/examples/ca.cpp2
-rw-r--r--doc/examples/gen_certs.cpp6
-rw-r--r--doc/examples/pkcs10.cpp2
-rw-r--r--doc/examples/self_sig.cpp3
-rw-r--r--doc/log.txt1
-rw-r--r--src/cert/x509/x509_ca.cpp52
-rw-r--r--src/cert/x509/x509_ca.h44
-rw-r--r--src/cert/x509/x509self.cpp6
-rw-r--r--src/cert/x509/x509self.h4
10 files changed, 91 insertions, 39 deletions
diff --git a/checks/x509.cpp b/checks/x509.cpp
index 6f191285c..69dd29492 100644
--- a/checks/x509.cpp
+++ b/checks/x509.cpp
@@ -129,6 +129,8 @@ void do_x509_tests(RandomNumberGenerator& rng)
{
std::cout << "Testing X.509 CA/CRL/cert/cert request: " << std::flush;
+ std::string hash_fn = "SHA-256";
+
/* Create the CA's key and self-signed cert */
std::cout << '.' << std::flush;
RSA_PrivateKey ca_key(rng, 1024);
@@ -136,6 +138,7 @@ void do_x509_tests(RandomNumberGenerator& rng)
std::cout << '.' << std::flush;
X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(),
ca_key,
+ hash_fn,
rng);
std::cout << '.' << std::flush;
@@ -146,12 +149,14 @@ void do_x509_tests(RandomNumberGenerator& rng)
std::cout << '.' << std::flush;
PKCS10_Request user1_req = X509::create_cert_req(req_opts1(),
user1_key,
+ "SHA-1",
rng);
/* Create user #2's key and cert request */
std::cout << '.' << std::flush;
#if defined(BOTAN_HAS_ECDSA)
- ECDSA_PrivateKey user2_key(rng, get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ EC_Domain_Params ecc_domain = get_EC_Dom_Pars_by_oid("1.2.840.10045.3.1.7");
+ ECDSA_PrivateKey user2_key(rng, ecc_domain);
#else
RSA_PrivateKey user2_key(rng, 1024);
#endif
@@ -159,11 +164,12 @@ void do_x509_tests(RandomNumberGenerator& rng)
std::cout << '.' << std::flush;
PKCS10_Request user2_req = X509::create_cert_req(req_opts2(),
user2_key,
+ hash_fn,
rng);
/* Create the CA object */
std::cout << '.' << std::flush;
- X509_CA ca(ca_cert, ca_key);
+ X509_CA ca(ca_cert, ca_key, hash_fn);
std::cout << '.' << std::flush;
/* Sign the requests to create the certs */
diff --git a/doc/examples/ca.cpp b/doc/examples/ca.cpp
index 41dd409d5..9195be418 100644
--- a/doc/examples/ca.cpp
+++ b/doc/examples/ca.cpp
@@ -47,7 +47,7 @@ int main(int argc, char* argv[])
PKCS8::load_key(arg_ca_key, rng, arg_passphrase)
);
- X509_CA ca(ca_cert, *privkey);
+ X509_CA ca(ca_cert, *privkey, "SHA-256");
// got a request
PKCS10_Request req(arg_req_file);
diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp
index f635e1ccf..90cb80038 100644
--- a/doc/examples/gen_certs.cpp
+++ b/doc/examples/gen_certs.cpp
@@ -34,7 +34,7 @@ X509_Certificate make_ca_cert(RandomNumberGenerator& rng,
opts.end = later;
opts.CA_key();
- return X509::create_self_signed_cert(opts, priv_key, rng);
+ return X509::create_self_signed_cert(opts, priv_key, "SHA-256", rng);
}
PKCS10_Request make_server_cert_req(const Private_Key& key,
@@ -47,7 +47,7 @@ PKCS10_Request make_server_cert_req(const Private_Key& key,
opts.add_ex_constraint("PKIX.ServerAuth");
- return X509::create_cert_req(opts, key, rng);
+ return X509::create_cert_req(opts, key, "SHA-1", rng);
}
void save_pair(const std::string& name,
@@ -92,7 +92,7 @@ int main()
save_pair("ca", ca_password, ca_cert, ca_key, rng);
- X509_CA ca(ca_cert, ca_key);
+ X509_CA ca(ca_cert, ca_key, "SHA-256");
RSA_PrivateKey httpd_key(rng, 1536);
X509_Certificate httpd_cert = ca.sign_request(
diff --git a/doc/examples/pkcs10.cpp b/doc/examples/pkcs10.cpp
index d719baf72..d9fa9accb 100644
--- a/doc/examples/pkcs10.cpp
+++ b/doc/examples/pkcs10.cpp
@@ -59,7 +59,7 @@ int main(int argc, char* argv[])
opts.xmpp = "[email protected]";
- PKCS10_Request req = X509::create_cert_req(opts, priv_key, rng);
+ PKCS10_Request req = X509::create_cert_req(opts, priv_key, "SHA-1", rng);
std::ofstream req_file("req.pem");
req_file << req.PEM_encode();
diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp
index 0bf17e3bc..93161f7d2 100644
--- a/doc/examples/self_sig.cpp
+++ b/doc/examples/self_sig.cpp
@@ -64,7 +64,8 @@ int main(int argc, char* argv[])
if(do_CA)
opts.CA_key();
- X509_Certificate cert = X509::create_self_signed_cert(opts, key, rng);
+ X509_Certificate cert =
+ X509::create_self_signed_cert(opts, key, "SHA-256", rng);
std::ofstream cert_file("cert.pem");
cert_file << cert.PEM_encode();
diff --git a/doc/log.txt b/doc/log.txt
index 75fde9a5f..f1c58be71 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -1,5 +1,6 @@
* 1.9.3-dev, ????-??-??
+ - Allow use of any hash function in X.509 certificate creation
- Set macros for available SIMD instructions in build.h
* 1.9.2, 2009-11-03
diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp
index f0eb9c3e5..48ec0bd1c 100644
--- a/src/cert/x509/x509_ca.cpp
+++ b/src/cert/x509/x509_ca.cpp
@@ -9,9 +9,10 @@
#include <botan/x509stor.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
-#include <botan/look_pk.h>
#include <botan/bigint.h>
#include <botan/parsing.h>
+#include <botan/lookup.h>
+#include <botan/look_pk.h>
#include <botan/oids.h>
#include <botan/timer.h>
#include <algorithm>
@@ -20,22 +21,33 @@
#include <memory>
#include <set>
+#include <stdio.h>
+
namespace Botan {
/*
* Load the certificate and private key
*/
X509_CA::X509_CA(const X509_Certificate& c,
- const Private_Key& key) : cert(c)
+ const Private_Key& key,
+ const std::string& hash_fn) : cert(c)
{
- const Private_Key* key_pointer = &key;
- if(!dynamic_cast<const PK_Signing_Key*>(key_pointer))
+ // Use pointer dynamic_cast to avoid exception if cast fails
+ if(!dynamic_cast<const PK_Signing_Key*>(&key))
throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign");
if(!cert.is_CA_cert())
throw Invalid_Argument("X509_CA: This certificate is not for a CA");
- signer = choose_sig_format(key, ca_sig_algo);
+ signer = choose_sig_format(key, hash_fn, ca_sig_algo);
+ }
+
+/*
+* X509_CA Destructor
+*/
+X509_CA::~X509_CA()
+ {
+ delete signer;
}
/*
@@ -70,7 +82,8 @@ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
extensions.add(
new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name()));
- return make_cert(signer, rng, ca_sig_algo, req.raw_public_key(),
+ return make_cert(signer, rng, ca_sig_algo,
+ req.raw_public_key(),
not_before, not_after,
cert.subject_dn(), req.subject_dn(),
extensions);
@@ -231,17 +244,10 @@ X509_Certificate X509_CA::ca_certificate() const
}
/*
-* X509_CA Destructor
-*/
-X509_CA::~X509_CA()
- {
- delete signer;
- }
-
-/*
* Choose a signing format for the key
*/
PK_Signer* choose_sig_format(const Private_Key& key,
+ const std::string& hash_fn,
AlgorithmIdentifier& sig_algo)
{
std::string padding;
@@ -249,24 +255,36 @@ PK_Signer* choose_sig_format(const Private_Key& key,
const std::string algo_name = key.algo_name();
+ const HashFunction* proto_hash = retrieve_hash(hash_fn);
+ if(!proto_hash)
+ throw Algorithm_Not_Found(hash_fn);
+
+ if(key.max_input_bits() < proto_hash->OUTPUT_LENGTH*8)
+ {
+ printf("%d %d\n", key.max_input_bits(), proto_hash->OUTPUT_LENGTH*8);
+ throw Invalid_Argument("Key is too small for chosen hash function");
+ }
+
if(algo_name == "RSA")
{
- padding = "EMSA3(SHA-160)";
+ padding = "EMSA3";
format = IEEE_1363;
}
else if(algo_name == "DSA")
{
- padding = "EMSA1(SHA-160)";
+ padding = "EMSA1";
format = DER_SEQUENCE;
}
else if(algo_name == "ECDSA")
{
- padding = "EMSA1_BSI(SHA-160)";
+ padding = "EMSA1_BSI";
format = IEEE_1363;
}
else
throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
+ padding = padding + '(' + proto_hash->name() + ')';
+
sig_algo.oid = OIDS::lookup(algo_name + "/" + padding);
std::auto_ptr<X509_Encoder> encoding(key.x509_encoder());
diff --git a/src/cert/x509/x509_ca.h b/src/cert/x509/x509_ca.h
index ef2a8d134..6eb4bbbef 100644
--- a/src/cert/x509/x509_ca.h
+++ b/src/cert/x509/x509_ca.h
@@ -50,7 +50,8 @@ class BOTAN_DLL X509_CA
* as the offset from the current time
* @return the new CRL
*/
- X509_CRL new_crl(RandomNumberGenerator& rng, u32bit = 0) const;
+ X509_CRL new_crl(RandomNumberGenerator& rng,
+ u32bit next_update = 0) const;
/**
* Create a new CRL by with additional entries.
@@ -65,27 +66,45 @@ class BOTAN_DLL X509_CA
RandomNumberGenerator& rng,
u32bit next_update = 0) const;
- static X509_Certificate make_cert(PK_Signer*,
- RandomNumberGenerator&,
- const AlgorithmIdentifier&,
- const MemoryRegion<byte>&,
- const X509_Time&, const X509_Time&,
- const X509_DN&, const X509_DN&,
- const Extensions&);
+ /**
+ * Interface for creating new certificates
+ * @param signer a signing object
+ * @param rng a random number generator
+ * @param sig_algo the signature algorithm identifier
+ * @param not_before the start time of the certificate
+ * @param not_after the end time of the certificate
+ * @param issuer_dn the DN of the issuer
+ * @param subject_dn the DN of the subject
+ * @param extensions an optional list of certificate extensions
+ * @returns newly minted certificate
+ */
+ static X509_Certificate make_cert(PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& sig_algo,
+ const MemoryRegion<byte>& pub_key,
+ const X509_Time& not_before,
+ const X509_Time& not_after,
+ const X509_DN& issuer_dn,
+ const X509_DN& subject_dn,
+ const Extensions& extensions);
/**
* Create a new CA object.
* @param ca_certificate the certificate of the CA
* @param key the private key of the CA
*/
- X509_CA(const X509_Certificate& ca_certificate, const Private_Key& key);
+ X509_CA(const X509_Certificate& ca_certificate,
+ const Private_Key& key,
+ const std::string& hash_fn);
+
~X509_CA();
private:
X509_CA(const X509_CA&) {}
X509_CA& operator=(const X509_CA&) { return (*this); }
- X509_CRL make_crl(const std::vector<CRL_Entry>&,
- u32bit, u32bit, RandomNumberGenerator&) const;
+ X509_CRL make_crl(const std::vector<CRL_Entry>& entries,
+ u32bit crl_number, u32bit next_update,
+ RandomNumberGenerator& rng) const;
AlgorithmIdentifier ca_sig_algo;
X509_Certificate cert;
@@ -96,13 +115,14 @@ class BOTAN_DLL X509_CA
* Choose the default signature format for a certain public key signature
* scheme.
* @param key will be the key to choose a padding scheme for
+* @param hash_fn is the desired hash function
* @param alg_id will be set to the chosen scheme
* @return A PK_Signer object for generating signatures
*/
BOTAN_DLL PK_Signer* choose_sig_format(const Private_Key& key,
+ const std::string& hash_fn,
AlgorithmIdentifier& alg_id);
-
}
#endif
diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp
index 8afb22a7e..f915c6ff5 100644
--- a/src/cert/x509/x509self.cpp
+++ b/src/cert/x509/x509self.cpp
@@ -65,6 +65,7 @@ namespace X509 {
*/
X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
const Private_Key& key,
+ const std::string& hash_fn,
RandomNumberGenerator& rng)
{
AlgorithmIdentifier sig_algo;
@@ -72,7 +73,7 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
AlternativeName subject_alt;
MemoryVector<byte> pub_key = shared_setup(opts, key);
- std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+ std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
load_info(opts, subject_dn, subject_alt);
Key_Constraints constraints;
@@ -103,6 +104,7 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
*/
PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
const Private_Key& key,
+ const std::string& hash_fn,
RandomNumberGenerator& rng)
{
AlgorithmIdentifier sig_algo;
@@ -110,7 +112,7 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
AlternativeName subject_alt;
MemoryVector<byte> pub_key = shared_setup(opts, key);
- std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+ std::auto_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
load_info(opts, subject_dn, subject_alt);
const u32bit PKCS10_VERSION = 0;
diff --git a/src/cert/x509/x509self.h b/src/cert/x509/x509self.h
index bd3e29179..741350067 100644
--- a/src/cert/x509/x509self.h
+++ b/src/cert/x509/x509self.h
@@ -172,12 +172,14 @@ namespace X509 {
* @param opts the options defining the certificate to create
* @param key the private key used for signing, i.e. the key
* associated with this self-signed certificate
+* @param hash_fn the hash function to use
* @param rng the rng to use
* @return the newly created self-signed certificate
*/
BOTAN_DLL X509_Certificate
create_self_signed_cert(const X509_Cert_Options& opts,
const Private_Key& key,
+ const std::string& hash_fn,
RandomNumberGenerator& rng);
/**
@@ -185,10 +187,12 @@ create_self_signed_cert(const X509_Cert_Options& opts,
* @param opts the options defining the request to create
* @param key the key used to sign this request
* @param rng the rng to use
+* @param hash_fn the hash function to use
* @return the newly created PKCS#10 request
*/
BOTAN_DLL PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
const Private_Key& key,
+ const std::string& hash_fn,
RandomNumberGenerator& rng);
}