line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
MODULE = CryptX PACKAGE = Crypt::PK::Ed25519 |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Crypt::PK::Ed25519 |
6
|
|
|
|
|
|
|
_new(Class) |
7
|
|
|
|
|
|
|
CODE: |
8
|
|
|
|
|
|
|
{ |
9
|
|
|
|
|
|
|
int rv; |
10
|
0
|
|
|
|
|
|
Newz(0, RETVAL, 1, struct ed25519_struct); |
11
|
0
|
0
|
|
|
|
|
if (!RETVAL) croak("FATAL: Newz failed"); |
12
|
0
|
|
|
|
|
|
RETVAL->initialized = 0; |
13
|
0
|
|
|
|
|
|
RETVAL->pindex = find_prng("chacha20"); |
14
|
0
|
0
|
|
|
|
|
if (RETVAL->pindex == -1) { |
15
|
0
|
|
|
|
|
|
Safefree(RETVAL); |
16
|
0
|
|
|
|
|
|
croak("FATAL: find_prng('chacha20') failed"); |
17
|
|
|
|
|
|
|
} |
18
|
0
|
|
|
|
|
|
rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */ |
19
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) { |
20
|
0
|
|
|
|
|
|
Safefree(RETVAL); |
21
|
0
|
|
|
|
|
|
croak("FATAL: rng_make_prng failed: %s", error_to_string(rv)); |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
OUTPUT: |
25
|
|
|
|
|
|
|
RETVAL |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
void |
28
|
|
|
|
|
|
|
generate_key(Crypt::PK::Ed25519 self) |
29
|
|
|
|
|
|
|
PPCODE: |
30
|
|
|
|
|
|
|
{ |
31
|
|
|
|
|
|
|
int rv; |
32
|
0
|
|
|
|
|
|
self->initialized = 0; |
33
|
0
|
|
|
|
|
|
rv = ed25519_make_key(&self->pstate, self->pindex, &self->key); |
34
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_make_key failed: %s", error_to_string(rv)); |
35
|
0
|
|
|
|
|
|
self->initialized = 1; |
36
|
0
|
0
|
|
|
|
|
XPUSHs(ST(0)); /* return self */ |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
void |
40
|
|
|
|
|
|
|
_import(Crypt::PK::Ed25519 self, SV * key_data) |
41
|
|
|
|
|
|
|
PPCODE: |
42
|
|
|
|
|
|
|
{ |
43
|
|
|
|
|
|
|
int rv; |
44
|
0
|
|
|
|
|
|
unsigned char *data=NULL; |
45
|
0
|
|
|
|
|
|
STRLEN data_len=0; |
46
|
|
|
|
|
|
|
|
47
|
0
|
0
|
|
|
|
|
data = (unsigned char *)SvPVbyte(key_data, data_len); |
48
|
0
|
|
|
|
|
|
self->initialized = 0; |
49
|
0
|
|
|
|
|
|
rv = ed25519_import(data, (unsigned long)data_len, &self->key); |
50
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_import failed: %s", error_to_string(rv)); |
51
|
0
|
|
|
|
|
|
self->initialized = 1; |
52
|
0
|
0
|
|
|
|
|
XPUSHs(ST(0)); /* return self */ |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
void |
56
|
|
|
|
|
|
|
_import_pkcs8(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd) |
57
|
|
|
|
|
|
|
PPCODE: |
58
|
|
|
|
|
|
|
{ |
59
|
|
|
|
|
|
|
int rv; |
60
|
0
|
|
|
|
|
|
unsigned char *data=NULL, *pwd=NULL; |
61
|
0
|
|
|
|
|
|
STRLEN data_len=0, pwd_len=0; |
62
|
|
|
|
|
|
|
|
63
|
0
|
0
|
|
|
|
|
data = (unsigned char *)SvPVbyte(key_data, data_len); |
64
|
0
|
0
|
|
|
|
|
if (SvOK(passwd)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
pwd = (unsigned char *)SvPVbyte(passwd, pwd_len); |
66
|
|
|
|
|
|
|
} |
67
|
0
|
|
|
|
|
|
self->initialized = 0; |
68
|
0
|
|
|
|
|
|
rv = ed25519_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key); |
69
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_import_pkcs8 failed: %s", error_to_string(rv)); |
70
|
0
|
|
|
|
|
|
self->initialized = 1; |
71
|
0
|
0
|
|
|
|
|
XPUSHs(ST(0)); /* return self */ |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
void |
75
|
|
|
|
|
|
|
_import_x509(Crypt::PK::Ed25519 self, SV * key_data) |
76
|
|
|
|
|
|
|
PPCODE: |
77
|
|
|
|
|
|
|
{ |
78
|
|
|
|
|
|
|
int rv; |
79
|
0
|
|
|
|
|
|
unsigned char *data=NULL; |
80
|
0
|
|
|
|
|
|
STRLEN data_len=0; |
81
|
|
|
|
|
|
|
|
82
|
0
|
0
|
|
|
|
|
data = (unsigned char *)SvPVbyte(key_data, data_len); |
83
|
0
|
|
|
|
|
|
self->initialized = 0; |
84
|
0
|
|
|
|
|
|
rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key); |
85
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv)); |
86
|
0
|
|
|
|
|
|
self->initialized = 1; |
87
|
0
|
0
|
|
|
|
|
XPUSHs(ST(0)); /* return self */ |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
void |
91
|
|
|
|
|
|
|
_import_raw(Crypt::PK::Ed25519 self, SV * key, int which) |
92
|
|
|
|
|
|
|
PPCODE: |
93
|
|
|
|
|
|
|
{ |
94
|
|
|
|
|
|
|
int rv; |
95
|
0
|
|
|
|
|
|
unsigned char *key_data=NULL; |
96
|
0
|
|
|
|
|
|
STRLEN key_len=0; |
97
|
|
|
|
|
|
|
|
98
|
0
|
0
|
|
|
|
|
if (SvOK(key)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
key_data = (unsigned char *)SvPVbyte(key, key_len); |
100
|
|
|
|
|
|
|
} |
101
|
0
|
|
|
|
|
|
self->initialized = 0; |
102
|
0
|
0
|
|
|
|
|
if (which == 0) { |
103
|
0
|
|
|
|
|
|
rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key); |
104
|
|
|
|
|
|
|
} |
105
|
0
|
0
|
|
|
|
|
else if (which == 1) { |
106
|
0
|
|
|
|
|
|
rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else { |
109
|
0
|
|
|
|
|
|
croak("FATAL: import_raw invalid type '%d'", which); |
110
|
|
|
|
|
|
|
} |
111
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv)); |
112
|
0
|
|
|
|
|
|
self->initialized = 1; |
113
|
0
|
0
|
|
|
|
|
XPUSHs(ST(0)); /* return self */ |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
int |
117
|
|
|
|
|
|
|
is_private(Crypt::PK::Ed25519 self) |
118
|
|
|
|
|
|
|
CODE: |
119
|
0
|
0
|
|
|
|
|
if (self->initialized == 0) XSRETURN_UNDEF; |
120
|
0
|
|
|
|
|
|
RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0; |
121
|
|
|
|
|
|
|
OUTPUT: |
122
|
|
|
|
|
|
|
RETVAL |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
SV* |
125
|
|
|
|
|
|
|
key2hash(Crypt::PK::Ed25519 self) |
126
|
|
|
|
|
|
|
PREINIT: |
127
|
|
|
|
|
|
|
HV *rv_hash; |
128
|
|
|
|
|
|
|
char buf[32 * 2 + 1]; |
129
|
|
|
|
|
|
|
unsigned long blen; |
130
|
|
|
|
|
|
|
SV **not_used; |
131
|
|
|
|
|
|
|
int rv; |
132
|
|
|
|
|
|
|
CODE: |
133
|
0
|
0
|
|
|
|
|
if (self->initialized == 0) XSRETURN_UNDEF; |
134
|
0
|
|
|
|
|
|
rv_hash = newHV(); |
135
|
|
|
|
|
|
|
/* priv */ |
136
|
0
|
0
|
|
|
|
|
if (self->key.type == PK_PRIVATE) { |
137
|
0
|
|
|
|
|
|
blen = sizeof(buf); |
138
|
0
|
|
|
|
|
|
rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0); |
139
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); |
140
|
0
|
|
|
|
|
|
not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
else { |
143
|
0
|
|
|
|
|
|
not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */ |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
/* pub */ |
146
|
0
|
|
|
|
|
|
blen = sizeof(buf); |
147
|
0
|
|
|
|
|
|
rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0); |
148
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv)); |
149
|
0
|
|
|
|
|
|
not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0); |
150
|
|
|
|
|
|
|
/* curve */ |
151
|
0
|
|
|
|
|
|
not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0); |
152
|
|
|
|
|
|
|
LTC_UNUSED_PARAM(not_used); |
153
|
0
|
|
|
|
|
|
RETVAL = newRV_noinc((SV*)rv_hash); |
154
|
|
|
|
|
|
|
OUTPUT: |
155
|
|
|
|
|
|
|
RETVAL |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
SV* |
158
|
|
|
|
|
|
|
export_key_der(Crypt::PK::Ed25519 self, char * type) |
159
|
|
|
|
|
|
|
CODE: |
160
|
|
|
|
|
|
|
{ |
161
|
|
|
|
|
|
|
int rv; |
162
|
|
|
|
|
|
|
unsigned char out[4096]; |
163
|
0
|
|
|
|
|
|
unsigned long int out_len = sizeof(out); |
164
|
|
|
|
|
|
|
|
165
|
0
|
|
|
|
|
|
RETVAL = newSVpvn(NULL, 0); /* undef */ |
166
|
0
|
0
|
|
|
|
|
if (strnEQ(type, "private", 7)) { |
167
|
0
|
|
|
|
|
|
rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key); |
168
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); |
169
|
0
|
|
|
|
|
|
RETVAL = newSVpvn((char*)out, out_len); |
170
|
|
|
|
|
|
|
} |
171
|
0
|
0
|
|
|
|
|
else if (strnEQ(type, "public", 6)) { |
172
|
0
|
|
|
|
|
|
rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key); |
173
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); |
174
|
0
|
|
|
|
|
|
RETVAL = newSVpvn((char*)out, out_len); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
else { |
177
|
0
|
|
|
|
|
|
croak("FATAL: export_key_der invalid type '%s'", type); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
OUTPUT: |
181
|
|
|
|
|
|
|
RETVAL |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
SV* |
184
|
|
|
|
|
|
|
export_key_raw(Crypt::PK::Ed25519 self, char * type) |
185
|
|
|
|
|
|
|
CODE: |
186
|
|
|
|
|
|
|
{ |
187
|
|
|
|
|
|
|
int rv; |
188
|
|
|
|
|
|
|
unsigned char out[32]; |
189
|
0
|
|
|
|
|
|
unsigned long int out_len = sizeof(out); |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
RETVAL = newSVpvn(NULL, 0); /* undef */ |
192
|
0
|
0
|
|
|
|
|
if (strnEQ(type, "private", 7)) { |
193
|
0
|
|
|
|
|
|
rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key); |
194
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); |
195
|
0
|
|
|
|
|
|
RETVAL = newSVpvn((char*)out, out_len); |
196
|
|
|
|
|
|
|
} |
197
|
0
|
0
|
|
|
|
|
else if (strnEQ(type, "public", 6)) { |
198
|
0
|
|
|
|
|
|
rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key); |
199
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); |
200
|
0
|
|
|
|
|
|
RETVAL = newSVpvn((char*)out, out_len); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
else { |
203
|
0
|
|
|
|
|
|
croak("FATAL: export_key_raw invalid type '%s'", type); |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
OUTPUT: |
207
|
|
|
|
|
|
|
RETVAL |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
SV * |
210
|
|
|
|
|
|
|
sign_message(Crypt::PK::Ed25519 self, SV * data) |
211
|
|
|
|
|
|
|
CODE: |
212
|
|
|
|
|
|
|
{ |
213
|
|
|
|
|
|
|
int rv; |
214
|
0
|
|
|
|
|
|
unsigned char buffer[64], *data_ptr = NULL; |
215
|
0
|
|
|
|
|
|
unsigned long buffer_len = 64; |
216
|
0
|
|
|
|
|
|
STRLEN data_len = 0; |
217
|
|
|
|
|
|
|
|
218
|
0
|
0
|
|
|
|
|
data_ptr = (unsigned char *)SvPVbyte(data, data_len); |
219
|
0
|
|
|
|
|
|
rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key); |
220
|
0
|
0
|
|
|
|
|
if (rv != CRYPT_OK) croak("FATAL: ed25519_sign failed: %s", error_to_string(rv)); |
221
|
0
|
|
|
|
|
|
RETVAL = newSVpvn((char*)buffer, buffer_len); |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
OUTPUT: |
224
|
|
|
|
|
|
|
RETVAL |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
int |
227
|
|
|
|
|
|
|
verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data) |
228
|
|
|
|
|
|
|
CODE: |
229
|
|
|
|
|
|
|
{ |
230
|
|
|
|
|
|
|
int rv, stat; |
231
|
0
|
|
|
|
|
|
unsigned char *data_ptr = NULL, *sig_ptr = NULL; |
232
|
0
|
|
|
|
|
|
STRLEN data_len = 0, sig_len = 0; |
233
|
|
|
|
|
|
|
|
234
|
0
|
0
|
|
|
|
|
data_ptr = (unsigned char *)SvPVbyte(data, data_len); |
235
|
0
|
0
|
|
|
|
|
sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len); |
236
|
0
|
|
|
|
|
|
RETVAL = 0; |
237
|
0
|
|
|
|
|
|
stat = 0; |
238
|
0
|
|
|
|
|
|
rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key); |
239
|
0
|
0
|
|
|
|
|
if (rv == CRYPT_OK && stat == 1) RETVAL = 1; |
|
|
0
|
|
|
|
|
|
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
OUTPUT: |
242
|
|
|
|
|
|
|
RETVAL |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
void |
245
|
|
|
|
|
|
|
DESTROY(Crypt::PK::Ed25519 self) |
246
|
|
|
|
|
|
|
CODE: |
247
|
0
|
|
|
|
|
|
Safefree(self); |