wsd/ProofKey.cpp | 101 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 40 deletions(-)
New commits: commit 0c0510cccf57688d6e7c8f7f17ee890095d1d931 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Jan 21 18:35:01 2020 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Tue Jan 21 19:28:32 2020 +0100 Implement proper proof-key value attribute Change-Id: I3f2ad960ce6d3dad4d0b064492355b5643f345c8 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/87148 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/wsd/ProofKey.cpp b/wsd/ProofKey.cpp index 118724def..3fe2af455 100644 --- a/wsd/ProofKey.cpp +++ b/wsd/ProofKey.cpp @@ -12,10 +12,12 @@ #include "ProofKey.hpp" #include "LOOLWSD.hpp" +#include <algorithm> #include <cassert> #include <chrono> #include <cstdlib> #include <memory> +#include <vector> #include <Poco/Base64Decoder.h> #include <Poco/Base64Encoder.h> @@ -40,6 +42,58 @@ namespace{ +std::vector<unsigned char> getBytesLE(const unsigned char* bytesInSystemOrder, const size_t n) +{ + std::vector<unsigned char> ret(n); +#if !defined __BYTE_ORDER__ + static_assert(false, "Byte order is not detected on this platform!"); +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::copy_n(bytesInSystemOrder, n, ret.begin()); +#else + std::copy_n(bytesInSystemOrder, n, ret.rbegin()); +#endif + return ret; +} + +// Returns a number as vector of bytes (little-endian) +template <typename T> +std::vector<unsigned char> getBytesLE(const T& x) +{ + return getBytesLE(reinterpret_cast<const unsigned char*>(&x), sizeof(x)); +} + +// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb +std::vector<unsigned char> RSA2CapiBlob(const std::vector<unsigned char>& modulus, + const std::vector<unsigned char>& exponent) +{ + std::vector<unsigned char> capiBlob = { + 0x06, 0x02, 0x00, 0x00, + 0x00, 0xA4, 0x00, 0x00, + 0x52, 0x53, 0x41, 0x31, + }; + // modulus size in bits - 4 bytes (little-endian) + const auto bitLen = getBytesLE<std::uint32_t>(modulus.size() * 8); + capiBlob.reserve(capiBlob.size() + bitLen.size() + exponent.size() + modulus.size()); + std::copy(bitLen.begin(), bitLen.end(), std::back_inserter(capiBlob)); + // exponent - 4 bytes (little-endian) + std::copy(exponent.rbegin(), exponent.rend(), std::back_inserter(capiBlob)); + // modulus (little-endian) + std::copy(modulus.rbegin(), modulus.rend(), std::back_inserter(capiBlob)); + return capiBlob; +} + +std::string BytesToBase64(const std::vector<unsigned char>& bytes) +{ + std::ostringstream oss; + // The signature generated contains CRLF line endings. + // Use a line ending converter to remove these CRLF + Poco::OutputLineEndingConverter lineEndingConv(oss, ""); + Poco::Base64Encoder encoder(lineEndingConv); + encoder << std::string(bytes.begin(), bytes.end()); + encoder.close(); + return oss.str(); +} + class Proof { public: Proof(); @@ -84,46 +138,13 @@ Proof::Proof() { if (m_pKey) { - { - // TODO: This is definitely not correct at the moment. The proof key must be - // base64-encoded blob in "unmanaged Microsoft Cryptographic API (CAPI)" format - // (as .Net's RSACryptoServiceProvider::ExportCspBlob returns). - std::ostringstream oss; - Poco::OutputLineEndingConverter lineEndingConv(oss, ""); - m_pKey->save(&lineEndingConv); - std::string sKey = oss.str(); - const std::string sBegin = "-----BEGIN RSA PUBLIC KEY-----"; - const std::string sEnd = "-----END RSA PUBLIC KEY-----"; - auto pos = sKey.find(sBegin); - if (pos != std::string::npos) - sKey = sKey.substr(pos + sBegin.length()); - pos = sKey.find(sEnd); - if (pos != std::string::npos) - sKey = sKey.substr(0, pos); - m_aAttribs.emplace_back("value", sKey); - } - { - std::ostringstream oss; - // The signature generated contains CRLF line endings. - // Use a line ending converter to remove these CRLF - Poco::OutputLineEndingConverter lineEndingConv(oss, ""); - Poco::Base64Encoder encoder(lineEndingConv); - const auto m = m_pKey->modulus(); - encoder << std::string(m.begin(), m.end()); - encoder.close(); - m_aAttribs.emplace_back("modulus", oss.str()); - } - { - std::ostringstream oss; - // The signature generated contains CRLF line endings. - // Use a line ending converter to remove these CRLF - Poco::OutputLineEndingConverter lineEndingConv(oss, ""); - Poco::Base64Encoder encoder(lineEndingConv); - const auto e = m_pKey->encryptionExponent(); - encoder << std::string(e.begin(), e.end()); - encoder.close(); - m_aAttribs.emplace_back("exponent", oss.str()); - } + const auto m = m_pKey->modulus(); + const auto e = m_pKey->encryptionExponent(); + const auto capiBlob = RSA2CapiBlob(m, e); + + m_aAttribs.emplace_back("value", BytesToBase64(capiBlob)); + m_aAttribs.emplace_back("modulus", BytesToBase64(m)); + m_aAttribs.emplace_back("exponent", BytesToBase64(e)); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits