forked from xuos/xiuos
				
			
		
			
				
	
	
		
			970 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			970 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
/*
 | 
						|
* Copyright (c) 2020 AIIT Ubiquitous Team
 | 
						|
* XiUOS is licensed under Mulan PSL v2.
 | 
						|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
						|
* You may obtain a copy of Mulan PSL v2 at:
 | 
						|
*        http://license.coscl.org.cn/MulanPSL2
 | 
						|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
						|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
						|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
						|
* See the Mulan PSL v2 for more details.
 | 
						|
*/
 | 
						|
 | 
						|
/**
 | 
						|
* @file qn.c
 | 
						|
* @brief arithmetic in extention field, and arithmetic in group G2, frobenius and LastPower in BiLinearPairing
 | 
						|
* @version 1.0 
 | 
						|
* @author AIIT Ubiquitous Team
 | 
						|
* @date 2021-04-24
 | 
						|
*/
 | 
						|
#include <qn.h>
 | 
						|
 | 
						|
big8w t; // sm9 ecc parameter
 | 
						|
big8w qnr; // (-1/2) mod curve.q
 | 
						|
big8w frobenius_constant_1[12];
 | 
						|
big8w frobenius_constant_2[12];
 | 
						|
/**
 | 
						|
 * @brief print the point in group G2
 | 
						|
 * 
 | 
						|
 * @param point a pointer of point in group G2
 | 
						|
 * 
 | 
						|
 * @return null
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void G2pointPrint(G2point* point) 
 | 
						|
{
 | 
						|
	Big8wPrint(&point->x.high);
 | 
						|
	Big8wPrint(&point->x.low);
 | 
						|
	Big8wPrint(&point->y.high);
 | 
						|
	Big8wPrint(&point->y.low);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief print a number in Fq12
 | 
						|
 * 
 | 
						|
 * @param number a pointer of number in Fq12
 | 
						|
 * 
 | 
						|
 * @return null
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Q12Print(q12* number)
 | 
						|
{
 | 
						|
	Big8wPrint(&number->high.high.high);
 | 
						|
	Big8wPrint(&number->high.high.low);
 | 
						|
	Big8wPrint(&number->high.low.high);
 | 
						|
	Big8wPrint(&number->high.low.low);
 | 
						|
 | 
						|
	Big8wPrint(&number->mid.high.high);
 | 
						|
	Big8wPrint(&number->mid.high.low);
 | 
						|
	Big8wPrint(&number->mid.low.high);
 | 
						|
	Big8wPrint(&number->mid.low.low);
 | 
						|
 | 
						|
	Big8wPrint(&number->low.high.high);
 | 
						|
	Big8wPrint(&number->low.high.low);
 | 
						|
	Big8wPrint(&number->low.low.high);
 | 
						|
	Big8wPrint(&number->low.low.low);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief convert q12 to big_12big
 | 
						|
 * 
 | 
						|
 * @param num pointer of number in Fq12
 | 
						|
 * @param ret pointer of big_12big, store the result
 | 
						|
 * 
 | 
						|
 * @result ret
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Q12To12big(q12* num, big_12big* ret)
 | 
						|
{
 | 
						|
	ret->word[0] = num->high.high.high;
 | 
						|
	ret->word[1] = num->high.high.low;
 | 
						|
	ret->word[2] = num->high.low.high;
 | 
						|
	ret->word[3] = num->high.low.low;
 | 
						|
 | 
						|
	ret->word[4] = num->mid.high.high;
 | 
						|
	ret->word[5] = num->mid.high.low;
 | 
						|
	ret->word[6] = num->mid.low.high;
 | 
						|
	ret->word[7] = num->mid.low.low;
 | 
						|
 | 
						|
	ret->word[8] = num->low.high.high;
 | 
						|
	ret->word[9] = num->low.high.low;
 | 
						|
	ret->word[10] = num->low.low.high;
 | 
						|
	ret->word[11] = num->low.low.low;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief set a number in Fq12 to 0
 | 
						|
 * 
 | 
						|
 * @param num pointer of a number in Fq12
 | 
						|
 * 
 | 
						|
 * @resulr num
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Q2Zero(q2* num)
 | 
						|
{
 | 
						|
	memset(num->high.word, 0x00, BIG8W_BYTESIZE);
 | 
						|
	memset(num->low.word, 0x00, BIG8W_BYTESIZE);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief set a number in Fq4 to 0
 | 
						|
 * 
 | 
						|
 * @param num number in Fq4
 | 
						|
 * 
 | 
						|
 * @result num
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Q4Zero(q4* num)
 | 
						|
{
 | 
						|
	Q2Zero(&num->high);
 | 
						|
	Q2Zero(&num->low);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief set a number in Fq12 to 0
 | 
						|
 * 
 | 
						|
 * @param num pointer of a number in Fq12
 | 
						|
 * 
 | 
						|
 * @result num
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Q12Zero(q12* num)
 | 
						|
{
 | 
						|
	Q4Zero(&num->high);
 | 
						|
	Q4Zero(&num->mid);
 | 
						|
	Q4Zero(&num->low);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return num1 == num2
 | 
						|
 * 
 | 
						|
 * @param num1 pointer of the first number in Fq2
 | 
						|
 * @param num2 pointer of the second number in Fq2
 | 
						|
 * 
 | 
						|
 * @return true if num1 == num2; else false
 | 
						|
 * 
 | 
						|
 */
 | 
						|
