ed25519.c revision 1.2
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.2 2014/10/19 16:30:58 christos Exp $");
10
11#include "crypto_api.h"
12
13#include "ge25519.h"
14
15static 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
27int 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
52int 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
104int 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