Commit 0c912b10 authored by Luker's avatar Luker

mark possible timing problems

parent a29d0971
......@@ -72,6 +72,7 @@ public:
Auth& operator= (Auth &&) = default;
virtual ~Auth() {}
// see issue #1 (constant time) when implementing
virtual Auth_Result authenticate (const Device_ID &dev_id,
const Service_ID &service,
const Username &auth_user,
......
......@@ -55,6 +55,7 @@ public:
{ return Auth::ID {1}; }
};
// see issue #1 (constant time)
FENRIR_INLINE Auth_Result Token::authenticate (const Device_ID &dev_id,
const Service_ID &service,
const Username &auth_user,
......
/*
* Copyright (c) 2017, Luca Fulchir<luca@fulchir.it>, All rights reserved.
*
* This file is part of libFenrir.
*
* libFenrir is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libFenrir is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and a copy of the GNU Lesser General Public License
* along with libFenrir. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Fenrir/v1/common.hpp"
#include <array>
#include <type_safe/strong_typedef.hpp>
namespace Fenrir__v1 {
namespace Impl {
struct FENRIR_LOCAL Token_ID :
type_safe::strong_typedef<Token_ID, std::array<uint8_t, 16>>
{
using strong_typedef::strong_typedef;
bool operator== (const Token_ID &rhs)
{
size_t diff = 0;
for (size_t idx = 0; idx < 16; ++idx) {
if (static_cast<std::array<uint8_t, 16>> (*this)[idx] !=
static_cast<std::array<uint8_t, 16>> (rhs)[idx]) {
++diff;
}
}
return diff == 0;
}
bool operator< (const Token_ID &rhs)
{
size_t diff = 0;
for (size_t idx = 0; idx < 16; ++idx) {
if (static_cast<std::array<uint8_t, 16>> (*this)[idx] <
static_cast<std::array<uint8_t, 16>> (rhs)[idx]) {
if (diff == 0)
++diff;
}
}
return diff == 0;
}
};
} // namespace Impl
} // namespace Fenrir__v1
......@@ -33,6 +33,7 @@ struct FENRIR_LOCAL Token_t :
using strong_typedef::strong_typedef;
bool operator== (const Token_t &rhs) const
{
// see issue #1 (constant time)
size_t diff = 0;
for (size_t idx = 0; idx < 32; ++idx) {
if (static_cast<std::array<uint8_t, 32>> (*this)[idx] !=
......
......@@ -53,6 +53,7 @@ public:
// Not a string. NOT NULL-terminated.
Username (const gsl::span<const uint8_t> raw)
{
// see issue #1 (constant time)
// check the index: no '@', '@' at first char, or domain of less
// than 4 chars
......@@ -104,6 +105,7 @@ public:
{ return user.size() != 0 && domain.size() > 4; }
bool operator== (const Fenrir__v1::Impl::Username& user2) const
{
// see issue #1 (constant time)
return user.size() == user2.user.size() &&
domain.size() == user2.domain.size() &&
std::equal (user.begin(), user.end(), user2.user.begin()) &&
......@@ -117,6 +119,7 @@ public:
}
bool is_anonymous() const {
// see issue #1 (constant time)
std::array<uint8_t, 9> anon = {{ 'a','n','o','n','y','m','o','u','s' }};
return anon.size() == user.size() &&
std::equal (user.begin(), user.end(), anon.begin());
......
......@@ -64,6 +64,12 @@ public:
{}
};
// see issue #1 (constant time)
// the DB should return data after the same time
// wether the user exists or not. This can be tricky for
// databases with lots of users, where finding the first is
// easy but you need to go through the whole list to return
// "non-existing".
virtual struct auth_data get_auth (const Device_ID &device_id,
const Service_ID &service,
const Username &auth_user,
......
......@@ -46,6 +46,8 @@ constexpr uint16_t conn_init_minlen = pkt_init_minlen - PKT_MINLEN;
} // empty namespace
// TODO: check all against issue #1 (constant time)
FENRIR_INLINE bool Handshake::add_auth (const Crypto::Auth::ID id)
{
Shared_Lock_Guard<Shared_Lock_Write> lock {Shared_Lock_NN{&_mtx_auths}};
......
......@@ -33,6 +33,8 @@ struct FENRIR_LOCAL Service_ID :
using strong_typedef::strong_typedef;
bool operator== (const Service_ID &rhs) const
{
// see issue #1
// try to make this parse the whole array instead of returning early
size_t diff = 0;
for (size_t idx = 0; idx < 16; ++idx) {
if (static_cast<std::array<uint8_t, 16>> (*this)[idx] !=
......@@ -45,15 +47,21 @@ struct FENRIR_LOCAL Service_ID :
bool operator< (const Service_ID &rhs) const
{
size_t diff = 0;
// see issue #1
// try to make this parse the whole array instead of returning early
ssize_t diff = 0;
for (size_t idx = 0; idx < 16; ++idx) {
if (static_cast<std::array<uint8_t, 16>> (*this)[idx] <
static_cast<std::array<uint8_t, 16>> (rhs)[idx]) {
if (diff == 0)
if (diff <= 0)
--diff;
} else if (static_cast<std::array<uint8_t, 16>> (*this)[idx] >
static_cast<std::array<uint8_t, 16>> (rhs)[idx]) {
if (diff >= 0)
++diff;
}
}
return diff == 0;
return diff < 0;
}
};
......
......@@ -33,6 +33,7 @@ namespace Fenrir__v1 {
namespace Impl {
// TODO: DEDUPLICATE this code
// TODO: see issue #1 (constant time)
FENRIR_LOCAL constexpr size_t z85_encoded_size (const size_t in);
FENRIR_LOCAL constexpr size_t z85_encoded_size_no_header (const size_t in);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment