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