/*---------------------------------------------------------------------------*/ void ecc_add(point_t * P0, point_t * P1, point_t * P2) { NN_DIGIT Z0[NUMWORDS]; NN_DIGIT Z1[NUMWORDS]; NN_DIGIT Z2[NUMWORDS]; p_clear(P0); NN_AssignZero(Z0, NUMWORDS); NN_AssignZero(Z1, NUMWORDS); NN_AssignZero(Z2, NUMWORDS); Z1[0] = 0x01; Z2[0] = 0x01; #ifdef ADD_MIX c_add_mix(P0, Z0, P1, Z1, P2); #else ecc_add_proj(P0, Z0, P1, Z1, P2, Z2); #endif if(!Z_is_one(Z0)) { NN_ModInv(Z1, Z0, param.p, NUMWORDS); NN_ModMultOpt(Z0, Z1, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(P0->x, P0->x, Z0, param.p, param.omega, NUMWORDS); NN_ModMultOpt(Z0, Z0, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(P0->y, P0->y, Z0, param.p, param.omega, NUMWORDS); } }
int ecc_check_point ( point_t *P ) { NN_DIGIT tmp1[NUMWORDS], tmp2[NUMWORDS]; if ( NN_Zero ( P->x, NUMWORDS ) ) return -1; if ( NN_Cmp ( P->x, param.p, NUMWORDS ) >= 0 ) return -1; if ( NN_Zero ( P->y, NUMWORDS ) ) return -1; if ( NN_Cmp ( P->y, param.p, NUMWORDS ) >= 0 ) return -1; memset ( tmp1, 0, NUMWORDS*NN_DIGIT_LEN ); memset ( tmp2, 0, NUMWORDS*NN_DIGIT_LEN ); NN_ModSqrOpt ( tmp2, P->x, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( tmp2, tmp2, P->x, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( tmp1, P->x, param.E.a, param.p, param.omega, NUMWORDS ); NN_ModAdd ( tmp2, tmp1, tmp2, param.p, NUMWORDS ); NN_ModAdd ( tmp2, tmp2, param.E.b, param.p, NUMWORDS ); NN_ModSqrOpt ( tmp1, P->y, param.p, param.omega, NUMWORDS ); if ( NN_Cmp ( tmp1, tmp2, NUMWORDS ) != 0 ) return -2; return 1; }
int ecc_octet2point ( point_t *P, uint8_t *octet, uint16_t octet_len ) { NN_DIGIT alpha[NUMWORDS], tmp[NUMWORDS]; if ( octet[0] == 0 ) { //infinity NN_AssignZero ( P->x, NUMWORDS ); NN_AssignZero ( P->y, NUMWORDS ); } else if ( octet[0] == 4 ) { //non compressed NN_Decode ( P->x, NUMWORDS, octet+1, KEYDIGITS*NN_DIGIT_LEN ); NN_Decode ( P->y, NUMWORDS, octet+1+KEYDIGITS*NN_DIGIT_LEN, KEYDIGITS*NN_DIGIT_LEN ); return 2*KEYDIGITS*NN_DIGIT_LEN+1; } else if ( octet[0] == 2 || octet[0] == 3 ) { //compressed form NN_Decode ( P->x, NUMWORDS, octet+1, KEYDIGITS*NN_DIGIT_LEN ); //compute y NN_ModSqrOpt ( alpha, P->x, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( alpha, alpha, P->x, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( tmp, param.E.a, P->x, param.p, param.omega, NUMWORDS ); NN_ModAdd ( tmp, tmp, alpha, param.p, NUMWORDS ); NN_ModAdd ( tmp, tmp, param.E.b, param.p, NUMWORDS ); NN_ModSqrOpt ( P->y, tmp, param.p, NUMWORDS, param.omega ); if ( octet[0] == 3 ) { NN_ModSub ( P->y, param.p, P->y, param.p, NUMWORDS ); } return KEYDIGITS*NN_DIGIT_LEN+1; } return -1; }
/* * scalar point multiplication * P0 = n*basepoint * pointArray is array of basepoint, pointArray[0] = basepoint, pointArray[1] = 2*basepoint ... */ void ecc_win_mul(point_t * P0, NN_DIGIT * n, point_t * pointArray) { int16_t i, tmp; int8_t j; NN_DIGIT windex; NN_DIGIT Z0[NUMWORDS]; NN_DIGIT Z1[NUMWORDS]; #ifndef REPEAT_DOUBLE int8_t k; #endif p_clear(P0); /* Convert to Jprojective coordinate */ NN_AssignZero(Z0, NUMWORDS); NN_AssignZero(Z1, NUMWORDS); Z1[0] = 0x01; tmp = NN_Digits(n, NUMWORDS); for(i = tmp - 1; i >= 0; i--) { for(j = NN_DIGIT_BITS/W_BITS - 1; j >= 0; j--) { #ifndef REPEAT_DOUBLE for(k = 0; k < W_BITS; k++) { ecc_dbl_proj(P0, Z0, P0, Z0); } #else ecc_m_dbl_projective(P0, Z0, W_BITS); #endif windex = mask[j] & n[i]; if(windex) { windex = windex >> (j*W_BITS); #ifdef ADD_MIX c_add_mix(P0, Z0, P0, Z0, &(pointArray[windex-1])); #else ecc_add_proj(P0, Z0, P0, Z0, &(pointArray[windex-1]), Z1); #endif } } } /* Convert back to affine coordinate */ if(!Z_is_one(Z0)) { NN_ModInv(Z1, Z0, param.p, NUMWORDS); NN_ModMultOpt(Z0, Z1, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(P0->x, P0->x, Z0, param.p, param.omega, NUMWORDS); NN_ModMultOpt(Z0, Z0, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(P0->y, P0->y, Z0, param.p, param.omega, NUMWORDS); } }
/* * P0 = n * P1 */ void ecc_mul ( point_t* P0, point_t* P1, NN_DIGIT* n ) { int16_t i, tmp; NN_DIGIT Z0[NUMWORDS]; NN_DIGIT Z1[NUMWORDS]; /* clear point */ p_clear ( P0 ); /* convert to Jprojective coordinate */ NN_AssignZero ( Z0, NUMWORDS ); NN_AssignZero ( Z1, NUMWORDS ); Z1[0] = 0x01; tmp = NN_Bits ( n, NUMWORDS ); for ( i = tmp-1; i >= 0; i-- ) { ecc_dbl_proj ( P0, Z0, P0, Z0 ); if ( b_testbit ( n, i ) ) { #ifdef ADD_MIX c_add_mix ( P0, Z0, P0, Z0, P1 ); #else ecc_add_proj ( P0, Z0, P0, Z0, P1, Z1 ); #endif } } /* convert back to affine coordinate */ if ( !Z_is_one ( Z0 ) ) { NN_ModInv ( Z1, Z0, param.p, NUMWORDS ); NN_ModMultOpt ( Z0, Z1, Z1, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( P0->x, P0->x, Z0, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( Z0, Z0, Z1, param.p, param.omega, NUMWORDS ); NN_ModMultOpt ( P0->y, P0->y, Z0, param.p, param.omega, NUMWORDS ); } }
/*---------------------------------------------------------------------------*/ void ecc_m_dbl_projective(point_t * P0, NN_DIGIT *Z0, uint8_t m) { uint8_t i; NN_DIGIT W[NUMWORDS]; NN_DIGIT A[NUMWORDS]; NN_DIGIT B[NUMWORDS]; NN_DIGIT t1[NUMWORDS]; NN_DIGIT y2[NUMWORDS]; if(NN_Zero(Z0, NUMWORDS)){ return; } /* P0->y = 2*P0->y */ NN_LShift(P0->y, P0->y, 1, NUMWORDS); NN_ModSmall(P0->y, param.p, NUMWORDS); /* W = Z^4 */ NN_ModSqrOpt(W, Z0, param.p, param.omega, NUMWORDS); NN_ModSqrOpt(W, W, param.p, param.omega, NUMWORDS); for(i=0; i<m; i++) { if(param.E.a_minus3) { /* A = 3(X^2-W) */ NN_ModSqrOpt(A, P0->x, param.p, param.omega, NUMWORDS); NN_ModSub(A, A, W, param.p, NUMWORDS); NN_LShift(t1, A, 1, NUMWORDS); NN_ModSmall(t1, param.p, NUMWORDS); NN_ModAdd(A, A, t1, param.p, NUMWORDS); } else if(param.E.a_zero) { /* A = 3*X^2 */ NN_ModSqrOpt(t1, P0->x, param.p, param.omega, NUMWORDS); NN_LShift(A, t1, 1, NUMWORDS); NN_ModSmall(A, param.p, NUMWORDS); NN_ModAdd(A, A, t1, param.p, NUMWORDS); } else { /* A = 3*X^2 + a*W */ NN_ModSqrOpt(t1, P0->x, param.p, param.omega, NUMWORDS); NN_LShift(A, t1, 1, NUMWORDS); NN_ModSmall(A, param.p, NUMWORDS); NN_ModAdd(A, A, t1, param.p, NUMWORDS); NN_ModMultOpt(t1, param.E.a, W, param.p, param.omega, NUMWORDS); NN_ModAdd(A, A, t1, param.p, NUMWORDS); } /* B = X*Y^2 */ NN_ModSqrOpt(y2, P0->y, param.p, param.omega, NUMWORDS); NN_ModMultOpt(B, P0->x, y2, param.p, param.omega, NUMWORDS); /* X = A^2 - 2B */ NN_ModSqrOpt(P0->x, A, param.p, param.omega, NUMWORDS); NN_LShift(t1, B, 1, NUMWORDS); NN_ModSmall(t1, param.p, NUMWORDS); NN_ModSub(P0->x, P0->x, t1, param.p, NUMWORDS); /* Z = Z*Y */ NN_ModMultOpt(Z0, Z0, P0->y, param.p, param.omega, NUMWORDS); NN_ModSqrOpt(y2, y2, param.p, param.omega, NUMWORDS); if (i < m-1) { /* W = W*Y^4 */ NN_ModMultOpt(W, W, y2, param.p, param.omega, NUMWORDS); } /* Y = 2A(B-X)-Y^4 */ NN_LShift(A, A, 1, NUMWORDS); NN_ModSmall(A, param.p, NUMWORDS); NN_ModSub(B, B, P0->x, param.p, NUMWORDS); NN_ModMultOpt(A, A, B, param.p, param.omega, NUMWORDS); NN_ModSub(P0->y, A, y2, param.p, NUMWORDS); } if((P0->y[0] % 2) == 1) { NN_Add(P0->y, P0->y, param.p, NUMWORDS); } NN_RShift(P0->y, P0->y, 1, NUMWORDS); }
/*---------------------------------------------------------------------------*/ void ecc_add_proj(point_t * P0, NN_DIGIT *Z0, point_t * P1, NN_DIGIT * Z1, point_t * P2, NN_DIGIT * Z2) { NN_DIGIT n0[NUMWORDS]; NN_DIGIT n1[NUMWORDS]; NN_DIGIT n2[NUMWORDS]; NN_DIGIT n3[NUMWORDS]; NN_DIGIT n4[NUMWORDS]; NN_DIGIT n5[NUMWORDS]; NN_DIGIT n6[NUMWORDS]; if(NN_Zero(Z1, NUMWORDS)) { p_copy(P0, P2); NN_Assign(Z0, Z2, NUMWORDS); return; } if(NN_Zero(Z2, NUMWORDS)) { p_copy(P0, P1); NN_Assign(Z0, Z1, NUMWORDS); return; } /* double */ if(p_equal(P1, P2)) { ecc_dbl_proj(P0, Z0, P1, Z1); return; } /* add_proj * n1, n2 */ if(Z_is_one(Z2)) { /* n1 = P1->x, n2 = P1->y */ NN_Assign(n1, P1->x, NUMWORDS); NN_Assign(n2, P1->y, NUMWORDS); } else { /* n1 = P1->x * Z2^2 */ NN_ModSqrOpt(n0, Z2, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n1, P1->x, n0, param.p, param.omega, NUMWORDS); /* n2 = P1->y * Z2^3 */ NN_ModMultOpt(n0, n0, Z2, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n2, P1->y, n0, param.p, param.omega, NUMWORDS); } /* n3, n4 */ if(Z_is_one(Z1)) { /* n3 = P2->x, n4 = P2->y */ NN_Assign(n3, P2->x, NUMWORDS); NN_Assign(n4, P2->y, NUMWORDS); } else { /* n3 = P2->x * Z1^2 */ NN_ModSqrOpt(n0, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n3, P2->x, n0, param.p, param.omega, NUMWORDS); /* n4 = P2->y * Z1^3 */ NN_ModMultOpt(n0, n0, Z1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n4, P2->y, n0, param.p, param.omega, NUMWORDS); } /* n5 = n1 - n3, n6 = n2 - n4 */ NN_ModSub(n5, n1, n3, param.p, NUMWORDS); NN_ModSub(n6, n2, n4, param.p, NUMWORDS); if(NN_Zero(n5, NUMWORDS)) { if(NN_Zero(n6, NUMWORDS)) { /* P1 and P2 are same point */ ecc_dbl_proj(P0, Z0, P1, Z1); return; } } else { /* P1 is the inverse of P2 */ NN_AssignZero(Z0, NUMWORDS); return; } /* 'n7' = n1 + n3, 'n8' = n2 + n4 */ NN_ModAdd(n1, n1, n3, param.p, NUMWORDS); NN_ModAdd(n2, n2, n4, param.p, NUMWORDS); /* Z0 = Z1 * Z2 * n5 */ if(Z_is_one(Z1) && Z_is_one(Z2)) { NN_Assign(Z0, n5, NUMWORDS); } else { if(Z_is_one(Z1)) { NN_Assign(n0, Z2, NUMWORDS); } else if(Z_is_one(Z2)) { NN_Assign(n0, Z1, NUMWORDS); } else { NN_ModMultOpt(n0, Z1, Z2, param.p, param.omega, NUMWORDS); } NN_ModMultOpt(Z0, n0, n5, param.p, param.omega, NUMWORDS); } /* P0->x = n6^2 - n5^2 * 'n7' */ NN_ModSqrOpt(n0, n6, param.p, param.omega, NUMWORDS); NN_ModSqrOpt(n4, n5, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n3, n1, n4, param.p, param.omega, NUMWORDS); NN_ModSub(P0->x, n0, n3, param.p, NUMWORDS); /* 'n9' = n5^2 * 'n7' - 2 * P0->x */ NN_LShift(n0, P0->x, 1, NUMWORDS); NN_ModSmall(n0, param.p, NUMWORDS); NN_ModSub(n0, n3, n0, param.p, NUMWORDS); /* P0->y = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ NN_ModMultOpt(n0, n0, n6, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n5, n4, n5, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n1, n2, n5, param.p, param.omega, NUMWORDS); NN_ModSub(n0, n0, n1, param.p, NUMWORDS); if((n0[0] % 2) == 1) { NN_Add(n0, n0, param.p, NUMWORDS); } NN_RShift(P0->y, n0, 1, NUMWORDS); }
/*---------------------------------------------------------------------------*/ void ecc_dbl_proj(point_t * P0, NN_DIGIT *Z0, point_t * P1, NN_DIGIT * Z1) { NN_DIGIT n0[NUMWORDS]; NN_DIGIT n1[NUMWORDS]; NN_DIGIT n2[NUMWORDS]; NN_DIGIT n3[NUMWORDS]; if(NN_Zero(Z1, NUMWORDS)) { NN_AssignZero(Z0, NUMWORDS); return; } // n1 if(Z_is_one(Z1)) { /* n1 = 3 * P1->x^2 + param.E.a */ NN_ModSqrOpt(n0, P1->x, param.p, param.omega, NUMWORDS); NN_LShift(n1, n0, 1, NUMWORDS); NN_ModSmall(n1, param.p, NUMWORDS); NN_ModAdd(n0, n0, n1, param.p, NUMWORDS); NN_ModAdd(n1, n0, param.E.a, param.p, NUMWORDS); } else { if(param.E.a_minus3) { /* for a = -3 * n1 = 3 * (X1 + Z1^2) * (X1 - Z1^2) = 3 * X1^2 - 3 * Z1^4 */ NN_ModSqrOpt(n1, Z1, param.p, param.omega, NUMWORDS); NN_ModAdd(n0, P1->x, n1, param.p, NUMWORDS); NN_ModSub(n2, P1->x, n1, param.p, NUMWORDS); NN_ModMultOpt(n1, n0, n2, param.p, param.omega, NUMWORDS); NN_LShift(n0, n1, 1, NUMWORDS); NN_ModSmall(n0, param.p, NUMWORDS); NN_ModAdd(n1, n0, n1, param.p, NUMWORDS); } else if (param.E.a_zero) { /* n1 = 3 * P1->x^2 */ NN_ModSqrOpt(n0, P1->x, param.p, param.omega, NUMWORDS); NN_LShift(n1, n0, 1, NUMWORDS); NN_ModSmall(n1, param.p, NUMWORDS); NN_ModAdd(n1, n0, n1, param.p, NUMWORDS); } else { /* n1 = 3 * P1->x^2 + param.E.a * Z1^4 */ NN_ModSqrOpt(n0, P1->x, param.p, param.omega, NUMWORDS); NN_LShift(n1, n0, 1, NUMWORDS); NN_ModSmall(n1, param.p, NUMWORDS); NN_ModAdd(n0, n0, n1, param.p, NUMWORDS); NN_ModSqrOpt(n1, Z1, param.p, param.omega, NUMWORDS); NN_ModSqrOpt(n1, n1, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n1, n1, param.E.a, param.p, param.omega, NUMWORDS); NN_ModAdd(n1, n1, n0, param.p, NUMWORDS); } } /* Z0 = 2 * P1->y * Z1 */ if(Z_is_one(Z1)) { NN_Assign(n0, P1->y, NUMWORDS); } else { NN_ModMultOpt(n0, P1->y, Z1, param.p, param.omega, NUMWORDS); } NN_LShift(Z0, n0, 1, NUMWORDS); NN_ModSmall(Z0, param.p, NUMWORDS); /* n2 = 4 * P1->x * P1->y^2 */ NN_ModSqrOpt(n3, P1->y, param.p, param.omega, NUMWORDS); NN_ModMultOpt(n2, P1->x, n3, param.p, param.omega, NUMWORDS); NN_LShift(n2, n2, 2, NUMWORDS); NN_ModSmall(n2, param.p, NUMWORDS); /* P0->x = n1^2 - 2 * n2 */ NN_LShift(n0, n2, 1, NUMWORDS); NN_ModSmall(n0, param.p, NUMWORDS); NN_ModSqrOpt(P0->x, n1, param.p, param.omega, NUMWORDS); NN_ModSub(P0->x, P0->x, n0, param.p, NUMWORDS); /* n3 = 8 * P1->y^4 */ NN_ModSqrOpt(n0, n3, param.p, param.omega, NUMWORDS); NN_LShift(n3, n0, 3, NUMWORDS); NN_ModSmall(n3, param.p, NUMWORDS); /* P0->y = n1 * (n2 - P0->x) - n3 */ NN_ModSub(n0, n2, P0->x, param.p, NUMWORDS); NN_ModMultOpt(n0, n1, n0, param.p, param.omega, NUMWORDS); NN_ModSub(P0->y, n0, n3, param.p, NUMWORDS); }
static void c_add_mix(point_t * P0, NN_DIGIT *Z0, point_t * P1, NN_DIGIT * Z1, point_t * P2) { NN_DIGIT t1[NUMWORDS]; NN_DIGIT t2[NUMWORDS]; NN_DIGIT t3[NUMWORDS]; NN_DIGIT t4[NUMWORDS]; NN_DIGIT Z2[NUMWORDS]; /* P2 == infinity */ if(NN_Zero(P2->x, NUMWORDS)) { if(NN_Zero(P2->y, NUMWORDS)) { p_copy(P0, P1); NN_Assign(Z0, Z1, NUMWORDS); return; } } /* P1 == infinity */ if(NN_Zero(Z1, NUMWORDS)) { p_copy(P0, P2); NN_AssignDigit(Z0, 1, NUMWORDS); return; } /* T1 = Z1^2 */ NN_ModSqrOpt(t1, Z1, param.p, param.omega, NUMWORDS); /* T2 = T1*Z1 */ NN_ModMultOpt(t2, t1, Z1, param.p, param.omega, NUMWORDS); /* T1 = T1*P2->x */ NN_ModMultOpt(t1, t1, P2->x, param.p, param.omega, NUMWORDS); /* T2 = T2*P2->y */ NN_ModMultOpt(t2, t2, P2->y, param.p, param.omega, NUMWORDS); /* T1 = T1-P1->x */ NN_ModSub(t1, t1, P1->x, param.p, NUMWORDS); /* T2 = T2-P1->y */ NN_ModSub(t2, t2, P1->y, param.p, NUMWORDS); if(NN_Zero(t1, NUMWORDS)) { if(NN_Zero(t2, NUMWORDS)) { NN_AssignDigit(Z2, 1, NUMWORDS); ecc_dbl_proj(P0, Z0, P2, Z2); return; } else { NN_AssignDigit(Z0, 0, NUMWORDS); return; } } /* Z3 = Z1*T1 */ NN_ModMultOpt(Z0, Z1, t1, param.p, param.omega, NUMWORDS); /* T3 = T1^2 */ NN_ModSqrOpt(t3, t1, param.p, param.omega, NUMWORDS); /* T4 = T3*T1 */ NN_ModMultOpt(t4, t3, t1, param.p, param.omega, NUMWORDS); /* T3 = T3*P1->x */ NN_ModMultOpt(t3, t3, P1->x, param.p, param.omega, NUMWORDS); /* T1 = 2*T3 */ NN_LShift(t1, t3, 1, NUMWORDS); NN_ModSmall(t1, param.p, NUMWORDS); /* P0->x = T2^2 */ NN_ModSqrOpt(P0->x, t2, param.p, param.omega, NUMWORDS); /* P0->x = P0->x-T1 */ NN_ModSub(P0->x, P0->x, t1, param.p, NUMWORDS); /* P0->x = P0->x-T4 */ NN_ModSub(P0->x, P0->x, t4, param.p, NUMWORDS); /* T3 = T3-P0->x */ NN_ModSub(t3, t3, P0->x, param.p, NUMWORDS); /* T3 = T3*T2 */ NN_ModMultOpt(t3, t3, t2, param.p, param.omega, NUMWORDS); /* T4 = T4*P1->y */ NN_ModMultOpt(t4, t4, P1->y, param.p, param.omega, NUMWORDS); /* P0->y = T3-T4 */ NN_ModSub(P0->y, t3, t4, param.p, NUMWORDS); return; }