diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-01 18:52:42 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-02-01 18:52:42 +0000 |
commit | 9218edabd1ef9852bc2f13115dcadc81b442dd6c (patch) | |
tree | 8229ff72c8cbb06f49dce3a8382930919fa6fc2b /bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java | |
parent | 9b30eb05e5be69d51881a0d1b31e503e97acd784 (diff) | |
parent | 397d32894b89b506dc318e0f83446187c9b76ebe (diff) | |
download | android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.gz android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.bz2 android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.zip |
Merge "Merge remote-tracking branch 'aosp/upstream-master' into merge-152-from-upstream"
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java new file mode 100644 index 0000000..6003037 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java @@ -0,0 +1,175 @@ +package org.bouncycastle.crypto.generators; + +import java.math.BigInteger; + +import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.DerivationParameters; +import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.MacDerivationFunction; +import org.bouncycastle.crypto.params.KDFFeedbackParameters; +import org.bouncycastle.crypto.params.KeyParameter; + +/** + * This KDF has been defined by the publicly available NIST SP 800-108 specification. + */ +public class KDFFeedbackBytesGenerator + implements MacDerivationFunction +{ + + private static final BigInteger INTEGER_MAX = BigInteger.valueOf(Integer.MAX_VALUE); + private static final BigInteger TWO = BigInteger.valueOf(2); + + // please refer to the standard for the meaning of the variable names + // all field lengths are in bytes, not in bits as specified by the standard + + // fields set by the constructor + private final Mac prf; + private final int h; + + // fields set by init + private byte[] fixedInputData; + private int maxSizeExcl; + // ios is i defined as an octet string (the binary representation) + private byte[] ios; + private byte[] iv; + private boolean useCounter; + + // operational + private int generatedBytes; + // k is used as buffer for all K(i) values + private byte[] k; + + + public KDFFeedbackBytesGenerator(Mac prf) + { + this.prf = prf; + this.h = prf.getMacSize(); + this.k = new byte[h]; + } + + public void init(DerivationParameters params) + { + if (!(params instanceof KDFFeedbackParameters)) + { + throw new IllegalArgumentException("Wrong type of arguments given"); + } + + KDFFeedbackParameters feedbackParams = (KDFFeedbackParameters)params; + + // --- init mac based PRF --- + + this.prf.init(new KeyParameter(feedbackParams.getKI())); + + // --- set arguments --- + + this.fixedInputData = feedbackParams.getFixedInputData(); + + int r = feedbackParams.getR(); + this.ios = new byte[r / 8]; + + if (feedbackParams.useCounter()) + { + // this is more conservative than the spec + BigInteger maxSize = TWO.pow(r).multiply(BigInteger.valueOf(h)); + this.maxSizeExcl = maxSize.compareTo(INTEGER_MAX) == 1 ? + Integer.MAX_VALUE : maxSize.intValue(); + } + else + { + this.maxSizeExcl = Integer.MAX_VALUE; + } + + this.iv = feedbackParams.getIV(); + this.useCounter = feedbackParams.useCounter(); + + // --- set operational state --- + + generatedBytes = 0; + } + + public Mac getMac() + { + return prf; + } + + public int generateBytes(byte[] out, int outOff, int len) + throws DataLengthException, IllegalArgumentException + { + + int generatedBytesAfter = generatedBytes + len; + if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl) + { + throw new DataLengthException( + "Current KDFCTR may only be used for " + maxSizeExcl + " bytes"); + } + + if (generatedBytes % h == 0) + { + generateNext(); + } + + // copy what is left in the currentT (1..hash + int toGenerate = len; + int posInK = generatedBytes % h; + int leftInK = h - generatedBytes % h; + int toCopy = Math.min(leftInK, toGenerate); + System.arraycopy(k, posInK, out, outOff, toCopy); + generatedBytes += toCopy; + toGenerate -= toCopy; + outOff += toCopy; + + while (toGenerate > 0) + { + generateNext(); + toCopy = Math.min(h, toGenerate); + System.arraycopy(k, 0, out, outOff, toCopy); + generatedBytes += toCopy; + toGenerate -= toCopy; + outOff += toCopy; + } + + return len; + } + + private void generateNext() + { + + // TODO enable IV + if (generatedBytes == 0) + { + prf.update(iv, 0, iv.length); + } + else + { + prf.update(k, 0, k.length); + } + + if (useCounter) + { + int i = generatedBytes / h + 1; + + // encode i into counter buffer + switch (ios.length) + { + case 4: + ios[0] = (byte)(i >>> 24); + // fall through + case 3: + ios[ios.length - 3] = (byte)(i >>> 16); + // fall through + case 2: + ios[ios.length - 2] = (byte)(i >>> 8); + // fall through + case 1: + ios[ios.length - 1] = (byte)i; + break; + default: + throw new IllegalStateException("Unsupported size of counter i"); + } + prf.update(ios, 0, ios.length); + } + + prf.update(fixedInputData, 0, fixedInputData.length); + prf.doFinal(k, 0); + } +} |