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