Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curve25519 signatures made compatible with 2.18.1 release #2774

Open
wants to merge 1 commit into
base: release-2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions news.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Release Notes
========================================

<<<<<<< HEAD
Version 2.18.1, 2021-05-09
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -87,6 +88,11 @@ Version 2.17.1, 2020-11-07
* Re-enable support for the x86 CLMUL instruction on Visual C++, which was
accidentally disabled starting in 2.12.0. (GH #2460)

=======
Version 3.0.0, Not Yet Released
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>>>>>>> c9fcd92e4 (Bump version to 3.0.0-alpha0)
Version 2.17.0, 2020-11-05
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
8 changes: 8 additions & 0 deletions src/build-data/version.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@

<<<<<<< HEAD
release_major = 2
release_minor = 18
release_patch = 1
release_suffix = ''
release_so_abi_rev = 18
=======
release_major = 3
release_minor = 0
release_patch = 0
release_suffix = '-alpha0'
release_so_abi_rev = 0
>>>>>>> c9fcd92e4 (Bump version to 3.0.0-alpha0)

# These are set by the distribution script
release_vc_rev = None
Expand Down
262 changes: 262 additions & 0 deletions src/lib/pubkey/curve25519/curve25519.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,83 @@
*/

#include <botan/curve25519.h>
#include <botan/internal/ed25519_internal.h>
#include <botan/internal/pk_ops_impl.h>
#include <botan/ber_dec.h>
#include <botan/der_enc.h>
#include <botan/rng.h>

namespace Botan {
/**
* Ed25519 signing operation ('C25519' - signs with a Curve25519 key)
*/
class Ed25519_C25519_Sign_Operation : public PK_Ops::Signature
{
public:
Ed25519_C25519_Sign_Operation(const Curve25519_PrivateKey& key) : m_key(key)
{
}
size_t signature_length() const override
{
return 64;
}
void update(const uint8_t msg[], size_t msg_len) override
{
m_msg.insert(m_msg.end(), msg, msg + msg_len);
}

secure_vector<uint8_t> sign(RandomNumberGenerator& rng) override
{
secure_vector<uint8_t> sig(64);
std::vector<uint8_t> rand;
rand.resize(64);
rng.randomize(rand.data(), 64);
secure_vector<uint8_t> privKey25519RAW;

BER_Decoder(m_key.private_key_bits()).decode(privKey25519RAW, Botan::ASN1_Tag::OCTET_STRING).discard_remaining();

curve25519_sign(sig.data(), privKey25519RAW.data(), m_msg.data(), m_msg.size(), rand.data());

m_msg.clear();
return sig;

}

private:
std::vector<uint8_t> m_msg;
const Curve25519_PrivateKey& m_key;
};

/**
* Ed255190_C25519 verifying operation
*/
class Ed25519_C25519_Verify_Operation : public PK_Ops::Verification
{
public:
Ed25519_C25519_Verify_Operation(const Curve25519_PublicKey& key) : m_key(key)
{
}

void update(const uint8_t msg[], size_t msg_len) override
{
m_msg.insert(m_msg.end(), msg, msg + msg_len);
}

bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
{
if (sig_len != 64)
return false;

bool ok = curve25519_verify(sig, m_key.public_key_bits().data(), m_msg.data(), m_msg.size());
m_msg.clear();
return ok;
}

private:
std::vector<uint8_t> m_msg;
const Curve25519_PublicKey& m_key;
};

void curve25519_basepoint(uint8_t mypublic[32], const uint8_t secret[32])
{
const uint8_t basepoint[32] = { 9 };
Expand Down Expand Up @@ -59,6 +129,18 @@ std::vector<uint8_t> Curve25519_PublicKey::public_key_bits() const
{
return m_public;
}
std::unique_ptr<PK_Ops::Verification>
Curve25519_PublicKey::create_verification_op(const std::string& params,
const std::string& provider) const
{
if (provider == "base" || provider.empty())
{
if (params == "" || params == "Pure")
return std::unique_ptr<PK_Ops::Verification>(new Ed25519_C25519_Verify_Operation(*this));

}
throw Provider_Not_Found(algo_name(), provider);
}

Curve25519_PrivateKey::Curve25519_PrivateKey(const secure_vector<uint8_t>& secret_key)
{
Expand Down Expand Up @@ -139,5 +221,185 @@ Curve25519_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/,
return std::unique_ptr<PK_Ops::Key_Agreement>(new Curve25519_KA_Operation(*this, params));
throw Provider_Not_Found(algo_name(), provider);
}
std::unique_ptr<PK_Ops::Signature>
Curve25519_PrivateKey::create_signature_op(RandomNumberGenerator&,
const std::string& params,
const std::string& provider) const
{
if (provider == "base" || provider.empty())
{
if (params == "Pure")
return std::unique_ptr<PK_Ops::Signature>(new Ed25519_C25519_Sign_Operation(*this));

}
throw Provider_Not_Found(algo_name(), provider);
}

void clamp(unsigned char* a)
{
a[0] &= 248; a[31] &= 127; a[31] |= 64;
}
int curve25519_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const size_t msg_len,
const unsigned char* random)
{
std::vector<uint8_t> privkey(32);
std::memcpy(privkey.data(), curve25519_privkey, 32);
clamp(privkey.data());

ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */
unsigned char *sigbuf; /* working buffer */
unsigned char sign_bit = 0;

if ((sigbuf = (unsigned char*)malloc(msg_len + 128)) == 0) {
memset(signature_out, 0, 64);
return -1;
}

/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(ed_pubkey, privkey.data());
sign_bit = ed_pubkey[31] & 0x80;

/* Perform an Ed25519 signature with explicit private key */
ed25519_sign_modified(signature_out, msg, msg_len, privkey.data(),
ed_pubkey, random);

/* Encode the sign bit into signature (in unused high bit of S) */
signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */
signature_out[63] |= sign_bit;

free(sigbuf);
return 0;
}

int ed25519_sign_modified(
unsigned char *signature_out,
const unsigned char *m, size_t mlen,
const unsigned char *sk, const unsigned char* pk,
const unsigned char* random
)
{
unsigned char nonce[64];
unsigned char hram[64];
unsigned char * sigbuf;

SHA_512 sha;
ge_p3 R;
int count = 0;

if ((sigbuf = (unsigned char*)malloc(mlen+128)) == 0) {
memset(signature_out, 0, 64);
return -1;
}

memmove(sigbuf + 64, m, mlen);
memmove(sigbuf + 32, sk, 32);
sigbuf[0] = 0xFE;
for (count = 1; count < 32; count++)
sigbuf[count] = 0xFF;

/* add suffix of random data */
memmove(sigbuf + mlen + 64, random, 64);
sha.update(sigbuf, mlen + 128);
sha.final(nonce);
memmove(sigbuf + 32, pk, 32);

sc_reduce(nonce);
ge_scalarmult_base(sigbuf, nonce);

sha.update(sigbuf, mlen + 64);
sha.final(hram);

sc_reduce(hram);
sc_muladd(sigbuf + 32, hram, sk, nonce);
memmove(signature_out, sigbuf, 64);

free(sigbuf);
return 0;
}

int ed25519_verify_modified(
const unsigned char *m, size_t mlen, const unsigned char *sig,
const unsigned char *pk
)
{
unsigned char pkcopy[32];
unsigned char rcopy[32];
unsigned char scopy[32];
unsigned char h[64];
unsigned char rcheck[32];
unsigned char *verifybuf = NULL;
ge_p3 A;
ge_p2 R;

std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-512"));
int retvalue = 0;

if (sig[63] & 224)
goto exit;

if (ge_frombytes_negate_vartime(&A, pk) != 0)
goto exit;

if ((verifybuf = (unsigned char*) malloc(mlen+64)) == 0) {
goto exit;
}

memmove(pkcopy, pk, 32);
memmove(rcopy, sig, 32);
memmove(scopy, sig + 32, 32);
memmove(verifybuf, sig, 64);
memmove(verifybuf+64, m, mlen);
memmove(verifybuf + 32, pkcopy, 32);

hash->update(verifybuf, mlen+64);
hash->final(h);

sc_reduce(h);

ge_double_scalarmult_vartime(rcheck, h, &A, scopy);

if (constant_time_compare(rcheck, rcopy, 32)) {
retvalue = 1;
}

exit:
if (verifybuf != NULL) {
free(verifybuf);
}

return retvalue;
}


int curve25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const size_t msg_len)
{
fe u;
fe y;
unsigned char ed_pubkey[32];
unsigned char loc_signature[64];
int result;

fe_frombytes(u, curve25519_pubkey);

/* Convert montgomery x-coordinate into an edwards y - coordinate:
y = (u - 1) / (u + 1) */
fe_montx_to_edy(&y, u);
fe_tobytes(ed_pubkey, y);

ed_pubkey[31] &= 0x7F;
ed_pubkey[31] |= (signature[63] & 0x80);
memmove(loc_signature, signature, 64);
loc_signature[63] &= 0x7F;

result = ed25519_verify_modified(msg, msg_len, loc_signature, ed_pubkey);

err:

return result;
}
}
27 changes: 27 additions & 0 deletions src/lib/pubkey/curve25519/curve25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class BOTAN_PUBLIC_API(2,0) Curve25519_PublicKey : public virtual Public_Key
*/
explicit Curve25519_PublicKey(const secure_vector<uint8_t>& pub) :
m_public(pub.begin(), pub.end()) {}

