From c3656aae3042899d9a2932635c21f86afe413323 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 24 Feb 2020 02:27:01 -0800 Subject: [PATCH] crypto: constant-time pss (if it survives optimization) --- .../crypto/impl/crypto_rsa_pss_impl.hpp | 38 ++++++++++--------- .../include/vapours/svc/svc_types_common.hpp | 2 + 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/libraries/libvapours/include/vapours/crypto/impl/crypto_rsa_pss_impl.hpp b/libraries/libvapours/include/vapours/crypto/impl/crypto_rsa_pss_impl.hpp index 5a17ff4e5..8c783b00c 100644 --- a/libraries/libvapours/include/vapours/crypto/impl/crypto_rsa_pss_impl.hpp +++ b/libraries/libvapours/include/vapours/crypto/impl/crypto_rsa_pss_impl.hpp @@ -73,9 +73,7 @@ namespace ams::crypto::impl { bool Verify(u8 *buf, size_t size, Hash *hash) { /* Validate sanity byte. */ - if (buf[size - 1] != TailMagic) { - return false; - } + bool is_valid = buf[size - 1] == TailMagic; /* Decrypt maskedDB */ const size_t db_len = size - HashSize - 1; @@ -87,33 +85,37 @@ namespace ams::crypto::impl { db[0] &= 0x7F; /* Verify that DB is of the form 0000...0001 */ - s32 salt_ofs = -1; - for (size_t i = 0; i < db_len; i++) { - if (db[i] != 0) { - salt_ofs = static_cast(i) + 1; - break; + s32 salt_ofs = 0; + { + int looking_for_one = 1; + int invalid_db_padding = 0; + int is_zero; + int is_one; + for (size_t i = 0; i < db_len; /* ... */) { + is_zero = (db[i] == 0); + is_one = (db[i] == 1); + salt_ofs += (looking_for_one & is_one) * (static_cast(++i)); + looking_for_one &= ~is_one; + invalid_db_padding |= (looking_for_one & ~is_zero); } - } - if (salt_ofs == -1) { - return false; - } - if (db[salt_ofs - 1] != 1) { - return false; + + is_valid &= (invalid_db_padding == 0); } /* Verify salt. */ const u8 *salt = db + salt_ofs; const size_t salt_size = db_len - salt_ofs; - if (salt_size == 0) { - return false; - } + is_valid &= (salt_size != 0); /* Verify hash. */ u8 cmp_hash[HashSize]; ON_SCOPE_EXIT { ClearMemory(cmp_hash, sizeof(cmp_hash)); }; ComputeHashWithPadding(cmp_hash, hash, salt, salt_size); - return IsSameBytes(cmp_hash, h, HashSize); + is_valid &= IsSameBytes(cmp_hash, h, HashSize); + + /* Succeed if all our checks succeeded. */ + return is_valid; } }; diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 14a4db6ce..5ba4d3911 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -58,6 +58,8 @@ namespace ams::svc { static constexpr bool IsInput = std::is_const::type>::value; private: T pointer; + public: + constexpr ALWAYS_INLINE UserPointer(T p) : pointer(p) { /* ... */ } }; template