aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/qpdf/QPDFCryptoImpl.hh11
-rw-r--r--libqpdf/MD5.cc163
-rw-r--r--libqpdf/MD5_native.cc192
-rw-r--r--libqpdf/QPDFCrypto_native.cc26
-rw-r--r--libqpdf/build.mk1
-rw-r--r--libqpdf/qpdf/MD5.hh70
-rw-r--r--libqpdf/qpdf/MD5_native.hh92
-rw-r--r--libqpdf/qpdf/QPDFCrypto_native.hh10
8 files changed, 328 insertions, 237 deletions
diff --git a/include/qpdf/QPDFCryptoImpl.hh b/include/qpdf/QPDFCryptoImpl.hh
index 4da299aa..8fa8b21e 100644
--- a/include/qpdf/QPDFCryptoImpl.hh
+++ b/include/qpdf/QPDFCryptoImpl.hh
@@ -23,6 +23,7 @@
#define QPDFCRYPTOIMPL_HH
#include <qpdf/DLL.h>
+#include <cstring>
// This class is part of qpdf's pluggable crypto provider support.
// Most users won't need to know or care about this class, but you can
@@ -39,6 +40,16 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
QPDF_DLL
virtual ~QPDFCryptoImpl() = default;
+
+ typedef unsigned char MD5_Digest[16];
+ QPDF_DLL
+ virtual void MD5_init() = 0;
+ QPDF_DLL
+ virtual void MD5_update(unsigned char const* data, size_t len) = 0;
+ QPDF_DLL
+ virtual void MD5_finalize() = 0;
+ QPDF_DLL
+ virtual void MD5_digest(MD5_Digest) = 0;
};
#endif // QPDFCRYPTOIMPL_HH
diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc
new file mode 100644
index 00000000..95edd3a4
--- /dev/null
+++ b/libqpdf/MD5.cc
@@ -0,0 +1,163 @@
+#include <qpdf/MD5.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/QIntC.hh>
+#include <qpdf/QPDFCryptoProvider.hh>
+
+#include <stdio.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+MD5::MD5()
+{
+ init();
+}
+
+void
+MD5::init()
+{
+ this->crypto = QPDFCryptoProvider::getImpl();
+ this->crypto->MD5_init();
+}
+
+void
+MD5::finalize()
+{
+ this->crypto->MD5_finalize();
+}
+
+void MD5::reset()
+{
+ init();
+}
+
+void MD5::encodeString(char const* str)
+{
+ size_t len = strlen(str);
+ crypto->MD5_init();
+ encodeDataIncrementally(str, len);
+ crypto->MD5_finalize();
+}
+
+void MD5::appendString(char const* input_string)
+{
+ encodeDataIncrementally(input_string, strlen(input_string));
+}
+
+void MD5::encodeDataIncrementally(char const* data, size_t len)
+{
+ this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
+}
+
+void MD5::encodeFile(char const *filename, qpdf_offset_t up_to_offset)
+{
+ char buffer[1024];
+
+ FILE *file = QUtil::safe_fopen(filename, "rb");
+ size_t len;
+ size_t so_far = 0;
+ size_t to_try = 1024;
+ size_t up_to_size = 0;
+ if (up_to_offset >= 0)
+ {
+ up_to_size = QIntC::to_size(up_to_offset);
+ }
+ do
+ {
+ if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size))
+ {
+ to_try = up_to_size - so_far;
+ }
+ len = fread(buffer, 1, to_try, file);
+ if (len > 0)
+ {
+ encodeDataIncrementally(buffer, len);
+ so_far += len;
+ if ((up_to_offset >= 0) && (so_far >= up_to_size))
+ {
+ break;
+ }
+ }
+ } while (len > 0);
+ if (ferror(file))
+ {
+ // Assume, perhaps incorrectly, that errno was set by the
+ // underlying call to read....
+ (void) fclose(file);
+ QUtil::throw_system_error(
+ std::string("MD5: read error on ") + filename);
+ }
+ (void) fclose(file);
+
+ this->crypto->MD5_finalize();
+}
+
+void MD5::digest(Digest result)
+{
+ this->crypto->MD5_finalize();
+ this->crypto->MD5_digest(result);
+}
+
+void MD5::print()
+{
+ Digest digest_val;
+ digest(digest_val);
+
+ unsigned int i;
+ for (i = 0; i < 16; ++i)
+ {
+ printf("%02x", digest_val[i]);
+ }
+ printf("\n");
+}
+
+std::string MD5::unparse()
+{
+ this->crypto->MD5_finalize();
+ Digest digest_val;
+ digest(digest_val);
+ return QUtil::hex_encode(
+ std::string(reinterpret_cast<char*>(digest_val), 16));
+}
+
+std::string
+MD5::getDataChecksum(char const* buf, size_t len)
+{
+ MD5 m;
+ m.encodeDataIncrementally(buf, len);
+ return m.unparse();
+}
+
+std::string
+MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
+{
+ MD5 m;
+ m.encodeFile(filename, up_to_offset);
+ return m.unparse();
+}
+
+bool
+MD5::checkDataChecksum(char const* const checksum,
+ char const* buf, size_t len)
+{
+ std::string actual_checksum = getDataChecksum(buf, len);
+ return (checksum == actual_checksum);
+}
+
+bool
+MD5::checkFileChecksum(char const* const checksum,
+ char const* filename, qpdf_offset_t up_to_offset)
+{
+ bool result = false;
+ try
+ {
+ std::string actual_checksum = getFileChecksum(filename, up_to_offset);
+ result = (checksum == actual_checksum);
+ }
+ catch (std::runtime_error const&)
+ {
+ // Ignore -- return false
+ }
+ return result;
+}
diff --git a/libqpdf/MD5_native.cc b/libqpdf/MD5_native.cc
index 6e166a7c..d4187e8c 100644
--- a/libqpdf/MD5_native.cc
+++ b/libqpdf/MD5_native.cc
@@ -27,7 +27,7 @@
//
/////////////////////////////////////////////////////////////////////////
-#include <qpdf/MD5.hh>
+#include <qpdf/MD5_native.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QIntC.hh>
@@ -72,28 +72,33 @@ static unsigned char PADDING[64] = {
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + static_cast<UINT4>(ac); \
+ (a) += F ((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + static_cast<UINT4>(ac); \
+ (a) += G ((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + static_cast<UINT4>(ac); \
+ (a) += H ((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + static_cast<UINT4>(ac); \
+ (a) += I ((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
+MD5_native::MD5_native()
+{
+ init();
+}
+
// MD5 initialization. Begins an MD5 operation, writing a new context.
-void MD5::init()
+void MD5_native::init()
{
count[0] = count[1] = 0;
// Load magic initialization constants.
@@ -110,7 +115,7 @@ void MD5::init()
// operation, processing another message block, and updating the
// context.
-void MD5::update(unsigned char *input,
+void MD5_native::update(unsigned char *input,
size_t inputLen)
{
unsigned int i, index, partLen;
@@ -119,10 +124,10 @@ void MD5::update(unsigned char *input,
index = static_cast<unsigned int>((count[0] >> 3) & 0x3f);
// Update number of bits
- if ((count[0] += (static_cast<UINT4>(inputLen) << 3)) <
- (static_cast<UINT4>(inputLen) << 3))
+ if ((count[0] += (static_cast<uint32_t>(inputLen) << 3)) <
+ (static_cast<uint32_t>(inputLen) << 3))
count[1]++;
- count[1] += (static_cast<UINT4>(inputLen) >> 29);
+ count[1] += (static_cast<uint32_t>(inputLen) >> 29);
partLen = 64 - index;
@@ -146,7 +151,7 @@ void MD5::update(unsigned char *input,
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
-void MD5::final()
+void MD5_native::finalize()
{
if (finalized)
{
@@ -178,10 +183,16 @@ void MD5::final()
finalized = true;
}
+void
+MD5_native::digest(Digest result)
+{
+ memcpy(result, digest_val, sizeof(digest_val));
+}
+
// MD5 basic transformation. Transforms state based on block.
-void MD5::transform(UINT4 state[4], unsigned char block[64])
+void MD5_native::transform(uint32_t state[4], unsigned char block[64])
{
- UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+ uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode(x, block, 64);
@@ -267,9 +278,9 @@ void MD5::transform(UINT4 state[4], unsigned char block[64])
memset (x, 0, sizeof (x));
}
-// Encodes input (UINT4) into output (unsigned char). Assumes len is a
+// Encodes input (uint32_t) into output (unsigned char). Assumes len is a
// multiple of 4.
-void MD5::encode(unsigned char *output, UINT4 *input, size_t len)
+void MD5_native::encode(unsigned char *output, uint32_t *input, size_t len)
{
unsigned int i, j;
@@ -281,155 +292,16 @@ void MD5::encode(unsigned char *output, UINT4 *input, size_t len)
}
}
-// Decodes input (unsigned char) into output (UINT4). Assumes len is a
+// Decodes input (unsigned char) into output (uint32_t). Assumes len is a
// multiple of 4.
-void MD5::decode(UINT4 *output, unsigned char *input, size_t len)
+void MD5_native::decode(uint32_t *output, unsigned char *input, size_t len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] =
- static_cast<UINT4>(input[j]) |
- (static_cast<UINT4>(input[j+1]) << 8) |
- (static_cast<UINT4>(input[j+2]) << 16) |
- (static_cast<UINT4>(input[j+3]) << 24);
-}
-
-// Public functions
-
-MD5::MD5()
-{
- init();
-}
-
-void MD5::reset()
-{
- init();
-}
-
-void MD5::encodeString(char const* str)
-{
- size_t len = strlen(str);
-
- update(QUtil::unsigned_char_pointer(str), len);
- final();
-}
-
-void MD5::appendString(char const* input_string)
-{
- update(QUtil::unsigned_char_pointer(input_string), strlen(input_string));
-}
-
-void MD5::encodeDataIncrementally(char const* data, size_t len)
-{
- update(QUtil::unsigned_char_pointer(data), len);
-}
-
-void MD5::encodeFile(char const *filename, qpdf_offset_t up_to_offset)
-{
- unsigned char buffer[1024];
-
- FILE *file = QUtil::safe_fopen(filename, "rb");
- size_t len;
- size_t so_far = 0;
- size_t to_try = 1024;
- size_t up_to_size = 0;
- if (up_to_offset >= 0)
- {
- up_to_size = QIntC::to_size(up_to_offset);
- }
- do
- {
- if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size))
- {
- to_try = up_to_size - so_far;
- }
- len = fread(buffer, 1, to_try, file);
- if (len > 0)
- {
- update(buffer, len);
- so_far += len;
- if ((up_to_offset >= 0) && (so_far >= up_to_size))
- {
- break;
- }
- }
- } while (len > 0);
- if (ferror(file))
- {
- // Assume, perhaps incorrectly, that errno was set by the
- // underlying call to read....
- (void) fclose(file);
- QUtil::throw_system_error(
- std::string("MD5: read error on ") + filename);
- }
- (void) fclose(file);
-
- final();
-}
-
-void MD5::digest(Digest result)
-{
- final();
- memcpy(result, digest_val, sizeof(digest_val));
-}
-
-void MD5::print()
-{
- final();
-
- unsigned int i;
- for (i = 0; i < 16; ++i)
- {
- printf("%02x", digest_val[i]);
- }
- printf("\n");
-}
-
-std::string MD5::unparse()
-{
- final();
- return QUtil::hex_encode(
- std::string(reinterpret_cast<char*>(digest_val), 16));
-}
-
-std::string
-MD5::getDataChecksum(char const* buf, size_t len)
-{
- MD5 m;
- m.encodeDataIncrementally(buf, len);
- return m.unparse();
-}
-
-std::string
-MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
-{
- MD5 m;
- m.encodeFile(filename, up_to_offset);
- return m.unparse();
-}
-
-bool
-MD5::checkDataChecksum(char const* const checksum,
- char const* buf, size_t len)
-{
- std::string actual_checksum = getDataChecksum(buf, len);
- return (checksum == actual_checksum);
-}
-
-bool
-MD5::checkFileChecksum(char const* const checksum,
- char const* filename, qpdf_offset_t up_to_offset)
-{
- bool result = false;
- try
- {
- std::string actual_checksum = getFileChecksum(filename, up_to_offset);
- result = (checksum == actual_checksum);
- }
- catch (std::runtime_error const&)
- {
- // Ignore -- return false
- }
- return result;
+ static_cast<uint32_t>(input[j]) |
+ (static_cast<uint32_t>(input[j+1]) << 8) |
+ (static_cast<uint32_t>(input[j+2]) << 16) |
+ (static_cast<uint32_t>(input[j+3]) << 24);
}
diff --git a/libqpdf/QPDFCrypto_native.cc b/libqpdf/QPDFCrypto_native.cc
index ab9fd3a2..1ee73782 100644
--- a/libqpdf/QPDFCrypto_native.cc
+++ b/libqpdf/QPDFCrypto_native.cc
@@ -1 +1,27 @@
#include <qpdf/QPDFCrypto_native.hh>
+#include <qpdf/QUtil.hh>
+
+void
+QPDFCrypto_native::MD5_init()
+{
+ this->md5 = std::make_shared<MD5_native>();
+}
+
+void
+QPDFCrypto_native::MD5_update(unsigned char const* data, size_t len)
+{
+ this->md5->update(const_cast<unsigned char*>(data), len);
+}
+
+void
+QPDFCrypto_native::MD5_finalize()
+{
+ this->md5->finalize();
+}
+
+void
+QPDFCrypto_native::MD5_digest(MD5_Digest d)
+{
+ this->md5->digest(d);
+}
+
diff --git a/libqpdf/build.mk b/libqpdf/build.mk
index d2bcd8c5..9f1244d0 100644
--- a/libqpdf/build.mk
+++ b/libqpdf/build.mk
@@ -16,6 +16,7 @@ SRCS_libqpdf = \
libqpdf/InsecureRandomDataProvider.cc \
libqpdf/JSON.cc \
libqpdf/MD5.cc \
+ libqpdf/MD5_native.cc \
libqpdf/OffsetInputSource.cc \
libqpdf/Pipeline.cc \
libqpdf/Pl_AES_PDF.cc \
diff --git a/libqpdf/qpdf/MD5.hh b/libqpdf/qpdf/MD5.hh
new file mode 100644
index 00000000..d04a89b4
--- /dev/null
+++ b/libqpdf/qpdf/MD5.hh
@@ -0,0 +1,70 @@
+#ifndef MD5_HH
+#define MD5_HH
+
+#include <qpdf/DLL.h>
+#include <qpdf/Types.h>
+#include <qpdf/QPDFCryptoImpl.hh>
+#include <string>
+#include <memory>
+
+class MD5
+{
+ public:
+ typedef unsigned char Digest[16];
+
+ QPDF_DLL
+ MD5();
+ QPDF_DLL
+ void reset();
+
+ // encodes string and finalizes
+ QPDF_DLL
+ void encodeString(char const* input_string);
+
+ // encodes file and finalizes; offset < 0 reads whole file
+ QPDF_DLL
+ void encodeFile(char const* filename, qpdf_offset_t up_to_offset = -1);
+
+ // appends string to current md5 object
+ QPDF_DLL
+ void appendString(char const* input_string);
+
+ // appends arbitrary data to current md5 object
+ QPDF_DLL
+ void encodeDataIncrementally(char const* input_data, size_t len);
+
+ // computes a raw digest
+ QPDF_DLL
+ void digest(Digest);
+
+ // prints the digest to stdout terminated with \r\n (primarily for
+ // testing)
+ QPDF_DLL
+ void print();
+
+ // returns the digest as a hexadecimal string
+ QPDF_DLL
+ std::string unparse();
+
+ // Convenience functions
+ QPDF_DLL
+ static std::string getDataChecksum(char const* buf, size_t len);
+ QPDF_DLL
+ static std::string getFileChecksum(char const* filename,
+ qpdf_offset_t up_to_offset = -1);
+ QPDF_DLL
+ static bool checkDataChecksum(char const* const checksum,
+ char const* buf, size_t len);
+ QPDF_DLL
+ static bool checkFileChecksum(char const* const checksum,
+ char const* filename,
+ qpdf_offset_t up_to_offset = -1);
+
+ private:
+ void init();
+ void finalize();
+
+ std::shared_ptr<QPDFCryptoImpl> crypto;
+};
+
+#endif // MD5_HH
diff --git a/libqpdf/qpdf/MD5_native.hh b/libqpdf/qpdf/MD5_native.hh
index 02cdb3cf..d7e65a50 100644
--- a/libqpdf/qpdf/MD5_native.hh
+++ b/libqpdf/qpdf/MD5_native.hh
@@ -1,94 +1,32 @@
-#ifndef MD5_HH
-#define MD5_HH
+#ifndef MD5_NATIVE_HH
+#define MD5_NATIVE_HH
-#include <qpdf/DLL.h>
#include <qpdf/qpdf-config.h>
-#include <qpdf/Types.h>
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <string>
+#include <cstdint>
+#include <cstring>
-class MD5
+class MD5_native
{
public:
typedef unsigned char Digest[16];
- QPDF_DLL
- MD5();
- QPDF_DLL
- void reset();
-
- // encodes string and finalizes
- QPDF_DLL
- void encodeString(char const* input_string);
-
- // encodes file and finalizes; offset < 0 reads whole file
- QPDF_DLL
- void encodeFile(char const* filename, qpdf_offset_t up_to_offset = -1);
-
- // appends string to current md5 object
- QPDF_DLL
- void appendString(char const* input_string);
-
- // appends arbitrary data to current md5 object
- QPDF_DLL
- void encodeDataIncrementally(char const* input_data, size_t len);
-
- // computes a raw digest
- QPDF_DLL
- void digest(Digest);
-
- // prints the digest to stdout terminated with \r\n (primarily for
- // testing)
- QPDF_DLL
- void print();
-
- // returns the digest as a hexadecimal string
- QPDF_DLL
- std::string unparse();
-
- // Convenience functions
- QPDF_DLL
- static std::string getDataChecksum(char const* buf, size_t len);
- QPDF_DLL
- static std::string getFileChecksum(char const* filename,
- qpdf_offset_t up_to_offset = -1);
- QPDF_DLL
- static bool checkDataChecksum(char const* const checksum,
- char const* buf, size_t len);
- QPDF_DLL
- static bool checkFileChecksum(char const* const checksum,
- char const* filename,
- qpdf_offset_t up_to_offset = -1);
-
- private:
- // POINTER defines a generic pointer type
- typedef void *POINTER;
-
- // UINT2 defines a two byte word
- typedef uint16_t UINT2;
-
- // UINT4 defines a four byte word
- typedef uint32_t UINT4;
-
+ MD5_native();
void init();
void update(unsigned char *, size_t);
- void final();
+ void finalize();
+ void digest(Digest);
- static void transform(UINT4 [4], unsigned char [64]);
- static void encode(unsigned char *, UINT4 *, size_t);
- static void decode(UINT4 *, unsigned char *, size_t);
+ private:
+ static void transform(uint32_t[4], unsigned char[64]);
+ static void encode(unsigned char *, uint32_t *, size_t);
+ static void decode(uint32_t *, unsigned char *, size_t);
- UINT4 state[4]; // state (ABCD)
- UINT4 count[2]; // number of bits, modulo 2^64 (lsb first)
+ uint32_t state[4]; // state (ABCD)
+ uint32_t count[2]; // number of bits, modulo 2^64 (lsb first)
unsigned char buffer[64]; // input buffer
bool finalized;
Digest digest_val;
};
-#endif // MD5_HH
+#endif // MD5_NATIVE_HH
diff --git a/libqpdf/qpdf/QPDFCrypto_native.hh b/libqpdf/qpdf/QPDFCrypto_native.hh
index 785d6c6f..77179075 100644
--- a/libqpdf/qpdf/QPDFCrypto_native.hh
+++ b/libqpdf/qpdf/QPDFCrypto_native.hh
@@ -3,6 +3,8 @@
#include <qpdf/DLL.h>
#include <qpdf/QPDFCryptoImpl.hh>
+#include <qpdf/MD5_native.hh>
+#include <memory>
class QPDFCrypto_native: public QPDFCryptoImpl
{
@@ -11,6 +13,14 @@ class QPDFCrypto_native: public QPDFCryptoImpl
QPDF_DLL
virtual ~QPDFCrypto_native() = default;
+
+ virtual void MD5_init();
+ virtual void MD5_update(unsigned char const* data, size_t len);
+ virtual void MD5_finalize();
+ virtual void MD5_digest(MD5_Digest);
+
+ private:
+ std::shared_ptr<MD5_native> md5;
};
#endif // QPDFCRYPTO_NATIVE_HH