net.sourceforge.plantuml.argon2.algorithm.FillSegment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plantuml-epl Show documentation
Show all versions of plantuml-epl Show documentation
PlantUML is a component that allows to quickly write diagrams from text.
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
* |
* | PlantUML : a free UML diagram generator
* |
* +=======================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/liberapay (only 1€ per month!)
* https://plantuml.com/paypal
*
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the Eclipse Public License.
*
* THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
* LICENSE ("AGREEMENT"). [Eclipse Public License - v 1.0]
*
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
*
* You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PlantUML can occasionally display sponsored or advertising messages. Those
* messages are usually generated on welcome or error images and never on
* functional diagrams.
* See https://plantuml.com/professional if you want to remove them
*
* Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
* are owned by the author of their corresponding sources code (that is, their
* textual description in PlantUML language). Those images are not covered by
* this EPL license.
*
* The generated images can then be used without any reference to the EPL license.
* It is not even necessary to stipulate that they have been generated with PlantUML,
* although this will be appreciated by the PlantUML team.
*
* There is an exception : if the textual description in PlantUML language is also covered
* by any license, then the generated images are logically covered
* by the very same license.
*
* This is the IGY distribution (Install GraphViz by Yourself).
* You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
* (see https://plantuml.com/graphviz-dot )
*
* Icons provided by OpenIconic : https://useiconic.com/open
* Archimate sprites provided by Archi : http://www.archimatetool.com
* Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
* Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
* ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
* ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
* CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
* Brotli (c) by the Brotli Authors https://github.com/google/brotli
* Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
* Twemoji (c) by Twitter at https://twemoji.twitter.com/
*
*/
package net.sourceforge.plantuml.argon2.algorithm;
import static net.sourceforge.plantuml.argon2.Constants.ARGON2_ADDRESSES_IN_BLOCK;
import static net.sourceforge.plantuml.argon2.Constants.ARGON2_VERSION_10;
import net.sourceforge.plantuml.argon2.Constants;
import net.sourceforge.plantuml.argon2.Util;
import net.sourceforge.plantuml.argon2.model.Argon2Type;
import net.sourceforge.plantuml.argon2.model.Block;
import net.sourceforge.plantuml.argon2.model.Instance;
import net.sourceforge.plantuml.argon2.model.Position;
class FillSegment {
static void fillSegment(Instance instance, Position position) {
Block addressBlock = null, inputBlock = null, zeroBlock = null;
boolean dataIndependentAddressing = isDataIndependentAddressing(instance, position);
int startingIndex = getStartingIndex(position);
int currentOffset = position.lane * instance.getLaneLength() + position.slice * instance.getSegmentLength()
+ startingIndex;
int prevOffset = getPrevOffset(instance, currentOffset);
if (dataIndependentAddressing) {
addressBlock = new Block();
zeroBlock = new Block();
inputBlock = new Block();
initAddressBlocks(instance, position, zeroBlock, inputBlock, addressBlock);
}
for (position.index = startingIndex; position.index < instance
.getSegmentLength(); position.index++, currentOffset++, prevOffset++) {
prevOffset = rotatePrevOffset(instance, currentOffset, prevOffset);
long pseudoRandom = getPseudoRandom(instance, position, addressBlock, inputBlock, zeroBlock, prevOffset,
dataIndependentAddressing);
int refLane = getRefLane(instance, position, pseudoRandom);
int refColumn = getRefColumn(instance, position, pseudoRandom, refLane == position.lane);
/* 2 Creating a new block */
Block prevBlock = instance.memory[prevOffset];
Block refBlock = instance.memory[((instance.getLaneLength()) * refLane + refColumn)];
Block currentBlock = instance.memory[currentOffset];
boolean withXor = isWithXor(instance, position);
FillBlock.fillBlock(prevBlock, refBlock, currentBlock, withXor);
}
}
private static boolean isDataIndependentAddressing(Instance instance, Position position) {
return (instance.getType() == Argon2Type.Argon2i) || (instance.getType() == Argon2Type.Argon2id
&& (position.pass == 0) && (position.slice < Constants.ARGON2_SYNC_POINTS / 2));
}
private static void initAddressBlocks(Instance instance, Position position, Block zeroBlock, Block inputBlock,
Block addressBlock) {
inputBlock.v[0] = Util.intToLong(position.pass);
inputBlock.v[1] = Util.intToLong(position.lane);
inputBlock.v[2] = Util.intToLong(position.slice);
inputBlock.v[3] = Util.intToLong(instance.memory.length);
inputBlock.v[4] = Util.intToLong(instance.getIterations());
inputBlock.v[5] = Util.intToLong(instance.getType().ordinal());
if ((position.pass == 0) && (position.slice == 0)) {
/* Don't forget to generate the first block of addresses: */
nextAddresses(zeroBlock, inputBlock, addressBlock);
}
}
private static boolean isWithXor(Instance instance, Position position) {
return !(position.pass == 0 || instance.getVersion() == ARGON2_VERSION_10);
}
private static int getPrevOffset(Instance instance, int currentOffset) {
if (currentOffset % instance.getLaneLength() == 0) {
/* Last block in this lane */
return currentOffset + instance.getLaneLength() - 1;
} else {
/* Previous block */
return currentOffset - 1;
}
}
private static int rotatePrevOffset(Instance instance, int currentOffset, int prevOffset) {
if (currentOffset % instance.getLaneLength() == 1) {
prevOffset = currentOffset - 1;
}
return prevOffset;
}
private static int getStartingIndex(Position position) {
if ((position.pass == 0) && (position.slice == 0)) {
return 2; /* we have already generated the first two blocks */
} else {
return 0;
}
}
private static void nextAddresses(Block zeroBlock, Block inputBlock, Block addressBlock) {
inputBlock.v[6]++;
FillBlock.fillBlock(zeroBlock, inputBlock, addressBlock, false);
FillBlock.fillBlock(zeroBlock, addressBlock, addressBlock, false);
}
/* 1.2 Computing the index of the reference block */
/* 1.2.1 Taking pseudo-random value from the previous block */
private static long getPseudoRandom(Instance instance, Position position, Block addressBlock, Block inputBlock,
Block zeroBlock, int prevOffset, boolean dataIndependentAddressing) {
if (dataIndependentAddressing) {
if (position.index % ARGON2_ADDRESSES_IN_BLOCK == 0) {
nextAddresses(zeroBlock, inputBlock, addressBlock);
}
return addressBlock.v[position.index % ARGON2_ADDRESSES_IN_BLOCK];
} else {
return instance.memory[prevOffset].v[0];
}
}
private static int getRefLane(Instance instance, Position position, long pseudoRandom) {
int refLane = (int) (((pseudoRandom >>> 32)) % instance.getLanes());
if ((position.pass == 0) && (position.slice == 0)) {
/* Can not reference other lanes yet */
refLane = position.lane;
}
return refLane;
}
private static int getRefColumn(Instance instance, Position position, long pseudoRandom, boolean sameLane) {
int referenceAreaSize;
int startPosition;
if (position.pass == 0) {
startPosition = 0;
if (sameLane) {
/* The same lane => add current segment */
referenceAreaSize = position.slice * instance.getSegmentLength() + position.index - 1;
} else {
/* pass == 0 && !sameLane => position.slice > 0 */
referenceAreaSize = position.slice * instance.getSegmentLength() + ((position.index == 0) ? (-1) : 0);
}
} else {
startPosition = ((position.slice + 1) * instance.getSegmentLength()) % instance.getLaneLength();
if (sameLane) {
referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength() + position.index - 1;
} else {
referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength()
+ ((position.index == 0) ? (-1) : 0);
}
}
long relativePosition = pseudoRandom & 0xFFFFFFFFL;
// long relativePosition = pseudoRandom << 32 >>> 32;
relativePosition = (relativePosition * relativePosition) >>> 32;
relativePosition = referenceAreaSize - 1 - (referenceAreaSize * relativePosition >>> 32);
return (int) (startPosition + relativePosition) % instance.getLaneLength();
}
}