Skip to content
Permalink
Browse files

MDEV-12160 Modern alternative to the SHA1 authentication plugin

ED25519 authentication plugin
  • Loading branch information...
vuvova committed Mar 5, 2017
1 parent 269ab56 commit 7120118a5e97477778715ebdc8e4fba548a6dc87
Showing with 5,124 additions and 0 deletions.
  1. +50 −0 mysql-test/suite/plugins/r/auth_ed25519.result
  2. +44 −0 mysql-test/suite/plugins/t/auth_ed25519.test
  3. +25 −0 plugin/auth_ed25519/CMakeLists.txt
  4. +12 −0 plugin/auth_ed25519/README
  5. +72 −0 plugin/auth_ed25519/client_ed25519.c
  6. +32 −0 plugin/auth_ed25519/common.h
  7. +2 −0 plugin/auth_ed25519/crypto_hash_sha256.h
  8. +2 −0 plugin/auth_ed25519/crypto_hash_sha512.h
  9. +5 −0 plugin/auth_ed25519/crypto_int32.h
  10. +5 −0 plugin/auth_ed25519/crypto_int64.h
  11. +11 −0 plugin/auth_ed25519/crypto_sign.h
  12. +5 −0 plugin/auth_ed25519/crypto_uint32.h
  13. +5 −0 plugin/auth_ed25519/crypto_uint64.h
  14. +1 −0 plugin/auth_ed25519/crypto_verify.h
  15. +2 −0 plugin/auth_ed25519/crypto_verify_32.h
  16. +58 −0 plugin/auth_ed25519/ed25519-t.c
  17. +1 −0 plugin/auth_ed25519/randombytes.h
  18. +4 −0 plugin/auth_ed25519/ref10/api.h
  19. +1,344 −0 plugin/auth_ed25519/ref10/base.h
  20. +40 −0 plugin/auth_ed25519/ref10/base2.h
  21. +1 −0 plugin/auth_ed25519/ref10/d.h
  22. +1 −0 plugin/auth_ed25519/ref10/d2.h
  23. +56 −0 plugin/auth_ed25519/ref10/fe.h
  24. +19 −0 plugin/auth_ed25519/ref10/fe_0.c
  25. +19 −0 plugin/auth_ed25519/ref10/fe_1.c
  26. +57 −0 plugin/auth_ed25519/ref10/fe_add.c
  27. +63 −0 plugin/auth_ed25519/ref10/fe_cmov.c
  28. +29 −0 plugin/auth_ed25519/ref10/fe_copy.c
  29. +73 −0 plugin/auth_ed25519/ref10/fe_frombytes.c
  30. +14 −0 plugin/auth_ed25519/ref10/fe_invert.c
  31. +16 −0 plugin/auth_ed25519/ref10/fe_isnegative.c
  32. +19 −0 plugin/auth_ed25519/ref10/fe_isnonzero.c
  33. +253 −0 plugin/auth_ed25519/ref10/fe_mul.c
  34. +45 −0 plugin/auth_ed25519/ref10/fe_neg.c
  35. +13 −0 plugin/auth_ed25519/ref10/fe_pow22523.c
  36. +149 −0 plugin/auth_ed25519/ref10/fe_sq.c
  37. +160 −0 plugin/auth_ed25519/ref10/fe_sq2.c
  38. +57 −0 plugin/auth_ed25519/ref10/fe_sub.c
  39. +119 −0 plugin/auth_ed25519/ref10/fe_tobytes.c
  40. +95 −0 plugin/auth_ed25519/ref10/ge.h
  41. +11 −0 plugin/auth_ed25519/ref10/ge_add.c
  42. +97 −0 plugin/auth_ed25519/ref10/ge_add.h
  43. +96 −0 plugin/auth_ed25519/ref10/ge_double_scalarmult.c
  44. +50 −0 plugin/auth_ed25519/ref10/ge_frombytes.c
  45. +11 −0 plugin/auth_ed25519/ref10/ge_madd.c
  46. +88 −0 plugin/auth_ed25519/ref10/ge_madd.h
  47. +11 −0 plugin/auth_ed25519/ref10/ge_msub.c
  48. +88 −0 plugin/auth_ed25519/ref10/ge_msub.h
  49. +12 −0 plugin/auth_ed25519/ref10/ge_p1p1_to_p2.c
  50. +13 −0 plugin/auth_ed25519/ref10/ge_p1p1_to_p3.c
  51. +8 −0 plugin/auth_ed25519/ref10/ge_p2_0.c
  52. +11 −0 plugin/auth_ed25519/ref10/ge_p2_dbl.c
  53. +73 −0 plugin/auth_ed25519/ref10/ge_p2_dbl.h
  54. +9 −0 plugin/auth_ed25519/ref10/ge_p3_0.c
  55. +12 −0 plugin/auth_ed25519/ref10/ge_p3_dbl.c
  56. +17 −0 plugin/auth_ed25519/ref10/ge_p3_to_cached.c
  57. +12 −0 plugin/auth_ed25519/ref10/ge_p3_to_p2.c
  58. +14 −0 plugin/auth_ed25519/ref10/ge_p3_tobytes.c
  59. +8 −0 plugin/auth_ed25519/ref10/ge_precomp_0.c
  60. +105 −0 plugin/auth_ed25519/ref10/ge_scalarmult_base.c
  61. +11 −0 plugin/auth_ed25519/ref10/ge_sub.c
  62. +97 −0 plugin/auth_ed25519/ref10/ge_sub.h
  63. +14 −0 plugin/auth_ed25519/ref10/ge_tobytes.c
  64. +23 −0 plugin/auth_ed25519/ref10/keypair.c
  65. +48 −0 plugin/auth_ed25519/ref10/open.c
  66. +160 −0 plugin/auth_ed25519/ref10/pow22523.h
  67. +160 −0 plugin/auth_ed25519/ref10/pow225521.h
  68. +15 −0 plugin/auth_ed25519/ref10/sc.h
  69. +368 −0 plugin/auth_ed25519/ref10/sc_muladd.c
  70. +275 −0 plugin/auth_ed25519/ref10/sc_reduce.c
  71. +41 −0 plugin/auth_ed25519/ref10/sign.c
  72. +1 −0 plugin/auth_ed25519/ref10/sqrtm1.h
  73. +40 −0 plugin/auth_ed25519/ref10/verify.c
  74. +147 −0 plugin/auth_ed25519/server_ed25519.c
