Blame src/external/ed25519.c

Packit 6c0a39
/* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
Packit 6c0a39
Packit 6c0a39
/*
Packit 6c0a39
 * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
Packit 6c0a39
 * Peter Schwabe, Bo-Yin Yang.
Packit 6c0a39
 * Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
#include "config.h"
Packit 6c0a39
Packit 6c0a39
#include "libssh/libcrypto.h"
Packit 6c0a39
#include "libssh/wrapper.h"
Packit 6c0a39
#include "libssh/ge25519.h"
Packit 6c0a39
#include "libssh/sc25519.h"
Packit 6c0a39
#include "libssh/ed25519.h"
Packit 6c0a39
Packit 6c0a39
/*
Packit 6c0a39
 * Public Domain, Author: Daniel J. Bernstein
Packit 6c0a39
 * Copied from nacl-20110221/crypto_verify/32/ref/verify.c
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
static int crypto_verify_32(const unsigned char *x,const unsigned char *y)
Packit 6c0a39
{
Packit 6c0a39
    unsigned int differentbits = 0;
Packit 6c0a39
#define F(i) differentbits |= x[i] ^ y[i];
Packit 6c0a39
    F(0)
Packit 6c0a39
    F(1)
Packit 6c0a39
    F(2)
Packit 6c0a39
    F(3)
Packit 6c0a39
    F(4)
Packit 6c0a39
    F(5)
Packit 6c0a39
    F(6)
Packit 6c0a39
    F(7)
Packit 6c0a39
    F(8)
Packit 6c0a39
    F(9)
Packit 6c0a39
    F(10)
Packit 6c0a39
    F(11)
Packit 6c0a39
    F(12)
Packit 6c0a39
    F(13)
Packit 6c0a39
    F(14)
Packit 6c0a39
    F(15)
Packit 6c0a39
    F(16)
Packit 6c0a39
    F(17)
Packit 6c0a39
    F(18)
Packit 6c0a39
    F(19)
Packit 6c0a39
    F(20)
Packit 6c0a39
    F(21)
Packit 6c0a39
    F(22)
Packit 6c0a39
    F(23)
Packit 6c0a39
    F(24)
Packit 6c0a39
    F(25)
Packit 6c0a39
    F(26)
Packit 6c0a39
    F(27)
Packit 6c0a39
    F(28)
Packit 6c0a39
    F(29)
Packit 6c0a39
    F(30)
Packit 6c0a39
    F(31)
Packit 6c0a39
Packit 6c0a39
    return (1 & ((differentbits - 1) >> 8)) - 1;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
static void get_hram(unsigned char *hram,
Packit 6c0a39
                     const unsigned char *sm,
Packit 6c0a39
                     const unsigned char *pk,
Packit 6c0a39
                     unsigned char *playground,
Packit 6c0a39
                     uint64_t smlen)
Packit 6c0a39
{
Packit 6c0a39
    uint64_t i;
Packit 6c0a39
    SHA512CTX ctx;
Packit 6c0a39
    for (i =  0;i < 32;++i)    playground[i] = sm[i];
Packit 6c0a39
    for (i = 32;i < 64;++i)    playground[i] = pk[i-32];
Packit 6c0a39
    for (i = 64;i < smlen;++i) playground[i] = sm[i];
Packit 6c0a39
Packit 6c0a39
    ctx = sha512_init();
Packit 6c0a39
    sha512_update(ctx, playground, smlen);
Packit 6c0a39
    sha512_final(hram, ctx);
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
int crypto_sign_ed25519_keypair(unsigned char *pk,
Packit 6c0a39
                                unsigned char *sk)
Packit 6c0a39
{
Packit 6c0a39
    sc25519 scsk;
Packit 6c0a39
    ge25519 gepk;
Packit 6c0a39
    SHA512CTX ctx;
Packit 6c0a39
    unsigned char extsk[64];
Packit 6c0a39
    int i;
Packit 6c0a39
    int ok;
Packit 6c0a39
Packit 6c0a39
    ok = ssh_get_random(sk, 32, 0);
Packit 6c0a39
    if (!ok) {
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    ctx = sha512_init();
Packit 6c0a39
    sha512_update(ctx, sk, 32);
Packit 6c0a39
    sha512_final(extsk, ctx);
Packit 6c0a39
    extsk[0] &= 248;
Packit 6c0a39
    extsk[31] &= 127;
Packit 6c0a39
    extsk[31] |= 64;
Packit 6c0a39
Packit 6c0a39
    sc25519_from32bytes(&scsk,extsk);
Packit 6c0a39
Packit 6c0a39
    ge25519_scalarmult_base(&gepk, &scsk;;
Packit 6c0a39
    ge25519_pack(pk, &gepk);
Packit 6c0a39
    for(i=0;i<32;i++) {
Packit 6c0a39
        sk[32 + i] = pk[i];
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    return 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int crypto_sign_ed25519(unsigned char *sm,
Packit 6c0a39
                        uint64_t *smlen,
Packit 6c0a39
                        const unsigned char *m,
Packit 6c0a39
                        uint64_t mlen,
Packit 6c0a39
                        const unsigned char *sk)
Packit 6c0a39
{
Packit 6c0a39
    sc25519 sck, scs, scsk;
Packit 6c0a39
    ge25519 ger;
Packit 6c0a39
    SHA512CTX ctx;
Packit 6c0a39
    unsigned char r[32];
Packit 6c0a39
    unsigned char s[32];
Packit 6c0a39
    unsigned char extsk[64];
Packit 6c0a39
    uint64_t i;
Packit 6c0a39
    unsigned char hmg[SHA512_DIGEST_LEN];
Packit 6c0a39
    unsigned char hram[SHA512_DIGEST_LEN];
Packit 6c0a39
Packit 6c0a39
    ctx = sha512_init();
Packit 6c0a39
    sha512_update(ctx, sk, 32);
Packit 6c0a39
    sha512_final(extsk, ctx);
Packit 6c0a39
Packit 6c0a39
    extsk[0] &= 248;
Packit 6c0a39
    extsk[31] &= 127;
Packit 6c0a39
    extsk[31] |= 64;
Packit 6c0a39
Packit 6c0a39
    *smlen = mlen + 64;
Packit 6c0a39
    for (i = 0;i < mlen; i++) {
Packit 6c0a39
        sm[64 + i] = m[i];
Packit 6c0a39
    }
Packit 6c0a39
    for (i = 0;i < 32; i++) {
Packit 6c0a39
        sm[32 + i] = extsk[32+i];
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    /* Generate k as h(extsk[32],...,extsk[63],m) */
Packit 6c0a39
    ctx = sha512_init();