std::unique_ptr<PK_Ops::Verification>
create_verification_op(const std::string& params,
const std::string& provider) const override;

protected:
Curve25519_PublicKey() = default;
Expand Down Expand Up @@ -94,6 +98,10 @@ class BOTAN_PUBLIC_API(2,0) Curve25519_PrivateKey final : public Curve25519_Publ
create_key_agreement_op(RandomNumberGenerator& rng,
const std::string& params,
const std::string& provider) const override;
std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator& rng,
const std::string& params,
const std::string& provider) const override;

private:
secure_vector<uint8_t> m_private;
Expand All @@ -119,5 +127,24 @@ void BOTAN_PUBLIC_API(2,0) curve25519_basepoint(uint8_t mypublic[32],
const uint8_t secret[32]);

}
namespace Botan {
/* returns 0 on success */
int curve25519_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const size_t msg_len,
const unsigned char * random); /* 64 bytes */

/* returns 0 on success */
int curve25519_verify(const unsigned char* signature, /* 64 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const size_t msg_len);

int ed25519_sign_modified(
unsigned char *sm,
const unsigned char *m, size_t mlen,
const unsigned char *sk, const unsigned char* pk,
const unsigned char* random
);

}
#endif
15 changes: 14 additions & 1 deletion src/lib/pubkey/ed25519/ed25519_fe.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,20 @@ inline void fe_pow22523(fe& x, const fe& y)
{
x = FE_25519::pow_22523(y);
}

inline void fe_montx_to_edy(fe *y, const fe u)
{
/*
y = (u - 1) / (u + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
*/
fe one, um1, up1;

fe_1(one);
fe_sub(um1, u, one);
fe_add(up1, u, one);
fe_invert(up1, up1);
fe_mul(*y, um1, up1);
}
}

#endif
Loading