void aes_gcm_init(aes_gcm *gcm, aes_key *key, uint8_t *iv, uint32_t len) { gcm->length_aad = 0; gcm->length_input = 0; block128_zero(&gcm->h); block128_zero(&gcm->tag); block128_zero(&gcm->iv); memcpy(&gcm->key, key, sizeof(aes_key)); /* prepare H : encrypt_K(0^128) */ aes_encrypt_block(&gcm->h, key, &gcm->h); if (len == 12) { block128_copy_bytes(&gcm->iv, iv, 12); gcm->iv.b[15] = 0x01; } else { uint32_t origlen = len << 3; int i; for (; len >= 16; len -= 16, iv += 16) { block128_xor(&gcm->iv, (block128 *) iv); gf_mul(&gcm->iv, &gcm->h); } if (len > 0) { block128_xor_bytes(&gcm->iv, iv, len); gf_mul(&gcm->iv, &gcm->h); } for (i = 15; origlen; --i, origlen >>= 8) gcm->iv.b[i] ^= (uint8_t) origlen; gf_mul(&gcm->iv, &gcm->h); } block128_copy(&gcm->civ, &gcm->iv); }
int main() { /* uint8_t a, b; printf("Gimme the A vector: "); a = g6_input(); scanf("\n"); printf("Gimme the B vector: "); scanf("\n"); b = g6_input(); printf("\nA + B: "); g6_print(gf_add(a, b)); printf("\nA * B: "); g6_print(gf_mul(a, b, 6, 0x1b)); printf("\n"); */ assert(gf_mul(0x00, 0x00, 6, g6poly) == 0x00); assert(gf_mul(0x01, 0x01, 6, g6poly) == 0x01); assert(gf_mul(0x1b, 0x01, 6, g6poly) == 0x1b); assert(gf_mul(0x1b, 0x0b, 6, g6poly) == 0x18); assert(gf_rotate(0x01, -1, 6) == 0x02); assert(gf_rotate(0x02, 1, 6) == 0x01); assert(gf_rotate(0x10, -1, 6) == 0x20); assert(gf_rotate(0x01, 1, 6) == 0x20); assert(gf_rotate(0x01, 6, 6) == 0x01); assert(gf_rotate(0x3f, 2, 6) == 0x3f); assert(gf_rotate(0x4, 2, 4) == 0x1); assert(gf_rotate(0x8, 3, 4) == 0x1); return 0; }
poly_t * poly_syndrome_init(poly_t generator, gf_t *support, int n) { int i,j,t; gf_t a; poly_t * F; F = malloc(n * sizeof (poly_t)); t = poly_deg(generator); //g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0 //f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0 for(j=0; j<n; j++) { F[j] = poly_alloc(t-1); poly_set_coeff(F[j],t-1,gf_unit()); for(i=t-2; i>=0; i--) { poly_set_coeff(F[j],i,gf_add(poly_coeff(generator,i+1), gf_mul(support[j],poly_coeff(F[j],i+1)))); } a = gf_add(poly_coeff(generator,0),gf_mul(support[j],poly_coeff(F[j],0))); for(i=0; i<t; i++) { poly_set_coeff(F[j],i, gf_div(poly_coeff(F[j],i),a)); } } return F; }
static void rs_calc_sigma(poly_t *dst, const poly_t *synd) { int L = 0; poly_t T = { .degree = 1, .terms[0] = 1 }; poly_t tmp; dst->degree = 1; dst->terms[0] = 1; for (int k = 0; k < synd->degree; k++) { uint8_t delta; // T(x) = T(x) * x cgc_memmove(&T.terms[1], &T.terms[0], T.degree++); T.terms[0] = 0; delta = synd->terms[synd->degree - 1 - k]; for (int i = 1; i < dst->degree; i++) delta ^= gf_mul(dst->terms[i], synd->terms[synd->degree - 1 - (k - i)]); if (delta != 0) { gf_poly_mul_const(&tmp, &T, delta); if (L <= k) { L = k; gf_poly_mul_const(&T, dst, gf_inverse(delta)); } gf_poly_add(dst, dst, &tmp); } } gf_poly_reduce(dst); } static void rs_calc_pos(poly_t *dst, const poly_t *sigma) { poly_t tmp; dst->degree = 0; tmp.degree = sigma->degree; // terms[0] is constant for (int k = 1; k < sigma->degree; k++) tmp.terms[k] = gf_mul(sigma->terms[k], gf_exp[k]); for (int i = 0; i < 255; i++) { // terms[0] is constant uint8_t sum = 1; for (int k = 1; k < tmp.degree; k++) { sum ^= tmp.terms[k]; tmp.terms[k] = gf_mul(tmp.terms[k], gf_exp[k]); } if (sum == 0) dst->terms[dst->degree++] = i; } }
void process_header(struct poet_ctx *ctx, const uint8_t *header, uint64_t header_len) { block mask; block factor; block in; block out; block product; uint64_t offset=0; ctx->mlen=0; memset(factor,0,BLOCKLEN); memset(product,0,BLOCKLEN); memset(mask,0,BLOCKLEN); memset(ctx->tau,0,BLOCKLEN); product[0] = 0x80; // since 1000 0000 = 1 factor[0] = 0x40; // since 0100 0000 = 2 while(header_len > BLOCKLEN) { gf_mul(mask, product, ctx->l); xor_block(in,header+offset,mask); AES_encrypt(in,out,&(ctx->aes_enc)); xor_block(ctx->tau,out,ctx->tau); offset += BLOCKLEN; header_len -= BLOCKLEN; gf_mul(product,product,factor); } /* LASTBLOCK */ if(header_len < 16) { factor[0]=0xA0; // 1010 0000 = 5 in Big Endian memset(in,0,BLOCKLEN); memcpy(in,header+offset,header_len); in[header_len]=0x80; } else { factor[0]=0xC0; // 1100 0000 = 3 in Big Endian memcpy(in,header+offset,BLOCKLEN); } gf_mul(product,product,factor); gf_mul(mask,product,ctx->l); xor_block(in,mask,in); xor_block(in,in,ctx->tau); AES_encrypt(in ,ctx->tau, &(ctx->aes_enc)); memcpy(ctx->x, ctx->tau, BLOCKLEN); memcpy(ctx->y, ctx->tau, BLOCKLEN); }
// p = p * x mod g // p de degré <= deg(g)-1 void poly_shiftmod(poly_t p, poly_t g) { int i, t; gf_t a; t = poly_deg(g); a = gf_div(p->coeff[t-1], g->coeff[t]); for (i = t - 1; i > 0; --i) p->coeff[i] = gf_add(p->coeff[i - 1], gf_mul(a, g->coeff[i])); p->coeff[0] = gf_mul(a, g->coeff[0]); }
int gf_invert_matrix(unsigned char *in_mat, unsigned char *out_mat, const int n) { int i, j, k; unsigned char temp; // Set out_mat[] to the identity matrix for (i = 0; i < n * n; i++) // memset(out_mat, 0, n*n) out_mat[i] = 0; for (i = 0; i < n; i++) out_mat[i * n + i] = 1; // Inverse for (i = 0; i < n; i++) { // Check for 0 in pivot element if (in_mat[i * n + i] == 0) { // Find a row with non-zero in current column and swap for (j = i + 1; j < n; j++) if (in_mat[j * n + i]) break; if (j == n) // Couldn't find means it's singular return -1; for (k = 0; k < n; k++) { // Swap rows i,j temp = in_mat[i * n + k]; in_mat[i * n + k] = in_mat[j * n + k]; in_mat[j * n + k] = temp; temp = out_mat[i * n + k]; out_mat[i * n + k] = out_mat[j * n + k]; out_mat[j * n + k] = temp; } } temp = gf_inv(in_mat[i * n + i]); // 1/pivot for (j = 0; j < n; j++) { // Scale row i by 1/pivot in_mat[i * n + j] = gf_mul(in_mat[i * n + j], temp); out_mat[i * n + j] = gf_mul(out_mat[i * n + j], temp); } for (j = 0; j < n; j++) { if (j == i) continue; temp = in_mat[j * n + i]; for (k = 0; k < n; k++) { out_mat[j * n + k] ^= gf_mul(temp, out_mat[i * n + k]); in_mat[j * n + k] ^= gf_mul(temp, in_mat[i * n + k]); } } } return 0; }
static void pniels_to_pt(curve448_point_t e, const pniels_t d) { gf eu; gf_add(eu, d->n->b, d->n->a); gf_sub(e->y, d->n->b, d->n->a); gf_mul(e->t, e->y, eu); gf_mul(e->x, d->z, e->y); gf_mul(e->y, d->z, eu); gf_sqr(e->z, d->z); }
c448_bool_t curve448_point_eq(const curve448_point_t p, const curve448_point_t q) { mask_t succ; gf a, b; /* equality mod 2-torsion compares x/y */ gf_mul(a, p->y, q->x); gf_mul(b, q->y, p->x); succ = gf_eq(a, b); return mask_to_bool(succ); }
// Exponentiation uint8_t gf_exp(uint8_t b, uint8_t e, uint8_t p) { uint8_t r = 1; uint8_t t = b; while (e > 0) { if (e & 1) { r = gf_mul(r, t, p); } t = gf_mul(t, t, p); e >>= 1; } return r; }
static void niels_to_pt(curve448_point_t e, const niels_t n) { gf_add(e->y, n->b, n->a); gf_sub(e->x, n->b, n->a); gf_mul(e->t, e->y, e->x); gf_copy(e->z, ONE); }
static uint8_t gf_poly_eval(const poly_t *poly, uint8_t x) { uint8_t result = poly->terms[poly->degree - 1]; for (int i = poly->degree - 2; i >= 0; i--) result = gf_mul(result, x) ^ poly->terms[i]; return result; }
int cgc_rs_decode(uint8_t *encoded, int n_parity) { poly_t tmp, synd, sigma, pos; cgc_memcpy(tmp.terms, encoded, 255); tmp.degree = 255; rs_calc_synd(&synd, &tmp, n_parity); // synd.degree must equal n_parity, e.g. don't eliminate zero terms rs_calc_sigma(&sigma, &synd); rs_calc_pos(&pos, &sigma); rs_calc_omega(&tmp, &synd, &sigma); rs_calc_sigma_deriv(&sigma); for (int i = 0; i < pos.degree; i++) { uint8_t x_inv = gf_inverse(gf_exp[(255 - 1 - pos.terms[i]) % 255]); uint8_t mag = gf_div(gf_poly_eval(&tmp, x_inv), gf_mul(x_inv, gf_poly_eval(&sigma, x_inv))); encoded[255 - 1 - pos.terms[i]] ^= mag; } // test result for errors cgc_memcpy(tmp.terms, encoded, 255); tmp.degree = 255; rs_calc_synd(&synd, &tmp, n_parity); gf_poly_reduce(&synd); // if no errors, then we succesfully decoded return synd.degree == 0; }
void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, unsigned char *dest) { //2nd element of table array is ref value used to fill it in unsigned char c = a[1]; while (len-- > 0) *dest++ = gf_mul(c, *src++); }
gf gf_div(gf a, gf b) { gf c = gf_inv(b); gf result = gf_mul(a, c); return result; }
static void raidz_init_scalar(void) { int c, i; for (c = 0; c < 256; c++) for (i = 0; i < 256; i++) vdev_raidz_mul_lt[c][i] = gf_mul(c, i); }
static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn, int before_double) { gf L0; gf_mul(L0, p->z, pn->z); gf_copy(p->z, L0); sub_niels_from_pt(p, pn->n, before_double); }
void mk_gf_mul_table(u8 * table) { // Populate a single table with all multiply combinations for a fast, // single-table lookup of GF(2^8) multiply at the expense of memory. int i, j; for (i = 0; i < 256; i++) for (j = 0; j < 256; j++) table[i * 256 + j] = gf_mul(i, j); }
static void gf_poly_mul(poly_t *dst, const poly_t *a, const poly_t *b) { dst->degree = a->degree + b->degree - 1; cgc_memset(dst->terms, 0, dst->degree); for (int i = 0; i < a->degree; i++) for (int j = 0; j < b->degree; j++) dst->terms[i + j] ^= gf_mul(a->terms[i], b->terms[j]); }
MAT key_genmat(gf_t *L, poly_t g) { //L- Support //t- Number of errors, i.e.=30. //n- Length of the Goppa code, i.e.=2^11 //m- The extension degree of the GF, i.e. =11 //g- The generator polynomial. gf_t x,y; MAT H,R; int i,j,k,r,n; int * perm, Laux[LENGTH]; n=LENGTH;//2^11=2048 r=NB_ERRORS*gf_extd();//32 x 11=352 H=mat_ini(r,n);//initialize matrix with actual no. of bits. mat_set_to_zero(H); //set the matrix with all 0's. for(i=0;i< n;i++) { x = poly_eval(g,L[i]);//evaluate the polynomial at the point L[i]. x = gf_inv(x); y = x; for(j=0;j<NB_ERRORS;j++) { for(k=0;k<gf_extd();k++) { if(y & (1<<k))//if((y>>k) & 1) mat_set_coeff_to_one(H,j*gf_extd()+k,i);//the co-eff. are set in 2^0,...,2^11 ; 2^0,...,2^11 format along the rows/cols? } y = gf_mul(y,L[i]); } }//The H matrix is fed. perm = mat_rref(H); if (perm == NULL) { mat_free(H); return NULL; } R = mat_ini(n-r,r); mat_set_to_zero(R); //set the matrix with all 0's. for (i = 0; i < R->rown; ++i) for (j = 0; j < R->coln; ++j) if (mat_coeff(H,j,perm[i])) mat_change_coeff(R,i,j); for (i = 0; i < LENGTH; ++i) Laux[i] = L[perm[i]]; for (i = 0; i < LENGTH; ++i) L[i] = Laux[i]; mat_free(H); free(perm); return (R); }
void gf_gen_rs_matrix(unsigned char *a, int m, int k) { int i, j; unsigned char p, gen = 1; memset(a, 0, k * m); for (i = 0; i < k; i++) a[k * i + i] = 1; for (i = k; i < m; i++) { p = 1; for (j = 0; j < k; j++) { a[k * i + j] = p; p = gf_mul(p, gen); } gen = gf_mul(gen, 2); } }
c448_bool_t curve448_point_valid(const curve448_point_t p) { mask_t out; gf a, b, c; gf_mul(a, p->x, p->y); gf_mul(b, p->z, p->t); out = gf_eq(a, b); gf_sqr(a, p->x); gf_sqr(b, p->y); gf_sub(a, b, a); gf_sqr(b, p->t); gf_mulw(c, b, TWISTED_D); gf_sqr(b, p->z); gf_add(b, b, c); out &= gf_eq(a, b); out &= ~gf_eq(p->z, ZERO); return mask_to_bool(out); }
gf_t poly_eval_aux(gf_t * coeff, gf_t a, int d) { gf_t b; b = coeff[d--]; for (; d >= 0; --d) if (b != gf_zero()) b = gf_add(gf_mul(b, a), coeff[d]); else b = coeff[d]; return b; }
void gf_vect_mad_base(int len, int vec, int vec_i, unsigned char *v, unsigned char *src, unsigned char *dest) { int i; unsigned char s; for (i = 0; i < len; i++) { s = dest[i]; s ^= gf_mul(src[i], v[vec_i * 32 + 1]); dest[i] = s; } }
int main(void) { unsigned x, y; for (x = 0; x < 16; x++) Ei[E[x]] = x; // for (x = 0; x < 16; x++) printf("%2x ", sbox(x)); for (y = 1; y < 8; y++) { for (x = 0; x < 8; x++) { cir[y][x] = cir[y-1][(x-1)&7]; } } /* printf("\n"); for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) printf("%2d ", cir[y][x]); printf("\n"); } */ for (y = 0; y < 8; y++) { printf("static const ulong64 sbox%d[] = {\n", y); for (x = 0; x < 256; ) { printf("CONST64(0x%02x%02x%02x%02x%02x%02x%02x%02x)", gf_mul(sbox(x), cir[y][0]), gf_mul(sbox(x), cir[y][1]), gf_mul(sbox(x), cir[y][2]), gf_mul(sbox(x), cir[y][3]), gf_mul(sbox(x), cir[y][4]), gf_mul(sbox(x), cir[y][5]), gf_mul(sbox(x), cir[y][6]), gf_mul(sbox(x), cir[y][7])); if (x < 255) printf(", "); if (!(++x & 3)) printf("\n"); } printf("};\n\n"); } printf("static const ulong64 cont[] = {\n"); for (y = 0; y <= 10; y++) { printf("CONST64(0x"); for (x = 0; x < 8; x++) { printf("%02x", sbox((8*y + x)&255)); } printf("),\n"); } printf("};\n\n"); return 0; }
void test_gf() { int i ; /* * test gf tables. Sufficiently tested... */ for (i=0; i<= GF_SIZE; i++) { if (gf_exp[gf_log[i]] != i) fprintf(stderr, "bad exp/log i %d log %d exp(log) %d\n", i, gf_log[i], gf_exp[gf_log[i]]); if (i != 0 && gf_mul(i, inverse[i]) != 1) fprintf(stderr, "bad mul/inv i %d inv %d i*inv(i) %d\n", i, inverse[i], gf_mul(i, inverse[i]) ); if (gf_mul(0,i) != 0) fprintf(stderr, "bad mul table 0,%d\n",i); if (gf_mul(i,0) != 0) fprintf(stderr, "bad mul table %d,0\n",i); } }
void gf_vect_dot_prod_ref(int len, int vlen, u8 * v, u8 ** src, u8 * dest) { int i, j; u8 s; for (i = 0; i < len; i++) { s = 0; for (j = 0; j < vlen; j++) s ^= gf_mul(src[j][i], v[j]); dest[i] = s; } }
void print_multiply_by(gf m) { /* * to multiply by m we determine its logarithm n, (a^n = m in * GF(256)), and add it to the table of powers. */ int i; for(i=0; i<=NN; i++) { printf("%02x x %02x = %02x\n", i, m, gf_mul(i, m)); } }
void gf_mat_mult(unsigned char A[], unsigned char x[],unsigned char y[],int num_err) { int i;int j; for (i=0;i<num_err;i++) { y[i]=0; for (j=0;j<num_err;j++) { y[i]^=gf_mul(A[i+j*num_err],x[j]); } } }
//eliminate by column to make the pivot row become reduced echelon form void eliminate_by_col(uint8_t *matrix, uint8_t *result, int pivotIndex, int size) { int row; int col; uint8_t matrixPivotValue; uint8_t resultPivotValue; uint8_t pivotRowItem; for(row=0; row<size; row++) { matrixPivotValue = matrix[ IDC2D(row, pivotIndex, size) ]; resultPivotValue = result[ IDC2D(row, pivotIndex, size) ]; for(col=0; col<size; col++) { pivotRowItem = matrix[ IDC2D(pivotIndex, col, size) ]; if(col != pivotIndex) { matrix[ IDC2D(row, col, size) ] ^= gf_mul(pivotRowItem, matrixPivotValue); result[ IDC2D(row, col, size) ] ^= gf_mul(pivotRowItem, resultPivotValue); } } } }