File: crypto_sign_ed25519.c

package info (click to toggle)
tinyssh 20230101-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,244 kB
  • sloc: ansic: 12,106; sh: 1,168; python: 479; makefile: 42
file content (121 lines) | stat: -rw-r--r-- 3,279 bytes parent folder | download
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
#include "randombytes.h"
#include "cleanup.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "ge25519.h"
#include "sc25519.h"
#include "crypto_sign_ed25519.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[64], pk[32];
    ge25519 R;

    /* 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;

    /* copy m to sm, copy secret key and public key */
    *smlen = n + 64;
    for (i = 31; i >= 0; --i) pk[i     ] = skorig[i + 32];
    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) {

    long long i;
    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 (i = n - 1; i >= 0; --i) m[i] = sm[i];
    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;
}