ta/wallet_ta.c
/**
  * Multiplies (r = op1 x op2) two multi-precision numbers of arbitrary size,
  * ignoring the current prime finite field. In other words, this does
  * multi-precision binary multiplication. It is to be used
  * internally (only by the functions of the TA itself).
  * \param r The result will be written into here. The size of the result (in
  *          number of bytes) will be op1_size + op2_size.
  * \param op1 The first operand to multiply. This cannot alias r.
  * \param op1_size The size, in number of bytes, of op1.
  * \param op2 The second operand to multiply. This cannot alias r, but it can
  *            alias op1.
  * \param op2_size The size, in number of bytes, of op2.
  * \warning This function is the speed bottleneck in an ECDSA signing
  *          operation. To speed up ECDSA signing, reimplement this in
  *          assembly and define PLATFORM_SPECIFIC_BIGMULTIPLY.
  */
Multiplies (r = op1 x op2) two multi-precision numbers of arbitrary size,
ignoring the current prime finite field. In other words, this does
multi-precision binary multiplication. It is to be used
internally (only by the functions of the TA itself).
\param r The result will be written into here. The size of the result (in
number of bytes) will be op1_size + op2_size.
\param op1 The first operand to multiply. This cannot alias r.
\param op1_size The size, in number of bytes, of op1.
\param op2 The second operand to multiply. This cannot alias r, but it can
alias op1.
\param op2_size The size, in number of bytes, of op2.
\warning This function is the speed bottleneck in an ECDSA signing
operation. To speed up ECDSA signing, reimplement this in
assembly and define PLATFORM_SPECIFIC_BIGMULTIPLY.
Multiplies ( r = op1 x op2 ) two multi - precision numbers of arbitrary size ignoring the current prime finite field . In other words this does multi - precision binary multiplication . It is to be used internally ( only by the functions of the TA itself ) . \ param r The result will be written into here . The size of the result ( in number of bytes ) will be op1_size + op2_size . \ param op1 The first operand to multiply . This cannot alias r . \ param op1_size The size in number of bytes of op1 . \ param op2 The second operand to multiply . This cannot alias r but it can alias op1 . \ param op2_size The size in number of bytes of op2 . \ warning This function is the speed bottleneck in an ECDSA signing operation . To speed up ECDSA signing reimplement this in assembly and define PLATFORM_SPECIFIC_BIGMULTIPLY .
static void big_multiply_variable_size_no_modulo_internal(uint8_t *r, uint8_t *op1, uint8_t op1_size, uint8_t *op2, uint8_t op2_size)
{
	uint8_t cached_op1;
	uint8_t low_carry;
	uint8_t high_carry;
	uint16_t multiply_result16;
	uint8_t multiply_result_low8;
	uint8_t multiply_result_high8;
	uint16_t partial_sum;
	uint8_t i;
	uint8_t j;
	TEE_MemFill((uint8_t*)r, (uint32_t)0, (uint32_t)(op1_size + op2_size));
	for (i = 0; i < op1_size; i++)
	{
		cached_op1 = op1[i];
		high_carry = 0;
		for (j = 0; j < op2_size; j++)
		{
			multiply_result16 = (uint16_t)((uint16_t)cached_op1 * (uint16_t)op2[j]);
			multiply_result_low8 = (uint8_t)multiply_result16;
			multiply_result_high8 = (uint8_t)(multiply_result16 >> 8);
			partial_sum = (uint16_t)((uint16_t)r[i + j] + (uint16_t)multiply_result_low8);
			r[i + j] = (uint8_t)partial_sum;
			low_carry = (uint8_t)(partial_sum >> 8);
			partial_sum = (uint16_t)((uint16_t)r[i + j + 1] + (uint16_t)multiply_result_high8 + (uint16_t)low_carry + (uint16_t)high_carry);
			r[i + j + 1] = (uint8_t)partial_sum;
			high_carry = (uint8_t)(partial_sum >> 8);
		}
	}
}
static void big_multiply_variable_size_no_modulo_internal ( uint8_t * r , uint8_t * op1 , uint8_t op1_size , uint8_t * op2 , uint8_t op2_size ) { uint8_t cached_op1 ; uint8_t low_carry ; uint8_t high_carry ; uint16_t multiply_result16 ; uint8_t multiply_result_low8 ; uint8_t multiply_result_high8 ; uint16_t partial_sum ; uint8_t i ; uint8_t j ; TEE_MemFill ( ( uint8_t * ) r , ( uint32_t ) 0 , ( uint32_t ) ( op1_size + op2_size ) ) ; for ( i = 0 ; i < op1_size ; i ++ ) { cached_op1 = op1 [ i ] ; high_carry = 0 ; for ( j = 0 ; j < op2_size ; j ++ ) { multiply_result16 = ( uint16_t ) ( ( uint16_t ) cached_op1 * ( uint16_t ) op2 [ j ] ) ; multiply_result_low8 = ( uint8_t ) multiply_result16 ; multiply_result_high8 = ( uint8_t ) ( multiply_result16 >> 8 ) ; partial_sum = ( uint16_t ) ( ( uint16_t ) r [ i + j ] + ( uint16_t ) multiply_result_low8 ) ; r [ i + j ] = ( uint8_t ) partial_sum ; low_carry = ( uint8_t ) ( partial_sum >> 8 ) ; partial_sum = ( uint16_t ) ( ( uint16_t ) r [ i + j + 1 ] + ( uint16_t ) multiply_result_high8 + ( uint16_t ) low_carry + ( uint16_t ) high_carry ) ; r [ i + j + 1 ] = ( uint8_t ) partial_sum ; high_carry = ( uint8_t ) ( partial_sum >> 8 ) ; } } }
Multiplies (r = op1 x op2) two multi-precision numbers of arbitrary size,
 ignoring the current prime finite field.
Multiplies ( r = op1 x op2 ) two multi - precision numbers of arbitrary size ignoring the current prime finite field .
/*
	 * The multiplication algorithm here is what GMP calls the "schoolbook"
	 * method. It's also sometimes referred to as "long multiplication". It's
	 * the most straightforward method of multiplication.
	 * Note that for the operand sizes this function typically deals with,
	 * and with the platforms this code is intended to run on, the Karatsuba
	 * algorithm isn't significantly better.
	 */ /*
		assert(high_carry == 0);
		*/