Commit e0a03ca3 authored by Sergei Golubchik's avatar Sergei Golubchik

ed25519 plugin: simplify the api

various ed25519/ref10 api simplifications for our specific use case
parent 7120118a
......@@ -10,13 +10,13 @@ ERROR HY000: Can't initialize function 'ed25519_password'; Authentication plugin
install soname 'auth_ed25519';
select ed25519_password("foo");
ed25519_password("foo")
NNJledu0Vmk+VAZyz5IvUt3g1lMuNb8GvgE6fFMvIOA
vubFBzIrapbfHct1/J72dnUryz5VS7lA6XHH8sIx4TI
select ed25519_password("foobar");
ed25519_password("foobar")
LgZlMsxPDw66qLCfGWRu4IVKqzyAqlA1aXSZbax5maE
qv2mG6HWCuy32Slb5xhV4THStewNz2VINVPbgk+XAJ8
select ed25519_password("foo bar");
ed25519_password("foo bar")
6EFKeQLw+p5Ovk8tD+tAi3Agyg7ItukdswOBpTB6f40
Y5fV74JAVRMOK2cdnUsYS+WW9sXaaL/o+6WGKOgqnzc
select ed25519_password(NULL);
ed25519_password(NULL)
NULL
......@@ -34,10 +34,10 @@ 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';
create user test1@localhost identified via ed25519 using 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY';
show grants for test1@localhost;
Grants for test1@localhost
GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'XQNqhYzon4REkXYuuJ4r+9UKSgoNpljksmKLJbEXrgk'
GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY'
connect(localhost,test1,public,test,PORT,SOCKET);
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES)
select current_user();
......
......@@ -10,3 +10,18 @@ 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
==============================
MariaDB changes:
API functions were simplified to better fit our use case:
* crypto_sign_open() does not return the verified message, only the
result of the verification (passed/failed)
* no secret key is generated explicitly, user specified password is used
as a source of randomness instead (SHA512("user password")).
* lengths are not returned, where they're known in advance
(e.g. from crypto_sign()).
* crypto_sign() does not take the public key as an argument, but
generates it on the fly (we used to generate public key before
crypto_sign(), doing it internally avoids double work).
See the changes done in this commit.
......@@ -27,20 +27,16 @@
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);
crypto_sign(reply, pkt, NONCE_BYTES,
(unsigned char*)mysql->passwd, strlen(mysql->passwd));
/* send the signature */
if (vio->write_packet(vio, reply, CRYPTO_BYTES))
......
......@@ -19,14 +19,5 @@
#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);
}
#include <mysql/service_sha2.h>
#define crypto_hash_sha256(DST,SRC,SLEN) my_sha256(DST,(char*)(SRC),SLEN)
int crypto_sign_keypair(unsigned char *pk,unsigned char *sk);
int crypto_sign_keypair(
unsigned char *pk,
unsigned char *pw, unsigned long long pwlen
);
int crypto_sign(
unsigned char *sm, unsigned long long *smlen,
unsigned char *sm,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk
const unsigned char *pw, unsigned long long pwlen
);
int crypto_sign_open(
unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
unsigned char *sm, unsigned long long smlen,
const unsigned char *pk
);
......@@ -20,38 +20,35 @@
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 pk[CRYPTO_PUBLICKEYBYTES];
uchar foobar_pk[CRYPTO_PUBLICKEYBYTES]= {170, 253, 166, 27, 161, 214, 10,
236, 183, 217, 41, 91, 231, 24, 85, 225, 49, 210, 181, 236, 13, 207, 101,
72, 53, 83, 219, 130, 79, 151, 0, 159};
uchar foobar_sign[CRYPTO_BYTES]= {232, 61, 201, 63, 67, 63, 51, 53, 86, 73,
238, 35, 170, 117, 146, 214, 26, 17, 35, 9, 8, 132, 245, 141, 48, 99, 66,
58, 36, 228, 48, 84, 115, 254, 187, 168, 88, 162, 249, 57, 35, 85, 79, 238,
167, 106, 68, 117, 56, 135, 171, 47, 20, 14, 133, 79, 15, 229, 124, 160,
176, 100, 138, 14};
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");
plan(4);
crypto_sign_keypair(pk, USTRING_WITH_LEN("foobar"));
ok(!memcmp(pk, foobar_pk, CRYPTO_PUBLICKEYBYTES), "foobar pk");
memset(nonce, 'A', sizeof(nonce));
crypto_sign(reply, &reply_len, nonce, sizeof(nonce), sk);
ok(reply_len == sizeof(reply), "reply_len");
crypto_sign(reply, nonce, sizeof(nonce), USTRING_WITH_LEN("foobar"));
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");
r= crypto_sign_open(reply, sizeof(reply), pk);
ok(!r, "good nonce");
crypto_sign(reply, nonce, sizeof(nonce), USTRING_WITH_LEN("foobar"));
reply[CRYPTO_BYTES + 10]='B';
r= crypto_sign_open(nonce, &scramble_len, reply, reply_len, pk);
r= crypto_sign_open(reply, sizeof(reply), pk);
ok(r, "bad nonce");
return exit_status();
......
#define randombytes(BUF,LEN) /* no-op */
#define CRYPTO_SECRETKEYBYTES 64
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 64
#define CRYPTO_DETERMINISTIC 1
#include <string.h>
#include "randombytes.h"
#include "crypto_sign.h"
#include "crypto_hash_sha512.h"
#include "ge.h"
int crypto_sign_keypair(unsigned char *pk,unsigned char *sk)
int crypto_sign_keypair(
unsigned char *pk,
unsigned char *pw, unsigned long long pwlen
)
{
unsigned char az[64];
ge_p3 A;
randombytes(sk,32);
crypto_hash_sha512(az,sk,32);
crypto_hash_sha512(az,pw,pwlen);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
......@@ -18,6 +19,5 @@ int crypto_sign_keypair(unsigned char *pk,unsigned char *sk)
ge_scalarmult_base(&A,az);
ge_p3_tobytes(pk,&A);
memmove(sk + 32,pk,32);
return 0;
}
......@@ -6,13 +6,10 @@
#include "sc.h"
int crypto_sign_open(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
unsigned char *sm, unsigned long long smlen,
const unsigned char *pk
)
{
unsigned char pkcopy[32];
unsigned char rcopy[32];
unsigned char scopy[32];
unsigned char h[64];
unsigned char rcheck[32];
......@@ -23,26 +20,17 @@ int crypto_sign_open(
if (sm[63] & 224) goto badsig;
if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
memmove(pkcopy,pk,32);
memmove(rcopy,sm,32);
memmove(scopy,sm + 32,32);
memmove(m,sm,smlen);
memmove(m + 32,pkcopy,32);
crypto_hash_sha512(h,m,smlen);
memmove(sm + 32,pk,32);
crypto_hash_sha512(h,sm,smlen);
sc_reduce(h);
ge_double_scalarmult_vartime(&R,h,&A,scopy);
ge_tobytes(rcheck,&R);
if (crypto_verify_32(rcheck,rcopy) == 0) {
memmove(m,m + 64,smlen - 64);
memset(m + smlen - 64,0,64);
*mlen = smlen - 64;
if (crypto_verify_32(rcheck,sm) == 0)
return 0;
}
badsig:
*mlen = -1;
memset(m,0,smlen);
return -1;
}
......@@ -5,29 +5,27 @@
#include "sc.h"
int crypto_sign(
unsigned char *sm,unsigned long long *smlen,
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk
const unsigned char *pw,unsigned long long pwlen
)
{
unsigned char pk[32];
unsigned char az[64];
unsigned char nonce[64];
unsigned char hram[64];
ge_p3 R;
ge_p3 A, R;
memmove(pk,sk + 32,32);
crypto_hash_sha512(az,sk,32);
crypto_hash_sha512(az,pw,pwlen);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
*smlen = mlen + 64;
memmove(sm + 64,m,mlen);
memmove(sm + 32,az + 32,32);
crypto_hash_sha512(nonce,sm + 32,mlen + 32);
memmove(sm + 32,pk,32);
ge_scalarmult_base(&A,az);
ge_p3_tobytes(sm + 32,&A);
sc_reduce(nonce);
ge_scalarmult_base(&R,nonce);
......
......@@ -33,11 +33,10 @@ static int loaded= 0;
static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
{
unsigned long long out_len;
unsigned int i;
int pkt_len;
unsigned long nonce[CRYPTO_LONGS + NONCE_LONGS];
unsigned char *pkt, *reply= (unsigned char*)nonce, out[NONCE_BYTES];
unsigned char *pkt, *reply= (unsigned char*)nonce;
unsigned char pk[PASSWORD_LEN_BUF/4*3];
char pw[PASSWORD_LEN_BUF];
......@@ -64,7 +63,7 @@ static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
return CR_AUTH_HANDSHAKE;
memcpy(reply, pkt, CRYPTO_BYTES);
if (crypto_sign_open(out, &out_len, reply, CRYPTO_BYTES + NONCE_BYTES, pk))
if (crypto_sign_open(reply, CRYPTO_BYTES + NONCE_BYTES, pk))
return CR_ERROR;
return CR_OK;
......@@ -113,14 +112,14 @@ char *ed25519_password(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args, char *result, unsigned long *length,
char *is_null, char *error __attribute__((unused)))
{
unsigned char sk[CRYPTO_SECRETKEYBYTES], pk[CRYPTO_PUBLICKEYBYTES];
unsigned char pk[CRYPTO_PUBLICKEYBYTES];
if ((*is_null= !args->args[0]))
return NULL;
*length= PASSWORD_LEN;
pw_to_sk_and_pk(args->args[0], args->lengths[0], sk, pk);
base64_encode(pk, sizeof(pk), result);
crypto_sign_keypair(pk, (unsigned char*)args->args[0], args->lengths[0]);
base64_encode(pk, CRYPTO_PUBLICKEYBYTES, result);
return result;
}
......
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