is needed.
[openssl.git] / perl / openssl_bn.xs
1
2 #include "openssl.h"
3
4 int sv_to_BIGNUM(var,arg,name)
5 BIGNUM **var;
6 SV *arg;
7 char *name;
8         {
9         int ret=1;
10
11         if (sv_derived_from(arg,"OpenSSL::BN"))
12                 {
13                 IV tmp = SvIV((SV*)SvRV(arg));
14                 *var = (BIGNUM *) tmp;
15                 }
16         else if (SvIOK(arg)) {
17                 SV *tmp=sv_newmortal();
18                 *var=BN_new();
19                 BN_set_word(*var,SvIV(arg));
20                 sv_setref_pv(tmp,"OpenSSL::BN",(void*)*var);
21                 }
22         else if (SvPOK(arg)) {
23                 char *ptr;
24                 STRLEN len;
25                 SV *tmp=sv_newmortal();
26                 *var=BN_new();
27                 sv_setref_pv(tmp,"OpenSSL::BN", (void*)*var);
28                 ptr=SvPV(arg,len);
29                 SvGROW(arg,len+1);
30                 ptr[len]='\0';
31                 BN_dec2bn(var,ptr);
32                 }
33         else
34                 {
35                 croak(name);
36                 ret=0;
37                 }
38         return(ret);
39         }
40
41 typedef struct gpc_args_st {
42         SV *cb;
43         SV *arg;
44         } GPC_ARGS;
45
46 static void generate_prime_callback(pos,num,arg)
47 int pos;
48 int num;
49 char *arg;
50         {
51         dSP ;
52         int i;
53         GPC_ARGS *a=(GPC_ARGS *)arg;
54
55         ENTER ;
56         SAVETMPS ;
57
58         PUSHMARK(sp);
59         XPUSHs(sv_2mortal(newSViv(pos)));
60         XPUSHs(sv_2mortal(newSViv(num)));
61         XPUSHs(sv_2mortal(newSVsv(a->arg)));
62         PUTBACK;
63
64         i=perl_call_sv(a->cb,G_DISCARD);
65
66         SPAGAIN;
67
68         PUTBACK;
69         FREETMPS;
70         LEAVE;
71         }
72
73 MODULE =  OpenSSL::BN   PACKAGE = OpenSSL::BN   PREFIX = p5_BN_
74
75 PROTOTYPES: ENABLE
76 VERSIONCHECK: DISABLE
77
78 void
79 p5_BN_new(...)
80         PREINIT:
81                 BIGNUM *bn;
82                 SV *arg;
83         PPCODE:
84                 pr_name("p5_BN_new");
85                 EXTEND(sp,1);
86                 PUSHs(sv_newmortal());
87                 bn=BN_new();
88                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)bn);
89
90 void
91 p5_BN_dup(a)
92         BIGNUM *a;
93         PREINIT:
94                 BIGNUM *bn;
95         PPCODE:
96                 pr_name("p5_BN_dup");
97                 EXTEND(sp,1);
98                 PUSHs(sv_newmortal());
99                 bn=BN_dup(a);
100                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)bn);
101
102 void
103 p5_BN_rand(bits,...)
104         int bits;
105         PREINIT:
106                 int top=1;
107                 int bottom=0;
108                 BIGNUM *ret;
109         PPCODE: 
110                 pr_name("p5_BN_rand");
111                 if ((items < 1) || (items > 3))
112                         croak("Usage: OpenSSL::BN::rand(bits[,top_bit][,bottombit]");
113                 if (items >= 2) top=(int)SvIV(ST(0));
114                 if (items >= 3) bottom=(int)SvIV(ST(1));
115                 EXTEND(sp,1);
116                 PUSHs(sv_newmortal());
117                 ret=BN_new();
118                 BN_rand(ret,bits,top,bottom);
119                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
120
121 void
122 p5_BN_bin2bn(a)
123         datum a;
124         PREINIT:
125                 BIGNUM *ret;
126         PPCODE:
127                 pr_name("p5_BN_bin2bn");
128                 EXTEND(sp,1);
129                 PUSHs(sv_newmortal());
130                 ret=BN_bin2bn(a.dptr,a.dsize,NULL);
131                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
132
133 void
134 p5_BN_bn2bin(a)
135         BIGNUM *a;
136         PREINIT:
137                 int i;
138         PPCODE:
139                 pr_name("p5_BN_bn2bin");
140                 EXTEND(sp,1);
141                 PUSHs(sv_newmortal());
142                 i=BN_num_bytes(a)+2;
143                 sv_setpvn(ST(0),"",1);
144                 SvGROW(ST(0),i+1);
145                 SvCUR_set(ST(0),BN_bn2bin(a,SvPV(ST(0),na)));
146
147 void
148 p5_BN_mpi2bn(a)
149         datum a;
150         PREINIT:
151                 BIGNUM *ret;
152         PPCODE:
153                 pr_name("p5_BN_mpi2bn");
154                 EXTEND(sp,1);
155                 PUSHs(sv_newmortal());
156                 ret=BN_mpi2bn(a.dptr,a.dsize,NULL);
157                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
158
159 void
160 p5_BN_bn2mpi(a)
161         BIGNUM *a;
162         PREINIT:
163                 int i;
164         PPCODE:
165                 pr_name("p5_BN_bn2mpi");
166                 EXTEND(sp,1);
167                 PUSHs(sv_newmortal());
168                 i=BN_bn2mpi(a,NULL);
169                 sv_setpvn(ST(0),"",1);
170                 SvGROW(ST(0),i+1);
171                 SvCUR_set(ST(0),BN_bn2mpi(a,SvPV(ST(0),na)));
172
173 void
174 p5_BN_hex2bn(a)
175         datum a;
176         PREINIT:
177                 BIGNUM *ret;
178         PPCODE:
179                 pr_name("p5_BN_hex2bn");
180                 EXTEND(sp,1);
181                 PUSHs(sv_newmortal());
182                 ret=BN_new();
183                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
184                 BN_hex2bn(&ret,a.dptr);
185
186 void
187 p5_BN_dec2bn(a)
188         datum a;
189         PREINIT:
190                 BIGNUM *ret;
191         PPCODE:
192                 pr_name("p5_BN_dec2bn");
193                 EXTEND(sp,1);
194                 PUSHs(sv_newmortal());
195                 ret=BN_new();
196                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
197                 BN_dec2bn(&ret,a.dptr);
198
199 SV *
200 p5_BN_bn2hex(a)
201         BIGNUM *a;
202         PREINIT:
203                 char *ptr;
204                 int i;
205         CODE:
206                 pr_name("p5_BN_bn2hex");
207                 ptr=BN_bn2hex(a);
208                 RETVAL=newSVpv("",0);
209                 i=strlen(ptr);
210                 SvGROW(RETVAL,i+1);
211                 memcpy(SvPV(RETVAL,na),ptr,i+1);
212                 SvCUR_set(RETVAL,i);
213                 Free(ptr);
214         OUTPUT:
215                 RETVAL
216
217 SV *
218 p5_BN_bn2dec(a)
219         BIGNUM *a;
220         PREINIT:
221                 char *ptr;
222                 int i;
223         CODE:
224                 pr_name("p5_BN_bn2dec");
225                 ptr=BN_bn2dec(a);
226                 RETVAL=newSVpv("",0);
227                 i=strlen(ptr);
228                 SvGROW(RETVAL,i+1);
229                 memcpy(SvPV(RETVAL,na),ptr,i+1);
230                 SvCUR_set(RETVAL,i);
231                 Free(ptr);
232         OUTPUT:
233                 RETVAL
234
235 void
236 p5_BN_add(a,b)
237         BIGNUM *a;
238         BIGNUM *b;
239         PREINIT:
240                 BIGNUM *ret;
241         PPCODE:
242                 pr_name("p5_BN_add");
243                 EXTEND(sp,1);
244                 PUSHs(sv_newmortal());
245                 ret=BN_new();
246                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
247                 BN_add(ret,a,b);
248
249 void
250 p5_BN_sub(a,b)
251         BIGNUM *a;
252         BIGNUM *b;
253         PREINIT:
254                 BIGNUM *ret;
255         PPCODE:
256                 pr_name("p5_BN_sub");
257                 EXTEND(sp,1);
258                 PUSHs(sv_newmortal());
259                 ret=BN_new();
260                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
261                 BN_sub(ret,a,b);
262
263 void
264 p5_BN_mul(a,b)
265         BIGNUM *a;
266         BIGNUM *b;
267         PREINIT:
268                 static BN_CTX *ctx=NULL;
269                 BIGNUM *ret;
270         PPCODE:
271                 pr_name("p5_BN_mul");
272                 if (ctx == NULL) ctx=BN_CTX_new();
273                 EXTEND(sp,1);
274                 PUSHs(sv_newmortal());
275                 ret=BN_new();
276                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
277                 BN_mul(ret,a,b,ctx);
278
279 void
280 p5_BN_div(a,b)
281         BIGNUM *a;
282         BIGNUM *b;
283         PREINIT:
284                 static BN_CTX *ctx=NULL;
285                 BIGNUM *div,*mod;
286         PPCODE:
287                 pr_name("p5_BN_div");
288                 if (ctx == NULL) ctx=BN_CTX_new();
289                 EXTEND(sp,2);
290                 PUSHs(sv_newmortal());
291                 PUSHs(sv_newmortal());
292                 div=BN_new();
293                 mod=BN_new();
294                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)div);
295                 sv_setref_pv(ST(1), "OpenSSL::BN", (void*)mod);
296                 BN_div(div,mod,a,b,ctx);
297
298 void
299 p5_BN_mod(a,b)
300         BIGNUM *a;
301         BIGNUM *b;
302         PREINIT:
303                 static BN_CTX *ctx=NULL;
304                 BIGNUM *rem;
305         PPCODE:
306                 pr_name("p5_BN_mod");
307                 if (ctx == NULL) ctx=BN_CTX_new();
308                 EXTEND(sp,1);
309                 PUSHs(sv_newmortal());
310                 rem=BN_new();
311                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)rem);
312                 BN_mod(rem,a,b,ctx);
313
314 void
315 p5_BN_exp(a,p)
316         BIGNUM *a;
317         BIGNUM *p;
318         PREINIT:
319                 BIGNUM *ret;
320                 static BN_CTX *ctx=NULL;
321         PPCODE:
322                 pr_name("p5_BN_exp");
323                 if (ctx == NULL) ctx=BN_CTX_new();
324                 EXTEND(sp,1);
325                 PUSHs(sv_newmortal());
326                 ret=BN_new();
327                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
328                 BN_exp(ret,a,p,ctx);
329
330 void
331 p5_BN_mod_mul(a,b,c)
332         BIGNUM *a;
333         BIGNUM *b;
334         BIGNUM *c;
335         PREINIT:
336                 static BN_CTX *ctx=NULL;
337                 BIGNUM *ret;
338         PPCODE:
339                 pr_name("p5_BN_mod_mul");
340                 if (ctx == NULL) ctx=BN_CTX_new();
341                 EXTEND(sp,1);
342                 PUSHs(sv_newmortal());
343                 ret=BN_new();
344                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
345                 BN_mod_mul(ret,a,b,c,ctx);
346
347 void
348 p5_BN_mod_exp(a,b,c)
349         BIGNUM *a;
350         BIGNUM *b;
351         BIGNUM *c;
352         PREINIT:
353                 static BN_CTX *ctx=NULL;
354                 BIGNUM *ret;
355         PPCODE:
356                 pr_name("p5_BN_mod_exp");
357                 if (ctx == NULL) ctx=BN_CTX_new();
358                 EXTEND(sp,1);
359                 PUSHs(sv_newmortal());
360                 ret=BN_new();
361                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
362                 BN_mod_exp(ret,a,b,c,ctx);
363
364 void
365 p5_BN_generate_prime(...)
366         PREINIT:
367                 int bits=512;
368                 int strong=0;
369                 BIGNUM *ret=NULL;
370                 SV *callback=NULL;
371                 SV *cb_arg=NULL;
372                 GPC_ARGS arg;
373                 dSP;
374
375         PPCODE:
376                 pr_name("p5_BN_generate_prime");
377                 if ((items < 0) || (items > 4))
378                         croak("Usage: OpenSSL::BN::generate_prime(a[,strong][,callback][,cb_arg]");
379                 if (items >= 1) bits=(int)SvIV(ST(0));
380                 if (items >= 2) strong=(int)SvIV(ST(1));
381                 if (items >= 3) callback=ST(2);
382                 if (items == 4) cb_arg=ST(3);
383
384                 if (callback == NULL)
385                         ret=BN_generate_prime(ret,bits,strong,NULL,NULL,NULL,NULL);
386                 else
387                         {
388                         arg.cb=callback;
389                         arg.arg=cb_arg;
390
391                         ret=BN_generate_prime(ret,bits,strong,NULL,NULL,
392                                 generate_prime_callback,(char *)&arg);
393                         }
394
395                 SPAGAIN;
396                 sp-=items; /* a bit evil that I do this */
397
398                 EXTEND(sp,1);
399                 PUSHs(sv_newmortal());
400                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
401
402 void
403 p5_BN_is_prime(p,...)
404         BIGNUM *p;
405         PREINIT:
406         int nchecks=5,ret;
407         SV *callback=NULL;
408         SV *cb_arg=NULL;
409         GPC_ARGS arg;
410         dSP;
411         static BN_CTX *ctx=NULL;
412         PPCODE:
413                 pr_name("p5_BN_is_prime");
414                 if ((items < 1) || (items > 4))
415                         croak("Usage: OpenSSL::BN::is_prime(a[,ncheck][,callback][,callback_arg]");
416                 if (ctx == NULL) ctx=BN_CTX_new();
417                 if (items >= 2) nchecks=(int)SvIV(ST(1));
418                 if (items >= 3) callback=ST(2);
419                 if (items >= 4) cb_arg=ST(3);
420                 arg.arg=cb_arg; 
421                 if (callback == NULL)
422                         ret=BN_is_prime(p,nchecks,NULL,ctx,NULL);
423                 else
424                         {
425                         arg.cb=callback;
426                         arg.arg=cb_arg;
427                         ret=BN_is_prime(p,nchecks,generate_prime_callback,
428                                 ctx,(char *)&arg);
429                         }
430                 SPAGAIN;
431                 sp-=items; /* a bit evil */
432                 PUSHs(sv_2mortal(newSViv(ret)));
433
434 int
435 p5_BN_num_bits(a)
436         BIGNUM *a;
437         CODE:
438                 pr_name("p5_BN_num_bits");
439                 RETVAL=BN_num_bits(a);
440         OUTPUT:
441                 RETVAL
442
443 int
444 p5_BN_cmp(a,b)
445         BIGNUM *a;
446         BIGNUM *b;
447         CODE:
448                 pr_name("p5_BN_cmp");
449                 RETVAL=BN_cmp(a,b);
450         OUTPUT:
451                 RETVAL
452
453 int
454 p5_BN_ucmp(a,b)
455         BIGNUM *a;
456         BIGNUM *b;
457         CODE:
458                 pr_name("p5_BN_ucmp");
459                 RETVAL=BN_ucmp(a,b);
460         OUTPUT:
461                 RETVAL
462
463 int
464 p5_BN_is_bit_set(a,b)
465         BIGNUM *a;
466         int b;
467         CODE:
468                 pr_name("p5_BN_is_bit_set");
469                 RETVAL=BN_is_bit_set(a,b);
470         OUTPUT:
471                 RETVAL
472
473 void
474 p5_BN_set_bit(a,b)
475         BIGNUM *a;
476         int b;
477         PREINIT:
478                 BIGNUM *ret;
479         PPCODE:
480                 pr_name("p5_BN_set_bit");
481                 EXTEND(sp,1);
482                 PUSHs(sv_newmortal());
483                 ret=BN_dup(a);
484                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
485                 BN_set_bit(ret,b);
486
487 void
488 p5_BN_clear_bit(a,b)
489         BIGNUM *a;
490         int b;
491         PREINIT:
492                 BIGNUM *ret;
493         PPCODE:
494                 pr_name("p5_BN_clear_bit");
495                 EXTEND(sp,1);
496                 PUSHs(sv_newmortal());
497                 ret=BN_dup(a);
498                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
499                 BN_clear_bit(ret,b);
500
501 void
502 p5_BN_lshift(a,b)
503         BIGNUM *a;
504         int b;
505         PREINIT:
506                 BIGNUM *ret;
507         PPCODE:
508                 pr_name("p5_BN_lshift");
509                 EXTEND(sp,1);
510                 PUSHs(sv_newmortal());
511                 ret=BN_new();
512                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
513                 if (b == 1)
514                         BN_lshift1(ret,a);
515                 else
516                         BN_lshift(ret,a,b);
517
518 void
519 p5_BN_rshift(a,b)
520         BIGNUM *a;
521         int b;
522         PREINIT:
523                 BIGNUM *ret;
524         PPCODE:
525                 pr_name("p5_BN_rshift");
526                 EXTEND(sp,1);
527                 PUSHs(sv_newmortal());
528                 ret=BN_new();
529                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
530                 if (b == 1)
531                         BN_rshift1(ret,a);
532                 else
533                         BN_rshift(ret,a,b);
534
535 void
536 p5_BN_mask_bits(a,b)
537         BIGNUM *a;
538         int b;
539         PREINIT:
540                 BIGNUM *ret;
541         PPCODE:
542                 pr_name("p5_BN_mask_bits");
543                 EXTEND(sp,1);
544                 PUSHs(sv_newmortal());
545                 ret=BN_dup(a);
546                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
547                 BN_mask_bits(ret,b);
548
549 void
550 p5_BN_clear(a)
551         BIGNUM *a;
552         PPCODE:
553                 pr_name("p5_BN_clear");
554                 BN_clear(a);
555
556 void
557 p5_BN_gcd(a,b)
558         BIGNUM *a;
559         BIGNUM *b;
560         PREINIT:
561                 static BN_CTX *ctx=NULL;
562                 BIGNUM *ret;
563         PPCODE:
564                 pr_name("p5_BN_gcd");
565                 if (ctx == NULL) ctx=BN_CTX_new();
566                 EXTEND(sp,1);
567                 PUSHs(sv_newmortal());
568                 ret=BN_new();
569                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
570                 BN_gcd(ret,a,b,ctx);
571
572 void
573 p5_BN_mod_inverse(a,mod)
574         BIGNUM *a;
575         BIGNUM *mod;
576         PREINIT:
577                 static BN_CTX *ctx=NULL;
578                 BIGNUM *ret;
579         PPCODE:
580                 pr_name("p5_BN_mod_inverse");
581                 if (ctx == NULL) ctx=BN_CTX_new();
582                 ret=BN_mod_inverse(ret,a,mod,ctx);
583                 EXTEND(sp,1);
584                 PUSHs(sv_newmortal());
585                 sv_setref_pv(ST(0), "OpenSSL::BN", (void*)ret);
586
587 void
588 p5_BN_DESTROY(bn)
589         BIGNUM *bn
590         CODE:
591         pr_name("p5_BN_DESTROY");
592         BN_free(bn);
593