diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-07-30 02:10:09 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-07-30 02:10:09 +0100 |
| commit | 57b862d997857868d0c3c91a9776f854b62c6b56 (patch) | |
| tree | ed3bf26ba60645094853d05918bc22750bb356f7 /src | |
| parent | d69d2d2d32b6f874cc13ecec1ce705d44a1feb24 (diff) | |
Merge Signer into CertificateChain.
Diffstat (limited to 'src')
| -rw-r--r-- | src/certificate.cc | 6 | ||||
| -rw-r--r-- | src/certificate.h | 10 | ||||
| -rw-r--r-- | src/certificate_chain.cc | 142 | ||||
| -rw-r--r-- | src/certificate_chain.h | 53 | ||||
| -rw-r--r-- | src/cpl.cc | 7 | ||||
| -rw-r--r-- | src/cpl.h | 4 | ||||
| -rw-r--r-- | src/dcp.cc | 6 | ||||
| -rw-r--r-- | src/dcp.h | 6 | ||||
| -rw-r--r-- | src/decrypted_kdm.cc | 6 | ||||
| -rw-r--r-- | src/decrypted_kdm.h | 6 | ||||
| -rw-r--r-- | src/encrypted_kdm.cc | 10 | ||||
| -rw-r--r-- | src/encrypted_kdm.h | 4 | ||||
| -rw-r--r-- | src/signer.cc | 195 | ||||
| -rw-r--r-- | src/signer.h | 96 | ||||
| -rw-r--r-- | src/util.h | 4 | ||||
| -rw-r--r-- | src/wscript | 2 |
16 files changed, 205 insertions, 352 deletions
diff --git a/src/certificate.cc b/src/certificate.cc index fcc7b0ae..73f403bf 100644 --- a/src/certificate.cc +++ b/src/certificate.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,8 +17,8 @@ */ -/** @file src/certificates.cc - * @brief Certificate and CertificateChain classes. +/** @file src/certificate.cc + * @brief Certificate class. */ #include "KM_util.h" diff --git a/src/certificate.h b/src/certificate.h index c2121a83..6225cf31 100644 --- a/src/certificate.h +++ b/src/certificate.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,12 +17,12 @@ */ -/** @file src/certificates.h - * @brief Certificate and CertificateChain classes. +/** @file src/certificate.h + * @brief Certificate class. */ -#ifndef LIBDCP_CERTIFICATES_H -#define LIBDCP_CERTIFICATES_H +#ifndef LIBDCP_CERTIFICATE_H +#define LIBDCP_CERTIFICATE_H #undef X509_NAME #include <openssl/x509.h> diff --git a/src/certificate_chain.cc b/src/certificate_chain.cc index e7de5bd8..c0bfd52f 100644 --- a/src/certificate_chain.cc +++ b/src/certificate_chain.cc @@ -26,11 +26,20 @@ #include "util.h" #include "dcp_assert.h" #include "KM_util.h" +#include "compose.hpp" +#include <libcxml/cxml.h> +#include <libxml++/libxml++.h> +#include <xmlsec/xmldsig.h> +#include <xmlsec/dl.h> +#include <xmlsec/app.h> +#include <xmlsec/crypto.h> #include <openssl/sha.h> #include <openssl/bio.h> #include <openssl/evp.h> +#include <openssl/pem.h> #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> +#include <boost/foreach.hpp> #include <fstream> #include <sstream> @@ -157,8 +166,7 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path return dig; } -boost::filesystem::path -dcp::make_certificate_chain ( +CertificateChain::CertificateChain ( boost::filesystem::path openssl, string organisation, string organisational_unit, @@ -280,7 +288,13 @@ dcp::make_certificate_chain ( boost::filesystem::current_path (cwd); - return directory; + _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "ca.self-signed.pem"))); + _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "intermediate.signed.pem"))); + _certificates.push_back (dcp::Certificate (dcp::file_to_string (directory / "leaf.signed.pem"))); + + _key = dcp::file_to_string (directory / "leaf.key"); + + boost::filesystem::remove_all (directory); } /** @return Root certificate */ @@ -351,12 +365,15 @@ CertificateChain::remove (int i) } /** Check to see if the chain is valid (i.e. root signs the intermediate, intermediate - * signs the leaf and so on). + * signs the leaf and so on) and that the private key (if there is one) matches the + * leaf certificate. * @return true if it's ok, false if not. */ bool CertificateChain::valid () const { + /* Check the certificate chain */ + X509_STORE* store = X509_STORE_new (); if (!store) { return false; @@ -398,7 +415,24 @@ CertificateChain::valid () const } X509_STORE_free (store); - return true; + + /* Check that the leaf certificate matches the private key, if there is one */ + + if (!_key) { + return true; + } + + BIO* bio = BIO_new_mem_buf (const_cast<char *> (_key->c_str ()), -1); + if (!bio) { + throw MiscError ("could not create memory BIO"); + } + + RSA* private_key = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); + RSA* public_key = leaf().public_key (); + bool const valid = !BN_cmp (private_key->n, public_key->n); + BIO_free (bio); + + return valid; } /** @return true if the chain is now in order from root to leaf, @@ -418,3 +452,101 @@ CertificateChain::attempt_reorder () _certificates = original; return false; } + +/** Add a <Signer> and <ds:Signature> nodes to an XML node. + * @param parent XML node to add to. + * @param standard INTEROP or SMPTE. + */ +void +CertificateChain::sign (xmlpp::Element* parent, Standard standard) const +{ + /* <Signer> */ + + xmlpp::Element* signer = parent->add_child("Signer"); + xmlpp::Element* data = signer->add_child("X509Data", "dsig"); + xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig"); + serial_element->add_child("X509IssuerName", "dsig")->add_child_text (leaf().issuer()); + serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (leaf().serial()); + data->add_child("X509SubjectName", "dsig")->add_child_text (leaf().subject()); + + /* <Signature> */ + + xmlpp::Element* signature = parent->add_child("Signature", "dsig"); + + xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig"); + signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); + + if (standard == INTEROP) { + signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1"); + } else { + signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); + } + + xmlpp::Element* reference = signed_info->add_child("Reference", "dsig"); + reference->set_attribute ("URI", ""); + + xmlpp::Element* transforms = reference->add_child("Transforms", "dsig"); + transforms->add_child("Transform", "dsig")->set_attribute ( + "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature" + ); + + reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); + /* This will be filled in by the signing later */ + reference->add_child("DigestValue", "dsig"); + + signature->add_child("SignatureValue", "dsig"); + signature->add_child("KeyInfo", "dsig"); + add_signature_value (signature, "dsig"); +} + + +/** Sign an XML node. + * + * @param parent Node to sign. + * @param ns Namespace to use for the signature XML nodes. + */ +void +CertificateChain::add_signature_value (xmlpp::Node* parent, string ns) const +{ + cxml::Node cp (parent); + xmlpp::Node* key_info = cp.node_child("KeyInfo")->node (); + + /* Add the certificate chain to the KeyInfo child node of parent */ + CertificateChain::List c = leaf_to_root (); + BOOST_FOREACH (Certificate const & i, leaf_to_root ()) { + xmlpp::Element* data = key_info->add_child("X509Data", ns); + + { + xmlpp::Element* serial = data->add_child("X509IssuerSerial", ns); + serial->add_child("X509IssuerName", ns)->add_child_text (i.issuer ()); + serial->add_child("X509SerialNumber", ns)->add_child_text (i.serial ()); + } + + data->add_child("X509Certificate", ns)->add_child_text (i.certificate()); + } + + xmlSecDSigCtxPtr signature_context = xmlSecDSigCtxCreate (0); + if (signature_context == 0) { + throw MiscError ("could not create signature context"); + } + + signature_context->signKey = xmlSecCryptoAppKeyLoadMemory ( + reinterpret_cast<const unsigned char *> (_key->c_str()), _key->size(), xmlSecKeyDataFormatPem, 0, 0, 0 + ); + + if (signature_context->signKey == 0) { + throw StringError ("could not read private key"); + } + + /* XXX: set key name to the PEM string: this can't be right! */ + if (xmlSecKeySetName (signature_context->signKey, reinterpret_cast<const xmlChar *> (_key->c_str())) < 0) { + throw MiscError ("could not set key name"); + } + + int const r = xmlSecDSigCtxSign (signature_context, parent->cobj ()); + if (r < 0) { + throw MiscError (String::compose ("could not sign (%1)", r)); + } + + xmlSecDSigCtxDestroy (signature_context); +} diff --git a/src/certificate_chain.h b/src/certificate_chain.h index b4cc2485..4e13d6ee 100644 --- a/src/certificate_chain.h +++ b/src/certificate_chain.h @@ -25,7 +25,13 @@ #define LIBDCP_CERTIFICATE_CHAIN_H #include "certificate.h" +#include "types.h" #include <boost/filesystem.hpp> +#include <boost/optional.hpp> + +namespace xmlpp { + class Node; +} namespace dcp { @@ -37,6 +43,23 @@ class CertificateChain public: CertificateChain () {} + /** Create a chain of certificates for signing things. + * @param openssl Name of openssl binary (if it is on the path) or full path. + * @return Directory (which should be deleted by the caller) containing: + * - ca.self-signed.pem self-signed root certificate + * - intermediate.signed.pem intermediate certificate + * - leaf.key leaf certificate private key + * - leaf.signed.pem leaf certificate + */ + CertificateChain ( + boost::filesystem::path openssl, + std::string organisation = "example.org", + std::string organisational_unit = "example.org", + std::string root_common_name = ".smpte-430-2.ROOT.NOT_FOR_PRODUCTION", + std::string intermediate_common_name = ".smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION", + std::string leaf_common_name = "CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION" + ); + void add (Certificate c); void remove (Certificate c); void remove (int); @@ -52,29 +75,25 @@ public: bool valid () const; bool attempt_reorder (); + void sign (xmlpp::Element* parent, Standard standard) const; + void add_signature_value (xmlpp::Node* parent, std::string ns) const; + + boost::optional<std::string> key () const { + return _key; + } + + void set_key (std::string k) { + _key = k; + } + private: friend class ::certificates; List _certificates; + /** Leaf certificate's private key, if known */ + boost::optional<std::string> _key; }; -/** Create a chain of certificates for signing things. - * @param openssl Name of openssl binary (if it is on the path) or full path. - * @return Directory (which should be deleted by the caller) containing: - * - ca.self-signed.pem self-signed root certificate - * - intermediate.signed.pem intermediate certificate - * - leaf.key leaf certificate private key - * - leaf.signed.pem leaf certificate - */ -boost::filesystem::path make_certificate_chain ( - boost::filesystem::path openssl, - std::string organisation = "example.org", - std::string organisational_unit = "example.org", - std::string root_common_name = ".smpte-430-2.ROOT.NOT_FOR_PRODUCTION", - std::string intermediate_common_name = ".smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION", - std::string leaf_common_name = "CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION" - ); - } #endif @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #include "util.h" #include "reel.h" #include "metadata.h" -#include "signer.h" +#include "certificate_chain.h" #include "xml.h" #include "reel_picture_asset.h" #include "reel_sound_asset.h" @@ -107,7 +107,7 @@ CPL::add (boost::shared_ptr<Reel> reel) * @param signer Signer to sign the CPL, or 0 to add no signature. */ void -CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<const Signer> signer) const +CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<const CertificateChain> signer) const { xmlpp::Document doc; xmlpp::Element* root; @@ -255,4 +255,3 @@ CPL::pkl_type (Standard standard) const DCP_ASSERT (false); } } - @@ -42,7 +42,7 @@ class ReelAsset; class Reel; class XMLMetadata; class MXFMetadata; -class Signer; +class CertificateChain; class DecryptedKDM; /** @class CPL @@ -108,7 +108,7 @@ public: void write_xml ( boost::filesystem::path file, Standard standard, - boost::shared_ptr<const Signer> + boost::shared_ptr<const CertificateChain> ) const; void resolve_refs (std::list<boost::shared_ptr<Object> >); @@ -34,7 +34,7 @@ #include "metadata.h" #include "exceptions.h" #include "cpl.h" -#include "signer.h" +#include "certificate_chain.h" #include "compose.hpp" #include "AS_DCP.h" #include "decrypted_kdm.h" @@ -245,7 +245,7 @@ DCP::add (DecryptedKDM const & kdm) } boost::filesystem::path -DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared_ptr<const Signer> signer) const +DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared_ptr<const CertificateChain> signer) const { boost::filesystem::path p = _directory; p /= String::compose ("pkl_%1.xml", pkl_uuid); @@ -400,7 +400,7 @@ void DCP::write_xml ( Standard standard, XMLMetadata metadata, - shared_ptr<const Signer> signer + shared_ptr<const CertificateChain> signer ) { BOOST_FOREACH (shared_ptr<CPL> i, cpls ()) { @@ -45,7 +45,7 @@ class Content; class Reel; class CPL; class XMLMetadata; -class Signer; +class CertificateChain; class DecryptedKDM; class Asset; class DCPReadError; @@ -94,7 +94,7 @@ public: void write_xml ( Standard standard, XMLMetadata metadata = XMLMetadata (), - boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> () + boost::shared_ptr<const CertificateChain> signer = boost::shared_ptr<const CertificateChain> () ); private: @@ -106,7 +106,7 @@ private: Standard standard, std::string pkl_uuid, XMLMetadata metadata, - boost::shared_ptr<const Signer> signer + boost::shared_ptr<const CertificateChain> signer ) const; void write_volindex (Standard standard) const; diff --git a/src/decrypted_kdm.cc b/src/decrypted_kdm.cc index 62058fee..949db72b 100644 --- a/src/decrypted_kdm.cc +++ b/src/decrypted_kdm.cc @@ -25,7 +25,7 @@ #include "util.h" #include "exceptions.h" #include "cpl.h" -#include "signer.h" +#include "certificate_chain.h" #include "dcp_assert.h" #include "AS_DCP.h" #include "KM_util.h" @@ -212,7 +212,7 @@ DecryptedKDM::DecryptedKDM ( } EncryptedKDM -DecryptedKDM::encrypt (shared_ptr<const Signer> signer, Certificate recipient, Formulation formulation) const +DecryptedKDM::encrypt (shared_ptr<const CertificateChain> signer, Certificate recipient, Formulation formulation) const { list<pair<string, string> > key_ids; list<string> keys; @@ -227,7 +227,7 @@ DecryptedKDM::encrypt (shared_ptr<const Signer> signer, Certificate recipient, F uint8_t structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab }; put (&p, structure_id, 16); - base64_decode (signer->certificates().leaf().thumbprint (), p, 20); + base64_decode (signer->leaf().thumbprint (), p, 20); p += 20; put_uuid (&p, i.cpl_id ()); diff --git a/src/decrypted_kdm.h b/src/decrypted_kdm.h index 710de519..45ad8fa6 100644 --- a/src/decrypted_kdm.h +++ b/src/decrypted_kdm.h @@ -35,7 +35,7 @@ namespace dcp { class DecryptedKDMKey; class EncryptedKDM; -class Signer; +class CertificateChain; class CPL; /** @class DecryptedKDM @@ -72,12 +72,12 @@ public: ); /** Encrypt this KDM's keys and sign the whole KDM. - * @param signer Signer. + * @param signer Chain to sign with. * @param recipient Certificate of the projector/server which should receive this KDM's keys. * @param formulation Formulation to use for the encrypted KDM. * @return Encrypted KDM. */ - EncryptedKDM encrypt (boost::shared_ptr<const Signer> signer, Certificate recipient, Formulation formulation) const; + EncryptedKDM encrypt (boost::shared_ptr<const CertificateChain> signer, Certificate recipient, Formulation formulation) const; /** @return This KDM's (decrypted) keys, which could be used to decrypt assets. */ std::list<DecryptedKDMKey> keys () const { diff --git a/src/encrypted_kdm.cc b/src/encrypted_kdm.cc index 948e26a5..c3d8a618 100644 --- a/src/encrypted_kdm.cc +++ b/src/encrypted_kdm.cc @@ -19,7 +19,7 @@ #include "encrypted_kdm.h" #include "util.h" -#include "signer.h" +#include "certificate_chain.h" #include <libcxml/cxml.h> #include <libxml++/document.h> #include <libxml++/nodes/element.h> @@ -492,7 +492,7 @@ EncryptedKDM::EncryptedKDM (string s) } EncryptedKDM::EncryptedKDM ( - shared_ptr<const Signer> signer, + shared_ptr<const CertificateChain> signer, Certificate recipient, string device_list_description, string cpl_id, @@ -508,8 +508,8 @@ EncryptedKDM::EncryptedKDM ( /* Fill our XML-ish description in with the juicy bits that the caller has given */ data::AuthenticatedPublic& aup = _data->authenticated_public; - aup.signer.x509_issuer_name = signer->certificates().leaf().issuer (); - aup.signer.x509_serial_number = signer->certificates().leaf().serial (); + aup.signer.x509_issuer_name = signer->leaf().issuer (); + aup.signer.x509_serial_number = signer->leaf().serial (); data::KDMRequiredExtensions& kre = _data->authenticated_public.required_extensions.kdm_required_extensions; kre.recipient.x509_issuer_serial.x509_issuer_name = recipient.issuer (); @@ -518,7 +518,7 @@ EncryptedKDM::EncryptedKDM ( kre.authorized_device_info.device_list_description = device_list_description; kre.composition_playlist_id = cpl_id; if (formulation == DCI_ANY || formulation == DCI_SPECIFIC) { - kre.content_authenticator = signer->certificates().leaf().thumbprint (); + kre.content_authenticator = signer->leaf().thumbprint (); } kre.content_title_text = content_title_text; kre.not_valid_before = not_valid_before; diff --git a/src/encrypted_kdm.h b/src/encrypted_kdm.h index dc98e1f1..247d6678 100644 --- a/src/encrypted_kdm.h +++ b/src/encrypted_kdm.h @@ -39,7 +39,7 @@ namespace data { class EncryptedKDMData; } -class Signer; +class CertificateChain; class Certificate; /** @class EncryptedKDM @@ -77,7 +77,7 @@ private: /** Construct an EncryptedKDM from a set of details */ EncryptedKDM ( - boost::shared_ptr<const Signer> signer, + boost::shared_ptr<const CertificateChain> signer, Certificate recipient, std::string device_list_description, std::string cpl_id, diff --git a/src/signer.cc b/src/signer.cc deleted file mode 100644 index c04ac122..00000000 --- a/src/signer.cc +++ /dev/null @@ -1,195 +0,0 @@ -/* - Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/signer.cc - * @brief Signer class. - */ - -#include "signer.h" -#include "exceptions.h" -#include "certificate_chain.h" -#include "util.h" -#include <libcxml/cxml.h> -#include <libxml++/libxml++.h> -#include <xmlsec/xmldsig.h> -#include <xmlsec/dl.h> -#include <xmlsec/app.h> -#include <xmlsec/crypto.h> -#include <openssl/pem.h> -#include "compose.hpp" - -using std::string; -using std::list; -using boost::shared_ptr; -using namespace dcp; - -Signer::Signer (boost::filesystem::path openssl) -{ - create (make_certificate_chain (openssl)); -} - -Signer::Signer (boost::filesystem::path openssl, - string organisation, - string organisational_unit, - string root_common_name, - string intermediate_common_name, - string leaf_common_name - ) -{ - create ( - make_certificate_chain ( - openssl, - organisation, - organisational_unit, - root_common_name, - intermediate_common_name, - leaf_common_name - ) - ); -} - -void -Signer::create (boost::filesystem::path directory) -{ - _certificates.add (dcp::Certificate (dcp::file_to_string (directory / "ca.self-signed.pem"))); - _certificates.add (dcp::Certificate (dcp::file_to_string (directory / "intermediate.signed.pem"))); - _certificates.add (dcp::Certificate (dcp::file_to_string (directory / "leaf.signed.pem"))); - - _key = dcp::file_to_string (directory / "leaf.key"); - - boost::filesystem::remove_all (directory); -} - -/** Add a <Signer> and <ds:Signature> nodes to an XML node. - * @param parent XML node to add to. - * @param standard INTEROP or SMPTE. - */ -void -Signer::sign (xmlpp::Element* parent, Standard standard) const -{ - /* <Signer> */ - - xmlpp::Element* signer = parent->add_child("Signer"); - xmlpp::Element* data = signer->add_child("X509Data", "dsig"); - xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig"); - serial_element->add_child("X509IssuerName", "dsig")->add_child_text (_certificates.leaf().issuer()); - serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (_certificates.leaf().serial()); - data->add_child("X509SubjectName", "dsig")->add_child_text (_certificates.leaf().subject()); - - /* <Signature> */ - - xmlpp::Element* signature = parent->add_child("Signature", "dsig"); - - xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig"); - signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); - - if (standard == INTEROP) { - signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1"); - } else { - signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); - } - - xmlpp::Element* reference = signed_info->add_child("Reference", "dsig"); - reference->set_attribute ("URI", ""); - - xmlpp::Element* transforms = reference->add_child("Transforms", "dsig"); - transforms->add_child("Transform", "dsig")->set_attribute ( - "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature" - ); - - reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); - /* This will be filled in by the signing later */ - reference->add_child("DigestValue", "dsig"); - - signature->add_child("SignatureValue", "dsig"); - signature->add_child("KeyInfo", "dsig"); - add_signature_value (signature, "dsig"); -} - - -/** Sign an XML node. - * - * @param parent Node to sign. - * @param ns Namespace to use for the signature XML nodes. - */ -void -Signer::add_signature_value (xmlpp::Node* parent, string ns) const -{ - cxml::Node cp (parent); - xmlpp::Node* key_info = cp.node_child("KeyInfo")->node (); - - /* Add the certificate chain to the KeyInfo child node of parent */ - CertificateChain::List c = _certificates.leaf_to_root (); - for (CertificateChain::List::iterator i = c.begin(); i != c.end(); ++i) { - xmlpp::Element* data = key_info->add_child("X509Data", ns); - - { - xmlpp::Element* serial = data->add_child("X509IssuerSerial", ns); - serial->add_child("X509IssuerName", ns)->add_child_text (i->issuer ()); - serial->add_child("X509SerialNumber", ns)->add_child_text (i->serial ()); - } - - data->add_child("X509Certificate", ns)->add_child_text (i->certificate()); - } - - xmlSecDSigCtxPtr signature_context = xmlSecDSigCtxCreate (0); - if (signature_context == 0) { - throw MiscError ("could not create signature context"); - } - - signature_context->signKey = xmlSecCryptoAppKeyLoadMemory ( - reinterpret_cast<const unsigned char *> (_key.c_str()), _key.size(), xmlSecKeyDataFormatPem, 0, 0, 0 - ); - - if (signature_context->signKey == 0) { - throw FileError ("could not load private key file", _key, 0); - } - - /* XXX: set key name to the file name: is this right? */ - if (xmlSecKeySetName (signature_context->signKey, reinterpret_cast<const xmlChar *> (_key.c_str())) < 0) { - throw MiscError ("could not set key name"); - } - - int const r = xmlSecDSigCtxSign (signature_context, parent->cobj ()); - if (r < 0) { - throw MiscError (String::compose ("could not sign (%1)", r)); - } - - xmlSecDSigCtxDestroy (signature_context); -} - -bool -Signer::valid () const -{ - if (!_certificates.valid ()) { - return false; - } - - BIO* bio = BIO_new_mem_buf (const_cast<char *> (_key.c_str ()), -1); - if (!bio) { - throw MiscError ("could not create memory BIO"); - } - - RSA* private_key = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); - RSA* public_key = _certificates.leaf().public_key (); - bool const valid = !BN_cmp (private_key->n, public_key->n); - BIO_free (bio); - - return valid; -} diff --git a/src/signer.h b/src/signer.h deleted file mode 100644 index b8bd5643..00000000 --- a/src/signer.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef LIBDCP_SIGNER_H -#define LIBDCP_SIGNER_H - -/** @file src/signer.h - * @brief Signer class. - */ - -#include "certificate.h" -#include "certificate_chain.h" -#include "types.h" -#include <boost/filesystem.hpp> - -namespace xmlpp { - class Element; - class Node; -} - -namespace dcp { - -/** @class Signer - * @brief A class which can sign XML files. - */ -class Signer -{ -public: - Signer (boost::filesystem::path openssl); - - Signer ( - boost::filesystem::path openssl, - std::string organisation, - std::string organisational_unit, - std::string root_common_name, - std::string intermediate_common_name, - std::string leaf_common_name - ); - - /** @param c Certificate chain to sign with. - * @param k Key to sign with as a PEM-format string. - */ - Signer (CertificateChain c, std::string k) - : _certificates (c) - , _key (k) - {} - - void sign (xmlpp::Element* parent, Standard standard) const; - void add_signature_value (xmlpp::Node* parent, std::string ns) const; - - CertificateChain const & certificates () const { - return _certificates; - } - - CertificateChain& certificates () { - return _certificates; - } - - std::string key () const { - return _key; - } - - void set_key (std::string k) { - _key = k; - } - - bool valid () const; - -private: - void create (boost::filesystem::path directory); - - /** Certificate chain to sign with */ - CertificateChain _certificates; - /** Key to sign with as a PEM-format string */ - std::string _key; -}; - -} - -#endif @@ -59,10 +59,6 @@ extern bool ids_equal (std::string a, std::string b); extern void init (); -extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, Standard standard); -extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, std::string const & ns); -extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns); - extern int base64_decode (std::string const & in, unsigned char* out, int out_length); extern boost::optional<boost::filesystem::path> relative_to_root (boost::filesystem::path root, boost::filesystem::path file); extern FILE * fopen_boost (boost::filesystem::path, std::string); diff --git a/src/wscript b/src/wscript index 15d1b781..6a2be894 100644 --- a/src/wscript +++ b/src/wscript @@ -43,7 +43,6 @@ def build(bld): reel_stereo_picture_asset.cc reel_subtitle_asset.cc rgb_xyz.cc - signer.cc smpte_load_font_node.cc smpte_subtitle_asset.cc sound_asset.cc @@ -105,7 +104,6 @@ def build(bld): reel_stereo_picture_asset.h reel_subtitle_asset.h ref.h - signer.h smpte_load_font_node.h smpte_subtitle_asset.h sound_frame.h |
