| 1 | # ---?--- |
| 2 | # |
| 3 | # $Id$ |
| 4 | # |
| 5 | # Elliptic curves |
| 6 | # |
| 7 | # (c) 2001 Straylight/Edgeware |
| 8 | # |
| 9 | |
| 10 | #----- Licensing notice ----------------------------------------------------- |
| 11 | # |
| 12 | # This file is part of the Perl interface to Catacomb. |
| 13 | # |
| 14 | # Catacomb/Perl is free software; you can redistribute it and/or modify |
| 15 | # it under the terms of the GNU General Public License as published by |
| 16 | # the Free Software Foundation; either version 2 of the License, or |
| 17 | # (at your option) any later version. |
| 18 | # |
| 19 | # Catacomb/Perl is distributed in the hope that it will be useful, |
| 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 22 | # GNU General Public License for more details. |
| 23 | # |
| 24 | # You should have received a copy of the GNU General Public License |
| 25 | # along with Catacomb/Perl; if not, write to the Free Software Foundation, |
| 26 | # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 27 | |
| 28 | MODULE = Catacomb PACKAGE = Catacomb::EC::Point PREFIX = ec_ |
| 29 | |
| 30 | ec * |
| 31 | new(me, x = 0, y = 0, z = 0) |
| 32 | SV *me |
| 33 | mp *x |
| 34 | mp *y |
| 35 | mp *z |
| 36 | CODE: |
| 37 | RETVAL = CREATE(ec); |
| 38 | EC_CREATE(RETVAL); |
| 39 | if (x && y) { |
| 40 | RETVAL->x = MP_COPY(x); |
| 41 | RETVAL->y = MP_COPY(y); |
| 42 | if (z) |
| 43 | RETVAL->z = MP_COPY(z); |
| 44 | } |
| 45 | OUTPUT: |
| 46 | RETVAL |
| 47 | |
| 48 | bool |
| 49 | atinfp(p) |
| 50 | ec *p |
| 51 | CODE: |
| 52 | RETVAL = EC_ATINF(p); |
| 53 | OUTPUT: |
| 54 | RETVAL |
| 55 | |
| 56 | mp * |
| 57 | x(p) |
| 58 | ec *p |
| 59 | CODE: |
| 60 | RETVAL = p->x ? MP_COPY(p->x) : 0; |
| 61 | OUTPUT: |
| 62 | RETVAL |
| 63 | |
| 64 | mp * |
| 65 | y(p) |
| 66 | ec *p |
| 67 | CODE: |
| 68 | RETVAL = p->y ? MP_COPY(p->y) : 0; |
| 69 | OUTPUT: |
| 70 | RETVAL |
| 71 | |
| 72 | mp * |
| 73 | z(p) |
| 74 | ec *p |
| 75 | CODE: |
| 76 | RETVAL = p->z ? MP_COPY(p->z) : 0; |
| 77 | OUTPUT: |
| 78 | RETVAL |
| 79 | |
| 80 | bool |
| 81 | ec_eq(p, q) |
| 82 | ec *p |
| 83 | ec *q |
| 84 | |
| 85 | SV * |
| 86 | DESTROY(p) |
| 87 | ec *p |
| 88 | CODE: |
| 89 | EC_DESTROY(p); |
| 90 | DESTROY(p); |
| 91 | XSRETURN_YES; |
| 92 | |
| 93 | SV * |
| 94 | put(p) |
| 95 | ec *p |
| 96 | PREINIT: |
| 97 | buf b; |
| 98 | size_t n = EC_ATINF(p) ? 2 : 4 + mp_octets(p->x) + mp_octets(p->y); |
| 99 | CODE: |
| 100 | RETVAL = NEWSV(0, n); |
| 101 | buf_init(&b, SvPVX(RETVAL), n); |
| 102 | if (buf_putec(&b, p)) |
| 103 | croak("unexpected failure in Catacomb::EC::Point::put"); |
| 104 | SvCUR_set(RETVAL, BLEN(&b)); |
| 105 | OUTPUT: |
| 106 | RETVAL |
| 107 | |
| 108 | void |
| 109 | get(s) |
| 110 | SV *s |
| 111 | PREINIT: |
| 112 | ec *p; |
| 113 | buf b; |
| 114 | char *q; |
| 115 | STRLEN n; |
| 116 | CODE: |
| 117 | q = SvPV(s, n); |
| 118 | buf_init(&b, q, n); |
| 119 | p = CREATE(ec); |
| 120 | EC_CREATE(p); |
| 121 | if (buf_getec(&b, p)) |
| 122 | DESTROY(p); |
| 123 | else { |
| 124 | XPUSHs(RET(p, "Catacomb::EC::Point")); |
| 125 | if (GIMME_V == G_ARRAY) |
| 126 | XPUSHs(sv_2mortal(newSVpvn((char *)BCUR(&b), BLEFT(&b)))); |
| 127 | } |
| 128 | |
| 129 | MODULE = Catacomb PACKAGE = Catacomb::EC::Curve PREFIX = ec_ |
| 130 | |
| 131 | EC_Curve * |
| 132 | prime(me, f, a, b) |
| 133 | SV *me |
| 134 | Field *f |
| 135 | mp *a |
| 136 | mp *b |
| 137 | CODE: |
| 138 | RETVAL = ec_prime(f, a, b); |
| 139 | OUTPUT: |
| 140 | RETVAL |
| 141 | |
| 142 | EC_Curve * |
| 143 | primeproj(me, f, a, b) |
| 144 | SV *me |
| 145 | Field *f |
| 146 | mp *a |
| 147 | mp *b |
| 148 | CODE: |
| 149 | RETVAL = ec_primeproj(f, a, b); |
| 150 | OUTPUT: |
| 151 | RETVAL |
| 152 | |
| 153 | EC_Curve * |
| 154 | bin(me, f, a, b) |
| 155 | SV *me |
| 156 | Field *f |
| 157 | gf *a |
| 158 | gf *b |
| 159 | CODE: |
| 160 | RETVAL = ec_bin(f, a, b); |
| 161 | OUTPUT: |
| 162 | RETVAL |
| 163 | |
| 164 | EC_Curve * |
| 165 | binproj(me, f, a, b) |
| 166 | SV *me |
| 167 | Field *f |
| 168 | gf *a |
| 169 | gf *b |
| 170 | CODE: |
| 171 | RETVAL = ec_binproj(f, a, b); |
| 172 | OUTPUT: |
| 173 | RETVAL |
| 174 | |
| 175 | char * |
| 176 | name(c) |
| 177 | EC_Curve *c |
| 178 | CODE: |
| 179 | RETVAL = (char *)EC_NAME(c); |
| 180 | OUTPUT: |
| 181 | RETVAL |
| 182 | |
| 183 | mp * |
| 184 | _a(c) |
| 185 | EC_Curve *c |
| 186 | CODE: |
| 187 | RETVAL = F_OUT(c->f, MP_NEW, c->a); |
| 188 | OUTPUT: |
| 189 | RETVAL |
| 190 | |
| 191 | mp * |
| 192 | _b(c) |
| 193 | EC_Curve *c |
| 194 | CODE: |
| 195 | RETVAL = F_OUT(c->f, MP_NEW, c->a); |
| 196 | OUTPUT: |
| 197 | RETVAL |
| 198 | |
| 199 | Field * |
| 200 | field(c) |
| 201 | EC_Curve *c |
| 202 | CODE: |
| 203 | RETVAL = copy_field(c->f); |
| 204 | OUTPUT: |
| 205 | RETVAL |
| 206 | |
| 207 | SV * |
| 208 | get(c) |
| 209 | EC_Curve *c |
| 210 | CODE: |
| 211 | RETVAL = info_curve(c); |
| 212 | OUTPUT: |
| 213 | RETVAL |
| 214 | |
| 215 | bool |
| 216 | ec_samep(me, c) |
| 217 | EC_Curve *me |
| 218 | EC_Curve *c |
| 219 | |
| 220 | SV * |
| 221 | putraw(c, p) |
| 222 | EC_Curve *c |
| 223 | ec *p |
| 224 | PREINIT: |
| 225 | buf b; |
| 226 | size_t n = c->f->noctets * 2 + 1; |
| 227 | CODE: |
| 228 | RETVAL = NEWSV(0, n); |
| 229 | buf_init(&b, SvPVX(RETVAL), n); |
| 230 | if (ec_putraw(c, &b, p)) |
| 231 | croak("unexpected failure in Catacomb::EC::Curve::putraw"); |
| 232 | SvCUR_set(RETVAL, BLEN(&b)); |
| 233 | OUTPUT: |
| 234 | RETVAL |
| 235 | |
| 236 | void |
| 237 | _getraw(c, s) |
| 238 | EC_Curve *c |
| 239 | SV *s |
| 240 | PREINIT: |
| 241 | ec *p; |
| 242 | buf b; |
| 243 | char *q; |
| 244 | STRLEN n; |
| 245 | CODE: |
| 246 | q = SvPV(s, n); |
| 247 | buf_init(&b, q, n); |
| 248 | p = CREATE(ec); |
| 249 | EC_CREATE(p); |
| 250 | if (ec_getraw(c, &b, &p)) |
| 251 | DESTROY(p); |
| 252 | else { |
| 253 | XPUSHs(RET(p, "Catacomb::EC::Point")); |
| 254 | if (GIMME_V == G_ARRAY) |
| 255 | XPUSHs(sv_2mortal(newSVpvn((char *)BCUR(&b), BLEFT(&b)))); |
| 256 | } |
| 257 | |
| 258 | ec * |
| 259 | _find(c, x) |
| 260 | EC_Curve *c |
| 261 | fe *x |
| 262 | CODE: |
| 263 | RETVAL = CREATE(ec); |
| 264 | EC_CREATE(RETVAL); |
| 265 | if (!ec_find(c, RETVAL, x)) { |
| 266 | DESTROY(RETVAL); |
| 267 | RETVAL = 0; |
| 268 | } |
| 269 | OUTPUT: |
| 270 | RETVAL |
| 271 | |
| 272 | ec * |
| 273 | _rand(c, r = &rand_global) |
| 274 | EC_Curve *c |
| 275 | grand *r |
| 276 | CODE: |
| 277 | RETVAL = CREATE(ec); |
| 278 | EC_CREATE(RETVAL); |
| 279 | ec_rand(c, RETVAL, r); |
| 280 | OUTPUT: |
| 281 | RETVAL |
| 282 | |
| 283 | ec * |
| 284 | neg(c, p) |
| 285 | EC_Curve *c |
| 286 | ec *p |
| 287 | CODE: |
| 288 | RETVAL = CREATE(ec); |
| 289 | EC_CREATE(RETVAL); |
| 290 | ec_neg(c, RETVAL, p); |
| 291 | OUTPUT: |
| 292 | RETVAL |
| 293 | |
| 294 | ec * |
| 295 | add(c, p, q) |
| 296 | EC_Curve *c |
| 297 | ec *p |
| 298 | ec *q |
| 299 | CODE: |
| 300 | RETVAL = CREATE(ec); |
| 301 | EC_CREATE(RETVAL); |
| 302 | ec_add(c, RETVAL, p, q); |
| 303 | OUTPUT: |
| 304 | RETVAL |
| 305 | |
| 306 | ec * |
| 307 | sub(c, p, q) |
| 308 | EC_Curve *c |
| 309 | ec *p |
| 310 | ec *q |
| 311 | CODE: |
| 312 | RETVAL = CREATE(ec); |
| 313 | EC_CREATE(RETVAL); |
| 314 | ec_sub(c, RETVAL, p, q); |
| 315 | OUTPUT: |
| 316 | RETVAL |
| 317 | |
| 318 | ec * |
| 319 | dbl(c, p) |
| 320 | EC_Curve *c |
| 321 | ec *p |
| 322 | CODE: |
| 323 | RETVAL = CREATE(ec); |
| 324 | EC_CREATE(RETVAL); |
| 325 | ec_dbl(c, RETVAL, p); |
| 326 | OUTPUT: |
| 327 | RETVAL |
| 328 | |
| 329 | SV * |
| 330 | check(c, p) |
| 331 | EC_Curve *c |
| 332 | ec *p |
| 333 | CODE: |
| 334 | if (ec_check(c, p)) |
| 335 | XSRETURN_UNDEF; |
| 336 | XSRETURN_YES; |
| 337 | |
| 338 | ec * |
| 339 | mul(c, p, x) |
| 340 | EC_Curve *c |
| 341 | ec *p |
| 342 | mp *x |
| 343 | CODE: |
| 344 | RETVAL = CREATE(ec); |
| 345 | EC_CREATE(RETVAL); |
| 346 | ec_mul(c, RETVAL, p, x); |
| 347 | OUTPUT: |
| 348 | RETVAL |
| 349 | |
| 350 | ec * |
| 351 | in(c, p) |
| 352 | EC_Curve *c |
| 353 | ec *p |
| 354 | CODE: |
| 355 | RETVAL = CREATE(ec); |
| 356 | EC_CREATE(RETVAL); |
| 357 | EC_IN(c, RETVAL, p); |
| 358 | OUTPUT: |
| 359 | RETVAL |
| 360 | |
| 361 | ec * |
| 362 | out(c, p) |
| 363 | EC_Curve *c |
| 364 | ec *p |
| 365 | CODE: |
| 366 | RETVAL = CREATE(ec); |
| 367 | EC_CREATE(RETVAL); |
| 368 | EC_OUT(c, RETVAL, p); |
| 369 | OUTPUT: |
| 370 | RETVAL |
| 371 | |
| 372 | ec * |
| 373 | fix(c, p) |
| 374 | EC_Curve *c |
| 375 | ec *p |
| 376 | CODE: |
| 377 | RETVAL = CREATE(ec); |
| 378 | EC_CREATE(RETVAL); |
| 379 | EC_FIX(c, RETVAL, p); |
| 380 | OUTPUT: |
| 381 | RETVAL |
| 382 | |
| 383 | ec * |
| 384 | ifind(c, x) |
| 385 | EC_Curve *c |
| 386 | mp *x |
| 387 | CODE: |
| 388 | RETVAL = CREATE(ec); |
| 389 | if (!EC_FIND(c, RETVAL, x)) { |
| 390 | DESTROY(RETVAL); |
| 391 | RETVAL = 0; |
| 392 | } |
| 393 | OUTPUT: |
| 394 | RETVAL |
| 395 | |
| 396 | ec * |
| 397 | ineg(c, p) |
| 398 | EC_Curve *c |
| 399 | ec *p |
| 400 | CODE: |
| 401 | RETVAL = CREATE(ec); |
| 402 | EC_CREATE(RETVAL); |
| 403 | EC_NEG(c, RETVAL, p); |
| 404 | OUTPUT: |
| 405 | RETVAL |
| 406 | |
| 407 | ec * |
| 408 | iadd(c, p, q) |
| 409 | EC_Curve *c |
| 410 | ec *p |
| 411 | ec *q |
| 412 | CODE: |
| 413 | RETVAL = CREATE(ec); |
| 414 | EC_CREATE(RETVAL); |
| 415 | EC_ADD(c, RETVAL, p, q); |
| 416 | OUTPUT: |
| 417 | RETVAL |
| 418 | |
| 419 | ec * |
| 420 | isub(c, p, q) |
| 421 | EC_Curve *c |
| 422 | ec *p |
| 423 | ec *q |
| 424 | CODE: |
| 425 | RETVAL = CREATE(ec); |
| 426 | EC_CREATE(RETVAL); |
| 427 | EC_SUB(c, RETVAL, p, q); |
| 428 | OUTPUT: |
| 429 | RETVAL |
| 430 | |
| 431 | ec * |
| 432 | idbl(c, p) |
| 433 | EC_Curve *c |
| 434 | ec *p |
| 435 | CODE: |
| 436 | RETVAL = CREATE(ec); |
| 437 | EC_CREATE(RETVAL); |
| 438 | EC_DBL(c, RETVAL, p); |
| 439 | OUTPUT: |
| 440 | RETVAL |
| 441 | |
| 442 | bool |
| 443 | icheck(c, p) |
| 444 | EC_Curve *c |
| 445 | ec *p |
| 446 | CODE: |
| 447 | RETVAL = EC_CHECK(c, p); |
| 448 | OUTPUT: |
| 449 | RETVAL |
| 450 | |
| 451 | ec * |
| 452 | imul(c, p, x) |
| 453 | EC_Curve *c |
| 454 | ec *p |
| 455 | mp *x |
| 456 | CODE: |
| 457 | RETVAL = CREATE(ec); |
| 458 | EC_CREATE(RETVAL); |
| 459 | ec_imul(c, RETVAL, p, x); |
| 460 | OUTPUT: |
| 461 | RETVAL |
| 462 | |
| 463 | ec * |
| 464 | immul(c, ...) |
| 465 | EC_Curve *c |
| 466 | PREINIT: |
| 467 | ec_mulfactor *v; |
| 468 | size_t i, j, n; |
| 469 | CODE: |
| 470 | if (items < 3 || !(items & 1)) { |
| 471 | croak("Usage: Catacomb::EC::Curve::immul" |
| 472 | "(c, p_0, x_0, p_1, x_1, ..."); |
| 473 | } |
| 474 | n = (items - 1)/2; |
| 475 | v = xmalloc(n * sizeof(mp_expfactor)); |
| 476 | for (i = 1, j = 0; i < items; i += 2, j++) { |
| 477 | v[j].base = *ecpt(ST(i), "p_i"); |
| 478 | v[j].exp = mp_fromsv(ST(i + 1), "x_i", 0, 0); |
| 479 | } |
| 480 | RETVAL = CREATE(RETVAL); |
| 481 | EC_CREATE(RETVAL); |
| 482 | ec_mmul(c, RETVAL, v, n); |
| 483 | xfree(v); |
| 484 | OUTPUT: |
| 485 | RETVAL |
| 486 | |
| 487 | void |
| 488 | _getinfo(me, p) |
| 489 | SV *me |
| 490 | char *p |
| 491 | PREINIT: |
| 492 | ec_info i; |
| 493 | const char *e; |
| 494 | ec *pt; |
| 495 | PPCODE: |
| 496 | if ((e = ec_getinfo(&i, p)) != 0) |
| 497 | croak("bad curve spec: %s", e); |
| 498 | pt = CREATE(ec); |
| 499 | *pt = i.g; |
| 500 | XPUSHs(RET(i.c, "Catacomb::EC::Curve")); |
| 501 | XPUSHs(RET(pt, "Catacomb::EC::Point")); |
| 502 | XPUSHs(RET(i.r, "Catacomb::MP")); |
| 503 | XPUSHs(RET(i.h, "Catacomb::MP")); |
| 504 | |
| 505 | const char * |
| 506 | checkinfo(c, g, r, h, rng = &rand_global) |
| 507 | EC_Curve *c |
| 508 | ec *g |
| 509 | mp *r |
| 510 | mp *h |
| 511 | grand *rng |
| 512 | PREINIT: |
| 513 | ec_info ei; |
| 514 | CODE: |
| 515 | ei.c = c; |
| 516 | ei.g = *g; |
| 517 | ei.r = r; |
| 518 | ei.h = h; |
| 519 | RETVAL = ec_checkinfo(&ei, rng); |
| 520 | OUTPUT: |
| 521 | RETVAL |