xref: /openbsd/usr.bin/ssh/ed25519.c (revision a6445c1d)
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 "crypto_api.h"
10 
11 #include "ge25519.h"
12 
13 static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
14 {
15   unsigned long long i;
16 
17   for (i =  0;i < 32;++i)    playground[i] = sm[i];
18   for (i = 32;i < 64;++i)    playground[i] = pk[i-32];
19   for (i = 64;i < smlen;++i) playground[i] = sm[i];
20 
21   crypto_hash_sha512(hram,playground,smlen);
22 }
23 
24 
25 int crypto_sign_ed25519_keypair(
26     unsigned char *pk,
27     unsigned char *sk
28     )
29 {
30   sc25519 scsk;
31   ge25519 gepk;
32   unsigned char extsk[64];
33   int i;
34 
35   randombytes(sk, 32);
36   crypto_hash_sha512(extsk, sk, 32);
37   extsk[0] &= 248;
38   extsk[31] &= 127;
39   extsk[31] |= 64;
40 
41   sc25519_from32bytes(&scsk,extsk);
42 
43   ge25519_scalarmult_base(&gepk, &scsk);
44   ge25519_pack(pk, &gepk);
45   for(i=0;i<32;i++)
46     sk[32 + i] = pk[i];
47   return 0;
48 }
49 
50 int crypto_sign_ed25519(
51     unsigned char *sm,unsigned long long *smlen,
52     const unsigned char *m,unsigned long long mlen,
53     const unsigned char *sk
54     )
55 {
56   sc25519 sck, scs, scsk;
57   ge25519 ger;
58   unsigned char r[32];
59   unsigned char s[32];
60   unsigned char extsk[64];
61   unsigned long long i;
62   unsigned char hmg[crypto_hash_sha512_BYTES];
63   unsigned char hram[crypto_hash_sha512_BYTES];
64 
65   crypto_hash_sha512(extsk, sk, 32);
66   extsk[0] &= 248;
67   extsk[31] &= 127;
68   extsk[31] |= 64;
69 
70   *smlen = mlen+64;
71   for(i=0;i<mlen;i++)
72     sm[64 + i] = m[i];
73   for(i=0;i<32;i++)
74     sm[32 + i] = extsk[32+i];
75 
76   crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */
77 
78   /* Computation of R */
79   sc25519_from64bytes(&sck, hmg);
80   ge25519_scalarmult_base(&ger, &sck);
81   ge25519_pack(r, &ger);
82 
83   /* Computation of s */
84   for(i=0;i<32;i++)
85     sm[i] = r[i];
86 
87   get_hram(hram, sm, sk+32, sm, mlen+64);
88 
89   sc25519_from64bytes(&scs, hram);
90   sc25519_from32bytes(&scsk, extsk);
91   sc25519_mul(&scs, &scs, &scsk);
92 
93   sc25519_add(&scs, &scs, &sck);
94 
95   sc25519_to32bytes(s,&scs); /* cat s */
96   for(i=0;i<32;i++)
97     sm[32 + i] = s[i];
98 
99   return 0;
100 }
101 
102 int crypto_sign_ed25519_open(
103     unsigned char *m,unsigned long long *mlen,
104     const unsigned char *sm,unsigned long long smlen,
105     const unsigned char *pk
106     )
107 {
108   unsigned int i;
109   int ret;
110   unsigned char t2[32];
111   ge25519 get1, get2;
112   sc25519 schram, scs;
113   unsigned char hram[crypto_hash_sha512_BYTES];
114 
115   *mlen = (unsigned long long) -1;
116   if (smlen < 64) return -1;
117 
118   if (ge25519_unpackneg_vartime(&get1, pk)) return -1;
119 
120   get_hram(hram,sm,pk,m,smlen);
121 
122   sc25519_from64bytes(&schram, hram);
123 
124   sc25519_from32bytes(&scs, sm+32);
125 
126   ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
127   ge25519_pack(t2, &get2);
128 
129   ret = crypto_verify_32(sm, t2);
130 
131   if (!ret)
132   {
133     for(i=0;i<smlen-64;i++)
134       m[i] = sm[i + 64];
135     *mlen = smlen-64;
136   }
137   else
138   {
139     for(i=0;i<smlen-64;i++)
140       m[i] = 0;
141   }
142   return ret;
143 }
144