static void setup(ulong32 *dk, ulong32 *k, ulong32 *uk) { int n, t; ulong32 p[2]; p[0] = dk[0]; p[1] = dk[1]; t = 4; n = 0; pi1(p); pi2(p, k); uk[n++] = p[0]; pi3(p, k); uk[n++] = p[1]; pi4(p, k); uk[n++] = p[0]; pi1(p); uk[n++] = p[1]; pi2(p, k+t); uk[n++] = p[0]; pi3(p, k+t); uk[n++] = p[1]; pi4(p, k+t); uk[n++] = p[0]; pi1(p); uk[n++] = p[1]; }
void KisStrokeBenchmark::benchmarkRandomLines(QString presetFileName) { KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName); bool loadedOk = preset->load(); if (!loadedOk){ dbgKrita << "The preset was not loaded correctly. Done."; return; }else{ dbgKrita << "preset : " << presetFileName; } m_painter->setPaintOpPreset(preset, m_layer, m_image); QBENCHMARK{ KisDistanceInformation currentDistance; for (int i = 0; i < LINES; i++){ KisPaintInformation pi1(m_startPoints[i], 0.0); KisPaintInformation pi2(m_endPoints[i], 1.0); m_painter->paintLine(pi1, pi2, ¤tDistance); } } #ifdef SAVE_OUTPUT m_layer->paintDevice()->convertToQImage(0).save(m_outputPath + presetFileName + "_randomLines" + OUTPUT_FORMAT); #endif }
static void noekeon_round(uint32_t *key, uint32_t *state, uint8_t const1, uint8_t const2){ ((uint8_t*)state)[RC_POS] ^= const1; theta(key, state); ((uint8_t*)state)[RC_POS] ^= const2; pi1(state); gamma_1(state); pi2(state); }
static void encrypt(ulong32 *p, int N, ulong32 *uk) { int n, t; for (t = n = 0; ; ) { pi1(p); if (++n == N) break; pi2(p, uk+t); if (++n == N) break; pi3(p, uk+t); if (++n == N) break; pi4(p, uk+t); if (++n == N) break; t ^= 4; } }
static void decrypt(ulong32 *p, int N, ulong32 *uk) { int n, t; for (t = 4*((N&1)^1), n = N; ; ) { switch (n >= 4 ? 4 : 0) { case 4: pi4(p, uk+t); --n; case 3: pi3(p, uk+t); --n; case 2: pi2(p, uk+t); --n; case 1: pi1(p); --n; break; case 0: return; } t ^= 4; } }
static bool IsQuadrangle(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) { cv::Point2d pi1((int)p1.x, (int)p1.y); cv::Point2d pi2((int)p2.x, (int)p2.y); cv::Point2d pi3((int)p3.x, (int)p3.y); cv::Point2d pi4((int)p4.x, (int)p4.y); return !(IsOverlapped(pi1, pi2) || IsOverlapped(pi1, pi3) || IsOverlapped(pi1, pi4) || IsOverlapped(pi2, pi3) || IsOverlapped(pi2, pi4) || IsOverlapped(pi3, pi4) || IsLine(pi1, pi2, pi3) || IsLine(pi1, pi2, pi4) || IsLine(pi2, pi3, pi4)); }
void ofDrawRectOutline(const ofRectangle & rect, int thickness, ofDrawRectOutlineMode mode) { float b0, b1; if(mode == ofDrawRectOutlineModeOuter) { b0 = thickness; b1 = 0; } else if(mode == ofDrawRectOutlineModeInner) { b0 = 0; b1 = thickness; } else if(mode == ofDrawRectOutlineModeMiddle) { b0 = thickness * 0.5; b1 = thickness * 0.5; } ofVec2f po0(rect.x - b0, rect.y - b0); ofVec2f po1(rect.x + rect.width + b0, rect.y - b0); ofVec2f po2(rect.x + rect.width + b0, rect.y + rect.height + b0); ofVec2f po3(rect.x - b0, rect.y + rect.height + b0); ofVec2f pi0(rect.x + b1, rect.y + b1); ofVec2f pi1(rect.x + rect.width - b1, rect.y + b1); ofVec2f pi2(rect.x + rect.width - b1, rect.y + rect.height - b1); ofVec2f pi3(rect.x + b1, rect.y + rect.height - b1); ofBeginShape(); ofVertex(po0.x, po0.y); ofVertex(po1.x, po1.y); ofVertex(po2.x, po2.y); ofVertex(po3.x, po3.y); ofNextContour(); ofVertex(pi0.x, pi0.y); ofVertex(pi1.x, pi1.y); ofVertex(pi2.x, pi2.y); ofVertex(pi3.x, pi3.y); ofEndShape(true); }
inline void KisStrokeBenchmark::benchmarkLine(QString presetFileName) { KisPaintOpPresetSP preset = new KisPaintOpPreset(m_dataPath + presetFileName); preset->load(); m_painter->setPaintOpPreset(preset, m_layer, m_image); QPointF startPoint(0.10 * TEST_IMAGE_WIDTH, 0.5 * TEST_IMAGE_HEIGHT); QPointF endPoint(0.90 * TEST_IMAGE_WIDTH, 0.5 * TEST_IMAGE_HEIGHT); KisDistanceInformation currentDistance; KisPaintInformation pi1(startPoint, 0.0); KisPaintInformation pi2(endPoint, 1.0); QBENCHMARK{ m_painter->paintLine(pi1, pi2, ¤tDistance); } #ifdef SAVE_OUTPUT m_layer->paintDevice()->convertToQImage(0).save(m_outputPath + presetFileName + "_line" + OUTPUT_FORMAT); #endif }
/** * This benchmark runs a series of huge strokes on a canvas with a * particular configuration of the swapper/pooler and history * management. After the test is done you can visualize the results * with the GNU Octave. Please use kis_low_memory_show_report.m file * for that. */ void KisLowMemoryBenchmark::benchmarkWideArea(const QString presetFileName, const QRectF &rect, qreal vstep, int numCycles, bool createTransaction, int hardLimitMiB, int softLimitMiB, int poolLimitMiB, int index) { KisPaintOpPresetSP preset = new KisPaintOpPreset(QString(FILES_DATA_DIR) + QDir::separator() + presetFileName); LOAD_PRESET_OR_RETURN(preset, presetFileName); /** * Initialize image and painter */ const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, HUGE_IMAGE_SIZE, HUGE_IMAGE_SIZE, colorSpace, "stroke sample image", true); KisLayerSP layer = new KisPaintLayer(image, "temporary for stroke sample", OPACITY_OPAQUE_U8, colorSpace); KisLayerSP layerExtra = new KisPaintLayer(image, "temporary for threading", OPACITY_OPAQUE_U8, colorSpace); image->addNode(layer, image->root()); image->addNode(layerExtra, image->root()); KisPainter *painter = new KisPainter(layer->paintDevice()); painter->setPaintColor(KoColor(Qt::black, colorSpace)); painter->setPaintOpPreset(preset, layer, image); /** * A simple adapter that will store all the transactions for us */ KisSurrogateUndoAdapter undoAdapter; /** * Reset configuration to the desired settings */ KisImageConfig config; qreal oldHardLimit = config.memoryHardLimitPercent(); qreal oldSoftLimit = config.memorySoftLimitPercent(); qreal oldPoolLimit = config.memoryPoolLimitPercent(); const qreal _MiB = 100.0 / KisImageConfig::totalRAM(); config.setMemoryHardLimitPercent(hardLimitMiB * _MiB); config.setMemorySoftLimitPercent(softLimitMiB * _MiB); config.setMemoryPoolLimitPercent(poolLimitMiB * _MiB); KisTileDataStore::instance()->testingRereadConfig(); /** * Create an empty the log file */ QString fileName; fileName = QString("log_%1_%2_%3_%4_%5.txt") .arg(createTransaction) .arg(hardLimitMiB) .arg(softLimitMiB) .arg(poolLimitMiB) .arg(index); QFile logFile(fileName); logFile.open(QFile::WriteOnly | QFile::Truncate); QTextStream logStream(&logFile); logStream.setFieldWidth(10); logStream.setFieldAlignment(QTextStream::AlignRight); /** * Start painting on the image */ QTime cycleTime; QTime lineTime; cycleTime.start(); lineTime.start(); qreal rectBottom = rect.y() + rect.height(); for (int i = 0; i < numCycles; i++) { cycleTime.restart(); QLineF line(rect.topLeft(), rect.topLeft() + QPointF(rect.width(), 0)); if (createTransaction) { painter->beginTransaction(); } KisDistanceInformation currentDistance; while(line.y1() < rectBottom) { lineTime.restart(); KisPaintInformation pi1(line.p1(), 0.0); KisPaintInformation pi2(line.p2(), 1.0); painter->paintLine(pi1, pi2, ¤tDistance); painter->device()->setDirty(painter->takeDirtyRegion()); logStream << "L 1" << i << lineTime.elapsed() << KisTileDataStore::instance()->numTilesInMemory() * 16 << KisTileDataStore::instance()->numTiles() * 16 << createTransaction << endl; line.translate(0, vstep); } painter->device()->setDirty(painter->takeDirtyRegion()); if (createTransaction) { painter->endTransaction(&undoAdapter); } // comment/uncomment to emulate user waiting after the stroke QTest::qSleep(1000); logStream << "C 2" << i << cycleTime.elapsed() << KisTileDataStore::instance()->numTilesInMemory() * 16 << KisTileDataStore::instance()->numTiles() * 16 << createTransaction << config.memoryHardLimitPercent() / _MiB << config.memorySoftLimitPercent() / _MiB << config.memoryPoolLimitPercent() / _MiB << endl; } config.setMemoryHardLimitPercent(oldHardLimit * _MiB); config.setMemorySoftLimitPercent(oldSoftLimit * _MiB); config.setMemoryPoolLimitPercent(oldPoolLimit * _MiB); delete painter; }
// Decryption and Verification procedure int crypto_aead_decrypt( unsigned char *m, unsigned long long *mlen, unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k ) { //... //... the code for the cipher implementation goes here, //... generating a plaintext m[0],m[1],...,m[*mlen-1] //... and secret message number nsec[0],nsec[1],... //... from a ciphertext c[0],c[1],...,c[clen-1] //... and associated data ad[0],ad[1],...,ad[adlen-1] //... and public message number npub[0],npub[1],... //... and secret key k[0],k[1],... //... // some 64-bit temp variables u_int64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13; // more 64-bit temp variables u_int64_t x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3; // more 64-bit temp variables u_int64_t pom1, pom2, pom3, pom4, nu1, nu2, nu3, nu4; // more 64-bit temp variables u_int64_t IS0, IS1, IS2, IS3, IS4, IS5, IS6, IS7, IS8, IS9, IS10, IS11, IS12, IS13, IS14, IS15; // more 64-bit temp variables u_int64_t preCompIS0, preCompIS1, preCompIS2, preCompIS3, preCompIS4, preCompIS5, preCompIS6, preCompIS7, preCompIS8, preCompIS9, preCompIS10, preCompIS11, preCompIS12, preCompIS13, preCompIS14, preCompIS15; // pointers to 64-bit variables u_int64_t *c64, *m64, *ad64, *nsec64, *npub64, *k64; // an array for storing some temporal values for the Tag computation u_int64_t tempTag[CRYPTO_ABYTES / W] = { 0 }; // counter ctr is a 64-bit variable in all variants of PiCipher u_int64_t ctr = 0x0000000000000000ull; // an array for the Common Internal State u_int64_t CIS[IS_SIZE] = { 0 }; u_int64_t CIS1[IS_SIZE] = { 0 }; // pointers that look at the used data arrays as arrays of bytes u_int8_t *InternalState8, *CommonInternalState8, *tempTag8; // variables for dealing with various lengths of the plaintext and associated data int LastMessageChunkLength, LastADChunkLength; // different iterator variables unsigned long long i, j, jj, ii, b, i1, j1, a, cblocks, ii1, ii2, b1; c64 = (u_int64_t *)c; m64 = (u_int64_t *)m; ad64 = (u_int64_t *)ad; nsec64 = (u_int64_t *)nsec; npub64 = (u_int64_t *)npub; k64 = (u_int64_t *)k; InternalState8 = (u_int8_t *)IS; CommonInternalState8 = (u_int8_t *)CIS; tempTag8 = (u_int8_t *)tempTag; // phase 1: Initialization /* for (i = 0; i < IS_SIZE; i++) { IS[i] = 0; } */ IS[0] = 0; IS[1] = 0; IS[2] = 0; IS[3] = 0; IS[4] = 0; IS[5] = 0; IS[6] = 0; IS[7] = 0; IS[8] = 0; IS[9] = 0; IS[10] = 0; IS[11] = 0; IS[12] = 0; IS[13] = 0; IS[14] = 0; IS[15] = 0; // injection of the key /*for (i = 0; i < CRYPTO_KEYBYTES; i++) { InternalState8[i] = k[i]; }*/ IS[0] = k64[0]; IS[1] = k64[1]; IS[2] = k64[2]; IS[3] = k64[3]; // injection of the nonce (public message number - PMN) /*for (j = 0; j < CRYPTO_NPUBBYTES; j++) { InternalState8[i++] = npub[j]; }*/ IS[4] = npub64[0]; IS[5] = npub64[1]; // appending a single 1 to the concatenated value of the key and PMN InternalState8[48] = 0x01; // applying the permutation function pi pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // initialization of the Common Internal State (CIS), common for all parallel invocations of pi() with different ctrs /* for (i = 0; i < IS_SIZE; i++) { CIS[i] = IS[i]; } */ CIS[0] = IS[0]; CIS[1] = IS[1]; CIS[2] = IS[2]; CIS[3] = IS[3]; CIS[4] = IS[4]; CIS[5] = IS[5]; CIS[6] = IS[6]; CIS[7] = IS[7]; CIS[8] = IS[8]; CIS[9] = IS[9]; CIS[10] = IS[10]; CIS[11] = IS[11]; CIS[12] = IS[12]; CIS[13] = IS[13]; CIS[14] = IS[14]; CIS[15] = IS[15]; // initialization of the ctr obtained from the first 64 bits of the capacity of CIS ctr = CIS[4]; // phase 2: Processing the associated data nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS1[4], CIS1[5], CIS1[6], CIS1[7]); nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS1[8], CIS1[9], CIS1[10], CIS1[11]); nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS1[12], CIS1[13], CIS1[14], CIS1[15]); nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3]; nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3]; nu2 = rotl64((nu2), 23); nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2]; nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3]; b = 0; a = adlen / RATE; for (j = 0; j < a; j++) { // IS for the triplex component is initialized by the CIS for every AD block /* for (i = 0; i < IS_SIZE; i++) { IS[i] = CIS[i]; } */ IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS1[4]; IS[5] = CIS1[5]; IS[6] = CIS1[6]; IS[7] = CIS1[7]; IS[8] = CIS1[8]; IS[9] = CIS1[9]; IS[10] = CIS1[10]; IS[11] = CIS1[11]; IS[12] = CIS1[12]; IS[13] = CIS1[13]; IS[14] = CIS1[14]; IS[15] = CIS1[15]; ctr++; // Inject ctr + j in IS IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); //pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // process the AD block // Inject the AD block /* for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { IS[ii1] = IS[ii1] ^ ad64[b]; b++; ii1++; } } */ IS[0] = IS[0] ^ ad64[b]; b++; IS[1] = IS[1] ^ ad64[b]; b++; IS[2] = IS[2] ^ ad64[b]; b++; IS[3] = IS[3] ^ ad64[b]; b++; IS[8] = IS[8] ^ ad64[b]; b++; IS[9] = IS[9] ^ ad64[b]; b++; IS[10] = IS[10] ^ ad64[b]; b++; IS[11] = IS[11] ^ ad64[b]; b++; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // Collect the tag for this block // Sum of the tags componentwise, where the length of one component is W /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { tempTag[jj] = tempTag[jj] + IS[ii1]; jj++; ii1++; } } */ tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } // if the last AD block is not the full block, we process it byte by byte LastADChunkLength = adlen % RATE; if (LastADChunkLength) { b = b * W; i1 = 0; /* for (i = 0; i < IS_SIZE; i++) { IS[i] = CIS[i]; } */ IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS1[4]; IS[5] = CIS1[5]; IS[6] = CIS1[6]; IS[7] = CIS1[7]; IS[8] = CIS1[8]; IS[9] = CIS1[9]; IS[10] = CIS1[10]; IS[11] = CIS1[11]; IS[12] = CIS1[12]; IS[13] = CIS1[13]; IS[14] = CIS1[14]; IS[15] = CIS1[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); //pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); for (i = 0; i < LastADChunkLength; i++) { InternalState8[i1] = InternalState8[i1] ^ ad[b]; i1++; if (i1 % (RATE_OUT) == 0) i1 += RATE_OUT; b++; } // padding with 10* InternalState8[i1] = InternalState8[i1] ^ 0x01; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); //updating the tag /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { tempTag[jj] = tempTag[jj] + IS[ii1]; jj++; ii1++; } } */ tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } // if the AD is full blocks we still need to append 10* and it is done in an additional block else { IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS1[4]; IS[5] = CIS1[5]; IS[6] = CIS1[6]; IS[7] = CIS1[7]; IS[8] = CIS1[8]; IS[9] = CIS1[9]; IS[10] = CIS1[10]; IS[11] = CIS1[11]; IS[12] = CIS1[12]; IS[13] = CIS1[13]; IS[14] = CIS1[14]; IS[15] = CIS1[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); // padding with 10* InternalState8[0] = InternalState8[0] ^ 0x01; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); //updating the tag tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } // updating the Common Internal State by injection of the tag (tempTag) obtained from the associated data /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; ii2 = (i + 1) * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { IS[ii1] = CIS[ii1] ^ tempTag[jj]; IS[ii2] = CIS[ii2]; jj++; ii1++; ii2++; } } */ IS[0] = CIS[0] ^ tempTag[0]; IS[1] = CIS[1] ^ tempTag[1]; IS[2] = CIS[2] ^ tempTag[2]; IS[3] = CIS[3] ^ tempTag[3]; IS[4] = CIS[4]; IS[5] = CIS[5]; IS[6] = CIS[6]; IS[7] = CIS[7]; IS[8] = CIS[8] ^ tempTag[4]; IS[9] = CIS[9] ^ tempTag[5]; IS[10] = CIS[10] ^ tempTag[6]; IS[11] = CIS[11] ^ tempTag[7]; IS[12] = CIS[12]; IS[13] = CIS[13]; IS[14] = CIS[14]; IS[15] = CIS[15]; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); /* for (i = 0; i < IS_SIZE; i++) { CIS[i] = IS[i]; } */ CIS[0] = IS[0]; CIS[1] = IS[1]; CIS[2] = IS[2]; CIS[3] = IS[3]; CIS[4] = IS[4]; CIS[5] = IS[5]; CIS[6] = IS[6]; CIS[7] = IS[7]; CIS[8] = IS[8]; CIS[9] = IS[9]; CIS[10] = IS[10]; CIS[11] = IS[11]; CIS[12] = IS[12]; CIS[13] = IS[13]; CIS[14] = IS[14]; CIS[15] = IS[15]; // phase 3: Processing the secret message number if (CRYPTO_NSECBYTES > 0) { nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS[4], CIS[5], CIS[6], CIS[7]); nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS[8], CIS[9], CIS[10], CIS[11]); nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS[12], CIS[13], CIS[14], CIS[15]); nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3]; nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3]; nu2 = rotl64((nu2), 23); nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2]; nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3]; /* for (i = 0; i < IS_SIZE; i++) { IS[i] = CIS[i]; } */ IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS[4]; IS[5] = CIS[5]; IS[6] = CIS[6]; IS[7] = CIS[7]; IS[8] = CIS[8]; IS[9] = CIS[9]; IS[10] = CIS[10]; IS[11] = CIS[11]; IS[12] = CIS[12]; IS[13] = CIS[13]; IS[14] = CIS[14]; IS[15] = CIS[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); //pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // decrypt the SMN // Inject the SMN b = 0; /* for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { nsec64[b] = IS[ii1] ^ c64[b]; IS[ii1] = c64[b]; b++; ii1++; } } */ nsec64[b] = IS[0] ^ c64[b]; IS[0] = c64[b]; b++; nsec64[b] = IS[1] ^ c64[b]; IS[1] = c64[b]; b++; nsec64[b] = IS[2] ^ c64[b]; IS[2] = c64[b]; b++; nsec64[b] = IS[3] ^ c64[b]; IS[3] = c64[b]; b++; nsec64[b] = IS[8] ^ c64[b]; IS[8] = c64[b]; b++; nsec64[b] = IS[9] ^ c64[b]; IS[9] = c64[b]; b++; nsec64[b] = IS[10] ^ c64[b]; IS[10] = c64[b]; b++; nsec64[b] = IS[11] ^ c64[b]; IS[11] = c64[b]; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // updating the Common Internal State after decrypting the SMN /* for (i = 0; i < IS_SIZE; i++) { CIS[i] = IS[i]; } */ CIS[0] = IS[0]; CIS[1] = IS[1]; CIS[2] = IS[2]; CIS[3] = IS[3]; CIS[4] = IS[4]; CIS[5] = IS[5]; CIS[6] = IS[6]; CIS[7] = IS[7]; CIS[8] = IS[8]; CIS[9] = IS[9]; CIS[10] = IS[10]; CIS[11] = IS[11]; CIS[12] = IS[12]; CIS[13] = IS[13]; CIS[14] = IS[14]; CIS[15] = IS[15]; // Collect the tag from this encryption and update the tempTag /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { tempTag[jj] = tempTag[jj] + IS[ii1]; jj++; ii1++; } } */ tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } //phase 4: Processing the ciphertext nu64(CIS[4], CIS[5], CIS[6], CIS[7], CIS[4], CIS[5], CIS[6], CIS[7]); nu64(CIS[8], CIS[9], CIS[10], CIS[11], CIS[8], CIS[9], CIS[10], CIS[11]); nu64(CIS[12], CIS[13], CIS[14], CIS[15], CIS[12], CIS[13], CIS[14], CIS[15]); nu1 = 0x8D8B87787472716C + CIS[2] + CIS[3]; nu2 = 0x6A696665635C5A59 + CIS[1] + CIS[2] + CIS[3]; nu2 = rotl64((nu2), 23); nu3 = 0x5655534E4D4B473C + CIS[1] + CIS[2]; nu4 = 0x3A393635332E2D2B + CIS[1] + CIS[3]; cblocks = (clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES) / RATE; b = 0; b1 = bSMN; for (j = 0; j < cblocks; j++) { /* for (i = 0; i < IS_SIZE; i++) { IS[i] = CIS[i]; } */ IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS[4]; IS[5] = CIS[5]; IS[6] = CIS[6]; IS[7] = CIS[7]; IS[8] = CIS[8]; IS[9] = CIS[9]; IS[10] = CIS[10]; IS[11] = CIS[11]; IS[12] = CIS[12]; IS[13] = CIS[13]; IS[14] = CIS[14]; IS[15] = CIS[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); //pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // decrypt the ciphertext c /* for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { // XOR the IS_bitrate (InternalState[0], InternalSate[2], ...) with the c to obtain m m64[b] = IS[ii1] ^ c64[b1]; // in order to proceed for tag computation, put the ciphertext data in the InternalState IS[ii1] = c64[b1]; b++; b1++; ii1++; } } */ m64[b] = IS[0] ^ c64[b1]; IS[0] = c64[b1]; b++; b1++; m64[b] = IS[1] ^ c64[b1]; IS[1] = c64[b1]; b++; b1++; m64[b] = IS[2] ^ c64[b1]; IS[2] = c64[b1]; b++; b1++; m64[b] = IS[3] ^ c64[b1]; IS[3] = c64[b1]; b++; b1++; m64[b] = IS[8] ^ c64[b1]; IS[8] = c64[b1]; b++; b1++; m64[b] = IS[9] ^ c64[b1]; IS[9] = c64[b1]; b++; b1++; m64[b] = IS[10] ^ c64[b1]; IS[10] = c64[b1]; b++; b1++; m64[b] = IS[11] ^ c64[b1]; IS[11] = c64[b1]; b++; b1++; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // Collect the tag from this decryption and update the tempTag /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { tempTag[jj] = tempTag[jj] + IS[ii1]; jj++; ii1++; } } */ tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } // if the last ciphertext block is not the full block, we process it byte by byte LastMessageChunkLength = (clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES) % RATE; if (LastMessageChunkLength) { b = b * W; b1 = CRYPTO_NSECBYTES + b; i1 = 0; /* for (i = 0; i < IS_SIZE; i++) { IS[i] = CIS[i]; } */ IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS[4]; IS[5] = CIS[5]; IS[6] = CIS[6]; IS[7] = CIS[7]; IS[8] = CIS[8]; IS[9] = CIS[9]; IS[10] = CIS[10]; IS[11] = CIS[11]; IS[12] = CIS[12]; IS[13] = CIS[13]; IS[14] = CIS[14]; IS[15] = CIS[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); //pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); for (i = 0; i < LastMessageChunkLength; i++) { m[b] = InternalState8[i1] ^ c[b1]; InternalState8[i1] = c[b1]; i1++; if (i1 % (RATE_OUT) == 0) i1 += RATE_OUT; b++; b1++; } // padding with 10* InternalState8[i1] = InternalState8[i1] ^ 0x01; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); // updating the tag /* jj = 0; for (i = 0; i < N; i += 2) { ii1 = i * WORDS_CHUNK; for (i1 = 0; i1 < WORDS_CHUNK; i1++) { tempTag[jj] = tempTag[jj] + IS[ii1]; jj++; ii1++; } } */ tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } // if the message is full blocks we still need to append 10* and it is done in an additional block else { IS[0] = CIS[0]; IS[1] = CIS[1]; IS[2] = CIS[2]; IS[3] = CIS[3]; IS[4] = CIS1[4]; IS[5] = CIS1[5]; IS[6] = CIS1[6]; IS[7] = CIS1[7]; IS[8] = CIS1[8]; IS[9] = CIS1[9]; IS[10] = CIS1[10]; IS[11] = CIS1[11]; IS[12] = CIS1[12]; IS[13] = CIS1[13]; IS[14] = CIS1[14]; IS[15] = CIS1[15]; ctr++; IS[0] = IS[0] ^ ctr; pi1(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15], nu1, nu2, nu3, nu4); // padding with 10* InternalState8[0] = InternalState8[0] ^ 0x01; pi(IS[0], IS[1], IS[2], IS[3], IS[4], IS[5], IS[6], IS[7], IS[8], IS[9], IS[10], IS[11], IS[12], IS[13], IS[14], IS[15]); //updating the tag tempTag[0] = tempTag[0] + IS[0]; tempTag[1] = tempTag[1] + IS[1]; tempTag[2] = tempTag[2] + IS[2]; tempTag[3] = tempTag[3] + IS[3]; tempTag[4] = tempTag[4] + IS[8]; tempTag[5] = tempTag[5] + IS[9]; tempTag[6] = tempTag[6] + IS[10]; tempTag[7] = tempTag[7] + IS[11]; } //updating the length of the message *mlen = clen - CRYPTO_ABYTES - CRYPTO_NSECBYTES; // tag verification b = (*mlen + CRYPTO_NSECBYTES); for (ii = b; ii < clen; ii++) { if (c[ii] != tempTag8[ii - b]) return -1; } return 0; }
void DrrnPsiClient::recv(Channel s0, Channel s1, span<block> inputs) { if (inputs.size() != mClientSetSize) throw std::runtime_error(LOCATION); Matrix<u64> bins(mNumSimpleBins, mBinSize); std::vector<u64> binSizes(mNumSimpleBins); u64 cuckooSlotsPerBin = (mCuckooParams.numBins() + mNumSimpleBins) / mNumSimpleBins; // Simple hashing with a PRP std::vector<block> hashs(inputs.size()); AES hasher(mHashingSeed); u64 numCuckooBins = mCuckooParams.numBins(); for (u64 i = 0; i < u64(inputs.size());) { auto min = std::min<u64>(inputs.size() - i, 8); auto end = i + min; hasher.ecbEncBlocks(inputs.data() + i, min, hashs.data() + i); for (; i < end; ++i) { hashs[i] = hashs[i] ^ inputs[i]; for (u64 j = 0; j < mCuckooParams.mNumHashes; ++j) { u64 idx = CuckooIndex<>::getHash(hashs[i], j, numCuckooBins) * mNumSimpleBins / mCuckooParams.numBins(); // insert this item in this bin. pack together the hash index and input index bins(idx, binSizes[idx]++) = (j << 56) | i; } //if (!i) //{ // ostreamLock(std::cout) << "cinput[" << i << "] = " << inputs[i] << " -> " << hashs[i] << " (" // << CuckooIndex<>::getHash(hashs[i], 0, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 1, numCuckooBins) << ", " // << CuckooIndex<>::getHash(hashs[i], 2, numCuckooBins) << ")" // << std::endl; //} } } // power of 2 u64 numLeafBlocks = (cuckooSlotsPerBin + mBigBlockSize * 128 - 1) / (mBigBlockSize * 128); u64 gDepth = 2; u64 kDepth = std::max<u64>(gDepth, log2floor(numLeafBlocks)) - gDepth; u64 groupSize = (numLeafBlocks + (u64(1) << kDepth) - 1) / (u64(1) << kDepth); if (groupSize > 8) throw std::runtime_error(LOCATION); //std::cout << "kDepth: " << kDepth << std::endl; //std::cout << "mBinSize: " << mBinSize << std::endl; u64 numQueries = mNumSimpleBins * mBinSize; auto permSize = numQueries * mBigBlockSize; // mask generation block rSeed = CCBlock;// mPrng.get<block>(); AES rGen(rSeed); std::vector<block> shares(mClientSetSize * mCuckooParams.mNumHashes), r(permSize), piS1(permSize), s(permSize); //std::vector<u32> rIdxs(numQueries); //std::vector<u64> sharesIdx(shares.size()); //TODO("use real masks"); //memset(r.data(), 0, r.size() * sizeof(block)); rGen.ecbEncCounterMode(r.size() * 0, r.size(), r.data()); rGen.ecbEncCounterMode(r.size() * 1, r.size(), piS1.data()); rGen.ecbEncCounterMode(r.size() * 2, r.size(), s.data()); //auto encIter = enc.begin(); auto shareIter = shares.begin(); //auto shareIdxIter = sharesIdx.begin(); u64 queryIdx = 0, dummyPermIdx = mClientSetSize * mCuckooParams.mNumHashes; std::unordered_map<u64, u64> inputMap; inputMap.reserve(mClientSetSize * mCuckooParams.mNumHashes); std::vector<u32> pi(permSize); auto piIter = pi.begin(); u64 keySize = kDepth + 1 + groupSize; u64 mask = (u64(1) << 56) - 1; auto binIter = bins.begin(); for (u64 bIdx = 0; bIdx < mNumSimpleBins; ++bIdx) { u64 i = 0; auto binOffset = (bIdx * numCuckooBins + mNumSimpleBins - 1) / mNumSimpleBins; std::vector<block> k0(keySize * mBinSize), k1(keySize * mBinSize); //std::vector<u64> idx0(mBinSize), idx1(mBinSize); auto k0Iter = k0.data(), k1Iter = k1.data(); //auto idx0Iter = idx0.data(), idx1Iter = idx1.data(); for (; i < binSizes[bIdx]; ++i) { span<block> kk0(k0Iter, kDepth + 1), g0(k0Iter + kDepth + 1, groupSize), kk1(k1Iter, kDepth + 1), g1(k1Iter + kDepth + 1, groupSize); k0Iter += keySize; k1Iter += keySize; u8 hashIdx = *binIter >> 56; u64 itemIdx = *binIter & mask; u64 cuckooIdx = CuckooIndex<>::getHash(hashs[itemIdx], hashIdx, numCuckooBins) - binOffset; ++binIter; auto bigBlockoffset = cuckooIdx % mBigBlockSize; auto bigBlockIdx = cuckooIdx / mBigBlockSize; BgiPirClient::keyGen(bigBlockIdx, mPrng.get<block>(), kk0, g0, kk1, g1); // the index of the mask that will mask this item auto rIdx = *piIter = itemIdx * mCuckooParams.mNumHashes + hashIdx * mBigBlockSize + bigBlockoffset; // the masked value that will be inputted into the PSI *shareIter = r[rIdx] ^ inputs[itemIdx]; //*shareIter = inputs[itemIdx]; //if (itemIdx == 0) // ostreamLock(std::cout) // << "item[" << i << "] bin " << bIdx // << " block " << bigBlockIdx // << " offset " << bigBlockoffset // << " psi " << *shareIter << std::endl; // This will be used to map itemed items in the intersection back to their input item inputMap.insert({ queryIdx, itemIdx }); ++shareIter; ++piIter; ++queryIdx; } u64 rem = mBinSize - i; binIter += rem; for (u64 i = 0; i < rem; ++i) { *piIter++ = dummyPermIdx++; } //s0.asyncSendCopy(k0); //s0.asyncSendCopy(k1); //s1.asyncSendCopy(k1); //s1.asyncSendCopy(k0); s0.asyncSend(std::move(k0)); s1.asyncSend(std::move(k1)); } std::vector<u32> pi1(permSize), pi0(permSize), pi1Inv(permSize); for (u32 i = 0; i < pi1.size(); ++i) pi1[i] = i; PRNG prng(rSeed ^ OneBlock); std::random_shuffle(pi1.begin(), pi1.end(), prng); //std::vector<block> pi1RS(pi.size()); for (u64 i = 0; i < permSize; ++i) { //auto pi1i = pi1[i]; //pi1RS[i] = r[pi1i] ^ s[pi1i]; pi1Inv[pi1[i]] = i; //std::cout << "pi1(r + s)[" << i << "] " << pi1RS[i] << std::endl; } std::vector<block> piS0(r.size()); for (u64 i = 0; i < permSize; ++i) { //std::cout << "r[" << i << "] " << r[i] << std::endl; //std::cout << "pi(r + s)[" << i << "]=" << (r[pi[i]] ^ s[pi[i]]) << std::endl; pi0[i] = pi1Inv[pi[i]]; piS0[i] = piS1[i] ^ s[pi[i]]; //std::cout << "pi (r + s)[" << i << "] = " << (r[pi[i]] ^ s[pi[i]]) << " = " << r[pi[i]] << " ^ " << s[pi[i]] << " c " << pi[i] << std::endl; //std::cout << "pi`(r + s)[" << i << "] = " << pi1RS[pi0[i]] <<" c " << pi0[pi1[i]] << std::endl; } s0.asyncSend(std::move(pi0)); s0.asyncSend(std::move(piS0)); //rGen.ecbEncBlocks(r.data(), r.size(), r.data()); //for (u64 i = 0; i < shares.size(); ++i) //{ // std::cout << IoStream::lock << "cshares[" << i << "] " << shares[i] << " input[" << sharesIdx[i]<<"]" << std::endl << IoStream::unlock; //} mPsi.sendInput(shares, s0); mIntersection.reserve(mPsi.mIntersection.size()); for (u64 i = 0; i < mPsi.mIntersection.size(); ++i) { // divide index by #hashes mIntersection.emplace(inputMap[mPsi.mIntersection[i]]); } }