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
|
#include <string.h>
#include "sc.h"
#include "ge.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "crypto_additions.h"
#include "crypto_sign.h"
int crypto_usign_open_modified(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk, const ge_p3* Bu
)
{
ge_p3 U;
unsigned char h[64];
unsigned char s[64];
unsigned char strict[64];
ge_p3 A;
ge_p2 R;
unsigned char hcheck[64];
int count;
// Ru = sBu + h(-U)
ge_p3 sBu, hU;
ge_p3 Ru;
if (smlen < 96) goto badsig;
if (sm[63] & 224) goto badsig; /* strict parsing of h */
if (sm[95] & 224) goto badsig; /* strict parsing of s */
/* Load -A */
if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
/* Load -U, h, s */
ge_frombytes_negate_vartime(&U, sm);
memset(h, 0, 64);
memset(s, 0, 64);
memmove(h, sm + 32, 32);
memmove(s, sm + 64, 32);
/* Insist that s and h are reduced scalars (strict parsing) */
memcpy(strict, h, 64);
sc_reduce(strict);
if (memcmp(strict, h, 32) != 0)
goto badsig;
memcpy(strict, s, 64);
sc_reduce(strict);
if (memcmp(strict, s, 32) != 0)
goto badsig;
/* Reject U (actually -U) if small order */
if (ge_is_small_order(&U))
goto badsig;
// R = sB + h(-A)
ge_double_scalarmult_vartime(&R,h,&A,s);
// sBu
ge_scalarmult(&sBu, s, Bu);
// h(-U)
ge_scalarmult(&hU, h, &U);
// Ru = sBu + h(-U)
{
ge_p1p1 Rp1p1;
ge_cached hUcached;
ge_p3_to_cached(&hUcached, &hU);
ge_add(&Rp1p1, &sBu, &hUcached);
ge_p1p1_to_p3(&Ru, &Rp1p1);
}
// Check h == SHA512(label(4) || A || U || R || Ru || M)
m[0] = 0xFB;
for (count = 1; count < 32; count++)
m[count] = 0xFF;
memmove(m+32, pk, 32);
/* undo the negation for U */
fe_neg(U.X, U.X);
fe_neg(U.T, U.T);
ge_p3_tobytes(m+64, &U);
ge_tobytes(m+96, &R);
ge_p3_tobytes(m+128, &Ru);
memmove(m+160, sm+96, smlen - 96);
crypto_hash_sha512(hcheck, m, smlen + 64);
sc_reduce(hcheck);
if (crypto_verify_32(hcheck, h) == 0) {
memmove(m,m + 64,smlen - 64);
memset(m + smlen - 64,0,64);
*mlen = smlen - 64;
return 0;
}
badsig:
*mlen = -1;
memset(m,0,smlen);
return -1;
}
|