package im.actor.runtime.crypto.primitives.kuznechik; // Disabling Bounds checks for speeding up calculations /*-[ #define J2OBJC_DISABLE_ALL_CHECKS 1 ]-*/ /** * Mathematical methods for Kuzhechik encryption * <p> * Ported by Steven Kite (steve@actor.im) from * https://github.com/mjosaarinen/kuznechik/blob/master/kuznechik_8bit.c * Multiplication optimization from * http://www.cs.utsa.edu/~wagner/laws/FFM.html */ class KuznechikMath { // poly multiplication mod p(x) = x^8 + x^7 + x^6 + x + 1 // totally not constant time public static byte kuz_mul_gf256(byte x, byte y) { // uint8_t z; // z = 0; byte z = 0; // while (y) { while ((y & 0xFF) != 0) { // if (y & 1) if ((y & 1) != 0) { // z ^= x; z ^= x; } // x = (x << 1) ^ (x & 0x80 ? 0xC3 : 0x00); x = (byte) (((x & 0xFF) << 1) ^ ((x & 0x80) != 0 ? 0xC3 : 0x00)); // y >>= 1; y = (byte) ((y & 0xFF) >> 1); } // return z; return z; } // Fast implementation of multiplication in GF(2^8) on x^8 + x^7 + x^6 + x + 1 // Implemented with public static byte kuz_mul_gf256_fast(byte a, byte b) { if (a == 0 || b == 0) return 0; int t = (KuznechikTables.gf256_L[(a & 0xff)] & 0xff) + (KuznechikTables.gf256_L[(b & 0xff)] & 0xff); if (t > 255) t = t - 255; return KuznechikTables.gf256_E[(t & 0xff)]; } // linear operation l // static void kuz_l(w128_t *w) public static void kuz_l(Kuz128 w) { // 16 rounds for (int j = 0; j < 16; j++) { // An LFSR with 16 elements from GF(2^8) // x = w->b[15]; // since lvec[15] = 1 byte x = w.getB()[15]; for (int i = 14; i >= 0; i--) { // w->b[i + 1] = w->b[i]; w.getB()[i + 1] = w.getB()[i]; // x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); x ^= kuz_mul_gf256_fast(w.getB()[i], KuznechikTables.kuz_lvec[i]); } w.getB()[0] = x; } } // inverse of linear operation l public static void kuz_l_inv(Kuz128 w) { // 16 rounds for (int j = 0; j < 16; j++) { // x = w->b[0]; byte x = w.getB()[0]; for (int i = 0; i < 15; i++) { // w->b[i] = w->b[i + 1]; w.getB()[i] = w.getB()[i + 1]; // x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); x ^= kuz_mul_gf256_fast(w.getB()[i], KuznechikTables.kuz_lvec[i]); } // w->b[15] = x; w.getB()[15] = x; } } }