/* * Function: grain_keystream * * Synopsis * Generates a new bit and updates the internal state of the cipher. */ u8 grain_keystream(ECRYPT_ctx* ctx) { u32 x0 = get3(S), x1 = get25(S), x2 = get46(S), x3 = get64(S), x4 = get63(B); u32 Z = get1(B) ^ get2(B) ^ get4(B) ^ get10(B) ^ get31(B) ^ get43(B) ^ get56(B) ^ h(x0,x1,x2,x3,x4); u32 S80 = get62(S) ^ get51(S) ^ get38(S) ^ get23(S) ^ get13(S) ^ get0(S); #if !defined(COMBINE_TERMS) u32 B80 =(get0(S)) ^ (get62(B)) ^ (get60(B)) ^ (get52(B)) ^ (get45(B)) ^ (get37(B)) ^ (get33(B)) ^ (get28(B)) ^ (get21(B))^ (get14(B)) ^ (get9(B)) ^ (get0(B)) ^ (get63(B)&get60(B)) ^ (get37(B)&get33(B)) ^ (get15(B)&get9(B))^ (get60(B)&get52(B)&get45(B)) ^ (get33(B)&get28(B)&get21(B)) ^ (get63(B)&get45(B)&get28(B)&get9(B))^ (get60(B)&get52(B)&get37(B)&get33(B)) ^ (get63(B)&get60(B)&get21(B)&get15(B))^ (get63(B)&get60(B)&get52(B)&get45(B)&get37(B)) ^ (get33(B)&get28(B)&get21(B)&get15(B)&get9(B))^ (get52(B)&get45(B)&get37(B)&get33(B)&get28(B)&get21(B)); #else u32 B33_28_21 = (get33(B)&get28(B)&get21(B)); /* 3 */ u32 B52_45_37 = (get52(B)&get45(B)&get37(B)); /* 2 */ u32 B52_37_33 = (get52(B)&get37(B)&get33(B)); /* 2 */ u32 B60_52_45 = (get60(B)&get52(B)&get45(B)); /* 2 */ u32 B63_60 = (get63(B)&get60(B)); /* 3 */ u32 B37_33 = (get37(B)&get33(B)); /* 3 */ u32 B45_28 = (get45(B)&get28(B)); /* 2 */ u32 B15_9 = (get15(B)&get9(B)); /* 2 */ u32 B21_15 = (get21(B)&get15(B)); /* 2 */ u32 B80 =(get0(S)) ^ (get62(B)) ^ (get60(B)) ^ (get52(B)) ^ (get45(B)) ^ (get37(B)) ^ (get33(B)) ^ (get28(B)) ^ (get21(B))^ (get14(B)) ^ (get9(B)) ^ (get0(B)) ^ (B63_60) ^ (B37_33) ^ (B15_9)^ (B60_52_45) ^ (B33_28_21) ^ (get63(B)&B45_28&get9(B))^ (get60(B)&B52_37_33) ^ (B63_60&B21_15)^ (B63_60&B52_45_37) ^ (B33_28_21&B15_9)^ (B52_45_37&B33_28_21); #endif SHIFT_FSR(S); SHIFT_FSR(B); set79(S,S80); set79(B,B80); return Z&1; }
void strassen_8thread_mult(matrix a, matrix b, matrix c){ matrix quar[12]; matrix m[7]; struct work_struct *jobs[7]; int size = a.size/2; int i, j; if(size==0){ c.rows[0][0] = a.rows[0][0] * b.rows[0][0]; return; } /* if (a.size <= BREAK) { int i, j, k; for (i = 0; i < (a.size); i++) { for (k = 0; k < (a.size); k++) { for (j = 0; j < (a.size); j++) { c.rows[i][j] += a.rows[i][k] * b.rows[k][j]; } } } return; } */ job_init(); quar[0]=get00(a); quar[1]=get01(a); quar[2]=get10(a); quar[3]=get11(a); quar[4]=get00(b); quar[5]=get01(b); quar[6]=get10(b); quar[7]=get11(b); quar[8]=get00(c); quar[9]=get01(c); quar[10]=get10(c); quar[11]=get11(c); for(i=0;i<7;i++){ m[i] = new_matrix(size); } for (i = 0; i < 7; i++) { jobs[i] = malloc(sizeof(struct work_struct)); if (jobs[i] == NULL) { perror(NULL); exit(1); } } jobs[0]->a_1 = quar[0]; jobs[0]->a_2 = quar[3]; jobs[0]->b_1 = quar[4]; jobs[0]->b_2 = quar[7]; jobs[0]->c = m[0]; jobs[0]->tid = 0; job_create(thread_main, jobs[0], 0); jobs[1]->a_1 = quar[2]; jobs[1]->a_2 = quar[3]; jobs[1]->b_1 = quar[4]; jobs[1]->c = m[1]; jobs[1]->tid = 1; job_create(thread_main, jobs[1], 0); jobs[2]->a_1 = quar[0]; jobs[2]->b_1 = quar[5]; jobs[2]->b_2 = quar[7]; jobs[2]->c = m[2]; jobs[2]->tid = 2; job_create(thread_main, jobs[2], 0); jobs[3]->a_1 = quar[3]; jobs[3]->b_1 = quar[6]; jobs[3]->b_2 = quar[4]; jobs[3]->c = m[3]; jobs[3]->tid = 3; job_create(thread_main, jobs[3], 0); jobs[4]->a_1 = quar[0]; jobs[4]->a_2 = quar[1]; jobs[4]->b_1 = quar[7]; jobs[4]->c = m[4]; jobs[4]->tid = 4; job_create(thread_main, jobs[4], 0); jobs[5]->a_1 = quar[2]; jobs[5]->a_2 = quar[0]; jobs[5]->b_1 = quar[4]; jobs[5]->b_2 = quar[5]; jobs[5]->c = m[5]; jobs[5]->tid = 5; job_create(thread_main, jobs[5], 0); jobs[6]->a_1 = quar[1]; jobs[6]->a_2 = quar[3]; jobs[6]->b_1 = quar[6]; jobs[6]->b_2 = quar[7]; jobs[6]->c = m[6]; jobs[6]->tid = 6; job_create(thread_main, jobs[6], 0); for(i=0;i<7;i++){ job_join(jobs[i]); } for(i=0;i<size;i++){ for(j=0;j<size;j++){ quar[8].rows[i][j] = m[0].rows[i][j] + m[3].rows[i][j] - m[4].rows[i][j] + m[6].rows[i][j]; quar[9].rows[i][j] = m[2].rows[i][j] + m[4].rows[i][j]; quar[10].rows[i][j] = m[1].rows[i][j] + m[3].rows[i][j]; quar[11].rows[i][j] = m[0].rows[i][j] - m[1].rows[i][j] + m[2].rows[i][j] + m[5].rows[i][j]; } } for(i=0;i<12;i++){ delete_matrix(quar[i]); } for(i=0;i<7;i++){ delete_matrix(m[i]); } }
//expects c to be initialized void strassen_mult(matrix a, matrix b, matrix c){ matrix quar[12]; matrix m[7]; matrix temp1, temp2; int size = a.size/2; int i,j; // if(size==0){ // c.rows[0][0] = a.rows[0][0] * b.rows[0][0]; // return; // } if (a.size <= BREAK) { int i, j, k; for (i = 0; i < (a.size); i++) { for (k = 0; k < (a.size); k++) { for (j = 0; j < (a.size); j++) { c.rows[i][j] += a.rows[i][k] * b.rows[k][j]; } } } } quar[0]=get00(a); quar[1]=get01(a); quar[2]=get10(a); quar[3]=get11(a); quar[4]=get00(b); quar[5]=get01(b); quar[6]=get10(b); quar[7]=get11(b); quar[8]=get00(c); quar[9]=get01(c); quar[10]=get10(c); quar[11]=get11(c); for(i=0;i<7;i++){ m[i] = new_matrix(size); } if (a.size <= BREAK) goto group; temp1 = new_matrix(size); temp2 = new_matrix(size); plus(quar[0], quar[3], temp1); plus(quar[4], quar[7], temp2); strassen_mult(temp1,temp2,m[0]); plus(quar[2], quar[3], temp1); strassen_mult(temp1, quar[4], m[1]); minus(quar[5], quar[7], temp2); strassen_mult(quar[0], temp2, m[2]); minus(quar[6], quar[4], temp2); strassen_mult(quar[3], temp2, m[3]); plus(quar[0], quar[1], temp1); strassen_mult(temp1, quar[7], m[4]); minus(quar[2], quar[0], temp1); plus(quar[4], quar[5], temp2); strassen_mult(temp1, temp2, m[5]); minus(quar[1], quar[3], temp1); plus(quar[6], quar[7], temp2); strassen_mult(temp1, temp2, m[6]); delete_matrix(temp1); delete_matrix(temp2); group: for(i=0;i<size;i++){ for(j=0;j<size;j++){ quar[8].rows[i][j] = m[0].rows[i][j] + m[3].rows[i][j] - m[4].rows[i][j] + m[6].rows[i][j]; quar[9].rows[i][j] = m[2].rows[i][j] + m[4].rows[i][j]; quar[10].rows[i][j] = m[1].rows[i][j] + m[3].rows[i][j]; quar[11].rows[i][j] = m[0].rows[i][j] - m[1].rows[i][j] + m[2].rows[i][j] + m[5].rows[i][j]; } } for(i=0;i<12;i++){ delete_matrix(quar[i]); } for(i=0;i<7;i++){ delete_matrix(m[i]); } }