2018-02-04 03:22:01 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2017-10-01 04:14:45 +02:00
|
|
|
|
|
|
|
#include <sodium.h>
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Internal
|
|
|
|
//
|
|
|
|
|
2017-10-01 12:05:09 +02:00
|
|
|
struct throw_on_error
|
2017-10-01 04:14:45 +02:00
|
|
|
{
|
2017-10-01 12:05:09 +02:00
|
|
|
throw_on_error(const int &val)
|
|
|
|
{
|
|
|
|
if(unlikely(val != 0))
|
|
|
|
throw ircd::nacl::error("sodium error");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// ircd/nacl.h
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::nacl::version()
|
|
|
|
{
|
|
|
|
return ::sodium_version_string();
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::nacl::init::init()
|
|
|
|
{
|
|
|
|
if(::sodium_init() < 0)
|
2017-10-01 04:14:45 +02:00
|
|
|
throw std::runtime_error("sodium_init(): error");
|
|
|
|
}
|
|
|
|
|
2017-10-01 12:05:09 +02:00
|
|
|
ircd::nacl::init::~init()
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-10-01 04:14:45 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// ircd/buffer.h
|
|
|
|
//
|
|
|
|
|
|
|
|
void
|
2018-02-03 08:20:26 +01:00
|
|
|
ircd::buffer::zero(const mutable_buffer &buf)
|
2017-10-01 04:14:45 +02:00
|
|
|
{
|
|
|
|
sodium_memzero(data(buf), size(buf));
|
|
|
|
}
|
2017-10-01 12:05:09 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// ircd/ed25519
|
|
|
|
//
|
|
|
|
|
2017-10-03 12:57:18 +02:00
|
|
|
static_assert(ircd::ed25519::SK_SZ == crypto_sign_ed25519_SECRETKEYBYTES);
|
2017-10-01 12:05:09 +02:00
|
|
|
static_assert(ircd::ed25519::PK_SZ == crypto_sign_ed25519_PUBLICKEYBYTES);
|
|
|
|
|
2017-10-03 12:57:18 +02:00
|
|
|
ircd::ed25519::sk::sk(pk *const &pk_arg,
|
2018-02-03 08:20:26 +01:00
|
|
|
const const_buffer &seed)
|
2017-10-03 12:57:18 +02:00
|
|
|
:key
|
|
|
|
{
|
|
|
|
reinterpret_cast<uint8_t *>(::sodium_malloc(crypto_sign_ed25519_SECRETKEYBYTES)),
|
|
|
|
&::sodium_free
|
|
|
|
}
|
|
|
|
{
|
|
|
|
assert(size(seed) >= SEED_SZ);
|
|
|
|
|
|
|
|
pk discard, &pk
|
|
|
|
{
|
|
|
|
pk_arg? *pk_arg : discard
|
|
|
|
};
|
|
|
|
|
2018-02-03 08:20:26 +01:00
|
|
|
const auto pk_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<uint8_t *>(pk.data())
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto seed_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<const uint8_t *>(data(seed))
|
|
|
|
};
|
|
|
|
|
2017-10-03 12:57:18 +02:00
|
|
|
throw_on_error
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
::crypto_sign_ed25519_seed_keypair(pk_data, key.get(), seed_data)
|
2017-10-03 12:57:18 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::ed25519::sk::sk(const std::string &filename,
|
2017-10-01 12:05:09 +02:00
|
|
|
pk *const &pk_arg)
|
2018-03-01 11:53:27 +01:00
|
|
|
try
|
2017-10-01 12:05:09 +02:00
|
|
|
:key
|
|
|
|
{
|
|
|
|
reinterpret_cast<uint8_t *>(::sodium_malloc(crypto_sign_ed25519_SECRETKEYBYTES)),
|
|
|
|
&::sodium_free
|
|
|
|
}
|
|
|
|
{
|
|
|
|
pk discard, &pk
|
|
|
|
{
|
|
|
|
pk_arg? *pk_arg : discard
|
|
|
|
};
|
|
|
|
|
2018-02-03 08:20:26 +01:00
|
|
|
const auto pk_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<uint8_t *>(pk.data())
|
|
|
|
};
|
|
|
|
|
|
|
|
const mutable_buffer key_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<char *>(key.get()), SK_SZ
|
|
|
|
};
|
|
|
|
|
2018-03-01 11:53:27 +01:00
|
|
|
if(!fs::exists(filename))
|
2017-10-03 12:57:18 +02:00
|
|
|
{
|
|
|
|
throw_on_error
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
::crypto_sign_ed25519_keypair(pk_data, key.get())
|
2017-10-03 12:57:18 +02:00
|
|
|
};
|
|
|
|
|
2018-02-03 08:20:26 +01:00
|
|
|
fs::write(filename, key_data);
|
2017-10-03 12:57:18 +02:00
|
|
|
}
|
2018-03-01 11:53:27 +01:00
|
|
|
else fs::read(filename, key_data);
|
2017-10-03 12:57:18 +02:00
|
|
|
|
2017-10-01 12:05:09 +02:00
|
|
|
throw_on_error
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
::crypto_sign_ed25519_sk_to_pk(pk_data, key.get())
|
2017-10-01 12:05:09 +02:00
|
|
|
};
|
|
|
|
}
|
2018-03-01 11:53:27 +01:00
|
|
|
catch(const fs::error &e)
|
|
|
|
{
|
|
|
|
throw error
|
|
|
|
{
|
|
|
|
"Failed to read existing ed25519 secret key in: %s :%s",
|
|
|
|
filename,
|
|
|
|
e.what()
|
|
|
|
};
|
|
|
|
}
|
2017-10-01 12:05:09 +02:00
|
|
|
|
|
|
|
ircd::ed25519::sig
|
2018-02-03 08:20:26 +01:00
|
|
|
ircd::ed25519::sk::sign(const const_buffer &msg)
|
2017-10-01 12:05:09 +02:00
|
|
|
const
|
|
|
|
{
|
|
|
|
struct sig sig;
|
2018-02-03 08:20:26 +01:00
|
|
|
unsigned long long sig_sz;
|
|
|
|
|
|
|
|
const auto sig_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<uint8_t *>(sig.data())
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto msg_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<const uint8_t *>(buffer::data(msg))
|
|
|
|
};
|
|
|
|
|
2017-10-01 12:05:09 +02:00
|
|
|
throw_on_error
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
::crypto_sign_ed25519_detached(sig_data,
|
2017-10-01 12:05:09 +02:00
|
|
|
&sig_sz,
|
2018-02-03 08:20:26 +01:00
|
|
|
msg_data,
|
2017-10-01 12:05:09 +02:00
|
|
|
buffer::size(msg),
|
|
|
|
key.get())
|
|
|
|
};
|
|
|
|
|
|
|
|
assert(sig_sz <= sig.size());
|
|
|
|
assert(sig.size() >= sig_sz);
|
|
|
|
memset(sig.data() + sig.size() - sig_sz, 0, sig.size() - sig_sz);
|
|
|
|
return sig;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2018-02-03 08:20:26 +01:00
|
|
|
ircd::ed25519::pk::verify(const const_buffer &msg,
|
2017-10-01 12:05:09 +02:00
|
|
|
const sig &sig)
|
|
|
|
const
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
const auto sig_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<const uint8_t *>(sig.data())
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto msg_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<const uint8_t *>(buffer::data(msg))
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto key_data
|
|
|
|
{
|
|
|
|
reinterpret_cast<const uint8_t *>(data())
|
|
|
|
};
|
|
|
|
|
2017-10-01 12:05:09 +02:00
|
|
|
const int ret
|
|
|
|
{
|
2018-02-03 08:20:26 +01:00
|
|
|
::crypto_sign_ed25519_verify_detached(sig_data,
|
|
|
|
msg_data,
|
2017-10-01 12:05:09 +02:00
|
|
|
buffer::size(msg),
|
2018-02-03 08:20:26 +01:00
|
|
|
key_data)
|
2017-10-01 12:05:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return ret == 0? true:
|
|
|
|
ret == -1? false:
|
|
|
|
throw nacl::error("verify failed: %d", ret);
|
|
|
|
}
|