Skip to content
Snippets Groups Projects
Commit 197aaa47 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

crypto: prevent duplicate CRLs, reimport after signing

parent ad234004
No related branches found
No related tags found
No related merge requests found
...@@ -161,6 +161,70 @@ private: ...@@ -161,6 +161,70 @@ private:
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length); //friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
}; };
class OPENDHT_PUBLIC RevocationList
{
using clock = std::chrono::system_clock;
using time_point = clock::time_point;
using duration = clock::duration;
public:
RevocationList();
RevocationList(const Blob& b);
RevocationList(RevocationList&& o) : crl(o.crl) { o.crl = nullptr; }
~RevocationList();
RevocationList& operator=(RevocationList&& o) { crl = o.crl; o.crl = nullptr; return *this; }
void pack(Blob& b) const;
void unpack(const uint8_t* dat, size_t dat_size);
Blob getPacked() const {
Blob b;
pack(b);
return b;
}
template <typename Packer>
void msgpack_pack(Packer& p) const
{
Blob b = getPacked();
p.pack_bin(b.size());
p.pack_bin_body((const char*)b.data(), b.size());
}
void msgpack_unpack(msgpack::object o);
void revoke(const Certificate& crt, time_point t = time_point::min());
bool isRevoked(const Certificate& crt) const;
/**
* Sign this revocation list using provided key and certificate.
* Validity_period sets the duration until next update (default to no next update).
*/
void sign(const PrivateKey&, const Certificate&, duration validity_period = {});
void sign(const Identity& id) { sign(*id.first, *id.second); }
bool isSignedBy(const Certificate& issuer) const;
std::string toString() const;
/**
* Read the CRL number extension field.
*/
Blob getNumber() const;
time_point getUpdateTime() const;
time_point getNextUpdateTime() const;
gnutls_x509_crl_t get() { return crl; }
private:
gnutls_x509_crl_t crl {};
RevocationList(const RevocationList&) = delete;
RevocationList& operator=(const RevocationList&) = delete;
};
struct OPENDHT_PUBLIC Certificate { struct OPENDHT_PUBLIC Certificate {
Certificate() {} Certificate() {}
...@@ -325,67 +389,14 @@ struct OPENDHT_PUBLIC Certificate { ...@@ -325,67 +389,14 @@ struct OPENDHT_PUBLIC Certificate {
private: private:
Certificate(const Certificate&) = delete; Certificate(const Certificate&) = delete;
Certificate& operator=(const Certificate&) = delete; Certificate& operator=(const Certificate&) = delete;
std::set<std::shared_ptr<RevocationList>> revocation_lists;
};
class OPENDHT_PUBLIC RevocationList
{
using clock = std::chrono::system_clock;
using time_point = clock::time_point;
using duration = clock::duration;
public:
RevocationList();
RevocationList(const Blob& b);
RevocationList(RevocationList&& o) : crl(o.crl) { o.crl = nullptr; }
~RevocationList();
RevocationList& operator=(RevocationList&& o) { crl = o.crl; o.crl = nullptr; return *this; } struct crlNumberCmp {
bool operator() (const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const {
void pack(Blob& b) const; return lhs->getNumber() < rhs->getNumber();
void unpack(const uint8_t* dat, size_t dat_size);
Blob getPacked() const {
Blob b;
pack(b);
return b;
} }
};
template <typename Packer> std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
void msgpack_pack(Packer& p) const
{
Blob b = getPacked();
p.pack_bin(b.size());
p.pack_bin_body((const char*)b.data(), b.size());
}
void msgpack_unpack(msgpack::object o);
void revoke(const Certificate& crt, time_point t = time_point::min());
bool isRevoked(const Certificate& crt) const;
/**
* Sign this revocation list using provided key and certificate.
* Validity_period sets the duration until expiration (default to certificate expiration).
*/
void sign(const PrivateKey&, const Certificate&, duration validity_period = {});
void sign(const Identity& id) { sign(*id.first, *id.second); }
bool isSignedBy(const Certificate& issuer) const;
std::string toString() const;
/**
* Read the CRL number extension field.
*/
Blob getNumber() const;
gnutls_x509_crl_t get() { return crl; }
private:
gnutls_x509_crl_t crl {};
RevocationList(const RevocationList&) = delete;
RevocationList& operator=(const RevocationList&) = delete;
}; };
......
...@@ -165,7 +165,7 @@ private: ...@@ -165,7 +165,7 @@ private:
const ValueType CERTIFICATE_TYPE = { const ValueType CERTIFICATE_TYPE = {
8, "Certificate", std::chrono::hours(24 * 7), 8, "Certificate", std::chrono::hours(24 * 7),
// A certificate can only be stored at it's public key ID. // A certificate can only be stored at its public key ID.
[](InfoHash id, std::shared_ptr<Value>& v, InfoHash, const sockaddr*, socklen_t) { [](InfoHash id, std::shared_ptr<Value>& v, InfoHash, const sockaddr*, socklen_t) {
try { try {
crypto::Certificate crt(v->data); crypto::Certificate crt(v->data);
......
...@@ -962,6 +962,24 @@ RevocationList::revoke(const Certificate& crt, std::chrono::system_clock::time_p ...@@ -962,6 +962,24 @@ RevocationList::revoke(const Certificate& crt, std::chrono::system_clock::time_p
throw CryptoException(std::string("Can't revoke certificate: ") + gnutls_strerror(err)); throw CryptoException(std::string("Can't revoke certificate: ") + gnutls_strerror(err));
} }
RevocationList::time_point
RevocationList::getNextUpdateTime() const
{
auto t = gnutls_x509_crl_get_next_update(crl);
if (t == (time_t)-1)
return std::chrono::system_clock::time_point::min();
return std::chrono::system_clock::from_time_t(t);
}
RevocationList::time_point
RevocationList::getUpdateTime() const
{
auto t = gnutls_x509_crl_get_this_update(crl);
if (t == (time_t)-1)
return std::chrono::system_clock::time_point::min();
return std::chrono::system_clock::from_time_t(t);
}
enum class Endian : uint32_t enum class Endian : uint32_t
{ {
LITTLE = 0, LITTLE = 0,
...@@ -1003,14 +1021,19 @@ RevocationList::sign(const PrivateKey& key, const Certificate& ca, duration vali ...@@ -1003,14 +1021,19 @@ RevocationList::sign(const PrivateKey& key, const Certificate& ca, duration vali
unsigned critical {0}; unsigned critical {0};
gnutls_x509_crl_get_number(crl, &number, &number_sz, &critical); gnutls_x509_crl_get_number(crl, &number, &number_sz, &critical);
if (number == 0) { if (number == 0) {
number = (uint64_t)1 | ((uint64_t)1 << (7*8)); // initialize to a random number
number_sz = sizeof(number); number_sz = sizeof(number);
} random_device rdev;
std::generate_n((uint8_t*)&number, sizeof(number), std::bind(rand_byte, std::ref(rdev)));
} else
number = endian(endian(number) + 1); number = endian(endian(number) + 1);
if (auto err = gnutls_x509_crl_set_number(crl, &number, sizeof(number))) if (auto err = gnutls_x509_crl_set_number(crl, &number, sizeof(number)))
throw CryptoException(std::string("Can't set CRL update time: ") + gnutls_strerror(err)); throw CryptoException(std::string("Can't set CRL update time: ") + gnutls_strerror(err));
if (auto err = gnutls_x509_crl_sign2(crl, ca.cert, key.x509_key, GNUTLS_DIG_SHA512, 0)) if (auto err = gnutls_x509_crl_sign2(crl, ca.cert, key.x509_key, GNUTLS_DIG_SHA512, 0))
throw CryptoException(std::string("Can't sign certificate revocation list: ") + gnutls_strerror(err)); throw CryptoException(std::string("Can't sign certificate revocation list: ") + gnutls_strerror(err));
// to be able to actually use the CRL we need to serialize/deserialize it
auto packed = getPacked();
unpack(packed.data(), packed.size());
} }
bool bool
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment