Home | History | Annotate | Download | only in openssh
      1 /* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
      2 
      3 /*
      4  * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
      5  * Peter Schwabe, Bo-Yin Yang.
      6  * Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c
      7  */
      8 
      9 #include "includes.h"
     10 #include "crypto_api.h"
     11 
     12 #include "ge25519.h"
     13 
     14 static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
     15 {
     16   unsigned long long i;
     17 
     18   for (i =  0;i < 32;++i)    playground[i] = sm[i];
     19   for (i = 32;i < 64;++i)    playground[i] = pk[i-32];
     20   for (i = 64;i < smlen;++i) playground[i] = sm[i];
     21 
     22   crypto_hash_sha512(hram,playground,smlen);
     23 }
     24 
     25 
     26 int crypto_sign_ed25519_keypair(
     27     unsigned char *pk,
     28     unsigned char *sk
     29     )
     30 {
     31   sc25519 scsk;
     32   ge25519 gepk;
     33   unsigned char extsk[64];
     34   int i;
     35 
     36   randombytes(sk, 32);
     37   crypto_hash_sha512(extsk, sk, 32);
     38   extsk[0] &= 248;
     39   extsk[31] &= 127;
     40   extsk[31] |= 64;
     41 
     42   sc25519_from32bytes(&scsk,extsk);
     43 
     44   ge25519_scalarmult_base(&gepk, &scsk);
     45   ge25519_pack(pk, &gepk);
     46   for(i=0;i<32;i++)
     47     sk[32 + i] = pk[i];
     48   return 0;
     49 }
     50 
     51 int crypto_sign_ed25519(
     52     unsigned char *sm,unsigned long long *smlen,
     53     const unsigned char *m,unsigned long long mlen,
     54     const unsigned char *sk
     55     )
     56 {
     57   sc25519 sck, scs, scsk;
     58   ge25519 ger;
     59   unsigned char r[32];
     60   unsigned char s[32];
     61   unsigned char extsk[64];
     62   unsigned long long i;
     63   unsigned char hmg[crypto_hash_sha512_BYTES];
     64   unsigned char hram[crypto_hash_sha512_BYTES];
     65 
     66   crypto_hash_sha512(extsk, sk, 32);
     67   extsk[0] &= 248;
     68   extsk[31] &= 127;
     69   extsk[31] |= 64;
     70 
     71   *smlen = mlen+64;
     72   for(i=0;i<mlen;i++)
     73     sm[64 + i] = m[i];
     74   for(i=0;i<32;i++)
     75     sm[32 + i] = extsk[32+i];
     76 
     77   crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */
     78 
     79   /* Computation of R */
     80   sc25519_from64bytes(&sck, hmg);
     81   ge25519_scalarmult_base(&ger, &sck);
     82   ge25519_pack(r, &ger);
     83 
     84   /* Computation of s */
     85   for(i=0;i<32;i++)
     86     sm[i] = r[i];
     87 
     88   get_hram(hram, sm, sk+32, sm, mlen+64);
     89 
     90   sc25519_from64bytes(&scs, hram);
     91   sc25519_from32bytes(&scsk, extsk);
     92   sc25519_mul(&scs, &scs, &scsk);
     93 
     94   sc25519_add(&scs, &scs, &sck);
     95 
     96   sc25519_to32bytes(s,&scs); /* cat s */
     97   for(i=0;i<32;i++)
     98     sm[32 + i] = s[i];
     99 
    100   return 0;
    101 }
    102 
    103 int crypto_sign_ed25519_open(
    104     unsigned char *m,unsigned long long *mlen,
    105     const unsigned char *sm,unsigned long long smlen,
    106     const unsigned char *pk
    107     )
    108 {
    109   unsigned int i;
    110   int ret;
    111   unsigned char t2[32];
    112   ge25519 get1, get2;
    113   sc25519 schram, scs;
    114   unsigned char hram[crypto_hash_sha512_BYTES];
    115 
    116   *mlen = (unsigned long long) -1;
    117   if (smlen < 64) return -1;
    118 
    119   if (ge25519_unpackneg_vartime(&get1, pk)) return -1;
    120 
    121   get_hram(hram,sm,pk,m,smlen);
    122 
    123   sc25519_from64bytes(&schram, hram);
    124 
    125   sc25519_from32bytes(&scs, sm+32);
    126 
    127   ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
    128   ge25519_pack(t2, &get2);
    129 
    130   ret = crypto_verify_32(sm, t2);
    131 
    132   if (!ret)
    133   {
    134     for(i=0;i<smlen-64;i++)
    135       m[i] = sm[i + 64];
    136     *mlen = smlen-64;
    137   }
    138   else
    139   {
    140     for(i=0;i<smlen-64;i++)
    141       m[i] = 0;
    142   }
    143   return ret;
    144 }
    145