@@ -35,52 +35,134 @@ namespace dwarfs {
35
35
namespace {
36
36
37
37
bool compute_evp (const EVP_MD* algorithm, void const * data, size_t size,
38
- void * result , unsigned int * digest_size) {
39
- return EVP_Digest (data, size, reinterpret_cast <unsigned char *>(result ),
38
+ void * digest , unsigned int * digest_size) {
39
+ return EVP_Digest (data, size, reinterpret_cast <unsigned char *>(digest ),
40
40
digest_size, algorithm, nullptr );
41
41
}
42
42
43
- bool compute_xxh3_64 (void const * data, size_t size, void * result) {
44
- auto checksum = XXH3_64bits (data, size);
45
- static_assert (checksum_size (checksum_algorithm::XXH3_64) == sizeof (checksum));
46
- ::memcpy (result, &checksum, sizeof (checksum));
43
+ bool compute_xxh3_64 (void const * data, size_t size, void * digest) {
44
+ auto hash = XXH3_64bits (data, size);
45
+ static_assert (checksum::digest_size (checksum::algorithm::XXH3_64) ==
46
+ sizeof (hash));
47
+ ::memcpy (digest, &hash, sizeof (hash));
47
48
return true ;
48
49
}
49
50
51
+ class checksum_evp : public checksum ::impl {
52
+ public:
53
+ checksum_evp (EVP_MD const * evp, checksum::algorithm alg)
54
+ : context_(EVP_MD_CTX_new())
55
+ , dig_size_(checksum::digest_size(alg)) {
56
+ EVP_DigestInit_ex (context_, evp, nullptr );
57
+ }
58
+
59
+ ~checksum_evp () override { EVP_MD_CTX_destroy (context_); }
60
+
61
+ void update (void const * data, size_t size) override {
62
+ DWARFS_CHECK (EVP_DigestUpdate (context_, data, size),
63
+ " EVP_DigestUpdate() failed" );
64
+ }
65
+
66
+ bool finalize (void * digest) override {
67
+ unsigned int dig_size = 0 ;
68
+ bool rv = EVP_DigestFinal_ex (
69
+ context_, reinterpret_cast <unsigned char *>(digest), &dig_size);
70
+
71
+ if (rv) {
72
+ DWARFS_CHECK (
73
+ dig_size_ == dig_size,
74
+ fmt::format (" digest size mismatch: {0} != {1}" , dig_size_, dig_size));
75
+ }
76
+
77
+ return rv;
78
+ }
79
+
80
+ private:
81
+ EVP_MD_CTX* context_;
82
+ size_t const dig_size_;
83
+ };
84
+
85
+ class checksum_xxh3_64 : public checksum ::impl {
86
+ public:
87
+ checksum_xxh3_64 ()
88
+ : state_(XXH3_createState()) {
89
+ DWARFS_CHECK (XXH3_64bits_reset (state_) == XXH_OK,
90
+ " XXH3_64bits_reset() failed" );
91
+ }
92
+
93
+ ~checksum_xxh3_64 () override { XXH3_freeState (state_); }
94
+
95
+ void update (void const * data, size_t size) override {
96
+ auto err = XXH3_64bits_update (state_, data, size);
97
+ DWARFS_CHECK (err == XXH_OK, fmt::format (" XXH3_64bits_update() failed: {}" ,
98
+ static_cast <int >(err)));
99
+ }
100
+
101
+ bool finalize (void * digest) override {
102
+ auto hash = XXH3_64bits_digest (state_);
103
+ ::memcpy (digest, &hash, sizeof (hash));
104
+ return true ;
105
+ }
106
+
107
+ private:
108
+ XXH3_state_t* state_;
109
+ };
110
+
50
111
} // namespace
51
112
52
- bool compute_checksum (checksum_algorithm alg, void const * data, size_t size,
53
- void * result ) {
113
+ bool checksum::compute (algorithm alg, void const * data, size_t size,
114
+ void * digest ) {
54
115
bool rv = false ;
55
- unsigned int digest_size = 0 ;
116
+ unsigned int dig_size = 0 ;
56
117
57
118
switch (alg) {
58
- case checksum_algorithm ::SHA1:
59
- rv = compute_evp (EVP_sha1 (), data, size, result , &digest_size );
119
+ case algorithm ::SHA1:
120
+ rv = compute_evp (EVP_sha1 (), data, size, digest , &dig_size );
60
121
break ;
61
- case checksum_algorithm ::SHA2_512_256:
62
- rv = compute_evp (EVP_sha512_256 (), data, size, result , &digest_size );
122
+ case algorithm ::SHA2_512_256:
123
+ rv = compute_evp (EVP_sha512_256 (), data, size, digest , &dig_size );
63
124
break ;
64
- case checksum_algorithm ::XXH3_64:
65
- rv = compute_xxh3_64 (data, size, result );
125
+ case algorithm ::XXH3_64:
126
+ rv = compute_xxh3_64 (data, size, digest );
66
127
break ;
67
128
}
68
129
69
- if (rv && digest_size > 0 ) {
70
- DWARFS_CHECK (checksum_size (alg) == digest_size ,
130
+ if (rv && dig_size > 0 ) {
131
+ DWARFS_CHECK (digest_size (alg) == dig_size ,
71
132
fmt::format (" digest size mismatch: {0} != {1} [{2}]" ,
72
- checksum_size (alg), digest_size ,
133
+ digest_size (alg), dig_size ,
73
134
static_cast <int >(alg)));
74
135
}
75
136
76
137
return rv;
77
138
}
78
139
79
- bool verify_checksum (checksum_algorithm alg, void const * data, size_t size,
80
- const void * checksum) {
140
+ bool checksum::verify (algorithm alg, void const * data, size_t size,
141
+ const void * digest) {
142
+ char tmp[EVP_MAX_MD_SIZE];
143
+ return compute (alg, data, size, tmp) &&
144
+ ::memcmp (digest, tmp, digest_size(alg)) == 0;
145
+ }
146
+
147
+ checksum::checksum (algorithm alg)
148
+ : alg_(alg) {
149
+ switch (alg) {
150
+ case algorithm::SHA1:
151
+ impl_ = std::make_unique<checksum_evp>(EVP_sha1 (), alg);
152
+ break ;
153
+ case algorithm::SHA2_512_256:
154
+ impl_ = std::make_unique<checksum_evp>(EVP_sha512_256 (), alg);
155
+ break ;
156
+ case algorithm::XXH3_64:
157
+ impl_ = std::make_unique<checksum_xxh3_64>();
158
+ break ;
159
+ }
160
+ DWARFS_CHECK (false , " unknown algorithm" );
161
+ }
162
+
163
+ bool checksum::verify (void const * digest) const {
81
164
char tmp[EVP_MAX_MD_SIZE];
82
- return compute_checksum (alg, data, size, tmp) &&
83
- ::memcmp (checksum, tmp, checksum_size(alg)) == 0;
165
+ return impl_->finalize (tmp) && ::memcmp (digest, tmp, digest_size (alg_)) == 0 ;
84
166
}
85
167
86
168
} // namespace dwarfs
0 commit comments