@@ -0,0 +1,50 @@
create function ed25519_password returns string soname "auth_ed25519.so";
select ed25519_password();
ERROR HY000: Can't initialize function 'ed25519_password'; Wrong arguments to ed25519_password()
select ed25519_password(1);
ERROR HY000: Can't initialize function 'ed25519_password'; Wrong arguments to ed25519_password()
select ed25519_password("foo", "bar");
ERROR HY000: Can't initialize function 'ed25519_password'; Wrong arguments to ed25519_password()
select ed25519_password("foo");
ERROR HY000: Can't initialize function 'ed25519_password'; Authentication plugin ed25519 is not loaded
install soname 'auth_ed25519';
select ed25519_password("foo");
ed25519_password("foo")
NNJledu0Vmk+VAZyz5IvUt3g1lMuNb8GvgE6fFMvIOA
select ed25519_password("foobar");
ed25519_password("foobar")
LgZlMsxPDw66qLCfGWRu4IVKqzyAqlA1aXSZbax5maE
select ed25519_password("foo bar");
ed25519_password("foo bar")
6EFKeQLw+p5Ovk8tD+tAi3Agyg7ItukdswOBpTB6f40
select ed25519_password(NULL);
ed25519_password(NULL)
NULL
select * from information_schema.plugins where plugin_name='ed25519';
PLUGIN_NAME ed25519
PLUGIN_VERSION 1.0
PLUGIN_STATUS ACTIVE
PLUGIN_TYPE AUTHENTICATION
PLUGIN_TYPE_VERSION 2.1
PLUGIN_LIBRARY auth_ed25519.so
PLUGIN_LIBRARY_VERSION 1.12
PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Elliptic curve ED25519 based authentication
PLUGIN_LICENSE GPL
LOAD_OPTION ON
PLUGIN_MATURITY Beta
PLUGIN_AUTH_VERSION 1.0-alpha
create user test1@localhost identified via ed25519 using 'XQNqhYzon4REkXYuuJ4r+9UKSgoNpljksmKLJbEXrgk';
show grants for test1@localhost;
Grants for test1@localhost
GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'XQNqhYzon4REkXYuuJ4r+9UKSgoNpljksmKLJbEXrgk'
connect(localhost,test1,public,test,PORT,SOCKET);
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES)
select current_user();
current_user()
test1@localhost
drop user test1@localhost;
uninstall plugin ed25519;
select ed25519_password("foo");
ERROR HY000: Can't initialize function 'ed25519_password'; Authentication plugin ed25519 is not loaded
drop function ed25519_password;
@@ -0,0 +1,44 @@
#
# MDEV-12160 Modern alternative to the SHA1 authentication plugin
#
source include/not_embedded.inc;
if (!$AUTH_ED25519_SO) {
skip No auth_ed25519 plugin;
}

