-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathecdsa.c
128 lines (103 loc) · 3.46 KB
/
ecdsa.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
#include <cry/ecdsa.h>
#include "mpi/mpi_pvt.h"
#define CHK0(exp) CRY_CHK(res = (exp), e0)
#define CHK1(exp) CRY_CHK(res = (exp), e1)
int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_sig *sig,
const unsigned char *in, size_t len,
cry_ecdsa_rand_gen rand_gen)
{
int res;
cry_mpi k, z;
cry_ecp X;
if ((res = cry_mpi_init_list(&k, &z, (cry_mpi *)NULL)) != 0)
return res;
CHK0(cry_ecp_init(&X));
/* z = input buffer is eventually truncated to the size of q */
if (ctx->grp.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->grp.n.used * CRY_MPI_DIGIT_BYTES;
CHK1(cry_mpi_load_bin(&z, in, len));
/* This should be a random number between 0 and n-1 */
if (rand_gen != NULL) {
unsigned char buf[32];
memset(buf, 0, sizeof(buf));
rand_gen(buf, sizeof(buf));
CHK1(cry_mpi_load_bin(&k, buf, sizeof(buf)));
} else {
CHK1(cry_mpi_rand_range(&k, &ctx->grp.n));
}
CHK1(cry_ecp_mul(&X, &ctx->grp.g, &k, &ctx->grp));
/* r = x mod n */
cry_mpi_swap(&sig->r, &X.x);
/* s = (inv(k) * (z + r*d)) mod n */
CHK1(cry_mpi_inv(&k, &k, &ctx->grp.n));
CHK1(cry_mpi_mul(&sig->s, &ctx->d, &sig->r));
CHK1(cry_mpi_add(&sig->s, &sig->s, &z));
CHK1(cry_mpi_mul(&sig->s, &sig->s, &k));
CHK1(cry_mpi_mod(&sig->s, &sig->s, &ctx->grp.n));
e1: cry_ecp_clear(&X);
e0: cry_mpi_clear_list(&k, &z, (cry_mpi *)NULL);
return 0;
}
int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_sig *sig,
const unsigned char *in, size_t len)
{
int res;
cry_mpi z, w;
cry_ecp G, Q;
if ((res = cry_mpi_init_list(&z, &w, (cry_mpi *)NULL)) != 0)
return res;
CHK0(cry_ecp_init_list(&G, &Q, (cry_ecp *)NULL));
/* z = input buffer is eventually truncated to the size of q */
if (ctx->grp.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->grp.n.used * CRY_MPI_DIGIT_BYTES;
CHK1(cry_mpi_load_bin(&z, in, len));
/* w = inv(s) mod n */
CHK1(cry_mpi_copy(&w, &sig->s));
CHK1(cry_mpi_inv(&w, &w, &ctx->grp.n));
/* u1 = (z * w) mod n */
CHK1(cry_mpi_mul(&z, &z, &w));
CHK1(cry_mpi_mod(&z, &z, &ctx->grp.n));
/* u2 = (r * w) mod n */
CHK1(cry_mpi_mul(&w, &sig->r, &w));
CHK1(cry_mpi_mod(&w, &w, &ctx->grp.n));
/* (x1, y1) = u1 * G + u2 * Q */
CHK1(cry_ecp_mul(&G, &ctx->grp.g, &z, &ctx->grp));
CHK1(cry_ecp_mul(&Q, &ctx->q, &w, &ctx->grp));
CHK1(cry_ecp_add(&G, &G, &Q, &ctx->grp));
/* r = x1 mod n */
CHK1(cry_mpi_mod(&G.x, &G.x, &ctx->grp.n)); // inutile
res = (cry_mpi_cmp_abs(&G.x, &sig->r) == 0);
e1: cry_ecp_clear_list(&G, &Q, (cry_ecp *)NULL);
e0: cry_mpi_clear_list(&z, &w, (cry_mpi *)NULL);
return res;
}
int cry_ecdsa_init(cry_ecdsa_ctx *ctx, int grp_id)
{
int res;
res = cry_mpi_init(&ctx->d);
if (res != 0)
return res;
CHK0(cry_ecp_init(&ctx->q));
if (grp_id != -1)
CHK1(cry_ecp_grp_load(&ctx->grp, grp_id));
else
CHK1(cry_ecp_grp_init(&ctx->grp));
return 0;
e1: cry_ecp_clear(&ctx->q);
e0: cry_mpi_clear(&ctx->d);
return res;
}
void cry_ecdsa_clear(cry_ecdsa_ctx *ctx)
{
cry_mpi_clear(&ctx->d);
cry_ecp_clear(&ctx->q);
cry_ecp_grp_clear(&ctx->grp);
cry_memset(ctx, 0, sizeof(*ctx));
}
int cry_ecdsa_keygen(cry_ecdsa_ctx *ctx)
{
int res;
if ((res = cry_mpi_rand_range(&ctx->d, &ctx->grp.n)) == 0)
res = cry_ecp_mul(&ctx->q, &ctx->grp.g, &ctx->d, &ctx->grp);
return res;
}