byte[] hmac = Arrays.copyOfRange(payload, inputOffset, inputOffset+HASH_LENGTH);
inputOffset += HASH_LENGTH;
byte[] computedExponential;
if(negType < 8) { // Legacy DH
NativeBigInteger _hisExponential = new NativeBigInteger(1, initiatorExponential);
NativeBigInteger _ourExponential = new NativeBigInteger(1, responderExponential);
DiffieHellmanLightContext ctx = findContextByExponential(_ourExponential);
if(ctx == null) {
Logger.error(this, "WTF? the HMAC verified but we don't know about that exponential! SHOULDN'T HAPPEN! - JFK3 - "+pn);
// Possible this is a replay or severely delayed? We don't keep every exponential we ever use.
return;
}
computedExponential = ctx.getHMACKey(_hisExponential);
} else {
ECPublicKey initiatorKey = ECDH.getPublicKey(initiatorExponential, ecdhCurveToUse);
ECPublicKey responderKey = ECDH.getPublicKey(responderExponential, ecdhCurveToUse);
ECDHLightContext ctx = findECDHContextByPubKey(responderKey);
if (ctx == null) {
Logger.error(this, "WTF? the HMAC verified but we don't know about that exponential! SHOULDN'T HAPPEN! - JFK3 - "+pn);
// Possible this is a replay or severely delayed? We don't keep
// every exponential we ever use.
return;
}
computedExponential = ctx.getHMACKey(initiatorKey);
}
if(logDEBUG) Logger.debug(this, "The shared Master secret is : "+HexUtil.bytesToHex(computedExponential) +" for " + pn);
/* 0 is the outgoing key for the initiator, 7 for the responder */
byte[] outgoingKey = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "7");
byte[] incommingKey = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "0");
byte[] Ke = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "1");
byte[] Ka = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "2");
byte[] hmacKey = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "3");
byte[] ivKey = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "4");
byte[] ivNonce = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "5");
/* Bytes 1-4: Initial sequence number for the initiator
* Bytes 5-8: Initial sequence number for the responder
* Bytes 9-12: Initial message id for the initiator
* Bytes 13-16: Initial message id for the responder
* Note that we are the responder */
byte[] sharedData = computeJFKSharedKey(computedExponential, nonceInitiatorHashed, nonceResponder, "6");
Arrays.fill(computedExponential, (byte)0);
int theirInitialSeqNum = ((sharedData[0] & 0xFF) << 24)
| ((sharedData[1] & 0xFF) << 16)
| ((sharedData[2] & 0xFF) << 8)
| (sharedData[3] & 0xFF);
int ourInitialSeqNum = ((sharedData[4] & 0xFF) << 24)
| ((sharedData[5] & 0xFF) << 16)
| ((sharedData[6] & 0xFF) << 8)
| (sharedData[7] & 0xFF);
int theirInitialMsgID, ourInitialMsgID;
if(negType >= 7) {
theirInitialMsgID =
unknownInitiator ? getInitialMessageID(crypto.myIdentity) :
getInitialMessageID(pn.identity, crypto.myIdentity);
ourInitialMsgID =
unknownInitiator ? getInitialMessageID(crypto.myIdentity) :
getInitialMessageID(crypto.myIdentity, pn.identity);
} else {
theirInitialMsgID= ((sharedData[8] & 0xFF) << 24)
| ((sharedData[9] & 0xFF) << 16)
| ((sharedData[10] & 0xFF) << 8)
| (sharedData[11] & 0xFF);
ourInitialMsgID= ((sharedData[12] & 0xFF) << 24)
| ((sharedData[13] & 0xFF) << 16)
| ((sharedData[14] & 0xFF) << 8)
| (sharedData[15] & 0xFF);
}
if(logMINOR)
Logger.minor(this, "Their initial message ID: "+theirInitialMsgID+" ours "+ourInitialMsgID);
c.initialize(Ke);
int ivLength = PCFBMode.lengthIV(c);
int decypheredPayloadOffset = 0;
// We compute the HMAC of ("I"+cyphertext) : the cyphertext includes the IV!
byte[] decypheredPayload = Arrays.copyOf(JFK_PREFIX_INITIATOR, JFK_PREFIX_INITIATOR.length + payload.length - inputOffset);
decypheredPayloadOffset += JFK_PREFIX_INITIATOR.length;
System.arraycopy(payload, inputOffset, decypheredPayload, decypheredPayloadOffset, decypheredPayload.length-decypheredPayloadOffset);
if(!HMAC.verifyWithSHA256(Ka, decypheredPayload, hmac)) {
Logger.error(this, "The inner-HMAC doesn't match; let's discard the packet JFK(3) - "+pn);
return;
}
final PCFBMode pk = PCFBMode.create(c, decypheredPayload, decypheredPayloadOffset);
// Get the IV
decypheredPayloadOffset += ivLength;
// Decrypt the payload
pk.blockDecipher(decypheredPayload, decypheredPayloadOffset, decypheredPayload.length-decypheredPayloadOffset);
/*
* DecipheredData Format:
* Signature
* Node Data (starting with BootID)
*/
int sigLength = getSignatureLength(negType);
byte[] sig = new byte[sigLength];
System.arraycopy(decypheredPayload, decypheredPayloadOffset, sig, 0, sigLength);
decypheredPayloadOffset += sigLength;
byte[] data = new byte[decypheredPayload.length - decypheredPayloadOffset];
System.arraycopy(decypheredPayload, decypheredPayloadOffset, data, 0, decypheredPayload.length - decypheredPayloadOffset);
int ptr = 0;
long trackerID;
trackerID = Fields.bytesToLong(data, ptr);
if(trackerID < 0) trackerID = -1;
ptr += 8;
long bootID = Fields.bytesToLong(data, ptr);
ptr += 8;
byte[] hisRef = Arrays.copyOfRange(data, ptr, data.length);
// construct the peernode
if(unknownInitiator) {
pn = getPeerNodeFromUnknownInitiator(hisRef, setupType, pn, replyTo);
}
if(pn == null) {
if(unknownInitiator) {
// Reject
Logger.normal(this, "Rejecting... unable to construct PeerNode");
} else {
Logger.error(this, "PeerNode is null and unknownInitiator is false!");
}
return;
}
// verify the signature
byte[] toVerify = assembleDHParams(nonceInitiatorHashed, nonceResponder, initiatorExponential, responderExponential, crypto.getIdentity(negType, false), data);
if(negType < 9) {
byte[] r = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
System.arraycopy(sig, 0, r, 0, Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
System.arraycopy(sig, Node.SIGNATURE_PARAMETER_LENGTH, s, 0, Node.SIGNATURE_PARAMETER_LENGTH);
DSASignature remoteSignature = new DSASignature(new NativeBigInteger(1,r), new NativeBigInteger(1,s));
if(!DSA.verify(pn.peerPubKey, remoteSignature, new NativeBigInteger(1, SHA256.digest(toVerify)), false)) {
Logger.error(this, "The signature verification has failed!! JFK(3) - "+pn.getPeer());
return;
}
} else {
if(!ECDSA.verify(Curves.P256, pn.peerECDSAPubKey(), sig, toVerify)) {