/*
*******************************************************************************
* Java Card Bitcoin Hardware Wallet
* (c) 2015 Ledger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************
*/
package com.ledger.wallet;
class MathMod256 {
/** c = a+b mod n
*
* a,b,n 256 unsigned bits value
* precondition:
* 0 <= a < n
* 0 <= b < n
* n > 0
* c shall either NOT partially overlap a or b, or shall be a or b
*
*/
public static void addm(byte[] c, short c_off,
byte[] a, short a_off,byte[] b, short b_off,
byte[] n, short n_off) {
if ((add(c, c_off,a, a_off, b, b_off) != 0) ||
(ucmp(c, c_off, n,n_off) > 0)) {
sub(c, c_off, c, c_off, n, n_off);
}
}
/** unsigned compare a and b
* return 0 if a == b
* return < 0 if a < b
* return > 0 if a > b
*/
public static short ucmp(byte[] a, short a_off, byte[] b, short b_off) {
short ai, bi;
for (short i =0; i<32; i++) {
ai = (short)(a[(short)(a_off+i)] & 0x00ff);
bi = (short)(b[(short)(b_off+i)] & 0x00ff);
if (ai!=bi) {
return (short)(ai-bi);
}
}
return 0;
}
protected static short add(byte[] c, short c_off,
byte[] a, short a_off, byte[] b, short b_off) {
short ci = 0;
for (short i = 31 ; i >= 0 ; i--) {
ci = (short) ((short)(a[(short)(a_off+i)]&0x00FF) + (short)(b[(short)(b_off+i)]&0xFF) + ci);
c[(short)(c_off+i)] = (byte)ci ;
ci = (short)(ci >> 8);
}
return ci;
}
protected static short sub(byte[] c, short c_off,
byte[] a, short a_off, byte[] b, short b_off) {
short ci = 0;
for (short i = 31 ; i >= 0 ; i--) {
ci = (short) ((short)(a[(short)(a_off+i)]&0xFF) - (short)(b[(short)(b_off+i)]&0xFF) - ci);
c[(short)(c_off+i)] = (byte)ci ;
ci = (short)(((ci >> 8) != 0) ? 1:0);
}
return ci;
}
}