diff --git a/ChangeLog b/ChangeLog index 1596d7f..d028860 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/INSTALL b/INSTALL index 6e90e07..2099840 100644 --- a/INSTALL +++ b/INSTALL @@ -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 diff --git a/include/pcp/config.h.in b/include/pcp/config.h.in index 7f7bd36..b53de92 100644 --- a/include/pcp/config.h.in +++ b/include/pcp/config.h.in @@ -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 diff --git a/include/pcp/util.h b/include/pcp/util.h index 843dddf..10e98e2 100644 --- a/include/pcp/util.h +++ b/include/pcp/util.h @@ -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 */ /**@}*/ diff --git a/libpcp/crypto.c b/libpcp/crypto.c index d8eb328..516f216 100644 --- a/libpcp/crypto.c +++ b/libpcp/crypto.c @@ -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; diff --git a/libpcp/ed.c b/libpcp/ed.c index 883e78d..fe772a1 100644 --- a/libpcp/ed.c +++ b/libpcp/ed.c @@ -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; diff --git a/libpcp/mgmt.c b/libpcp/mgmt.c index 9daea8d..59093d4 100644 --- a/libpcp/mgmt.c +++ b/libpcp/mgmt.c @@ -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; } diff --git a/libpcp/util.c b/libpcp/util.c index 11f9302..92f6aab 100644 --- a/libpcp/util.c +++ b/libpcp/util.c @@ -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; +} diff --git a/libpcp/vault.c b/libpcp/vault.c index b290660..927890f 100644 --- a/libpcp/vault.c +++ b/libpcp/vault.c @@ -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; }