| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877 |
- #include "sec_osal_light.h"
- #include "sec_osal.h"
- #include "sec_cust_struct.h"
- #include "bgn_internal.h"
- #define MOD "BGN"
- /**************************************************************************
- * FUNCTIONS
- **************************************************************************/
- int bgn_grow(bgn *P_X, int nbl)
- {
- ulong *p;
- if (P_X->n < nbl) {
- p = (ulong *) osal_kmalloc(nbl * ciL);
- if (p == NULL)
- return 1;
- memset(p, 0, nbl * ciL);
- if (P_X->p != NULL) {
- memcpy(p, P_X->p, P_X->n * ciL);
- memset(P_X->p, 0, P_X->n * ciL);
- osal_kfree(P_X->p);
- }
- P_X->n = nbl;
- P_X->p = p;
- }
- return 0;
- }
- int bgn_copy(bgn *P_X, const bgn *Y)
- {
- int ret, i;
- if (P_X == Y)
- return 0;
- for (i = Y->n - 1; i > 0; i--)
- if (Y->p[i] != 0)
- break;
- i++;
- P_X->s = Y->s;
- ret = bgn_grow(P_X, i);
- if (0 != ret)
- goto _exit;
- memset(P_X->p, 0, P_X->n * ciL);
- memcpy(P_X->p, Y->p, i * ciL);
- _exit:
- return ret;
- }
- void bgn_swap(bgn *P_X, bgn *Y)
- {
- bgn T;
- memcpy(&T, P_X, sizeof(bgn));
- memcpy(P_X, Y, sizeof(bgn));
- memcpy(Y, &T, sizeof(bgn));
- }
- int bgn_lset(bgn *P_X, int z)
- {
- int ret;
- ret = bgn_grow(P_X, 1);
- if (0 != ret)
- goto _exit;
- memset(P_X->p, 0, P_X->n * ciL);
- P_X->p[0] = (z < 0) ? -z : z;
- P_X->s = (z < 0) ? -1 : 1;
- _exit:
- return ret;
- }
- int bgn_lsb(const bgn *P_X)
- {
- int i, j, count = 0;
- for (i = 0; i < P_X->n; i++)
- for (j = 0; j < (int)biL; j++, count++)
- if (((P_X->p[i] >> j) & 1) != 0)
- return count;
- return 0;
- }
- int bgn_msb(const bgn *P_X)
- {
- int i, j;
- for (i = P_X->n - 1; i > 0; i--)
- if (P_X->p[i] != 0)
- break;
- for (j = biL - 1; j >= 0; j--)
- if (((P_X->p[i] >> j) & 1) != 0)
- break;
- return (i * biL) + j + 1;
- }
- int bgn_size(const bgn *P_X)
- {
- return (bgn_msb(P_X) + 7) >> 3;
- }
- int bgn_shift_l(bgn *P_X, int count)
- {
- int ret, i, v0, t1;
- ulong r0 = 0, r1;
- v0 = count / (biL);
- t1 = count & (biL - 1);
- i = bgn_msb(P_X) + count;
- if (P_X->n * (int)biL < i) {
- ret = bgn_grow(P_X, B_T_L(i));
- if (0 != ret)
- goto _exit;
- }
- ret = 0;
- if (v0 > 0) {
- for (i = P_X->n - 1; i >= v0; i--)
- P_X->p[i] = P_X->p[i - v0];
- for (; i >= 0; i--)
- P_X->p[i] = 0;
- }
- if (t1 > 0) {
- for (i = v0; i < P_X->n; i++) {
- r1 = P_X->p[i] >> (biL - t1);
- P_X->p[i] <<= t1;
- P_X->p[i] |= r0;
- r0 = r1;
- }
- }
- _exit:
- return ret;
- }
- int bgn_shift_r(bgn *P_X, int count)
- {
- int i, v0, v1;
- ulong r0 = 0, r1;
- v0 = count / biL;
- v1 = count & (biL - 1);
- if (v0 > 0) {
- for (i = 0; i < P_X->n - v0; i++)
- P_X->p[i] = P_X->p[i + v0];
- for (; i < P_X->n; i++)
- P_X->p[i] = 0;
- }
- if (v1 > 0) {
- for (i = P_X->n - 1; i >= 0; i--) {
- r1 = P_X->p[i] << (biL - v1);
- P_X->p[i] >>= v1;
- P_X->p[i] |= r0;
- r0 = r1;
- }
- }
- return 0;
- }
- int bgn_cmp_abs(const bgn *P_X, const bgn *Y)
- {
- int i, j;
- for (i = P_X->n - 1; i >= 0; i--) {
- if (P_X->p[i] != 0)
- break;
- }
- for (j = Y->n - 1; j >= 0; j--) {
- if (Y->p[j] != 0)
- break;
- }
- if (i < 0 && j < 0)
- return 0;
- if (i > j)
- return 1;
- if (j > i)
- return -1;
- for (; i >= 0; i--) {
- if (P_X->p[i] > Y->p[i])
- return 1;
- if (P_X->p[i] < Y->p[i])
- return -1;
- }
- return 0;
- }
- int bgn_cmp_num(const bgn *P_X, const bgn *Y)
- {
- int i, j;
- for (i = P_X->n - 1; i >= 0; i--) {
- if (P_X->p[i] != 0)
- break;
- }
- for (j = Y->n - 1; j >= 0; j--) {
- if (Y->p[j] != 0)
- break;
- }
- if (i < 0 && j < 0)
- return 0;
- if (i > j)
- return P_X->s;
- if (j > i)
- return -P_X->s;
- if (P_X->s > 0 && Y->s < 0)
- return 1;
- if (Y->s > 0 && P_X->s < 0)
- return -1;
- for (; i >= 0; i--) {
- if (P_X->p[i] > Y->p[i])
- return P_X->s;
- if (P_X->p[i] < Y->p[i])
- return -P_X->s;
- }
- return 0;
- }
- int bgn_cmp_int(const bgn *P_X, int z)
- {
- bgn Y;
- ulong p[1];
- *p = (z < 0) ? -z : z;
- Y.s = (z < 0) ? -1 : 1;
- Y.n = 1;
- Y.p = p;
- return bgn_cmp_num(P_X, &Y);
- }
- int bgn_add_abs(bgn *P_X, const bgn *P_A, const bgn *P_B)
- {
- int ret, i, j;
- ulong *o, *p, c;
- if (P_X == P_B) {
- const bgn *T = P_A;
- P_A = P_X;
- P_B = T;
- }
- if (P_X != P_A) {
- ret = bgn_copy(P_X, P_A);
- if (0 != ret)
- goto _exit;
- }
- P_X->s = 1;
- for (j = P_B->n - 1; j >= 0; j--) {
- if (P_B->p[j] != 0)
- break;
- }
- ret = bgn_grow(P_X, j + 1);
- if (0 != ret)
- goto _exit;
- o = P_B->p;
- p = P_X->p;
- c = 0;
- for (i = 0; i <= j; i++, o++, p++) {
- *p += c;
- c = (*p < c);
- *p += *o;
- c += (*p < *o);
- }
- while (c != 0) {
- if (i >= P_X->n) {
- ret = bgn_grow(P_X, i + 1);
- if (0 != ret)
- goto _exit;
- p = P_X->p + i;
- }
- *p += c;
- c = (*p < c);
- i++;
- }
- _exit:
- return ret;
- }
- void bgn_sub_hlp(int n, ulong *s, ulong *d)
- {
- int i;
- ulong c, z;
- for (i = c = 0; i < n; i++, s++, d++) {
- z = (*d < c);
- *d -= c;
- c = (*d < *s) + z;
- *d -= *s;
- }
- while (c != 0) {
- z = (*d < c);
- *d -= c;
- c = z;
- i++;
- d++;
- }
- }
- int bgn_sub_abs(bgn *P_X, const bgn *P_A, const bgn *P_B)
- {
- bgn TB;
- int ret, n;
- if (bgn_cmp_abs(P_A, P_B) < 0)
- return E_BGN_NEGATIVE_VALUE;
- bgn_init(&TB);
- if (P_X == P_B) {
- ret = bgn_copy(&TB, P_B);
- if (0 != ret)
- goto _exit;
- P_B = &TB;
- }
- if (P_X != P_A) {
- ret = bgn_copy(P_X, P_A);
- if (0 != ret)
- goto _exit;
- }
- P_X->s = 1;
- ret = 0;
- for (n = P_B->n - 1; n >= 0; n--) {
- if (P_B->p[n] != 0)
- break;
- }
- bgn_sub_hlp(n + 1, P_B->p, P_X->p);
- _exit:
- bgn_free(&TB);
- return ret;
- }
- int bgn_add_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
- {
- int ret, s = P_A->s;
- if (P_A->s * P_B->s < 0) {
- if (bgn_cmp_abs(P_A, P_B) >= 0) {
- ret = bgn_sub_abs(P_X, P_A, P_B);
- if (0 != ret)
- goto _exit;
- P_X->s = s;
- } else {
- ret = bgn_sub_abs(P_X, P_B, P_A);
- if (0 != ret)
- goto _exit;
- P_X->s = -s;
- }
- } else {
- ret = bgn_add_abs(P_X, P_A, P_B);
- if (0 != ret)
- goto _exit;
- P_X->s = s;
- }
- _exit:
- return ret;
- }
- int bgn_sub_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
- {
- int ret, s = P_A->s;
- if (P_A->s * P_B->s > 0) {
- if (bgn_cmp_abs(P_A, P_B) >= 0) {
- ret = bgn_sub_abs(P_X, P_A, P_B);
- if (0 != ret)
- goto _exit;
- P_X->s = s;
- } else {
- ret = bgn_sub_abs(P_X, P_B, P_A);
- if (0 != ret)
- goto _exit;
- P_X->s = -s;
- }
- } else {
- ret = bgn_add_abs(P_X, P_A, P_B);
- if (0 != ret)
- goto _exit;
- P_X->s = s;
- }
- _exit:
- return ret;
- }
- int bgn_add_int(bgn *P_X, const bgn *P_A, int b)
- {
- bgn _B;
- ulong p[1];
- p[0] = (b < 0) ? -b : b;
- _B.s = (b < 0) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
- return bgn_add_bgn(P_X, P_A, &_B);
- }
- int bgn_sub_int(bgn *P_X, const bgn *P_A, int b)
- {
- bgn _B;
- ulong p[1];
- p[0] = (b < 0) ? -b : b;
- _B.s = (b < 0) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
- return bgn_sub_bgn(P_X, P_A, &_B);
- }
- void bgn_alu(ulong **s, ulong **d, ulong b, ulong c, unsigned int loop_count)
- {
- unsigned int i;
- unsigned long s_0, s_1, b_0, b_1;
- unsigned long r_0, r_1, r_x, r_y;
- b_0 = (b << biH) >> biH;
- b_1 = (b >> biH);
- for (i = 0; i < loop_count; i++) {
- s_0 = (**s << biH) >> biH;
- s_1 = (**s >> biH); (*s)++;
- r_x = s_0 * b_1; r_0 = s_0 * b_0;
- r_y = s_1 * b_0; r_1 = s_1 * b_1;
- r_1 += (r_x >> biH);
- r_1 += (r_y >> biH);
- r_x <<= biH; r_y <<= biH;
- r_0 += r_x; r_1 += (r_0 < r_x);
- r_0 += r_y; r_1 += (r_0 < r_y);
- r_0 += c; r_1 += (r_0 < c);
- r_0 += (unsigned long)*d;
- r_1 += (r_0 < (unsigned long) *d);
- c = r_1; *((*d)++) = r_0;
- }
- }
- void bgn_mul_hlp(int i, ulong *s, ulong *d, ulong b)
- {
- ulong c = 0, t = 0;
- for (; i >= 16; i -= 16)
- bgn_alu(&s, &d, b, c, 16);
- for (; i >= 8; i -= 8)
- bgn_alu(&s, &d, b, c, 8);
- for (; i > 0; i--)
- bgn_alu(&s, &d, b, c, 1);
- t++;
- do {
- *d += c;
- c = (*d < c);
- d++;
- } while (c != 0);
- }
- int bgn_mul_bgn(bgn *P_X, const bgn *P_A, const bgn *P_B)
- {
- int ret, i, j;
- bgn TA, TB;
- bgn_init(&TA);
- bgn_init(&TB);
- if (P_X == P_A) {
- ret = bgn_copy(&TA, P_A);
- if (0 != ret)
- goto _exit;
- P_A = &TA;
- }
- if (P_X == P_B) {
- ret = bgn_copy(&TB, P_B);
- if (0 != ret)
- goto _exit;
- P_B = &TB;
- }
- for (i = P_A->n - 1; i >= 0; i--) {
- if (P_A->p[i] != 0)
- break;
- }
- for (j = P_B->n - 1; j >= 0; j--) {
- if (P_B->p[j] != 0)
- break;
- }
- ret = bgn_grow(P_X, i + j + 2);
- if (0 != ret)
- goto _exit;
- ret = bgn_lset(P_X, 0);
- if (0 != ret)
- goto _exit;
- for (i++; j >= 0; j--)
- bgn_mul_hlp(i, P_A->p, P_X->p + j, P_B->p[j]);
- P_X->s = P_A->s * P_B->s;
- _exit:
- bgn_free(&TB);
- bgn_free(&TA);
- return ret;
- }
- int bgn_mul_int(bgn *P_X, const bgn *P_A, ulong b)
- {
- bgn _B;
- ulong p[1];
- _B.s = 1;
- _B.n = 1;
- _B.p = p;
- p[0] = b;
- return bgn_mul_bgn(P_X, P_A, &_B);
- }
- int bgn_div_bgn(bgn *P_Q, bgn *P_R, const bgn *P_A, const bgn *P_B)
- {
- int ret, i, n, t, k;
- bgn X, Y, Z, T1, T2;
- if (bgn_cmp_int(P_B, 0) == 0)
- return E_BGN_DIVISION_BY_ZERO;
- bgn_init(&X);
- bgn_init(&Y);
- bgn_init(&Z);
- bgn_init(&T1);
- bgn_init(&T2);
- if (bgn_cmp_abs(P_A, P_B) < 0) {
- if (P_Q != NULL) {
- ret = bgn_lset(P_Q, 0);
- if (0 != ret)
- goto _exit;
- }
- if (P_R != NULL) {
- ret = bgn_copy(P_R, P_A);
- if (0 != ret)
- goto _exit;
- }
- return 0;
- }
- ret = bgn_copy(&X, P_A);
- if (0 != ret)
- goto _exit;
- ret = bgn_copy(&Y, P_B);
- if (0 != ret)
- goto _exit;
- X.s = Y.s = 1;
- ret = bgn_grow(&Z, P_A->n + 2);
- if (0 != ret)
- goto _exit;
- ret = bgn_lset(&Z, 0);
- if (0 != ret)
- goto _exit;
- ret = bgn_grow(&T1, 2);
- if (0 != ret)
- goto _exit;
- ret = bgn_grow(&T2, 3);
- if (0 != ret)
- goto _exit;
- k = bgn_msb(&Y) % biL;
- if (k < (int)biL - 1) {
- k = biL - 1 - k;
- ret = bgn_shift_l(&X, k);
- if (0 != ret)
- goto _exit;
- ret = bgn_shift_l(&Y, k);
- if (0 != ret)
- goto _exit;
- } else {
- k = 0;
- }
- n = X.n - 1;
- t = Y.n - 1;
- bgn_shift_l(&Y, biL * (n - t));
- while (bgn_cmp_num(&X, &Y) >= 0) {
- Z.p[n - t]++;
- bgn_sub_bgn(&X, &X, &Y);
- }
- bgn_shift_r(&Y, biL * (n - t));
- for (i = n; i > t; i--) {
- if (X.p[i] >= Y.p[t]) {
- Z.p[i - t - 1] = ~0;
- } else {
- ulong q0, q1, r0, r1;
- ulong d0, d1, d, m;
- d = Y.p[t];
- d0 = (d << biH) >> biH;
- d1 = (d >> biH);
- q1 = X.p[i] / d1;
- r1 = X.p[i] - d1 * q1;
- r1 <<= biH;
- r1 |= (X.p[i - 1] >> biH);
- m = q1 * d0;
- if (r1 < m) {
- q1--, r1 += d;
- while (r1 >= d && r1 < m)
- q1--, r1 += d;
- }
- r1 -= m;
- q0 = r1 / d1;
- r0 = r1 - d1 * q0;
- r0 <<= biH;
- r0 |= (X.p[i - 1] << biH) >> biH;
- m = q0 * d0;
- if (r0 < m) {
- q0--, r0 += d;
- while (r0 >= d && r0 < m)
- q0--, r0 += d;
- }
- r0 -= m;
- Z.p[i - t - 1] = (q1 << biH) | q0;
- }
- Z.p[i - t - 1]++;
- do {
- Z.p[i - t - 1]--;
- ret = bgn_lset(&T1, 0);
- if (0 != ret)
- goto _exit;
- T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
- T1.p[1] = Y.p[t];
- ret = bgn_mul_int(&T1, &T1, Z.p[i - t - 1]);
- if (0 != ret)
- goto _exit;
- ret = bgn_lset(&T2, 0);
- if (0 != ret)
- goto _exit;
- T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
- T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
- T2.p[2] = X.p[i];
- } while (bgn_cmp_num(&T1, &T2) > 0);
- ret = bgn_mul_int(&T1, &Y, Z.p[i - t - 1]);
- if (0 != ret)
- goto _exit;
- ret = bgn_shift_l(&T1, biL * (i - t - 1));
- if (0 != ret)
- goto _exit;
- ret = bgn_sub_bgn(&X, &X, &T1);
- if (0 != ret)
- goto _exit;
- if (bgn_cmp_int(&X, 0) < 0) {
- ret = bgn_copy(&T1, &Y);
- if (0 != ret)
- goto _exit;
- ret = bgn_shift_l(&T1, biL * (i - t - 1));
- if (0 != ret)
- goto _exit;
- ret = bgn_add_bgn(&X, &X, &T1);
- if (0 != ret)
- goto _exit;
- Z.p[i - t - 1]--;
- }
- }
- if (P_Q != NULL) {
- bgn_copy(P_Q, &Z);
- P_Q->s = P_A->s * P_B->s;
- }
- if (P_R != NULL) {
- bgn_shift_r(&X, k);
- bgn_copy(P_R, &X);
- P_R->s = P_A->s;
- if (bgn_cmp_int(P_R, 0) == 0)
- P_R->s = 1;
- }
- _exit:
- bgn_free(&X);
- bgn_free(&Y);
- bgn_free(&Z);
- bgn_free(&T1);
- bgn_free(&T2);
- return ret;
- }
- int bgn_div_int(bgn *P_Q, bgn *P_R, const bgn *P_A, int b)
- {
- bgn _B;
- ulong p[1];
- p[0] = (b < 0) ? -b : b;
- _B.s = (b < 0) ? -1 : 1;
- _B.n = 1;
- _B.p = p;
- return bgn_div_bgn(P_Q, P_R, P_A, &_B);
- }
- int bgn_mod_bgn(bgn *P_R, const bgn *P_A, const bgn *P_B)
- {
- int ret;
- if (bgn_cmp_int(P_B, 0) < 0)
- return E_BGN_NEGATIVE_VALUE;
- ret = bgn_div_bgn(NULL, P_R, P_A, P_B);
- if (0 != ret)
- goto _exit;
- while (bgn_cmp_int(P_R, 0) < 0) {
- ret = bgn_add_bgn(P_R, P_R, P_B);
- if (0 != ret)
- goto _exit;
- }
- while (bgn_cmp_num(P_R, P_B) >= 0) {
- ret = bgn_sub_bgn(P_R, P_R, P_B);
- if (0 != ret)
- goto _exit;
- }
- _exit:
- return ret;
- }
- int bgn_mod_int(ulong *r, const bgn *P_A, int b)
- {
- int i;
- ulong x, y, z;
- if (b == 0)
- return E_BGN_DIVISION_BY_ZERO;
- if (b < 0)
- return E_BGN_NEGATIVE_VALUE;
- if (b == 1) {
- *r = 0;
- return 0;
- }
- if (b == 2) {
- *r = P_A->p[0] & 1;
- return 0;
- }
- for (i = P_A->n - 1, y = 0; i >= 0; i--) {
- x = P_A->p[i];
- y = (y << biH) | (x >> biH);
- z = y / b;
- y -= z * b;
- x <<= biH;
- y = (y << biH) | (x >> biH);
- z = y / b;
- y -= z * b;
- }
- if (P_A->s < 0 && y != 0)
- y = b - y;
- *r = y;
- return 0;
- }
|