File Coverage

inc/CryptX_PK_RSA.xs.inc
Criterion Covered Total %
statement 203 263 77.1
branch 121 272 44.4
condition n/a
subroutine n/a
pod n/a
total 324 535 60.5


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::PK::RSA
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::PK::RSA
6             _new(Class)
7             CODE:
8             {
9             int rv;
10 107           Newz(0, RETVAL, 1, struct rsa_struct);
11 107 50         if (!RETVAL) croak("FATAL: Newz failed");
12 107           RETVAL->key.type = -1;
13 107           RETVAL->pindex = find_prng("chacha20");
14 107 50         if (RETVAL->pindex == -1) {
15 0           Safefree(RETVAL);
16 0           croak("FATAL: find_prng('chacha20') failed");
17             }
18 107           rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */
19 107 50         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::RSA self, int key_size=256, long key_e=65537)
29             PPCODE:
30             {
31             /* key_size is in octets */
32             int rv;
33             /* gen the key */
34 1           rv = rsa_make_key(&self->pstate, self->pindex, key_size, key_e, &self->key);
35 1 50         if (rv != CRYPT_OK) croak("FATAL: rsa_make_key failed: %s", error_to_string(rv));
36 1 50         XPUSHs(ST(0)); /* return self */
37             }
38              
39             void
40             _import(Crypt::PK::RSA self, SV * key_data)
41             PPCODE:
42             {
43             int rv;
44 128           unsigned char *data=NULL;
45 128           STRLEN data_len=0;
46              
47 128 50         data = (unsigned char *)SvPVbyte(key_data, data_len);
48 128 100         if (self->key.type != -1) { rsa_free(&self->key); self->key.type = -1; }
49 128           rv = rsa_import(data, (unsigned long)data_len, &self->key);
50 128 100         if (rv != CRYPT_OK) croak("FATAL: rsa_import failed: %s", error_to_string(rv));
51 125 50         XPUSHs(ST(0)); /* return self */
52             }
53              
54             void
55             _import_pkcs8(Crypt::PK::RSA self, SV * key_data, SV * passwd)
56             PPCODE:
57             {
58             int rv;
59 5           unsigned char *data=NULL, *pwd=NULL;
60 5           STRLEN data_len=0, pwd_len=0;
61              
62 5 50         data = (unsigned char *)SvPVbyte(key_data, data_len);
63 5 100         if (SvOK(passwd)) {
    50          
    50          
64 2 50         pwd = (unsigned char *)SvPVbyte(passwd, pwd_len);
65             }
66 5 100         if (self->key.type != -1) { rsa_free(&self->key); self->key.type = -1; }
67 5           rv = rsa_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key);
68 5 100         if (rv != CRYPT_OK) croak("FATAL: rsa_import_pkcs8 failed: %s", error_to_string(rv));
69 4 50         XPUSHs(ST(0)); /* return self */
70             }
71              
72             void
73             _import_x509(Crypt::PK::RSA self, SV * key_data)
74             PPCODE:
75             {
76             int rv;
77 2           unsigned char *data=NULL;
78 2           STRLEN data_len=0;
79              
80 2 50         data = (unsigned char *)SvPVbyte(key_data, data_len);
81 2 50         if (self->key.type != -1) { rsa_free(&self->key); self->key.type = -1; }
82 2           rv = rsa_import_x509(data, (unsigned long)data_len, &self->key);
83 2 50         if (rv != CRYPT_OK) croak("FATAL: rsa_import_x509 failed: %s", error_to_string(rv));
84 2 50         XPUSHs(ST(0)); /* return self */
85             }
86              
87             void
88             _import_hex(Crypt::PK::RSA self, char *N, char *e, char *d=NULL, char *p=NULL, char *q=NULL, char *dP=NULL, char *dQ=NULL, char *qP=NULL)
89             PPCODE:
90             {
91             int rv;
92             unsigned char Nbin[1024], ebin[128], dbin[1024], pbin[512], qbin[512], dPbin[512], dQbin[512], qPbin[512];
93 13           unsigned long Nlen=sizeof(Nbin), elen=sizeof(ebin), dlen=sizeof(dbin), plen=sizeof(pbin),
94 13           qlen=sizeof(qbin), dPlen=sizeof(dPbin), dQlen=sizeof(dQbin), qPlen=sizeof(qPbin);
95              
96 13           rv = radix_to_bin(N, 16, Nbin, &Nlen);
97 13 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(N) failed: %s", error_to_string(rv));
98 13           rv = radix_to_bin(e, 16, ebin, &elen);
99 13 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(e) failed: %s", error_to_string(rv));
100              
101 13 50         if (d && strlen(d) > 0) {
    0          
102             /* private */
103 0           rv = radix_to_bin(d, 16, dbin, &dlen);
104 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(d) failed: %s", error_to_string(rv));
105 0           rv = rsa_set_key(Nbin, Nlen, ebin, elen, dbin, dlen, &self->key);
106 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_set_key failed: %s", error_to_string(rv));
107             }
108             else {
109             /* public */
110 13           rv = rsa_set_key(Nbin, Nlen, ebin, elen, NULL, 0, &self->key);
111 13 50         if (rv != CRYPT_OK) croak("FATAL: rsa_set_key failed: %s", error_to_string(rv));
112             }
113              
114 13 50         if (p && strlen(p) > 0 && q && strlen(q) > 0) {
    0          
    0          
    0          
115             /* private only */
116 0           rv = radix_to_bin(p, 16, pbin, &plen);
117 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
118 0           rv = radix_to_bin(q, 16, qbin, &qlen);
119 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(q) failed: %s", error_to_string(rv));
120 0           rv = rsa_set_factors(pbin, plen, qbin, qlen, &self->key);
121 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_set_factors failed: %s", error_to_string(rv));
122             }
123              
124 13 50         if (dP && strlen(dP) > 0 && dQ && strlen(dQ) > 0 && qP && strlen(qP) > 0) {
    0          
    0          
    0          
    0          
    0          
125             /* private only */
126 0           rv = radix_to_bin(dP, 16, dPbin, &dPlen);
127 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(dP) failed: %s", error_to_string(rv));
128 0           rv = radix_to_bin(dQ, 16, dQbin, &dQlen);
129 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(dQ) failed: %s", error_to_string(rv));
130 0           rv = radix_to_bin(qP, 16, qPbin, &qPlen);
131 0 0         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(qP) failed: %s", error_to_string(rv));
132 0           rv = rsa_set_crt_params(dPbin, dPlen, dQbin, dQlen, qPbin, qPlen, &self->key);
133 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_set_crt_params failed: %s", error_to_string(rv));
134             }
135              
136 13 50         XPUSHs(ST(0)); /* return self */
137             }
138              
139             int
140             is_private(Crypt::PK::RSA self)
141             CODE:
142 70 50         if (self->key.type == -1 || self->key.N == NULL) XSRETURN_UNDEF;
    50          
