Add `KdfParameters` class

This commit is contained in:
Christian Hagau 2020-09-29 00:00:00 +00:00
parent f6a5141e24
commit d3c51b26e8
1 changed files with 134 additions and 0 deletions

View File

@ -0,0 +1,134 @@
package org.sufficientlysecure.keychain.securitytoken;
import com.google.auto.value.AutoValue;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import java.io.IOException;
import java.nio.ByteBuffer;
@SuppressWarnings("unused") // just expose all included data
@AutoValue
public abstract class KdfParameters {
public enum HashType {
SHA256
, SHA512
}
public enum PasswordType {
PW1
, PW2
, PW3
}
public abstract HashType getDigestAlgorithm();
public abstract int getIterations();
public abstract byte[] getSaltPw1();
public abstract byte[] getSaltPw2();
public abstract byte[] getSaltPw3();
public abstract byte[] getHashUser();
public abstract byte[] getHashAdmin();
public abstract boolean isHasUsesKdf();
public static KdfParameters fromKdfDo(byte[] kdfDo) throws IOException {
// parse elements of KDF-DO
Iso7816TLV[] tlvs = Iso7816TLV.readList(kdfDo, false);
return new AutoValue_KdfParameters.Builder().parseKdfTLVs(tlvs).build();
}
public KdfCalculator.KdfCalculatorArguments forType(PasswordType passwordType) {
byte[] salt = null;
// select salt based on the specified password type
switch (passwordType) {
case PW1:
salt = getSaltPw1();
break;
case PW2:
salt = getSaltPw2();
break;
case PW3:
salt = getSaltPw3();
break;
}
KdfCalculator.KdfCalculatorArguments arguments = new KdfCalculator.KdfCalculatorArguments();
arguments.digestAlgorithm = getDigestAlgorithm();
arguments.salt = salt;
arguments.iterations = getIterations();
return arguments;
}
@AutoValue.Builder
abstract static class Builder {
abstract Builder digestAlgorithm(HashType digestAlgorithm);
abstract Builder iterations(int iterations);
abstract Builder saltPw1(byte[] saltPw1);
abstract Builder saltPw2(byte[] saltPw1);
abstract Builder saltPw3(byte[] saltPw1);
abstract Builder hashUser(byte[] hashUser);
abstract Builder hashAdmin(byte[] hashAdmin);
abstract Builder hasUsesKdf(boolean hasUsesKdf);
abstract KdfParameters build();
public Builder() {
hasUsesKdf(false);
}
Builder parseKdfTLVs(Iso7816TLV[] tlvs) throws IOException {
for (Iso7816TLV tlv : tlvs) {
switch (tlv.mT) {
case 0x81:
switch (tlv.mV[0]) {
case (byte)0x00:
// no KDF, plain password
hasUsesKdf(false);
case (byte)0x03:
// using KDF
hasUsesKdf(true);
break;
default:
throw new CardException("Unknown KDF algorithm!");
}
break;
case 0x82:
// hash algorithm
switch (tlv.mV[0]) {
case (byte)0x08: // SHA256
digestAlgorithm(HashType.SHA256);
break;
case (byte)0x0a: // SHA512
digestAlgorithm(HashType.SHA512);
break;
default:
throw new CardException("Unknown hash algorithm!");
}
break;
case 0x83:
// iteration count
ByteBuffer buf = ByteBuffer.wrap(tlv.mV);
iterations(buf.getInt());
break;
case 0x84:
saltPw1(tlv.mV);
break;
case 0x85:
saltPw2(tlv.mV);
break;
case 0x86:
saltPw3(tlv.mV);
break;
case 0x87:
hashUser(tlv.mV);
break;
case 0x88:
hashAdmin(tlv.mV);
break;
}
}
return this;
}
}
}