using constant time memcmp by C.Meessen

This commit is contained in:
TLINDEN
2015-08-27 11:19:24 +02:00
parent 1b7681ee83
commit bbdda67a6e
9 changed files with 63 additions and 11 deletions

View File

@@ -18,6 +18,10 @@ NEXT
so, pcp aims to be secure by default and fails
safely.
Using cst_time_memcpy by Christophe Meessen instead
of libc's memcpy: constant time memcpy is much more
secure than the default, especially in our context.
0.3.0
Changed publuc key signature storage, previously
I didn't add the actual signature, therefore a

View File

@@ -1,7 +1,7 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation,
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
@@ -12,8 +12,8 @@ without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented

View File

@@ -160,9 +160,6 @@
*/
#undef LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */
#undef PACKAGE

View File

@@ -115,6 +115,14 @@ char *_bin2hex(byte *bin, size_t len);
*/
size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_array_max);
/** compare two memory regions in a constant time
\param[in] m1 array1
\param[in] m2 array2
\param[in] n size in bytes to compare
\return 0 if m1 and m2 are equal up to n
*/
int cst_time_memcmp(const void *m1, const void *m2, size_t n);
#endif /* _HAVE_PCP_UTIL_H */
/**@}*/

View File

@@ -614,7 +614,7 @@ size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
if(verifiedhash == NULL)
out_size = 0;
else {
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't match */
fatal(ptx, "signed hash doesn't match actual hash of signed decrypted file content\n");
out_size = 0;

View File

@@ -301,7 +301,7 @@ pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p
if(verifiedhash == NULL)
goto errvb1;
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
free(verifiedhash);
@@ -441,7 +441,7 @@ pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream
if(verifiedhash == NULL)
goto errdea4;
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
/* sig verified, but the hash doesn't */
fatal(ptx, "signed hash doesn't match actual hash of signed file content\n");
goto errdea5;

View File

@@ -181,7 +181,7 @@ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
/* compare them */
if(memcmp(hash, verifyhash, crypto_generichash_BYTES_MAX) != 0) {
if(cst_time_memcmp(hash, verifyhash, crypto_generichash_BYTES_MAX) != 0) {
fatal(ptx, "Signature verifies but signed hash doesn't match signature contents\n");
goto chker2;
}

View File

@@ -119,3 +119,46 @@ size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_arra
return byte_array_size;
}
/* via https://github.com/chmike/cst_time_memcmp
Licensed as:
The MIT License (MIT)
Copyright (c) 2015 Christophe Meessen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This is the safest1 variant using subscriptions.
*/
int cst_time_memcmp(const void *m1, const void *m2, size_t n) {
int res = 0, diff;
if (m1 != m2 && n && m1 && m2) {
const unsigned char *pm1 = (const unsigned char *)m1;
const unsigned char *pm2 = (const unsigned char *)m2;
do {
--n;
diff = pm1[n] - pm2[n];
res = (res & (((diff - 1) & ~diff) >> 8)) | diff;
} while (n != 0);
}
return ((res - 1) >> 8) + (res >> 8) + 1;
}

View File

@@ -522,7 +522,7 @@ int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault) {
if(pcphash_count(ptx) + pcphash_countpub(ptx) > 0) {
/* only validate the checksum if there are keys */
if(memcmp(checksum, vault->checksum, LSHA) != 0) {
if(cst_time_memcmp(checksum, vault->checksum, LSHA) != 0) {
fatal(ptx, "Error: the checksum of the key vault doesn't match its contents!\n");
goto err;
}