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