replace_result dll so;
eval create function ed25519_password returns string soname "$AUTH_ED25519_SO";
error ER_CANT_INITIALIZE_UDF;
select ed25519_password();
error ER_CANT_INITIALIZE_UDF;
select ed25519_password(1);
error ER_CANT_INITIALIZE_UDF;
select ed25519_password("foo", "bar");
error ER_CANT_INITIALIZE_UDF;
select ed25519_password("foo");

install soname 'auth_ed25519';
select ed25519_password("foo");
select ed25519_password("foobar");
select ed25519_password("foo bar");
select ed25519_password(NULL);

replace_result dll so;
query_vertical select * from information_schema.plugins where plugin_name='ed25519';
let $pwd=`select ed25519_password("secret")`;
eval create user test1@localhost identified via ed25519 using '$pwd';
show grants for test1@localhost;

replace_result $MASTER_MYPORT PORT $MASTER_MYSOCK SOCKET;
error ER_ACCESS_DENIED_ERROR;
connect con1, localhost, test1, public;
connect con1, localhost, test1, secret;
select current_user();
disconnect con1;
connection default;

drop user test1@localhost;
uninstall plugin ed25519;
error ER_CANT_INITIALIZE_UDF;
select ed25519_password("foo");
drop function ed25519_password;
@@ -0,0 +1,25 @@
SET(REF10_SOURCES
ref10/fe_0.c ref10/fe_1.c ref10/fe_add.c ref10/fe_cmov.c ref10/fe_copy.c
ref10/fe_frombytes.c ref10/fe_invert.c ref10/fe_isnegative.c
ref10/fe_isnonzero.c ref10/fe_mul.c ref10/fe_neg.c ref10/fe_pow22523.c
ref10/fe_sq.c ref10/fe_sq2.c ref10/fe_sub.c ref10/fe_tobytes.c
ref10/ge_add.c ref10/ge_double_scalarmult.c ref10/ge_frombytes.c
ref10/ge_madd.c ref10/ge_msub.c ref10/ge_p1p1_to_p2.c
ref10/ge_p1p1_to_p3.c ref10/ge_p2_0.c ref10/ge_p2_dbl.c ref10/ge_p3_0.c
ref10/ge_p3_dbl.c ref10/ge_p3_to_cached.c ref10/ge_p3_to_p2.c
ref10/ge_p3_tobytes.c ref10/ge_precomp_0.c ref10/ge_scalarmult_base.c
ref10/ge_sub.c ref10/ge_tobytes.c ref10/keypair.c ref10/open.c
ref10/sc_muladd.c ref10/sc_reduce.c ref10/sign.c ref10/verify.c)

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

