Line | Count | Source (jump to first uncovered line) |
1 | | #include <qpdf/MD5.hh> |
2 | | |
3 | | #include <qpdf/QIntC.hh> |
4 | | #include <qpdf/QPDFCryptoProvider.hh> |
5 | | #include <qpdf/QUtil.hh> |
6 | | |
7 | | #include <cstring> |
8 | | |
9 | | MD5::MD5() |
10 | 73.4k | { |
11 | 73.4k | init(); |
12 | 73.4k | } |
13 | | |
14 | | void |
15 | | MD5::init() |
16 | 73.4k | { |
17 | 73.4k | crypto = QPDFCryptoProvider::getImpl(); |
18 | 73.4k | crypto->MD5_init(); |
19 | 73.4k | } |
20 | | |
21 | | void |
22 | | MD5::finalize() |
23 | 0 | { |
24 | 0 | crypto->MD5_finalize(); |
25 | 0 | } |
26 | | |
27 | | void |
28 | | MD5::reset() |
29 | 0 | { |
30 | 0 | init(); |
31 | 0 | } |
32 | | |
33 | | void |
34 | | MD5::encodeString(char const* str) |
35 | 0 | { |
36 | 0 | size_t len = strlen(str); |
37 | 0 | crypto->MD5_init(); |
38 | 0 | encodeDataIncrementally(str, len); |
39 | 0 | crypto->MD5_finalize(); |
40 | 0 | } |
41 | | |
42 | | void |
43 | | MD5::appendString(char const* input_string) |
44 | 0 | { |
45 | 0 | encodeDataIncrementally(input_string, strlen(input_string)); |
46 | 0 | } |
47 | | |
48 | | void |
49 | | MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset) |
50 | 0 | { |
51 | 0 | char buffer[1024]; |
52 | |
|
53 | 0 | FILE* file = QUtil::safe_fopen(filename, "rb"); |
54 | 0 | size_t len; |
55 | 0 | size_t so_far = 0; |
56 | 0 | size_t to_try = 1024; |
57 | 0 | size_t up_to_size = 0; |
58 | 0 | if (up_to_offset >= 0) { |
59 | 0 | up_to_size = QIntC::to_size(up_to_offset); |
60 | 0 | } |
61 | 0 | do { |
62 | 0 | if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size)) { |
63 | 0 | to_try = up_to_size - so_far; |
64 | 0 | } |
65 | 0 | len = fread(buffer, 1, to_try, file); |
66 | 0 | if (len > 0) { |
67 | 0 | encodeDataIncrementally(buffer, len); |
68 | 0 | so_far += len; |
69 | 0 | if ((up_to_offset >= 0) && (so_far >= up_to_size)) { |
70 | 0 | break; |
71 | 0 | } |
72 | 0 | } |
73 | 0 | } while (len > 0); |
74 | 0 | if (ferror(file)) { |
75 | | // Assume, perhaps incorrectly, that errno was set by the underlying call to read.... |
76 | 0 | (void)fclose(file); |
77 | 0 | QUtil::throw_system_error(std::string("MD5: read error on ") + filename); |
78 | 0 | } |
79 | 0 | (void)fclose(file); |
80 | |
|
81 | 0 | crypto->MD5_finalize(); |
82 | 0 | } |
83 | | |
84 | | void |
85 | | MD5::digest(Digest result) |
86 | 73.4k | { |
87 | 73.4k | crypto->MD5_finalize(); |
88 | 73.4k | crypto->MD5_digest(result); |
89 | 73.4k | } |
90 | | |
91 | | std::string |
92 | | MD5::digest() |
93 | 662 | { |
94 | 662 | Digest digest_val; |
95 | 662 | digest(digest_val); |
96 | 662 | return {reinterpret_cast<char*>(digest_val), 16}; |
97 | 662 | } |
98 | | |
99 | | std::string |
100 | | MD5::digest(std::string_view data) |
101 | 5.91k | { |
102 | 5.91k | MD5 m; |
103 | 5.91k | m.encodeDataIncrementally(data.data(), data.size()); |
104 | 5.91k | Digest digest_val; |
105 | 5.91k | m.digest(digest_val); |
106 | 5.91k | return {reinterpret_cast<char*>(digest_val), 16}; |
107 | 5.91k | } |
108 | | |
109 | | void |
110 | | MD5::print() |
111 | 0 | { |
112 | 0 | Digest digest_val; |
113 | 0 | digest(digest_val); |
114 | |
|
115 | 0 | unsigned int i; |
116 | 0 | for (i = 0; i < 16; ++i) { |
117 | 0 | printf("%02x", digest_val[i]); |
118 | 0 | } |
119 | 0 | printf("\n"); |
120 | 0 | } |
121 | | |
122 | | std::string |
123 | | MD5::unparse() |
124 | 0 | { |
125 | 0 | crypto->MD5_finalize(); |
126 | 0 | Digest digest_val; |
127 | 0 | digest(digest_val); |
128 | 0 | return QUtil::hex_encode(std::string(reinterpret_cast<char*>(digest_val), 16)); |
129 | 0 | } |
130 | | |
131 | | std::string |
132 | | MD5::getDataChecksum(char const* buf, size_t len) |
133 | 0 | { |
134 | 0 | MD5 m; |
135 | 0 | m.encodeDataIncrementally(buf, len); |
136 | 0 | return m.unparse(); |
137 | 0 | } |
138 | | |
139 | | std::string |
140 | | MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset) |
141 | 0 | { |
142 | 0 | MD5 m; |
143 | 0 | m.encodeFile(filename, up_to_offset); |
144 | 0 | return m.unparse(); |
145 | 0 | } |
146 | | |
147 | | bool |
148 | | MD5::checkDataChecksum(char const* const checksum, char const* buf, size_t len) |
149 | 0 | { |
150 | 0 | std::string actual_checksum = getDataChecksum(buf, len); |
151 | 0 | return (checksum == actual_checksum); |
152 | 0 | } |
153 | | |
154 | | bool |
155 | | MD5::checkFileChecksum(char const* const checksum, char const* filename, qpdf_offset_t up_to_offset) |
156 | 0 | { |
157 | 0 | bool result = false; |
158 | 0 | try { |
159 | 0 | std::string actual_checksum = getFileChecksum(filename, up_to_offset); |
160 | 0 | result = (checksum == actual_checksum); |
161 | 0 | } catch (std::runtime_error const&) { |
162 | | // Ignore -- return false |
163 | 0 | } |
164 | 0 | return result; |
165 | 0 | } |