Add support for hybrid forward secrecy
This commit is contained in:
parent
4bc27fefce
commit
683b9b2315
@ -37,12 +37,15 @@ public class HandshakeState implements Destroyable {
|
||||
private boolean isInitiator;
|
||||
private DHState localKeyPair;
|
||||
private DHState localEphemeral;
|
||||
private DHState localHybrid;
|
||||
private DHState remotePublicKey;
|
||||
private DHState remoteEphemeral;
|
||||
private DHState remoteHybrid;
|
||||
private DHState fixedEphemeral;
|
||||
private DHState fixedHybrid;
|
||||
private int action;
|
||||
private int requirements;
|
||||
private byte[] pattern;
|
||||
private short[] pattern;
|
||||
private int patternIndex;
|
||||
private byte[] preSharedKey;
|
||||
private byte[] prologue;
|
||||
@ -150,6 +153,7 @@ public class HandshakeState implements Destroyable {
|
||||
String prefix = components[0];
|
||||
String patternId = components[1];
|
||||
String dh = components[2];
|
||||
String hybrid = null;
|
||||
String cipher = components[3];
|
||||
String hash = components[4];
|
||||
if (!prefix.equals("Noise") && !prefix.equals("NoisePSK"))
|
||||
@ -157,7 +161,7 @@ public class HandshakeState implements Destroyable {
|
||||
pattern = Pattern.lookup(patternId);
|
||||
if (pattern == null)
|
||||
throw new IllegalArgumentException("Handshake pattern is not recognized");
|
||||
byte flags = pattern[0];
|
||||
short flags = pattern[0];
|
||||
int extraReqs = 0;
|
||||
if ((flags & Pattern.FLAG_REMOTE_REQUIRED) != 0 && patternId.length() > 1)
|
||||
extraReqs |= FALLBACK_POSSIBLE;
|
||||
@ -165,6 +169,17 @@ public class HandshakeState implements Destroyable {
|
||||
// Reverse the pattern flags so that the responder is "local".
|
||||
flags = Pattern.reverseFlags(flags);
|
||||
}
|
||||
int index = dh.indexOf('+');
|
||||
if (index != -1) {
|
||||
// The DH name has two components: regular and hybrid.
|
||||
hybrid = dh.substring(index + 1);
|
||||
dh = dh.substring(0, index);
|
||||
if ((flags & Pattern.FLAG_LOCAL_HYBRID) == 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) == 0)
|
||||
throw new IllegalArgumentException("Hybrid function specified for non-hybrid pattern");
|
||||
} else {
|
||||
if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) != 0)
|
||||
throw new IllegalArgumentException("Hybrid function not specified for hybrid pattern");
|
||||
}
|
||||
|
||||
// Check that the role is correctly specified.
|
||||
if (role != INITIATOR && role != RESPONDER)
|
||||
@ -182,10 +197,14 @@ public class HandshakeState implements Destroyable {
|
||||
localKeyPair = Noise.createDH(dh);
|
||||
if ((flags & Pattern.FLAG_LOCAL_EPHEMERAL) != 0)
|
||||
localEphemeral = Noise.createDH(dh);
|
||||
if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0)
|
||||
localHybrid = Noise.createDH(hybrid);
|
||||
if ((flags & Pattern.FLAG_REMOTE_STATIC) != 0)
|
||||
remotePublicKey = Noise.createDH(dh);
|
||||
if ((flags & Pattern.FLAG_REMOTE_EPHEMERAL) != 0)
|
||||
remoteEphemeral = Noise.createDH(dh);
|
||||
if ((flags & Pattern.FLAG_REMOTE_HYBRID) != 0)
|
||||
remoteHybrid = Noise.createDH(hybrid);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -403,6 +422,33 @@ public class HandshakeState implements Destroyable {
|
||||
return fixedEphemeral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DHState object containing a fixed local hybrid
|
||||
* key value for this handshake.
|
||||
*
|
||||
* @return The fixed hybrid key object, or null if a local
|
||||
* hybrid key is not required by this handshake.
|
||||
*
|
||||
* This function is intended for testing only. It can be used
|
||||
* to establish a fixed hybrid key for test vectors. This
|
||||
* function should not be used in real applications.
|
||||
*/
|
||||
public DHState getFixedHybridKey()
|
||||
{
|
||||
if (fixedHybrid != null)
|
||||
return fixedHybrid;
|
||||
if (localHybrid == null)
|
||||
return null;
|
||||
try {
|
||||
fixedHybrid = Noise.createDH(localHybrid.getDHName());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// This shouldn't happen - the local hybrid key would
|
||||
// have already been created with the same name!
|
||||
fixedHybrid = null;
|
||||
}
|
||||
return fixedHybrid;
|
||||
}
|
||||
|
||||
// Empty value for when the prologue is not supplied.
|
||||
private static final byte[] emptyPrologue = new byte [0];
|
||||
|
||||
@ -468,6 +514,8 @@ public class HandshakeState implements Destroyable {
|
||||
symmetric.mixPublicKey(localKeyPair);
|
||||
if ((requirements & FALLBACK_PREMSG) != 0) {
|
||||
symmetric.mixPublicKey(remoteEphemeral);
|
||||
if (remoteHybrid != null)
|
||||
symmetric.mixPublicKey(remoteHybrid);
|
||||
if (preSharedKey != null)
|
||||
symmetric.mixPublicKeyIntoCK(remoteEphemeral);
|
||||
}
|
||||
@ -478,6 +526,8 @@ public class HandshakeState implements Destroyable {
|
||||
symmetric.mixPublicKey(remotePublicKey);
|
||||
if ((requirements & FALLBACK_PREMSG) != 0) {
|
||||
symmetric.mixPublicKey(localEphemeral);
|
||||
if (localHybrid != null)
|
||||
symmetric.mixPublicKey(localHybrid);
|
||||
if (preSharedKey != null)
|
||||
symmetric.mixPublicKeyIntoCK(localEphemeral);
|
||||
}
|
||||
@ -576,7 +626,7 @@ public class HandshakeState implements Destroyable {
|
||||
throw new UnsupportedOperationException("Previous handshake pattern does not support fallback");
|
||||
|
||||
// Check that "patternName" supports fallback.
|
||||
byte[] newPattern = Pattern.lookup(patternName);
|
||||
short[] newPattern = Pattern.lookup(patternName);
|
||||
if (newPattern == null || (newPattern[0] & Pattern.FLAG_REMOTE_EPHEM_REQ) == 0)
|
||||
throw new UnsupportedOperationException("New pattern is not a fallback pattern");
|
||||
|
||||
@ -612,12 +662,16 @@ public class HandshakeState implements Destroyable {
|
||||
if (isInitiator) {
|
||||
if (remoteEphemeral != null)
|
||||
remoteEphemeral.clearKey();
|
||||
if (remoteHybrid != null)
|
||||
remoteHybrid.clearKey();
|
||||
if (remotePublicKey != null)
|
||||
remotePublicKey.clearKey();
|
||||
isInitiator = false;
|
||||
} else {
|
||||
if (localEphemeral != null)
|
||||
localEphemeral.clearKey();
|
||||
if (localHybrid != null)
|
||||
localHybrid.clearKey();
|
||||
if ((newPattern[0] & Pattern.FLAG_REMOTE_REQUIRED) == 0 && remotePublicKey != null)
|
||||
remotePublicKey.clearKey();
|
||||
isInitiator = true;
|
||||
@ -625,7 +679,7 @@ public class HandshakeState implements Destroyable {
|
||||
action = NO_ACTION;
|
||||
pattern = newPattern;
|
||||
patternIndex = 1;
|
||||
byte flags = pattern[0];
|
||||
short flags = pattern[0];
|
||||
if (!isInitiator) {
|
||||
// Reverse the pattern flags so that the responder is "local".
|
||||
flags = Pattern.reverseFlags(flags);
|
||||
@ -718,7 +772,7 @@ public class HandshakeState implements Destroyable {
|
||||
action = SPLIT;
|
||||
break;
|
||||
}
|
||||
byte token = pattern[patternIndex++];
|
||||
short token = pattern[patternIndex++];
|
||||
if (token == Pattern.FLIP_DIR) {
|
||||
// Change directions, so this message is complete and the
|
||||
// next action is "read message".
|
||||
@ -801,6 +855,35 @@ public class HandshakeState implements Destroyable {
|
||||
}
|
||||
break;
|
||||
|
||||
case Pattern.F:
|
||||
{
|
||||
// Generate a local hybrid keypair and add the public
|
||||
// key to the message. If we are running fixed vector tests,
|
||||
// then a fixed hybrid key may have already been provided.
|
||||
if (localHybrid == null)
|
||||
throw new IllegalStateException("Pattern definition error");
|
||||
if (fixedHybrid == null)
|
||||
localHybrid.generateKeyPair(); // FIXME: dependent keys
|
||||
else
|
||||
localHybrid.copyFrom(fixedHybrid);
|
||||
len = localHybrid.getPublicKeyLength();
|
||||
if (space < len)
|
||||
throw new ShortBufferException();
|
||||
macLen = symmetric.getMACLength();
|
||||
if (space < (len + macLen))
|
||||
throw new ShortBufferException();
|
||||
localHybrid.getPublicKey(message, messagePosn);
|
||||
messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case Pattern.FF:
|
||||
{
|
||||
// DH operation with initiator and responder hybrid keys.
|
||||
mixDH(localHybrid, remoteHybrid);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Unknown token code. Abort.
|
||||
@ -877,7 +960,7 @@ public class HandshakeState implements Destroyable {
|
||||
action = SPLIT;
|
||||
break;
|
||||
}
|
||||
byte token = pattern[patternIndex++];
|
||||
short token = pattern[patternIndex++];
|
||||
if (token == Pattern.FLIP_DIR) {
|
||||
// Change directions, so this message is complete and the
|
||||
// next action is "write message".
|
||||
@ -968,6 +1051,34 @@ public class HandshakeState implements Destroyable {
|
||||
}
|
||||
break;
|
||||
|
||||
case Pattern.F:
|
||||
{
|
||||
// Decrypt and read the remote hybrid ephemeral key.
|
||||
if (remoteHybrid == null)
|
||||
throw new IllegalStateException("Pattern definition error");
|
||||
len = remoteHybrid.getPublicKeyLength(); // TODO: Dependent keys
|
||||
macLen = symmetric.getMACLength();
|
||||
if (space < (len + macLen))
|
||||
throw new ShortBufferException();
|
||||
byte[] temp = new byte [len];
|
||||
try {
|
||||
if (symmetric.decryptAndHash(message, messageOffset, temp, 0, len + macLen) != len)
|
||||
throw new ShortBufferException();
|
||||
remoteHybrid.setPublicKey(temp, 0);
|
||||
} finally {
|
||||
Noise.destroy(temp);
|
||||
}
|
||||
messageOffset += len + macLen;
|
||||
}
|
||||
break;
|
||||
|
||||
case Pattern.FF:
|
||||
{
|
||||
// DH operation with initiator and responder hybrid keys.
|
||||
mixDH(localHybrid, remoteHybrid);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Unknown token code. Abort.
|
||||
@ -1065,12 +1176,18 @@ public class HandshakeState implements Destroyable {
|
||||
localKeyPair.destroy();
|
||||
if (localEphemeral != null)
|
||||
localEphemeral.destroy();
|
||||
if (localHybrid != null)
|
||||
localHybrid.destroy();
|
||||
if (remotePublicKey != null)
|
||||
remotePublicKey.destroy();
|
||||
if (remoteEphemeral != null)
|
||||
remoteEphemeral.destroy();
|
||||
if (remoteHybrid != null)
|
||||
remoteHybrid.destroy();
|
||||
if (fixedEphemeral != null)
|
||||
fixedEphemeral.destroy();
|
||||
if (fixedHybrid != null)
|
||||
fixedHybrid.destroy();
|
||||
if (preSharedKey != null)
|
||||
Noise.destroy(preSharedKey);
|
||||
if (prologue != null)
|
||||
@ -1089,7 +1206,7 @@ public class HandshakeState implements Destroyable {
|
||||
*
|
||||
* @return The set of requirements for the handshake.
|
||||
*/
|
||||
private static int computeRequirements(byte flags, String prefix, int role, boolean isFallback)
|
||||
private static int computeRequirements(short flags, String prefix, int role, boolean isFallback)
|
||||
{
|
||||
int requirements = 0;
|
||||
if ((flags & Pattern.FLAG_LOCAL_STATIC) != 0) {
|
||||
|
||||
@ -30,25 +30,31 @@ class Pattern {
|
||||
private Pattern() {}
|
||||
|
||||
// Token codes.
|
||||
public static final byte S = 1;
|
||||
public static final byte E = 2;
|
||||
public static final byte EE = 3;
|
||||
public static final byte ES = 4;
|
||||
public static final byte SE = 5;
|
||||
public static final byte SS = 6;
|
||||
public static final byte FLIP_DIR = 7;
|
||||
public static final short S = 1;
|
||||
public static final short E = 2;
|
||||
public static final short EE = 3;
|
||||
public static final short ES = 4;
|
||||
public static final short SE = 5;
|
||||
public static final short SS = 6;
|
||||
public static final short F = 7;
|
||||
public static final short FF = 8;
|
||||
public static final short FLIP_DIR = 255;
|
||||
|
||||
// Pattern flag bits.
|
||||
public static final byte FLAG_LOCAL_STATIC = 0x01;
|
||||
public static final byte FLAG_LOCAL_EPHEMERAL = 0x02;
|
||||
public static final byte FLAG_LOCAL_REQUIRED = 0x04;
|
||||
public static final byte FLAG_LOCAL_EPHEM_REQ = 0x08;
|
||||
public static final byte FLAG_REMOTE_STATIC = 0x10;
|
||||
public static final byte FLAG_REMOTE_EPHEMERAL = 0x20;
|
||||
public static final byte FLAG_REMOTE_REQUIRED = 0x40;
|
||||
public static final byte FLAG_REMOTE_EPHEM_REQ = (byte)0x80;
|
||||
public static final short FLAG_LOCAL_STATIC = 0x0001;
|
||||
public static final short FLAG_LOCAL_EPHEMERAL = 0x0002;
|
||||
public static final short FLAG_LOCAL_REQUIRED = 0x0004;
|
||||
public static final short FLAG_LOCAL_EPHEM_REQ = 0x0008;
|
||||
public static final short FLAG_LOCAL_HYBRID = 0x0010;
|
||||
public static final short FLAG_LOCAL_HYBRID_REQ = 0x0020;
|
||||
public static final short FLAG_REMOTE_STATIC = 0x0100;
|
||||
public static final short FLAG_REMOTE_EPHEMERAL = 0x0200;
|
||||
public static final short FLAG_REMOTE_REQUIRED = 0x0400;
|
||||
public static final short FLAG_REMOTE_EPHEM_REQ = 0x0800;
|
||||
public static final short FLAG_REMOTE_HYBRID = 0x1000;
|
||||
public static final short FLAG_REMOTE_HYBRID_REQ = 0x2000;
|
||||
|
||||
private static final byte[] noise_pattern_N = {
|
||||
private static final short[] noise_pattern_N = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_REQUIRED,
|
||||
@ -57,7 +63,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_K = {
|
||||
private static final short[] noise_pattern_K = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
@ -69,7 +75,7 @@ class Pattern {
|
||||
SS
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_X = {
|
||||
private static final short[] noise_pattern_X = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -81,7 +87,7 @@ class Pattern {
|
||||
SS
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_NN = {
|
||||
private static final short[] noise_pattern_NN = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_EPHEMERAL,
|
||||
|
||||
@ -91,7 +97,7 @@ class Pattern {
|
||||
EE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_NK = {
|
||||
private static final short[] noise_pattern_NK = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
@ -104,7 +110,7 @@ class Pattern {
|
||||
EE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_NX = {
|
||||
private static final short[] noise_pattern_NX = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL,
|
||||
@ -117,7 +123,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_XN = {
|
||||
private static final short[] noise_pattern_XN = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_EPHEMERAL,
|
||||
@ -131,7 +137,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_XK = {
|
||||
private static final short[] noise_pattern_XK = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -148,7 +154,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_XX = {
|
||||
private static final short[] noise_pattern_XX = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -165,7 +171,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_KN = {
|
||||
private static final short[] noise_pattern_KN = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
@ -178,7 +184,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_KK = {
|
||||
private static final short[] noise_pattern_KK = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
@ -195,7 +201,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_KX = {
|
||||
private static final short[] noise_pattern_KX = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
@ -211,7 +217,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_IN = {
|
||||
private static final short[] noise_pattern_IN = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_EPHEMERAL,
|
||||
@ -224,7 +230,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_IK = {
|
||||
private static final short[] noise_pattern_IK = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -241,7 +247,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_IX = {
|
||||
private static final short[] noise_pattern_IX = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -257,7 +263,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_XXfallback = {
|
||||
private static final short[] noise_pattern_XXfallback = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -273,7 +279,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_Xnoidh = {
|
||||
private static final short[] noise_pattern_Xnoidh = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -285,7 +291,7 @@ class Pattern {
|
||||
SS
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_NXnoidh = {
|
||||
private static final short[] noise_pattern_NXnoidh = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL,
|
||||
@ -298,7 +304,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_XXnoidh = {
|
||||
private static final short[] noise_pattern_XXnoidh = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -315,7 +321,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_KXnoidh = {
|
||||
private static final short[] noise_pattern_KXnoidh = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
@ -331,7 +337,7 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_IKnoidh = {
|
||||
private static final short[] noise_pattern_IKnoidh = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -348,7 +354,7 @@ class Pattern {
|
||||
SE
|
||||
};
|
||||
|
||||
private static final byte[] noise_pattern_IXnoidh = {
|
||||
private static final short[] noise_pattern_IXnoidh = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_REMOTE_STATIC |
|
||||
@ -364,13 +370,374 @@ class Pattern {
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_NNhfs = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_NKhfs = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID |
|
||||
FLAG_REMOTE_REQUIRED,
|
||||
|
||||
E,
|
||||
F,
|
||||
ES,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_NXhfs = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
S,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_XNhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
FLIP_DIR,
|
||||
S,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_XKhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID |
|
||||
FLAG_REMOTE_REQUIRED,
|
||||
|
||||
E,
|
||||
F,
|
||||
ES,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
FLIP_DIR,
|
||||
S,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_XXhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
S,
|
||||
ES,
|
||||
FLIP_DIR,
|
||||
S,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_KNhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_KKhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID |
|
||||
FLAG_REMOTE_REQUIRED,
|
||||
|
||||
E,
|
||||
F,
|
||||
ES,
|
||||
SS,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_KXhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE,
|
||||
S,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_INhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_IKhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID |
|
||||
FLAG_REMOTE_REQUIRED,
|
||||
|
||||
E,
|
||||
F,
|
||||
ES,
|
||||
S,
|
||||
SS,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_IXhfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE,
|
||||
S,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_XXfallback_hfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_EPHEM_REQ |
|
||||
FLAG_REMOTE_HYBRID |
|
||||
FLAG_REMOTE_HYBRID_REQ,
|
||||
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
S,
|
||||
SE,
|
||||
FLIP_DIR,
|
||||
S,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_NXnoidh_hfs = {
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
EE,
|
||||
FF,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_XXnoidh_hfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
EE,
|
||||
FF,
|
||||
ES,
|
||||
FLIP_DIR,
|
||||
S,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_KXnoidh_hfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_REQUIRED |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
EE,
|
||||
FF,
|
||||
SE,
|
||||
ES
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_IKnoidh_hfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
ES,
|
||||
SS,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
EE,
|
||||
FF,
|
||||
SE
|
||||
};
|
||||
|
||||
private static final short[] noise_pattern_IXnoidh_hfs = {
|
||||
FLAG_LOCAL_STATIC |
|
||||
FLAG_LOCAL_EPHEMERAL |
|
||||
FLAG_LOCAL_HYBRID |
|
||||
FLAG_REMOTE_STATIC |
|
||||
FLAG_REMOTE_EPHEMERAL |
|
||||
FLAG_REMOTE_HYBRID,
|
||||
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
FLIP_DIR,
|
||||
E,
|
||||
F,
|
||||
S,
|
||||
EE,
|
||||
FF,
|
||||
SE,
|
||||
ES
|
||||
};
|
||||
|
||||
/**
|
||||
* Look up the description information for a pattern.
|
||||
*
|
||||
* @param name The name of the pattern.
|
||||
* @return The pattern description or null.
|
||||
*/
|
||||
public static byte[] lookup(String name)
|
||||
public static short[] lookup(String name)
|
||||
{
|
||||
if (name.equals("N"))
|
||||
return noise_pattern_N;
|
||||
@ -416,6 +783,42 @@ class Pattern {
|
||||
return noise_pattern_IKnoidh;
|
||||
else if (name.equals("IXnoidh"))
|
||||
return noise_pattern_IXnoidh;
|
||||
else if (name.equals("NNhfs"))
|
||||
return noise_pattern_NNhfs;
|
||||
else if (name.equals("NKhfs"))
|
||||
return noise_pattern_NKhfs;
|
||||
else if (name.equals("NXhfs"))
|
||||
return noise_pattern_NXhfs;
|
||||
else if (name.equals("XNhfs"))
|
||||
return noise_pattern_XNhfs;
|
||||
else if (name.equals("XKhfs"))
|
||||
return noise_pattern_XKhfs;
|
||||
else if (name.equals("XXhfs"))
|
||||
return noise_pattern_XXhfs;
|
||||
else if (name.equals("KNhfs"))
|
||||
return noise_pattern_KNhfs;
|
||||
else if (name.equals("KKhfs"))
|
||||
return noise_pattern_KKhfs;
|
||||
else if (name.equals("KXhfs"))
|
||||
return noise_pattern_KXhfs;
|
||||
else if (name.equals("INhfs"))
|
||||
return noise_pattern_INhfs;
|
||||
else if (name.equals("IKhfs"))
|
||||
return noise_pattern_IKhfs;
|
||||
else if (name.equals("IXhfs"))
|
||||
return noise_pattern_IXhfs;
|
||||
else if (name.equals("XXfallback+hfs"))
|
||||
return noise_pattern_XXfallback_hfs;
|
||||
else if (name.equals("NXnoidh+hfs"))
|
||||
return noise_pattern_NXnoidh_hfs;
|
||||
else if (name.equals("XXnoidh+hfs"))
|
||||
return noise_pattern_XXnoidh_hfs;
|
||||
else if (name.equals("KXnoidh+hfs"))
|
||||
return noise_pattern_KXnoidh_hfs;
|
||||
else if (name.equals("IKnoidh+hfs"))
|
||||
return noise_pattern_IKnoidh_hfs;
|
||||
else if (name.equals("IXnoidh+hfs"))
|
||||
return noise_pattern_IXnoidh_hfs;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -425,8 +828,8 @@ class Pattern {
|
||||
* @param flags The flags, assuming that the initiator is "local".
|
||||
* @return The reversed flags, with the responder now being "local".
|
||||
*/
|
||||
public static byte reverseFlags(byte flags)
|
||||
public static short reverseFlags(short flags)
|
||||
{
|
||||
return (byte)(((flags >> 4) & 0x0F) | ((flags << 4) & 0xF0));
|
||||
return (short)(((flags >> 8) & 0x00FF) | ((flags << 8) & 0xFF00));
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,17 +73,20 @@ public class VectorTests {
|
||||
public String name;
|
||||
public String pattern;
|
||||
public String dh;
|
||||
public String hybrid;
|
||||
public String cipher;
|
||||
public String hash;
|
||||
public String fallback_pattern;
|
||||
public byte[] init_prologue;
|
||||
public byte[] init_ephemeral;
|
||||
public byte[] init_hybrid;
|
||||
public byte[] init_static;
|
||||
public byte[] init_remote_static;
|
||||
public byte[] init_psk;
|
||||
public byte[] init_ssk;
|
||||
public byte[] resp_prologue;
|
||||
public byte[] resp_ephemeral;
|
||||
public byte[] resp_hybrid;
|
||||
public byte[] resp_static;
|
||||
public byte[] resp_remote_static;
|
||||
public byte[] resp_psk;
|
||||
@ -130,6 +133,8 @@ public class VectorTests {
|
||||
initiator.getLocalKeyPair().setPrivateKey(vec.init_static, 0);
|
||||
if (vec.init_remote_static != null)
|
||||
initiator.getRemotePublicKey().setPublicKey(vec.init_remote_static, 0);
|
||||
if (vec.init_hybrid != null)
|
||||
initiator.getFixedHybridKey().setPrivateKey(vec.init_hybrid, 0);
|
||||
if (vec.init_ephemeral != null)
|
||||
initiator.getFixedEphemeralKey().setPrivateKey(vec.init_ephemeral, 0);
|
||||
if (vec.init_psk != null)
|
||||
@ -146,6 +151,8 @@ public class VectorTests {
|
||||
if (vec.pattern.length() != 1)
|
||||
responder.getFixedEphemeralKey().setPrivateKey(vec.resp_ephemeral, 0);
|
||||
}
|
||||
if (vec.resp_hybrid != null)
|
||||
responder.getFixedHybridKey().setPrivateKey(vec.resp_hybrid, 0);
|
||||
if (vec.resp_psk != null)
|
||||
responder.setPreSharedKey(vec.resp_psk, 0, vec.resp_psk.length);
|
||||
|
||||
@ -299,6 +306,8 @@ public class VectorTests {
|
||||
vec.pattern = reader.nextString();
|
||||
else if (name.equals("dh"))
|
||||
vec.dh = reader.nextString();
|
||||
else if (name.equals("hybrid"))
|
||||
vec.hybrid = reader.nextString();
|
||||
else if (name.equals("cipher"))
|
||||
vec.cipher = reader.nextString();
|
||||
else if (name.equals("hash"))
|
||||
@ -309,6 +318,8 @@ public class VectorTests {
|
||||
vec.init_prologue = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("init_ephemeral"))
|
||||
vec.init_ephemeral = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("init_hybrid_ephemeral"))
|
||||
vec.init_hybrid = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("init_static"))
|
||||
vec.init_static = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("init_remote_static"))
|
||||
@ -321,6 +332,8 @@ public class VectorTests {
|
||||
vec.resp_prologue = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("resp_ephemeral"))
|
||||
vec.resp_ephemeral = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("resp_hybrid_ephemeral"))
|
||||
vec.resp_hybrid = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("resp_static"))
|
||||
vec.resp_static = DatatypeConverter.parseHexBinary(reader.nextString());
|
||||
else if (name.equals("resp_remote_static"))
|
||||
@ -362,7 +375,10 @@ public class VectorTests {
|
||||
String protocolName = "Noise";
|
||||
if (vec.init_psk != null || vec.resp_psk != null)
|
||||
protocolName += "PSK";
|
||||
protocolName += "_" + vec.pattern + "_" + vec.dh + "_" + vec.cipher + "_" + vec.hash;
|
||||
String dh = vec.dh;
|
||||
if (vec.hybrid != null)
|
||||
dh = dh + "+" + vec.hybrid;
|
||||
protocolName += "_" + vec.pattern + "_" + dh + "_" + vec.cipher + "_" + vec.hash;
|
||||
if (vec.name == null)
|
||||
vec.name = protocolName;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user