-
Notifications
You must be signed in to change notification settings - Fork 79
/
crypto_sign_ed25519_tinyssh.c
131 lines (101 loc) · 3.36 KB
/
crypto_sign_ed25519_tinyssh.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "crypto_sign_ed25519.h"
#include "haslib25519.h"
#ifndef HASLIB25519
#include "randombytes.h"
#include "cleanup.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "ge25519.h"
#include "sc25519.h"
int crypto_sign_ed25519_tinyssh(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long n, const unsigned char *skorig) {
long long i;
unsigned char nonce[64], hram[64], sk[96], pk[32];
ge25519 R;
/* copy public key*/
for (i = 31; i >= 0; --i) pk[i] = skorig[i + 32];
/* compute secret key from seed sk = H(skorig), H = sha512 */
crypto_hash_sha512(sk, skorig, 32);
sk[0] &= 248;
sk[31] &= 63;
sk[31] |= 64;
randombytes(sk + 64, 32);
crypto_hash_sha512(sk + 32, sk + 32, 64);
/* copy m to sm, copy secret key */
*smlen = n + 64;
for (i = n - 1; i >= 0; --i) sm[i + 64] = m[i];
for (i = 31; i >= 0; --i) sm[i + 32] = sk[i + 32];
/* get pseudorandom nonce = H(sk2, m) */
crypto_hash_sha512(nonce, sm + 32, n + 32);
sc25519_reduce(nonce);
/* copy pk to sm */
for (i = 31; i >= 0; --i) sm[i + 32] = pk[i];
/* compute R */
ge25519_scalarmult_base(R, nonce);
ge25519_tobytes(sm, R);
/* calculate hram = H(r, a, m) */
crypto_hash_sha512(hram, sm, n + 64);
sc25519_reduce(hram);
/* compute S */
sc25519_muladd(sm + 32, hram, sk, nonce);
/* cleanup */
cleanup(nonce); cleanup(hram); cleanup(sk); cleanup(pk); cleanup(R);
return 0;
}
int crypto_sign_ed25519_tinyssh_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long n, const unsigned char *pk) {
unsigned long long i;
long long j;
unsigned char pkcopy[32], rcopy[32], scopy[32], hram[64], rcheck[32];
ge25519 R, S, A;
int ret = -1;
/* check input */
if (n < 64) goto fail;
if (sm[63] & 224) goto fail;
/* unpack pk */
if (ge25519_frombytes_negate_vartime(A, pk) != 0) goto fail;
/* copy pk, r, s */
for (i = 0; i < 32; ++i) pkcopy[i] = pk[i];
for (i = 0; i < 32; ++i) rcopy[i] = sm[i];
for (i = 0; i < 32; ++i) scopy[i] = sm[i + 32];
/* copy sm to m and copy pk to m */
for (j = n - 1; j >= 0; --j) m[j] = sm[j];
for (i = 0; i < 32; ++i) m[i + 32] = pkcopy[i];
/* calculate hram = H(r, a, m) */
crypto_hash_sha512(hram, m, n);
sc25519_reduce(hram);
/* compute R */
ge25519_scalarmult(A, A, hram);
ge25519_scalarmult_base(S, scopy);
ge25519_add(R, S, A);
/* check R */
ge25519_tobytes(rcheck, R);
if (crypto_verify_32(rcheck, rcopy) != 0) goto fail;
/* copy message */
n -= 64; *mlen = n;
for (i = 0; i < n; ++i) m[i] = m[i + 64];
for (i = 0; i < 64; ++i) m[i + n] = 0;
ret = 0;
goto cleanup;
fail:
for (i = 0; i < n; ++i) m[i] = 0;
cleanup:
cleanup(pkcopy); cleanup(rcopy); cleanup(scopy);
cleanup(hram); cleanup(rcheck);
cleanup(R); cleanup(S); cleanup(A);
return ret;
}
int crypto_sign_ed25519_tinyssh_keypair(unsigned char *pk, unsigned char *sk) {
unsigned char h[64];
ge25519 A;
long long i;
randombytes(sk, 32);
crypto_hash_sha512(h, sk, 32);
h[0] &= 248;
h[31] &= 63;
h[31] |= 64;
ge25519_scalarmult_base(A, h);
ge25519_tobytes(pk, A);
for (i = 31; i >= 0; --i) sk[i + 32] = pk[i];
cleanup(h); cleanup(A);
return 0;
}
#endif