summaryrefslogtreecommitdiff
path: root/ed25519.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-12-07 11:24:01 +1100
committerDamien Miller <djm@mindrot.org>2013-12-07 11:24:01 +1100
commit5be9d9e3cbd9c66f24745d25bf2e809c1d158ee0 (patch)
treed2086d37436014ea44f0f024396a1a8638640b00 /ed25519.c
parentbcd00abd8451f36142ae2ee10cc657202149201e (diff)
- markus@cvs.openbsd.org 2013/12/06 13:39:49
[authfd.c authfile.c key.c key.h myproposal.h pathnames.h readconf.c] [servconf.c ssh-agent.c ssh-keygen.c ssh-keyscan.1 ssh-keyscan.c] [ssh-keysign.c ssh.c ssh_config.5 sshd.8 sshd.c verify.c ssh-ed25519.c] [sc25519.h sc25519.c hash.c ge25519_base.data ge25519.h ge25519.c] [fe25519.h fe25519.c ed25519.c crypto_api.h blocks.c] support ed25519 keys (hostkeys and user identities) using the public domain ed25519 reference code from SUPERCOP, see http://ed25519.cr.yp.to/software.html feedback, help & ok djm@
Diffstat (limited to 'ed25519.c')
-rw-r--r--ed25519.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/ed25519.c b/ed25519.c
new file mode 100644
index 000000000..da9673a0b
--- /dev/null
+++ b/ed25519.c
@@ -0,0 +1,139 @@
1/* $OpenBSD: */
2
3/* Public Domain, from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c */
4
5#include "crypto_api.h"
6
7#include "ge25519.h"
8
9static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
10{
11 unsigned long long i;
12
13 for (i = 0;i < 32;++i) playground[i] = sm[i];
14 for (i = 32;i < 64;++i) playground[i] = pk[i-32];
15 for (i = 64;i < smlen;++i) playground[i] = sm[i];
16
17 crypto_hash_sha512(hram,playground,smlen);
18}
19
20
21int crypto_sign_ed25519_keypair(
22 unsigned char *pk,
23 unsigned char *sk
24 )
25{
26 sc25519 scsk;
27 ge25519 gepk;
28 unsigned char extsk[64];
29 int i;
30
31 randombytes(sk, 32);
32 crypto_hash_sha512(extsk, sk, 32);
33 extsk[0] &= 248;
34 extsk[31] &= 127;
35 extsk[31] |= 64;
36
37 sc25519_from32bytes(&scsk,extsk);
38
39 ge25519_scalarmult_base(&gepk, &scsk);
40 ge25519_pack(pk, &gepk);
41 for(i=0;i<32;i++)
42 sk[32 + i] = pk[i];
43 return 0;
44}
45
46int crypto_sign_ed25519(
47 unsigned char *sm,unsigned long long *smlen,
48 const unsigned char *m,unsigned long long mlen,
49 const unsigned char *sk
50 )
51{
52 sc25519 sck, scs, scsk;
53 ge25519 ger;
54 unsigned char r[32];
55 unsigned char s[32];
56 unsigned char extsk[64];
57 unsigned long long i;
58 unsigned char hmg[crypto_hash_sha512_BYTES];
59 unsigned char hram[crypto_hash_sha512_BYTES];
60
61 crypto_hash_sha512(extsk, sk, 32);
62 extsk[0] &= 248;
63 extsk[31] &= 127;
64 extsk[31] |= 64;
65
66 *smlen = mlen+64;
67 for(i=0;i<mlen;i++)
68 sm[64 + i] = m[i];
69 for(i=0;i<32;i++)
70 sm[32 + i] = extsk[32+i];
71
72 crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */
73
74 /* Computation of R */
75 sc25519_from64bytes(&sck, hmg);
76 ge25519_scalarmult_base(&ger, &sck);
77 ge25519_pack(r, &ger);
78
79 /* Computation of s */
80 for(i=0;i<32;i++)
81 sm[i] = r[i];
82
83 get_hram(hram, sm, sk+32, sm, mlen+64);
84
85 sc25519_from64bytes(&scs, hram);
86 sc25519_from32bytes(&scsk, extsk);
87 sc25519_mul(&scs, &scs, &scsk);
88
89 sc25519_add(&scs, &scs, &sck);
90
91 sc25519_to32bytes(s,&scs); /* cat s */
92 for(i=0;i<32;i++)
93 sm[32 + i] = s[i];
94
95 return 0;
96}
97
98int crypto_sign_ed25519_open(
99 unsigned char *m,unsigned long long *mlen,
100 const unsigned char *sm,unsigned long long smlen,
101 const unsigned char *pk
102 )
103{
104 unsigned int i;
105 int ret;
106 unsigned char t2[32];
107 ge25519 get1, get2;
108 sc25519 schram, scs;
109 unsigned char hram[crypto_hash_sha512_BYTES];
110
111 *mlen = (unsigned long long) -1;
112 if (smlen < 64) return -1;
113
114 if (ge25519_unpackneg_vartime(&get1, pk)) return -1;
115
116 get_hram(hram,sm,pk,m,smlen);
117
118 sc25519_from64bytes(&schram, hram);
119
120 sc25519_from32bytes(&scs, sm+32);
121
122 ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
123 ge25519_pack(t2, &get2);
124
125 ret = crypto_verify_32(sm, t2);
126
127 if (!ret)
128 {
129 for(i=0;i<smlen-64;i++)
130 m[i] = sm[i + 64];
131 *mlen = smlen-64;
132 }
133 else
134 {
135 for(i=0;i<smlen-64;i++)
136 m[i] = 0;
137 }
138 return ret;
139}