diff options
| -rw-r--r-- | src/certificates.cc | 32 | ||||
| -rw-r--r-- | src/certificates.h | 4 | ||||
| -rw-r--r-- | src/kdm.cc | 16 | ||||
| -rw-r--r-- | src/kdm.h | 2 |
4 files changed, 49 insertions, 5 deletions
diff --git a/src/certificates.cc b/src/certificates.cc index d02754f1..4c41ebba 100644 --- a/src/certificates.cc +++ b/src/certificates.cc @@ -23,6 +23,7 @@ #include <openssl/x509.h> #include <openssl/ssl.h> #include <openssl/asn1.h> +#include <openssl/err.h> #include <libxml++/nodes/element.h> #include "KM_util.h" #include "certificates.h" @@ -39,12 +40,14 @@ using namespace libdcp; /** @param c X509 certificate, which this object will take ownership of */ Certificate::Certificate (X509* c) : _certificate (c) + , _public_key (0) { } Certificate::Certificate (boost::filesystem::path filename) : _certificate (0) + , _public_key (0) { FILE* f = fopen (filename.c_str(), "r"); if (!f) { @@ -58,12 +61,14 @@ Certificate::Certificate (boost::filesystem::path filename) Certificate::Certificate (string cert) : _certificate (0) + , _public_key (0) { read_string (cert); } Certificate::Certificate (Certificate const & other) : _certificate (0) + , _public_key (0) { read_string (other.certificate (true)); } @@ -87,6 +92,7 @@ Certificate::read_string (string cert) Certificate::~Certificate () { X509_free (_certificate); + RSA_free (_public_key); } Certificate & @@ -97,6 +103,10 @@ Certificate::operator= (Certificate const & other) } X509_free (_certificate); + _certificate = 0; + RSA_free (_public_key); + _public_key = 0; + read_string (other.certificate ()); return *this; @@ -224,6 +234,28 @@ Certificate::thumbprint () const return Kumu::base64encode (digest, 20, digest_base64, 64); } +RSA * +Certificate::public_key () const +{ + assert (_certificate); + + if (_public_key) { + return _public_key; + } + + EVP_PKEY* key = X509_get_pubkey (_certificate); + if (!key) { + throw MiscError ("could not get public key from certificate"); + } + + _public_key = EVP_PKEY_get1_RSA (key); + if (!_public_key) { + throw MiscError (String::compose ("could not get RSA public key (%1)", ERR_error_string (ERR_get_error(), 0))); + } + + return _public_key; +} + shared_ptr<Certificate> CertificateChain::root () const { diff --git a/src/certificates.h b/src/certificates.h index ef2e63b4..198773f1 100644 --- a/src/certificates.h +++ b/src/certificates.h @@ -59,6 +59,9 @@ public: std::string serial () const; std::string subject () const; + /** @return RSA public key from this Certificate. Caller must not free the returned value. */ + RSA* public_key () const; + std::string thumbprint () const; private: @@ -69,6 +72,7 @@ private: static std::string get_name_part (X509_NAME *, int); X509* _certificate; + mutable RSA* _public_key; }; class CertificateChain @@ -133,7 +133,7 @@ KDM::KDM ( shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i); if (mxf) { xml_kdm->authenticated_private.encrypted_keys.push_back ( - KDMKey (signer, cpl->id (), mxf->key_id (), not_valid_before, not_valid_after, mxf->key().get()).base64 () + KDMKey (signer, cpl->id (), mxf->key_id (), not_valid_before, not_valid_after, mxf->key().get()).encrypted_base64 (recipient_cert) ); } } @@ -225,7 +225,7 @@ KDMKey::operator= (KDMKey const & other) } string -KDMKey::base64 () const +KDMKey::encrypted_base64 (shared_ptr<const Certificate> recipient_cert) const { /* XXX: SMPTE only */ uint8_t block[138]; @@ -242,9 +242,17 @@ KDMKey::base64 () const put (&p, _not_valid_after); put (&p, _key.value(), ASDCP::KeyLen); + /* Encrypt using the projector's public key */ + RSA* rsa = recipient_cert->public_key (); + unsigned char encrypted[RSA_size(rsa)]; + int const encrypted_len = RSA_public_encrypt (138, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING); + if (encrypted_len == -1) { + throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0))); + } + /* Lazy overallocation */ - char string[138 * 2]; - return Kumu::base64encode (block, 138, string, 138 * 2); + char out[encrypted_len * 2]; + return Kumu::base64encode (block, 138, out, 138 * 2); } string @@ -72,7 +72,7 @@ public: return _key; } - std::string base64 () const; + std::string encrypted_base64 (boost::shared_ptr<const Certificate>) const; private: void get (uint8_t *, uint8_t const **, int) const; |
