Blame src/external/ed25519.c

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