[Libreoffice-commits] online.git: wsd/ProofKey.cpp

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Wed Feb 19 09:20:16 UTC 2020


 wsd/ProofKey.cpp |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

New commits:
commit 6eda59123a8fc1d237a25468244118219497bf5e
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Tue Feb 18 23:46:46 2020 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Wed Feb 19 10:19:55 2020 +0100

    Proof key: make sure public exponent is exactly 4 bytes
    
    It seems that Poco returns 3-byte public exponent (0x010001) as
    3-element vector, and MS CAPI blob must include 4-byte exponent
    
    In Poco code (Crypto/src/RSAKeyImpl.cpp), its convertToByteVec
    uses OpenSSL's BN_bn2bin, which returns big-endian byte order
    (see OpenSSL's crypto/bn/bn_lib.c). That is returned from Poco's
    RSAKey::modulus() and RSAKey::*Exponent() unchanged, so treat
    them accordingly.
    
    Change-Id: I37f5fb9a310d42c7f346429c39611b25dd5bba2f
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/88989
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/wsd/ProofKey.cpp b/wsd/ProofKey.cpp
index fa6dd6bd0..e0dba1b46 100644
--- a/wsd/ProofKey.cpp
+++ b/wsd/ProofKey.cpp
@@ -37,6 +37,7 @@
 #include <Poco/URI.h>
 #include <Poco/Util/Application.h>
 
+#include "Exceptions.hpp"
 #include <Log.hpp>
 #include <Util.hpp>
 
@@ -102,7 +103,7 @@ public:
 private:
     static std::string ProofKeyPath();
 
-    // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb
+    // modulus and exponent are big-endian vectors
     static std::vector<unsigned char> RSA2CapiBlob(const std::vector<unsigned char>& modulus,
                                                    const std::vector<unsigned char>& exponent);
 
@@ -174,9 +175,17 @@ std::string Proof::ProofKeyPath()
     return keyPath;
 }
 
+// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb
 std::vector<unsigned char> Proof::RSA2CapiBlob(const std::vector<unsigned char>& modulus,
                                                const std::vector<unsigned char>& exponent)
 {
+    // Exponent might have arbitrary length in OpenSSL; we need exactly 4
+    if (exponent.size() > 4)
+        throw ParseError("Proof key public exponent is longer than 4 bytes.");
+    // make sure exponent length is correct; assume we are passed big-endian vectors
+    std::vector<unsigned char> exponent32LE(4);
+    std::copy(exponent.rbegin(), exponent.rend(), exponent32LE.begin());
+
     std::vector<unsigned char> capiBlob = {
         0x06, 0x02, 0x00, 0x00,
         0x00, 0xA4, 0x00, 0x00,
@@ -184,11 +193,11 @@ std::vector<unsigned char> Proof::RSA2CapiBlob(const std::vector<unsigned char>&
     };
     // modulus size in bits - 4 bytes (little-endian)
     const auto bitLen = ToLEBytes<std::uint32_t>(modulus.size() * 8);
-    capiBlob.reserve(capiBlob.size() + bitLen.size() + exponent.size() + modulus.size());
+    capiBlob.reserve(capiBlob.size() + bitLen.size() + exponent32LE.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(exponent32LE.begin(), exponent32LE.end(), std::back_inserter(capiBlob));
+    // modulus (passed big-endian, stored little-endian)
     std::copy(modulus.rbegin(), modulus.rend(), std::back_inserter(capiBlob));
     return capiBlob;
 }


More information about the Libreoffice-commits mailing list