Packit 6c0a39
    sha512_update(ctx, sm + 32, mlen + 32);
Packit 6c0a39
    sha512_final(hmg, ctx);
Packit 6c0a39
Packit 6c0a39
    /* Computation of R */
Packit 6c0a39
    sc25519_from64bytes(&sck, hmg);
Packit 6c0a39
    ge25519_scalarmult_base(&ger, &sck;;
Packit 6c0a39
    ge25519_pack(r, &ger;;
Packit 6c0a39
Packit 6c0a39
    /* Computation of s */
Packit 6c0a39
    for (i = 0; i < 32; i++) {
Packit 6c0a39
        sm[i] = r[i];
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    get_hram(hram, sm, sk+32, sm, mlen+64);
Packit 6c0a39
Packit 6c0a39
    sc25519_from64bytes(&scs, hram);
Packit 6c0a39
    sc25519_from32bytes(&scsk, extsk);
Packit 6c0a39
    sc25519_mul(&scs, &scs, &scsk;;
Packit 6c0a39
Packit 6c0a39
    sc25519_add(&scs, &scs, &sck;;
Packit 6c0a39
Packit 6c0a39
    sc25519_to32bytes(s,&scs); /* cat s */
Packit 6c0a39
    for (i = 0;i < 32; i++) {
Packit 6c0a39
        sm[32 + i] = s[i];
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    return 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int crypto_sign_ed25519_open(unsigned char *m,
Packit 6c0a39
                             uint64_t *mlen,
Packit 6c0a39
                             const unsigned char *sm,
Packit 6c0a39
                             uint64_t smlen,
Packit 6c0a39
                             const unsigned char *pk)
Packit 6c0a39
{
Packit 6c0a39
    unsigned int i;
Packit 6c0a39
    int ret;
Packit 6c0a39
    unsigned char t2[32];
Packit 6c0a39
    ge25519 get1, get2;
Packit 6c0a39
    sc25519 schram, scs;
Packit 6c0a39
    unsigned char hram[SHA512_DIGEST_LEN];
Packit 6c0a39
Packit 6c0a39
    *mlen = (uint64_t) -1;
Packit 6c0a39
    if (smlen < 64) return -1;
Packit 6c0a39
Packit 6c0a39
    if (ge25519_unpackneg_vartime(&get1, pk)) {
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    get_hram(hram,sm,pk,m,smlen);
Packit 6c0a39
Packit 6c0a39
    sc25519_from64bytes(&schram, hram);
Packit 6c0a39
Packit 6c0a39
    sc25519_from32bytes(&scs, sm+32);
Packit 6c0a39
Packit 6c0a39
    ge25519_double_scalarmult_vartime(&get2,
Packit 6c0a39
                                      &get1,
Packit 6c0a39
                                      &schram,
Packit 6c0a39
                                      &ge25519_base,
Packit 6c0a39
                                      &scs);
Packit 6c0a39
    ge25519_pack(t2, &get2);
Packit 6c0a39
Packit 6c0a39
    ret = crypto_verify_32(sm, t2);
Packit 6c0a39
    if (ret != 0) {
Packit 6c0a39
        for (i = 0; i < smlen - 64; i++) {
Packit 6c0a39
            m[i] = sm[i + 64];
Packit 6c0a39
        }
Packit 6c0a39
        *mlen = smlen-64;
Packit 6c0a39
    } else {
Packit 6c0a39
        for (i = 0; i < smlen - 64; i++) {
Packit 6c0a39
            m[i] = 0;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    return ret;
Packit 6c0a39
}