![JAR search and dependency download from the Maven repository](/logo.png)
org.bouncycastle.crypto.fips.ConcatenationKDFGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bc-fips-debug Show documentation
Show all versions of bc-fips-debug Show documentation
The FIPS 140-2 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-2 level 1. This jar contains the debug version JCE provider and low-level API for the BC-FJA version 1.0.2.3, FIPS Certificate #3514. Please note the debug jar is not certified.
package org.bouncycastle.crypto.fips;
import org.bouncycastle.crypto.internal.DataLengthException;
import org.bouncycastle.crypto.internal.DerivationFunction;
import org.bouncycastle.crypto.internal.DerivationParameters;
import org.bouncycastle.crypto.internal.Digest;
import org.bouncycastle.crypto.internal.Mac;
import org.bouncycastle.crypto.internal.macs.HMac;
import org.bouncycastle.crypto.internal.params.KDFParameters;
import org.bouncycastle.crypto.internal.params.KeyParameterImpl;
/**
* Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1
*/
class ConcatenationKDFGenerator
implements DerivationFunction
{
private final Mac mac;
private Digest digest;
private byte[] shared;
private byte[] otherInfo;
private int hLen;
/**
* @param digest the digest to be used as the source of generated bytes
*/
public ConcatenationKDFGenerator(
Digest digest)
{
this.digest = digest;
this.mac = null;
this.hLen = digest.getDigestSize();
}
public ConcatenationKDFGenerator(
Mac mac)
{
this.mac = mac;
this.digest = null;
this.hLen = mac.getMacSize();
}
public void init(
DerivationParameters param)
{
if (param instanceof KDFParameters)
{
KDFParameters p = (KDFParameters)param;
shared = p.getSharedSecret();
otherInfo = p.getIV();
if (mac != null)
{
byte[] salt = p.getSalt();
if (p.getSalt() == null)
{
if (mac instanceof HMac)
{
salt = new byte[((HMac)mac).getUnderlyingDigest().getByteLength()];
}
else if (mac instanceof KMAC)
{
salt = new byte[(((KMAC)mac).getByteLength()) - 4];
}
else
{
throw new IllegalArgumentException("cannot recognise MAC");
}
}
mac.init(new KeyParameterImpl(salt));
}
}
else
{
throw new IllegalArgumentException("KDF parameters required for KDF generator");
}
}
/**
* return the underlying digest.
*/
public Digest getDigest()
{
return digest;
}
/**
* int to octet string.
*/
private void ItoOSP(
int i,
byte[] sp)
{
sp[0] = (byte)(i >>> 24);
sp[1] = (byte)(i >>> 16);
sp[2] = (byte)(i >>> 8);
sp[3] = (byte)(i >>> 0);
}
/**
* fill len bytes of the output buffer with bytes generated from
* the derivation function.
*
* @throws DataLengthException if the out buffer is too small.
*/
public int generateBytes(
byte[] out,
int outOff,
int len)
throws DataLengthException, IllegalArgumentException
{
if (digest != null)
{
return digestGenerateBytes(out, outOff, len);
}
else
{
return macGenerateBytes(out, outOff, len);
}
}
/**
* fill len bytes of the output buffer with bytes generated from
* the derivation function.
*
* @throws DataLengthException if the out buffer is too small.
*/
public int digestGenerateBytes(
byte[] out,
int outOff,
int len)
throws DataLengthException, IllegalArgumentException
{
if ((out.length - len) < outOff)
{
throw new DataLengthException("output buffer too small");
}
byte[] hashBuf = new byte[hLen];
byte[] C = new byte[4];
int counter = 1;
int outputLen = 0;
digest.reset();
if (len > hLen)
{
do
{
ItoOSP(counter, C);
digest.update(C, 0, C.length);
digest.update(shared, 0, shared.length);
if (otherInfo != null)
{
digest.update(otherInfo, 0, otherInfo.length);
}
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, hLen);
outputLen += hLen;
}
while ((counter++) < (len / hLen));
}
if (outputLen < len)
{
ItoOSP(counter, C);
digest.update(C, 0, C.length);
digest.update(shared, 0, shared.length);
if (otherInfo != null)
{
digest.update(otherInfo, 0, otherInfo.length);
}
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, len - outputLen);
}
return len;
}
/**
* fill len bytes of the output buffer with bytes generated from
* the derivation function.
*
* @throws DataLengthException if the out buffer is too small.
*/
private int macGenerateBytes(
byte[] out,
int outOff,
int len)
throws DataLengthException, IllegalArgumentException
{
if ((out.length - len) < outOff)
{
throw new DataLengthException("output buffer too small");
}
byte[] hashBuf = new byte[hLen];
byte[] C = new byte[4];
int counter = 1;
int outputLen = 0;
mac.reset();
if (mac instanceof KMAC)
{
ItoOSP(counter, C);
mac.update(C, 0, C.length);
mac.update(shared, 0, shared.length);
if (otherInfo != null)
{
mac.update(otherInfo, 0, otherInfo.length);
}
return ((KMAC)mac).doFinal(out, outOff, len);
}
if (len > hLen)
{
do
{
ItoOSP(counter, C);
mac.update(C, 0, C.length);
mac.update(shared, 0, shared.length);
if (otherInfo != null)
{
mac.update(otherInfo, 0, otherInfo.length);
}
mac.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, hLen);
outputLen += hLen;
}
while ((counter++) < (len / hLen));
}
if (outputLen < len)
{
ItoOSP(counter, C);
mac.update(C, 0, C.length);
mac.update(shared, 0, shared.length);
if (otherInfo != null)
{
mac.update(otherInfo, 0, otherInfo.length);
}
mac.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, len - outputLen);
}
return len;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy