diff options
author | Never <[email protected]> | 2017-02-21 17:45:26 +0100 |
---|---|---|
committer | Never <[email protected]> | 2017-02-21 17:45:26 +0100 |
commit | 63e0ef29e578c3d7b282c3b4f84972694345b134 (patch) | |
tree | b7ca890c1ad1782f78b2679356ee8757aa10ca26 /src/lib/pk_pad | |
parent | b521e251b2786fa8a06a1d7de10072769b7d685d (diff) |
fix possible iso9796 side channel and add length check
Diffstat (limited to 'src/lib/pk_pad')
-rw-r--r-- | src/lib/pk_pad/iso9796/iso9796.cpp | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/src/lib/pk_pad/iso9796/iso9796.cpp b/src/lib/pk_pad/iso9796/iso9796.cpp index f123a7e15..f56689389 100644 --- a/src/lib/pk_pad/iso9796/iso9796.cpp +++ b/src/lib/pk_pad/iso9796/iso9796.cpp @@ -9,6 +9,7 @@ #include <botan/mgf1.h> #include <botan/internal/bit_ops.h> #include <botan/hash_id.h> +#include <botan/internal/ct_utils.h> namespace Botan { @@ -125,7 +126,8 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, } secure_vector<uint8_t> coded = const_coded; - + + CT::poison(coded.data(), coded.size()); //remove mask uint8_t* DB = coded.data(); const size_t DB_size = coded.size() - HASH_SIZE - tLength; @@ -137,19 +139,26 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, DB[0] &= 0x7F; //recover msg1 and salt - size_t msg1_offset = 0; - for(size_t j = 0; j != DB_size; ++j) + size_t msg1_offset = 1; + uint8_t waiting_for_delim = 0xFF; + uint8_t bad_input = 0; + for(size_t j = 0; j < DB_size; ++j) { - if(DB[j] == 0x01) - { - msg1_offset = j + 1; - break; - } - } - if(msg1_offset == 0) - { - return false; + const uint8_t one_m = CT::is_equal<uint8_t>(DB[j], 0x01); + const uint8_t zero_m = CT::is_zero(DB[j]); + const uint8_t add_m = waiting_for_delim & zero_m; + + bad_input |= waiting_for_delim & ~(zero_m | one_m); + msg1_offset += CT::select<uint8_t>(add_m, 1, 0); + + waiting_for_delim &= zero_m; } + + //invalid, if delimiter 0x01 was not found or msg1_offset is too big + bad_input |= waiting_for_delim; + bad_input |= CT::is_less(coded.size(), tLength + HASH_SIZE + msg1_offset + SALT_SIZE); + //in case that msg1_offset is too big, just continue with offset = 0. + msg1_offset = CT::select<size_t>(bad_input, 0, msg1_offset); secure_vector<uint8_t> msg1(coded.begin() + msg1_offset, coded.end() - tLength - HASH_SIZE - SALT_SIZE); secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(), @@ -186,9 +195,12 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, hash->update(msg2); hash->update(salt); secure_vector<uint8_t> H2 = hash->final(); - + //check if H3 == H2 - return same_mem(H3.data(), H2.data(), HASH_SIZE); + bad_input |= CT::is_equal<uint8_t>(same_mem(H3.data(), H2.data(), HASH_SIZE), false); + CT::unpoison(coded.data(), coded.size()); + + return (bad_input == 0); } } |