@@ -181,6 +181,27 @@ std::string generateClientProof(const unsigned char saltedPassword[hashSize],
181
181
return base64::encode (reinterpret_cast <char *>(clientProof), hashSize);
182
182
}
183
183
184
+ /* *
185
+ * Compare two arrays of bytes for equality in constant time.
186
+ *
187
+ * This means that the function runs for the same amount of time even if they differ. Unlike memcmp,
188
+ * this function does not exit on the first difference.
189
+ *
190
+ * Returns true if the two arrays are equal.
191
+ *
192
+ * TODO: evaluate if LTO inlines or changes the code flow of this function.
193
+ */
194
+ NOINLINE_DECL
195
+ bool memequal (volatile const unsigned char * s1, volatile const unsigned char * s2, size_t length) {
196
+ unsigned char ret = 0 ;
197
+
198
+ for (size_t i = 0 ; i < length; ++i) {
199
+ ret |= s1[i] ^ s2[i];
200
+ }
201
+
202
+ return ret == 0 ;
203
+ }
204
+
184
205
bool verifyServerSignature (const unsigned char saltedPassword[hashSize],
185
206
const std::string& authMessage,
186
207
const std::string& receivedServerSignature) {
@@ -207,7 +228,14 @@ bool verifyServerSignature(const unsigned char saltedPassword[hashSize],
207
228
208
229
std::string encodedServerSignature =
209
230
base64::encode (reinterpret_cast <char *>(serverSignature), sizeof (serverSignature));
210
- return (receivedServerSignature == encodedServerSignature);
231
+
232
+ if (encodedServerSignature.size () != receivedServerSignature.size ()) {
233
+ return false ;
234
+ }
235
+
236
+ return memequal (reinterpret_cast <const unsigned char *>(encodedServerSignature.c_str ()),
237
+ reinterpret_cast <const unsigned char *>(receivedServerSignature.c_str ()),
238
+ encodedServerSignature.size ());
211
239
}
212
240
213
241
} // namespace scram
0 commit comments