143 70           RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
144             OUTPUT:
145             RETVAL
146              
147             int
148             size(Crypt::PK::RSA self)
149             CODE:
150 1 50         if (self->key.type == -1 || self->key.N == NULL) XSRETURN_UNDEF;
    50          
151 1           RETVAL = mp_unsigned_bin_size(self->key.N);
152             OUTPUT:
153             RETVAL
154              
155             SV*
156             key2hash(Crypt::PK::RSA self)
157             PREINIT:
158             HV *rv_hash;
159             long siz, nsize;
160             char buf[20001];
161             SV **not_used;
162             CODE:
163 109 50         if (self->key.type == -1 || self->key.N == NULL) XSRETURN_UNDEF;
    50          
164 109           nsize = mp_unsigned_bin_size(self->key.N);
165 109           rv_hash = newHV();
166             /* e */
167 109 50         siz = (self->key.e) ? mp_unsigned_bin_size(self->key.e) : 0;
168 109 50         if (siz>10000) {
169 0           croak("FATAL: key2hash failed - 'e' too big number");
170             }
171 109 50         if (siz>0) {
172 109           cryptx_internal_mp2hex_with_leading_zero(self->key.e, buf, 20000, 0);
173 109           not_used = hv_store(rv_hash, "e", 1, newSVpv(buf, strlen(buf)), 0);
174             }
175             else{
176 0           not_used = hv_store(rv_hash, "e", 1, newSVpv("", 0), 0);
177             }
178             /* d */
179 109 50         siz = (self->key.d) ? mp_unsigned_bin_size(self->key.d) : 0;
180 109 50         if (siz>10000) {
181 0           croak("FATAL: key2hash failed - 'd' too big number");
182             }
183 109 100         if (siz>0) {
184 49           cryptx_internal_mp2hex_with_leading_zero(self->key.d, buf, 20000, 0);
185 49           not_used = hv_store(rv_hash, "d", 1, newSVpv(buf, strlen(buf)), 0);
186             }
187             else{
188 60           not_used = hv_store(rv_hash, "d", 1, newSVpv("", 0), 0);
189             }
190             /* N */
191 109 50         siz = (self->key.N) ? nsize : 0;
192 109 50         if (siz>10000) {
193 0           croak("FATAL: key2hash failed - 'N' too big number");
194             }
195 109 50         if (siz>0) {
196 109           cryptx_internal_mp2hex_with_leading_zero(self->key.N, buf, 20000, 0);
197 109           not_used = hv_store(rv_hash, "N", 1, newSVpv(buf, strlen(buf)), 0);
198             }
199             else{
200 0           not_used = hv_store(rv_hash, "N", 1, newSVpv("", 0), 0);
201             }
202             /* q */
203 109 50         siz = (self->key.q) ? mp_unsigned_bin_size(self->key.q) : 0;
204 109 50         if (siz>10000) {
205 0           croak("FATAL: key2hash failed - 'q' too big number");
206             }
207 109 100         if (siz>0) {
208 49           cryptx_internal_mp2hex_with_leading_zero(self->key.q, buf, 20000, 0);
209 49           not_used = hv_store(rv_hash, "q", 1, newSVpv(buf, strlen(buf)), 0);
210             }
211             else{
212 60           not_used = hv_store(rv_hash, "q", 1, newSVpv("", 0), 0);
213             }
214             /* p */
215 109 50         siz = (self->key.p) ? mp_unsigned_bin_size(self->key.p) : 0;
216 109 50         if (siz>10000) {
217 0           croak("FATAL: key2hash failed - 'p' too big number");
218             }
219 109 100         if (siz>0) {
220 49           cryptx_internal_mp2hex_with_leading_zero(self->key.p, buf, 20000, 0);
221 49           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
222             }
223             else{
224 60           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
225             }
226             /* qP */
227 109 50         siz = (self->key.qP) ? mp_unsigned_bin_size(self->key.qP) : 0;
228 109 50         if (siz>10000) {
229 0           croak("FATAL: key2hash failed - 'qP' too big number");
230             }
231 109 100         if (siz>0) {
232 49           cryptx_internal_mp2hex_with_leading_zero(self->key.qP, buf, 20000, 0);
233 49           not_used = hv_store(rv_hash, "qP", 2, newSVpv(buf, strlen(buf)), 0);
234             }
235             else{
236 60           not_used = hv_store(rv_hash, "qP", 2, newSVpv("", 0), 0);
237             }
238             /* dP */
239 109 50         siz = (self->key.dP) ? mp_unsigned_bin_size(self->key.dP) : 0;
240 109 50         if (siz>10000) {
241 0           croak("FATAL: key2hash failed - 'dP' too big number");
242             }
243 109 100         if (siz>0) {
244 49           cryptx_internal_mp2hex_with_leading_zero(self->key.dP, buf, 20000, 0);
245 49           not_used = hv_store(rv_hash, "dP", 2, newSVpv(buf, strlen(buf)), 0);
246             }
247             else{
248 60           not_used = hv_store(rv_hash, "dP", 2, newSVpv("", 0), 0);
249             }
250             /* dQ */
251 109 50         siz = (self->key.dQ) ? mp_unsigned_bin_size(self->key.dQ) : 0;
252 109 50         if (siz>10000) {
253 0           croak("FATAL: key2hash failed - 'dQ' too big number");
254             }
255 109 100         if (siz>0) {
256 49           cryptx_internal_mp2hex_with_leading_zero(self->key.dQ, buf, 20000, 0);
257 49           not_used = hv_store(rv_hash, "dQ", 2, newSVpv(buf, strlen(buf)), 0);
258             }
259             else{
260 60           not_used = hv_store(rv_hash, "dQ", 2, newSVpv("", 0), 0);
261             }
262             /* size */
263 109           not_used = hv_store(rv_hash, "size", 4, newSViv(nsize), 0);
264             /* type */
265 109           not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
266             LTC_UNUSED_PARAM(not_used);
267 109           RETVAL = newRV_noinc((SV*)rv_hash);
268             OUTPUT:
269             RETVAL
270              
271             SV*
272             export_key_der(Crypt::PK::RSA self, char * type)
273             CODE:
274             {
275             int rv;
276             unsigned char out[4096];
277 5           unsigned long out_len = 4096;
278              
279 5           RETVAL = newSVpvn(NULL, 0); /* undef */
280 5 100         if (strnEQ(type, "private", 7)) {
281 2           rv = rsa_export(out, &out_len, PK_PRIVATE, &self->key);
282 2 50         if (rv != CRYPT_OK) croak("FATAL: rsa_export(PK_PRIVATE) failed: %s", error_to_string(rv));
283 2           RETVAL = newSVpvn((char*)out, out_len);
284             }
285 3 50         else if (strnEQ(type, "public", 6)) {
286 3           rv = rsa_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
287 3 50         if (rv != CRYPT_OK) croak("FATAL: rsa_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv));
288 3           RETVAL = newSVpvn((char*)out, out_len);
289             }
290             else {
291 0           croak("FATAL: export_key_der invalid type '%s'", type);
292             }
293             }
294             OUTPUT:
295             RETVAL
296              
297             SV *
298             encrypt(Crypt::PK::RSA self, SV * data, const char * padding = "oaep", const char * oaep_hash = "SHA1", SV * oaep_lparam = NULL)
299             CODE:
300             {
301             int rv, hash_id;
302 2           unsigned char *lparam_ptr=NULL;
303 2           STRLEN lparam_len=0;
304 2           unsigned char *data_ptr=NULL;
305 2           STRLEN data_len=0;
306             unsigned char buffer[1024];
307 2           unsigned long buffer_len = 1024;
308              
309 2 50         data_ptr = (unsigned char *)SvPVbyte(data, data_len);
310              
311 2           RETVAL = newSVpvn(NULL, 0); /* undef */
312 2 100         if (strnEQ(padding, "oaep", 4)) {
313 1           hash_id = cryptx_internal_find_hash(oaep_hash);
314 1 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", oaep_hash);
315 1 50         if (oaep_lparam) lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
    0          
316 1           rv = rsa_encrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, lparam_ptr, (unsigned long)lparam_len,
317             &self->pstate, self->pindex,
318 1           hash_id, LTC_PKCS_1_OAEP, &self->key);
319 1 50         if (rv != CRYPT_OK) croak("FATAL: rsa_encrypt_key_ex failed: %s", error_to_string(rv));
320 1           RETVAL = newSVpvn((char*)buffer, buffer_len);
321             }
322 1 50         else if (strnEQ(padding, "v1.5", 4)) {
323 0           rv = rsa_encrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, NULL, 0,
324             &self->pstate, self->pindex,
325 0           0, LTC_PKCS_1_V1_5, &self->key);
326 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_encrypt_key_ex failed: %s", error_to_string(rv));
327 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
328             }
329 1 50         else if (strnEQ(padding, "none", 4)) {
330             /* raw RSA */
331 1           rv = ltc_mp.rsa_me(data_ptr, (unsigned long)data_len, buffer, &buffer_len, PK_PUBLIC, &self->key);
332 1 50         if (rv != CRYPT_OK) croak("FATAL: rsa_me failed: %s", error_to_string(rv));
333 1           RETVAL = newSVpvn((char*)buffer, buffer_len);
334             }
335             else {
336 0           croak("FATAL: rsa_encrypt invalid padding '%s'", padding);
337             }
338             }
339             OUTPUT:
340             RETVAL
341              
342             SV *
343             decrypt(Crypt::PK::RSA self, SV * data, const char * padding = "oaep", const char * oaep_hash = "SHA1", SV * oaep_lparam = NULL)
344             CODE:
345             {
346             int rv, hash_id, stat;
347 38           unsigned char *lparam_ptr=NULL;
348 38           STRLEN lparam_len=0;
349 38           unsigned char *data_ptr=NULL;
350 38           STRLEN data_len=0;
351             unsigned char buffer[1024];
352 38           unsigned long buffer_len = 1024;
353              
354 38 50         data_ptr = (unsigned char *)SvPVbyte(data, data_len);
355              
356 38           RETVAL = newSVpvn(NULL, 0); /* undef */
357 38 100         if (strnEQ(padding, "oaep", 4)) {
358 1           hash_id = cryptx_internal_find_hash(oaep_hash);
359 1 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", oaep_hash);
360 1 50         if (oaep_lparam) lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
    0          
361 1           rv = rsa_decrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, lparam_ptr, (unsigned long)lparam_len,
362 1           hash_id, LTC_PKCS_1_OAEP, &stat, &self->key);
363 1 50         if (rv != CRYPT_OK) croak("FATAL: rsa_decrypt_key_ex failed: %s", error_to_string(rv));
364 1 50         if (stat != 1) croak("FATAL: rsa_decrypt - not valid OAEP packet");
365 1           RETVAL = newSVpvn((char*)buffer, buffer_len);
366             }
367 37 100         else if (strnEQ(padding, "v1.5", 4)) {
368 36           rv = rsa_decrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, NULL, 0,
369 36           0, LTC_PKCS_1_V1_5, &stat, &self->key);
370 36 50         if (rv != CRYPT_OK) croak("FATAL: rsa_decrypt_key_ex failed: %s", error_to_string(rv));
371 36 50         if (stat != 1) croak("FATAL: rsa_decrypt - invalid");
372 36           RETVAL = newSVpvn((char*)buffer, buffer_len);
373             }
374 1 50         else if (strnEQ(padding, "none", 4)) {
375             /* raw RSA */
376 1           rv = ltc_mp.rsa_me(data_ptr, (unsigned long)data_len, buffer, &buffer_len, PK_PRIVATE, &self->key);
377 1 50         if (rv != CRYPT_OK) croak("FATAL: rsa_me failed: %s", error_to_string(rv));
378 1           RETVAL = newSVpvn((char*)buffer, buffer_len);
379             }
380             else {
381 0           croak("FATAL: rsa_encrypt invalid padding '%s'", padding);
382             }
383             }
384             OUTPUT:
385             RETVAL
386              
387             SV *
388             sign_hash(Crypt::PK::RSA self, SV * data, const char * hash_name = "SHA1", const char * padding = "pss", unsigned long saltlen=12)
389             ALIAS:
390             sign_message = 1
391             CODE:
392             {
393             int rv, hash_id;
394 4           unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
395 4           unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
396 4           STRLEN data_len = 0;
397              
398 4 50         data_ptr = (unsigned char *)SvPVbyte(data, data_len);
399 4 100         if (ix == 1) {
400 2           hash_id = cryptx_internal_find_hash(hash_name);
401 2 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
402 2           rv = hash_memory(hash_id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
403 2 50         if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
404 2           data_ptr = tmp;
405 2           data_len = tmp_len;
406             }
407 4 50         if (strnEQ(padding, "pss", 3)) {
408 4           hash_id = cryptx_internal_find_hash(hash_name);
409 4 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
410 4           rv = rsa_sign_hash_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, LTC_PKCS_1_PSS,
411             &self->pstate, self->pindex,
412 4           hash_id, saltlen, &self->key);
413 4 50         if (rv != CRYPT_OK) croak("FATAL: rsa_sign_hash_ex failed: %s", error_to_string(rv));
414 4           RETVAL = newSVpvn((char*)buffer, buffer_len);
415             }
416 0 0         else if (strnEQ(padding, "v1.5", 4)) {
417 0           hash_id = cryptx_internal_find_hash(hash_name);
418 0 0         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
419 0           rv = rsa_sign_hash_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, LTC_PKCS_1_V1_5,
420             &self->pstate, self->pindex,
421 0           hash_id, 0, &self->key);
422 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_sign_hash_ex failed: %s", error_to_string(rv));
423 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
424             }
425 0 0         else if (strnEQ(padding, "none", 4)) {
426             /* raw RSA */
427 0           rv = ltc_mp.rsa_me(data_ptr, (unsigned long)data_len, buffer, &buffer_len, PK_PRIVATE, &self->key);
428 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_me failed: %s", error_to_string(rv));
429 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
430             }
431             else {
432 0           croak("FATAL: rsa_sign invalid padding '%s'", padding);
433             }
434             }
435             OUTPUT:
436             RETVAL
437              
438             int
439             verify_hash(Crypt::PK::RSA self, SV * sig, SV * data, const char * hash_name = "SHA1", const char * padding = "pss", unsigned long saltlen = 12)
440             ALIAS:
441             verify_message = 1
442             CODE:
443             {
444             int rv, hash_id, stat;
445 109           unsigned char tmp[MAXBLOCKSIZE], buffer[1024], *data_ptr = NULL, *sig_ptr = NULL;
446 109           unsigned long i, tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
447 109           STRLEN data_len = 0, sig_len = 0;
448              
449 109 50         data_ptr = (unsigned char *)SvPVbyte(data, data_len);
450 109 50         sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
451 109 100         if (ix == 1) {
452 107           hash_id = cryptx_internal_find_hash(hash_name);
453 107 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
454 107           rv = hash_memory(hash_id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
455 107 50         if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
456 107           data_ptr = tmp;
457 107           data_len = tmp_len;
458             }
459 109           RETVAL = 1;
460 109           stat = 0;
461 109 100         if (strnEQ(padding, "pss", 3)) {
462 4           hash_id = cryptx_internal_find_hash(hash_name);
463 4 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
464 4           rv = rsa_verify_hash_ex(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, LTC_PKCS_1_PSS,
465 4           hash_id, saltlen, &stat, &self->key);
466 4 50         if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
    50          
467             }
468 105 50         else if (strnEQ(padding, "v1.5", 4)) {
469 105           hash_id = cryptx_internal_find_hash(hash_name);
470 105 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
471 105           rv = rsa_verify_hash_ex(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, LTC_PKCS_1_V1_5,
472 105           hash_id, 0, &stat, &self->key);
473 105 100         if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
    50          
474             }
475 0 0         else if (strnEQ(padding, "none", 4)) {
476             /* raw RSA */
477 0           Zero(buffer, buffer_len, unsigned char);
478 0           rv = ltc_mp.rsa_me(sig_ptr, (unsigned long)sig_len, buffer, &buffer_len, PK_PUBLIC, &self->key);
479 0 0         if (rv != CRYPT_OK) croak("FATAL: rsa_me failed: %s", error_to_string(rv));
480 0 0         if (data_len <= buffer_len && buffer_len > 0 && data_len > 0) {
    0          
    0          
481 0 0         for (i = 0; i < buffer_len - data_len; i++) if (buffer[i] != 0) RETVAL = 0;
    0          
482 0 0         if (memNE(data_ptr, buffer + buffer_len - data_len, data_len)) RETVAL = 0;
483             }
484             else {
485 0           RETVAL = 0;
486             }
487             }
488             else {
489 0           croak("FATAL: rsa_verify invalid padding '%s'", padding);
490             }
491             }
492             OUTPUT:
493             RETVAL
494              
495             void
496             DESTROY(Crypt::PK::RSA self)
497             CODE:
498 107 50         if (self->key.type != -1) { rsa_free(&self->key); self->key.type = -1; }
499 107           Safefree(self);