/* return 0 if $a == b$ in $GF(3^m)$, 1 otherwise. */ static int gf3m_cmp(element_t a, element_t b) { unsigned long *pa = DATA1(a), *pb = DATA1(b); unsigned i; for (i = 0; i < LEN(a) * 2; i++, pa++, pb++) if (*pa != *pb) return 1; return 0; }
static int gf3m_is1(element_t e) { unsigned i; if (DATA1(e)[0] != 1) return 0; for (i = 1; i < LEN(e) * 2; i++) if (DATA1(e)[i]) return 0; return 1; }
/* doing multiplication of $n \in \{0,1,2\}$ and $a$ in $GF(3^m)$ * The function sets $e <- n * a$. */ static void gf3m_f1(element_t e, unsigned n, element_t a) { /* assert $e$ is not $a$ */ if (n == 0) memset(DATA1(e), 0, SIZE(e)); else if (n == 1) memcpy(DATA1(e), DATA1(a), SIZE(e)); else { memcpy(DATA1(e), DATA2(a), SIZE(e) / 2); memcpy(DATA2(e), DATA1(a), SIZE(e) / 2); } }
/* $e <- x-y$ */ static void gf3m_sub(element_t e, element_t a, element_t b) { unsigned long *e1 = DATA1(e), *e2 = DATA2(e), *a1 = DATA1(a), *a2 = DATA2(a), *b1 = DATA2(b), *b2 = DATA1(b); unsigned i; for (i = 0; i < LEN(e); i++, e1++, e2++, a1++, a2++, b1++, b2++) { unsigned long t = (*a1 | *a2) & (*b1 | *b2), c1 = t ^ (*a1 | *b1), c2 = t ^ (*a2 | *b2); *e1 = c1; *e2 = c2; } }
/* $y <- (-x)$ */ static void gf3m_neg(element_t y, element_t x) { unsigned long *a1 = DATA1(x), *a2 = DATA2(x), *c1 = DATA1(y), *c2 = DATA2(y); if (a1 == c1) { unsigned i; for (i = 0; i < LEN(y); i++, a1++, a2++) swap(a1, a2); } else { memcpy(c1, a2, SIZE(y) / 2); memcpy(c2, a1, SIZE(y) / 2); } }
static int gf3m_is0(element_t e) { unsigned i; for (i = 0; i < LEN(e) * 2; i++) if (DATA1(e)[i]) return 0; return 1; }
/* set the coefficient of $x^pos$ as 1 */ static void gf3m_set(element_t e, unsigned pos, unsigned value) { unsigned long *a = DATA1(e); /* assert value == 0, 1 or 2 */ if (value == 2) a = DATA2(e); if (value) a[pos / W] |= 1ul << (pos % W); }
int gf3m_to_bytes(unsigned char *d, element_ptr e) { unsigned long *a = DATA1(e), *b = DATA2(e); unsigned long i, j; for (i = 0; i < LEN(e); i++, a++, b++) { for (j = 0; j < sizeof(unsigned long) * 8; j += 8) { *(d++) = (unsigned char) ((*a) >> j); *(d++) = (unsigned char) ((*b) >> j); } } return SIZE(e); }
/* $e <- x^3$ */ static void gf3m_cubic(element_t e, element_t x) { /* TODO: faster algorithm */ params *p = PARAM(x); unsigned old = p->len; unsigned len = (3 * p->m - 2 + W - 1) / W; /* length of $b1 */ p->len = len; element_t a; element_init(a, x->field); unsigned i; for (i = 0; i < p->m; i++) { p->len = old; unsigned v = gf3m_get(x, i); p->len = len; gf3m_set(a, 3 * i, v); } gf3m_reduct(a, len, 3 * p->m - 3); p->len = old; memcpy(DATA1(e), DATA1(a), SIZE(e) / 2); memcpy(DATA2(e), DATA1(a) + len, SIZE(e) / 2); element_clear(a); }
static size_t gf3m_out_str(FILE *stream, int base, element_t e) { if (base != 10 && base != 16) pbc_die("only support base 10 and base 16"); size_t size = 0; unsigned i; unsigned long *d = DATA1(e); for (i = 0; i < LEN(e) * 2; i++) { if (base == 16) size += fprintf(stream, "0x%lx,", d[i]); else size += fprintf(stream, "%lu,", d[i]); } return size; }
int gf3m_from_bytes(element_ptr e, unsigned char *d) { unsigned long *a = DATA1(e), *b = DATA2(e); unsigned i; int j; for (i = 0; i < LEN(e); i++, a++, b++, d += sizeof(unsigned long) * 2) { *a = 0, *b = 0; j = 2 * sizeof(unsigned long) - 2; while (j >= 0) { *a <<= 8, *b <<= 8; *a += d[j]; *b += d[j + 1]; j -= 2; } } return SIZE(e); }
/* set $a$ to be a random element in $GF(3^m)$ */ static void gf3m_random(element_t a) { /* TODO: use uniform distribution? */ params *c = PARAM(a); unsigned rm = c->m % W; const unsigned long i1 = ~0ul; unsigned long i2 = (1ul << rm) - 1; unsigned long *a1 = DATA1(a), *a2 = DATA2(a); unsigned i; for (i = 0; i < c->len - 1; i++, a1++, a2++) { /* TODO: if $RAND_MAX < i1$ ? */ *a1 = rand() & i1; *a2 = rand() & i1 & ~(*a1); /* assuring there is no bit that a1[x] & a2[x] == 1 */ } unsigned long x = rm ? i2 : i1; *a1 = rand() & x; *a2 = rand() & x & ~(*a1); }
/* setopt wrapper for curl_slist options */ CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config, const char *name, CURLoption tag, struct curl_slist *list) { CURLcode ret = CURLE_OK; char *escaped = NULL; bool skip = FALSE; ret = curl_easy_setopt(curl, tag, list); if(!list) skip = TRUE; if(config->libcurl && !skip && !ret) { struct curl_slist *s; int i; /* May need several slist variables, so invent name */ i = ++ easysrc_slist_count; DECL1("struct curl_slist *slist%d;", i); DATA1("slist%d = NULL;", i); CLEAN1("curl_slist_free_all(slist%d);", i); CLEAN1("slist%d = NULL;", i); for(s=list; s; s=s->next) { Curl_safefree(escaped); escaped = c_escape(s->data); if(!escaped) { ret = CURLE_OUT_OF_MEMORY; goto nomem; } DATA3("slist%d = curl_slist_append(slist%d, \"%s\");", i, i, escaped); } CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i); } nomem: Curl_safefree(escaped); return ret; }
/* $e <- e*x$ */ static void gf3m_shift_up(element_t e) { shift_up(LEN(e), DATA1(e)); shift_up(LEN(e), DATA2(e)); }
/* setopt wrapper for CURLOPT_HTTPPOST */ CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config, const char *name, CURLoption tag, struct curl_httppost *post) { CURLcode ret = CURLE_OK; char *escaped = NULL; bool skip = FALSE; ret = curl_easy_setopt(curl, tag, post); if(!post) skip = TRUE; if(config->libcurl && !skip && !ret) { struct curl_httppost *pp, *p; int i; /* May use several httppost lists, if multiple POST actions */ i = ++ easysrc_form_count; DECL1("struct curl_httppost *post%d;", i); DATA1("post%d = NULL;", i); CLEAN1("curl_formfree(post%d);", i); CLEAN1("post%d = NULL;", i); if(i == 1) DECL0("struct curl_httppost *postend;"); DATA0("postend = NULL;"); for(p=post; p; p=p->next) { DATA1("curl_formadd(&post%d, &postend,", i); DATA1(" CURLFORM_COPYNAME, \"%s\",", p->name); for(pp=p; pp; pp=pp->more) { /* May be several files uploaded for one name; * these are linked through the 'more' pointer */ Curl_safefree(escaped); escaped = c_escape(pp->contents); if(!escaped) { ret = CURLE_OUT_OF_MEMORY; goto nomem; } if(pp->flags & CURL_HTTPPOST_FILENAME) { /* file upload as for -F @filename */ DATA1(" CURLFORM_FILE, \"%s\",", escaped); } else if(pp->flags & CURL_HTTPPOST_READFILE) { /* content from file as for -F <filename */ DATA1(" CURLFORM_FILECONTENT, \"%s\",", escaped); } else DATA1(" CURLFORM_COPYCONTENTS, \"%s\",", escaped); if(pp->showfilename) { Curl_safefree(escaped); escaped = c_escape(pp->showfilename); if(!escaped) { ret = CURLE_OUT_OF_MEMORY; goto nomem; } DATA1(" CURLFORM_FILENAME, \"%s\",", escaped); } if(pp->contenttype) { Curl_safefree(escaped); escaped = c_escape(pp->contenttype); if(!escaped) { ret = CURLE_OUT_OF_MEMORY; goto nomem; } DATA1(" CURLFORM_CONTENTTYPE, \"%s\",", escaped); } } DATA0(" CURLFORM_END);"); } CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i); } nomem: Curl_safefree(escaped); return ret; }
/* $a <- 1$ */ static void gf3m_one(element_t a) { gf3m_zero(a); *DATA1(a) = 1; }
/* return the coefficient of $x^pos$ in $e$ */ static unsigned gf3m_get(element_t e, unsigned pos) { unsigned long *a1 = DATA1(e), *a2 = DATA2(e); unsigned x = pos / W; unsigned long y = 1ul << (pos % W), v1 = a1[x] & y, v2 = a2[x] & y; return v1 ? 1 : (v2 ? 2 : 0); }
static void gf3m_swap(element_t a, element_t b) { unsigned long *p = DATA1(a); a->data = b->data; b->data = p; }
/* computing the inversion of an element $a$ in GF(3^m), i.e., $e <- a^{-1}$ The algorithm is by Tim Kerins, Emanuel Popovici and William Marnane in the paper of "Algorithms and Architectures for use in FPGA", Lecture Notes in Computer Science, 2004, Volume 3203/2004, 74-83. Note that $U$ must have an extra bit, i.e, (_m + W - 1) // W == (_m + W) // W */ static void gf3m_invert(element_t e, element_t a) { struct field_s *f = a->field; params *p = PARAM(a); unsigned lenA = p->len; unsigned lenS = (3 * p->m + W - 1) / W; p->len = lenS; element_t S, R, t, U, V, t2; element_init(S, f); element_init(R, f); element_init(t, f); memcpy(DATA1(S), DATA1(p->p), lenA * sizeof(unsigned long)); /* S = p(x) */ memcpy(DATA1(S) + lenS, DATA1(p->p) + lenA, lenA * sizeof(unsigned long)); memcpy(DATA1(R), DATA1(a), lenA * sizeof(unsigned long)); /* R = _clone(a) */ memcpy(DATA1(R) + lenS, DATA1(a) + lenA, lenA * sizeof(unsigned long)); p->len = lenA; element_init(U, f); gf3m_one(U); element_init(V, f); element_init(t2, f); unsigned d = 0, i, r_m, s_m, q, x; for (i = 0; i < p->m * 2; i++) { p->len = lenS; r_m = gf3m_get(R, p->m), s_m = gf3m_get(S, p->m); if (r_m == 0) { gf3m_shift_up(R); /* R = xR */ p->len = lenA; gf3m_f2(U); /* U = xU mod p */ d++; } else { q = gf3_mult(r_m, s_m); gf3m_f1(t, q, R); gf3m_sub(S, S, t); /* S = S-qR */ gf3m_shift_up(S); /* S = xS */ p->len = lenA; gf3m_f1(t2, q, U); gf3m_sub(V, V, t2); /* V = V-qU */ if (d == 0) { gf3m_swap(S, R); gf3m_swap(U, V); gf3m_f2(U); /* U = xU mod p*/ d++; } else { x = gf3m_get(U, 0); if (x == 1) /* assuring x|U */ gf3m_add(U, U, p->p); else if (x == 2) gf3m_sub(U, U, p->p); gf3m_shift_down(U); /* divide U by $x$ */ d--; } } } p->len = lenS; r_m = gf3m_get(R, p->m); /* assume r_m is not zero */ p->len = lenA; if (r_m == 2) gf3m_neg(U, U); memcpy(e->data, U->data, lenA * 2 * sizeof(unsigned long)); element_clear(S); element_clear(R); element_clear(U); element_clear(V); element_clear(t); element_clear(t2); }