ADD_CONVENIENCE_LIBRARY(ref10 ${REF10_SOURCES})

MYSQL_ADD_PLUGIN(auth_ed25519 server_ed25519.c ${REF10_SOURCES} MODULE_ONLY)

MYSQL_ADD_PLUGIN(client_ed25519 client_ed25519.c MODULE_ONLY
CLIENT LINK_LIBRARIES mysys_ssl ref10 COMPONENT ClientPlugins)

IF(WITH_UNIT_TESTS)
MY_ADD_TESTS(ed25519 LINK_LIBRARIES mysys ref10)
ENDIF()
@@ -0,0 +1,12 @@
This plugin uses public domain ed25519 code
by Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin Yang.

It is "ref10" implementation from the SUPERCOP:
https://bench.cr.yp.to/supercop.html

OpenSSH also uses ed25519 from SUPERCOP, but "ref" implementation.

There are four ed25519 implementations in SUPERCOP, ref10 is faster then ref,
and there are two that are even faster, written in amd64 assembler.
Benchmarks are here: https://bench.cr.yp.to/impl-sign/ed25519.html

@@ -0,0 +1,72 @@
/*
Copyright (c) 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program 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
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

/************************** CLIENT *************************************/

#include <stdlib.h>
#include "common.h"
#include <mysql/client_plugin.h>
#include <errmsg.h>

#if !defined(__attribute__) && !defined(__GNUC__)
#define __attribute__(A)
#endif

static int do_auth(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
unsigned char sk[CRYPTO_SECRETKEYBYTES], pk[CRYPTO_PUBLICKEYBYTES];
unsigned char reply[CRYPTO_BYTES + NONCE_BYTES], *pkt;
unsigned long long reply_len;
int pkt_len;

/* compute keys */
pw_to_sk_and_pk(mysql->passwd, strlen(mysql->passwd), sk, pk);

/* read the nonce */
if ((pkt_len= vio->read_packet(vio, &pkt)) != NONCE_BYTES)
return CR_SERVER_HANDSHAKE_ERR;

/* sign the nonce */
crypto_sign(reply, &reply_len, pkt, NONCE_BYTES, sk);

/* send the signature */
if (vio->write_packet(vio, reply, CRYPTO_BYTES))
return CR_ERROR;

return CR_OK;
}

static int init_client(char *unused1 __attribute__((unused)),
size_t unused2 __attribute__((unused)),
int unused3 __attribute__((unused)),
va_list unused4 __attribute__((unused)))
{
return 0;
}

mysql_declare_client_plugin(AUTHENTICATION)
"client_ed25519",
"Sergei Golubchik",
"Elliptic curve ED25519 based authentication",
{0,1,0},
"GPL",
NULL,
init_client,
NULL,
NULL,
do_auth,
mysql_end_client_plugin;