bool Q2Equal(q2* num1, q2* num2)
 | 
						|
{
 | 
						|
	return Big8wEqual(&num1->high, &num2->high) 
 | 
						|
		&& Big8wEqual(&num1->low, &num2->low);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 + num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq2
 | 
						|
 * @param num2 the second number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq2, ret = num1 + num2.
 | 
						|
 */
 | 
						|
q2 Q2Add(q2 num1, q2 num2)
 | 
						|
{
 | 
						|
	q2 ret;
 | 
						|
 | 
						|
	ret.high = Big8wAddMod(num1.high, num2.high, curve.q);
 | 
						|
	ret.low = Big8wAddMod(num1.low, num2.low, curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 - num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq2
 | 
						|
 * @param num2 the second number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq2, ret = num1 - num2.
 | 
						|
 */
 | 
						|
q2 Q2Minus(q2 num1, q2 num2)
 | 
						|
{
 | 
						|
	q2 ret;
 | 
						|
 | 
						|
	ret.high = Big8wMinusMod(num1.high, num2.high, curve.q);
 | 
						|
	ret.low = Big8wMinusMod(num1.low, num2.low, curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief 
 | 
						|
 * 		set num1 = (a, b), num2 = (c, d), num1*num2 = (a*d + b*c, b*d - 2*a*c)......(high, low)
 | 
						|
 * 		Toom-Cook: (a*d + b*c) = (a + b)(c + d) - a*c - b*d
 | 
						|
 * 		Calls: Big8wMultMod, Big8wAddMod, Big8wMinusMod
 | 
						|
 * 		Called By: G2pointAdd, Q4Mult, Q2Reverse and more
 | 
						|
 * @param num1 the first number in Fq2
 | 
						|
 * @param num2 the second number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq2, ret = num1 * num2
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q2 Q2Mult(q2 num1, q2 num2) 
 | 
						|
{ // num1 = (a1, a0), num2 = (b1, b0).....(high, low)
 | 
						|
	q2 ret;
 | 
						|
	big8w a0b0, a1b1;
 | 
						|
	// Toom-Cook
 | 
						|
	a0b0 = Big8wMultMod(num1.low, num2.low, curve.q);
 | 
						|
	a1b1 = Big8wMultMod(num1.high, num2.high, curve.q);
 | 
						|
 | 
						|
	ret.high = Big8wMultMod(
 | 
						|
		Big8wAddMod(num1.high, num1.low, curve.q),
 | 
						|
		Big8wAddMod(num2.high, num2.low, curve.q), 
 | 
						|
		curve.q);
 | 
						|
 | 
						|
	ret.high = Big8wMinusMod(
 | 
						|
		ret.high,
 | 
						|
		Big8wAddMod(a0b0, a1b1, curve.q),
 | 
						|
		curve.q);
 | 
						|
 | 
						|
	ret.low = Big8wMinusMod(
 | 
						|
		a0b0,
 | 
						|
		Big8wAddMod(a1b1, a1b1, curve.q),
 | 
						|
		curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * 
 | 
						|
 * @brief num1 = (a, b), num2 = (c, d), num1*num2*u = (b*d - 2*a*c, -2*(a*d +b*c)). compare Q2Mult
 | 
						|
 *              
 | 
						|
 * @param num1 the first number in Fq2
 | 
						|
 * @param num2 the second number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq2; ret = a * b * u
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q2 Q2MultFlag(q2 num1, q2 num2)
 | 
						|
{
 | 
						|
	q2 ret = Q2Mult(num1, num2);
 | 
						|
	big8w temp = ret.high;
 | 
						|
 | 
						|
	ret.high = ret.low;
 | 
						|
	ret.low = Big8wMinusMod(
 | 
						|
		curve.q,
 | 
						|
		Big8wAddMod(temp, temp, curve.q), curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * 
 | 
						|
 * @brief num = (a, b), num^(-1) = ((-a)/(b*b +2*a*a), b/(b*b, 2*a*a))
 | 
						|
 * 
 | 
						|
 * @param num number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, number in Fq2, ret = num^(-1).
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q2 Q2Reverse(q2 num)
 | 
						|
{
 | 
						|
	big8w temp;
 | 
						|
	q2 ret;
 | 
						|
 | 
						|
	temp = Big8wMultMod(num.high, num.high, curve.q); // a*a
 | 
						|
	temp = Big8wAddMod(temp, temp, curve.q); // 2*a*a
 | 
						|
	temp = Big8wAddMod(temp, 
 | 
						|
		Big8wMultMod(num.low, num.low, curve.q), curve.q); // (b*b +2*a*a)
 | 
						|
	temp = Big8wReverse(temp, curve.q); // (1/(b*b + 2*a*a))
 | 
						|
 | 
						|
	ret.high = Big8wMinusMod(curve.q, num.high, curve.q); // (-a)
 | 
						|
	ret.high = Big8wMultMod(ret.high, temp, curve.q); 
 | 
						|
	ret.low = Big8wMultMod(num.low, temp, curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (-num);(-num.high, -num.low) mod curve.q = (curve.q - num.high, curve.q - num.low)
 | 
						|
 * 
 | 
						|
 * @param num number in Fq2
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq2
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q2 Q2Negate(q2 num)
 | 
						|
{
 | 
						|
	num.high = Big8wMinusMod(curve.q, num.high, curve.q);
 | 
						|
	num.low = Big8wMinusMod(curve.q, num.low, curve.q);
 | 
						|
 | 
						|
	return num;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief 
 | 
						|
 * 
 | 
						|
 * @param num number in Fq2
 | 
						|
 * 
 | 
						|
 * @return num
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q2 Q2Txx(q2 num)
 | 
						|
{
 | 
						|
	big8w temp;
 | 
						|
 | 
						|
	temp = num.high;
 | 
						|
	num.high = num.low;
 | 
						|
	num.low = Big8wMinusMod(curve.q, temp, curve.q);
 | 
						|
	num.low = Big8wAddMod(num.low, num.low, curve.q);
 | 
						|
 | 
						|
	return num;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief add of two points in group G2
 | 
						|
 * 
 | 
						|
 * @param point1 the first point in group G2
 | 
						|
 * @param point2 the second point in group G2
 | 
						|
 * 
 | 
						|
 * @return ret, a point in group G2
 | 
						|
 * 
 | 
						|
 */
 | 
						|
G2point G2PointAdd(G2point point1, G2point point2)
 | 
						|
{
 | 
						|
	q2 temp, lambda;
 | 
						|
	G2point ret;
 | 
						|
 | 
						|
	memset(&temp, 0x00, BIG8W_BYTESIZE * 2);
 | 
						|
 | 
						|
	// temp = zero
 | 
						|
	// infinite point judge
 | 
						|
	if (Q2Equal(&point1.x, &temp) && Q2Equal(&point1.y, &temp))
 | 
						|
		return point2;
 | 
						|
	else if (Q2Equal(&point2.x, &temp) && Q2Equal(&point2.y, &temp))
 | 
						|
		return point1;
 | 
						|
 | 
						|
	if (Big8wEqual(&point1.x.high, &point2.x.high)
 | 
						|
		&& Big8wEqual(&point1.x.low, &point2.x.low)) { // x1 = x2
 | 
						|
 | 
						|
		if (!Big8wEqual(&point1.y.high, &point2.y.high)
 | 
						|
			|| !Big8wEqual(&point1.y.low, &point2.y.low)) // y1 != y2 (y1 = -y2)
 | 
						|
		{
 | 
						|
			memset(&ret, 0x00, BIG8W_BYTESIZE * 4);
 | 
						|
			return ret; // ret = O
 | 
						|
		}
 | 
						|
 | 
						|
		temp = Q2Mult(point1.x, point1.x);
 | 
						|
 | 
						|
		lambda = Q2Add(temp, temp);
 | 
						|
		lambda = Q2Add(lambda, temp);
 | 
						|
		lambda = Q2Mult(lambda, Q2Reverse(Q2Add(point1.y, point1.y)));
 | 
						|
	}
 | 
						|
 | 
						|
	else {
 | 
						|
		lambda = Q2Mult(
 | 
						|
			Q2Minus(point1.y, point2.y),
 | 
						|
			Q2Reverse(Q2Minus(point1.x, point2.x)));
 | 
						|
	}
 | 
						|
 | 
						|
	ret.x = Q2Mult(lambda, lambda);
 | 
						|
	ret.x = Q2Minus(ret.x, point1.x);
 | 
						|
	ret.x = Q2Minus(ret.x, point2.x);
 | 
						|
 | 
						|
	ret.y = Q2Minus(point1.x, ret.x);
 | 
						|
	ret.y = Q2Mult(lambda, ret.y);
 | 
						|
	ret.y = Q2Minus(ret.y, point1.y);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief mult point in group G2. (num * point)
 | 
						|
 * 
 | 
						|
 * @param num big number, num > 0
 | 
						|
 * @param point point in group G2
 | 
						|
 * 
 | 
						|
 * @return ret, a point in group G2
 | 
						|
 * 
 | 
						|
 */
 | 
						|
G2point G2PointMult(big8w num, G2point point)
 | 
						|
{
 | 
						|
	bool flag = 0;
 | 
						|
	int i = BIGNUMBER_SIZE_8WORD - 1;
 | 
						|
	int index = Big8wHighestbit(&num);
 | 
						|
	uint32_t elem;
 | 
						|
	G2point ret = point, temp = point;
 | 
						|
 | 
						|
	while (num.word[i] == 0)
 | 
						|
		i--;
 | 
						|
	elem = num.word[i];
 | 
						|
 | 
						|
	index--;
 | 
						|
	while (index >= 0) {
 | 
						|
		flag = (elem >> (index--)) & 1;
 | 
						|
		ret = G2PointAdd(temp, temp); 
 | 
						|
		if (flag) 
 | 
						|
			ret = G2PointAdd(ret, point);
 | 
						|
		temp = ret;
 | 
						|
	}
 | 
						|
 | 
						|
	i--; 
 | 
						|
	for (; i >= 0; i--) {
 | 
						|
		elem = num.word[i];
 | 
						|
		index = 31;
 | 
						|
 | 
						|
		while (index >= 0) {
 | 
						|
			flag = (elem >> (index--)) & 1;
 | 
						|
			ret = G2PointAdd(temp, temp);
 | 
						|
			if (flag)
 | 
						|
				ret = G2PointAdd(ret, point);
 | 
						|
			temp = ret;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 + num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq4
 | 
						|
 * @param num2 the second number in Fq4
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq4, ret = (num1 + num2)
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4Add(q4 num1, q4 num2)
 | 
						|
{
 | 
						|
	q4 ret;
 | 
						|
 | 
						|
	ret.high = Q2Add(num1.high, num2.high);
 | 
						|
	ret.low = Q2Add(num1.low, num2.low);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 - num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq4
 | 
						|
 * @param num2 the second number in Fq4
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq4, ret = (num1 - num2)
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4Minus(q4 num1, q4 num2)
 | 
						|
{
 | 
						|
	q4 ret;
 | 
						|
 | 
						|
	ret.high = Q2Minus(num1.high, num2.high);
 | 
						|
	ret.low = Q2Minus(num1.low, num2.low);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief num1 * num2; num1, num2 are numbers in Fq4, the way to compute is similar to Q2Mult
 | 
						|
 * 			q4 num = (num1, num2), similar to Q2Mult, except num1 = (a1, a0), a0, a1 is big8w
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq4
 | 
						|
 * @param num2 the second number in Fq4
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq4
 | 
						|
 */
 | 
						|
q4 Q4Mult(q4 num1, q4 num2)
 | 
						|
{// num1 = (a1, a0), num2 = (b1, b0). left high value
 | 
						|
	q4 ret;
 | 
						|
	q2 a0b0, a1b1;
 | 
						|
 | 
						|
	// Toom-Cook
 | 
						|
	a1b1 = Q2Mult(num1.high, num2.high);
 | 
						|
	a0b0 = Q2Mult(num1.low, num2.low);
 | 
						|
 | 
						|
	ret.high = Q2Mult(
 | 
						|
		Q2Add(num1.high, num1.low),
 | 
						|
		Q2Add(num2.high, num2.low));
 | 
						|
 | 
						|
	ret.high = Q2Minus(
 | 
						|
		ret.high,
 | 
						|
		Q2Add(a0b0, a1b1));
 | 
						|
 | 
						|
	ret.low.high = Big8wAddMod(a0b0.high, a1b1.low, curve.q);
 | 
						|
	ret.low.low = Big8wMinusMod(
 | 
						|
		a0b0.low,
 | 
						|
		Big8wAddMod(a1b1.high, a1b1.high, curve.q),
 | 
						|
		curve.q);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return num1 * num2 * u; num1, num2 are numbers in Fq4
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq4
 | 
						|
 * @param num2 the second number in Fq4
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq4
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4MultFlag(q4 num1, q4 num2)
 | 
						|
{
 | 
						|
	q4 ret;
 | 
						|
 | 
						|
	ret.high = Q2Add(
 | 
						|
		Q2Mult(num1.low, num2.low),
 | 
						|
		Q2MultFlag(num1.high, num2.high));
 | 
						|
	ret.low = Q2Add(
 | 
						|
		Q2MultFlag(num1.high, num2.low),
 | 
						|
		Q2MultFlag(num1.low, num2.high));
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief 
 | 
						|
 * 
 | 
						|
 * @param num number in Fq4
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq4
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4Txx(q4 num)
 | 
						|
{
 | 
						|
	q2 temp;
 | 
						|
 | 
						|
	temp = num.high;
 | 
						|
	num.high = num.low;
 | 
						|
	num.low = Q2Txx(temp);
 | 
						|
	
 | 
						|
	return num;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (-num), similar to Q2Negate
 | 
						|
 * 
 | 
						|
 * @param num a number in Fq4
 | 
						|
 * 
 | 
						|
 * @return num, a number in Fq4
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4Negate(q4 num)
 | 
						|
{
 | 
						|
	num.high = Q2Negate(num.high);
 | 
						|
	num.low = Q2Negate(num.low);
 | 
						|
 | 
						|
	return num;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return num^(-1)
 | 
						|
 * 
 | 
						|
 * @param num number in Fq4
 | 
						|
 * 
 | 
						|
 * @return num, number in Fq4
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q4 Q4Reverse(q4 num)
 | 
						|
{
 | 
						|
	q2 t1, t2;
 | 
						|
	
 | 
						|
	t1 = Q2Mult(num.low, num.low);
 | 
						|
	t2 = Q2Mult(num.high, num.high);
 | 
						|
	t2 = Q2Txx(t2);
 | 
						|
	t1 = Q2Minus(t1, t2);
 | 
						|
	t1 = Q2Reverse(t1);
 | 
						|
	num.low = Q2Mult(num.low, t1);
 | 
						|
	t1 = Q2Negate(t1);
 | 
						|
	num.high = Q2Mult(num.high, t1);
 | 
						|
 | 
						|
	return num;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 * num2);
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq12
 | 
						|
 * @param num2 the second number in Fq12
 | 
						|
 * 
 | 
						|
 * @return a number in Fq12
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q12 Q12MultMod(q12 num1, q12 num2)
 | 
						|
{
 | 
						|
	q12 ret;
 | 
						|
 | 
						|
	ret.high = Q4Add(
 | 
						|
		Q4Mult(num1.high, num2.low),
 | 
						|
		Q4Mult(num1.mid, num2.mid));
 | 
						|
 | 
						|
	ret.high = Q4Add(
 | 
						|
		ret.high, 
 | 
						|
		Q4Mult(num1.low, num2.high));
 | 
						|
 | 
						|
	ret.mid = Q4Add(
 | 
						|
		Q4Mult(num1.low, num2.mid),
 | 
						|
		Q4Mult(num1.mid, num2.low));
 | 
						|
 | 
						|
	ret.mid = Q4Add(
 | 
						|
		ret.mid, 
 | 
						|
		Q4MultFlag(num1.high, num2.high));
 | 
						|
 | 
						|
	ret.low = Q4Add(
 | 
						|
		Q4MultFlag(num1.high, num2.mid),
 | 
						|
		Q4MultFlag(num1.mid, num2.high));
 | 
						|
 | 
						|
	ret.low = Q4Add(
 | 
						|
		ret.low, 
 | 
						|
		Q4Mult(num1.low, num2.low));
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 - num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq12
 | 
						|
 * @param num2 the second number in Fq12
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq12.
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q12 Q12MinusMod(q12 num1, q12 num2)
 | 
						|
{
 | 
						|
	q12 ret;
 | 
						|
 | 
						|
	ret.high = Q4Minus(num1.high, num2.high);
 | 
						|
	ret.mid = Q4Minus(num1.mid, num2.mid);
 | 
						|
	ret.low = Q4Minus(num1.low, num2.low);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return (num1 + num2)
 | 
						|
 * 
 | 
						|
 * @param num1 the first number in Fq12
 | 
						|
 * @param num2 the second number in Fq12
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq12
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q12 Q12AddMod(q12 num1, q12 num2)
 | 
						|
{
 | 
						|
	q12 ret;
 | 
						|
 | 
						|
	ret.high = Q4Add(num1.high, num2.high);
 | 
						|
	ret.mid = Q4Add(num1.mid, num2.mid);
 | 
						|
	ret.low = Q4Add(num1.low, num2.low);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief return num^(-1)
 | 
						|
 * 
 | 
						|
 * @param num number in Fq12
 | 
						|
 * 
 | 
						|
 * @return ret, number in Fq12
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q12 Q12Reverse(q12 num)
 | 
						|
{
 | 
						|
	q12 ret;
 | 
						|
	q4 temp1, temp2;
 | 
						|
 | 
						|
	ret.low = Q4Mult(num.low, num.low);
 | 
						|
	ret.mid = Q4Mult(num.mid, num.high);
 | 
						|
	ret.mid = Q4Txx(ret.mid);
 | 
						|
	ret.low = Q4Minus(ret.low, ret.mid);
 | 
						|
 | 
						|
	ret.high = Q4Mult(num.high, num.high);
 | 
						|
	ret.high = Q4Txx(ret.high);
 | 
						|
	ret.mid = Q4Mult(num.low, num.mid);
 | 
						|
	ret.mid = Q4Minus(ret.high, ret.mid);
 | 
						|
 | 
						|
	ret.high = Q4Mult(num.mid, num.mid);
 | 
						|
	temp1 = Q4Mult(num.low, num.high);
 | 
						|
	ret.high = Q4Minus(ret.high, temp1);
 | 
						|
 | 
						|
	temp1 = Q4Mult(num.mid, ret.high);
 | 
						|
	temp1 = Q4Txx(temp1);
 | 
						|
 | 
						|
	temp2 = Q4Mult(num.low, ret.low);
 | 
						|
	temp1 = Q4Add(temp1, temp2);
 | 
						|
 | 
						|
	temp2 = Q4Mult(num.high, ret.mid);
 | 
						|
	temp2 = Q4Txx(temp2);
 | 
						|
	temp1 = Q4Add(temp1, temp2);
 | 
						|
 | 
						|
	temp1 = Q4Reverse(temp1);
 | 
						|
 | 
						|
	ret.low = Q4Mult(ret.low, temp1);
 | 
						|
	ret.mid = Q4Mult(ret.mid, temp1);
 | 
						|
	ret.high = Q4Mult(ret.high, temp1);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief compute g^r. scan every bit of r
 | 
						|
 * 
 | 
						|
 * @param g a number in Fq12
 | 
						|
 * @param r power, a big number, r >= 0
 | 
						|
 * 
 | 
						|
 * @return ret, a number in Fq12
 | 
						|
 * 
 | 
						|
 */
 | 
						|
q12 Q12PowerMod(q12 g, big8w r)
 | 
						|
{
 | 
						|
	bool flag;
 | 
						|
	int bitindex = Big8wHighestbit(&r);
 | 
						|
	int i = BIGNUMBER_SIZE_8WORD - 1;
 | 
						|
	uint32_t elem;
 | 
						|
	q12 ret = g, temp = g;
 | 
						|
	q12 one;
 | 
						|
 | 
						|
	memset(&one, 0x00, BIG8W_BYTESIZE * 12);
 | 
						|
	one.low.low.low.word[0] = 1;
 | 
						|
 | 
						|
	while (i && r.word[i] == 0)
 | 
						|
		i--;
 | 
						|
	if (i < 0)
 | 
						|
		return one;
 | 
						|
	elem = r.word[i];
 | 
						|
 | 
						|
	bitindex--;
 | 
						|
	while (bitindex >= 0) {
 | 
						|
		flag = (elem >> (bitindex--)) & 1;
 | 
						|
		ret = Q12MultMod(temp, temp); 
 | 
						|
		if (flag)
 | 
						|
			ret = Q12MultMod(ret, g);
 | 
						|
		temp = ret;
 | 
						|
	}
 | 
						|
 | 
						|
	i--; 
 | 
						|
	for (; i >= 0; i--) {
 | 
						|
		elem = r.word[i];
 | 
						|
		bitindex = 31;
 | 
						|
		while (bitindex >= 0) {
 | 
						|
			flag = (elem >> (bitindex--)) & 1;
 | 
						|
			ret = Q12MultMod(temp, temp); 
 | 
						|
			if (flag)
 | 
						|
				ret = Q12MultMod(ret, g); 
 | 
						|
			temp = ret;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief compute f^(curve.q^(flag)); f = (f11, f10, ... f0), f^(curve.q^(flag)) = (f11*c11, f10*c10, ... f0*c0)
 | 
						|
 * 
 | 
						|
 * @param f pointer of a number in Fq12
 | 
						|
 * @param flag 1, 2, 6;
 | 
						|
 * 
 | 
						|
 * @return null
 | 
						|
 */
 | 
						|
void Q12Frobenius(q12* f, uint8_t flag)
 | 
						|
{
 | 
						|
	if (flag == 1) {
 | 
						|
		f->high.high.high = Big8wMultMod(f->high.high.high, frobenius_constant_1[11], curve.q);
 | 
						|
		f->high.high.low = Big8wMultMod(f->high.high.low, frobenius_constant_1[10], curve.q);
 | 
						|
		f->high.low.high = Big8wMultMod(f->high.low.high, frobenius_constant_1[9], curve.q);
 | 
						|
		f->high.low.low = Big8wMultMod(f->high.low.low, frobenius_constant_1[8], curve.q);
 | 
						|
 | 
						|
		f->mid.high.high = Big8wMultMod(f->mid.high.high, frobenius_constant_1[7], curve.q);
 | 
						|
		f->mid.high.low = Big8wMultMod(f->mid.high.low, frobenius_constant_1[6], curve.q);
 | 
						|
		f->mid.low.high = Big8wMultMod(f->mid.low.high, frobenius_constant_1[5], curve.q);
 | 
						|
		f->mid.low.low = Big8wMultMod(f->mid.low.low, frobenius_constant_1[4], curve.q);
 | 
						|
 | 
						|
		f->low.high.high = Big8wMultMod(f->low.high.high, frobenius_constant_1[3], curve.q);
 | 
						|
		f->low.high.low = Big8wMultMod(f->low.high.low, frobenius_constant_1[2], curve.q);
 | 
						|
		f->low.low.high = Big8wMultMod(f->low.low.high, frobenius_constant_1[1], curve.q);
 | 
						|
		f->low.low.low = Big8wMultMod(f->low.low.low, frobenius_constant_1[0], curve.q);
 | 
						|
	}
 | 
						|
 | 
						|
	else if (flag == 2) {
 | 
						|
 | 
						|
		f->high.high.high = Big8wMultMod(f->high.high.high, frobenius_constant_2[11], curve.q);
 | 
						|
		f->high.high.low = Big8wMultMod(f->high.high.low, frobenius_constant_2[10], curve.q);
 | 
						|
		f->high.low.high = Big8wMultMod(f->high.low.high, frobenius_constant_2[9], curve.q);
 | 
						|
		f->high.low.low = Big8wMultMod(f->high.low.low, frobenius_constant_2[8], curve.q);
 | 
						|
 | 
						|
		f->mid.high.high = Big8wMultMod(f->mid.high.high, frobenius_constant_2[7], curve.q);
 | 
						|
		f->mid.high.low = Big8wMultMod(f->mid.high.low, frobenius_constant_2[6], curve.q);
 | 
						|
		f->mid.low.high = Big8wMultMod(f->mid.low.high, frobenius_constant_2[5], curve.q);
 | 
						|
		f->mid.low.low = Big8wMultMod(f->mid.low.low, frobenius_constant_2[4], curve.q);
 | 
						|
 | 
						|
		f->low.high.high = Big8wMultMod(f->low.high.high, frobenius_constant_2[3], curve.q);
 | 
						|
		f->low.high.low = Big8wMultMod(f->low.high.low, frobenius_constant_2[2], curve.q);
 | 
						|
		f->low.low.high = Big8wMultMod(f->low.low.high, frobenius_constant_2[1], curve.q);
 | 
						|
		f->low.low.low = Big8wMultMod(f->low.low.low, frobenius_constant_2[0], curve.q);
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	else if (flag == 6) {
 | 
						|
		f->high.high.high = Big8wMinusMod(curve.q, f->high.high.high, curve.q);
 | 
						|
		f->high.high.low = Big8wMinusMod(curve.q, f->high.high.low, curve.q);
 | 
						|
 | 
						|
		f->mid.low.high = Big8wMinusMod(curve.q, f->mid.low.high, curve.q);
 | 
						|
		f->mid.low.low = Big8wMinusMod(curve.q, f->mid.low.low, curve.q);
 | 
						|
 | 
						|
		f->low.high.high = Big8wMinusMod(curve.q, f->low.high.high, curve.q);
 | 
						|
		f->low.high.low = Big8wMinusMod(curve.q, f->low.high.low, curve.q);
 | 
						|
	}
 | 
						|
}
 | 
						|
/**
 | 
						|
 * 
 | 
						|
 * @brief compute Frobenius(Q)
 | 
						|
 *		  Q = Q(x, y), point in group G2;first convert x, y to q12 number:(x*beta^(-1/2), y*beta(-1/3))
 | 
						|
 *        then run Q12Frobenius, last convert back to G2point(ret.x*(beta^(1/2)), ret.y*(beta^(1/3)))
 | 
						|
 * 
 | 
						|
 * @param Q point in group G2
 | 
						|
 * @param Q1 pointer of a point in group G2, store the result
 | 
						|
 * @param flag power of frobenius
 | 
						|
 * 
 | 
						|
 * @result Q1
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void G2pointFrobenius(G2point Q, G2point* Q1, uint8_t flag)
 | 
						|
{
 | 
						|
	q12 temp, ret;
 | 
						|
	
 | 
						|
	Q12Zero(&temp);
 | 
						|
	Q12Zero(&ret);
 | 
						|
 | 
						|
	ret.low.low = Q.x;
 | 
						|
	temp.mid.high.high = qnr;
 | 
						|
	ret = Q12MultMod(ret, temp);
 | 
						|
	Q12Frobenius(&ret, flag);
 | 
						|
	memset(temp.mid.high.high.word, 0x00, BIG8W_BYTESIZE);
 | 
						|
	temp.high.low.low.word[0] = 1;
 | 
						|
	ret = Q12MultMod(ret, temp);
 | 
						|
	Q1->x = ret.low.low;
 | 
						|
 | 
						|
	Q12Zero(&ret);
 | 
						|
	Q12Zero(&temp);
 | 
						|
 | 
						|
	ret.low.low = Q.y;
 | 
						|
	temp.low.high.high = qnr;
 | 
						|
	ret = Q12MultMod(ret, temp);
 | 
						|
	Q12Frobenius(&ret, flag);
 | 
						|
	memset(temp.low.high.high.word, 0x00, BIG8W_BYTESIZE);
 | 
						|
	temp.low.high.low.word[0] = 1;
 | 
						|
	ret = Q12MultMod(ret, temp);
 | 
						|
	Q1->y = ret.low.low;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief line function defined in SM9 and a Q12MultMod
 | 
						|
 * 
 | 
						|
 * @param P a point in group G1
 | 
						|
 * @param T a pointer of a point in group G2
 | 
						|
 * @param Q a point in group G2
 | 
						|
 * @param doubleflag if (*T) == Q
 | 
						|
 * @param f a pointer of a number in Fq12, (*f) = (*f) * g(T, Q, P), g(T, Q, P) is the line function defined in SM9
 | 
						|
 * 
 | 
						|
 * @return null
 | 
						|
 * 
 | 
						|
 */
 | 
						|
void Line(G1point P, G2point* T, G2point Q, bool doubleflag, q12* f)
 | 
						|
{
 | 
						|
	q2 lambda, temp;
 | 
						|
	q12 ret;
 | 
						|
 | 
						|
	Q12Zero(&ret);
 | 
						|
	Q2Zero(&temp);
 | 
						|
 | 
						|
	if (doubleflag) {
 | 
						|
 | 
						|
		if (Q2Equal(&Q.x, &temp) && Q2Equal(&Q.y, &temp)) // Q = T = O
 | 
						|
			return;
 | 
						|
 | 
						|
		lambda = Q2Mult(Q.x, Q.x);
 | 
						|
		lambda = Q2Add(lambda, Q2Add(lambda, lambda));
 | 
						|
		lambda = Q2Mult(
 | 
						|
			lambda,
 | 
						|
			Q2Reverse(Q2Add(Q.y, Q.y)));
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		if (Q2Equal(&T->x, &Q.x)){
 | 
						|
			// T = -Q => T = T + Q = O
 | 
						|
			Q2Zero(&T->x), Q2Zero(&T->y);
 | 
						|
			// g(T, Q, P) = xP - xQ
 | 
						|
			temp.high = qnr;
 | 
						|
			temp = Q2Mult(temp, Q.x);
 | 
						|
			temp = Q2Negate(temp);
 | 
						|
			ret.mid.high = temp;
 | 
						|
			ret.low.low.low = P.x;
 | 
						|
 | 
						|
			*f = Q12MultMod(*f, ret);
 | 
						|
		}
 | 
						|
		else if (Q2Equal(&T->x, &temp) && Q2Equal(&T->y, &temp)){ // T = O
 | 
						|
			// g(U, V, O) = 1 => f * g(U, V, O) = f; *T = T + Q = Q
 | 
						|
			*T = Q;
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		else if (Q2Equal(&Q.x, &temp) && Q2Equal(&Q.y, &temp)){ // Q = O
 | 
						|
			// g(U, V, O) = 1 => f * g(U, V, O) = f; *T = T + Q = T
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		
 | 
						|
		lambda = Q2Mult(
 | 
						|
			Q2Minus(T->y, Q.y),
 | 
						|
			Q2Reverse(Q2Minus(T->x, Q.x)));
 | 
						|
	}
 | 
						|
 | 
						|
	temp.high = qnr;
 | 
						|
 | 
						|
	ret.high.high = lambda;
 | 
						|
	ret.high.high.high = Big8wMultMod(ret.high.high.high, P.x, curve.q);
 | 
						|
	ret.high.high.low = Big8wMultMod(ret.high.high.low, P.x, curve.q);
 | 
						|
	ret.high.high = Q2Mult(ret.high.high, temp);
 | 
						|
 | 
						|
	ret.low.high = Q2Minus(
 | 
						|
		T->y,
 | 
						|
		Q2Mult(lambda, T->x));
 | 
						|
	ret.low.high = Q2Mult(temp, ret.low.high);
 | 
						|
 | 
						|
	ret.low.low.low = Big8wMinusMod(curve.q, P.y, curve.q);
 | 
						|
 | 
						|
	*T = G2PointAdd(Q, *T);
 | 
						|
	*f = Q12MultMod(ret, *f);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * @brief compute (f^(curve.q^(12) - 1)), called by BiLinearParing function(in topfunc.h).
 | 
						|
 * 
 | 
						|
 * @param f a pointer of a number in Fq12
 | 
						|
 * 
 | 
						|
 * @return null, result stored in *f.
 | 
						|
 * 
 | 
						|
 */
 | 
						|
// t = 0x60000000 0058F98A
 | 
						|
void LastPower(q12* f)
 | 
						|
{
 | 
						|
	q12 m, g, s, temp;
 | 
						|
 | 
						|
	m = Q12Reverse(*f);
 | 
						|
	Q12Frobenius(f, 6);
 | 
						|
	// f = f^(q^6 - 1)
 | 
						|
	*f = Q12MultMod(*f, m);
 | 
						|
	m = *f;
 | 
						|
	Q12Frobenius(f, 2);
 | 
						|
	*f = Q12MultMod(*f, m);  // f = f^(q^6 - 1)(q^2+1)
 | 
						|
	s = *f;  
 | 
						|
 | 
						|
	// hard part
 | 
						|
	s = *f;
 | 
						|
	m = s, temp = m;
 | 
						|
	Q12Frobenius(&temp, 1);
 | 
						|
	s = temp;
 | 
						|
	Q12Frobenius(&temp, 1);
 | 
						|
	s = Q12MultMod(s, temp);
 | 
						|
	Q12Frobenius(&temp, 1);
 | 
						|
	s = Q12MultMod(s, temp);
 | 
						|
 | 
						|
	temp = Q12PowerMod(m, t);
 | 
						|
	temp = Q12PowerMod(temp, t);
 | 
						|
 | 
						|
	g = Q12MultMod(temp, temp);
 | 
						|
	temp = Q12MultMod(g, g);
 | 
						|
	temp = Q12MultMod(temp, g);
 | 
						|
	Q12Frobenius(&temp, 2);
 | 
						|
 | 
						|
	s = Q12MultMod(s, temp);
 | 
						|
 | 
						|
	temp = m;
 | 
						|
	Q12Frobenius(&temp, 6);
 | 
						|
	temp = Q12MultMod(temp, temp);
 | 
						|
	s = Q12MultMod(s, temp);
 | 
						|
	g = temp;
 | 
						|
 | 
						|
	temp = Q12MultMod(g, g);
 | 
						|
	g = Q12MultMod(temp, g);
 | 
						|
	g = Q12PowerMod(g, t);
 | 
						|
	
 | 
						|
	temp = Q12MultMod(g, g);
 | 
						|
	s = Q12MultMod(s, Q12MultMod(temp, g));
 | 
						|
	Q12Frobenius(&temp, 1);
 | 
						|
	s = Q12MultMod(s, temp);
 | 
						|
 | 
						|
	g = Q12PowerMod(g, t);
 | 
						|
	temp = Q12MultMod(g, g);
 | 
						|
	m = Q12MultMod(g, temp);
 | 
						|
	s = Q12MultMod(s, m);
 | 
						|
	s = Q12MultMod(s, temp); 
 | 
						|
	g = m;
 | 
						|
	Q12Frobenius(&m, 1);
 | 
						|
	s = Q12MultMod(s, m);
 | 
						|
 | 
						|
	g = Q12MultMod(g, g);
 | 
						|
	g = Q12PowerMod(g, t);
 | 
						|
 | 
						|
	s = Q12MultMod(s, g);
 | 
						|
	Q12Frobenius(&g, 1);
 | 
						|
	s = Q12MultMod(s, g);
 | 
						|
 | 
						|
	*f = s;;
 | 
						|
} |