@@ -0,0 +1,32 @@
/*
Copyright (c) 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program 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
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

#include <mysql.h>
#include <string.h>

#include "ref10/api.h"
#include "crypto_sign.h"
#include "crypto_hash_sha256.h"

#define NONCE_BYTES 32

static inline void pw_to_sk_and_pk(const char *pw, size_t pwlen,
unsigned char *sk, unsigned char *pk)
{
crypto_hash_sha256(sk, pw, pwlen);
crypto_sign_keypair(pk, sk);
}

@@ -0,0 +1,2 @@
#include <mysql/service_sha2.h>
#define crypto_hash_sha256(DST,SRC,SLEN) my_sha256(DST,(char*)(SRC),SLEN)
@@ -0,0 +1,2 @@
#include <mysql/service_sha2.h>
#define crypto_hash_sha512(DST,SRC,SLEN) my_sha512(DST,(char*)(SRC),SLEN)
@@ -0,0 +1,5 @@
#include <stdint.h>
#include <sys/types.h>
typedef int32_t crypto_int32;

#define select ed25519_select
@@ -0,0 +1,5 @@
#include <stdint.h>
#include <sys/types.h>
typedef int64_t crypto_int64;

#define select ed25519_select
@@ -0,0 +1,11 @@
int crypto_sign_keypair(unsigned char *pk,unsigned char *sk);
int crypto_sign(
unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk
);
int crypto_sign_open(
unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk
);
@@ -0,0 +1,5 @@
#include <stdint.h>
#include <sys/types.h>
typedef uint32_t crypto_uint32;

#define select ed25519_select
@@ -0,0 +1,5 @@
#include <stdint.h>
#include <sys/types.h>
typedef uint64_t crypto_uint64;

#define select ed25519_select
@@ -0,0 +1 @@
int crypto_verify(const unsigned char *x,const unsigned char *y);
@@ -0,0 +1,2 @@
#define crypto_verify_32 crypto_verify
int crypto_verify(const unsigned char *x,const unsigned char *y);
@@ -0,0 +1,58 @@
/*
Copyright (c) 2017, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program 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
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

#include <tap.h>
#include <m_string.h>
#include "common.h"

int main()
{
uchar sk[CRYPTO_SECRETKEYBYTES], pk[CRYPTO_PUBLICKEYBYTES];
uchar foobar_sk[CRYPTO_SECRETKEYBYTES]= {195, 171, 143, 241, 55, 32, 232,
173, 144, 71, 221, 57, 70, 107, 60, 137, 116, 229, 146, 194, 250, 56, 61,
74, 57, 96, 113, 76, 174, 240, 196, 242, 46, 6, 101, 50, 204, 79, 15, 14,
186, 168, 176, 159, 25, 100, 110, 224, 133, 74, 171, 60, 128, 170, 80, 53,
105, 116, 153, 109, 172, 121, 153, 161};
uchar foobar_sign[CRYPTO_BYTES]= {164, 116, 168, 41, 250, 169, 91, 205, 126,
71, 253, 70, 233, 228, 79, 70, 43, 157, 221, 169, 35, 130, 101, 62, 133,
50, 104, 50, 45, 168, 238, 198, 48, 243, 76, 167, 173, 56, 241, 81, 221,
197, 31, 60, 247, 225, 52, 158, 31, 82, 20, 6, 237, 68, 54, 32, 78, 244,
91, 49, 194, 238, 117, 5 };

uchar nonce[NONCE_BYTES];
uchar reply[NONCE_BYTES+CRYPTO_BYTES];
unsigned long long reply_len, scramble_len;
int r;

plan(6);
pw_to_sk_and_pk(STRING_WITH_LEN("foobar"), sk, pk);
ok(!memcmp(sk, foobar_sk, CRYPTO_SECRETKEYBYTES), "foobar sk");

memset(nonce, 'A', sizeof(nonce));
crypto_sign(reply, &reply_len, nonce, sizeof(nonce), sk);
ok(reply_len == sizeof(reply), "reply_len");
ok(!memcmp(reply, foobar_sign, CRYPTO_BYTES), "foobar sign");

r= crypto_sign_open(nonce, &scramble_len, reply, reply_len, pk);
ok(scramble_len == sizeof(nonce), "scramble_len");
ok(!r, "good nonce");

reply[CRYPTO_BYTES + 10]='B';
r= crypto_sign_open(nonce, &scramble_len, reply, reply_len, pk);
ok(r, "bad nonce");

return exit_status();
}
@@ -0,0 +1 @@
#define randombytes(BUF,LEN) /* no-op */
@@ -0,0 +1,4 @@
#define CRYPTO_SECRETKEYBYTES 64
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 64
#define CRYPTO_DETERMINISTIC 1

0 comments on commit 7120118

Please sign in to comment.
You can’t perform that action at this time.